diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Orchard.Azure.MediaServices.csproj b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Orchard.Azure.MediaServices.csproj index cb6b96b29..316f91612 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Orchard.Azure.MediaServices.csproj +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Orchard.Azure.MediaServices.csproj @@ -218,6 +218,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.js new file mode 100644 index 000000000..484143a1d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.js @@ -0,0 +1,215 @@ +/** + * @preserve console-shim 1.0.2 + * https://github.com/kayahr/console-shim + * Copyright (C) 2011 Klaus Reimer + * Licensed under the MIT license + * (See http://www.opensource.org/licenses/mit-license) + */ + + +(function(){ +"use strict"; + +/** + * Returns a function which calls the specified function in the specified + * scope. + * + * @param {Function} func + * The function to call. + * @param {Object} scope + * The scope to call the function in. + * @param {...*} args + * Additional arguments to pass to the bound function. + * @returns {function(...[*]): undefined} + * The bound function. + */ +var bind = function(func, scope, args) +{ + var fixedArgs = Array.prototype.slice.call(arguments, 2); + return function() + { + var args = fixedArgs.concat(Array.prototype.slice.call(arguments, 0)); + (/** @type {Function} */ func).apply(scope, args); + }; +}; + +// Create console if not present +if (!window["console"]) window.console = /** @type {Console} */ ({}); +var console = (/** @type {Object} */ window.console); + +// Implement console log if needed +if (!console["log"]) +{ + // Use log4javascript if present + if (window["log4javascript"]) + { + var log = log4javascript.getDefaultLogger(); + console.log = bind(log.info, log); + console.debug = bind(log.debug, log); + console.info = bind(log.info, log); + console.warn = bind(log.warn, log); + console.error = bind(log.error, log); + } + + // Use empty dummy implementation to ignore logging + else + { + console.log = (/** @param {...*} args */ function(args) {}); + } +} + +// Implement other log levels to console.log if missing +if (!console["debug"]) console.debug = console.log; +if (!console["info"]) console.info = console.log; +if (!console["warn"]) console.warn = console.log; +if (!console["error"]) console.error = console.log; + +// Wrap the log methods in IE (<=9) because their argument handling is wrong +// This wrapping is also done if the __consoleShimTest__ symbol is set. This +// is needed for unit testing. +if (window["__consoleShimTest__"] != null || + eval("/*@cc_on @_jscript_version <= 9@*/")) +{ + /** + * Wraps the call to a real IE logging method. Modifies the arguments so + * parameters which are not represented by a placeholder are properly + * printed with a space character as separator. + * + * @param {...*} args + * The function arguments. First argument is the log function + * to call, the other arguments are the log arguments. + */ + var wrap = function(args) + { + var i, max, match, log; + + // Convert argument list to real array + args = Array.prototype.slice.call(arguments, 0); + + // First argument is the log method to call + log = args.shift(); + + max = args.length; + if (max > 1 && window["__consoleShimTest__"] !== false) + { + // When first parameter is not a string then add a format string to + // the argument list so we are able to modify it in the next stop + if (typeof(args[0]) != "string") + { + args.unshift("%o"); + max += 1; + } + + // For each additional parameter which has no placeholder in the + // format string we add another placeholder separated with a + // space character. + match = args[0].match(/%[a-z]/g); + for (i = match ? match.length + 1 : 1; i < max; i += 1) + { + args[0] += " %o"; + } + } + Function.apply.call(log, console, args); + }; + + // Wrap the native log methods of IE to fix argument output problems + console.log = bind(wrap, window, console.log); + console.debug = bind(wrap, window, console.debug); + console.info = bind(wrap, window, console.info); + console.warn = bind(wrap, window, console.warn); + console.error = bind(wrap, window, console.error); +} + +// Implement console.assert if missing +if (!console["assert"]) +{ + console["assert"] = function() + { + var args = Array.prototype.slice.call(arguments, 0); + var expr = args.shift(); + if (!expr) + { + args[0] = "Assertion failed: " + args[0]; + console.error.apply(console, args); + } + }; +} + +// Linking console.dir and console.dirxml to the console.log method if +// missing. Hopefully the browser already logs objects and DOM nodes as a +// tree. +if (!console["dir"]) console["dir"] = console.log; +if (!console["dirxml"]) console["dirxml"] = console.log; + +// Linking console.exception to console.error. This is not the same but +// at least some error message is displayed. +if (!console["exception"]) console["exception"] = console.error; + +// Implement console.time and console.timeEnd if one of them is missing +if (!console["time"] || !console["timeEnd"]) +{ + var timers = {}; + console["time"] = function(id) + { + timers[id] = new Date().getTime(); + }; + console["timeEnd"] = function(id) + { + var start = timers[id]; + if (start) + { + console.log(id + ": " + (new Date().getTime() - start) + "ms"); + delete timers[id]; + } + }; +} + +// Implement console.table if missing +if (!console["table"]) +{ + console["table"] = function(data, columns) + { + var i, iMax, row, j, jMax, k; + + // Do nothing if data has wrong type or no data was specified + if (!data || !(data instanceof Array) || !data.length) return; + + // Auto-calculate columns array if not set + if (!columns || !(columns instanceof Array)) + { + columns = []; + for (k in data[0]) + { + if (!data[0].hasOwnProperty(k)) continue; + columns.push(k); + } + } + + for (i = 0, iMax = data.length; i < iMax; i += 1) + { + row = []; + for (j = 0, jMax = columns.length; j < jMax; j += 1) + { + row.push(data[i][columns[j]]); + } + + Function.apply.call(console.log, console, row); + } + }; +} + +// Dummy implementations of other console features to prevent error messages +// in browsers not supporting it. +if (!console["clear"]) console["clear"] = function() {}; +if (!console["trace"]) console["trace"] = function() {}; +if (!console["group"]) console["group"] = function() {}; +if (!console["groupCollapsed"]) console["groupCollapsed"] = function() {}; +if (!console["groupEnd"]) console["groupEnd"] = function() {}; +if (!console["timeStamp"]) console["timeStamp"] = function() {}; +if (!console["profile"]) console["profile"] = function() {}; +if (!console["profileEnd"]) console["profileEnd"] = function() {}; +if (!console["count"]) console["count"] = function() {}; + +})(); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJjb25zb2xlLXNoaW0uanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIEBwcmVzZXJ2ZSBjb25zb2xlLXNoaW0gMS4wLjJcclxuICogaHR0cHM6Ly9naXRodWIuY29tL2theWFoci9jb25zb2xlLXNoaW1cclxuICogQ29weXJpZ2h0IChDKSAyMDExIEtsYXVzIFJlaW1lciA8a0BhaWxpcy5kZT5cclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXHJcbiAqIChTZWUgaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZSlcclxuICovXHJcbiBcclxuIFxyXG4oZnVuY3Rpb24oKXtcclxuXCJ1c2Ugc3RyaWN0XCI7XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHdoaWNoIGNhbGxzIHRoZSBzcGVjaWZpZWQgZnVuY3Rpb24gaW4gdGhlIHNwZWNpZmllZFxyXG4gKiBzY29wZS5cclxuICpcclxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuY1xyXG4gKiAgICAgICAgICAgIFRoZSBmdW5jdGlvbiB0byBjYWxsLlxyXG4gKiBAcGFyYW0ge09iamVjdH0gc2NvcGVcclxuICogICAgICAgICAgICBUaGUgc2NvcGUgdG8gY2FsbCB0aGUgZnVuY3Rpb24gaW4uXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJnc1xyXG4gKiAgICAgICAgICAgIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIGJvdW5kIGZ1bmN0aW9uLlxyXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb24oLi4uWypdKTogdW5kZWZpbmVkfVxyXG4gKiAgICAgICAgICAgIFRoZSBib3VuZCBmdW5jdGlvbi5cclxuICovXHJcbnZhciBiaW5kID0gZnVuY3Rpb24oZnVuYywgc2NvcGUsIGFyZ3MpXHJcbntcclxuICAgIHZhciBmaXhlZEFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uKClcclxuICAgIHtcclxuICAgICAgICB2YXIgYXJncyA9IGZpeGVkQXJncy5jb25jYXQoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSk7XHJcbiAgICAgICAgKC8qKiBAdHlwZSB7RnVuY3Rpb259ICovIGZ1bmMpLmFwcGx5KHNjb3BlLCBhcmdzKTtcclxuICAgIH07XHJcbn07XHJcblxyXG4vLyBDcmVhdGUgY29uc29sZSBpZiBub3QgcHJlc2VudFxyXG5pZiAoIXdpbmRvd1tcImNvbnNvbGVcIl0pIHdpbmRvdy5jb25zb2xlID0gLyoqIEB0eXBlIHtDb25zb2xlfSAqLyAoe30pO1xyXG52YXIgY29uc29sZSA9ICgvKiogQHR5cGUge09iamVjdH0gKi8gd2luZG93LmNvbnNvbGUpO1xyXG5cclxuLy8gSW1wbGVtZW50IGNvbnNvbGUgbG9nIGlmIG5lZWRlZFxyXG5pZiAoIWNvbnNvbGVbXCJsb2dcIl0pXHJcbntcclxuICAgIC8vIFVzZSBsb2c0amF2YXNjcmlwdCBpZiBwcmVzZW50XHJcbiAgICBpZiAod2luZG93W1wibG9nNGphdmFzY3JpcHRcIl0pXHJcbiAgICB7XHJcbiAgICAgICAgdmFyIGxvZyA9IGxvZzRqYXZhc2NyaXB0LmdldERlZmF1bHRMb2dnZXIoKTtcclxuICAgICAgICBjb25zb2xlLmxvZyA9IGJpbmQobG9nLmluZm8sIGxvZyk7XHJcbiAgICAgICAgY29uc29sZS5kZWJ1ZyA9IGJpbmQobG9nLmRlYnVnLCBsb2cpO1xyXG4gICAgICAgIGNvbnNvbGUuaW5mbyA9IGJpbmQobG9nLmluZm8sIGxvZyk7XHJcbiAgICAgICAgY29uc29sZS53YXJuID0gYmluZChsb2cud2FybiwgbG9nKTtcclxuICAgICAgICBjb25zb2xlLmVycm9yID0gYmluZChsb2cuZXJyb3IsIGxvZyk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIFVzZSBlbXB0eSBkdW1teSBpbXBsZW1lbnRhdGlvbiB0byBpZ25vcmUgbG9nZ2luZ1xyXG4gICAgZWxzZVxyXG4gICAge1xyXG4gICAgICAgIGNvbnNvbGUubG9nID0gKC8qKiBAcGFyYW0gey4uLip9IGFyZ3MgKi8gZnVuY3Rpb24oYXJncykge30pO1xyXG4gICAgfVxyXG59XHJcblxyXG4vLyBJbXBsZW1lbnQgb3RoZXIgbG9nIGxldmVscyB0byBjb25zb2xlLmxvZyBpZiBtaXNzaW5nXHJcbmlmICghY29uc29sZVtcImRlYnVnXCJdKSBjb25zb2xlLmRlYnVnID0gY29uc29sZS5sb2c7XHJcbmlmICghY29uc29sZVtcImluZm9cIl0pIGNvbnNvbGUuaW5mbyA9IGNvbnNvbGUubG9nO1xyXG5pZiAoIWNvbnNvbGVbXCJ3YXJuXCJdKSBjb25zb2xlLndhcm4gPSBjb25zb2xlLmxvZztcclxuaWYgKCFjb25zb2xlW1wiZXJyb3JcIl0pIGNvbnNvbGUuZXJyb3IgPSBjb25zb2xlLmxvZztcclxuXHJcbi8vIFdyYXAgdGhlIGxvZyBtZXRob2RzIGluIElFICg8PTkpIGJlY2F1c2UgdGhlaXIgYXJndW1lbnQgaGFuZGxpbmcgaXMgd3JvbmdcclxuLy8gVGhpcyB3cmFwcGluZyBpcyBhbHNvIGRvbmUgaWYgdGhlIF9fY29uc29sZVNoaW1UZXN0X18gc3ltYm9sIGlzIHNldC4gVGhpc1xyXG4vLyBpcyBuZWVkZWQgZm9yIHVuaXQgdGVzdGluZy5cclxuaWYgKHdpbmRvd1tcIl9fY29uc29sZVNoaW1UZXN0X19cIl0gIT0gbnVsbCB8fCBcclxuICAgIGV2YWwoXCIvKkBjY19vbiBAX2pzY3JpcHRfdmVyc2lvbiA8PSA5QCovXCIpKVxyXG57XHJcbiAgICAvKipcclxuICAgICAqIFdyYXBzIHRoZSBjYWxsIHRvIGEgcmVhbCBJRSBsb2dnaW5nIG1ldGhvZC4gTW9kaWZpZXMgdGhlIGFyZ3VtZW50cyBzb1xyXG4gICAgICogcGFyYW1ldGVycyB3aGljaCBhcmUgbm90IHJlcHJlc2VudGVkIGJ5IGEgcGxhY2Vob2xkZXIgYXJlIHByb3Blcmx5XHJcbiAgICAgKiBwcmludGVkIHdpdGggYSBzcGFjZSBjaGFyYWN0ZXIgYXMgc2VwYXJhdG9yLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7Li4uKn0gYXJnc1xyXG4gICAgICogICAgICAgICAgICBUaGUgZnVuY3Rpb24gYXJndW1lbnRzLiBGaXJzdCBhcmd1bWVudCBpcyB0aGUgbG9nIGZ1bmN0aW9uXHJcbiAgICAgKiAgICAgICAgICAgIHRvIGNhbGwsIHRoZSBvdGhlciBhcmd1bWVudHMgYXJlIHRoZSBsb2cgYXJndW1lbnRzLlxyXG4gICAgICovXHJcbiAgICB2YXIgd3JhcCA9IGZ1bmN0aW9uKGFyZ3MpXHJcbiAgICB7XHJcbiAgICAgICAgdmFyIGksIG1heCwgbWF0Y2gsIGxvZztcclxuICAgICAgICBcclxuICAgICAgICAvLyBDb252ZXJ0IGFyZ3VtZW50IGxpc3QgdG8gcmVhbCBhcnJheVxyXG4gICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIEZpcnN0IGFyZ3VtZW50IGlzIHRoZSBsb2cgbWV0aG9kIHRvIGNhbGxcclxuICAgICAgICBsb2cgPSBhcmdzLnNoaWZ0KCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgbWF4ID0gYXJncy5sZW5ndGg7XHJcbiAgICAgICAgaWYgKG1heCA+IDEgJiYgd2luZG93W1wiX19jb25zb2xlU2hpbVRlc3RfX1wiXSAhPT0gZmFsc2UpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICAvLyBXaGVuIGZpcnN0IHBhcmFtZXRlciBpcyBub3QgYSBzdHJpbmcgdGhlbiBhZGQgYSBmb3JtYXQgc3RyaW5nIHRvXHJcbiAgICAgICAgICAgIC8vIHRoZSBhcmd1bWVudCBsaXN0IHNvIHdlIGFyZSBhYmxlIHRvIG1vZGlmeSBpdCBpbiB0aGUgbmV4dCBzdG9wXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YoYXJnc1swXSkgIT0gXCJzdHJpbmdcIilcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgYXJncy51bnNoaWZ0KFwiJW9cIik7XHJcbiAgICAgICAgICAgICAgICBtYXggKz0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gRm9yIGVhY2ggYWRkaXRpb25hbCBwYXJhbWV0ZXIgd2hpY2ggaGFzIG5vIHBsYWNlaG9sZGVyIGluIHRoZVxyXG4gICAgICAgICAgICAvLyBmb3JtYXQgc3RyaW5nIHdlIGFkZCBhbm90aGVyIHBsYWNlaG9sZGVyIHNlcGFyYXRlZCB3aXRoIGFcclxuICAgICAgICAgICAgLy8gc3BhY2UgY2hhcmFjdGVyLlxyXG4gICAgICAgICAgICBtYXRjaCA9IGFyZ3NbMF0ubWF0Y2goLyVbYS16XS9nKTtcclxuICAgICAgICAgICAgZm9yIChpID0gbWF0Y2ggPyBtYXRjaC5sZW5ndGggKyAxIDogMTsgaSA8IG1heDsgaSArPSAxKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBhcmdzWzBdICs9IFwiICVvXCI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgRnVuY3Rpb24uYXBwbHkuY2FsbChsb2csIGNvbnNvbGUsIGFyZ3MpO1xyXG4gICAgfTtcclxuICAgIFxyXG4gICAgLy8gV3JhcCB0aGUgbmF0aXZlIGxvZyBtZXRob2RzIG9mIElFIHRvIGZpeCBhcmd1bWVudCBvdXRwdXQgcHJvYmxlbXNcclxuICAgIGNvbnNvbGUubG9nID0gYmluZCh3cmFwLCB3aW5kb3csIGNvbnNvbGUubG9nKTtcclxuICAgIGNvbnNvbGUuZGVidWcgPSBiaW5kKHdyYXAsIHdpbmRvdywgY29uc29sZS5kZWJ1Zyk7XHJcbiAgICBjb25zb2xlLmluZm8gPSBiaW5kKHdyYXAsIHdpbmRvdywgY29uc29sZS5pbmZvKTtcclxuICAgIGNvbnNvbGUud2FybiA9IGJpbmQod3JhcCwgd2luZG93LCBjb25zb2xlLndhcm4pO1xyXG4gICAgY29uc29sZS5lcnJvciA9IGJpbmQod3JhcCwgd2luZG93LCBjb25zb2xlLmVycm9yKTtcclxufVxyXG5cclxuLy8gSW1wbGVtZW50IGNvbnNvbGUuYXNzZXJ0IGlmIG1pc3NpbmdcclxuaWYgKCFjb25zb2xlW1wiYXNzZXJ0XCJdKVxyXG57XHJcbiAgICBjb25zb2xlW1wiYXNzZXJ0XCJdID0gZnVuY3Rpb24oKVxyXG4gICAge1xyXG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcclxuICAgICAgICB2YXIgZXhwciA9IGFyZ3Muc2hpZnQoKTtcclxuICAgICAgICBpZiAoIWV4cHIpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBhcmdzWzBdID0gXCJBc3NlcnRpb24gZmFpbGVkOiBcIiArIGFyZ3NbMF07XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IuYXBwbHkoY29uc29sZSwgYXJncyk7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuLy8gTGlua2luZyBjb25zb2xlLmRpciBhbmQgY29uc29sZS5kaXJ4bWwgdG8gdGhlIGNvbnNvbGUubG9nIG1ldGhvZCBpZlxyXG4vLyBtaXNzaW5nLiBIb3BlZnVsbHkgdGhlIGJyb3dzZXIgYWxyZWFkeSBsb2dzIG9iamVjdHMgYW5kIERPTSBub2RlcyBhcyBhXHJcbi8vIHRyZWUuXHJcbmlmICghY29uc29sZVtcImRpclwiXSkgY29uc29sZVtcImRpclwiXSA9IGNvbnNvbGUubG9nO1xyXG5pZiAoIWNvbnNvbGVbXCJkaXJ4bWxcIl0pIGNvbnNvbGVbXCJkaXJ4bWxcIl0gPSBjb25zb2xlLmxvZztcclxuXHJcbi8vIExpbmtpbmcgY29uc29sZS5leGNlcHRpb24gdG8gY29uc29sZS5lcnJvci4gVGhpcyBpcyBub3QgdGhlIHNhbWUgYnV0XHJcbi8vIGF0IGxlYXN0IHNvbWUgZXJyb3IgbWVzc2FnZSBpcyBkaXNwbGF5ZWQuXHJcbmlmICghY29uc29sZVtcImV4Y2VwdGlvblwiXSkgY29uc29sZVtcImV4Y2VwdGlvblwiXSA9IGNvbnNvbGUuZXJyb3I7XHJcblxyXG4vLyBJbXBsZW1lbnQgY29uc29sZS50aW1lIGFuZCBjb25zb2xlLnRpbWVFbmQgaWYgb25lIG9mIHRoZW0gaXMgbWlzc2luZ1xyXG5pZiAoIWNvbnNvbGVbXCJ0aW1lXCJdIHx8ICFjb25zb2xlW1widGltZUVuZFwiXSlcclxue1xyXG4gICAgdmFyIHRpbWVycyA9IHt9O1xyXG4gICAgY29uc29sZVtcInRpbWVcIl0gPSBmdW5jdGlvbihpZClcclxuICAgIHtcclxuICAgICAgICB0aW1lcnNbaWRdID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XHJcbiAgICB9O1xyXG4gICAgY29uc29sZVtcInRpbWVFbmRcIl0gPSBmdW5jdGlvbihpZClcclxuICAgIHtcclxuICAgICAgICB2YXIgc3RhcnQgPSB0aW1lcnNbaWRdO1xyXG4gICAgICAgIGlmIChzdGFydClcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGlkICsgXCI6IFwiICsgKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gc3RhcnQpICsgXCJtc1wiKTtcclxuICAgICAgICAgICAgZGVsZXRlIHRpbWVyc1tpZF07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuLy8gSW1wbGVtZW50IGNvbnNvbGUudGFibGUgaWYgbWlzc2luZ1xyXG5pZiAoIWNvbnNvbGVbXCJ0YWJsZVwiXSlcclxue1xyXG4gICAgY29uc29sZVtcInRhYmxlXCJdID0gZnVuY3Rpb24oZGF0YSwgY29sdW1ucylcclxuICAgIHtcclxuICAgICAgICB2YXIgaSwgaU1heCwgcm93LCBqLCBqTWF4LCBrO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIERvIG5vdGhpbmcgaWYgZGF0YSBoYXMgd3JvbmcgdHlwZSBvciBubyBkYXRhIHdhcyBzcGVjaWZpZWRcclxuICAgICAgICBpZiAoIWRhdGEgfHwgIShkYXRhIGluc3RhbmNlb2YgQXJyYXkpIHx8ICFkYXRhLmxlbmd0aCkgcmV0dXJuO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIEF1dG8tY2FsY3VsYXRlIGNvbHVtbnMgYXJyYXkgaWYgbm90IHNldFxyXG4gICAgICAgIGlmICghY29sdW1ucyB8fCAhKGNvbHVtbnMgaW5zdGFuY2VvZiBBcnJheSkpXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgICBjb2x1bW5zID0gW107XHJcbiAgICAgICAgICAgIGZvciAoayBpbiBkYXRhWzBdKVxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWRhdGFbMF0uaGFzT3duUHJvcGVydHkoaykpIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY29sdW1ucy5wdXNoKGspO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIGZvciAoaSA9IDAsIGlNYXggPSBkYXRhLmxlbmd0aDsgaSA8IGlNYXg7IGkgKz0gMSlcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIHJvdyA9IFtdO1xyXG4gICAgICAgICAgICBmb3IgKGogPSAwLCBqTWF4ID0gY29sdW1ucy5sZW5ndGg7IGogPCBqTWF4OyBqICs9IDEpXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHJvdy5wdXNoKGRhdGFbaV1bY29sdW1uc1tqXV0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBGdW5jdGlvbi5hcHBseS5jYWxsKGNvbnNvbGUubG9nLCBjb25zb2xlLCByb3cpO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcbi8vIER1bW15IGltcGxlbWVudGF0aW9ucyBvZiBvdGhlciBjb25zb2xlIGZlYXR1cmVzIHRvIHByZXZlbnQgZXJyb3IgbWVzc2FnZXNcclxuLy8gaW4gYnJvd3NlcnMgbm90IHN1cHBvcnRpbmcgaXQuXHJcbmlmICghY29uc29sZVtcImNsZWFyXCJdKSBjb25zb2xlW1wiY2xlYXJcIl0gPSBmdW5jdGlvbigpIHt9O1xyXG5pZiAoIWNvbnNvbGVbXCJ0cmFjZVwiXSkgY29uc29sZVtcInRyYWNlXCJdID0gZnVuY3Rpb24oKSB7fTtcclxuaWYgKCFjb25zb2xlW1wiZ3JvdXBcIl0pIGNvbnNvbGVbXCJncm91cFwiXSA9IGZ1bmN0aW9uKCkge307XHJcbmlmICghY29uc29sZVtcImdyb3VwQ29sbGFwc2VkXCJdKSBjb25zb2xlW1wiZ3JvdXBDb2xsYXBzZWRcIl0gPSBmdW5jdGlvbigpIHt9O1xyXG5pZiAoIWNvbnNvbGVbXCJncm91cEVuZFwiXSkgY29uc29sZVtcImdyb3VwRW5kXCJdID0gZnVuY3Rpb24oKSB7fTtcclxuaWYgKCFjb25zb2xlW1widGltZVN0YW1wXCJdKSBjb25zb2xlW1widGltZVN0YW1wXCJdID0gZnVuY3Rpb24oKSB7fTtcclxuaWYgKCFjb25zb2xlW1wicHJvZmlsZVwiXSkgY29uc29sZVtcInByb2ZpbGVcIl0gPSBmdW5jdGlvbigpIHt9O1xyXG5pZiAoIWNvbnNvbGVbXCJwcm9maWxlRW5kXCJdKSBjb25zb2xlW1wicHJvZmlsZUVuZFwiXSA9IGZ1bmN0aW9uKCkge307XHJcbmlmICghY29uc29sZVtcImNvdW50XCJdKSBjb25zb2xlW1wiY291bnRcIl0gPSBmdW5jdGlvbigpIHt9O1xyXG5cclxufSkoKTtcclxuIl0sImZpbGUiOiJjb25zb2xlLXNoaW0uanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.min.js new file mode 100644 index 000000000..2be054aa1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/console-shim.min.js @@ -0,0 +1 @@ +!function(){"use strict";var bind=function(o,n,e){var l=Array.prototype.slice.call(arguments,2);return function(){var e=l.concat(Array.prototype.slice.call(arguments,0));o.apply(n,e)}};window.console||(window.console={});var console=window.console;if(!console.log)if(window.log4javascript){var log=log4javascript.getDefaultLogger();console.log=bind(log.info,log),console.debug=bind(log.debug,log),console.info=bind(log.info,log),console.warn=bind(log.warn,log),console.error=bind(log.error,log)}else console.log=function(o){};if(console.debug||(console.debug=console.log),console.info||(console.info=console.log),console.warn||(console.warn=console.log),console.error||(console.error=console.log),null!=window.__consoleShimTest__||eval("/*@cc_on @_jscript_version <= 9@*/")){var wrap=function(o){var n,e,l,c;if(o=Array.prototype.slice.call(arguments,0),c=o.shift(),e=o.length,e>1&&window.__consoleShimTest__!==!1)for("string"!=typeof o[0]&&(o.unshift("%o"),e+=1),l=o[0].match(/%[a-z]/g),n=l?l.length+1:1;e>n;n+=1)o[0]+=" %o";Function.apply.call(c,console,o)};console.log=bind(wrap,window,console.log),console.debug=bind(wrap,window,console.debug),console.info=bind(wrap,window,console.info),console.warn=bind(wrap,window,console.warn),console.error=bind(wrap,window,console.error)}if(console.assert||(console.assert=function(){var o=Array.prototype.slice.call(arguments,0),n=o.shift();n||(o[0]="Assertion failed: "+o[0],console.error.apply(console,o))}),console.dir||(console.dir=console.log),console.dirxml||(console.dirxml=console.log),console.exception||(console.exception=console.error),!console.time||!console.timeEnd){var timers={};console.time=function(o){timers[o]=(new Date).getTime()},console.timeEnd=function(o){var n=timers[o];n&&(console.log(o+": "+((new Date).getTime()-n)+"ms"),delete timers[o])}}console.table||(console.table=function(o,n){var e,l,c,s,r,i;if(o&&o instanceof Array&&o.length){if(!(n&&n instanceof Array)){n=[];for(i in o[0])o[0].hasOwnProperty(i)&&n.push(i)}for(e=0,l=o.length;l>e;e+=1){for(c=[],s=0,r=n.length;r>s;s+=1)c.push(o[e][n[s]]);Function.apply.call(console.log,console,c)}}}),console.clear||(console.clear=function(){}),console.trace||(console.trace=function(){}),console.group||(console.group=function(){}),console.groupCollapsed||(console.groupCollapsed=function(){}),console.groupEnd||(console.groupEnd=function(){}),console.timeStamp||(console.timeStamp=function(){}),console.profile||(console.profile=function(){}),console.profileEnd||(console.profileEnd=function(){}),console.count||(console.count=function(){})}(); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.js new file mode 100644 index 000000000..7b9f7b0d2 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.js @@ -0,0 +1,6 @@ +function X2JS(a,b,c){function d(a){var b=a.localName;return null==b&&(b=a.baseName),(null==b||""==b)&&(b=a.nodeName),b}function e(a){return a.prefix}function f(a){return"string"==typeof a?a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):a}function g(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(///g,"/")}function h(f){if(f.nodeType==u.DOCUMENT_NODE){var i,j,k,l=f.firstChild;for(j=0,k=f.childNodes.length;k>j;j+=1)if(f.childNodes[j].nodeType!==u.COMMENT_NODE){l=f.childNodes[j];break}if(c)i=h(l);else{i={};var m=d(l);i[m]=h(l)}return i}if(f.nodeType==u.ELEMENT_NODE){var i=new Object;i.__cnt=0;for(var n=f.childNodes,o=0;ow;w++){var y=a[w];y.test.call(this,s.value)&&(v=y.converter.call(this,s.value))}i[b+s.name]=v}var z=e(f);return null!=z&&""!=z&&(i.__cnt++,i.__prefix=z),1==i.__cnt&&null!=i["#text"]&&(i=i["#text"]),null!=i["#text"]&&(i.__text=i["#text"],t&&(i.__text=g(i.__text)),delete i["#text"],delete i["#text_asArray"]),null!=i["#cdata-section"]&&(i.__cdata=i["#cdata-section"],delete i["#cdata-section"],delete i["#cdata-section_asArray"]),(null!=i.__text||null!=i.__cdata)&&(i.toString=function(){return(null!=this.__text?this.__text:"")+(null!=this.__cdata?this.__cdata:"")}),i}return f.nodeType==u.TEXT_NODE||f.nodeType==u.CDATA_SECTION_NODE?f.nodeValue:f.nodeType==u.COMMENT_NODE?null:void 0}function i(a,b,c,d){var e="<"+(null!=a&&null!=a.__prefix?a.__prefix+":":"")+b;if(null!=c)for(var f=0;f":">"}function j(a,b){return""+(null!=a.__prefix?a.__prefix+":":"")+b+">"}function k(a,b){return-1!==a.indexOf(b,a.length-b.length)}function l(a,b){return k(b.toString(),"_asArray")||0==b.toString().indexOf("_")||a[b]instanceof Function?!0:!1}function m(a){var b=0;if(a instanceof Object)for(var c in a)l(a,c)||b++;return b}function n(a){var b=[];if(a instanceof Object)for(var c in a)-1==c.toString().indexOf("__")&&0==c.toString().indexOf("_")&&b.push(c);return b}function o(a){var b="";return null!=a.__cdata&&(b+=""),null!=a.__text&&(b+=t?f(a.__text):a.__text),b}function p(a){var b="";return a instanceof Object?b+=o(a):null!=a&&(b+=t?f(a):a),b}function q(a,b,c){var d="";if(0==a.length)d+=i(a,b,c,!0);else for(var e=0;e0)for(var d in a)if(!l(a,d)){var e=a[d],f=n(e);if(null==e||void 0==e)b+=i(e,d,f,!0);else if(e instanceof Object)if(e instanceof Array)b+=q(e,d,f);else{var g=m(e);g>0||null!=e.__text||null!=e.__cdata?(b+=i(e,d,f,!1),b+=r(e),b+=j(e,d)):b+=i(e,d,f,!0)}else b+=i(e,d,f,!1),b+=p(e),b+=j(e,d)}return b+=p(a)}(null===b||void 0===b)&&(b="_"),(null===c||void 0===c)&&(c=!1);var s="1.0.11",t=!1,u={ELEMENT_NODE:1,TEXT_NODE:3,CDATA_SECTION_NODE:4,COMMENT_NODE:8,DOCUMENT_NODE:9};this.parseXmlString=function(a){var b;if(window.DOMParser){var c=new window.DOMParser;b=c.parseFromString(a,"text/xml")}else 0==a.indexOf("")&&(a=a.substr(a.indexOf("?>")+2)),b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(a);return b},this.xml2json=function(a){return h(a)},this.xml_str2json=function(a){var b=this.parseXmlString(a);return this.xml2json(b)},this.json2xml_str=function(a){return r(a)},this.json2xml=function(a){var b=this.json2xml_str(a);return this.parseXmlString(b)},this.getVersion=function(){return s},this.escapeMode=function(a){t=a}}function ObjectIron(a){var b;for(b=[],i=0,len=a.length;len>i;i+=1)a[i].isRoot?b.push("root"):b.push(a[i].name);var c=function(a,b){var c;if(null!==a&&null!==b)for(c in a)a.hasOwnProperty(c)&&(b.hasOwnProperty(c)||(b[c]=a[c]))},d=function(a,b,d){var e,f,g,h,i;if(null!==a&&0!==a.length)for(e=0,f=a.length;f>e;e+=1)g=a[e],b.hasOwnProperty(g.name)&&(d.hasOwnProperty(g.name)?g.merge&&(h=b[g.name],i=d[g.name],"object"==typeof h&&"object"==typeof i?c(h,i):d[g.name]=null!=g.mergeFunction?g.mergeFunction(h,i):h+i):d[g.name]=b[g.name])},e=function(a,b){var c,f,g,h,i,j,k,l=a;if(null!==l.children&&0!==l.children.length)for(c=0,f=l.children.length;f>c;c+=1)if(j=l.children[c],b.hasOwnProperty(j.name))if(j.isArray)for(i=b[j.name+"_asArray"],g=0,h=i.length;h>g;g+=1)k=i[g],d(l.properties,b,k),e(j,k);else k=b[j.name],d(l.properties,b,k),e(j,k)},f=function(c){var d,g,h,i,j,k,l;if(null===c)return c;if("object"!=typeof c)return c;for(d=0,g=b.length;g>d;d+=1)"root"===b[d]&&(j=a[d],k=c,e(j,k));for(i in c)if(c.hasOwnProperty(i)){if(h=b.indexOf(i),-1!==h)if(j=a[h],j.isArray)for(l=c[i+"_asArray"],d=0,g=l.length;g>d;d+=1)k=l[d],e(j,k);else k=c[i],e(j,k);f(c[i])}return c};return{run:f}}if(function(a){a(void 0,Q={})}(function(a,b){function c(a,b){b.stack&&"object"==typeof a&&null!==a&&a.stack&&-1===a.stack.indexOf(N)&&(a.stack=d(a.stack)+"\n"+N+"\n"+d(b.stack))}function d(a){for(var a=a.split("\n"),b=[],c=0;c=x&&T>=f}else d=!1;!d&&!(-1!==e.indexOf("(module.js:")||-1!==e.indexOf("(node.js:"))&&b.push(e)}return b.join("\n")}function e(){if(Error.captureStackTrace){var a,b,c=Error.prepareStackTrace;return Error.prepareStackTrace=function(c,d){a=d[1].getFileName(),b=d[1].getLineNumber()},Error().stack,Error.prepareStackTrace=c,w=a,b}}function f(a,b,c){return function(){return"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(b+" is deprecated, use "+c+" instead.",Error("").stack),a.apply(a,arguments)}}function g(){function a(a){c&&(b=n(a),H(c,function(a,c){A(function(){b.promiseDispatch.apply(b,c)})},void 0),d=c=void 0)}var b,c=[],d=[],e=K(g.prototype),f=K(h.prototype);return f.promiseDispatch=function(a,e,f){var g=G(arguments);c?(c.push(g),"when"===e&&f[1]&&d.push(f[1])):A(function(){b.promiseDispatch.apply(b,g)})},f.valueOf=function(){return c?f:b.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(f,g),f.stack=f.stack.substring(f.stack.indexOf("\n")+1)),z(f),e.promise=f,e.resolve=a,e.reject=function(b){a(m(b))},e.notify=function(a){c&&H(d,function(b,c){A(function(){c(a)})},void 0)},e}function h(a,b,c,d){void 0===b&&(b=function(a){return m(Error("Promise does not support operation: "+a))});var e=K(h.prototype);return e.promiseDispatch=function(c,d,f){var g;try{g=a[d]?a[d].apply(e,f):b.call(e,d,f)}catch(h){g=m(h)}c&&c(g)},c&&(e.valueOf=c),d&&(e.exception=d),z(e),e}function i(a){return j(a)?a.valueOf():a}function j(a){return a&&"function"==typeof a.promiseDispatch}function k(a){return!j(i(a))}function l(a){return a=i(a),j(a)&&"exception"in a}function m(a){var a=a||Error(),b=h({when:function(b){if(b){var c=I(P,this);-1!==c&&(Q.splice(c,1),P.splice(c,1))}return b?b(a):m(a)}},function(){return m(a)},function(){return this},a);return!O&&"undefined"!=typeof window&&!window.Touch&&window.console&&console.log("Should be empty:",Q),O=!0,P.push(b),Q.push(a),b}function n(a){if(j(a))return a;if((a=i(a))&&"function"==typeof a.then){var b=g();return a.then(b.resolve,b.reject,b.notify),b.promise}return h({when:function(){return a},get:function(b){return a[b]},put:function(b,c){return a[b]=c,a},del:function(b){return delete a[b],a},post:function(b,c){return a[b].apply(a,c)},apply:function(b){return a.apply(void 0,b)},keys:function(){return L(a)}},void 0,function(){return a})}function o(a,b,d,e){function f(a){try{return b?b(a):a}catch(c){return m(c)}}function h(a){if(d){c(a,k);try{return d(a)}catch(b){return m(b)}}return m(a)}var i=g(),j=!1,k=n(a);return A(function(){k.promiseDispatch(function(a){j||(j=!0,i.resolve(f(a)))},"when",[function(a){j||(j=!0,i.resolve(h(a)))}])}),k.promiseDispatch(void 0,"when",[void 0,function(a){i.notify(e?e(a):a)}]),i.promise}function p(a,b,c){return o(a,function(a){return t(a).then(function(a){return b.apply(void 0,a)},c)},c)}function q(a,b,c){var d=g();return A(function(){n(a).promiseDispatch(d.resolve,b,c)}),d.promise}function r(a){return function(b){var c=G(arguments,1);return q(b,a,c)}}function s(a){var b=G(arguments,1);return S(a,b)}function t(a){return o(a,function(a){var b=a.length;if(0===b)return n(a);var c=g();return H(a,function(d,e,f){k(e)?(a[f]=i(e),0===--b&&c.resolve(a)):o(e,function(d){a[f]=d,0===--b&&c.resolve(a)}).fail(c.reject)},void 0),c.promise})}function u(a,b){return o(a,void 0,b)}function v(a,b){var c=G(arguments,2),d=g();return c.push(d.makeNodeResolver()),R(a,b,c).fail(d.reject),d.promise}var w,x=e(),y=function(){},z=Object.freeze||y;"undefined"!=typeof cajaVM&&(z=cajaVM.def);var A;if("undefined"!=typeof process)A=process.nextTick;else if("function"==typeof setImmediate)A=setImmediate;else if("undefined"!=typeof MessageChannel){var B=new MessageChannel,C={},D=C;B.port1.onmessage=function(){C=C.next;var a=C.task;delete C.task,a()},A=function(a){D=D.next={task:a},B.port2.postMessage(0)}}else A=function(a){setTimeout(a,0)};var E;Function.prototype.bind?(E=Function.prototype.bind,E=E.bind(E.call)):E=function(a){return function(){return a.call.apply(a,arguments)}};var F,G=E(Array.prototype.slice),H=E(Array.prototype.reduce||function(a,b){var c=0,d=this.length;if(1===arguments.length)for(;;){if(c in this){b=this[c++];break}if(++c>=d)throw new TypeError}for(;d>c;c++)c in this&&(b=a(b,this[c],c));return b}),I=E(Array.prototype.indexOf||function(a){for(var b=0;b2?a.resolve(G(arguments,1)):a.resolve(c)}},b.promise=function(a){var b=g();return s(a,b.resolve,b.reject,b.notify).fail(b.reject),b.promise},b.makePromise=h,h.prototype.then=function(a,b,c){return o(this,a,b,c)},h.prototype.thenResolve=function(a){return o(this,function(){return a})},H("isResolved isFulfilled isRejected dispatch when spread get put del post send invoke keys fapply fcall fbind all allResolved timeout delay catch finally fail fin progress end done nfcall nfapply nfbind ncall napply nbind npost nsend ninvoke nend nodeify".split(" "),function(a,c){h.prototype[c]=function(){return b[c].apply(b,[this].concat(G(arguments)))}},void 0),h.prototype.toSource=function(){return this.toString()},h.prototype.toString=function(){return"[object Promise]"},z(h.prototype),b.nearer=i,b.isPromise=j,b.isResolved=function(a){return k(a)||l(a)},b.isFulfilled=k,b.isRejected=l;var O,P=[],Q=[];b.reject=m,b.resolve=n,b.master=function(a){return h({isDef:function(){}},function(b,c){return q(a,b,c)},function(){return i(a)})},b.when=o,b.spread=p,b.async=function(a){return function(){function b(a,b){var f;try{f=c[a](b)}catch(g){return"[object StopIteration]"===M(g)||g instanceof F?g.value:m(g)}return o(f,d,e)}var c=a.apply(this,arguments),d=b.bind(b,"send"),e=b.bind(b,"throw");return d()}},b["return"]=function(a){throw new F(a)},b.promised=function(a){return function(){return p([this,t(arguments)],function(b,c){return a.apply(b,c)})}},b.dispatch=q,b.dispatcher=r,b.get=r("get"),b.put=r("put"),b["delete"]=b.del=r("del");var R=b.post=r("post");b.send=function(a,b){var c=G(arguments,2);return R(a,b,c)},b.invoke=f(b.send,"invoke","send");var S=b.fapply=r("apply");b["try"]=s,b.fcall=s,b.fbind=function(a){var b=G(arguments,1);return function(){var c=b.concat(G(arguments));return S(a,c)}},b.keys=r("keys"),b.all=t,b.allResolved=function(a){return o(a,function(a){return o(t(J(a,function(a){return o(a,y,y)})),function(){return J(a,n)})})},b["catch"]=b.fail=u,b.progress=function(a,b){return o(a,void 0,void 0,b)},b["finally"]=b.fin=function(a,b){return o(a,function(a){return o(b(),function(){return a})},function(a){return o(b(),function(){return m(a)})})},b.done=function(a,d,e,f){d=d||e||f?o(a,d,e,f):a,u(d,function(d){A(function(){if(c(d,a),!b.onerror)throw d;b.onerror(d)})})},b.timeout=function(a,b){var c=g(),d=setTimeout(function(){c.reject(Error("Timed out after "+b+" ms"))},b);return o(a,function(a){clearTimeout(d),c.resolve(a)},function(a){clearTimeout(d),c.reject(a)}),c.promise},b.delay=function(a,b){void 0===b&&(b=a,a=void 0);var c=g();return setTimeout(function(){c.resolve(a)},b),c.promise},b.nfapply=function(a,b){var c=G(b),d=g();return c.push(d.makeNodeResolver()),S(a,c).fail(d.reject),d.promise},b.nfcall=function(a){var b=G(arguments,1),c=g();return b.push(c.makeNodeResolver()),S(a,b).fail(c.reject),c.promise},b.nfbind=function(a){var b=G(arguments,1);return function(){var c=b.concat(G(arguments)),d=g();return c.push(d.makeNodeResolver()),S(a,c).fail(d.reject),d.promise}},b.npost=function(a,b,c){var c=G(c),d=g();return c.push(d.makeNodeResolver()),R(a,b,c).fail(d.reject),d.promise},b.nsend=v,b.ninvoke=f(v,"ninvoke","nsend"),b.nodeify=function(a,b){return b?(a.then(function(a){A(function(){b(null,a)})},function(a){A(function(){b(a)})}),void 0):a};var T=e()}),function(a){"use strict";var b={VERSION:"0.5.3"};b.System=function(){this._mappings={},this._outlets={},this._handlers={},this.strictInjections=!0,this.autoMapOutlets=!1,this.postInjectionHook="setup"},b.System.prototype={_createAndSetupInstance:function(a,b){var c=new b;return this.injectInto(c,a),c},_retrieveFromCacheOrCreate:function(a,b){"undefined"==typeof b&&(b=!1);var c;if(!this._mappings.hasOwnProperty(a))throw new Error(1e3);var d=this._mappings[a];return!b&&d.isSingleton?(null==d.object&&(d.object=this._createAndSetupInstance(a,d.clazz)),c=d.object):c=d.clazz?this._createAndSetupInstance(a,d.clazz):d.object,c},mapOutlet:function(a,b,c){if("undefined"==typeof a)throw new Error(1010);return b=b||"global",c=c||a,this._outlets.hasOwnProperty(b)||(this._outlets[b]={}),this._outlets[b][c]=a,this},getObject:function(a){if("undefined"==typeof a)throw new Error(1020);return this._retrieveFromCacheOrCreate(a)},mapValue:function(a,b){if("undefined"==typeof a)throw new Error(1030);return this._mappings[a]={clazz:null,object:b,isSingleton:!0},this.autoMapOutlets&&this.mapOutlet(a),this.hasMapping(a)&&this.injectInto(b,a),this},hasMapping:function(a){if("undefined"==typeof a)throw new Error(1040);return this._mappings.hasOwnProperty(a)},mapClass:function(a,b){if("undefined"==typeof a)throw new Error(1050);if("undefined"==typeof b)throw new Error(1051);return this._mappings[a]={clazz:b,object:null,isSingleton:!1},this.autoMapOutlets&&this.mapOutlet(a),this},mapSingleton:function(a,b){if("undefined"==typeof a)throw new Error(1060);if("undefined"==typeof b)throw new Error(1061);return this._mappings[a]={clazz:b,object:null,isSingleton:!0},this.autoMapOutlets&&this.mapOutlet(a),this},instantiate:function(a){if("undefined"==typeof a)throw new Error(1070);return this._retrieveFromCacheOrCreate(a,!0)},injectInto:function(a,b){if("undefined"==typeof a)throw new Error(1080);if("object"==typeof a){var c=[];this._outlets.hasOwnProperty("global")&&c.push(this._outlets.global),"undefined"!=typeof b&&this._outlets.hasOwnProperty(b)&&c.push(this._outlets[b]);for(var d in c){var e=c[d];for(var f in e){var g=e[f];(!this.strictInjections||f in a)&&(a[f]=this.getObject(g))}}"setup"in a&&a.setup.call(a)}return this},unmap:function(a){if("undefined"==typeof a)throw new Error(1090);return delete this._mappings[a],this},unmapOutlet:function(a,b){if("undefined"==typeof a)throw new Error(1100);if("undefined"==typeof b)throw new Error(1101);return delete this._outlets[a][b],this},mapHandler:function(a,b,c,d,e){if("undefined"==typeof a)throw new Error(1110);return b=b||"global",c=c||a,"undefined"==typeof d&&(d=!1),"undefined"==typeof e&&(e=!1),this._handlers.hasOwnProperty(a)||(this._handlers[a]={}),this._handlers[a].hasOwnProperty(b)||(this._handlers[a][b]=[]),this._handlers[a][b].push({handler:c,oneShot:d,passEvent:e}),this},unmapHandler:function(a,b,c){if("undefined"==typeof a)throw new Error(1120);if(b=b||"global",c=c||a,this._handlers.hasOwnProperty(a)&&this._handlers[a].hasOwnProperty(b)){var d=this._handlers[a][b];for(var e in d){var f=d[e];if(f.handler===c){d.splice(e,1);break}}}return this},notify:function(a){if("undefined"==typeof a)throw new Error(1130);var b=Array.prototype.slice.call(arguments),c=b.slice(1);if(this._handlers.hasOwnProperty(a)){var d=this._handlers[a];for(var e in d){var f,g=d[e];"global"!==e&&(f=this.getObject(e));var h,i,j=[];for(h=0,i=g.length;i>h;h++){var k,l=g[h];k=f&&"string"==typeof l.handler?f[l.handler]:l.handler,l.oneShot&&j.unshift(h),l.passEvent?k.apply(f,b):k.apply(f,c)}for(h=0,i=j.length;i>h;h++)g.splice(j[h],1)}}return this}},a.dijon=b}(this),"undefined"==typeof utils)var utils={};"undefined"==typeof utils.Math&&(utils.Math={}),utils.Math.to64BitNumber=function(a,b){var c,d,e;return c=new goog.math.Long(0,b),d=new goog.math.Long(a,0),e=c.add(d),e.toNumber()},goog={},goog.math={},goog.math.Long=function(a,b){this.low_=0|a,this.high_=0|b},goog.math.Long.IntCache_={},goog.math.Long.fromInt=function(a){if(a>=-128&&128>a){var b=goog.math.Long.IntCache_[a];if(b)return b}var c=new goog.math.Long(0|a,0>a?-1:0);return a>=-128&&128>a&&(goog.math.Long.IntCache_[a]=c),c},goog.math.Long.fromNumber=function(a){return isNaN(a)||!isFinite(a)?goog.math.Long.ZERO:a<=-goog.math.Long.TWO_PWR_63_DBL_?goog.math.Long.MIN_VALUE:a+1>=goog.math.Long.TWO_PWR_63_DBL_?goog.math.Long.MAX_VALUE:0>a?goog.math.Long.fromNumber(-a).negate():new goog.math.Long(0|a%goog.math.Long.TWO_PWR_32_DBL_,0|a/goog.math.Long.TWO_PWR_32_DBL_)},goog.math.Long.fromBits=function(a,b){return new goog.math.Long(a,b)},goog.math.Long.fromString=function(a,b){if(0==a.length)throw Error("number format error: empty string");var c=b||10;if(2>c||c>36)throw Error("radix out of range: "+c);if("-"==a.charAt(0))return goog.math.Long.fromString(a.substring(1),c).negate();if(a.indexOf("-")>=0)throw Error('number format error: interior "-" character: '+a);for(var d=goog.math.Long.fromNumber(Math.pow(c,8)),e=goog.math.Long.ZERO,f=0;fg){var i=goog.math.Long.fromNumber(Math.pow(c,g));e=e.multiply(i).add(goog.math.Long.fromNumber(h))}else e=e.multiply(d),e=e.add(goog.math.Long.fromNumber(h))}return e},goog.math.Long.TWO_PWR_16_DBL_=65536,goog.math.Long.TWO_PWR_24_DBL_=1<<24,goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_,goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2,goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_,goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_,goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2,goog.math.Long.ZERO=goog.math.Long.fromInt(0),goog.math.Long.ONE=goog.math.Long.fromInt(1),goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1),goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(-1,2147483647),goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,-2147483648),goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24),goog.math.Long.prototype.toInt=function(){return this.low_},goog.math.Long.prototype.toNumber=function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()},goog.math.Long.prototype.toString=function(a){var b=a||10;if(2>b||b>36)throw Error("radix out of range: "+b);if(this.isZero())return"0";if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var c=goog.math.Long.fromNumber(b),d=this.div(c),e=d.multiply(c).subtract(this);return d.toString(b)+e.toInt().toString(b)}return"-"+this.negate().toString(b)}for(var f=goog.math.Long.fromNumber(Math.pow(b,6)),e=this,g="";;){var h=e.div(f),i=e.subtract(h.multiply(f)).toInt(),j=i.toString(b);if(e=h,e.isZero())return j+g;for(;j.length<6;)j="0"+j;g=""+j+g}},goog.math.Long.prototype.getHighBits=function(){return this.high_},goog.math.Long.prototype.getLowBits=function(){return this.low_},goog.math.Long.prototype.getLowBitsUnsigned=function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_},goog.math.Long.prototype.getNumBitsAbs=function(){if(this.isNegative())return this.equals(goog.math.Long.MIN_VALUE)?64:this.negate().getNumBitsAbs();for(var a=0!=this.high_?this.high_:this.low_,b=31;b>0&&0==(a&1<0},goog.math.Long.prototype.greaterThanOrEqual=function(a){return this.compare(a)>=0},goog.math.Long.prototype.compare=function(a){if(this.equals(a))return 0;var b=this.isNegative(),c=a.isNegative();return b&&!c?-1:!b&&c?1:this.subtract(a).isNegative()?-1:1},goog.math.Long.prototype.negate=function(){return this.equals(goog.math.Long.MIN_VALUE)?goog.math.Long.MIN_VALUE:this.not().add(goog.math.Long.ONE)},goog.math.Long.prototype.add=function(a){var b=this.high_>>>16,c=65535&this.high_,d=this.low_>>>16,e=65535&this.low_,f=a.high_>>>16,g=65535&a.high_,h=a.low_>>>16,i=65535&a.low_,j=0,k=0,l=0,m=0;return m+=e+i,l+=m>>>16,m&=65535,l+=d+h,k+=l>>>16,l&=65535,k+=c+g,j+=k>>>16,k&=65535,j+=b+f,j&=65535,goog.math.Long.fromBits(l<<16|m,j<<16|k)},goog.math.Long.prototype.subtract=function(a){return this.add(a.negate())},goog.math.Long.prototype.multiply=function(a){if(this.isZero())return goog.math.Long.ZERO;if(a.isZero())return goog.math.Long.ZERO;if(this.equals(goog.math.Long.MIN_VALUE))return a.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO;if(a.equals(goog.math.Long.MIN_VALUE))return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO;if(this.isNegative())return a.isNegative()?this.negate().multiply(a.negate()):this.negate().multiply(a).negate();if(a.isNegative())return this.multiply(a.negate()).negate();if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&a.lessThan(goog.math.Long.TWO_PWR_24_))return goog.math.Long.fromNumber(this.toNumber()*a.toNumber());var b=this.high_>>>16,c=65535&this.high_,d=this.low_>>>16,e=65535&this.low_,f=a.high_>>>16,g=65535&a.high_,h=a.low_>>>16,i=65535&a.low_,j=0,k=0,l=0,m=0;return m+=e*i,l+=m>>>16,m&=65535,l+=d*i,k+=l>>>16,l&=65535,l+=e*h,k+=l>>>16,l&=65535,k+=c*i,j+=k>>>16,k&=65535,k+=d*h,j+=k>>>16,k&=65535,k+=e*g,j+=k>>>16,k&=65535,j+=b*i+c*h+d*g+e*f,j&=65535,goog.math.Long.fromBits(l<<16|m,j<<16|k)},goog.math.Long.prototype.div=function(a){if(a.isZero())throw Error("division by zero");if(this.isZero())return goog.math.Long.ZERO;if(this.equals(goog.math.Long.MIN_VALUE)){if(a.equals(goog.math.Long.ONE)||a.equals(goog.math.Long.NEG_ONE))return goog.math.Long.MIN_VALUE;if(a.equals(goog.math.Long.MIN_VALUE))return goog.math.Long.ONE;var b=this.shiftRight(1),c=b.div(a).shiftLeft(1);if(c.equals(goog.math.Long.ZERO))return a.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE;var d=this.subtract(a.multiply(c)),e=c.add(d.div(a));return e}if(a.equals(goog.math.Long.MIN_VALUE))return goog.math.Long.ZERO;if(this.isNegative())return a.isNegative()?this.negate().div(a.negate()):this.negate().div(a).negate();if(a.isNegative())return this.div(a.negate()).negate();for(var f=goog.math.Long.ZERO,d=this;d.greaterThanOrEqual(a);){for(var c=Math.max(1,Math.floor(d.toNumber()/a.toNumber())),g=Math.ceil(Math.log(c)/Math.LN2),h=48>=g?1:Math.pow(2,g-48),i=goog.math.Long.fromNumber(c),j=i.multiply(a);j.isNegative()||j.greaterThan(d);)c-=h,i=goog.math.Long.fromNumber(c),j=i.multiply(a);i.isZero()&&(i=goog.math.Long.ONE),f=f.add(i),d=d.subtract(j)}return f},goog.math.Long.prototype.modulo=function(a){return this.subtract(this.div(a).multiply(a))},goog.math.Long.prototype.not=function(){return goog.math.Long.fromBits(~this.low_,~this.high_)},goog.math.Long.prototype.and=function(a){return goog.math.Long.fromBits(this.low_&a.low_,this.high_&a.high_)},goog.math.Long.prototype.or=function(a){return goog.math.Long.fromBits(this.low_|a.low_,this.high_|a.high_)},goog.math.Long.prototype.xor=function(a){return goog.math.Long.fromBits(this.low_^a.low_,this.high_^a.high_)},goog.math.Long.prototype.shiftLeft=function(a){if(a&=63,0==a)return this;var b=this.low_;if(32>a){var c=this.high_;return goog.math.Long.fromBits(b<>>32-a)}return goog.math.Long.fromBits(0,b<a){var c=this.low_;return goog.math.Long.fromBits(c>>>a|b<<32-a,b>>a)}return goog.math.Long.fromBits(b>>a-32,b>=0?0:-1)},goog.math.Long.prototype.shiftRightUnsigned=function(a){if(a&=63,0==a)return this;var b=this.high_;if(32>a){var c=this.low_;return goog.math.Long.fromBits(c>>>a|b<<32-a,b>>>a)}return 32==a?goog.math.Long.fromBits(b,0):goog.math.Long.fromBits(b>>>a-32,0)};var UTF8={};UTF8.encode=function(a){for(var b=[],c=0;cd?b.push(d):2048>d?(b.push(192|d>>6),b.push(128|63&d)):65536>d?(b.push(224|d>>12),b.push(128|63&d>>6),b.push(128|63&d)):(b.push(240|d>>18),b.push(128|63&d>>12),b.push(128|63&d>>6),b.push(128|63&d))}return b},UTF8.decode=function(a){for(var b=[],c=0;cd||(224>d?(d=(31&d)<<6,d|=63&a[c++]):240>d?(d=(15&d)<<12,d|=(63&a[c++])<<6,d|=63&a[c++]):(d=(7&d)<<18,d|=(63&a[c++])<<12,d|=(63&a[c++])<<6,d|=63&a[c++])),b.push(String.fromCharCode(d))}return b.join("")};var BASE64={};if(function(b){var c=function(a){for(var c=0,d=[],e=0|a.length/3;0>18)),d.push(b.charAt(63&f>>12)),d.push(b.charAt(63&f>>6)),d.push(b.charAt(63&f))}if(2==a.length-c){var f=(a[c]<<16)+(a[c+1]<<8);d.push(b.charAt(63&f>>18)),d.push(b.charAt(63&f>>12)),d.push(b.charAt(63&f>>6)),d.push("=")}else if(1==a.length-c){var f=a[c]<<16;d.push(b.charAt(63&f>>18)),d.push(b.charAt(63&f>>12)),d.push("==")}return d.join("")},d=function(){for(var a=[],c=0;c>16),c.push(255&f>>8),c.push(255&f),b+=4}return c&&("="==a.charAt(b-2)?(c.pop(),c.pop()):"="==a.charAt(b-1)&&c.pop()),c},f={};f.encode=function(a){for(var b=[],c=0;cf;f+=1)l=m.getInt8(o),j+=String.fromCharCode(l),o+=1;"moof"!==j&&"traf"!==j&&"sidx"!==j?o+=k-8:"sidx"===j&&(o-=8)}if(e=m.getUint32(o,!1)+o,e>a.byteLength)throw"sidx terminates after array buffer";for(n.version=m.getUint8(o+8),o+=12,n.timescale=m.getUint32(o+4,!1),o+=8,0===n.version?(n.earliest_presentation_time=m.getUint32(o,!1),n.first_offset=m.getUint32(o+4,!1),o+=8):(n.earliest_presentation_time=utils.Math.to64BitNumber(m.getUint32(o+4,!1),m.getUint32(o,!1)),n.first_offset=(m.getUint32(o+8,!1)<<32)+m.getUint32(o+12,!1),o+=16),n.first_offset+=e+(b||0),n.reference_count=m.getUint16(o+2,!1),o+=4,n.references=[],c=n.first_offset,d=n.earliest_presentation_time,f=0;f>>31,h=2147483647&h,i=m.getUint32(o+4,!1),o+=12,n.references.push({size:h,type:g,offset:c,duration:i,time:d,timescale:n.timescale}),c+=h,d+=i;if(o!==e)throw"Error: final pos "+o+" differs from SIDX end "+e;return n},b=function(b,c,d){var e,f,g,h,i,j,k,l;for(e=a.call(this,b,d),f=e.references,g=[],i=0,j=f.length;j>i;i+=1)h=new Dash.vo.Segment,h.duration=f[i].duration,h.media=c,h.startTime=f[i].time,h.timescale=f[i].timescale,k=f[i].offset,l=f[i].offset+f[i].size-1,h.mediaRange=k+"-"+l,g.push(h);return this.debug.log("Parsed SIDX box: "+g.length+" segments."),Q.when(g)},c=function(a,b){var d,e,f,g,h,i,j,k=Q.defer(),l=new DataView(a),m=0,n="",o=0,p=!1,q=this;for(q.debug.log("Searching for initialization.");"moov"!==n&&mg;g+=1)h=l.getInt8(m),n+=String.fromCharCode(h),m+=1;"moov"!==n&&(m+=o-8)}return f=l.byteLength-m,"moov"!==n?(q.debug.log("Loading more bytes to find initialization."),b.range.start=0,b.range.end=b.bytesLoaded+b.bytesToLoad,i=new XMLHttpRequest,i.onloadend=function(){p||k.reject("Error loading initialization.")},i.onload=function(){p=!0,b.bytesLoaded=b.range.end,c.call(q,i.response).then(function(a){k.resolve(a)})},i.onerror=function(){k.reject("Error loading initialization.")},i.open("GET",b.url),i.responseType="arraybuffer",i.setRequestHeader("Range","bytes="+b.range.start+"-"+b.range.end),i.send(null)):(d=m-8,e=d+o-1,j=d+"-"+e,q.debug.log("Found the initialization. Range: "+j),k.resolve(j)),k.promise},d=function(a){var b=Q.defer(),d=new XMLHttpRequest,e=!0,f=this,g={url:a,range:{},searching:!1,bytesLoaded:0,bytesToLoad:1500,request:d};return f.debug.log("Start searching for initialization."),g.range.start=0,g.range.end=g.bytesToLoad,d.onload=function(){d.status<200||d.status>299||(e=!1,g.bytesLoaded=g.range.end,c.call(f,d.response,g).then(function(a){b.resolve(a)}))},d.onloadend=d.onerror=function(){e&&(e=!1,f.errHandler.downloadError("initialization",g.url,d),b.reject(d))},d.open("GET",g.url),d.responseType="arraybuffer",d.setRequestHeader("Range","bytes="+g.range.start+"-"+g.range.end),d.send(null),f.debug.log("Perform init search: "+g.url),b.promise},e=function(a,c){var d,f,g,h,i,j,k,l,m=Q.defer(),n=new DataView(a),o=new XMLHttpRequest,p=0,q="",r=0,s=!0,t=!1,u=this;for(u.debug.log("Searching for SIDX box."),u.debug.log(c.bytesLoaded+" bytes loaded.");"sidx"!==q&πi+=1)j=n.getInt8(p),q+=String.fromCharCode(j),p+=1;"sidx"!==q&&(p+=r-8)}if(d=n.byteLength-p,"sidx"!==q)m.reject();else if(r-8>d)u.debug.log("Found SIDX but we don't have all of it."),c.range.start=0,c.range.end=c.bytesLoaded+(r-d),o.onload=function(){o.status<200||o.status>299||(s=!1,c.bytesLoaded=c.range.end,e.call(u,o.response,c).then(function(a){m.resolve(a)}))},o.onloadend=o.onerror=function(){s&&(s=!1,u.errHandler.downloadError("SIDX",c.url,o),m.reject(o))},o.open("GET",c.url),o.responseType="arraybuffer",o.setRequestHeader("Range","bytes="+c.range.start+"-"+c.range.end),o.send(null);else if(c.range.start=p-8,c.range.end=c.range.start+r,u.debug.log("Found the SIDX box. Start: "+c.range.start+" | End: "+c.range.end),f=new ArrayBuffer(c.range.end-c.range.start),h=new Uint8Array(f),g=new Uint8Array(a,c.range.start,c.range.end-c.range.start),h.set(g),k=this.parseSIDX.call(this,f,c.range.start),l=k.references,null!==l&&void 0!==l&&l.length>0&&(t=1===l[0].type),t){u.debug.log("Initiate multiple SIDX load.");var v,w,x,y,z,A,B=[];for(v=0,w=l.length;w>v;v+=1)x=l[v].offset,y=l[v].offset+l[v].size-1,z=x+"-"+y,B.push(this.loadSegments.call(u,c.url,z));Q.all(B).then(function(a){for(A=[],v=0,w=a.length;w>v;v+=1)A=A.concat(a[v]);m.resolve(A)},function(a){m.reject(a)})}else u.debug.log("Parsing segments from SIDX."),b.call(u,f,c.url,c.range.start).then(function(a){m.resolve(a)});return m.promise},f=function(a,c){var d,f=Q.defer(),g=new XMLHttpRequest,h=!0,i=this,j={url:a,range:{},searching:!1,bytesLoaded:0,bytesToLoad:1500,request:g};return null===c?(i.debug.log("No known range for SIDX request."),j.searching=!0,j.range.start=0,j.range.end=j.bytesToLoad):(d=c.split("-"),j.range.start=parseFloat(d[0]),j.range.end=parseFloat(d[1])),g.onload=function(){g.status<200||g.status>299||(h=!1,j.searching?(j.bytesLoaded=j.range.end,e.call(i,g.response,j).then(function(a){f.resolve(a)})):b.call(i,g.response,j.url,j.range.start).then(function(a){f.resolve(a)}))},g.onloadend=g.onerror=function(){h&&(h=!1,i.errHandler.downloadError("SIDX",j.url,g),f.reject(g))},g.open("GET",j.url),g.responseType="arraybuffer",g.setRequestHeader("Range","bytes="+j.range.start+"-"+j.range.end),g.send(null),i.debug.log("Perform SIDX load: "+j.url),f.promise};return{debug:void 0,errHandler:void 0,loadSegments:f,loadInitialization:d,parseSegments:b,parseSIDX:a,findSIDX:e}},Dash.dependencies.BaseURLExtensions.prototype={constructor:Dash.dependencies.BaseURLExtensions},Dash.dependencies.DashHandler=function(){"use strict";var a,b,c,d=-1,e=function(a,b){var c=null;return b&&b.Representation_asArray&&b.Representation_asArray.length>0&&(c=b.Representation_asArray[a]),c},f=function(a,b){var c=b.toString();return a.split("$Number$").join(c)},g=function(a,b){var c=b.toString();return a.split("$Time$").join(c)},h=function(a,b){var c=b.toString();return a.split("$Bandwidth$").join(c)},i=function(a,b){if(null===b||-1===a.indexOf("$RepresentationID$"))return a;var c=b.toString();return a.split("$RepresentationID$").join(c)},j=function(a,b){var c;return c=a===b?a:-1!==a.indexOf("http://")?a:b+a},k=function(a,b){var d=Q.defer(),f=e(a,b),g=null,k=null,l=null,m=null,n=this;return f?(n.debug.log("Getting the initialization request."),f.hasOwnProperty("SegmentTemplate")?f.SegmentTemplate.hasOwnProperty("initialization")&&(k=f.SegmentTemplate.initialization,k=h(k,f.bandwidth),k=i(k,f.id)):f.hasOwnProperty("SegmentList")&&f.SegmentList.hasOwnProperty("Initialization")&&f.SegmentList.Initialization.hasOwnProperty("range")?(k=f.SegmentList.Initialization.hasOwnProperty("sourceURL")?f.SegmentList.Initialization.sourceURL:f.BaseURL,m=f.SegmentList.Initialization.range):f.hasOwnProperty("SegmentList")&&f.SegmentList.hasOwnProperty("Initialization")&&f.SegmentList.Initialization.hasOwnProperty("sourceURL")?k=f.SegmentList.Initialization.sourceURL:f.hasOwnProperty("SegmentBase")&&f.SegmentBase.hasOwnProperty("Initialization")&&f.SegmentBase.Initialization.hasOwnProperty("range")?(k=f.BaseURL,m=f.SegmentBase.Initialization.range):f.hasOwnProperty("mimeType")&&n.manifestExt.getIsTextTrack(f.mimeType)?(k=f.BaseURL,m=0):(l=f.BaseURL,n.baseURLExt.loadInitialization(l).then(function(b){n.debug.log("Got an initialization."),g=new MediaPlayer.vo.SegmentRequest,g.streamType=c,g.type="Initialization Segment",g.url=j(l,f.BaseURL),g.range=b,g.quality=a,d.resolve(g)},function(a){d.reject(a)})),k&&k.length>0&&(n.debug.log("Got an initialization."),g=new MediaPlayer.vo.SegmentRequest,g.streamType=c,g.type="Initialization Segment",g.url=j(k,f.BaseURL),g.range=m,g.quality=a,d.resolve(g)),d.promise):Q.reject("no represenation")},l=function(c){var e,f,g,h,i,j,k=!1;return this.debug.log("Checking for stream end..."),a?(this.debug.log("Live never ends! (TODO)"),k=!1):c.hasOwnProperty("segments")&&null!==c.segments?(this.debug.log("Segments: "+d+" / "+c.segments.length),k=d>=c.segments.length):c.hasOwnProperty("SegmentTemplate")&&!c.SegmentTemplate.hasOwnProperty("SegmentTimeline")&&(f=1,i=1,h=b,c.SegmentTemplate.hasOwnProperty("duration")&&(e=c.SegmentTemplate.duration,c.SegmentTemplate.hasOwnProperty("timescale")&&(f=c.SegmentTemplate.timescale),c.SegmentTemplate.hasOwnProperty("startNumber")&&(i=c.SegmentTemplate.startNumber),g=e/f,j=d-i,this.debug.log("SegmentTemplate: "+g+" * "+j+" = "+g*j+" / "+h),k=g*j>=h)),Q.when(k)},m=function(a,c){var d,e,h,i,j,k,l,m,n=[],o=0,p=1,q=1;for(a.hasOwnProperty("startNumber")&&(p=a.startNumber),a.hasOwnProperty("timescale")&&(q=a.timescale),d=c.S_asArray,h=0,i=d.length;i>h;h+=1)for(e=d[h],k=0,e.hasOwnProperty("r")&&(k=e.r),0>k&&(k=(b-o/q)/(e.d/q)-1),j=0;k>=j;j+=1)l=new Dash.vo.Segment,l.timescale=q,0===j&&e.hasOwnProperty("t")?(l.startTime=e.t,o=e.t):l.startTime=o,l.duration=e.d,m=a.media,m=f(m,p),m=g(m,l.startTime),l.media=m,n.push(l),o+=l.duration,p+=1;return Q.when(n)},n=function(a){var b,c,d,e,f,g=[],h=1;for(a.hasOwnProperty("startNumber")&&(h=Math.max(a.startNumber,1)),f=(h-1)*a.duration,b=0,c=a.SegmentURL_asArray.length;c>b;b+=1)e=a.SegmentURL_asArray[b],d=new Dash.vo.Segment,d.media=e.media,d.mediaRange=e.mediaRange,d.index=e.index,d.indexRange=e.indexRange,d.timescale=a.timescale,d.duration=a.duration,d.startTime=f+b*a.duration,g.push(d);return Q.when(g)},o=function(a){var b=a.BaseURL,c=null;return a.hasOwnProperty("SegmentBase")&&a.SegmentBase.hasOwnProperty("indexRange")&&(c=a.SegmentBase.indexRange),this.baseURLExt.loadSegments(b,c)},p=function(a){var b;return b=a.hasOwnProperty("SegmentTemplate")&&!a.SegmentTemplate.hasOwnProperty("SegmentTimeline")?Q.when(null):a.hasOwnProperty("segments")&&null!==a.segments?Q.when(a.segments):a.hasOwnProperty("SegmentTemplate")&&a.SegmentTemplate.hasOwnProperty("SegmentTimeline")?m.call(this,a.SegmentTemplate,a.SegmentTemplate.SegmentTimeline):a.hasOwnProperty("SegmentList")?n.call(this,a.SegmentList):o.call(this,a)},q=function(a,b){var c,d,e,f,g=-1;if(b&&b.length>0)for(f=b.length-1;f>=0;f--){if(c=b[f],d=c.startTime/c.timescale,e=c.duration/c.timescale,a+Dash.dependencies.DashHandler.EPSILON>=d&&a-Dash.dependencies.DashHandler.EPSILON<=d+e){g=f;break}-1===g&&a-Dash.dependencies.DashHandler.EPSILON>d+e&&(g=f+1)}return-1===g&&(console.log("Couldn't figure out a time!"),console.log("Time: "+a),console.log(b)),Q.when(g)},r=function(a,b){var c,d,e=-1,f=1,g=1;if(!b.hasOwnProperty("duration"))throw"Expected 'duration' attribute on SegmentTemplate!";return c=b.duration,b.hasOwnProperty("timescale")&&(f=b.timescale),b.hasOwnProperty("startNumber")&&(g=b.startNumber),d=c/f,e=Math.floor(a/d),e+=g,Q.when(e)},s=function(a,b,d,e){var k,l,m=new MediaPlayer.vo.SegmentRequest,n=1,o=1;return b.hasOwnProperty("timescale")&&(n=b.timescale),b.hasOwnProperty("startNumber")&&(o=b.startNumber),l=b.duration*a/n,l=Math.floor(l),k=b.media,k=f(k,a),k=g(k,l),k=h(k,d.bandwidth),k=i(k,d.id),m.streamType=c,m.type="Media Segment",m.url=j(k,d.BaseURL),m.duration=b.duration/n,m.timescale=n,m.startTime=(a-o)*b.duration/n,m.quality=e,m.index=a,Q.when(m)},t=function(a,b,d,e){if(null===b||void 0===b)return Q.when(null);var k,l=new MediaPlayer.vo.SegmentRequest;return k=j(b.media,d.BaseURL),k=f(k,a),k=g(k,b.startTime),k=h(k,d.bandwidth),k=i(k,d.id),l.streamType=c,l.type="Media Segment",l.url=k,l.range=b.mediaRange,l.startTime=b.startTime/b.timescale,l.duration=b.duration/b.timescale,l.timescale=b.timescale,l.quality=e,l.index=a,Q.when(l)},u=function(a,b,c){var f,g,h,i=e(b,c),j=!1,k=this;return i?(k.debug.log("Getting the request for time: "+a),f=Q.defer(),p.call(k,i).then(function(b){var c;if(k.debug.log("Got segments."),k.debug.log(b),null===b){if(!i.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";j=!0,k.debug.log("No segments found, so we must be using a SegmentTemplate."),c=r.call(k,a,i.SegmentTemplate)}else k.debug.log("Got a list of segments, so dig deeper."),i.segments=b,j=!1,c=q.call(k,a,b);return c},function(){f.reject()}).then(function(b){return k.debug.log("Index for time "+a+" is "+b),d=b,l.call(k,i)}).then(function(a){var c=null;return k.debug.log("Stream finished? "+a),a?(g=new MediaPlayer.vo.SegmentRequest,g.action=g.ACTION_COMPLETE,g.index=d,k.debug.log("Signal complete."),k.debug.log(g),f.resolve(g)):j?c=s.call(k,d,i.SegmentTemplate,i,b):(h=i.segments[d],c=t.call(k,d,h,i,b)),c}).then(function(a){k.debug.log("Got a request."),k.debug.log(a),f.resolve(a)}),f.promise):Q.reject("no represenation")},v=function(a,b){var c,f,g,h=e(a,b),i=this;if(!h)return Q.reject("no represenation");if(i.debug.log("Getting the next request."),-1===d)throw"You must call getSegmentRequestForTime first.";return d+=1,i.debug.log("New index: "+d),c=Q.defer(),l.call(i,h).then(function(b){i.debug.log("Stream finished? "+b),b?(f=new MediaPlayer.vo.SegmentRequest,f.action=f.ACTION_COMPLETE,f.index=d,i.debug.log("Signal complete."),i.debug.log(f),c.resolve(f)):p.call(i,h).then(function(b){var c;if(i.debug.log("Got segments."),i.debug.log(b),null===b){if(!h.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";i.debug.log("No segments found, so we must be using a SegmentTemplate."),c=s.call(i,d,h.SegmentTemplate,h,a)}else h.segments=b,g=h.segments[d],c=t.call(i,d,g,h,a);return c},function(){c.reject()}).then(function(a){i.debug.log("Got a request."),i.debug.log(a),c.resolve(a)})}),c.promise},w=function(a,b,c,d){var f,g,h,i=this,j=e(a,b),k=Math.max(c-d,0),l=Q.defer(),m=0,n=1;return j?(p.call(i,j).then(function(a){if(null===a||void 0===a){if(!j.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";j.SegmentTemplate.hasOwnProperty("timescale")&&(n=j.SegmentTemplate.timescale),h=j.SegmentTemplate.duration,f=h/n}else g=a[0],g.hasOwnProperty("timescale")&&(n=g.timescale),h=g.duration,f=h/n;m=Math.ceil(k/f),l.resolve(m)},function(){l.resolve(0)}),l.promise):Q.reject("no represenation")},x=function(b,c){var f,g,h,i,j=this,k=e(b,c),l=!1,m=1,n=1,o=Q.defer();return k?(g=d,0>g&&(l=a,g=0),p.call(j,k).then(function(a){if(null===a||void 0===a){if(!k.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";i=k.SegmentTemplate.duration,k.SegmentTemplate.hasOwnProperty("timescale")&&(m=k.SegmentTemplate.timescale),k.SegmentTemplate.hasOwnProperty("startNumber")&&(n=k.SegmentTemplate.startNumber),f=i/m*Math.max(g-n,0)}else(l||g>=a.length)&&(g=a.length-1),h=a[g].startTime,i=a[g].duration,a[g].hasOwnProperty("timescale")&&(m=a[g].timescale),f=h/m;o.resolve(f)},function(){o.reject()}),o.promise):Q.reject("no represenation")};return{debug:void 0,baseURLExt:void 0,manifestModel:void 0,manifestExt:void 0,errHandler:void 0,getType:function(){return c},setType:function(a){c=a},getIsLive:function(){return a},setIsLive:function(b){a=b},getDuration:function(){return b},setDuration:function(a){b=a},getInitRequest:k,getSegmentRequestForTime:u,getNextSegmentRequest:v,getCurrentTime:x,getSegmentCountForDuration:w}},Dash.dependencies.DashHandler.EPSILON=.003,Dash.dependencies.DashHandler.prototype={constructor:Dash.dependencies.DashHandler},Dash.dependencies.DashManifestExtensions=function(){"use strict"},Dash.dependencies.DashManifestExtensions.prototype={constructor:Dash.dependencies.DashManifestExtensions,getIsAudio:function(a){"use strict";var b,c,d,e=a.ContentComponent_asArray,f=!1,g=!1;if(e)for(b=0,c=e.length;c>b;b+=1)"audio"===e[b].contentType&&(f=!0,g=!0);if(a.hasOwnProperty("mimeType")&&(f=-1!==a.mimeType.indexOf("audio"),g=!0),!g)for(b=0,c=a.Representation_asArray.length;!g&&c>b;)d=a.Representation_asArray[b],d.hasOwnProperty("mimeType")&&(f=-1!==d.mimeType.indexOf("audio"),g=!0),b+=1;return f&&(a.type="audio"),Q.when(f)},getIsVideo:function(a){"use strict";var b,c,d,e=a.ContentComponent_asArray,f=!1,g=!1;if(e)for(b=0,c=e.length;c>b;b+=1)"video"===e[b].contentType&&(f=!0,g=!0);if(a.hasOwnProperty("mimeType")&&(f=-1!==a.mimeType.indexOf("video"),g=!0),!g)for(b=0,c=a.Representation_asArray.length;!g&&c>b;)d=a.Representation_asArray[b],d.hasOwnProperty("mimeType")&&(f=-1!==d.mimeType.indexOf("video"),g=!0),b+=1;return f&&(a.type="video"),Q.when(f)},getIsText:function(a){"use strict";var b,c,d,e=a.ContentComponent_asArray,f=!1,g=!1;if(e)for(b=0,c=e.length;c>b;b+=1)"text"===e[b].contentType&&(f=!0,g=!0);if(a.hasOwnProperty("mimeType")&&(f=-1!==a.mimeType.indexOf("text"),g=!0),!g)for(b=0,c=a.Representation_asArray.length;!g&&c>b;)d=a.Representation_asArray[b],d.hasOwnProperty("mimeType")&&(f=-1!==d.mimeType.indexOf("text"),g=!0),b+=1;return Q.when(f)},getIsTextTrack:function(a){return"text/vtt"===a||"application/ttml+xml"===a},getIsMain:function(){"use strict";return Q.when(!1)},processAdaptation:function(a){"use strict";return void 0!==a.Representation_asArray&&null!==a.Representation_asArray&&a.Representation_asArray.sort(function(a,b){return a.bandwidth-b.bandwidth}),a},getDataForId:function(a,b,c){"use strict";var d,e,f=b.Period_asArray[c].AdaptationSet_asArray;for(d=0,e=f.length;e>d;d+=1)if(f[d].hasOwnProperty("id")&&f[d].id===a)return Q.when(f[d]);return Q.when(null)},getDataForIndex:function(a,b,c){"use strict";var d=b.Period_asArray[c].AdaptationSet_asArray;return Q.when(d[a])},getDataIndex:function(a,b,c){"use strict";var d,e,f=b.Period_asArray[c].AdaptationSet_asArray;for(d=0,e=f.length;e>d;d+=1)if(f[d]===a)return Q.when(d);return Q.when(-1)},getVideoData:function(a,b){"use strict";var c,d,e=this,f=a.Period_asArray[b].AdaptationSet_asArray,g=Q.defer(),h=[];for(c=0,d=f.length;d>c;c+=1)h.push(this.getIsVideo(f[c]));return Q.all(h).then(function(a){var b=!1;for(c=0,d=a.length;d>c;c+=1)a[c]===!0&&(b=!0,g.resolve(e.processAdaptation(f[c])));b||g.resolve(null)}),g.promise},getTextData:function(a,b){"use strict";var c,d,e=this,f=a.Period_asArray[b].AdaptationSet_asArray,g=Q.defer(),h=[];for(c=0,d=f.length;d>c;c+=1)h.push(this.getIsText(f[c]));return Q.all(h).then(function(a){var b=!1;for(c=0,d=a.length;d>c;c+=1)a[c]===!0&&(b=!0,g.resolve(e.processAdaptation(f[c])));b||g.resolve(null)}),g.promise},getAudioDatas:function(a,b){"use strict";var c,d,e=this,f=a.Period_asArray[b].AdaptationSet_asArray,g=Q.defer(),h=[];for(c=0,d=f.length;d>c;c+=1)h.push(this.getIsAudio(f[c]));return Q.all(h).then(function(a){var b=[];for(c=0,d=a.length;d>c;c+=1)a[c]===!0&&b.push(e.processAdaptation(f[c]));g.resolve(b)}),g.promise},getPrimaryAudioData:function(a,b){"use strict";var c,d,e=Q.defer(),f=[],g=this;return this.getAudioDatas(a,b).then(function(a){for(a&&0!==a.length||e.resolve(null),c=0,d=a.length;d>c;c+=1)f.push(g.getIsMain(a[c]));Q.all(f).then(function(b){var f=!1;for(c=0,d=b.length;d>c;c+=1)b[c]===!0&&(f=!0,e.resolve(g.processAdaptation(a[c])));f||e.resolve(a[0])})}),e.promise},getCodec:function(a){"use strict";var b=a.Representation_asArray[0],c=b.mimeType+';codecs="'+b.codecs+'"';return Q.when(c)},getMimeType:function(a){"use strict";return Q.when(a.Representation_asArray[0].mimeType)},getKID:function(a){"use strict";return a&&a.hasOwnProperty("cenc:default_KID")?a["cenc:default_KID"]:null},getContentProtectionData:function(a){"use strict";return a&&a.hasOwnProperty("ContentProtection_asArray")&&0!==a.ContentProtection_asArray.length?Q.when(a.ContentProtection_asArray):Q.when(null)},getSegmentInfoFor:function(a){return a.hasOwnProperty("SegmentBase")?a.SegmentBase:a.hasOwnProperty("SegmentList")?a.SegmentList:a.hasOwnProperty("SegmentTemplate")?a.SegmentTemplate:null},getLiveOffset:function(a){"use strict";var b=15;return a.hasOwnProperty("suggestedPresentationDelay")&&(b=a.suggestedPresentationDelay),Q.when(b)},getLiveStart:function(a,b){var c,d,e=0,f=1,g=1,h=null,i=null;return d=a.Period_asArray[b].AdaptationSet_asArray[1].Representation_asArray[0],d.hasOwnProperty("SegmentList")?(h=d.SegmentList,h.hasOwnProperty("startNumber")&&(f=Math.max(h.startNumber,1)),h.hasOwnProperty("timescale")&&(g=h.timescale),c=h.duration,e=(f-1)*c/g):d.hasOwnProperty("SegmentTemplate")&&(i=d.SegmentTemplate,i.hasOwnProperty("startNumber")&&(f=Math.max(i.startNumber,1)),i.hasOwnProperty("timescale")&&(g=i.timescale),c=i.duration,e=i.hasOwnProperty("SegmentTimeline")?i.SegmentTimeline.S_asArray[0].t/g:(f-1)*c/g),Q.when(e)},getLiveEdge:function(a,b){"use strict";var c,d=this,e=Q.defer(),f=0,g=new Date,h=a.availabilityStartTime;return d.getLiveOffset(a).then(function(i){a.hasOwnProperty("availabilityEndTime")?(c=a.availabilityEndTime,f=(c.getTime()-h.getTime())/1e3):f=(g.getTime()-h.getTime())/1e3,d.getLiveStart(a,b).then(function(a){f+=a,f-=i,e.resolve(f)})}),e.promise},getPresentationOffset:function(a,b){var c,d,e=this,f=Q.defer(),g=0,h=1;return e.getRepresentationFor(a,b).then(function(a){d=e.getSegmentInfoFor(a),null!==d&&void 0!==d&&d.hasOwnProperty("presentationTimeOffset")&&(c=d.presentationTimeOffset,d.hasOwnProperty("timescale")&&(h=d.timescale),g=c/h),f.resolve(g)}),f.promise},getIsLive:function(a){"use strict";var b=!1,c="dynamic";return a.hasOwnProperty("type")&&(b=a.type===c),b},getIsDVR:function(a,b){"use strict";var c,d;return c=!isNaN(a.timeShiftBufferDepth),d=b&&c,Q.when(d)},getIsOnDemand:function(a){"use strict";var b=!1;return a.profiles&&a.profiles.length>0&&(b=-1!==a.profiles.indexOf("urn:mpeg:dash:profile:isoff-on-demand:2011")),Q.when(b)},getDuration:function(a,b){"use strict";var c=0/0;return b?c=Number.POSITIVE_INFINITY:a.mediaPresentationDuration?c=a.mediaPresentationDuration:a.availabilityEndTime&&a.availabilityStartTime&&(c=a.availabilityEndTime.getTime()-a.availabilityStartTime.getTime()),Q.when(c)},getDurationForPeriod:function(a,b,c){"use strict";var d=0/0;return c?d=Number.POSITIVE_INFINITY:b.Period_asArray.length>1&&void 0!==b.Period_asArray[a].duration?d=b.Period_asArray[a].duration:b.mediaPresentationDuration?d=b.mediaPresentationDuration:b.availabilityEndTime&&b.availabilityStartTime&&(d=b.availabilityEndTime.getTime()-b.availabilityStartTime.getTime()),Q.when(d)},getBandwidth:function(a){"use strict";return Q.when(a.bandwidth)},getRefreshDelay:function(a){"use strict";var b=0/0;return a.hasOwnProperty("minimumUpdatePeriod")&&(b=parseFloat(a.minimumUpdatePeriod)),Q.when(b)},getRepresentationCount:function(a){"use strict";return Q.when(a.Representation_asArray.length)},getRepresentationFor:function(a,b){"use strict";return Q.when(b.Representation_asArray[a])},getPeriodCount:function(a){"use strict";return Q.when(a.Period_asArray.length)},getTimestampOffsetForPeriod:function(a,b,c,d){var e,f=this,g=Q.defer();return f.getPresentationOffset(c,d).then(function(c){f.getPeriodStart(b,a).then(function(a){e=a-c,g.resolve(e)})}),g.promise},getPeriodStart:function(a,b){var c,d,e=this,f=e.getIsLive(a),g=null,h=null,i=null;for(c=0;b>=c;c+=1)g=a.Period_asArray[c],g.hasOwnProperty("start")?d=g.start:null!==h&&null!==i?d=h+i:0!==c||f||(d=0),g.hasOwnProperty("duration")&&(i=g.duration),h=d;return Q.when(d)}},Dash.dependencies.DashMetricsExtensions=function(){"use strict";var a=function(a,b){var c,d,e,f,g,h,i,j;for(h=0;hf;f+=1)g=i.getInt8(j),e+=String.fromCharCode(g),j+=1;"moof"!==e&&"traf"!==e&&"tfdt"!==e&&(j+=d-8)}if(j===i.byteLength)throw"Error finding live offset.";return c=i.getUint8(j),this.debug.log("position: "+j),0===c?(j+=4,b=i.getUint32(j,!1)):(j+=d-16,b=utils.Math.to64BitNumber(i.getUint32(j+4,!1),i.getUint32(j,!1))),h.resolve({version:c,base_media_decode_time:b}),h.promise},b=function(a){for(var b,c,d,e,f,g,h,i=new DataView(a),j=0;"sidx"!==f&&je;e+=1)h=i.getInt8(j),f+=String.fromCharCode(h),j+=1;"moof"!==f&&"traf"!==f&&"sidx"!==f?j+=g-8:"sidx"===f&&(j-=8)}return b=i.getUint8(j+8),j+=12,c=i.getUint32(j+4,!1),j+=8,d=0===b?i.getUint32(j,!1):utils.Math.to64BitNumber(i.getUint32(j+4,!1),i.getUint32(j,!1)),Q.when({earliestPresentationTime:d,timescale:c})},c=function(b){var c,d,e,f=Q.defer(),g=new XMLHttpRequest,h=!1;return c=b,g.onloadend=function(){h||(d="Error loading fragment: "+c,f.reject(d))},g.onload=function(){h=!0,e=a(g.response),f.resolve(e)},g.onerror=function(){d="Error loading fragment: "+c,f.reject(d)},g.responseType="arraybuffer",g.open("GET",c),g.send(null),f.promise};return{debug:void 0,loadFragment:c,parseTFDT:a,parseSIDX:b}},Dash.dependencies.FragmentExtensions.prototype={constructor:Dash.dependencies.FragmentExtensions},Dash.vo.Segment=function(){"use strict";this.indexRange=null,this.index=null,this.mediaRange=null,this.media=null,this.duration=0/0,this.startTime=0/0,this.timescale=0/0},Dash.vo.Segment.prototype={constructor:Dash.vo.Segment},MediaPlayer.dependencies.AbrController=function(){"use strict";var a=!0,b={},c={},d=function(a){var c;return b.hasOwnProperty(a)||(b[a]=0),c=b[a]},e=function(a,c){b[a]=c},f=function(a){var b;return c.hasOwnProperty(a)||(c[a]=0),b=c[a]},g=function(a,b){c[a]=b};return{debug:void 0,abrRulesCollection:void 0,manifestExt:void 0,metricsModel:void 0,getAutoSwitchBitrate:function(){return a},setAutoSwitchBitrate:function(b){a=b},getMetricsFor:function(a){var b=Q.defer(),c=this;return c.manifestExt.getIsVideo(a).then(function(d){d?b.resolve(c.metricsModel.getMetricsFor("video")):c.manifestExt.getIsAudio(a).then(function(a){a?b.resolve(c.metricsModel.getMetricsFor("audio")):b.resolve(c.metricsModel.getMetricsFor("stream"))})}),b.promise},getPlaybackQuality:function(b,c){var h,i,j,k,l,m,n=this,o=Q.defer(),p=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,q=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,r=[];return l=d(b),m=f(b),n.debug.log("ABR enabled? ("+a+")"),a?(n.debug.log("Check ABR rules."),n.getMetricsFor(c).then(function(a){n.abrRulesCollection.getRules().then(function(d){for(h=0,i=d.length;i>h;h+=1)r.push(d[h].checkIndex(l,a,c)); +Q.all(r).then(function(a){for(n.debug.log(a),k={},k[MediaPlayer.rules.SwitchRequest.prototype.STRONG]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,k[MediaPlayer.rules.SwitchRequest.prototype.WEAK]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,k[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,h=0,i=a.length;i>h;h+=1)j=a[h],j.quality!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(k[j.priority]=Math.min(k[j.priority],j.quality));k[MediaPlayer.rules.SwitchRequest.prototype.WEAK]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(q=MediaPlayer.rules.SwitchRequest.prototype.WEAK,p=k[MediaPlayer.rules.SwitchRequest.prototype.WEAK]),k[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(q=MediaPlayer.rules.SwitchRequest.prototype.DEFAULT,p=k[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]),k[MediaPlayer.rules.SwitchRequest.prototype.STRONG]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(q=MediaPlayer.rules.SwitchRequest.prototype.STRONG,p=k[MediaPlayer.rules.SwitchRequest.prototype.STRONG]),p!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&void 0!==p&&(l=p),q!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&void 0!==q&&(m=q),n.manifestExt.getRepresentationCount(c).then(function(a){0>l&&(l=0),l>=a&&(l=a-1),m!=MediaPlayer.rules.SwitchRequest.prototype.STRONG&&m!=MediaPlayer.rules.SwitchRequest.prototype.WEAK&&(m=MediaPlayer.rules.SwitchRequest.prototype.DEFAULT),e(b,l),n.debug.log("New quality of "+l),g(b,m),n.debug.log("New confidence of "+m),o.resolve({quality:l,confidence:m})})})})})):(n.debug.log("Unchanged quality of "+l),o.resolve({quality:l,confidence:m})),o.promise},setPlaybackQuality:function(a,b){var c=d(a);b!==c&&e(a,b)},getQualityFor:function(a){return d(a)}}},MediaPlayer.dependencies.AbrController.prototype={constructor:MediaPlayer.dependencies.AbrController},MediaPlayer.dependencies.BufferController=function(){"use strict";var a,b,c,d,e=.5,f=22,g="WAITING",h="READY",i="VALIDATING",j="LOADING",k=g,l=!1,m=!1,n=!1,o=!0,p=[],q=!1,r=-1,s=!0,t=-1,u=!1,v=!1,w=!1,x=!1,y=[],z=null,A=Q.defer(),B=null,C=null,D=-1,E=0,F=0,G=null,H=0,I=!1,J=null,K=0,L=!1,M=null,N=null,O=null,P=null,R=!0,S=function(a){var b=this;b.debug.log("BufferController "+c+" setState to:"+a),k=a,null!==G&&b.fragmentController.onBufferControllerStateChange()},T=function(a,b){var c=0,d=null;R===!1&&(d=P.start,c=a.getTime()-d.getTime(),P.duration=c,P.stopreason=b,R=!0)},U=function(){var a=this.manifestModel.getValue(),b=this.manifestExt.getIsLive(a);return w=!0,Q.when(b)},V=function(){if(l&&m){var a=this;U.call(this).then(function(b){v=b,a.debug.log("BufferController begin "+c+" validation"),S.call(a,h),a.requestScheduler.startScheduling(a,rb),G=a.fragmentController.attachBufferController(a)})}},W=function(){var a;this.requestScheduler.isScheduled(this)||(q===!1&&(a=new Date,T(a,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON),O=this.metricsModel.addPlayList(c,a,0,MediaPlayer.vo.metrics.PlayList.INITIAL_PLAY_START_REASON)),this.debug.log("BufferController "+c+" start."),m=!0,n=!0,V.call(this))},X=function(a){var b;this.debug.log("BufferController "+c+" seek: "+a),q=!0,r=a,b=new Date,T(b,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON),O=this.metricsModel.addPlayList(c,b,r,MediaPlayer.vo.metrics.PlayList.SEEK_START_REASON),W.call(this)},Y=function(){k!==g&&(this.debug.log("BufferController "+c+" stop."),S.call(this,g),this.requestScheduler.stopScheduling(this),this.fragmentController.cancelPendingRequestsForModel(G),m=!1,n=!1,T(new Date,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON))},Z=function(a,b){var c=null;return b&&b.Representation_asArray&&b.Representation_asArray.length>0&&(c=b.Representation_asArray[a]),c},$=function(){var a=this;k===j&&(u&&(u=!1,this.videoModel.stallStream(c,u)),S.call(a,h))},_=function(a){if(this.fragmentController.isInitializationRequest(a))S.call(this,h);else{S.call(this,j);var b=this,c=b.fragmentController.getLoadingTime(b);setTimeout(function(){(M||N)&&(S.call(b,h),qb.call(b))},c)}},ab=function(a,b){this.fragmentController.isInitializationRequest(a)?hb.call(this,a,b):bb.call(this,a,b)},bb=function(a,b){var d=this;d.debug.log(c+" Bytes finished loading: "+a.url),K||isNaN(a.duration)||(K=a.duration),d.fragmentController.process(b.data).then(function(b){null!==b&&null!==z?Q.when(z.promise).then(function(){cb.call(d,b,a.quality).then(function(){A.promise.then(function(b){b.index-1!==a.index||x||(x=!0,u&&(u=!1,d.videoModel.stallStream(c,u)),S.call(d,h),d.system.notify("bufferingCompleted"))})})}):d.debug.log("No "+c+" bytes to push.")})},cb=function(a,b){var d=this,e=a==J,h=e?B:Q.defer(),i=e?y.length:y.push(h),j=Z(t,d.getData()),l=d.videoModel.getCurrentTime(),m=new Date;return d.debug.log("Push ("+c+") bytes: "+a.byteLength),R===!0&&k!==g&&-1!==t&&(R=!1,P=d.metricsModel.appendPlayListTrace(O,j.id,null,m,l,null,1,null)),Q.when(e||2>i||y[i-2].promise).then(function(){N&&fb.call(d).then(function(){return b!==t?(h.resolve(),e&&(B=null,J=null),void 0):(Q.when(C?C.promise:!0).then(function(){d.sourceBufferExt.append(N,a,d.videoModel).then(function(){e&&(B=null,J=null),d.requestScheduler.isScheduled(d)||W.call(d),I=!1,db.call(d).then(function(){h.resolve()}),N&&d.sourceBufferExt.getAllRanges(N).then(function(a){if(a&&(d.debug.log("Append "+c+" complete: "+a.length),a.length>0)){var b,e;for(d.debug.log("Number of buffered "+c+" ranges: "+a.length),b=0,e=a.length;e>b;b+=1)d.debug.log("Buffered "+c+" Range: "+a.start(b)+" - "+a.end(b))}})},function(b){b.err.code===f&&(J=a,B=h,I=!0,F=0,Y.call(d))})}),void 0)})}),h.promise},db=function(){if(!M&&!N)return Q.when(!1);var a=this,b=Q.defer(),d=ob.call(a);return a.sourceBufferExt.getBufferLength(N,d).then(function(d){H=d,a.metricsModel.addBufferLevel(c,new Date,H),eb.call(a),b.resolve()}),b.promise},eb=function(){var a=this.bufferExt.getLeastBufferLevel(),b=2*K,c=H-a;c>b&&!C?(F=0,C=Q.defer()):b>c&&C&&(C.resolve(),C=null)},fb=function(){var a,b=this,c=Q.defer(),d=0;return I?(a=function(){gb.call(b).then(function(b){d+=b,d>=K?c.resolve():setTimeout(a,1e3*K)})},a.call(b),c.promise):Q.when(!0)},gb=function(){var a,c,d=this,e=Q.defer(),f=d.videoModel.getCurrentTime(),g=0;return c=d.fragmentController.getExecutedRequestForTime(G,f),a=c&&!isNaN(c.startTime)?c.startTime:Math.floor(f),K=c&&!isNaN(c.duration)?c.duration:1,d.sourceBufferExt.getBufferRange(N,f).then(function(c){null===c&&r===f&&N.buffered.length>0&&(a=N.buffered.end(N.buffered.length-1)),g=N.buffered.start(0),d.sourceBufferExt.remove(N,g,a,E,b).then(function(){d.fragmentController.removeExecutedRequestsBeforeTime(G,a),e.resolve(a-g)})}),e.promise},hb=function(a,b){var d=this,e=b.data,f=a.quality;d.debug.log(c+" Initialization finished loading: "+a.url),d.fragmentController.process(e).then(function(b){null!==b?(p[f]=b,f===t&&cb.call(d,b,a.quality).then(function(){z.resolve()})):d.debug.log("No "+c+" bytes to push.")})},ib=function(){var a=this,b=a.manifestModel.getValue(),c=a.manifestExt.getIsLive(b);k===j&&S.call(a,h),c||a.system.notify("segmentLoadingFailed")},jb=function(a){this.debug.log(c+" Stream is complete."),T(new Date,MediaPlayer.vo.metrics.PlayList.Trace.END_OF_CONTENT_STOP_REASON),Y.call(this),A.resolve(a)},kb=function(a,b){var d,e=null,f=this.bufferExt.getTopQualityIndex(c),g=[];if(o&&(this.debug.log("Marking a special seek for initial "+c+" playback."),q||(q=!0,r=0),o=!1),s){for(z=Q.defer(),p=[],d=0;f>=d;d+=1)g.push(this.indexHandler.getInitRequest(d,M));t=b,e=Q.all(g)}else e=Q.when(null),a&&(z=Q.defer(),t=b,p[b]&&cb.call(this,p[b],b).then(function(){z.resolve()}));return e},lb=function(b){var d,e=this;if(s&&!q)e.debug.log("Data changed - loading the "+c+" fragment for time: "+a),d=e.indexHandler.getSegmentRequestForTime(a,b,M);else{var f=Q.defer(),g=e.videoModel.getCurrentTime();d=f.promise,e.sourceBufferExt.getBufferRange(N,g).then(function(a){q=!1,null!==a&&(g=a.end),e.debug.log("Loading the "+c+" fragment for time: "+g),e.indexHandler.getSegmentRequestForTime(g,b,M).then(function(a){f.resolve(a)},function(){f.reject()})},function(){f.reject()})}return s=!1,d},mb=function(a){var b=this;null!==a?b.fragmentController.isFragmentLoadedOrPending(b,a)?"complete"!==a.action?b.indexHandler.getNextSegmentRequest(t,M).then(mb.bind(b)):(Y.call(b),S.call(b,h)):(b.debug.log("Loading an "+c+" fragment: "+a.url),Q.when(C?C.promise:!0).then(function(){b.fragmentController.prepareFragmentForLoading(b,a,_,ab,ib,jb).then(function(){S.call(b,h)})})):S.call(b,h)},nb=function(){n&&(d>H&&d0?(F--,lb.call(a,t).then(mb.bind(a))):(k===i&&S.call(a,h),$.call(a))},rb=function(){var a,b=this,d=!1,f=null,g=new Date,l=b.videoModel.getCurrentTime(),m=ob.call(b);if(b.debug.log("BufferController.validate() "+c+" | state: "+k),b.debug.log(c+" Playback rate: "+b.videoModel.getElement().playbackRate),b.debug.log(c+" Working time: "+m),b.debug.log(c+" Video time: "+l),b.debug.log("Current "+c+" buffer length: "+H),nb.call(b),k===j&&e>H)u||(b.debug.log("Stalling "+c+" Buffer: "+c),T(new Date,MediaPlayer.vo.metrics.PlayList.Trace.REBUFFERING_REASON),u=!0,n=!0,b.videoModel.stallStream(c,u));else if(k===h){S.call(b,i);var o=b.manifestModel.getValue().minBufferTime;b.bufferExt.decideBufferLength(o,E,n).then(function(a){b.debug.log("Buffer time: "+a),b.setMinBufferTime(a),b.requestScheduler.adjustExecuteInterval()}),b.abrController.getPlaybackQuality(c,M).then(function(e){var h=e.quality;if(b.debug.log(c+" Playback quality: "+h),b.debug.log("Populate "+c+" buffers."),void 0!==h&&(a=h),d=h!==t,d===!0){if(b.fragmentController.abortRequestsForModel(G),f=Z(a,b.getData()),null===f||void 0===f)throw"Unexpected error!";b.manifestExt.getTimestampOffsetForPeriod(D,b.manifestModel.getValue(),h,M).then(function(a){N.timestampOffset!==a&&(N.timestampOffset=a)}),T(new Date,MediaPlayer.vo.metrics.PlayList.Trace.REPRESENTATION_SWITCH_STOP_REASON),b.metricsModel.addRepresentationSwitch(c,g,l,f.id)}return b.debug.log(d?c+" Quality changed to: "+h:"Quality didn't change."),pb.call(b,h)}).then(function(e){F=e,kb.call(b,d,a).then(function(a){if(null!==a){var d,e,f=a.length;for(e=0;f>e;e+=1)d=a[e],b.debug.log("Loading "+c+" initialization: "+d.url),b.debug.log(d),b.fragmentController.prepareFragmentForLoading(b,d,_,ab,ib,jb).then(function(){S.call(b,h)})}}),qb.call(b)})}else k===i&&S.call(b,h)};return{videoModel:void 0,metricsModel:void 0,manifestExt:void 0,manifestModel:void 0,bufferExt:void 0,sourceBufferExt:void 0,abrController:void 0,fragmentExt:void 0,indexHandler:void 0,debug:void 0,system:void 0,errHandler:void 0,initialize:function(a,b,c,d,e,f,g,h){var i=this,j=i.manifestModel.getValue(),k=i.manifestExt.getIsLive(j);i.setMediaSource(h),i.setVideoModel(e),i.setType(a),i.setPeriodIndex(b),i.setData(c).then(function(){l=!0,V.call(i)}),i.setBuffer(d),i.setScheduler(f),i.setFragmentController(g),i.indexHandler.setIsLive(k),i.manifestExt.getDurationForPeriod(b,i.manifestModel.getValue()).then(function(a){E=a,i.indexHandler.setDuration(a),i.bufferExt.decideBufferLength(j.minBufferTime,E,n).then(function(a){i.setMinBufferTime(a)})})},getType:function(){return c},setType:function(a){c=a,void 0!==this.indexHandler&&this.indexHandler.setType(a)},getPeriodIndex:function(){return D},setPeriodIndex:function(a){D=a},getVideoModel:function(){return this.videoModel},setVideoModel:function(a){this.videoModel=a},getScheduler:function(){return this.requestScheduler},setScheduler:function(a){this.requestScheduler=a},getFragmentController:function(){return this.fragmentController},setFragmentController:function(a){this.fragmentController=a},getAutoSwitchBitrate:function(){var a=this;return a.abrController.getAutoSwitchBitrate()},setAutoSwitchBitrate:function(a){var b=this;b.abrController.setAutoSwitchBitrate(a)},getData:function(){return M},setData:function(b){var d=this,e=Q.defer(),f=M;return f||(f=b),d.abrController.getPlaybackQuality(c,f).then(function(g){d.indexHandler.getCurrentTime(g.quality,f).then(function(f){s=!0,a=f,M=b,d.seek(f),d.bufferExt.updateData(M,c),e.resolve()})}),e.promise},getBuffer:function(){return N},setBuffer:function(a){N=a},getMinBufferTime:function(){return d},setMinBufferTime:function(a){d=a},setMediaSource:function(a){b=a},isReady:function(){return k===h},isBufferingCompleted:function(){return x},clearMetrics:function(){var a=this;null!==c&&""!==c&&a.metricsModel.clearCurrentMetricsForType(c)},updateBufferState:function(){var a=this;I&&J&&!L?(L=!0,cb.call(a,J,t).then(function(){L=!1})):db.call(a)},reset:function(a){var c=this;Y.call(c),c.clearMetrics(),c.fragmentController.abortRequestsForModel(G),c.fragmentController.detachBufferController(G),G=null,y=[],z=null,p=[],A=Q.defer(),a||(c.sourceBufferExt.abort(b,N),c.sourceBufferExt.removeSourceBuffer(b,N)),M=null,N=null},start:W,seek:X,stop:Y}},MediaPlayer.dependencies.BufferController.prototype={constructor:MediaPlayer.dependencies.BufferController},MediaPlayer.dependencies.BufferExtensions=function(){"use strict";var a,b,c=0,d=0,e=null,f=null,g=function(a){var b=this.metricsExt.getCurrentHttpRequest(a);return null!==b?(b.tresponse.getTime()-b.trequest.getTime())/1e3:0},h=function(){var a,b=this,g=Q.defer();return Q.when(e?b.abrController.getPlaybackQuality("audio",e):c).then(function(e){Q.when(f?b.abrController.getPlaybackQuality("video",f):d).then(function(b){a=e.quality===c&&b.quality===d,a=a||e.confidence===MediaPlayer.rules.SwitchRequest.prototype.STRONG&&b.confidence===MediaPlayer.rules.SwitchRequest.prototype.STRONG,g.resolve(a)})}),g.promise};return{system:void 0,videoModel:void 0,manifestExt:void 0,metricsExt:void 0,metricsModel:void 0,abrController:void 0,bufferMax:void 0,updateData:function(a,b){var g=a.Representation_asArray.length-1;"audio"===b?(c=g,e=a):"video"===b&&(d=g,f=a)},getTopQualityIndex:function(a){var b=null;return"audio"===a?b=c:"video"===a&&(b=d),b},decideBufferLength:function(b,c){return a=MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIMEb?Math.max(MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME,b):b>=c?Math.min(c,MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME):Math.min(c,b),Q.when(a)},getLeastBufferLevel:function(){var a=this.metricsModel.getReadOnlyMetricsFor("video"),b=this.metricsExt.getCurrentBufferLevel(a),c=this.metricsModel.getReadOnlyMetricsFor("audio"),d=this.metricsExt.getCurrentBufferLevel(c),e=null;return e=null===b||null===d?null!==d?d.level:null!==b?b.level:null:Math.min(d.level,b.level)},getRequiredBufferLength:function(c,d,e,f){var i,j=this,k=j.metricsModel.getReadOnlyMetricsFor("video"),l=j.metricsModel.getReadOnlyMetricsFor("audio"),m=f>=MediaPlayer.dependencies.BufferExtensions.LONG_FORM_CONTENT_DURATION_THRESHOLD,n=Q.defer(),o=null;return j.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_MIN?(i=a,n.resolve(i)):j.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_INFINITY?(i=f,n.resolve(i)):j.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_REQUIRED?(b=a,e||c||(o=h.call(j)),Q.when(o).then(function(a){a&&(b=m?MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM:MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY),i=b+d+Math.max(g.call(j,k),g.call(j,l)),n.resolve(i)})):n.reject("invalid bufferMax value: "+j.bufferMax),n.promise},getBufferTarget:function(){return void 0===b?a:b}}},MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_REQUIRED="required",MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_MIN="min",MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_INFINITY="infinity",MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_STARTUP=1,MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME=8,MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY=30,MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM=300,MediaPlayer.dependencies.BufferExtensions.LONG_FORM_CONTENT_DURATION_THRESHOLD=600,MediaPlayer.dependencies.BufferExtensions.prototype.constructor=MediaPlayer.dependencies.BufferExtensions,MediaPlayer.utils.Capabilities=function(){"use strict"},MediaPlayer.utils.Capabilities.prototype={constructor:MediaPlayer.utils.Capabilities,supportsMediaSource:function(){"use strict";var a="WebKitMediaSource"in window,b="MediaSource"in window;return a||b},supportsMediaKeys:function(){"use strict";var a="WebKitMediaKeys"in window,b="MSMediaKeys"in window,c="MediaKeys"in window;return a||b||c},supportsCodec:function(a,b){"use strict";if(!(a instanceof HTMLVideoElement))throw"element must be of type HTMLVideoElement.";var c=a.canPlayType(b);return"probably"===c}},MediaPlayer.utils.Debug=function(){"use strict";var a=!0;return{eventBus:void 0,setLogToBrowserConsole:function(b){a=b},getLogToBrowserConsole:function(){return a},log:function(b){a&&console.log(b),this.eventBus.dispatchEvent({type:"log",message:b})}}},MediaPlayer.dependencies.ErrorHandler=function(){"use strict";return{eventBus:void 0,capabilityError:function(a){this.eventBus.dispatchEvent({type:"error",error:"capability",event:a})},downloadError:function(a,b,c){this.eventBus.dispatchEvent({type:"error",error:"download",event:{id:a,url:b,request:c}})},manifestError:function(a,b,c){this.eventBus.dispatchEvent({type:"error",error:"manifestError",event:{message:a,id:b,manifest:c}})},mediaSourceError:function(a){this.eventBus.dispatchEvent({type:"error",error:"mediasource",event:a})},mediaKeySessionError:function(a){this.eventBus.dispatchEvent({type:"error",error:"key_session",event:a})},mediaKeyMessageError:function(a){this.eventBus.dispatchEvent({type:"error",error:"key_message",event:a})},mediaKeySystemSelectionError:function(a){this.eventBus.dispatchEvent({type:"error",error:"key_system_selection",event:a})}}},MediaPlayer.dependencies.ErrorHandler.prototype={constructor:MediaPlayer.dependencies.ErrorHandler},MediaPlayer.utils.EventBus=function(){"use strict";var a,b=function(b,c){var d=(c?"1":"0")+b;return d in a||(a[d]=[]),a[d]},c=function(){a={}};return c(),{addEventListener:function(a,c,d){var e=b(a,d),f=e.indexOf(c);-1===f&&e.push(c)},removeEventListener:function(a,c,d){var e=b(a,d),f=e.indexOf(c);-1!==f&&e.splice(f,1)},dispatchEvent:function(a){for(var c=b(a.type,!1).slice(),d=0;dd;d++)if(a[d].getContext()==b)return a[d];return null},c=function(){for(var b=!0,c=a.length,d=0;c>d;d++)if(!a[d].isReady()){b=!1;break}return b},d=function(){for(var b=0;b0&&(b=new Uint8Array(a)),Q.when(b)},attachBufferController:function(c){if(!c)return null;var d=b(c);return d||(d=this.system.getObject("fragmentModel"),d.setContext(c),a.push(d)),d},detachBufferController:function(b){var c=a.indexOf(b);c>-1&&a.splice(c,1)},onBufferControllerStateChange:function(){c()&&d.call(this)},isFragmentLoadedOrPending:function(a,c){var d,e=b(a);return e?d=e.isFragmentLoadedOrPending(c):!1},getPendingRequests:function(a){var c=b(a);return c?c.getPendingRequests():null},getLoadingRequests:function(a){var c=b(a);return c?c.getLoadingRequests():null},isInitializationRequest:function(a){return a&&a.type&&"initialization segment"===a.type.toLowerCase()},getLoadingTime:function(a){var c=b(a);return c?c.getLoadingTime():null},getExecutedRequestForTime:function(a,b){return a?a.getExecutedRequestForTime(b):null},removeExecutedRequest:function(a,b){a&&a.removeExecutedRequest(b)},removeExecutedRequestsBeforeTime:function(a,b){a&&a.removeExecutedRequestsBeforeTime(b)},cancelPendingRequestsForModel:function(a){a&&a.cancelPendingRequests()},abortRequestsForModel:function(a){a&&a.abortRequests()},prepareFragmentForLoading:function(a,c,d,e,f,g){var h=b(a);return h&&c&&!this.isFragmentLoadedOrPending(a,c)?(h.addRequest(c),h.setCallbacks(d,e,f,g),Q.when(!0)):Q.when(null)}}},MediaPlayer.dependencies.FragmentController.prototype={constructor:MediaPlayer.dependencies.FragmentController},MediaPlayer.dependencies.FragmentLoader=function(){"use strict";var a=3,b=500,c=[],d=function(a,e){var f=new XMLHttpRequest,g=null,h=!0,i=!0,j=this;c.push(f),a.requestStartDate=new Date,a.firstByteDate=a.requestStartDate,f.open("GET",a.url,!0),f.responseType="arraybuffer",a.range&&f.setRequestHeader("Range","bytes="+a.range),f.onprogress=function(b){h&&(h=!1,(!b.lengthComputable||b.lengthComputable&&b.total!=b.loaded)&&(a.firstByteDate=new Date))},f.onload=function(){if(!(f.status<200||f.status>299)){i=!1,a.requestEndDate=new Date;var b=a.requestEndDate,c=f.response,d=a.firstByteDate.getTime()-a.requestStartDate.getTime(),e=a.requestEndDate.getTime()-a.firstByteDate.getTime(),h=a.requestEndDate.getTime()-a.requestStartDate.getTime();j.debug.log("segment loaded: ("+f.status+", "+d+"ms, "+e+"ms, "+h+"ms) "+a.url),g=j.metricsModel.addHttpRequest(a.streamType,null,a.type,a.url,null,a.range,a.requestStartDate,a.firstByteDate,a.requestEndDate,f.status,null,a.duration),j.metricsModel.appendHttpTrace(g,b,(new Date).getTime()-b.getTime(),[c.byteLength]),a.deferred.resolve({data:c,request:a})}},f.onloadend=f.onerror=function(){if(-1!==c.indexOf(f)&&(c.splice(c.indexOf(f),1),i)){i=!1,a.requestEndDate=new Date;var h=a.firstByteDate.getTime()-a.requestStartDate.getTime(),k=a.requestEndDate.getTime()-a.firstByteDate.getTime(),l=a.requestEndDate.getTime()-a.requestStartDate.getTime();j.debug.log("segment loaded: ("+f.status+", "+h+"ms, "+k+"ms, "+l+"ms) "+a.url),g=j.metricsModel.addHttpRequest(a.streamType,null,a.type,a.url,null,a.range,a.requestStartDate,a.firstByteDate,a.requestEndDate,f.status,null,a.duration),e>0?(j.debug.log("Failed loading segment: "+a.url+", retry in "+b+"ms"+" attempts: "+e),e--,setTimeout(function(){d.call(j,a,e)},b)):(j.debug.log("Failed loading segment: "+a.url+" no retry attempts left"),j.errHandler.downloadError("content",a.url,f),a.deferred.reject(f))}},f.send()};return{metricsModel:void 0,errHandler:void 0,debug:void 0,load:function(b){return b?(b.deferred=Q.defer(),d.call(this,b,a),b.deferred.promise):Q.when(null)},abort:function(){var a,b,d=c.length;for(a=0;d>a;a+=1)b=c[a],c[a]=null,b.abort(),b=null;c=[]}}},MediaPlayer.dependencies.FragmentLoader.prototype={constructor:MediaPlayer.dependencies.FragmentLoader},MediaPlayer.dependencies.FragmentModel=function(){"use strict";var a,b,c,d,e,f=[],g=[],h=[],i=5,j=function(e){var g,i=this;b.call(a,e),g=function(b,d){h.splice(h.indexOf(b),1),f.push(b),c.call(a,b,d),b.deferred=null},i.fragmentLoader.load(e).then(g.bind(a,e),d.bind(a,e))},k=function(a,b){var c=function(a,c){return a[b]c[b]?1:0};a.sort(c)},l=function(a,b){var c,d,e=a.length-1;for(d=e;d>=0;d-=1)if(c=a[d],c.url===b.url&&c.startTime===b.startTime)return!0;return!1},m=function(a){var b=f.indexOf(a);-1!==b&&f.splice(b,1)};return{system:void 0,debug:void 0,fragmentLoader:void 0,setContext:function(b){a=b},getContext:function(){return a},addRequest:function(a){a&&(g.push(a),k.call(this,g,"index"))},setCallbacks:function(a,f,g,h){b=a,e=h,d=g,c=f},isFragmentLoadedOrPending:function(a){for(var b,c=this,d=!1,e=f.length-1,i=e;i>=0;i-=1)if(b=f[i],a.startTime===b.startTime||"complete"===b.action&&a.action===b.action){if(c.debug.log(a.streamType+" Fragment already loaded for time: "+a.startTime),a.url===b.url){c.debug.log(a.streamType+" Fragment url already loaded: "+a.url),d=!0;break}m(a)}return d||(d=l.call(c,g,a)||l.call(c,h,a)),d},isReady:function(){return a.isReady()},getPendingRequests:function(){return g},getLoadingRequests:function(){return h},getLoadingTime:function(){var a,b,c=0;for(b=f.length-1;b>=0;b-=1)if(a=f[b],a.requestEndDate instanceof Date&&a.firstByteDate instanceof Date){c=a.requestEndDate.getTime()-a.firstByteDate.getTime();break}return c},getExecutedRequestForTime:function(a){var b,c=f.length-1,d=0/0,e=0/0,g=null;for(b=c;b>=0;b-=1)if(g=f[b],d=g.startTime,e=d+g.duration,!isNaN(d)&&!isNaN(e)&&a>d&&e>a)return g;return null},removeExecutedRequest:function(a){m.call(this,a)},removeExecutedRequestsBeforeTime:function(a){var b,c=f.length-1,d=0/0,e=null;for(b=c;b>=0;b-=1)e=f[b],d=e.startTime,!isNaN(d)&&a>d&&m.call(this,e)},cancelPendingRequests:function(){g=[]},abortRequests:function(){this.fragmentLoader.abort(),h=[]},executeCurrentRequest:function(){var b,c=this;if(0!==g.length&&!(h.length>=i))switch(b=g.shift(),b.action){case"complete":f.push(b),e.call(a,b);break;case"download":h.push(b),j.call(c,b);break;default:this.debug.log("Unknown request action.")}}}},MediaPlayer.dependencies.FragmentModel.prototype={constructor:MediaPlayer.dependencies.FragmentModel},MediaPlayer.dependencies.ManifestLoader=function(){"use strict";var a=3,b=500,c=null,d=function(a){var b=null;return-1!==a.indexOf("/")&&(b=a.substring(0,a.lastIndexOf("/")+1)),b},e=function(a,f){var g=d(a),h=new XMLHttpRequest,i=new Date,j=!0,k=this;this.debug.log("Start loading manifest: "+a),h.open("GET",a,!0),h.onload=function(){h.status<200||h.status>299||(j=!1,k.metricsModel.addHttpRequest("stream",null,"MPD",a,null,null,i,new Date,h.status,null,null),k.parser.parse(h.responseText,g).then(function(b){b.mpdUrl=a,c.resolve(b)},function(){c.reject(h)}))},h.onloadend=h.onerror=function(){j&&(j=!1,k.metricsModel.addHttpRequest("stream",null,"MPD",a,null,null,i,new Date,h.status,null,null),f>0?(k.debug.log("Failed loading manifest: "+a+", retry in "+b+"ms"+" attempts: "+f),f--,setTimeout(function(){e.call(k,a,f)},b)):(k.debug.log("Failed loading manifest: "+a+" no retry attempts left"),k.errHandler.downloadError("manifest",a,h),c.reject(h)))},h.send()};return{debug:void 0,parser:void 0,errHandler:void 0,metricsModel:void 0,load:function(b){return c=Q.defer(),e.call(this,b,a),c.promise}}},MediaPlayer.dependencies.ManifestLoader.prototype={constructor:MediaPlayer.dependencies.ManifestLoader},MediaPlayer.models.ManifestModel=function(){"use strict";var a;return{getValue:function(){return a},setValue:function(b){a=b}}},MediaPlayer.models.ManifestModel.prototype={constructor:MediaPlayer.models.ManifestModel},MediaPlayer.dependencies.ManifestUpdater=function(){"use strict";var a=0/0,b=null,c=null,d=function(){null!==b&&(clearInterval(b),b=null)},e=function(){d.call(this),isNaN(a)||(this.debug.log("Refresh manifest in "+a+" seconds."),b=setInterval(c.bind(this),1e3*a,this))},f=function(){var b=this,c=b.manifestModel.getValue();void 0!==c&&null!==c&&b.manifestExt.getRefreshDelay(c).then(function(c){a=c,e.call(b)})};return c=function(){var a=this,b=a.manifestModel.getValue(),c=b.mpdUrl;b.hasOwnProperty("Location")&&(c=b.Location),a.debug.log("Refresh manifest @ "+c),a.manifestLoader.load(c).then(function(b){a.manifestModel.setValue(b),a.debug.log("Manifest has been refreshed."),a.debug.log(b),f.call(a),a.system.notify("manifestUpdated")})},{debug:void 0,system:void 0,manifestModel:void 0,manifestExt:void 0,manifestLoader:void 0,setup:function(){f.call(this)},init:function(){f.call(this)},stop:function(){d.call(this)}}},MediaPlayer.dependencies.ManifestUpdater.prototype={constructor:MediaPlayer.dependencies.ManifestUpdater},MediaPlayer.dependencies.MediaSourceExtensions=function(){"use strict"},MediaPlayer.dependencies.MediaSourceExtensions.prototype={constructor:MediaPlayer.dependencies.MediaSourceExtensions,createMediaSource:function(){"use strict";var a="WebKitMediaSource"in window,b="MediaSource"in window;return b?Q.when(new MediaSource):a?Q.when(new WebKitMediaSource):null},attachMediaSource:function(a,b){"use strict";return b.setSource(window.URL.createObjectURL(a)),Q.when(!0)},detachMediaSource:function(a){"use strict";return a.setSource(""),Q.when(!0)},setDuration:function(a,b){"use strict";return a.duration=b,Q.when(a.duration)},signalEndOfStream:function(a){"use strict";return a.endOfStream(),Q.when(!0)}},MediaPlayer.models.MetricsModel=function(){"use strict";return{system:void 0,streamMetrics:{},clearCurrentMetricsForType:function(a){delete this.streamMetrics[a]},clearAllCurrentMetrics:function(){this.streamMetrics={}},getReadOnlyMetricsFor:function(a){return this.streamMetrics.hasOwnProperty(a)?this.streamMetrics[a]:null},getMetricsFor:function(a){var b;return this.streamMetrics.hasOwnProperty(a)?b=this.streamMetrics[a]:(b=this.system.getObject("metrics"),this.streamMetrics[a]=b),b},addTcpConnection:function(a,b,c,d,e,f){var g=new MediaPlayer.vo.metrics.TCPConnection;return g.tcpid=b,g.dest=c,g.topen=d,g.tclose=e,g.tconnect=f,this.getMetricsFor(a).TcpList.push(g),g},addHttpRequest:function(a,b,c,d,e,f,g,h,i,j,k,l){var m=new MediaPlayer.vo.metrics.HTTPRequest;return m.tcpid=b,m.type=c,m.url=d,m.actualurl=e,m.range=f,m.trequest=g,m.tresponse=h,m.tfinish=i,m.responsecode=j,m.interval=k,m.mediaduration=l,this.getMetricsFor(a).HttpList.push(m),m},appendHttpTrace:function(a,b,c,d){var e=new MediaPlayer.vo.metrics.HTTPRequest.Trace;return e.s=b,e.d=c,e.b=d,a.trace.push(e),e},addRepresentationSwitch:function(a,b,c,d,e){var f=new MediaPlayer.vo.metrics.RepresentationSwitch;return f.t=b,f.mt=c,f.to=d,f.lto=e,this.getMetricsFor(a).RepSwitchList.push(f),f},addBufferLevel:function(a,b,c){var d=new MediaPlayer.vo.metrics.BufferLevel;return d.t=b,d.level=c,this.getMetricsFor(a).BufferLevel.push(d),d},addPlayList:function(a,b,c,d){var e=new MediaPlayer.vo.metrics.PlayList;return e.start=b,e.mstart=c,e.starttype=d,this.getMetricsFor(a).PlayList.push(e),e},appendPlayListTrace:function(a,b,c,d,e,f,g,h){var i=new MediaPlayer.vo.metrics.PlayList.Trace;return i.representationid=b,i.subreplevel=c,i.start=d,i.mstart=e,i.duration=f,i.playbackspeed=g,i.stopreason=h,a.trace.push(i),i}}},MediaPlayer.models.MetricsModel.prototype={constructor:MediaPlayer.models.MetricsModel},MediaPlayer.dependencies.ProtectionController=function(){"use strict";var a=null,b=null,c=function(a){var b=this;b.protectionModel.removeKeySystem(a)},d=function(a,c){for(var d=this,e=0;ee;e+=1)if(g=f.start(e),h=f.end(e),null===i){if(k=Math.abs(g-b),b>=g&&h>b){i=g,j=h;continue}if(l>=k){i=g,j=h;continue}}else{if(k=g-j,!(l>=k))break;j=h}if(null!==i)return Q.when({start:i,end:j})}return Q.when(null)},getAllRanges:function(a){var b=null;try{return b=a.buffered,Q.when(b)}catch(c){return Q.when(null)}},getBufferLength:function(a,b,c){"use strict";var d=this,e=Q.defer();return d.getBufferRange(a,b,c).then(function(a){null===a?e.resolve(0):e.resolve(a.end-b)}),e.promise},waitForUpdateEnd:function(a){"use strict";var b,c=Q.defer(),d=50,e=function(){a.updating||(clearInterval(b),c.resolve(!0))},f=function(){a.removeEventListener("updateend",f,!1),c.resolve(!0)};if(a.hasOwnProperty("addEventListener"))try{a.addEventListener("updateend",f,!1)}catch(g){b=setInterval(e,d)}else b=setInterval(e,d);return c.promise},append:function(a,b){var c=Q.defer();try{"append"in a?a.append(b):"appendBuffer"in a&&a.appendBuffer(b),this.waitForUpdateEnd(a).then(function(){c.resolve()})}catch(d){c.reject({err:d,data:b})}return c.promise},remove:function(a,b,c,d,e){var f=Q.defer();try{b>=0&&d>b&&c>b&&"ended"!==e.readyState&&a.remove(b,c),this.waitForUpdateEnd(a).then(function(){f.resolve()})}catch(g){f.reject(g)}return f.promise},abort:function(a,b){"use strict";var c=Q.defer();try{"open"===a.readyState&&b.abort(),c.resolve()}catch(d){c.reject(d.description)}return c.promise}},MediaPlayer.dependencies.Stream=function(){"use strict";var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q=null,r=null,s=null,t=null,u=-1,v=null,w=-1,x=null,y=-1,z=!0,A=!1,B=!1,C=null,D=[],E=-1,F=null,G=function(){this.debug.log("Attempting play..."),A&&(this.debug.log("Do play."),this.videoModel.play())},H=function(){this.debug.log("Do pause."),this.videoModel.pause()},I=function(a){this.debug.log("Attempting seek..."),A&&(this.debug.log("Do seek: "+a),this.system.notify("setCurrentTime"),this.videoModel.setCurrentTime(a),t&&t.seek(a),v&&v.seek(a))},J=function(a){var b,c=this;if(b="msneedkey"!==a.type?a.type:q,D.push({type:b,initData:a.initData}),this.debug.log("DRM: Key required for - "+b),s&&q&&!C)try{C=c.protectionController.selectKeySystem(q,s)}catch(d){H.call(c),c.debug.log(d),c.errHandler.mediaKeySystemSelectionError(d)}C&&c.protectionController.ensureKeySession(C,b,a.initData)},K=function(a){var b=this,c=null,d=null,e=null,f=null;this.debug.log("DRM: Got a key message..."),c=a.target,d=new Uint16Array(a.message.buffer),e=String.fromCharCode.apply(null,d),f=a.destinationURL,b.protectionController.updateFromMessage(C,c,e,f).fail(function(a){H.call(b),b.debug.log(a),b.errHandler.mediaKeyMessageError(a)})},L=function(){this.debug.log("DRM: Key added.")},M=function(){var a,b=event.target;switch(a="DRM: MediaKeyError - sessionId: "+b.sessionId+" errorCode: "+b.error.code+" systemErrorCode: "+b.error.systemCode+" [",b.error.code){case 1:a+="MEDIA_KEYERR_UNKNOWN - An unspecified error occurred. This value is used for errors that don't match any of the other codes.";break;case 2:a+="MEDIA_KEYERR_CLIENT - The Key System could not be installed or updated.";break;case 3:a+="MEDIA_KEYERR_SERVICE - The message passed into update indicated an error from the license service.";break;case 4:a+="MEDIA_KEYERR_OUTPUT - There is no available output device with the required characteristics for the content protection system.";break;case 5:a+="MEDIA_KEYERR_HARDWARECHANGE - A hardware configuration change caused a content protection error.";break;case 6:a+="MEDIA_KEYERR_DOMAIN - An error occurred in a multi-device domain licensing configuration. The most common error is a failure to join the domain."}a+="]",this.debug.log(a),this.errHandler.mediaKeySessionError(a)},N=function(a){var b=Q.defer(),c=this,d=function(e){c.debug.log("MediaSource is open!"),c.debug.log(e),a.removeEventListener("sourceopen",d),a.removeEventListener("webkitsourceopen",d),b.resolve(a)};return c.debug.log("MediaSource should be closed. The actual readyState is: "+a.readyState),a.addEventListener("sourceopen",d,!1),a.addEventListener("webkitsourceopen",d,!1),c.mediaSourceExt.attachMediaSource(a,c.videoModel),c.debug.log("MediaSource attached to video. Waiting on open..."),b.promise},O=function(){var c=this;t&&t.reset(B),v&&v.reset(B),b&&c.mediaSourceExt.detachMediaSource(c.videoModel),A=!1,C=null,D=[],s=null,t=null,v=null,x=null,q=null,r=null,b=null,a=null},P=function(b,c,d,e){if(b&&c&&d)if(null===t&&null===v&&null===x){var f="No streams to play.";this.errHandler.manifestError(f,"nostreams",a),this.debug.log(f),e.reject()}else this.debug.log("MediaSource initialized!"),e.resolve(!0)},R=function(){this.debug.log("Getting MediaSource ready...");var a=Q.defer(),c=!1,d=!1,e=!1,f=this,g=f.manifestModel.getValue(),h=f.manifestExt.getIsLive(g);return f.debug.log("Gathering information for buffers. (1)"),f.manifestExt.getDuration(g,h).then(function(){f.manifestExt.getVideoData(g,E).then(function(h){return null!==h?(f.debug.log("Create video buffer."),f.manifestExt.getDataIndex(h,g,E).then(function(a){u=a,f.debug.log("Save video track: "+u)}),f.manifestExt.getCodec(h).then(function(a){return f.debug.log("Video codec: "+a),q=a,f.manifestExt.getContentProtectionData(h).then(function(c){if(f.debug.log("Video contentProtection"),c&&!f.capabilities.supportsMediaKeys())return f.errHandler.capabilityError("mediakeys"),Q.when(null);if(s=c,!f.capabilities.supportsCodec(f.videoModel.getElement(),a)){var d="Video Codec ("+a+") is not supported.";return f.errHandler.manifestError(d,"codec",g),f.debug.log(d),Q.when(null)}return f.sourceBufferExt.createSourceBuffer(b,a)})}).then(function(g){null===g?f.debug.log("No buffer was created, skipping video stream."):(t=f.system.getObject("bufferController"),t.initialize("video",E,h,g,f.videoModel,f.requestScheduler,f.fragmentController,b),f.debug.log("Video is ready!")),c=!0,P.call(f,c,d,e,a)},function(){f.errHandler.mediaSourceError("Error creating video source buffer."),c=!0,P.call(f,c,d,e,a)})):(f.debug.log("No video data."),c=!0,P.call(f,c,d,e,a)),f.manifestExt.getAudioDatas(g,E)}).then(function(h){return null!==h&&h.length>0?(f.debug.log("Have audio streams: "+h.length),f.manifestExt.getPrimaryAudioData(g,E).then(function(h){f.manifestExt.getDataIndex(h,g,E).then(function(a){w=a,f.debug.log("Save audio track: "+w)}),f.manifestExt.getCodec(h).then(function(a){return f.debug.log("Audio codec: "+a),r=a,f.manifestExt.getContentProtectionData(h).then(function(c){if(f.debug.log("Audio contentProtection"),c&&!f.capabilities.supportsMediaKeys())return f.errHandler.capabilityError("mediakeys"),Q.when(null);if(s=c,!f.capabilities.supportsCodec(f.videoModel.getElement(),a)){var d="Audio Codec ("+a+") is not supported.";return f.errHandler.manifestError(d,"codec",g),f.debug.log(d),Q.when(null)}return f.sourceBufferExt.createSourceBuffer(b,a)})}).then(function(g){null===g?f.debug.log("No buffer was created, skipping audio stream."):(v=f.system.getObject("bufferController"),v.initialize("audio",E,h,g,f.videoModel,f.requestScheduler,f.fragmentController,b),f.debug.log("Audio is ready!")),d=!0,P.call(f,c,d,e,a)},function(){f.errHandler.mediaSourceError("Error creating audio source buffer."),d=!0,P.call(f,c,d,e,a)})})):(f.debug.log("No audio streams."),d=!0,P.call(f,c,d,e,a)),f.manifestExt.getTextData(g,E)}).then(function(h){var i;null!==h?(f.manifestExt.getDataIndex(h,g,E).then(function(a){y=a,f.debug.log("Save text track: "+y)}),f.manifestExt.getMimeType(h).then(function(a){return i=a,f.sourceBufferExt.createSourceBuffer(b,i)}).then(function(b){null===b?f.debug.log("Source buffer was not created for text track"):(x=f.system.getObject("textController"),x.initialize(E,h,b,f.videoModel),b.hasOwnProperty("initialize")&&b.initialize(i,x),f.debug.log("Text is ready!"),e=!0,P.call(f,c,d,e,a))},function(b){f.debug.log("Error creating text source buffer:"),f.debug.log(b),f.errHandler.mediaSourceError("Error creating text source buffer."),e=!0,P.call(f,c,d,e,a)})):(f.debug.log("No text tracks."),e=!0,P.call(f,c,d,e,a))})}),a.promise},S=function(){var a=this,c=Q.defer(),d=a.manifestModel.getValue(),e=a.manifestExt.getIsLive(d);return a.debug.log("Getting ready for playback..."),a.manifestExt.getDurationForPeriod(E,a.manifestModel.getValue(),e).then(function(a){l=a}),a.manifestExt.getDuration(a.manifestModel.getValue(),e).then(function(c){return a.debug.log("Setting duration: "+c),a.mediaSourceExt.setDuration(b,c)}).then(function(){return a.debug.log("Duration successfully set."),a.manifestExt.getPeriodStart(a.manifestModel.getValue(),E)}).then(function(a){F=a,A=!0,c.resolve(!0)}),c.promise},T=function(){var a=this;a.debug.log("Got loadmetadata event."),c.resolve(null)},U=function(){this.debug.log("Got play event."),A&&(null!==F?(this.debug.log("Starting segment loading at offset: "+F),t&&t.seek(F),v&&v.seek(F),x&&x.seek(F)):(t&&t.start(),v&&v.start(),x&&x.start()))},V=function(){this.debug.log("Got pause event."),this.scheduleWhilePaused||ab.call(this)},W=function(a){var b=a.srcElement.error,c=b.code,d="";if(-1!==c){switch(c){case 1:d="MEDIA_ERR_ABORTED";break;case 2:d="MEDIA_ERR_NETWORK";break;case 3:d="MEDIA_ERR_DECODE";break;case 4:d="MEDIA_ERR_SRC_NOT_SUPPORTED";break;case 5:d="MEDIA_ERR_ENCRYPTED"}B=!0,this.debug.log("Video Element Error: "+d),this.debug.log(b),this.errHandler.mediaSourceError(d),this.reset()}},X=function(){this.debug.log("Got seeking event.");var a=this.videoModel.getCurrentTime();t&&t.seek(a),v&&v.seek(a)},Y=function(){this.debug.log("Seek complete."),this.videoModel.listen("seeking",h),this.videoModel.unlisten("seeked",i)},Z=function(){_.call(this)},$=function(){_.call(this)},_=function(){t&&t.updateBufferState(),v&&v.updateBufferState()},ab=function(){t&&t.stop(),v&&v.stop()},bb=function(d){var e=this;return e.debug.log("Stream start loading."),a=d,e.mediaSourceExt.createMediaSource().then(function(a){return e.debug.log("MediaSource created."),N.call(e,a)}).then(function(a){return b=a,e.debug.log("MediaSource set up."),R.call(e)}).then(function(){return e.debug.log("Start initializing playback."),S.call(e)}).then(function(){return z?(e.debug.log("Playback initialized!"),c.promise):void 0}).then(function(){e.debug.log("element loaded!"),0===E&&G.call(e)})},cb=function(){this.debug.log("Current time has changed, block programmatic seek."),this.videoModel.unlisten("seeking",h),this.videoModel.listen("seeked",i)},db=function(){t&&!t.isBufferingCompleted()||v&&!v.isBufferingCompleted()||b&&this.mediaSourceExt.signalEndOfStream(b)},eb=function(){ab.call(this)},fb=function(){var a,b,c=this,d=c.manifestModel.getValue();c.debug.log("Manifest updated... set new data on buffers."),t&&(a=t.getData(),a&&a.hasOwnProperty("id")?c.manifestExt.getDataForId(a.id,d,E).then(function(a){t.setData(a)}):c.manifestExt.getDataForIndex(u,d,E).then(function(a){t.setData(a)})),v&&(b=v.getData(),b&&b.hasOwnProperty("id")?c.manifestExt.getDataForId(b.id,d,E).then(function(a){v.setData(a)}):c.manifestExt.getDataForIndex(w,d,E).then(function(a){v.setData(a)}))};return{system:void 0,videoModel:void 0,manifestLoader:void 0,manifestModel:void 0,mediaSourceExt:void 0,sourceBufferExt:void 0,bufferExt:void 0,manifestExt:void 0,fragmentController:void 0,abrController:void 0,fragmentExt:void 0,protectionModel:void 0,protectionController:void 0,protectionExt:void 0,capabilities:void 0,debug:void 0,metricsExt:void 0,errHandler:void 0,requestScheduler:void 0,scheduleWhilePaused:void 0,setup:function(){this.system.mapHandler("manifestUpdated",void 0,fb.bind(this)),this.system.mapHandler("setCurrentTime",void 0,cb.bind(this)),this.system.mapHandler("bufferingCompleted",void 0,db.bind(this)),this.system.mapHandler("segmentLoadingFailed",void 0,eb.bind(this)),c=Q.defer(),e=U.bind(this),f=V.bind(this),g=W.bind(this),h=X.bind(this),i=Y.bind(this),k=Z.bind(this),j=$.bind(this),d=T.bind(this)},load:function(a,b){E=b,bb.call(this,a)},setVideoModel:function(a){this.videoModel=a,this.videoModel.listen("play",e),this.videoModel.listen("pause",f),this.videoModel.listen("error",g),this.videoModel.listen("seeking",h),this.videoModel.listen("timeupdate",j),this.videoModel.listen("progress",k),this.videoModel.listen("loadedmetadata",d)},initProtection:function(){m=J.bind(this),n=K.bind(this),o=L.bind(this),p=M.bind(this),this.protectionModel=this.system.getObject("protectionModel"),this.protectionModel.init(this.getVideoModel()),this.protectionController=this.system.getObject("protectionController"),this.protectionController.init(this.videoModel,this.protectionModel),this.protectionModel.listenToNeedKey(m),this.protectionModel.listenToKeyMessage(n),this.protectionModel.listenToKeyError(p),this.protectionModel.listenToKeyAdded(o)},getVideoModel:function(){return this.videoModel},getManifestExt:function(){var a=this;return a.manifestExt},setAutoPlay:function(a){z=a},getAutoPlay:function(){return z},reset:function(){H.call(this),this.videoModel.unlisten("play",e),this.videoModel.unlisten("pause",f),this.videoModel.unlisten("error",g),this.videoModel.unlisten("seeking",h),this.videoModel.unlisten("timeupdate",j),this.videoModel.unlisten("progress",k),this.videoModel.unlisten("loadedmetadata",d),O.call(this),this.protectionController&&this.protectionController.teardownKeySystem(C),this.protectionController=void 0,this.protectionModel=void 0,this.fragmentController=void 0,this.requestScheduler=void 0,c=Q.defer()},getDuration:function(){return l},setPeriodIndex:function(a){E=a},getPeriodIndex:function(){return E},getStartTime:function(){return F},play:G,seek:I,pause:H}},MediaPlayer.dependencies.Stream.prototype={constructor:MediaPlayer.dependencies.Stream},MediaPlayer.dependencies.StreamController=function(){"use strict";var a,b=[],c=4,d=3,e=!0,f=null,g=function(){a.play()},h=function(){a.pause()},i=function(b){a.seek(b)},j=function(a,b){var c=a.getElement(),d=b.getElement();return d.parentNode||c.parentNode.insertBefore(d,c),c.style.width="0px",d.style.width="100%",m(c,d),l(a),k(b),Q.when(!0)},k=function(a){a.listen("seeking",p),a.listen("progress",n),r()&&a.listen("timeupdate",o)},l=function(a){a.unlisten("seeking",p),a.unlisten("progress",n),a.unlisten("timeupdate",o)},m=function(a,b){["controls","loop","muted","playbackRate","volume"].forEach(function(c){b[c]=a[c]})},n=function(){var b=a.getVideoModel().getElement().buffered;if(b.length){var d=b.length-1,e=b.end(d),f=a.getStartTime()+a.getDuration()-e;c>f&&(a.getVideoModel().unlisten("progress",n),q())}},o=function(){if(!a.getVideoModel().getElement().seeking){var b=a.getStartTime()+a.getDuration(),c=a.getVideoModel().getCurrentTime();d>b-c&&v(a,r())}},p=function(){var b=a.getVideoModel().getCurrentTime(),c=s(b);c&&c!==a&&v(a,c,b)},q=function(){var a=r();a&&a.seek(a.getStartTime())},r=function(){var c=a.getPeriodIndex()+1;return ce;e++)if(d=b[e],c+=d.getDuration(),c>a)return d},t=function(){var a=this.system.getObject("videoModel"),b=document.createElement("video");return a.setElement(b),a},u=function(a){a.parentNode&&a.parentNode.removeChild(a)},v=function(b,c,d){b&&c&&b!==c&&Q.when(f||!0).then(function(){b.pause(),a=c,f=j(b.getVideoModel(),c.getVideoModel()),d?i(b.getVideoModel().getCurrentTime()):i(c.getStartTime()),g()})};return{system:void 0,videoModel:void 0,manifestLoader:void 0,manifestUpdater:void 0,manifestModel:void 0,mediaSourceExt:void 0,sourceBufferExt:void 0,bufferExt:void 0,manifestExt:void 0,fragmentController:void 0,abrController:void 0,fragmentExt:void 0,capabilities:void 0,debug:void 0,metricsExt:void 0,errHandler:void 0,getManifestExt:function(){return a.getManifestExt()},setAutoPlay:function(a){e=a},getAutoPlay:function(){return e},getVideoModel:function(){return this.videoModel},setVideoModel:function(a){this.videoModel=a},load:function(c){var d,f=this;f.manifestLoader.load(c).then(function(c){f.manifestModel.setValue(c),f.debug.log("Manifest has loaded."),f.debug.log(f.manifestModel.getValue()),f.manifestUpdater.init(),f.manifestExt.getPeriodCount(c).then(function(g){for(var h=0;g>h;h++)d=f.system.getObject("stream"),d.setVideoModel(0===h?f.videoModel:t.call(f)),d.initProtection(),d.setAutoPlay(e),d.load(c,h),b.push(d);a=b[0],k(a.getVideoModel())})},function(){f.reset()})},reset:function(){a&&l(a.getVideoModel());for(var c=0,d=b.length;d>c;c++){var e=b[c];e.reset(),e!==a&&u(e.getVideoModel().getElement())}b=[],this.manifestUpdater.stop(),this.manifestModel.setValue(null),f=null,a=null},play:g,seek:i,pause:h}},MediaPlayer.dependencies.StreamController.prototype={constructor:MediaPlayer.dependencies.StreamController},MediaPlayer.models.VideoModel=function(){"use strict";var a,b=[],c=function(){return b.length>0},d=function(c){null!==c&&b[c]!==!0&&(b.push(c),b[c]=!0,a.playbackRate=0)},e=function(d){if(null!==d){b[d]=!1;var e=b.indexOf(d);-1!==e&&b.splice(e,1),c()===!1&&(a.playbackRate=1)}},f=function(a,b){b?d(a):e(a)};return{system:void 0,setup:function(){},play:function(){a.play()},pause:function(){a.pause()},isPaused:function(){return a.paused},getPlaybackRate:function(){return a.playbackRate},setPlaybackRate:function(b){a.playbackRate=b},getCurrentTime:function(){return a.currentTime},setCurrentTime:function(b){a.currentTime!=b&&(a.currentTime=b)},listen:function(b,c){a.addEventListener(b,c,!1)},unlisten:function(b,c){a.removeEventListener(b,c,!1)},getElement:function(){return a},setElement:function(b){a=b},setSource:function(b){a.src=b},stallStream:f,isStalled:c}},MediaPlayer.models.VideoModel.prototype={constructor:MediaPlayer.models.VideoModel},MediaPlayer.dependencies.VideoModelExtensions=function(){"use strict";return{getDroppedFrames:function(a){var b=null!==a.webkitDroppedFrameCount,c=-1;return b&&(c=a.webkitDroppedFrameCount),c}}},MediaPlayer.dependencies.VideoModelExtensions.prototype={constructor:MediaPlayer.dependencies.VideoModelExtensions},MediaPlayer.dependencies.TextController=function(){var a,b,c="LOADING",d="READY",e=!1,f=-1,g=d,h=function(a){this.debug.log("TextController setState to:"+a),g=a},i=function(){if(e&&g===d){var b=this;h.call(b,c),b.indexHandler.getInitRequest(0,a).then(function(a){b.debug.log("Loading text track initialization: "+a.url),b.debug.log(a),b.fragmentLoader.load(a).then(k.bind(b,a),l.bind(b,a)),h.call(b,c)})}},j=function(){i.call(this)},k=function(a,c){var d=this;d.debug.log(" Text track Bytes finished loading: "+a.url),d.fragmentController.process(c.data).then(function(a){null!==a&&(d.debug.log("Push text track bytes: "+a.byteLength),d.sourceBufferExt.append(b,a,d.videoModel))})},l=function(){};return{videoModel:void 0,fragmentLoader:void 0,fragmentController:void 0,indexHandler:void 0,sourceBufferExt:void 0,debug:void 0,initialize:function(a,b,c,d){var f=this;f.setVideoModel(d),f.setPeriodIndex(a),f.setData(b),f.setBuffer(c),e=!0},getPeriodIndex:function(){return f},setPeriodIndex:function(a){f=a},getVideoModel:function(){return this.videoModel},setVideoModel:function(a){this.videoModel=a},getData:function(){return a},setData:function(b){a=b},getBuffer:function(){return b},setBuffer:function(a){b=a},reset:function(a,c){a||(this.sourceBufferExt.abort(c,b),this.sourceBufferExt.removeSourceBuffer(c,b))},start:j}},MediaPlayer.dependencies.TextController.prototype={constructor:MediaPlayer.dependencies.TextController},MediaPlayer.utils.TextTrackExtensions=function(){"use strict";return{addTextTrack:function(a,b,c,d,e){var f=a.addTextTrack("captions",c,d);f.default=e,f.mode="showing";for(var g in b){var h=b[g];f.addCue(new TextTrackCue(h.start,h.end,h.data))}return Q.when(f)},deleteCues:function(a){for(var b=a.textTracks[0],c=b.cues,d=c.length;d>=0;d--)b.removeCue(c[d]);b.mode="disabled"}}},MediaPlayer.dependencies.TextVTTSourceBuffer=function(){var a,b,c;return{system:void 0,eventBus:void 0,initialize:function(d,e){c=d,a=e.getVideoModel().getElement(),b=e.getData()},append:function(c){var d=this;d.getParser().parse(String.fromCharCode.apply(null,new Uint16Array(c))).then(function(c){var e=b.Representation_asArray[0].id,f=b.lang;d.getTextTrackExtensions().addTextTrack(a,c,e,f,!0).then(function(){d.eventBus.dispatchEvent({type:"updateend"})})})},abort:function(){this.getTextTrackExtensions().deleteCues(a)},getParser:function(){var a;return"text/vtt"===c&&(a=this.system.getObject("vttParser")),a},getTextTrackExtensions:function(){return this.system.getObject("textTrackExtensions")},addEventListener:function(a,b,c){this.eventBus.addEventListener(a,b,c)},removeEventListener:function(a,b,c){this.eventBus.removeEventListener(a,b,c)}}},MediaPlayer.dependencies.TextVTTSourceBuffer.prototype={constructor:MediaPlayer.dependencies.TextVTTSourceBuffer},MediaPlayer.utils.VTTParser=function(){"use strict";var a=function(a){var b=a.split(":"),c=b.length-1;return a=60*parseInt(b[c-1],10)+parseFloat(b[c],10),2===c&&(a+=3600*parseInt(b[0],10)),a};return{parse:function(b){var c,d=/(?:\r\n|\r|\n)/gm,e=/-->/,f=/(^[\s]+|[\s]+$)/g,g=[];b=b.split(d),c=b.length;for(var h=0;c>h;h++){var i=b[h];if(i.length>0&&"WEBVTT"!==i&&i.match(e)){var j=i.split(e),k=b[h+1];g.push({start:a(j[0].replace(f,"")),end:a(j[1].replace(f,"")),data:k})}}return Q.when(g)}}},MediaPlayer.rules.BaseRulesCollection=function(){"use strict";var a=[];return{downloadRatioRule:void 0,insufficientBufferRule:void 0,getRules:function(){return Q.when(a)},setup:function(){var a=this;a.getRules().then(function(b){b.push(a.downloadRatioRule),b.push(a.insufficientBufferRule)})}}},MediaPlayer.rules.BaseRulesCollection.prototype={constructor:MediaPlayer.rules.BaseRulesCollection},MediaPlayer.rules.DownloadRatioRule=function(){"use strict";var a=function(a,b,c){var d=this,e=Q.defer();return d.manifestExt.getRepresentationFor(a,c).then(function(a){d.manifestExt.getBandwidth(a).then(function(a){e.resolve(a/b)})}),e.promise};return{debug:void 0,manifestExt:void 0,checkIndex:function(b,c,d){var e,f,g,h,i,j,k,l,m,n,o=this,p=c.HttpList,q=.75;return o.debug.log("Checking download ratio rule..."),c?null===p||void 0===p||0===p.length?(o.debug.log("No requests made for this stream yet, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(e=p[p.length-1],g=(e.tfinish.getTime()-e.trequest.getTime())/1e3,f=(e.tfinish.getTime()-e.tresponse.getTime())/1e3,0>=g?(o.debug.log("Don't know how long the download of the last fragment took, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):null===e.mediaduration||void 0===e.mediaduration||e.mediaduration<=0?(o.debug.log("Don't know the duration of the last media fragment, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(k=Q.defer(),i=e.mediaduration/g,h=e.mediaduration/f*q,isNaN(h)||isNaN(i)?(o.debug.log("Total time: "+g+"s"),o.debug.log("Download time: "+f+"s"),o.debug.log("The ratios are NaN, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(o.debug.log("Total ratio: "+i),o.debug.log("Download ratio: "+h),o.debug.log("Download ratio: "+h),isNaN(h)?(o.debug.log("Invalid ratio, bailing."),k.resolve(new MediaPlayer.rules.SwitchRequest)):1>h?(o.debug.log("Download ratio is poor."),b>0?(o.debug.log("We are not at the lowest bitrate, so switch down."),o.manifestExt.getRepresentationFor(b-1,d).then(function(a){o.manifestExt.getBandwidth(a).then(function(a){o.manifestExt.getRepresentationFor(b,d).then(function(c){o.manifestExt.getBandwidth(c).then(function(c){j=a/c,o.debug.log("Switch ratio: "+j),j>h?(o.debug.log("Things must be going pretty bad, switch all the way down."),k.resolve(new MediaPlayer.rules.SwitchRequest(0))):(o.debug.log("Things could be better, so just switch down one index."),k.resolve(new MediaPlayer.rules.SwitchRequest(b-1))) +})})})})):(o.debug.log("We are at the lowest bitrate and cannot switch down, use current."),k.resolve(new MediaPlayer.rules.SwitchRequest(b)))):(o.debug.log("Download ratio is good."),o.manifestExt.getRepresentationCount(d).then(function(c){c-=1,c>b?(o.debug.log("We are not at the highest bitrate, so switch up."),o.manifestExt.getRepresentationFor(b+1,d).then(function(e){o.manifestExt.getBandwidth(e).then(function(e){o.manifestExt.getRepresentationFor(b,d).then(function(f){o.manifestExt.getBandwidth(f).then(function(f){if(j=e/f,o.debug.log("Switch ratio: "+j),h>=j)if(h>1e3)o.debug.log("Tons of bandwidth available, go all the way up."),k.resolve(new MediaPlayer.rules.SwitchRequest(c-1));else if(h>100)o.debug.log("Just enough bandwidth available, switch up one."),k.resolve(new MediaPlayer.rules.SwitchRequest(b+1));else{for(o.debug.log("Not exactly sure where to go, so do some math."),m=-1,l=[];(m+=1)m&&!(hb&&(i=MediaPlayer.rules.SwitchRequest.prototype.STRONG,g.debug.log("Apply STRONG to buffer rule.")),h?(g.debug.log("The buffer ran dry recently, switch down."),Q.when(new MediaPlayer.rules.SwitchRequest(c-1,i))):a>b?(g.debug.log("Too many dry buffer hits, quit switching bitrates."),Q.when(new MediaPlayer.rules.SwitchRequest(c,i))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,i)))))}}},MediaPlayer.rules.InsufficientBufferRule.prototype={constructor:MediaPlayer.rules.InsufficientBufferRule},MediaPlayer.rules.LimitSwitchesRule=function(){"use strict";var a=10,b=2e4,c=5,d=0;return{debug:void 0,checkIndex:function(e,f){if(d>0)return d-=1,Q.when(new MediaPlayer.rules.SwitchRequest(e,MediaPlayer.rules.SwitchRequest.prototype.STRONG));var g,h,i,j=this,k=!1,l=(new Date).getTime(),m=f.RepSwitchList.length;for(j.debug.log("Checking limit switches rule..."),i=m-1;i>=0;i-=1){if(g=f.RepSwitchList[i],h=l-g.t.getTime(),h>=b){j.debug.log("Reached time limit, bailing.");break}if(i>=a){j.debug.log("Found too many switches within validation time, force the stream to not change."),k=!0;break}}return k?(j.debug.log("Wait some time before allowing another switch."),d=c,Q.when(new MediaPlayer.rules.SwitchRequest(e,MediaPlayer.rules.SwitchRequest.prototype.STRONG))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,MediaPlayer.rules.SwitchRequest.prototype.STRONG))}}},MediaPlayer.rules.LimitSwitchesRule.prototype={constructor:MediaPlayer.rules.LimitSwitchesRule},MediaPlayer.rules.SwitchRequest=function(a,b){"use strict";this.quality=a,this.priority=b,void 0===this.quality&&(this.quality=999),void 0===this.priority&&(this.priority=.5)},MediaPlayer.rules.SwitchRequest.prototype={constructor:MediaPlayer.rules.SwitchRequest,NO_CHANGE:999,DEFAULT:.5,STRONG:1,WEAK:0},MediaPlayer.models.MetricsList=function(){"use strict";return{TcpList:[],HttpList:[],RepSwitchList:[],BufferLevel:[],PlayList:[],DroppedFrames:[]}},MediaPlayer.models.MetricsList.prototype={constructor:MediaPlayer.models.MetricsList},MediaPlayer.vo.SegmentRequest=function(){"use strict";this.action="download",this.startTime=0/0,this.streamType=null,this.type=null,this.duration=0/0,this.timescale=0/0,this.range=null,this.url=null,this.requestStartDate=null,this.firstByteDate=null,this.requestEndDate=null,this.deferred=null,this.quality=0/0,this.index=0/0},MediaPlayer.vo.SegmentRequest.prototype={constructor:MediaPlayer.vo.SegmentRequest,ACTION_DOWNLOAD:"download",ACTION_COMPLETE:"complete"},MediaPlayer.vo.metrics.BufferLevel=function(){"use strict";this.t=null,this.level=null},MediaPlayer.vo.metrics.BufferLevel.prototype={constructor:MediaPlayer.vo.metrics.BufferLevel},MediaPlayer.vo.metrics.DroppedFrames=function(){"use strict";this.time=null,this.droppedFrames=null},MediaPlayer.vo.metrics.DroppedFrames.prototype={constructor:MediaPlayer.vo.metrics.DroppedFrames},MediaPlayer.vo.metrics.HTTPRequest=function(){"use strict";this.tcpid=null,this.type=null,this.url=null,this.actualurl=null,this.range=null,this.trequest=null,this.tresponse=null,this.tfinish=null,this.responsecode=null,this.interval=null,this.mediaduration=null,this.trace=[]},MediaPlayer.vo.metrics.HTTPRequest.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest},MediaPlayer.vo.metrics.HTTPRequest.Trace=function(){"use strict";this.s=null,this.d=null,this.b=[]},MediaPlayer.vo.metrics.HTTPRequest.Trace.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest.Trace},MediaPlayer.vo.metrics.PlayList=function(){"use strict";this.start=null,this.mstart=null,this.starttype=null,this.trace=[]},MediaPlayer.vo.metrics.PlayList.Trace=function(){"use strict";this.representationid=null,this.subreplevel=null,this.start=null,this.mstart=null,this.duration=null,this.playbackspeed=null,this.stopreason=null},MediaPlayer.vo.metrics.PlayList.prototype={constructor:MediaPlayer.vo.metrics.PlayList},MediaPlayer.vo.metrics.PlayList.INITIAL_PLAY_START_REASON="initial_start",MediaPlayer.vo.metrics.PlayList.SEEK_START_REASON="seek",MediaPlayer.vo.metrics.PlayList.Trace.prototype={constructor:MediaPlayer.vo.metrics.PlayList.Trace()},MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON="user_request",MediaPlayer.vo.metrics.PlayList.Trace.REPRESENTATION_SWITCH_STOP_REASON="representation_switch",MediaPlayer.vo.metrics.PlayList.Trace.END_OF_CONTENT_STOP_REASON="end_of_content",MediaPlayer.vo.metrics.PlayList.Trace.REBUFFERING_REASON="rebuffering",MediaPlayer.vo.metrics.RepresentationSwitch=function(){"use strict";this.t=null,this.mt=null,this.to=null,this.lto=null},MediaPlayer.vo.metrics.RepresentationSwitch.prototype={constructor:MediaPlayer.vo.metrics.RepresentationSwitch},MediaPlayer.vo.metrics.TCPConnection=function(){"use strict";this.tcpid=null,this.dest=null,this.topen=null,this.tclose=null,this.tconnect=null},MediaPlayer.vo.metrics.TCPConnection.prototype={constructor:MediaPlayer.vo.metrics.TCPConnection}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJkYXNoLmFsbC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBYMkpTKGEsYixjKXtmdW5jdGlvbiBkKGEpe3ZhciBiPWEubG9jYWxOYW1lO3JldHVybiBudWxsPT1iJiYoYj1hLmJhc2VOYW1lKSwobnVsbD09Ynx8XCJcIj09YikmJihiPWEubm9kZU5hbWUpLGJ9ZnVuY3Rpb24gZShhKXtyZXR1cm4gYS5wcmVmaXh9ZnVuY3Rpb24gZihhKXtyZXR1cm5cInN0cmluZ1wiPT10eXBlb2YgYT9hLnJlcGxhY2UoLyYvZyxcIiZhbXA7XCIpLnJlcGxhY2UoLzwvZyxcIiZsdDtcIikucmVwbGFjZSgvPi9nLFwiJmd0O1wiKS5yZXBsYWNlKC9cIi9nLFwiJnF1b3Q7XCIpLnJlcGxhY2UoLycvZyxcIiYjeDI3O1wiKS5yZXBsYWNlKC9cXC8vZyxcIiYjeDJGO1wiKTphfWZ1bmN0aW9uIGcoYSl7cmV0dXJuIGEucmVwbGFjZSgvJmFtcDsvZyxcIiZcIikucmVwbGFjZSgvJmx0Oy9nLFwiPFwiKS5yZXBsYWNlKC8mZ3Q7L2csXCI+XCIpLnJlcGxhY2UoLyZxdW90Oy9nLCdcIicpLnJlcGxhY2UoLyYjeDI3Oy9nLFwiJ1wiKS5yZXBsYWNlKC8mI3gyRjsvZyxcIi9cIil9ZnVuY3Rpb24gaChmKXtpZihmLm5vZGVUeXBlPT11LkRPQ1VNRU5UX05PREUpe3ZhciBpLGosayxsPWYuZmlyc3RDaGlsZDtmb3Ioaj0wLGs9Zi5jaGlsZE5vZGVzLmxlbmd0aDtrPmo7ais9MSlpZihmLmNoaWxkTm9kZXNbal0ubm9kZVR5cGUhPT11LkNPTU1FTlRfTk9ERSl7bD1mLmNoaWxkTm9kZXNbal07YnJlYWt9aWYoYylpPWgobCk7ZWxzZXtpPXt9O3ZhciBtPWQobCk7aVttXT1oKGwpfXJldHVybiBpfWlmKGYubm9kZVR5cGU9PXUuRUxFTUVOVF9OT0RFKXt2YXIgaT1uZXcgT2JqZWN0O2kuX19jbnQ9MDtmb3IodmFyIG49Zi5jaGlsZE5vZGVzLG89MDtvPG4ubGVuZ3RoO28rKyl7dmFyIGw9bi5pdGVtKG8pLG09ZChsKTtpZihpLl9fY250KyssbnVsbD09aVttXSlpW21dPWgobCksaVttK1wiX2FzQXJyYXlcIl09bmV3IEFycmF5KDEpLGlbbStcIl9hc0FycmF5XCJdWzBdPWlbbV07ZWxzZXtpZihudWxsIT1pW21dJiYhKGlbbV1pbnN0YW5jZW9mIEFycmF5KSl7dmFyIHA9aVttXTtpW21dPW5ldyBBcnJheSxpW21dWzBdPXAsaVttK1wiX2FzQXJyYXlcIl09aVttXX1mb3IodmFyIHE9MDtudWxsIT1pW21dW3FdOylxKys7aVttXVtxXT1oKGwpfX1mb3IodmFyIHI9MDtyPGYuYXR0cmlidXRlcy5sZW5ndGg7cisrKXt2YXIgcz1mLmF0dHJpYnV0ZXMuaXRlbShyKTtpLl9fY250Kys7Zm9yKHZhciB2PXMudmFsdWUsdz0wLHg9YS5sZW5ndGg7eD53O3crKyl7dmFyIHk9YVt3XTt5LnRlc3QuY2FsbCh0aGlzLHMudmFsdWUpJiYodj15LmNvbnZlcnRlci5jYWxsKHRoaXMscy52YWx1ZSkpfWlbYitzLm5hbWVdPXZ9dmFyIHo9ZShmKTtyZXR1cm4gbnVsbCE9eiYmXCJcIiE9eiYmKGkuX19jbnQrKyxpLl9fcHJlZml4PXopLDE9PWkuX19jbnQmJm51bGwhPWlbXCIjdGV4dFwiXSYmKGk9aVtcIiN0ZXh0XCJdKSxudWxsIT1pW1wiI3RleHRcIl0mJihpLl9fdGV4dD1pW1wiI3RleHRcIl0sdCYmKGkuX190ZXh0PWcoaS5fX3RleHQpKSxkZWxldGUgaVtcIiN0ZXh0XCJdLGRlbGV0ZSBpW1wiI3RleHRfYXNBcnJheVwiXSksbnVsbCE9aVtcIiNjZGF0YS1zZWN0aW9uXCJdJiYoaS5fX2NkYXRhPWlbXCIjY2RhdGEtc2VjdGlvblwiXSxkZWxldGUgaVtcIiNjZGF0YS1zZWN0aW9uXCJdLGRlbGV0ZSBpW1wiI2NkYXRhLXNlY3Rpb25fYXNBcnJheVwiXSksKG51bGwhPWkuX190ZXh0fHxudWxsIT1pLl9fY2RhdGEpJiYoaS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybihudWxsIT10aGlzLl9fdGV4dD90aGlzLl9fdGV4dDpcIlwiKSsobnVsbCE9dGhpcy5fX2NkYXRhP3RoaXMuX19jZGF0YTpcIlwiKX0pLGl9cmV0dXJuIGYubm9kZVR5cGU9PXUuVEVYVF9OT0RFfHxmLm5vZGVUeXBlPT11LkNEQVRBX1NFQ1RJT05fTk9ERT9mLm5vZGVWYWx1ZTpmLm5vZGVUeXBlPT11LkNPTU1FTlRfTk9ERT9udWxsOnZvaWQgMH1mdW5jdGlvbiBpKGEsYixjLGQpe3ZhciBlPVwiPFwiKyhudWxsIT1hJiZudWxsIT1hLl9fcHJlZml4P2EuX19wcmVmaXgrXCI6XCI6XCJcIikrYjtpZihudWxsIT1jKWZvcih2YXIgZj0wO2Y8Yy5sZW5ndGg7ZisrKXt2YXIgZz1jW2ZdLGg9YVtnXTtlKz1cIiBcIitnLnN1YnN0cigxKStcIj0nXCIraCtcIidcIn1yZXR1cm4gZSs9ZD9cIi8+XCI6XCI+XCJ9ZnVuY3Rpb24gaihhLGIpe3JldHVyblwiPC9cIisobnVsbCE9YS5fX3ByZWZpeD9hLl9fcHJlZml4K1wiOlwiOlwiXCIpK2IrXCI+XCJ9ZnVuY3Rpb24gayhhLGIpe3JldHVybi0xIT09YS5pbmRleE9mKGIsYS5sZW5ndGgtYi5sZW5ndGgpfWZ1bmN0aW9uIGwoYSxiKXtyZXR1cm4gayhiLnRvU3RyaW5nKCksXCJfYXNBcnJheVwiKXx8MD09Yi50b1N0cmluZygpLmluZGV4T2YoXCJfXCIpfHxhW2JdaW5zdGFuY2VvZiBGdW5jdGlvbj8hMDohMX1mdW5jdGlvbiBtKGEpe3ZhciBiPTA7aWYoYSBpbnN0YW5jZW9mIE9iamVjdClmb3IodmFyIGMgaW4gYSlsKGEsYyl8fGIrKztyZXR1cm4gYn1mdW5jdGlvbiBuKGEpe3ZhciBiPVtdO2lmKGEgaW5zdGFuY2VvZiBPYmplY3QpZm9yKHZhciBjIGluIGEpLTE9PWMudG9TdHJpbmcoKS5pbmRleE9mKFwiX19cIikmJjA9PWMudG9TdHJpbmcoKS5pbmRleE9mKFwiX1wiKSYmYi5wdXNoKGMpO3JldHVybiBifWZ1bmN0aW9uIG8oYSl7dmFyIGI9XCJcIjtyZXR1cm4gbnVsbCE9YS5fX2NkYXRhJiYoYis9XCI8IVtDREFUQVtcIithLl9fY2RhdGErXCJdXT5cIiksbnVsbCE9YS5fX3RleHQmJihiKz10P2YoYS5fX3RleHQpOmEuX190ZXh0KSxifWZ1bmN0aW9uIHAoYSl7dmFyIGI9XCJcIjtyZXR1cm4gYSBpbnN0YW5jZW9mIE9iamVjdD9iKz1vKGEpOm51bGwhPWEmJihiKz10P2YoYSk6YSksYn1mdW5jdGlvbiBxKGEsYixjKXt2YXIgZD1cIlwiO2lmKDA9PWEubGVuZ3RoKWQrPWkoYSxiLGMsITApO2Vsc2UgZm9yKHZhciBlPTA7ZTxhLmxlbmd0aDtlKyspZCs9aShhW2VdLGIsbihhW2VdKSwhMSksZCs9cihhW2VdKSxkKz1qKGFbZV0sYik7cmV0dXJuIGR9ZnVuY3Rpb24gcihhKXt2YXIgYj1cIlwiLGM9bShhKTtpZihjPjApZm9yKHZhciBkIGluIGEpaWYoIWwoYSxkKSl7dmFyIGU9YVtkXSxmPW4oZSk7aWYobnVsbD09ZXx8dm9pZCAwPT1lKWIrPWkoZSxkLGYsITApO2Vsc2UgaWYoZSBpbnN0YW5jZW9mIE9iamVjdClpZihlIGluc3RhbmNlb2YgQXJyYXkpYis9cShlLGQsZik7ZWxzZXt2YXIgZz1tKGUpO2c+MHx8bnVsbCE9ZS5fX3RleHR8fG51bGwhPWUuX19jZGF0YT8oYis9aShlLGQsZiwhMSksYis9cihlKSxiKz1qKGUsZCkpOmIrPWkoZSxkLGYsITApfWVsc2UgYis9aShlLGQsZiwhMSksYis9cChlKSxiKz1qKGUsZCl9cmV0dXJuIGIrPXAoYSl9KG51bGw9PT1ifHx2b2lkIDA9PT1iKSYmKGI9XCJfXCIpLChudWxsPT09Y3x8dm9pZCAwPT09YykmJihjPSExKTt2YXIgcz1cIjEuMC4xMVwiLHQ9ITEsdT17RUxFTUVOVF9OT0RFOjEsVEVYVF9OT0RFOjMsQ0RBVEFfU0VDVElPTl9OT0RFOjQsQ09NTUVOVF9OT0RFOjgsRE9DVU1FTlRfTk9ERTo5fTt0aGlzLnBhcnNlWG1sU3RyaW5nPWZ1bmN0aW9uKGEpe3ZhciBiO2lmKHdpbmRvdy5ET01QYXJzZXIpe3ZhciBjPW5ldyB3aW5kb3cuRE9NUGFyc2VyO2I9Yy5wYXJzZUZyb21TdHJpbmcoYSxcInRleHQveG1sXCIpfWVsc2UgMD09YS5pbmRleE9mKFwiPD9cIikmJihhPWEuc3Vic3RyKGEuaW5kZXhPZihcIj8+XCIpKzIpKSxiPW5ldyBBY3RpdmVYT2JqZWN0KFwiTWljcm9zb2Z0LlhNTERPTVwiKSxiLmFzeW5jPVwiZmFsc2VcIixiLmxvYWRYTUwoYSk7cmV0dXJuIGJ9LHRoaXMueG1sMmpzb249ZnVuY3Rpb24oYSl7cmV0dXJuIGgoYSl9LHRoaXMueG1sX3N0cjJqc29uPWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMucGFyc2VYbWxTdHJpbmcoYSk7cmV0dXJuIHRoaXMueG1sMmpzb24oYil9LHRoaXMuanNvbjJ4bWxfc3RyPWZ1bmN0aW9uKGEpe3JldHVybiByKGEpfSx0aGlzLmpzb24yeG1sPWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMuanNvbjJ4bWxfc3RyKGEpO3JldHVybiB0aGlzLnBhcnNlWG1sU3RyaW5nKGIpfSx0aGlzLmdldFZlcnNpb249ZnVuY3Rpb24oKXtyZXR1cm4gc30sdGhpcy5lc2NhcGVNb2RlPWZ1bmN0aW9uKGEpe3Q9YX19ZnVuY3Rpb24gT2JqZWN0SXJvbihhKXt2YXIgYjtmb3IoYj1bXSxpPTAsbGVuPWEubGVuZ3RoO2xlbj5pO2krPTEpYVtpXS5pc1Jvb3Q/Yi5wdXNoKFwicm9vdFwiKTpiLnB1c2goYVtpXS5uYW1lKTt2YXIgYz1mdW5jdGlvbihhLGIpe3ZhciBjO2lmKG51bGwhPT1hJiZudWxsIT09Yilmb3IoYyBpbiBhKWEuaGFzT3duUHJvcGVydHkoYykmJihiLmhhc093blByb3BlcnR5KGMpfHwoYltjXT1hW2NdKSl9LGQ9ZnVuY3Rpb24oYSxiLGQpe3ZhciBlLGYsZyxoLGk7aWYobnVsbCE9PWEmJjAhPT1hLmxlbmd0aClmb3IoZT0wLGY9YS5sZW5ndGg7Zj5lO2UrPTEpZz1hW2VdLGIuaGFzT3duUHJvcGVydHkoZy5uYW1lKSYmKGQuaGFzT3duUHJvcGVydHkoZy5uYW1lKT9nLm1lcmdlJiYoaD1iW2cubmFtZV0saT1kW2cubmFtZV0sXCJvYmplY3RcIj09dHlwZW9mIGgmJlwib2JqZWN0XCI9PXR5cGVvZiBpP2MoaCxpKTpkW2cubmFtZV09bnVsbCE9Zy5tZXJnZUZ1bmN0aW9uP2cubWVyZ2VGdW5jdGlvbihoLGkpOmgraSk6ZFtnLm5hbWVdPWJbZy5uYW1lXSl9LGU9ZnVuY3Rpb24oYSxiKXt2YXIgYyxmLGcsaCxpLGosayxsPWE7aWYobnVsbCE9PWwuY2hpbGRyZW4mJjAhPT1sLmNoaWxkcmVuLmxlbmd0aClmb3IoYz0wLGY9bC5jaGlsZHJlbi5sZW5ndGg7Zj5jO2MrPTEpaWYoaj1sLmNoaWxkcmVuW2NdLGIuaGFzT3duUHJvcGVydHkoai5uYW1lKSlpZihqLmlzQXJyYXkpZm9yKGk9YltqLm5hbWUrXCJfYXNBcnJheVwiXSxnPTAsaD1pLmxlbmd0aDtoPmc7Zys9MSlrPWlbZ10sZChsLnByb3BlcnRpZXMsYixrKSxlKGosayk7ZWxzZSBrPWJbai5uYW1lXSxkKGwucHJvcGVydGllcyxiLGspLGUoaixrKX0sZj1mdW5jdGlvbihjKXt2YXIgZCxnLGgsaSxqLGssbDtpZihudWxsPT09YylyZXR1cm4gYztpZihcIm9iamVjdFwiIT10eXBlb2YgYylyZXR1cm4gYztmb3IoZD0wLGc9Yi5sZW5ndGg7Zz5kO2QrPTEpXCJyb290XCI9PT1iW2RdJiYoaj1hW2RdLGs9YyxlKGosaykpO2ZvcihpIGluIGMpaWYoYy5oYXNPd25Qcm9wZXJ0eShpKSl7aWYoaD1iLmluZGV4T2YoaSksLTEhPT1oKWlmKGo9YVtoXSxqLmlzQXJyYXkpZm9yKGw9Y1tpK1wiX2FzQXJyYXlcIl0sZD0wLGc9bC5sZW5ndGg7Zz5kO2QrPTEpaz1sW2RdLGUoaixrKTtlbHNlIGs9Y1tpXSxlKGosayk7ZihjW2ldKX1yZXR1cm4gY307cmV0dXJue3J1bjpmfX1pZihmdW5jdGlvbihhKXthKHZvaWQgMCxRPXt9KX0oZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKGEsYil7Yi5zdGFjayYmXCJvYmplY3RcIj09dHlwZW9mIGEmJm51bGwhPT1hJiZhLnN0YWNrJiYtMT09PWEuc3RhY2suaW5kZXhPZihOKSYmKGEuc3RhY2s9ZChhLnN0YWNrKStcIlxcblwiK04rXCJcXG5cIitkKGIuc3RhY2spKX1mdW5jdGlvbiBkKGEpe2Zvcih2YXIgYT1hLnNwbGl0KFwiXFxuXCIpLGI9W10sYz0wO2M8YS5sZW5ndGg7KytjKXt2YXIgZCxlPWFbY107aWYoZD0vYXQgLisgXFwoKC4qKTooXFxkKyk6XFxkK1xcKS8uZXhlYyhlKSl7dmFyIGY9ZFsyXTtkPWRbMV09PT13JiZmPj14JiZUPj1mfWVsc2UgZD0hMTshZCYmISgtMSE9PWUuaW5kZXhPZihcIihtb2R1bGUuanM6XCIpfHwtMSE9PWUuaW5kZXhPZihcIihub2RlLmpzOlwiKSkmJmIucHVzaChlKX1yZXR1cm4gYi5qb2luKFwiXFxuXCIpfWZ1bmN0aW9uIGUoKXtpZihFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSl7dmFyIGEsYixjPUVycm9yLnByZXBhcmVTdGFja1RyYWNlO3JldHVybiBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZT1mdW5jdGlvbihjLGQpe2E9ZFsxXS5nZXRGaWxlTmFtZSgpLGI9ZFsxXS5nZXRMaW5lTnVtYmVyKCl9LEVycm9yKCkuc3RhY2ssRXJyb3IucHJlcGFyZVN0YWNrVHJhY2U9Yyx3PWEsYn19ZnVuY3Rpb24gZihhLGIsYyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGNvbnNvbGUmJlwiZnVuY3Rpb25cIj09dHlwZW9mIGNvbnNvbGUud2FybiYmY29uc29sZS53YXJuKGIrXCIgaXMgZGVwcmVjYXRlZCwgdXNlIFwiK2MrXCIgaW5zdGVhZC5cIixFcnJvcihcIlwiKS5zdGFjayksYS5hcHBseShhLGFyZ3VtZW50cyl9fWZ1bmN0aW9uIGcoKXtmdW5jdGlvbiBhKGEpe2MmJihiPW4oYSksSChjLGZ1bmN0aW9uKGEsYyl7QShmdW5jdGlvbigpe2IucHJvbWlzZURpc3BhdGNoLmFwcGx5KGIsYyl9KX0sdm9pZCAwKSxkPWM9dm9pZCAwKX12YXIgYixjPVtdLGQ9W10sZT1LKGcucHJvdG90eXBlKSxmPUsoaC5wcm90b3R5cGUpO3JldHVybiBmLnByb21pc2VEaXNwYXRjaD1mdW5jdGlvbihhLGUsZil7dmFyIGc9Ryhhcmd1bWVudHMpO2M/KGMucHVzaChnKSxcIndoZW5cIj09PWUmJmZbMV0mJmQucHVzaChmWzFdKSk6QShmdW5jdGlvbigpe2IucHJvbWlzZURpc3BhdGNoLmFwcGx5KGIsZyl9KX0sZi52YWx1ZU9mPWZ1bmN0aW9uKCl7cmV0dXJuIGM/ZjpiLnZhbHVlT2YoKX0sRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UmJihFcnJvci5jYXB0dXJlU3RhY2tUcmFjZShmLGcpLGYuc3RhY2s9Zi5zdGFjay5zdWJzdHJpbmcoZi5zdGFjay5pbmRleE9mKFwiXFxuXCIpKzEpKSx6KGYpLGUucHJvbWlzZT1mLGUucmVzb2x2ZT1hLGUucmVqZWN0PWZ1bmN0aW9uKGIpe2EobShiKSl9LGUubm90aWZ5PWZ1bmN0aW9uKGEpe2MmJkgoZCxmdW5jdGlvbihiLGMpe0EoZnVuY3Rpb24oKXtjKGEpfSl9LHZvaWQgMCl9LGV9ZnVuY3Rpb24gaChhLGIsYyxkKXt2b2lkIDA9PT1iJiYoYj1mdW5jdGlvbihhKXtyZXR1cm4gbShFcnJvcihcIlByb21pc2UgZG9lcyBub3Qgc3VwcG9ydCBvcGVyYXRpb246IFwiK2EpKX0pO3ZhciBlPUsoaC5wcm90b3R5cGUpO3JldHVybiBlLnByb21pc2VEaXNwYXRjaD1mdW5jdGlvbihjLGQsZil7dmFyIGc7dHJ5e2c9YVtkXT9hW2RdLmFwcGx5KGUsZik6Yi5jYWxsKGUsZCxmKX1jYXRjaChoKXtnPW0oaCl9YyYmYyhnKX0sYyYmKGUudmFsdWVPZj1jKSxkJiYoZS5leGNlcHRpb249ZCkseihlKSxlfWZ1bmN0aW9uIGkoYSl7cmV0dXJuIGooYSk/YS52YWx1ZU9mKCk6YX1mdW5jdGlvbiBqKGEpe3JldHVybiBhJiZcImZ1bmN0aW9uXCI9PXR5cGVvZiBhLnByb21pc2VEaXNwYXRjaH1mdW5jdGlvbiBrKGEpe3JldHVybiFqKGkoYSkpfWZ1bmN0aW9uIGwoYSl7cmV0dXJuIGE9aShhKSxqKGEpJiZcImV4Y2VwdGlvblwiaW4gYX1mdW5jdGlvbiBtKGEpe3ZhciBhPWF8fEVycm9yKCksYj1oKHt3aGVuOmZ1bmN0aW9uKGIpe2lmKGIpe3ZhciBjPUkoUCx0aGlzKTstMSE9PWMmJihRLnNwbGljZShjLDEpLFAuc3BsaWNlKGMsMSkpfXJldHVybiBiP2IoYSk6bShhKX19LGZ1bmN0aW9uKCl7cmV0dXJuIG0oYSl9LGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LGEpO3JldHVybiFPJiZcInVuZGVmaW5lZFwiIT10eXBlb2Ygd2luZG93JiYhd2luZG93LlRvdWNoJiZ3aW5kb3cuY29uc29sZSYmY29uc29sZS5sb2coXCJTaG91bGQgYmUgZW1wdHk6XCIsUSksTz0hMCxQLnB1c2goYiksUS5wdXNoKGEpLGJ9ZnVuY3Rpb24gbihhKXtpZihqKGEpKXJldHVybiBhO2lmKChhPWkoYSkpJiZcImZ1bmN0aW9uXCI9PXR5cGVvZiBhLnRoZW4pe3ZhciBiPWcoKTtyZXR1cm4gYS50aGVuKGIucmVzb2x2ZSxiLnJlamVjdCxiLm5vdGlmeSksYi5wcm9taXNlfXJldHVybiBoKHt3aGVuOmZ1bmN0aW9uKCl7cmV0dXJuIGF9LGdldDpmdW5jdGlvbihiKXtyZXR1cm4gYVtiXX0scHV0OmZ1bmN0aW9uKGIsYyl7cmV0dXJuIGFbYl09YyxhfSxkZWw6ZnVuY3Rpb24oYil7cmV0dXJuIGRlbGV0ZSBhW2JdLGF9LHBvc3Q6ZnVuY3Rpb24oYixjKXtyZXR1cm4gYVtiXS5hcHBseShhLGMpfSxhcHBseTpmdW5jdGlvbihiKXtyZXR1cm4gYS5hcHBseSh2b2lkIDAsYil9LGtleXM6ZnVuY3Rpb24oKXtyZXR1cm4gTChhKX19LHZvaWQgMCxmdW5jdGlvbigpe3JldHVybiBhfSl9ZnVuY3Rpb24gbyhhLGIsZCxlKXtmdW5jdGlvbiBmKGEpe3RyeXtyZXR1cm4gYj9iKGEpOmF9Y2F0Y2goYyl7cmV0dXJuIG0oYyl9fWZ1bmN0aW9uIGgoYSl7aWYoZCl7YyhhLGspO3RyeXtyZXR1cm4gZChhKX1jYXRjaChiKXtyZXR1cm4gbShiKX19cmV0dXJuIG0oYSl9dmFyIGk9ZygpLGo9ITEsaz1uKGEpO3JldHVybiBBKGZ1bmN0aW9uKCl7ay5wcm9taXNlRGlzcGF0Y2goZnVuY3Rpb24oYSl7anx8KGo9ITAsaS5yZXNvbHZlKGYoYSkpKX0sXCJ3aGVuXCIsW2Z1bmN0aW9uKGEpe2p8fChqPSEwLGkucmVzb2x2ZShoKGEpKSl9XSl9KSxrLnByb21pc2VEaXNwYXRjaCh2b2lkIDAsXCJ3aGVuXCIsW3ZvaWQgMCxmdW5jdGlvbihhKXtpLm5vdGlmeShlP2UoYSk6YSl9XSksaS5wcm9taXNlfWZ1bmN0aW9uIHAoYSxiLGMpe3JldHVybiBvKGEsZnVuY3Rpb24oYSl7cmV0dXJuIHQoYSkudGhlbihmdW5jdGlvbihhKXtyZXR1cm4gYi5hcHBseSh2b2lkIDAsYSl9LGMpfSxjKX1mdW5jdGlvbiBxKGEsYixjKXt2YXIgZD1nKCk7cmV0dXJuIEEoZnVuY3Rpb24oKXtuKGEpLnByb21pc2VEaXNwYXRjaChkLnJlc29sdmUsYixjKX0pLGQucHJvbWlzZX1mdW5jdGlvbiByKGEpe3JldHVybiBmdW5jdGlvbihiKXt2YXIgYz1HKGFyZ3VtZW50cywxKTtyZXR1cm4gcShiLGEsYyl9fWZ1bmN0aW9uIHMoYSl7dmFyIGI9Ryhhcmd1bWVudHMsMSk7cmV0dXJuIFMoYSxiKX1mdW5jdGlvbiB0KGEpe3JldHVybiBvKGEsZnVuY3Rpb24oYSl7dmFyIGI9YS5sZW5ndGg7aWYoMD09PWIpcmV0dXJuIG4oYSk7dmFyIGM9ZygpO3JldHVybiBIKGEsZnVuY3Rpb24oZCxlLGYpe2soZSk/KGFbZl09aShlKSwwPT09LS1iJiZjLnJlc29sdmUoYSkpOm8oZSxmdW5jdGlvbihkKXthW2ZdPWQsMD09PS0tYiYmYy5yZXNvbHZlKGEpfSkuZmFpbChjLnJlamVjdCl9LHZvaWQgMCksYy5wcm9taXNlfSl9ZnVuY3Rpb24gdShhLGIpe3JldHVybiBvKGEsdm9pZCAwLGIpfWZ1bmN0aW9uIHYoYSxiKXt2YXIgYz1HKGFyZ3VtZW50cywyKSxkPWcoKTtyZXR1cm4gYy5wdXNoKGQubWFrZU5vZGVSZXNvbHZlcigpKSxSKGEsYixjKS5mYWlsKGQucmVqZWN0KSxkLnByb21pc2V9dmFyIHcseD1lKCkseT1mdW5jdGlvbigpe30sej1PYmplY3QuZnJlZXplfHx5O1widW5kZWZpbmVkXCIhPXR5cGVvZiBjYWphVk0mJih6PWNhamFWTS5kZWYpO3ZhciBBO2lmKFwidW5kZWZpbmVkXCIhPXR5cGVvZiBwcm9jZXNzKUE9cHJvY2Vzcy5uZXh0VGljaztlbHNlIGlmKFwiZnVuY3Rpb25cIj09dHlwZW9mIHNldEltbWVkaWF0ZSlBPXNldEltbWVkaWF0ZTtlbHNlIGlmKFwidW5kZWZpbmVkXCIhPXR5cGVvZiBNZXNzYWdlQ2hhbm5lbCl7dmFyIEI9bmV3IE1lc3NhZ2VDaGFubmVsLEM9e30sRD1DO0IucG9ydDEub25tZXNzYWdlPWZ1bmN0aW9uKCl7Qz1DLm5leHQ7dmFyIGE9Qy50YXNrO2RlbGV0ZSBDLnRhc2ssYSgpfSxBPWZ1bmN0aW9uKGEpe0Q9RC5uZXh0PXt0YXNrOmF9LEIucG9ydDIucG9zdE1lc3NhZ2UoMCl9fWVsc2UgQT1mdW5jdGlvbihhKXtzZXRUaW1lb3V0KGEsMCl9O3ZhciBFO0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kPyhFPUZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kLEU9RS5iaW5kKEUuY2FsbCkpOkU9ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGEuY2FsbC5hcHBseShhLGFyZ3VtZW50cyl9fTt2YXIgRixHPUUoQXJyYXkucHJvdG90eXBlLnNsaWNlKSxIPUUoQXJyYXkucHJvdG90eXBlLnJlZHVjZXx8ZnVuY3Rpb24oYSxiKXt2YXIgYz0wLGQ9dGhpcy5sZW5ndGg7aWYoMT09PWFyZ3VtZW50cy5sZW5ndGgpZm9yKDs7KXtpZihjIGluIHRoaXMpe2I9dGhpc1tjKytdO2JyZWFrfWlmKCsrYz49ZCl0aHJvdyBuZXcgVHlwZUVycm9yfWZvcig7ZD5jO2MrKyljIGluIHRoaXMmJihiPWEoYix0aGlzW2NdLGMpKTtyZXR1cm4gYn0pLEk9RShBcnJheS5wcm90b3R5cGUuaW5kZXhPZnx8ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPTA7Yjx0aGlzLmxlbmd0aDtiKyspaWYodGhpc1tiXT09PWEpcmV0dXJuIGI7cmV0dXJuLTF9KSxKPUUoQXJyYXkucHJvdG90eXBlLm1hcHx8ZnVuY3Rpb24oYSxiKXt2YXIgYz10aGlzLGQ9W107cmV0dXJuIEgoYyxmdW5jdGlvbihlLGYsZyl7ZC5wdXNoKGEuY2FsbChiLGYsZyxjKSl9LHZvaWQgMCksZH0pLEs9T2JqZWN0LmNyZWF0ZXx8ZnVuY3Rpb24oYSl7ZnVuY3Rpb24gYigpe31yZXR1cm4gYi5wcm90b3R5cGU9YSxuZXcgYn0sTD1PYmplY3Qua2V5c3x8ZnVuY3Rpb24oYSl7dmFyIGIsYz1bXTtmb3IoYiBpbiBhKWMucHVzaChiKTtyZXR1cm4gY30sTT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO0Y9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIFJldHVyblZhbHVlP1JldHVyblZhbHVlOmZ1bmN0aW9uKGEpe3RoaXMudmFsdWU9YX07dmFyIE49XCJGcm9tIHByZXZpb3VzIGV2ZW50OlwiO2IubmV4dFRpY2s9QSxiLmRlZmVyPWcsZy5wcm90b3R5cGUubWFrZU5vZGVSZXNvbHZlcj1mdW5jdGlvbigpe3ZhciBhPXRoaXM7cmV0dXJuIGZ1bmN0aW9uKGIsYyl7Yj9hLnJlamVjdChiKTphcmd1bWVudHMubGVuZ3RoPjI/YS5yZXNvbHZlKEcoYXJndW1lbnRzLDEpKTphLnJlc29sdmUoYyl9fSxiLnByb21pc2U9ZnVuY3Rpb24oYSl7dmFyIGI9ZygpO3JldHVybiBzKGEsYi5yZXNvbHZlLGIucmVqZWN0LGIubm90aWZ5KS5mYWlsKGIucmVqZWN0KSxiLnByb21pc2V9LGIubWFrZVByb21pc2U9aCxoLnByb3RvdHlwZS50aGVuPWZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbyh0aGlzLGEsYixjKX0saC5wcm90b3R5cGUudGhlblJlc29sdmU9ZnVuY3Rpb24oYSl7cmV0dXJuIG8odGhpcyxmdW5jdGlvbigpe3JldHVybiBhfSl9LEgoXCJpc1Jlc29sdmVkIGlzRnVsZmlsbGVkIGlzUmVqZWN0ZWQgZGlzcGF0Y2ggd2hlbiBzcHJlYWQgZ2V0IHB1dCBkZWwgcG9zdCBzZW5kIGludm9rZSBrZXlzIGZhcHBseSBmY2FsbCBmYmluZCBhbGwgYWxsUmVzb2x2ZWQgdGltZW91dCBkZWxheSBjYXRjaCBmaW5hbGx5IGZhaWwgZmluIHByb2dyZXNzIGVuZCBkb25lIG5mY2FsbCBuZmFwcGx5IG5mYmluZCBuY2FsbCBuYXBwbHkgbmJpbmQgbnBvc3QgbnNlbmQgbmludm9rZSBuZW5kIG5vZGVpZnlcIi5zcGxpdChcIiBcIiksZnVuY3Rpb24oYSxjKXtoLnByb3RvdHlwZVtjXT1mdW5jdGlvbigpe3JldHVybiBiW2NdLmFwcGx5KGIsW3RoaXNdLmNvbmNhdChHKGFyZ3VtZW50cykpKX19LHZvaWQgMCksaC5wcm90b3R5cGUudG9Tb3VyY2U9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50b1N0cmluZygpfSxoLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVyblwiW29iamVjdCBQcm9taXNlXVwifSx6KGgucHJvdG90eXBlKSxiLm5lYXJlcj1pLGIuaXNQcm9taXNlPWosYi5pc1Jlc29sdmVkPWZ1bmN0aW9uKGEpe3JldHVybiBrKGEpfHxsKGEpfSxiLmlzRnVsZmlsbGVkPWssYi5pc1JlamVjdGVkPWw7dmFyIE8sUD1bXSxRPVtdO2IucmVqZWN0PW0sYi5yZXNvbHZlPW4sYi5tYXN0ZXI9ZnVuY3Rpb24oYSl7cmV0dXJuIGgoe2lzRGVmOmZ1bmN0aW9uKCl7fX0sZnVuY3Rpb24oYixjKXtyZXR1cm4gcShhLGIsYyl9LGZ1bmN0aW9uKCl7cmV0dXJuIGkoYSl9KX0sYi53aGVuPW8sYi5zcHJlYWQ9cCxiLmFzeW5jPWZ1bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigpe2Z1bmN0aW9uIGIoYSxiKXt2YXIgZjt0cnl7Zj1jW2FdKGIpfWNhdGNoKGcpe3JldHVyblwiW29iamVjdCBTdG9wSXRlcmF0aW9uXVwiPT09TShnKXx8ZyBpbnN0YW5jZW9mIEY/Zy52YWx1ZTptKGcpfXJldHVybiBvKGYsZCxlKX12YXIgYz1hLmFwcGx5KHRoaXMsYXJndW1lbnRzKSxkPWIuYmluZChiLFwic2VuZFwiKSxlPWIuYmluZChiLFwidGhyb3dcIik7cmV0dXJuIGQoKX19LGJbXCJyZXR1cm5cIl09ZnVuY3Rpb24oYSl7dGhyb3cgbmV3IEYoYSl9LGIucHJvbWlzZWQ9ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHAoW3RoaXMsdChhcmd1bWVudHMpXSxmdW5jdGlvbihiLGMpe3JldHVybiBhLmFwcGx5KGIsYyl9KX19LGIuZGlzcGF0Y2g9cSxiLmRpc3BhdGNoZXI9cixiLmdldD1yKFwiZ2V0XCIpLGIucHV0PXIoXCJwdXRcIiksYltcImRlbGV0ZVwiXT1iLmRlbD1yKFwiZGVsXCIpO3ZhciBSPWIucG9zdD1yKFwicG9zdFwiKTtiLnNlbmQ9ZnVuY3Rpb24oYSxiKXt2YXIgYz1HKGFyZ3VtZW50cywyKTtyZXR1cm4gUihhLGIsYyl9LGIuaW52b2tlPWYoYi5zZW5kLFwiaW52b2tlXCIsXCJzZW5kXCIpO3ZhciBTPWIuZmFwcGx5PXIoXCJhcHBseVwiKTtiW1widHJ5XCJdPXMsYi5mY2FsbD1zLGIuZmJpbmQ9ZnVuY3Rpb24oYSl7dmFyIGI9Ryhhcmd1bWVudHMsMSk7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIGM9Yi5jb25jYXQoRyhhcmd1bWVudHMpKTtyZXR1cm4gUyhhLGMpfX0sYi5rZXlzPXIoXCJrZXlzXCIpLGIuYWxsPXQsYi5hbGxSZXNvbHZlZD1mdW5jdGlvbihhKXtyZXR1cm4gbyhhLGZ1bmN0aW9uKGEpe3JldHVybiBvKHQoSihhLGZ1bmN0aW9uKGEpe3JldHVybiBvKGEseSx5KX0pKSxmdW5jdGlvbigpe3JldHVybiBKKGEsbil9KX0pfSxiW1wiY2F0Y2hcIl09Yi5mYWlsPXUsYi5wcm9ncmVzcz1mdW5jdGlvbihhLGIpe3JldHVybiBvKGEsdm9pZCAwLHZvaWQgMCxiKX0sYltcImZpbmFsbHlcIl09Yi5maW49ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbyhhLGZ1bmN0aW9uKGEpe3JldHVybiBvKGIoKSxmdW5jdGlvbigpe3JldHVybiBhfSl9LGZ1bmN0aW9uKGEpe3JldHVybiBvKGIoKSxmdW5jdGlvbigpe3JldHVybiBtKGEpfSl9KX0sYi5kb25lPWZ1bmN0aW9uKGEsZCxlLGYpe2Q9ZHx8ZXx8Zj9vKGEsZCxlLGYpOmEsdShkLGZ1bmN0aW9uKGQpe0EoZnVuY3Rpb24oKXtpZihjKGQsYSksIWIub25lcnJvcil0aHJvdyBkO2Iub25lcnJvcihkKX0pfSl9LGIudGltZW91dD1mdW5jdGlvbihhLGIpe3ZhciBjPWcoKSxkPXNldFRpbWVvdXQoZnVuY3Rpb24oKXtjLnJlamVjdChFcnJvcihcIlRpbWVkIG91dCBhZnRlciBcIitiK1wiIG1zXCIpKX0sYik7cmV0dXJuIG8oYSxmdW5jdGlvbihhKXtjbGVhclRpbWVvdXQoZCksYy5yZXNvbHZlKGEpfSxmdW5jdGlvbihhKXtjbGVhclRpbWVvdXQoZCksYy5yZWplY3QoYSl9KSxjLnByb21pc2V9LGIuZGVsYXk9ZnVuY3Rpb24oYSxiKXt2b2lkIDA9PT1iJiYoYj1hLGE9dm9pZCAwKTt2YXIgYz1nKCk7cmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtjLnJlc29sdmUoYSl9LGIpLGMucHJvbWlzZX0sYi5uZmFwcGx5PWZ1bmN0aW9uKGEsYil7dmFyIGM9RyhiKSxkPWcoKTtyZXR1cm4gYy5wdXNoKGQubWFrZU5vZGVSZXNvbHZlcigpKSxTKGEsYykuZmFpbChkLnJlamVjdCksZC5wcm9taXNlfSxiLm5mY2FsbD1mdW5jdGlvbihhKXt2YXIgYj1HKGFyZ3VtZW50cywxKSxjPWcoKTtyZXR1cm4gYi5wdXNoKGMubWFrZU5vZGVSZXNvbHZlcigpKSxTKGEsYikuZmFpbChjLnJlamVjdCksYy5wcm9taXNlfSxiLm5mYmluZD1mdW5jdGlvbihhKXt2YXIgYj1HKGFyZ3VtZW50cywxKTtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgYz1iLmNvbmNhdChHKGFyZ3VtZW50cykpLGQ9ZygpO3JldHVybiBjLnB1c2goZC5tYWtlTm9kZVJlc29sdmVyKCkpLFMoYSxjKS5mYWlsKGQucmVqZWN0KSxkLnByb21pc2V9fSxiLm5wb3N0PWZ1bmN0aW9uKGEsYixjKXt2YXIgYz1HKGMpLGQ9ZygpO3JldHVybiBjLnB1c2goZC5tYWtlTm9kZVJlc29sdmVyKCkpLFIoYSxiLGMpLmZhaWwoZC5yZWplY3QpLGQucHJvbWlzZX0sYi5uc2VuZD12LGIubmludm9rZT1mKHYsXCJuaW52b2tlXCIsXCJuc2VuZFwiKSxiLm5vZGVpZnk9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj8oYS50aGVuKGZ1bmN0aW9uKGEpe0EoZnVuY3Rpb24oKXtiKG51bGwsYSl9KX0sZnVuY3Rpb24oYSl7QShmdW5jdGlvbigpe2IoYSl9KX0pLHZvaWQgMCk6YX07dmFyIFQ9ZSgpfSksZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGI9e1ZFUlNJT046XCIwLjUuM1wifTtiLlN5c3RlbT1mdW5jdGlvbigpe3RoaXMuX21hcHBpbmdzPXt9LHRoaXMuX291dGxldHM9e30sdGhpcy5faGFuZGxlcnM9e30sdGhpcy5zdHJpY3RJbmplY3Rpb25zPSEwLHRoaXMuYXV0b01hcE91dGxldHM9ITEsdGhpcy5wb3N0SW5qZWN0aW9uSG9vaz1cInNldHVwXCJ9LGIuU3lzdGVtLnByb3RvdHlwZT17X2NyZWF0ZUFuZFNldHVwSW5zdGFuY2U6ZnVuY3Rpb24oYSxiKXt2YXIgYz1uZXcgYjtyZXR1cm4gdGhpcy5pbmplY3RJbnRvKGMsYSksY30sX3JldHJpZXZlRnJvbUNhY2hlT3JDcmVhdGU6ZnVuY3Rpb24oYSxiKXtcInVuZGVmaW5lZFwiPT10eXBlb2YgYiYmKGI9ITEpO3ZhciBjO2lmKCF0aGlzLl9tYXBwaW5ncy5oYXNPd25Qcm9wZXJ0eShhKSl0aHJvdyBuZXcgRXJyb3IoMWUzKTt2YXIgZD10aGlzLl9tYXBwaW5nc1thXTtyZXR1cm4hYiYmZC5pc1NpbmdsZXRvbj8obnVsbD09ZC5vYmplY3QmJihkLm9iamVjdD10aGlzLl9jcmVhdGVBbmRTZXR1cEluc3RhbmNlKGEsZC5jbGF6eikpLGM9ZC5vYmplY3QpOmM9ZC5jbGF6ej90aGlzLl9jcmVhdGVBbmRTZXR1cEluc3RhbmNlKGEsZC5jbGF6eik6ZC5vYmplY3QsY30sbWFwT3V0bGV0OmZ1bmN0aW9uKGEsYixjKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYSl0aHJvdyBuZXcgRXJyb3IoMTAxMCk7cmV0dXJuIGI9Ynx8XCJnbG9iYWxcIixjPWN8fGEsdGhpcy5fb3V0bGV0cy5oYXNPd25Qcm9wZXJ0eShiKXx8KHRoaXMuX291dGxldHNbYl09e30pLHRoaXMuX291dGxldHNbYl1bY109YSx0aGlzfSxnZXRPYmplY3Q6ZnVuY3Rpb24oYSl7aWYoXCJ1bmRlZmluZWRcIj09dHlwZW9mIGEpdGhyb3cgbmV3IEVycm9yKDEwMjApO3JldHVybiB0aGlzLl9yZXRyaWV2ZUZyb21DYWNoZU9yQ3JlYXRlKGEpfSxtYXBWYWx1ZTpmdW5jdGlvbihhLGIpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBhKXRocm93IG5ldyBFcnJvcigxMDMwKTtyZXR1cm4gdGhpcy5fbWFwcGluZ3NbYV09e2NsYXp6Om51bGwsb2JqZWN0OmIsaXNTaW5nbGV0b246ITB9LHRoaXMuYXV0b01hcE91dGxldHMmJnRoaXMubWFwT3V0bGV0KGEpLHRoaXMuaGFzTWFwcGluZyhhKSYmdGhpcy5pbmplY3RJbnRvKGIsYSksdGhpc30saGFzTWFwcGluZzpmdW5jdGlvbihhKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYSl0aHJvdyBuZXcgRXJyb3IoMTA0MCk7cmV0dXJuIHRoaXMuX21hcHBpbmdzLmhhc093blByb3BlcnR5KGEpfSxtYXBDbGFzczpmdW5jdGlvbihhLGIpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBhKXRocm93IG5ldyBFcnJvcigxMDUwKTtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYil0aHJvdyBuZXcgRXJyb3IoMTA1MSk7cmV0dXJuIHRoaXMuX21hcHBpbmdzW2FdPXtjbGF6ejpiLG9iamVjdDpudWxsLGlzU2luZ2xldG9uOiExfSx0aGlzLmF1dG9NYXBPdXRsZXRzJiZ0aGlzLm1hcE91dGxldChhKSx0aGlzfSxtYXBTaW5nbGV0b246ZnVuY3Rpb24oYSxiKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYSl0aHJvdyBuZXcgRXJyb3IoMTA2MCk7aWYoXCJ1bmRlZmluZWRcIj09dHlwZW9mIGIpdGhyb3cgbmV3IEVycm9yKDEwNjEpO3JldHVybiB0aGlzLl9tYXBwaW5nc1thXT17Y2xheno6YixvYmplY3Q6bnVsbCxpc1NpbmdsZXRvbjohMH0sdGhpcy5hdXRvTWFwT3V0bGV0cyYmdGhpcy5tYXBPdXRsZXQoYSksdGhpc30saW5zdGFudGlhdGU6ZnVuY3Rpb24oYSl7aWYoXCJ1bmRlZmluZWRcIj09dHlwZW9mIGEpdGhyb3cgbmV3IEVycm9yKDEwNzApO3JldHVybiB0aGlzLl9yZXRyaWV2ZUZyb21DYWNoZU9yQ3JlYXRlKGEsITApfSxpbmplY3RJbnRvOmZ1bmN0aW9uKGEsYil7aWYoXCJ1bmRlZmluZWRcIj09dHlwZW9mIGEpdGhyb3cgbmV3IEVycm9yKDEwODApO2lmKFwib2JqZWN0XCI9PXR5cGVvZiBhKXt2YXIgYz1bXTt0aGlzLl9vdXRsZXRzLmhhc093blByb3BlcnR5KFwiZ2xvYmFsXCIpJiZjLnB1c2godGhpcy5fb3V0bGV0cy5nbG9iYWwpLFwidW5kZWZpbmVkXCIhPXR5cGVvZiBiJiZ0aGlzLl9vdXRsZXRzLmhhc093blByb3BlcnR5KGIpJiZjLnB1c2godGhpcy5fb3V0bGV0c1tiXSk7Zm9yKHZhciBkIGluIGMpe3ZhciBlPWNbZF07Zm9yKHZhciBmIGluIGUpe3ZhciBnPWVbZl07KCF0aGlzLnN0cmljdEluamVjdGlvbnN8fGYgaW4gYSkmJihhW2ZdPXRoaXMuZ2V0T2JqZWN0KGcpKX19XCJzZXR1cFwiaW4gYSYmYS5zZXR1cC5jYWxsKGEpfXJldHVybiB0aGlzfSx1bm1hcDpmdW5jdGlvbihhKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYSl0aHJvdyBuZXcgRXJyb3IoMTA5MCk7cmV0dXJuIGRlbGV0ZSB0aGlzLl9tYXBwaW5nc1thXSx0aGlzfSx1bm1hcE91dGxldDpmdW5jdGlvbihhLGIpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBhKXRocm93IG5ldyBFcnJvcigxMTAwKTtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYil0aHJvdyBuZXcgRXJyb3IoMTEwMSk7cmV0dXJuIGRlbGV0ZSB0aGlzLl9vdXRsZXRzW2FdW2JdLHRoaXN9LG1hcEhhbmRsZXI6ZnVuY3Rpb24oYSxiLGMsZCxlKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgYSl0aHJvdyBuZXcgRXJyb3IoMTExMCk7cmV0dXJuIGI9Ynx8XCJnbG9iYWxcIixjPWN8fGEsXCJ1bmRlZmluZWRcIj09dHlwZW9mIGQmJihkPSExKSxcInVuZGVmaW5lZFwiPT10eXBlb2YgZSYmKGU9ITEpLHRoaXMuX2hhbmRsZXJzLmhhc093blByb3BlcnR5KGEpfHwodGhpcy5faGFuZGxlcnNbYV09e30pLHRoaXMuX2hhbmRsZXJzW2FdLmhhc093blByb3BlcnR5KGIpfHwodGhpcy5faGFuZGxlcnNbYV1bYl09W10pLHRoaXMuX2hhbmRsZXJzW2FdW2JdLnB1c2goe2hhbmRsZXI6YyxvbmVTaG90OmQscGFzc0V2ZW50OmV9KSx0aGlzfSx1bm1hcEhhbmRsZXI6ZnVuY3Rpb24oYSxiLGMpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBhKXRocm93IG5ldyBFcnJvcigxMTIwKTtpZihiPWJ8fFwiZ2xvYmFsXCIsYz1jfHxhLHRoaXMuX2hhbmRsZXJzLmhhc093blByb3BlcnR5KGEpJiZ0aGlzLl9oYW5kbGVyc1thXS5oYXNPd25Qcm9wZXJ0eShiKSl7dmFyIGQ9dGhpcy5faGFuZGxlcnNbYV1bYl07Zm9yKHZhciBlIGluIGQpe3ZhciBmPWRbZV07aWYoZi5oYW5kbGVyPT09Yyl7ZC5zcGxpY2UoZSwxKTticmVha319fXJldHVybiB0aGlzfSxub3RpZnk6ZnVuY3Rpb24oYSl7aWYoXCJ1bmRlZmluZWRcIj09dHlwZW9mIGEpdGhyb3cgbmV3IEVycm9yKDExMzApO3ZhciBiPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyksYz1iLnNsaWNlKDEpO2lmKHRoaXMuX2hhbmRsZXJzLmhhc093blByb3BlcnR5KGEpKXt2YXIgZD10aGlzLl9oYW5kbGVyc1thXTtmb3IodmFyIGUgaW4gZCl7dmFyIGYsZz1kW2VdO1wiZ2xvYmFsXCIhPT1lJiYoZj10aGlzLmdldE9iamVjdChlKSk7dmFyIGgsaSxqPVtdO2ZvcihoPTAsaT1nLmxlbmd0aDtpPmg7aCsrKXt2YXIgayxsPWdbaF07az1mJiZcInN0cmluZ1wiPT10eXBlb2YgbC5oYW5kbGVyP2ZbbC5oYW5kbGVyXTpsLmhhbmRsZXIsbC5vbmVTaG90JiZqLnVuc2hpZnQoaCksbC5wYXNzRXZlbnQ/ay5hcHBseShmLGIpOmsuYXBwbHkoZixjKX1mb3IoaD0wLGk9ai5sZW5ndGg7aT5oO2grKylnLnNwbGljZShqW2hdLDEpfX1yZXR1cm4gdGhpc319LGEuZGlqb249Yn0odGhpcyksXCJ1bmRlZmluZWRcIj09dHlwZW9mIHV0aWxzKXZhciB1dGlscz17fTtcInVuZGVmaW5lZFwiPT10eXBlb2YgdXRpbHMuTWF0aCYmKHV0aWxzLk1hdGg9e30pLHV0aWxzLk1hdGgudG82NEJpdE51bWJlcj1mdW5jdGlvbihhLGIpe3ZhciBjLGQsZTtyZXR1cm4gYz1uZXcgZ29vZy5tYXRoLkxvbmcoMCxiKSxkPW5ldyBnb29nLm1hdGguTG9uZyhhLDApLGU9Yy5hZGQoZCksZS50b051bWJlcigpfSxnb29nPXt9LGdvb2cubWF0aD17fSxnb29nLm1hdGguTG9uZz1mdW5jdGlvbihhLGIpe3RoaXMubG93Xz0wfGEsdGhpcy5oaWdoXz0wfGJ9LGdvb2cubWF0aC5Mb25nLkludENhY2hlXz17fSxnb29nLm1hdGguTG9uZy5mcm9tSW50PWZ1bmN0aW9uKGEpe2lmKGE+PS0xMjgmJjEyOD5hKXt2YXIgYj1nb29nLm1hdGguTG9uZy5JbnRDYWNoZV9bYV07aWYoYilyZXR1cm4gYn12YXIgYz1uZXcgZ29vZy5tYXRoLkxvbmcoMHxhLDA+YT8tMTowKTtyZXR1cm4gYT49LTEyOCYmMTI4PmEmJihnb29nLm1hdGguTG9uZy5JbnRDYWNoZV9bYV09YyksY30sZ29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcj1mdW5jdGlvbihhKXtyZXR1cm4gaXNOYU4oYSl8fCFpc0Zpbml0ZShhKT9nb29nLm1hdGguTG9uZy5aRVJPOmE8PS1nb29nLm1hdGguTG9uZy5UV09fUFdSXzYzX0RCTF8/Z29vZy5tYXRoLkxvbmcuTUlOX1ZBTFVFOmErMT49Z29vZy5tYXRoLkxvbmcuVFdPX1BXUl82M19EQkxfP2dvb2cubWF0aC5Mb25nLk1BWF9WQUxVRTowPmE/Z29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcigtYSkubmVnYXRlKCk6bmV3IGdvb2cubWF0aC5Mb25nKDB8YSVnb29nLm1hdGguTG9uZy5UV09fUFdSXzMyX0RCTF8sMHxhL2dvb2cubWF0aC5Mb25nLlRXT19QV1JfMzJfREJMXyl9LGdvb2cubWF0aC5Mb25nLmZyb21CaXRzPWZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBnb29nLm1hdGguTG9uZyhhLGIpfSxnb29nLm1hdGguTG9uZy5mcm9tU3RyaW5nPWZ1bmN0aW9uKGEsYil7aWYoMD09YS5sZW5ndGgpdGhyb3cgRXJyb3IoXCJudW1iZXIgZm9ybWF0IGVycm9yOiBlbXB0eSBzdHJpbmdcIik7dmFyIGM9Ynx8MTA7aWYoMj5jfHxjPjM2KXRocm93IEVycm9yKFwicmFkaXggb3V0IG9mIHJhbmdlOiBcIitjKTtpZihcIi1cIj09YS5jaGFyQXQoMCkpcmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21TdHJpbmcoYS5zdWJzdHJpbmcoMSksYykubmVnYXRlKCk7aWYoYS5pbmRleE9mKFwiLVwiKT49MCl0aHJvdyBFcnJvcignbnVtYmVyIGZvcm1hdCBlcnJvcjogaW50ZXJpb3IgXCItXCIgY2hhcmFjdGVyOiAnK2EpO2Zvcih2YXIgZD1nb29nLm1hdGguTG9uZy5mcm9tTnVtYmVyKE1hdGgucG93KGMsOCkpLGU9Z29vZy5tYXRoLkxvbmcuWkVSTyxmPTA7ZjxhLmxlbmd0aDtmKz04KXt2YXIgZz1NYXRoLm1pbig4LGEubGVuZ3RoLWYpLGg9cGFyc2VJbnQoYS5zdWJzdHJpbmcoZixmK2cpLGMpO2lmKDg+Zyl7dmFyIGk9Z29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcihNYXRoLnBvdyhjLGcpKTtlPWUubXVsdGlwbHkoaSkuYWRkKGdvb2cubWF0aC5Mb25nLmZyb21OdW1iZXIoaCkpfWVsc2UgZT1lLm11bHRpcGx5KGQpLGU9ZS5hZGQoZ29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcihoKSl9cmV0dXJuIGV9LGdvb2cubWF0aC5Mb25nLlRXT19QV1JfMTZfREJMXz02NTUzNixnb29nLm1hdGguTG9uZy5UV09fUFdSXzI0X0RCTF89MTw8MjQsZ29vZy5tYXRoLkxvbmcuVFdPX1BXUl8zMl9EQkxfPWdvb2cubWF0aC5Mb25nLlRXT19QV1JfMTZfREJMXypnb29nLm1hdGguTG9uZy5UV09fUFdSXzE2X0RCTF8sZ29vZy5tYXRoLkxvbmcuVFdPX1BXUl8zMV9EQkxfPWdvb2cubWF0aC5Mb25nLlRXT19QV1JfMzJfREJMXy8yLGdvb2cubWF0aC5Mb25nLlRXT19QV1JfNDhfREJMXz1nb29nLm1hdGguTG9uZy5UV09fUFdSXzMyX0RCTF8qZ29vZy5tYXRoLkxvbmcuVFdPX1BXUl8xNl9EQkxfLGdvb2cubWF0aC5Mb25nLlRXT19QV1JfNjRfREJMXz1nb29nLm1hdGguTG9uZy5UV09fUFdSXzMyX0RCTF8qZ29vZy5tYXRoLkxvbmcuVFdPX1BXUl8zMl9EQkxfLGdvb2cubWF0aC5Mb25nLlRXT19QV1JfNjNfREJMXz1nb29nLm1hdGguTG9uZy5UV09fUFdSXzY0X0RCTF8vMixnb29nLm1hdGguTG9uZy5aRVJPPWdvb2cubWF0aC5Mb25nLmZyb21JbnQoMCksZ29vZy5tYXRoLkxvbmcuT05FPWdvb2cubWF0aC5Mb25nLmZyb21JbnQoMSksZ29vZy5tYXRoLkxvbmcuTkVHX09ORT1nb29nLm1hdGguTG9uZy5mcm9tSW50KC0xKSxnb29nLm1hdGguTG9uZy5NQVhfVkFMVUU9Z29vZy5tYXRoLkxvbmcuZnJvbUJpdHMoLTEsMjE0NzQ4MzY0NyksZ29vZy5tYXRoLkxvbmcuTUlOX1ZBTFVFPWdvb2cubWF0aC5Mb25nLmZyb21CaXRzKDAsLTIxNDc0ODM2NDgpLGdvb2cubWF0aC5Mb25nLlRXT19QV1JfMjRfPWdvb2cubWF0aC5Mb25nLmZyb21JbnQoMTw8MjQpLGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS50b0ludD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxvd199LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS50b051bWJlcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmhpZ2hfKmdvb2cubWF0aC5Mb25nLlRXT19QV1JfMzJfREJMXyt0aGlzLmdldExvd0JpdHNVbnNpZ25lZCgpfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oYSl7dmFyIGI9YXx8MTA7aWYoMj5ifHxiPjM2KXRocm93IEVycm9yKFwicmFkaXggb3V0IG9mIHJhbmdlOiBcIitiKTtpZih0aGlzLmlzWmVybygpKXJldHVyblwiMFwiO2lmKHRoaXMuaXNOZWdhdGl2ZSgpKXtpZih0aGlzLmVxdWFscyhnb29nLm1hdGguTG9uZy5NSU5fVkFMVUUpKXt2YXIgYz1nb29nLm1hdGguTG9uZy5mcm9tTnVtYmVyKGIpLGQ9dGhpcy5kaXYoYyksZT1kLm11bHRpcGx5KGMpLnN1YnRyYWN0KHRoaXMpO3JldHVybiBkLnRvU3RyaW5nKGIpK2UudG9JbnQoKS50b1N0cmluZyhiKX1yZXR1cm5cIi1cIit0aGlzLm5lZ2F0ZSgpLnRvU3RyaW5nKGIpfWZvcih2YXIgZj1nb29nLm1hdGguTG9uZy5mcm9tTnVtYmVyKE1hdGgucG93KGIsNikpLGU9dGhpcyxnPVwiXCI7Oyl7dmFyIGg9ZS5kaXYoZiksaT1lLnN1YnRyYWN0KGgubXVsdGlwbHkoZikpLnRvSW50KCksaj1pLnRvU3RyaW5nKGIpO2lmKGU9aCxlLmlzWmVybygpKXJldHVybiBqK2c7Zm9yKDtqLmxlbmd0aDw2OylqPVwiMFwiK2o7Zz1cIlwiK2orZ319LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5nZXRIaWdoQml0cz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmhpZ2hffSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUuZ2V0TG93Qml0cz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxvd199LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5nZXRMb3dCaXRzVW5zaWduZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5sb3dfPj0wP3RoaXMubG93Xzpnb29nLm1hdGguTG9uZy5UV09fUFdSXzMyX0RCTF8rdGhpcy5sb3dffSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUuZ2V0TnVtQml0c0Ficz1mdW5jdGlvbigpe2lmKHRoaXMuaXNOZWdhdGl2ZSgpKXJldHVybiB0aGlzLmVxdWFscyhnb29nLm1hdGguTG9uZy5NSU5fVkFMVUUpPzY0OnRoaXMubmVnYXRlKCkuZ2V0TnVtQml0c0FicygpO2Zvcih2YXIgYT0wIT10aGlzLmhpZ2hfP3RoaXMuaGlnaF86dGhpcy5sb3dfLGI9MzE7Yj4wJiYwPT0oYSYxPDxiKTtiLS0pO3JldHVybiAwIT10aGlzLmhpZ2hfP2IrMzM6YisxfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUuaXNaZXJvPWZ1bmN0aW9uKCl7cmV0dXJuIDA9PXRoaXMuaGlnaF8mJjA9PXRoaXMubG93X30sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLmlzTmVnYXRpdmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5oaWdoXzwwfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUuaXNPZGQ9ZnVuY3Rpb24oKXtyZXR1cm4gMT09KDEmdGhpcy5sb3dfKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLmVxdWFscz1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5oaWdoXz09YS5oaWdoXyYmdGhpcy5sb3dfPT1hLmxvd199LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5ub3RFcXVhbHM9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuaGlnaF8hPWEuaGlnaF98fHRoaXMubG93XyE9YS5sb3dffSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUubGVzc1RoYW49ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuY29tcGFyZShhKTwwfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUubGVzc1RoYW5PckVxdWFsPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmNvbXBhcmUoYSk8PTB9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5ncmVhdGVyVGhhbj1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5jb21wYXJlKGEpPjB9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5ncmVhdGVyVGhhbk9yRXF1YWw9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuY29tcGFyZShhKT49MH0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLmNvbXBhcmU9ZnVuY3Rpb24oYSl7aWYodGhpcy5lcXVhbHMoYSkpcmV0dXJuIDA7dmFyIGI9dGhpcy5pc05lZ2F0aXZlKCksYz1hLmlzTmVnYXRpdmUoKTtyZXR1cm4gYiYmIWM/LTE6IWImJmM/MTp0aGlzLnN1YnRyYWN0KGEpLmlzTmVnYXRpdmUoKT8tMToxfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUubmVnYXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZXF1YWxzKGdvb2cubWF0aC5Mb25nLk1JTl9WQUxVRSk/Z29vZy5tYXRoLkxvbmcuTUlOX1ZBTFVFOnRoaXMubm90KCkuYWRkKGdvb2cubWF0aC5Mb25nLk9ORSl9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5hZGQ9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5oaWdoXz4+PjE2LGM9NjU1MzUmdGhpcy5oaWdoXyxkPXRoaXMubG93Xz4+PjE2LGU9NjU1MzUmdGhpcy5sb3dfLGY9YS5oaWdoXz4+PjE2LGc9NjU1MzUmYS5oaWdoXyxoPWEubG93Xz4+PjE2LGk9NjU1MzUmYS5sb3dfLGo9MCxrPTAsbD0wLG09MDtyZXR1cm4gbSs9ZStpLGwrPW0+Pj4xNixtJj02NTUzNSxsKz1kK2gsays9bD4+PjE2LGwmPTY1NTM1LGsrPWMrZyxqKz1rPj4+MTYsayY9NjU1MzUsais9YitmLGomPTY1NTM1LGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKGw8PDE2fG0sajw8MTZ8ayl9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5zdWJ0cmFjdD1mdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hZGQoYS5uZWdhdGUoKSl9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5tdWx0aXBseT1mdW5jdGlvbihhKXtpZih0aGlzLmlzWmVybygpKXJldHVybiBnb29nLm1hdGguTG9uZy5aRVJPO2lmKGEuaXNaZXJvKCkpcmV0dXJuIGdvb2cubWF0aC5Mb25nLlpFUk87aWYodGhpcy5lcXVhbHMoZ29vZy5tYXRoLkxvbmcuTUlOX1ZBTFVFKSlyZXR1cm4gYS5pc09kZCgpP2dvb2cubWF0aC5Mb25nLk1JTl9WQUxVRTpnb29nLm1hdGguTG9uZy5aRVJPO2lmKGEuZXF1YWxzKGdvb2cubWF0aC5Mb25nLk1JTl9WQUxVRSkpcmV0dXJuIHRoaXMuaXNPZGQoKT9nb29nLm1hdGguTG9uZy5NSU5fVkFMVUU6Z29vZy5tYXRoLkxvbmcuWkVSTztpZih0aGlzLmlzTmVnYXRpdmUoKSlyZXR1cm4gYS5pc05lZ2F0aXZlKCk/dGhpcy5uZWdhdGUoKS5tdWx0aXBseShhLm5lZ2F0ZSgpKTp0aGlzLm5lZ2F0ZSgpLm11bHRpcGx5KGEpLm5lZ2F0ZSgpO2lmKGEuaXNOZWdhdGl2ZSgpKXJldHVybiB0aGlzLm11bHRpcGx5KGEubmVnYXRlKCkpLm5lZ2F0ZSgpO2lmKHRoaXMubGVzc1RoYW4oZ29vZy5tYXRoLkxvbmcuVFdPX1BXUl8yNF8pJiZhLmxlc3NUaGFuKGdvb2cubWF0aC5Mb25nLlRXT19QV1JfMjRfKSlyZXR1cm4gZ29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcih0aGlzLnRvTnVtYmVyKCkqYS50b051bWJlcigpKTt2YXIgYj10aGlzLmhpZ2hfPj4+MTYsYz02NTUzNSZ0aGlzLmhpZ2hfLGQ9dGhpcy5sb3dfPj4+MTYsZT02NTUzNSZ0aGlzLmxvd18sZj1hLmhpZ2hfPj4+MTYsZz02NTUzNSZhLmhpZ2hfLGg9YS5sb3dfPj4+MTYsaT02NTUzNSZhLmxvd18saj0wLGs9MCxsPTAsbT0wO3JldHVybiBtKz1lKmksbCs9bT4+PjE2LG0mPTY1NTM1LGwrPWQqaSxrKz1sPj4+MTYsbCY9NjU1MzUsbCs9ZSpoLGsrPWw+Pj4xNixsJj02NTUzNSxrKz1jKmksais9az4+PjE2LGsmPTY1NTM1LGsrPWQqaCxqKz1rPj4+MTYsayY9NjU1MzUsays9ZSpnLGorPWs+Pj4xNixrJj02NTUzNSxqKz1iKmkrYypoK2QqZytlKmYsaiY9NjU1MzUsZ29vZy5tYXRoLkxvbmcuZnJvbUJpdHMobDw8MTZ8bSxqPDwxNnxrKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLmRpdj1mdW5jdGlvbihhKXtpZihhLmlzWmVybygpKXRocm93IEVycm9yKFwiZGl2aXNpb24gYnkgemVyb1wiKTtpZih0aGlzLmlzWmVybygpKXJldHVybiBnb29nLm1hdGguTG9uZy5aRVJPO2lmKHRoaXMuZXF1YWxzKGdvb2cubWF0aC5Mb25nLk1JTl9WQUxVRSkpe2lmKGEuZXF1YWxzKGdvb2cubWF0aC5Mb25nLk9ORSl8fGEuZXF1YWxzKGdvb2cubWF0aC5Mb25nLk5FR19PTkUpKXJldHVybiBnb29nLm1hdGguTG9uZy5NSU5fVkFMVUU7aWYoYS5lcXVhbHMoZ29vZy5tYXRoLkxvbmcuTUlOX1ZBTFVFKSlyZXR1cm4gZ29vZy5tYXRoLkxvbmcuT05FO3ZhciBiPXRoaXMuc2hpZnRSaWdodCgxKSxjPWIuZGl2KGEpLnNoaWZ0TGVmdCgxKTtpZihjLmVxdWFscyhnb29nLm1hdGguTG9uZy5aRVJPKSlyZXR1cm4gYS5pc05lZ2F0aXZlKCk/Z29vZy5tYXRoLkxvbmcuT05FOmdvb2cubWF0aC5Mb25nLk5FR19PTkU7dmFyIGQ9dGhpcy5zdWJ0cmFjdChhLm11bHRpcGx5KGMpKSxlPWMuYWRkKGQuZGl2KGEpKTtyZXR1cm4gZX1pZihhLmVxdWFscyhnb29nLm1hdGguTG9uZy5NSU5fVkFMVUUpKXJldHVybiBnb29nLm1hdGguTG9uZy5aRVJPO2lmKHRoaXMuaXNOZWdhdGl2ZSgpKXJldHVybiBhLmlzTmVnYXRpdmUoKT90aGlzLm5lZ2F0ZSgpLmRpdihhLm5lZ2F0ZSgpKTp0aGlzLm5lZ2F0ZSgpLmRpdihhKS5uZWdhdGUoKTtpZihhLmlzTmVnYXRpdmUoKSlyZXR1cm4gdGhpcy5kaXYoYS5uZWdhdGUoKSkubmVnYXRlKCk7Zm9yKHZhciBmPWdvb2cubWF0aC5Mb25nLlpFUk8sZD10aGlzO2QuZ3JlYXRlclRoYW5PckVxdWFsKGEpOyl7Zm9yKHZhciBjPU1hdGgubWF4KDEsTWF0aC5mbG9vcihkLnRvTnVtYmVyKCkvYS50b051bWJlcigpKSksZz1NYXRoLmNlaWwoTWF0aC5sb2coYykvTWF0aC5MTjIpLGg9NDg+PWc/MTpNYXRoLnBvdygyLGctNDgpLGk9Z29vZy5tYXRoLkxvbmcuZnJvbU51bWJlcihjKSxqPWkubXVsdGlwbHkoYSk7ai5pc05lZ2F0aXZlKCl8fGouZ3JlYXRlclRoYW4oZCk7KWMtPWgsaT1nb29nLm1hdGguTG9uZy5mcm9tTnVtYmVyKGMpLGo9aS5tdWx0aXBseShhKTtpLmlzWmVybygpJiYoaT1nb29nLm1hdGguTG9uZy5PTkUpLGY9Zi5hZGQoaSksZD1kLnN1YnRyYWN0KGopfXJldHVybiBmfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUubW9kdWxvPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnN1YnRyYWN0KHRoaXMuZGl2KGEpLm11bHRpcGx5KGEpKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLm5vdD1mdW5jdGlvbigpe3JldHVybiBnb29nLm1hdGguTG9uZy5mcm9tQml0cyh+dGhpcy5sb3dfLH50aGlzLmhpZ2hfKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLmFuZD1mdW5jdGlvbihhKXtyZXR1cm4gZ29vZy5tYXRoLkxvbmcuZnJvbUJpdHModGhpcy5sb3dfJmEubG93Xyx0aGlzLmhpZ2hfJmEuaGlnaF8pfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUub3I9ZnVuY3Rpb24oYSl7cmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKHRoaXMubG93X3xhLmxvd18sdGhpcy5oaWdoX3xhLmhpZ2hfKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLnhvcj1mdW5jdGlvbihhKXtyZXR1cm4gZ29vZy5tYXRoLkxvbmcuZnJvbUJpdHModGhpcy5sb3dfXmEubG93Xyx0aGlzLmhpZ2hfXmEuaGlnaF8pfSxnb29nLm1hdGguTG9uZy5wcm90b3R5cGUuc2hpZnRMZWZ0PWZ1bmN0aW9uKGEpe2lmKGEmPTYzLDA9PWEpcmV0dXJuIHRoaXM7dmFyIGI9dGhpcy5sb3dfO2lmKDMyPmEpe3ZhciBjPXRoaXMuaGlnaF87cmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKGI8PGEsYzw8YXxiPj4+MzItYSl9cmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKDAsYjw8YS0zMil9LGdvb2cubWF0aC5Mb25nLnByb3RvdHlwZS5zaGlmdFJpZ2h0PWZ1bmN0aW9uKGEpe2lmKGEmPTYzLDA9PWEpcmV0dXJuIHRoaXM7dmFyIGI9dGhpcy5oaWdoXztpZigzMj5hKXt2YXIgYz10aGlzLmxvd187cmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKGM+Pj5hfGI8PDMyLWEsYj4+YSl9cmV0dXJuIGdvb2cubWF0aC5Mb25nLmZyb21CaXRzKGI+PmEtMzIsYj49MD8wOi0xKX0sZ29vZy5tYXRoLkxvbmcucHJvdG90eXBlLnNoaWZ0UmlnaHRVbnNpZ25lZD1mdW5jdGlvbihhKXtpZihhJj02MywwPT1hKXJldHVybiB0aGlzO3ZhciBiPXRoaXMuaGlnaF87aWYoMzI+YSl7dmFyIGM9dGhpcy5sb3dfO3JldHVybiBnb29nLm1hdGguTG9uZy5mcm9tQml0cyhjPj4+YXxiPDwzMi1hLGI+Pj5hKX1yZXR1cm4gMzI9PWE/Z29vZy5tYXRoLkxvbmcuZnJvbUJpdHMoYiwwKTpnb29nLm1hdGguTG9uZy5mcm9tQml0cyhiPj4+YS0zMiwwKX07dmFyIFVURjg9e307VVRGOC5lbmNvZGU9ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPVtdLGM9MDtjPGEubGVuZ3RoOysrYyl7dmFyIGQ9YS5jaGFyQ29kZUF0KGMpOzEyOD5kP2IucHVzaChkKToyMDQ4PmQ/KGIucHVzaCgxOTJ8ZD4+NiksYi5wdXNoKDEyOHw2MyZkKSk6NjU1MzY+ZD8oYi5wdXNoKDIyNHxkPj4xMiksYi5wdXNoKDEyOHw2MyZkPj42KSxiLnB1c2goMTI4fDYzJmQpKTooYi5wdXNoKDI0MHxkPj4xOCksYi5wdXNoKDEyOHw2MyZkPj4xMiksYi5wdXNoKDEyOHw2MyZkPj42KSxiLnB1c2goMTI4fDYzJmQpKX1yZXR1cm4gYn0sVVRGOC5kZWNvZGU9ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPVtdLGM9MDtjPGEubGVuZ3RoOyl7dmFyIGQ9YVtjKytdOzEyOD5kfHwoMjI0PmQ/KGQ9KDMxJmQpPDw2LGR8PTYzJmFbYysrXSk6MjQwPmQ/KGQ9KDE1JmQpPDwxMixkfD0oNjMmYVtjKytdKTw8NixkfD02MyZhW2MrK10pOihkPSg3JmQpPDwxOCxkfD0oNjMmYVtjKytdKTw8MTIsZHw9KDYzJmFbYysrXSk8PDYsZHw9NjMmYVtjKytdKSksYi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoZCkpfXJldHVybiBiLmpvaW4oXCJcIil9O3ZhciBCQVNFNjQ9e307aWYoZnVuY3Rpb24oYil7dmFyIGM9ZnVuY3Rpb24oYSl7Zm9yKHZhciBjPTAsZD1bXSxlPTB8YS5sZW5ndGgvMzswPGUtLTspe3ZhciBmPShhW2NdPDwxNikrKGFbYysxXTw8OCkrYVtjKzJdO2MrPTMsZC5wdXNoKGIuY2hhckF0KDYzJmY+PjE4KSksZC5wdXNoKGIuY2hhckF0KDYzJmY+PjEyKSksZC5wdXNoKGIuY2hhckF0KDYzJmY+PjYpKSxkLnB1c2goYi5jaGFyQXQoNjMmZikpfWlmKDI9PWEubGVuZ3RoLWMpe3ZhciBmPShhW2NdPDwxNikrKGFbYysxXTw8OCk7ZC5wdXNoKGIuY2hhckF0KDYzJmY+PjE4KSksZC5wdXNoKGIuY2hhckF0KDYzJmY+PjEyKSksZC5wdXNoKGIuY2hhckF0KDYzJmY+PjYpKSxkLnB1c2goXCI9XCIpfWVsc2UgaWYoMT09YS5sZW5ndGgtYyl7dmFyIGY9YVtjXTw8MTY7ZC5wdXNoKGIuY2hhckF0KDYzJmY+PjE4KSksZC5wdXNoKGIuY2hhckF0KDYzJmY+PjEyKSksZC5wdXNoKFwiPT1cIil9cmV0dXJuIGQuam9pbihcIlwiKX0sZD1mdW5jdGlvbigpe2Zvcih2YXIgYT1bXSxjPTA7YzxiLmxlbmd0aDsrK2MpYVtiLmNoYXJDb2RlQXQoYyldPWM7cmV0dXJuIGFbXCI9XCIuY2hhckNvZGVBdCgwKV09MCxhfSgpLGU9ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPTAsYz1bXSxlPTB8YS5sZW5ndGgvNDswPGUtLTspe3ZhciBmPShkW2EuY2hhckNvZGVBdChiKV08PDE4KSsoZFthLmNoYXJDb2RlQXQoYisxKV08PDEyKSsoZFthLmNoYXJDb2RlQXQoYisyKV08PDYpK2RbYS5jaGFyQ29kZUF0KGIrMyldO2MucHVzaCgyNTUmZj4+MTYpLGMucHVzaCgyNTUmZj4+OCksYy5wdXNoKDI1NSZmKSxiKz00fXJldHVybiBjJiYoXCI9XCI9PWEuY2hhckF0KGItMik/KGMucG9wKCksYy5wb3AoKSk6XCI9XCI9PWEuY2hhckF0KGItMSkmJmMucG9wKCkpLGN9LGY9e307Zi5lbmNvZGU9ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPVtdLGM9MDtjPGEubGVuZ3RoOysrYyliLnB1c2goYS5jaGFyQ29kZUF0KGMpKTtyZXR1cm4gYn0sZi5kZWNvZGU9ZnVuY3Rpb24oKXtmb3IodmFyIGI9MDtiPHMubGVuZ3RoOysrYilhW2JdPVN0cmluZy5mcm9tQ2hhckNvZGUoYVtiXSk7cmV0dXJuIGEuam9pbihcIlwiKX0sQkFTRTY0LmRlY29kZUFycmF5PWZ1bmN0aW9uKGEpe3ZhciBiPWUoYSk7cmV0dXJuIG5ldyBVaW50OEFycmF5KGIpfSxCQVNFNjQuZW5jb2RlQVNDSUk9ZnVuY3Rpb24oYSl7dmFyIGI9Zi5lbmNvZGUoYSk7cmV0dXJuIGMoYil9LEJBU0U2NC5kZWNvZGVBU0NJST1mdW5jdGlvbihhKXt2YXIgYj1lKGEpO3JldHVybiBmLmRlY29kZShiKX0sQkFTRTY0LmVuY29kZT1mdW5jdGlvbihhKXt2YXIgYj1VVEY4LmVuY29kZShhKTtyZXR1cm4gYyhiKX0sQkFTRTY0LmRlY29kZT1mdW5jdGlvbihhKXt2YXIgYj1lKGEpO3JldHVybiBVVEY4LmRlY29kZShiKX19KFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL1wiKSx2b2lkIDA9PT1idG9hKXZhciBidG9hPUJBU0U2NC5lbmNvZGU7aWYodm9pZCAwPT09YXRvYil2YXIgYXRvYj1CQVNFNjQuZGVjb2RlO01lZGlhUGxheWVyPWZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3ZhciBiLGMsZCxlLGYsZz1cIjEuMC4wXCIsaD1hLGk9ITEsaj0hMSxrPSEwLGw9ITEsbT1NZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5CVUZGRVJfU0laRV9SRVFVSVJFRCxuPWZ1bmN0aW9uKCl7cmV0dXJuISFjJiYhIWR9LG89ZnVuY3Rpb24oKXtpZighaSl0aHJvd1wiTWVkaWFQbGF5ZXIgbm90IGluaXRpYWxpemVkIVwiO2lmKCF0aGlzLmNhcGFiaWxpdGllcy5zdXBwb3J0c01lZGlhU291cmNlKCkpcmV0dXJuIHRoaXMuZXJySGFuZGxlci5jYXBhYmlsaXR5RXJyb3IoXCJtZWRpYXNvdXJjZVwiKSx2b2lkIDA7aWYoIWN8fCFkKXRocm93XCJNaXNzaW5nIHZpZXcgb3Igc291cmNlLlwiO2o9ITAsdGhpcy5kZWJ1Zy5sb2coXCJQbGF5YmFjayBpbml0aWF0ZWQhXCIpLGU9Yi5nZXRPYmplY3QoXCJzdHJlYW1Db250cm9sbGVyXCIpLGUuc2V0VmlkZW9Nb2RlbChmKSxlLnNldEF1dG9QbGF5KGspLGUubG9hZChkKSxiLm1hcFZhbHVlKFwic2NoZWR1bGVXaGlsZVBhdXNlZFwiLGwpLGIubWFwT3V0bGV0KFwic2NoZWR1bGVXaGlsZVBhdXNlZFwiLFwic3RyZWFtXCIpLGIubWFwVmFsdWUoXCJidWZmZXJNYXhcIixtKSxiLmluamVjdEludG8odGhpcy5idWZmZXJFeHQsXCJidWZmZXJNYXhcIil9LHA9ZnVuY3Rpb24oKXtuKCkmJm8uY2FsbCh0aGlzKX07cmV0dXJuIGI9bmV3IGRpam9uLlN5c3RlbSxiLm1hcFZhbHVlKFwic3lzdGVtXCIsYiksYi5tYXBPdXRsZXQoXCJzeXN0ZW1cIiksYi5pbmplY3RJbnRvKGgpLHtkZWJ1Zzp2b2lkIDAsZXZlbnRCdXM6dm9pZCAwLGNhcGFiaWxpdGllczp2b2lkIDAsYWJyQ29udHJvbGxlcjp2b2lkIDAsbWV0cmljc01vZGVsOnZvaWQgMCxtZXRyaWNzRXh0OnZvaWQgMCxidWZmZXJFeHQ6dm9pZCAwLGFkZEV2ZW50TGlzdGVuZXI6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuZXZlbnRCdXMuYWRkRXZlbnRMaXN0ZW5lcihhLGIsYyl9LHJlbW92ZUV2ZW50TGlzdGVuZXI6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuZXZlbnRCdXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihhLGIsYyl9LGdldFZlcnNpb246ZnVuY3Rpb24oKXtyZXR1cm4gZ30sc3RhcnR1cDpmdW5jdGlvbigpe2l8fChiLmluamVjdEludG8odGhpcyksaT0hMCl9LGdldERlYnVnOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGVidWd9LGdldFZpZGVvTW9kZWw6ZnVuY3Rpb24oKXtyZXR1cm4gZn0sc2V0QXV0b1BsYXk6ZnVuY3Rpb24oYSl7az1hfSxnZXRBdXRvUGxheTpmdW5jdGlvbigpe3JldHVybiBrfSxzZXRTY2hlZHVsZVdoaWxlUGF1c2VkOmZ1bmN0aW9uKGEpe2w9YX0sZ2V0U2NoZWR1bGVXaGlsZVBhdXNlZDpmdW5jdGlvbigpe3JldHVybiBsfSxzZXRCdWZmZXJNYXg6ZnVuY3Rpb24oYSl7bT1hfSxnZXRCdWZmZXJNYXg6ZnVuY3Rpb24oKXtyZXR1cm4gbX0sZ2V0TWV0cmljc0V4dDpmdW5jdGlvbigpe3JldHVybiB0aGlzLm1ldHJpY3NFeHR9LGdldE1ldHJpY3NGb3I6ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5tZXRyaWNzTW9kZWwuZ2V0UmVhZE9ubHlNZXRyaWNzRm9yKGEpO3JldHVybiBifSxnZXRRdWFsaXR5Rm9yOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmFickNvbnRyb2xsZXIuZ2V0UXVhbGl0eUZvcihhKX0sc2V0UXVhbGl0eUZvcjpmdW5jdGlvbihhLGIpe3RoaXMuYWJyQ29udHJvbGxlci5zZXRQbGF5YmFja1F1YWxpdHkoYSxiKX0sZ2V0QXV0b1N3aXRjaFF1YWxpdHk6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hYnJDb250cm9sbGVyLmdldEF1dG9Td2l0Y2hCaXRyYXRlKCl9LHNldEF1dG9Td2l0Y2hRdWFsaXR5OmZ1bmN0aW9uKGEpe3RoaXMuYWJyQ29udHJvbGxlci5zZXRBdXRvU3dpdGNoQml0cmF0ZShhKX0sYXR0YWNoVmlldzpmdW5jdGlvbihhKXtpZighaSl0aHJvd1wiTWVkaWFQbGF5ZXIgbm90IGluaXRpYWxpemVkIVwiO2M9YSxmPW51bGwsYyYmKGY9Yi5nZXRPYmplY3QoXCJ2aWRlb01vZGVsXCIpLGYuc2V0RWxlbWVudChjKSksaiYmZSYmKGUucmVzZXQoKSxlPW51bGwsaj0hMSksbi5jYWxsKHRoaXMpJiZwLmNhbGwodGhpcyl9LGF0dGFjaFNvdXJjZTpmdW5jdGlvbihhKXtpZighaSl0aHJvd1wiTWVkaWFQbGF5ZXIgbm90IGluaXRpYWxpemVkIVwiO2Q9YSx0aGlzLnNldFF1YWxpdHlGb3IoXCJ2aWRlb1wiLDApLHRoaXMuc2V0UXVhbGl0eUZvcihcImF1ZGlvXCIsMCksaiYmZSYmKGUucmVzZXQoKSxlPW51bGwsaj0hMSksbi5jYWxsKHRoaXMpJiZwLmNhbGwodGhpcyl9LHJlc2V0OmZ1bmN0aW9uKCl7dGhpcy5hdHRhY2hTb3VyY2UobnVsbCksdGhpcy5hdHRhY2hWaWV3KG51bGwpfSxwbGF5Om8saXNSZWFkeTpufX0sTWVkaWFQbGF5ZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllcn0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzPXt9LE1lZGlhUGxheWVyLnV0aWxzPXt9LE1lZGlhUGxheWVyLm1vZGVscz17fSxNZWRpYVBsYXllci52bz17fSxNZWRpYVBsYXllci52by5tZXRyaWNzPXt9LE1lZGlhUGxheWVyLnJ1bGVzPXt9LE1lZGlhUGxheWVyLmRpPXt9LE1lZGlhUGxheWVyLmRpLkNvbnRleHQ9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjtyZXR1cm57c3lzdGVtOnZvaWQgMCxzZXR1cDpmdW5jdGlvbigpe3RoaXMuc3lzdGVtLmF1dG9NYXBPdXRsZXRzPSEwLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcImRlYnVnXCIsTWVkaWFQbGF5ZXIudXRpbHMuRGVidWcpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcImV2ZW50QnVzXCIsTWVkaWFQbGF5ZXIudXRpbHMuRXZlbnRCdXMpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcImNhcGFiaWxpdGllc1wiLE1lZGlhUGxheWVyLnV0aWxzLkNhcGFiaWxpdGllcyksdGhpcy5zeXN0ZW0ubWFwU2luZ2xldG9uKFwidGV4dFRyYWNrRXh0ZW5zaW9uc1wiLE1lZGlhUGxheWVyLnV0aWxzLlRleHRUcmFja0V4dGVuc2lvbnMpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcInZ0dFBhcnNlclwiLE1lZGlhUGxheWVyLnV0aWxzLlZUVFBhcnNlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJ2aWRlb01vZGVsXCIsTWVkaWFQbGF5ZXIubW9kZWxzLlZpZGVvTW9kZWwpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcIm1hbmlmZXN0TW9kZWxcIixNZWRpYVBsYXllci5tb2RlbHMuTWFuaWZlc3RNb2RlbCksdGhpcy5zeXN0ZW0ubWFwU2luZ2xldG9uKFwibWV0cmljc01vZGVsXCIsTWVkaWFQbGF5ZXIubW9kZWxzLk1ldHJpY3NNb2RlbCksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJwcm90ZWN0aW9uTW9kZWxcIixNZWRpYVBsYXllci5tb2RlbHMuUHJvdGVjdGlvbk1vZGVsKSx0aGlzLnN5c3RlbS5tYXBTaW5nbGV0b24oXCJ0ZXh0VlRUU291cmNlQnVmZmVyXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlRleHRWVFRTb3VyY2VCdWZmZXIpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcIm1lZGlhU291cmNlRXh0XCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1lZGlhU291cmNlRXh0ZW5zaW9ucyksdGhpcy5zeXN0ZW0ubWFwU2luZ2xldG9uKFwic291cmNlQnVmZmVyRXh0XCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNvdXJjZUJ1ZmZlckV4dGVuc2lvbnMpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcImJ1ZmZlckV4dFwiLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zKSx0aGlzLnN5c3RlbS5tYXBTaW5nbGV0b24oXCJhYnJDb250cm9sbGVyXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkFickNvbnRyb2xsZXIpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcImVyckhhbmRsZXJcIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRXJyb3JIYW5kbGVyKSx0aGlzLnN5c3RlbS5tYXBTaW5nbGV0b24oXCJwcm90ZWN0aW9uRXh0XCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25FeHRlbnNpb25zKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcInByb3RlY3Rpb25Db250cm9sbGVyXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25Db250cm9sbGVyKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcIm1ldHJpY3NcIixNZWRpYVBsYXllci5tb2RlbHMuTWV0cmljc0xpc3QpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwiZG93bmxvYWRSYXRpb1J1bGVcIixNZWRpYVBsYXllci5ydWxlcy5Eb3dubG9hZFJhdGlvUnVsZSksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJpbnN1ZmZpY2llbnRCdWZmZXJSdWxlXCIsTWVkaWFQbGF5ZXIucnVsZXMuSW5zdWZmaWNpZW50QnVmZmVyUnVsZSksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJsaW1pdFN3aXRjaGVzUnVsZVwiLE1lZGlhUGxheWVyLnJ1bGVzLkxpbWl0U3dpdGNoZXNSdWxlKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcImFiclJ1bGVzQ29sbGVjdGlvblwiLE1lZGlhUGxheWVyLnJ1bGVzLkJhc2VSdWxlc0NvbGxlY3Rpb24pLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwidGV4dENvbnRyb2xsZXJcIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuVGV4dENvbnRyb2xsZXIpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwiYnVmZmVyQ29udHJvbGxlclwiLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJDb250cm9sbGVyKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcIm1hbmlmZXN0TG9hZGVyXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0TG9hZGVyKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcIm1hbmlmZXN0VXBkYXRlclwiLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5NYW5pZmVzdFVwZGF0ZXIpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwiZnJhZ21lbnRDb250cm9sbGVyXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkZyYWdtZW50Q29udHJvbGxlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJmcmFnbWVudExvYWRlclwiLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5GcmFnbWVudExvYWRlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJmcmFnbWVudE1vZGVsXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkZyYWdtZW50TW9kZWwpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcInN0cmVhbUNvbnRyb2xsZXJcIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU3RyZWFtQ29udHJvbGxlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJzdHJlYW1cIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU3RyZWFtKSx0aGlzLnN5c3RlbS5tYXBDbGFzcyhcInJlcXVlc3RTY2hlZHVsZXJcIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuUmVxdWVzdFNjaGVkdWxlciksdGhpcy5zeXN0ZW0ubWFwU2luZ2xldG9uKFwic2NoZWR1bGVyRXh0XCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNjaGVkdWxlckV4dGVuc2lvbnMpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwic2NoZWR1bGVyTW9kZWxcIixNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU2NoZWR1bGVyTW9kZWwpXHJcbn19fSxEYXNoPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJue21vZHVsZXM6e30sZGVwZW5kZW5jaWVzOnt9LHZvOnt9LGRpOnt9fX0oKSxEYXNoLmRpLkRhc2hDb250ZXh0PWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJue3N5c3RlbTp2b2lkIDAsc2V0dXA6ZnVuY3Rpb24oKXtEYXNoLmRpLkRhc2hDb250ZXh0LnByb3RvdHlwZS5zZXR1cC5jYWxsKHRoaXMpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwicGFyc2VyXCIsRGFzaC5kZXBlbmRlbmNpZXMuRGFzaFBhcnNlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJpbmRleEhhbmRsZXJcIixEYXNoLmRlcGVuZGVuY2llcy5EYXNoSGFuZGxlciksdGhpcy5zeXN0ZW0ubWFwQ2xhc3MoXCJiYXNlVVJMRXh0XCIsRGFzaC5kZXBlbmRlbmNpZXMuQmFzZVVSTEV4dGVuc2lvbnMpLHRoaXMuc3lzdGVtLm1hcENsYXNzKFwiZnJhZ21lbnRFeHRcIixEYXNoLmRlcGVuZGVuY2llcy5GcmFnbWVudEV4dGVuc2lvbnMpLHRoaXMuc3lzdGVtLm1hcFNpbmdsZXRvbihcIm1hbmlmZXN0RXh0XCIsRGFzaC5kZXBlbmRlbmNpZXMuRGFzaE1hbmlmZXN0RXh0ZW5zaW9ucyksdGhpcy5zeXN0ZW0ubWFwU2luZ2xldG9uKFwibWV0cmljc0V4dFwiLERhc2guZGVwZW5kZW5jaWVzLkRhc2hNZXRyaWNzRXh0ZW5zaW9ucyl9fX0sRGFzaC5kaS5EYXNoQ29udGV4dC5wcm90b3R5cGU9bmV3IE1lZGlhUGxheWVyLmRpLkNvbnRleHQsRGFzaC5kaS5EYXNoQ29udGV4dC5wcm90b3R5cGUuY29uc3RydWN0b3I9RGFzaC5kaS5EYXNoQ29udGV4dCxEYXNoLmRlcGVuZGVuY2llcy5CYXNlVVJMRXh0ZW5zaW9ucz1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPWZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjLGQsZSxmLGcsaCxpLGosayxsLG09bmV3IERhdGFWaWV3KGEpLG49e30sbz0wO1wic2lkeFwiIT09aiYmbzxtLmJ5dGVMZW5ndGg7KXtmb3Ioaz1tLmdldFVpbnQzMihvKSxvKz00LGo9XCJcIixmPTA7ND5mO2YrPTEpbD1tLmdldEludDgobyksais9U3RyaW5nLmZyb21DaGFyQ29kZShsKSxvKz0xO1wibW9vZlwiIT09aiYmXCJ0cmFmXCIhPT1qJiZcInNpZHhcIiE9PWo/bys9ay04Olwic2lkeFwiPT09aiYmKG8tPTgpfWlmKGU9bS5nZXRVaW50MzIobywhMSkrbyxlPmEuYnl0ZUxlbmd0aCl0aHJvd1wic2lkeCB0ZXJtaW5hdGVzIGFmdGVyIGFycmF5IGJ1ZmZlclwiO2ZvcihuLnZlcnNpb249bS5nZXRVaW50OChvKzgpLG8rPTEyLG4udGltZXNjYWxlPW0uZ2V0VWludDMyKG8rNCwhMSksbys9OCwwPT09bi52ZXJzaW9uPyhuLmVhcmxpZXN0X3ByZXNlbnRhdGlvbl90aW1lPW0uZ2V0VWludDMyKG8sITEpLG4uZmlyc3Rfb2Zmc2V0PW0uZ2V0VWludDMyKG8rNCwhMSksbys9OCk6KG4uZWFybGllc3RfcHJlc2VudGF0aW9uX3RpbWU9dXRpbHMuTWF0aC50bzY0Qml0TnVtYmVyKG0uZ2V0VWludDMyKG8rNCwhMSksbS5nZXRVaW50MzIobywhMSkpLG4uZmlyc3Rfb2Zmc2V0PShtLmdldFVpbnQzMihvKzgsITEpPDwzMikrbS5nZXRVaW50MzIobysxMiwhMSksbys9MTYpLG4uZmlyc3Rfb2Zmc2V0Kz1lKyhifHwwKSxuLnJlZmVyZW5jZV9jb3VudD1tLmdldFVpbnQxNihvKzIsITEpLG8rPTQsbi5yZWZlcmVuY2VzPVtdLGM9bi5maXJzdF9vZmZzZXQsZD1uLmVhcmxpZXN0X3ByZXNlbnRhdGlvbl90aW1lLGY9MDtmPG4ucmVmZXJlbmNlX2NvdW50O2YrPTEpaD1tLmdldFVpbnQzMihvLCExKSxnPWg+Pj4zMSxoPTIxNDc0ODM2NDcmaCxpPW0uZ2V0VWludDMyKG8rNCwhMSksbys9MTIsbi5yZWZlcmVuY2VzLnB1c2goe3NpemU6aCx0eXBlOmcsb2Zmc2V0OmMsZHVyYXRpb246aSx0aW1lOmQsdGltZXNjYWxlOm4udGltZXNjYWxlfSksYys9aCxkKz1pO2lmKG8hPT1lKXRocm93XCJFcnJvcjogZmluYWwgcG9zIFwiK28rXCIgZGlmZmVycyBmcm9tIFNJRFggZW5kIFwiK2U7cmV0dXJuIG59LGI9ZnVuY3Rpb24oYixjLGQpe3ZhciBlLGYsZyxoLGksaixrLGw7Zm9yKGU9YS5jYWxsKHRoaXMsYixkKSxmPWUucmVmZXJlbmNlcyxnPVtdLGk9MCxqPWYubGVuZ3RoO2o+aTtpKz0xKWg9bmV3IERhc2gudm8uU2VnbWVudCxoLmR1cmF0aW9uPWZbaV0uZHVyYXRpb24saC5tZWRpYT1jLGguc3RhcnRUaW1lPWZbaV0udGltZSxoLnRpbWVzY2FsZT1mW2ldLnRpbWVzY2FsZSxrPWZbaV0ub2Zmc2V0LGw9ZltpXS5vZmZzZXQrZltpXS5zaXplLTEsaC5tZWRpYVJhbmdlPWsrXCItXCIrbCxnLnB1c2goaCk7cmV0dXJuIHRoaXMuZGVidWcubG9nKFwiUGFyc2VkIFNJRFggYm94OiBcIitnLmxlbmd0aCtcIiBzZWdtZW50cy5cIiksUS53aGVuKGcpfSxjPWZ1bmN0aW9uKGEsYil7dmFyIGQsZSxmLGcsaCxpLGosaz1RLmRlZmVyKCksbD1uZXcgRGF0YVZpZXcoYSksbT0wLG49XCJcIixvPTAscD0hMSxxPXRoaXM7Zm9yKHEuZGVidWcubG9nKFwiU2VhcmNoaW5nIGZvciBpbml0aWFsaXphdGlvbi5cIik7XCJtb292XCIhPT1uJiZtPGwuYnl0ZUxlbmd0aDspe2ZvcihvPWwuZ2V0VWludDMyKG0pLG0rPTQsbj1cIlwiLGc9MDs0Pmc7Zys9MSloPWwuZ2V0SW50OChtKSxuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGgpLG0rPTE7XCJtb292XCIhPT1uJiYobSs9by04KX1yZXR1cm4gZj1sLmJ5dGVMZW5ndGgtbSxcIm1vb3ZcIiE9PW4/KHEuZGVidWcubG9nKFwiTG9hZGluZyBtb3JlIGJ5dGVzIHRvIGZpbmQgaW5pdGlhbGl6YXRpb24uXCIpLGIucmFuZ2Uuc3RhcnQ9MCxiLnJhbmdlLmVuZD1iLmJ5dGVzTG9hZGVkK2IuYnl0ZXNUb0xvYWQsaT1uZXcgWE1MSHR0cFJlcXVlc3QsaS5vbmxvYWRlbmQ9ZnVuY3Rpb24oKXtwfHxrLnJlamVjdChcIkVycm9yIGxvYWRpbmcgaW5pdGlhbGl6YXRpb24uXCIpfSxpLm9ubG9hZD1mdW5jdGlvbigpe3A9ITAsYi5ieXRlc0xvYWRlZD1iLnJhbmdlLmVuZCxjLmNhbGwocSxpLnJlc3BvbnNlKS50aGVuKGZ1bmN0aW9uKGEpe2sucmVzb2x2ZShhKX0pfSxpLm9uZXJyb3I9ZnVuY3Rpb24oKXtrLnJlamVjdChcIkVycm9yIGxvYWRpbmcgaW5pdGlhbGl6YXRpb24uXCIpfSxpLm9wZW4oXCJHRVRcIixiLnVybCksaS5yZXNwb25zZVR5cGU9XCJhcnJheWJ1ZmZlclwiLGkuc2V0UmVxdWVzdEhlYWRlcihcIlJhbmdlXCIsXCJieXRlcz1cIitiLnJhbmdlLnN0YXJ0K1wiLVwiK2IucmFuZ2UuZW5kKSxpLnNlbmQobnVsbCkpOihkPW0tOCxlPWQrby0xLGo9ZCtcIi1cIitlLHEuZGVidWcubG9nKFwiRm91bmQgdGhlIGluaXRpYWxpemF0aW9uLiAgUmFuZ2U6IFwiK2opLGsucmVzb2x2ZShqKSksay5wcm9taXNlfSxkPWZ1bmN0aW9uKGEpe3ZhciBiPVEuZGVmZXIoKSxkPW5ldyBYTUxIdHRwUmVxdWVzdCxlPSEwLGY9dGhpcyxnPXt1cmw6YSxyYW5nZTp7fSxzZWFyY2hpbmc6ITEsYnl0ZXNMb2FkZWQ6MCxieXRlc1RvTG9hZDoxNTAwLHJlcXVlc3Q6ZH07cmV0dXJuIGYuZGVidWcubG9nKFwiU3RhcnQgc2VhcmNoaW5nIGZvciBpbml0aWFsaXphdGlvbi5cIiksZy5yYW5nZS5zdGFydD0wLGcucmFuZ2UuZW5kPWcuYnl0ZXNUb0xvYWQsZC5vbmxvYWQ9ZnVuY3Rpb24oKXtkLnN0YXR1czwyMDB8fGQuc3RhdHVzPjI5OXx8KGU9ITEsZy5ieXRlc0xvYWRlZD1nLnJhbmdlLmVuZCxjLmNhbGwoZixkLnJlc3BvbnNlLGcpLnRoZW4oZnVuY3Rpb24oYSl7Yi5yZXNvbHZlKGEpfSkpfSxkLm9ubG9hZGVuZD1kLm9uZXJyb3I9ZnVuY3Rpb24oKXtlJiYoZT0hMSxmLmVyckhhbmRsZXIuZG93bmxvYWRFcnJvcihcImluaXRpYWxpemF0aW9uXCIsZy51cmwsZCksYi5yZWplY3QoZCkpfSxkLm9wZW4oXCJHRVRcIixnLnVybCksZC5yZXNwb25zZVR5cGU9XCJhcnJheWJ1ZmZlclwiLGQuc2V0UmVxdWVzdEhlYWRlcihcIlJhbmdlXCIsXCJieXRlcz1cIitnLnJhbmdlLnN0YXJ0K1wiLVwiK2cucmFuZ2UuZW5kKSxkLnNlbmQobnVsbCksZi5kZWJ1Zy5sb2coXCJQZXJmb3JtIGluaXQgc2VhcmNoOiBcIitnLnVybCksYi5wcm9taXNlfSxlPWZ1bmN0aW9uKGEsYyl7dmFyIGQsZixnLGgsaSxqLGssbCxtPVEuZGVmZXIoKSxuPW5ldyBEYXRhVmlldyhhKSxvPW5ldyBYTUxIdHRwUmVxdWVzdCxwPTAscT1cIlwiLHI9MCxzPSEwLHQ9ITEsdT10aGlzO2Zvcih1LmRlYnVnLmxvZyhcIlNlYXJjaGluZyBmb3IgU0lEWCBib3guXCIpLHUuZGVidWcubG9nKGMuYnl0ZXNMb2FkZWQrXCIgYnl0ZXMgbG9hZGVkLlwiKTtcInNpZHhcIiE9PXEmJnA8bi5ieXRlTGVuZ3RoOyl7Zm9yKHI9bi5nZXRVaW50MzIocCkscCs9NCxxPVwiXCIsaT0wOzQ+aTtpKz0xKWo9bi5nZXRJbnQ4KHApLHErPVN0cmluZy5mcm9tQ2hhckNvZGUoaikscCs9MTtcInNpZHhcIiE9PXEmJihwKz1yLTgpfWlmKGQ9bi5ieXRlTGVuZ3RoLXAsXCJzaWR4XCIhPT1xKW0ucmVqZWN0KCk7ZWxzZSBpZihyLTg+ZCl1LmRlYnVnLmxvZyhcIkZvdW5kIFNJRFggYnV0IHdlIGRvbid0IGhhdmUgYWxsIG9mIGl0LlwiKSxjLnJhbmdlLnN0YXJ0PTAsYy5yYW5nZS5lbmQ9Yy5ieXRlc0xvYWRlZCsoci1kKSxvLm9ubG9hZD1mdW5jdGlvbigpe28uc3RhdHVzPDIwMHx8by5zdGF0dXM+Mjk5fHwocz0hMSxjLmJ5dGVzTG9hZGVkPWMucmFuZ2UuZW5kLGUuY2FsbCh1LG8ucmVzcG9uc2UsYykudGhlbihmdW5jdGlvbihhKXttLnJlc29sdmUoYSl9KSl9LG8ub25sb2FkZW5kPW8ub25lcnJvcj1mdW5jdGlvbigpe3MmJihzPSExLHUuZXJySGFuZGxlci5kb3dubG9hZEVycm9yKFwiU0lEWFwiLGMudXJsLG8pLG0ucmVqZWN0KG8pKX0sby5vcGVuKFwiR0VUXCIsYy51cmwpLG8ucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIixvLnNldFJlcXVlc3RIZWFkZXIoXCJSYW5nZVwiLFwiYnl0ZXM9XCIrYy5yYW5nZS5zdGFydCtcIi1cIitjLnJhbmdlLmVuZCksby5zZW5kKG51bGwpO2Vsc2UgaWYoYy5yYW5nZS5zdGFydD1wLTgsYy5yYW5nZS5lbmQ9Yy5yYW5nZS5zdGFydCtyLHUuZGVidWcubG9nKFwiRm91bmQgdGhlIFNJRFggYm94LiAgU3RhcnQ6IFwiK2MucmFuZ2Uuc3RhcnQrXCIgfCBFbmQ6IFwiK2MucmFuZ2UuZW5kKSxmPW5ldyBBcnJheUJ1ZmZlcihjLnJhbmdlLmVuZC1jLnJhbmdlLnN0YXJ0KSxoPW5ldyBVaW50OEFycmF5KGYpLGc9bmV3IFVpbnQ4QXJyYXkoYSxjLnJhbmdlLnN0YXJ0LGMucmFuZ2UuZW5kLWMucmFuZ2Uuc3RhcnQpLGguc2V0KGcpLGs9dGhpcy5wYXJzZVNJRFguY2FsbCh0aGlzLGYsYy5yYW5nZS5zdGFydCksbD1rLnJlZmVyZW5jZXMsbnVsbCE9PWwmJnZvaWQgMCE9PWwmJmwubGVuZ3RoPjAmJih0PTE9PT1sWzBdLnR5cGUpLHQpe3UuZGVidWcubG9nKFwiSW5pdGlhdGUgbXVsdGlwbGUgU0lEWCBsb2FkLlwiKTt2YXIgdix3LHgseSx6LEEsQj1bXTtmb3Iodj0wLHc9bC5sZW5ndGg7dz52O3YrPTEpeD1sW3ZdLm9mZnNldCx5PWxbdl0ub2Zmc2V0K2xbdl0uc2l6ZS0xLHo9eCtcIi1cIit5LEIucHVzaCh0aGlzLmxvYWRTZWdtZW50cy5jYWxsKHUsYy51cmwseikpO1EuYWxsKEIpLnRoZW4oZnVuY3Rpb24oYSl7Zm9yKEE9W10sdj0wLHc9YS5sZW5ndGg7dz52O3YrPTEpQT1BLmNvbmNhdChhW3ZdKTttLnJlc29sdmUoQSl9LGZ1bmN0aW9uKGEpe20ucmVqZWN0KGEpfSl9ZWxzZSB1LmRlYnVnLmxvZyhcIlBhcnNpbmcgc2VnbWVudHMgZnJvbSBTSURYLlwiKSxiLmNhbGwodSxmLGMudXJsLGMucmFuZ2Uuc3RhcnQpLnRoZW4oZnVuY3Rpb24oYSl7bS5yZXNvbHZlKGEpfSk7cmV0dXJuIG0ucHJvbWlzZX0sZj1mdW5jdGlvbihhLGMpe3ZhciBkLGY9US5kZWZlcigpLGc9bmV3IFhNTEh0dHBSZXF1ZXN0LGg9ITAsaT10aGlzLGo9e3VybDphLHJhbmdlOnt9LHNlYXJjaGluZzohMSxieXRlc0xvYWRlZDowLGJ5dGVzVG9Mb2FkOjE1MDAscmVxdWVzdDpnfTtyZXR1cm4gbnVsbD09PWM/KGkuZGVidWcubG9nKFwiTm8ga25vd24gcmFuZ2UgZm9yIFNJRFggcmVxdWVzdC5cIiksai5zZWFyY2hpbmc9ITAsai5yYW5nZS5zdGFydD0wLGoucmFuZ2UuZW5kPWouYnl0ZXNUb0xvYWQpOihkPWMuc3BsaXQoXCItXCIpLGoucmFuZ2Uuc3RhcnQ9cGFyc2VGbG9hdChkWzBdKSxqLnJhbmdlLmVuZD1wYXJzZUZsb2F0KGRbMV0pKSxnLm9ubG9hZD1mdW5jdGlvbigpe2cuc3RhdHVzPDIwMHx8Zy5zdGF0dXM+Mjk5fHwoaD0hMSxqLnNlYXJjaGluZz8oai5ieXRlc0xvYWRlZD1qLnJhbmdlLmVuZCxlLmNhbGwoaSxnLnJlc3BvbnNlLGopLnRoZW4oZnVuY3Rpb24oYSl7Zi5yZXNvbHZlKGEpfSkpOmIuY2FsbChpLGcucmVzcG9uc2Usai51cmwsai5yYW5nZS5zdGFydCkudGhlbihmdW5jdGlvbihhKXtmLnJlc29sdmUoYSl9KSl9LGcub25sb2FkZW5kPWcub25lcnJvcj1mdW5jdGlvbigpe2gmJihoPSExLGkuZXJySGFuZGxlci5kb3dubG9hZEVycm9yKFwiU0lEWFwiLGoudXJsLGcpLGYucmVqZWN0KGcpKX0sZy5vcGVuKFwiR0VUXCIsai51cmwpLGcucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIixnLnNldFJlcXVlc3RIZWFkZXIoXCJSYW5nZVwiLFwiYnl0ZXM9XCIrai5yYW5nZS5zdGFydCtcIi1cIitqLnJhbmdlLmVuZCksZy5zZW5kKG51bGwpLGkuZGVidWcubG9nKFwiUGVyZm9ybSBTSURYIGxvYWQ6IFwiK2oudXJsKSxmLnByb21pc2V9O3JldHVybntkZWJ1Zzp2b2lkIDAsZXJySGFuZGxlcjp2b2lkIDAsbG9hZFNlZ21lbnRzOmYsbG9hZEluaXRpYWxpemF0aW9uOmQscGFyc2VTZWdtZW50czpiLHBhcnNlU0lEWDphLGZpbmRTSURYOmV9fSxEYXNoLmRlcGVuZGVuY2llcy5CYXNlVVJMRXh0ZW5zaW9ucy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOkRhc2guZGVwZW5kZW5jaWVzLkJhc2VVUkxFeHRlbnNpb25zfSxEYXNoLmRlcGVuZGVuY2llcy5EYXNoSGFuZGxlcj1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhLGIsYyxkPS0xLGU9ZnVuY3Rpb24oYSxiKXt2YXIgYz1udWxsO3JldHVybiBiJiZiLlJlcHJlc2VudGF0aW9uX2FzQXJyYXkmJmIuUmVwcmVzZW50YXRpb25fYXNBcnJheS5sZW5ndGg+MCYmKGM9Yi5SZXByZXNlbnRhdGlvbl9hc0FycmF5W2FdKSxjfSxmPWZ1bmN0aW9uKGEsYil7dmFyIGM9Yi50b1N0cmluZygpO3JldHVybiBhLnNwbGl0KFwiJE51bWJlciRcIikuam9pbihjKX0sZz1mdW5jdGlvbihhLGIpe3ZhciBjPWIudG9TdHJpbmcoKTtyZXR1cm4gYS5zcGxpdChcIiRUaW1lJFwiKS5qb2luKGMpfSxoPWZ1bmN0aW9uKGEsYil7dmFyIGM9Yi50b1N0cmluZygpO3JldHVybiBhLnNwbGl0KFwiJEJhbmR3aWR0aCRcIikuam9pbihjKX0saT1mdW5jdGlvbihhLGIpe2lmKG51bGw9PT1ifHwtMT09PWEuaW5kZXhPZihcIiRSZXByZXNlbnRhdGlvbklEJFwiKSlyZXR1cm4gYTt2YXIgYz1iLnRvU3RyaW5nKCk7cmV0dXJuIGEuc3BsaXQoXCIkUmVwcmVzZW50YXRpb25JRCRcIikuam9pbihjKX0saj1mdW5jdGlvbihhLGIpe3ZhciBjO3JldHVybiBjPWE9PT1iP2E6LTEhPT1hLmluZGV4T2YoXCJodHRwOi8vXCIpP2E6YithfSxrPWZ1bmN0aW9uKGEsYil7dmFyIGQ9US5kZWZlcigpLGY9ZShhLGIpLGc9bnVsbCxrPW51bGwsbD1udWxsLG09bnVsbCxuPXRoaXM7cmV0dXJuIGY/KG4uZGVidWcubG9nKFwiR2V0dGluZyB0aGUgaW5pdGlhbGl6YXRpb24gcmVxdWVzdC5cIiksZi5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUZW1wbGF0ZVwiKT9mLlNlZ21lbnRUZW1wbGF0ZS5oYXNPd25Qcm9wZXJ0eShcImluaXRpYWxpemF0aW9uXCIpJiYoaz1mLlNlZ21lbnRUZW1wbGF0ZS5pbml0aWFsaXphdGlvbixrPWgoayxmLmJhbmR3aWR0aCksaz1pKGssZi5pZCkpOmYuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50TGlzdFwiKSYmZi5TZWdtZW50TGlzdC5oYXNPd25Qcm9wZXJ0eShcIkluaXRpYWxpemF0aW9uXCIpJiZmLlNlZ21lbnRMaXN0LkluaXRpYWxpemF0aW9uLmhhc093blByb3BlcnR5KFwicmFuZ2VcIik/KGs9Zi5TZWdtZW50TGlzdC5Jbml0aWFsaXphdGlvbi5oYXNPd25Qcm9wZXJ0eShcInNvdXJjZVVSTFwiKT9mLlNlZ21lbnRMaXN0LkluaXRpYWxpemF0aW9uLnNvdXJjZVVSTDpmLkJhc2VVUkwsbT1mLlNlZ21lbnRMaXN0LkluaXRpYWxpemF0aW9uLnJhbmdlKTpmLmhhc093blByb3BlcnR5KFwiU2VnbWVudExpc3RcIikmJmYuU2VnbWVudExpc3QuaGFzT3duUHJvcGVydHkoXCJJbml0aWFsaXphdGlvblwiKSYmZi5TZWdtZW50TGlzdC5Jbml0aWFsaXphdGlvbi5oYXNPd25Qcm9wZXJ0eShcInNvdXJjZVVSTFwiKT9rPWYuU2VnbWVudExpc3QuSW5pdGlhbGl6YXRpb24uc291cmNlVVJMOmYuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50QmFzZVwiKSYmZi5TZWdtZW50QmFzZS5oYXNPd25Qcm9wZXJ0eShcIkluaXRpYWxpemF0aW9uXCIpJiZmLlNlZ21lbnRCYXNlLkluaXRpYWxpemF0aW9uLmhhc093blByb3BlcnR5KFwicmFuZ2VcIik/KGs9Zi5CYXNlVVJMLG09Zi5TZWdtZW50QmFzZS5Jbml0aWFsaXphdGlvbi5yYW5nZSk6Zi5oYXNPd25Qcm9wZXJ0eShcIm1pbWVUeXBlXCIpJiZuLm1hbmlmZXN0RXh0LmdldElzVGV4dFRyYWNrKGYubWltZVR5cGUpPyhrPWYuQmFzZVVSTCxtPTApOihsPWYuQmFzZVVSTCxuLmJhc2VVUkxFeHQubG9hZEluaXRpYWxpemF0aW9uKGwpLnRoZW4oZnVuY3Rpb24oYil7bi5kZWJ1Zy5sb2coXCJHb3QgYW4gaW5pdGlhbGl6YXRpb24uXCIpLGc9bmV3IE1lZGlhUGxheWVyLnZvLlNlZ21lbnRSZXF1ZXN0LGcuc3RyZWFtVHlwZT1jLGcudHlwZT1cIkluaXRpYWxpemF0aW9uIFNlZ21lbnRcIixnLnVybD1qKGwsZi5CYXNlVVJMKSxnLnJhbmdlPWIsZy5xdWFsaXR5PWEsZC5yZXNvbHZlKGcpfSxmdW5jdGlvbihhKXtkLnJlamVjdChhKX0pKSxrJiZrLmxlbmd0aD4wJiYobi5kZWJ1Zy5sb2coXCJHb3QgYW4gaW5pdGlhbGl6YXRpb24uXCIpLGc9bmV3IE1lZGlhUGxheWVyLnZvLlNlZ21lbnRSZXF1ZXN0LGcuc3RyZWFtVHlwZT1jLGcudHlwZT1cIkluaXRpYWxpemF0aW9uIFNlZ21lbnRcIixnLnVybD1qKGssZi5CYXNlVVJMKSxnLnJhbmdlPW0sZy5xdWFsaXR5PWEsZC5yZXNvbHZlKGcpKSxkLnByb21pc2UpOlEucmVqZWN0KFwibm8gcmVwcmVzZW5hdGlvblwiKX0sbD1mdW5jdGlvbihjKXt2YXIgZSxmLGcsaCxpLGosaz0hMTtyZXR1cm4gdGhpcy5kZWJ1Zy5sb2coXCJDaGVja2luZyBmb3Igc3RyZWFtIGVuZC4uLlwiKSxhPyh0aGlzLmRlYnVnLmxvZyhcIkxpdmUgbmV2ZXIgZW5kcyEgKFRPRE8pXCIpLGs9ITEpOmMuaGFzT3duUHJvcGVydHkoXCJzZWdtZW50c1wiKSYmbnVsbCE9PWMuc2VnbWVudHM/KHRoaXMuZGVidWcubG9nKFwiU2VnbWVudHM6IFwiK2QrXCIgLyBcIitjLnNlZ21lbnRzLmxlbmd0aCksaz1kPj1jLnNlZ21lbnRzLmxlbmd0aCk6Yy5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUZW1wbGF0ZVwiKSYmIWMuU2VnbWVudFRlbXBsYXRlLmhhc093blByb3BlcnR5KFwiU2VnbWVudFRpbWVsaW5lXCIpJiYoZj0xLGk9MSxoPWIsYy5TZWdtZW50VGVtcGxhdGUuaGFzT3duUHJvcGVydHkoXCJkdXJhdGlvblwiKSYmKGU9Yy5TZWdtZW50VGVtcGxhdGUuZHVyYXRpb24sYy5TZWdtZW50VGVtcGxhdGUuaGFzT3duUHJvcGVydHkoXCJ0aW1lc2NhbGVcIikmJihmPWMuU2VnbWVudFRlbXBsYXRlLnRpbWVzY2FsZSksYy5TZWdtZW50VGVtcGxhdGUuaGFzT3duUHJvcGVydHkoXCJzdGFydE51bWJlclwiKSYmKGk9Yy5TZWdtZW50VGVtcGxhdGUuc3RhcnROdW1iZXIpLGc9ZS9mLGo9ZC1pLHRoaXMuZGVidWcubG9nKFwiU2VnbWVudFRlbXBsYXRlOiBcIitnK1wiICogXCIraitcIiA9IFwiK2cqaitcIiAvIFwiK2gpLGs9ZypqPj1oKSksUS53aGVuKGspfSxtPWZ1bmN0aW9uKGEsYyl7dmFyIGQsZSxoLGksaixrLGwsbSxuPVtdLG89MCxwPTEscT0xO2ZvcihhLmhhc093blByb3BlcnR5KFwic3RhcnROdW1iZXJcIikmJihwPWEuc3RhcnROdW1iZXIpLGEuaGFzT3duUHJvcGVydHkoXCJ0aW1lc2NhbGVcIikmJihxPWEudGltZXNjYWxlKSxkPWMuU19hc0FycmF5LGg9MCxpPWQubGVuZ3RoO2k+aDtoKz0xKWZvcihlPWRbaF0saz0wLGUuaGFzT3duUHJvcGVydHkoXCJyXCIpJiYoaz1lLnIpLDA+ayYmKGs9KGItby9xKS8oZS5kL3EpLTEpLGo9MDtrPj1qO2orPTEpbD1uZXcgRGFzaC52by5TZWdtZW50LGwudGltZXNjYWxlPXEsMD09PWomJmUuaGFzT3duUHJvcGVydHkoXCJ0XCIpPyhsLnN0YXJ0VGltZT1lLnQsbz1lLnQpOmwuc3RhcnRUaW1lPW8sbC5kdXJhdGlvbj1lLmQsbT1hLm1lZGlhLG09ZihtLHApLG09ZyhtLGwuc3RhcnRUaW1lKSxsLm1lZGlhPW0sbi5wdXNoKGwpLG8rPWwuZHVyYXRpb24scCs9MTtyZXR1cm4gUS53aGVuKG4pfSxuPWZ1bmN0aW9uKGEpe3ZhciBiLGMsZCxlLGYsZz1bXSxoPTE7Zm9yKGEuaGFzT3duUHJvcGVydHkoXCJzdGFydE51bWJlclwiKSYmKGg9TWF0aC5tYXgoYS5zdGFydE51bWJlciwxKSksZj0oaC0xKSphLmR1cmF0aW9uLGI9MCxjPWEuU2VnbWVudFVSTF9hc0FycmF5Lmxlbmd0aDtjPmI7Yis9MSllPWEuU2VnbWVudFVSTF9hc0FycmF5W2JdLGQ9bmV3IERhc2gudm8uU2VnbWVudCxkLm1lZGlhPWUubWVkaWEsZC5tZWRpYVJhbmdlPWUubWVkaWFSYW5nZSxkLmluZGV4PWUuaW5kZXgsZC5pbmRleFJhbmdlPWUuaW5kZXhSYW5nZSxkLnRpbWVzY2FsZT1hLnRpbWVzY2FsZSxkLmR1cmF0aW9uPWEuZHVyYXRpb24sZC5zdGFydFRpbWU9ZitiKmEuZHVyYXRpb24sZy5wdXNoKGQpO3JldHVybiBRLndoZW4oZyl9LG89ZnVuY3Rpb24oYSl7dmFyIGI9YS5CYXNlVVJMLGM9bnVsbDtyZXR1cm4gYS5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRCYXNlXCIpJiZhLlNlZ21lbnRCYXNlLmhhc093blByb3BlcnR5KFwiaW5kZXhSYW5nZVwiKSYmKGM9YS5TZWdtZW50QmFzZS5pbmRleFJhbmdlKSx0aGlzLmJhc2VVUkxFeHQubG9hZFNlZ21lbnRzKGIsYyl9LHA9ZnVuY3Rpb24oYSl7dmFyIGI7cmV0dXJuIGI9YS5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUZW1wbGF0ZVwiKSYmIWEuU2VnbWVudFRlbXBsYXRlLmhhc093blByb3BlcnR5KFwiU2VnbWVudFRpbWVsaW5lXCIpP1Eud2hlbihudWxsKTphLmhhc093blByb3BlcnR5KFwic2VnbWVudHNcIikmJm51bGwhPT1hLnNlZ21lbnRzP1Eud2hlbihhLnNlZ21lbnRzKTphLmhhc093blByb3BlcnR5KFwiU2VnbWVudFRlbXBsYXRlXCIpJiZhLlNlZ21lbnRUZW1wbGF0ZS5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUaW1lbGluZVwiKT9tLmNhbGwodGhpcyxhLlNlZ21lbnRUZW1wbGF0ZSxhLlNlZ21lbnRUZW1wbGF0ZS5TZWdtZW50VGltZWxpbmUpOmEuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50TGlzdFwiKT9uLmNhbGwodGhpcyxhLlNlZ21lbnRMaXN0KTpvLmNhbGwodGhpcyxhKX0scT1mdW5jdGlvbihhLGIpe3ZhciBjLGQsZSxmLGc9LTE7aWYoYiYmYi5sZW5ndGg+MClmb3IoZj1iLmxlbmd0aC0xO2Y+PTA7Zi0tKXtpZihjPWJbZl0sZD1jLnN0YXJ0VGltZS9jLnRpbWVzY2FsZSxlPWMuZHVyYXRpb24vYy50aW1lc2NhbGUsYStEYXNoLmRlcGVuZGVuY2llcy5EYXNoSGFuZGxlci5FUFNJTE9OPj1kJiZhLURhc2guZGVwZW5kZW5jaWVzLkRhc2hIYW5kbGVyLkVQU0lMT048PWQrZSl7Zz1mO2JyZWFrfS0xPT09ZyYmYS1EYXNoLmRlcGVuZGVuY2llcy5EYXNoSGFuZGxlci5FUFNJTE9OPmQrZSYmKGc9ZisxKX1yZXR1cm4tMT09PWcmJihjb25zb2xlLmxvZyhcIkNvdWxkbid0IGZpZ3VyZSBvdXQgYSB0aW1lIVwiKSxjb25zb2xlLmxvZyhcIlRpbWU6IFwiK2EpLGNvbnNvbGUubG9nKGIpKSxRLndoZW4oZyl9LHI9ZnVuY3Rpb24oYSxiKXt2YXIgYyxkLGU9LTEsZj0xLGc9MTtpZighYi5oYXNPd25Qcm9wZXJ0eShcImR1cmF0aW9uXCIpKXRocm93XCJFeHBlY3RlZCAnZHVyYXRpb24nIGF0dHJpYnV0ZSBvbiBTZWdtZW50VGVtcGxhdGUhXCI7cmV0dXJuIGM9Yi5kdXJhdGlvbixiLmhhc093blByb3BlcnR5KFwidGltZXNjYWxlXCIpJiYoZj1iLnRpbWVzY2FsZSksYi5oYXNPd25Qcm9wZXJ0eShcInN0YXJ0TnVtYmVyXCIpJiYoZz1iLnN0YXJ0TnVtYmVyKSxkPWMvZixlPU1hdGguZmxvb3IoYS9kKSxlKz1nLFEud2hlbihlKX0scz1mdW5jdGlvbihhLGIsZCxlKXt2YXIgayxsLG09bmV3IE1lZGlhUGxheWVyLnZvLlNlZ21lbnRSZXF1ZXN0LG49MSxvPTE7cmV0dXJuIGIuaGFzT3duUHJvcGVydHkoXCJ0aW1lc2NhbGVcIikmJihuPWIudGltZXNjYWxlKSxiLmhhc093blByb3BlcnR5KFwic3RhcnROdW1iZXJcIikmJihvPWIuc3RhcnROdW1iZXIpLGw9Yi5kdXJhdGlvbiphL24sbD1NYXRoLmZsb29yKGwpLGs9Yi5tZWRpYSxrPWYoayxhKSxrPWcoayxsKSxrPWgoayxkLmJhbmR3aWR0aCksaz1pKGssZC5pZCksbS5zdHJlYW1UeXBlPWMsbS50eXBlPVwiTWVkaWEgU2VnbWVudFwiLG0udXJsPWooayxkLkJhc2VVUkwpLG0uZHVyYXRpb249Yi5kdXJhdGlvbi9uLG0udGltZXNjYWxlPW4sbS5zdGFydFRpbWU9KGEtbykqYi5kdXJhdGlvbi9uLG0ucXVhbGl0eT1lLG0uaW5kZXg9YSxRLndoZW4obSl9LHQ9ZnVuY3Rpb24oYSxiLGQsZSl7aWYobnVsbD09PWJ8fHZvaWQgMD09PWIpcmV0dXJuIFEud2hlbihudWxsKTt2YXIgayxsPW5ldyBNZWRpYVBsYXllci52by5TZWdtZW50UmVxdWVzdDtyZXR1cm4gaz1qKGIubWVkaWEsZC5CYXNlVVJMKSxrPWYoayxhKSxrPWcoayxiLnN0YXJ0VGltZSksaz1oKGssZC5iYW5kd2lkdGgpLGs9aShrLGQuaWQpLGwuc3RyZWFtVHlwZT1jLGwudHlwZT1cIk1lZGlhIFNlZ21lbnRcIixsLnVybD1rLGwucmFuZ2U9Yi5tZWRpYVJhbmdlLGwuc3RhcnRUaW1lPWIuc3RhcnRUaW1lL2IudGltZXNjYWxlLGwuZHVyYXRpb249Yi5kdXJhdGlvbi9iLnRpbWVzY2FsZSxsLnRpbWVzY2FsZT1iLnRpbWVzY2FsZSxsLnF1YWxpdHk9ZSxsLmluZGV4PWEsUS53aGVuKGwpfSx1PWZ1bmN0aW9uKGEsYixjKXt2YXIgZixnLGgsaT1lKGIsYyksaj0hMSxrPXRoaXM7cmV0dXJuIGk/KGsuZGVidWcubG9nKFwiR2V0dGluZyB0aGUgcmVxdWVzdCBmb3IgdGltZTogXCIrYSksZj1RLmRlZmVyKCkscC5jYWxsKGssaSkudGhlbihmdW5jdGlvbihiKXt2YXIgYztpZihrLmRlYnVnLmxvZyhcIkdvdCBzZWdtZW50cy5cIiksay5kZWJ1Zy5sb2coYiksbnVsbD09PWIpe2lmKCFpLmhhc093blByb3BlcnR5KFwiU2VnbWVudFRlbXBsYXRlXCIpKXRocm93XCJFeHBlY3RlZCBTZWdtZW50VGVtcGxhdGUhXCI7aj0hMCxrLmRlYnVnLmxvZyhcIk5vIHNlZ21lbnRzIGZvdW5kLCBzbyB3ZSBtdXN0IGJlIHVzaW5nIGEgU2VnbWVudFRlbXBsYXRlLlwiKSxjPXIuY2FsbChrLGEsaS5TZWdtZW50VGVtcGxhdGUpfWVsc2Ugay5kZWJ1Zy5sb2coXCJHb3QgYSBsaXN0IG9mIHNlZ21lbnRzLCBzbyBkaWcgZGVlcGVyLlwiKSxpLnNlZ21lbnRzPWIsaj0hMSxjPXEuY2FsbChrLGEsYik7cmV0dXJuIGN9LGZ1bmN0aW9uKCl7Zi5yZWplY3QoKX0pLnRoZW4oZnVuY3Rpb24oYil7cmV0dXJuIGsuZGVidWcubG9nKFwiSW5kZXggZm9yIHRpbWUgXCIrYStcIiBpcyBcIitiKSxkPWIsbC5jYWxsKGssaSl9KS50aGVuKGZ1bmN0aW9uKGEpe3ZhciBjPW51bGw7cmV0dXJuIGsuZGVidWcubG9nKFwiU3RyZWFtIGZpbmlzaGVkPyBcIithKSxhPyhnPW5ldyBNZWRpYVBsYXllci52by5TZWdtZW50UmVxdWVzdCxnLmFjdGlvbj1nLkFDVElPTl9DT01QTEVURSxnLmluZGV4PWQsay5kZWJ1Zy5sb2coXCJTaWduYWwgY29tcGxldGUuXCIpLGsuZGVidWcubG9nKGcpLGYucmVzb2x2ZShnKSk6aj9jPXMuY2FsbChrLGQsaS5TZWdtZW50VGVtcGxhdGUsaSxiKTooaD1pLnNlZ21lbnRzW2RdLGM9dC5jYWxsKGssZCxoLGksYikpLGN9KS50aGVuKGZ1bmN0aW9uKGEpe2suZGVidWcubG9nKFwiR290IGEgcmVxdWVzdC5cIiksay5kZWJ1Zy5sb2coYSksZi5yZXNvbHZlKGEpfSksZi5wcm9taXNlKTpRLnJlamVjdChcIm5vIHJlcHJlc2VuYXRpb25cIil9LHY9ZnVuY3Rpb24oYSxiKXt2YXIgYyxmLGcsaD1lKGEsYiksaT10aGlzO2lmKCFoKXJldHVybiBRLnJlamVjdChcIm5vIHJlcHJlc2VuYXRpb25cIik7aWYoaS5kZWJ1Zy5sb2coXCJHZXR0aW5nIHRoZSBuZXh0IHJlcXVlc3QuXCIpLC0xPT09ZCl0aHJvd1wiWW91IG11c3QgY2FsbCBnZXRTZWdtZW50UmVxdWVzdEZvclRpbWUgZmlyc3QuXCI7cmV0dXJuIGQrPTEsaS5kZWJ1Zy5sb2coXCJOZXcgaW5kZXg6IFwiK2QpLGM9US5kZWZlcigpLGwuY2FsbChpLGgpLnRoZW4oZnVuY3Rpb24oYil7aS5kZWJ1Zy5sb2coXCJTdHJlYW0gZmluaXNoZWQ/IFwiK2IpLGI/KGY9bmV3IE1lZGlhUGxheWVyLnZvLlNlZ21lbnRSZXF1ZXN0LGYuYWN0aW9uPWYuQUNUSU9OX0NPTVBMRVRFLGYuaW5kZXg9ZCxpLmRlYnVnLmxvZyhcIlNpZ25hbCBjb21wbGV0ZS5cIiksaS5kZWJ1Zy5sb2coZiksYy5yZXNvbHZlKGYpKTpwLmNhbGwoaSxoKS50aGVuKGZ1bmN0aW9uKGIpe3ZhciBjO2lmKGkuZGVidWcubG9nKFwiR290IHNlZ21lbnRzLlwiKSxpLmRlYnVnLmxvZyhiKSxudWxsPT09Yil7aWYoIWguaGFzT3duUHJvcGVydHkoXCJTZWdtZW50VGVtcGxhdGVcIikpdGhyb3dcIkV4cGVjdGVkIFNlZ21lbnRUZW1wbGF0ZSFcIjtpLmRlYnVnLmxvZyhcIk5vIHNlZ21lbnRzIGZvdW5kLCBzbyB3ZSBtdXN0IGJlIHVzaW5nIGEgU2VnbWVudFRlbXBsYXRlLlwiKSxjPXMuY2FsbChpLGQsaC5TZWdtZW50VGVtcGxhdGUsaCxhKX1lbHNlIGguc2VnbWVudHM9YixnPWguc2VnbWVudHNbZF0sYz10LmNhbGwoaSxkLGcsaCxhKTtyZXR1cm4gY30sZnVuY3Rpb24oKXtjLnJlamVjdCgpfSkudGhlbihmdW5jdGlvbihhKXtpLmRlYnVnLmxvZyhcIkdvdCBhIHJlcXVlc3QuXCIpLGkuZGVidWcubG9nKGEpLGMucmVzb2x2ZShhKX0pfSksYy5wcm9taXNlfSx3PWZ1bmN0aW9uKGEsYixjLGQpe3ZhciBmLGcsaCxpPXRoaXMsaj1lKGEsYiksaz1NYXRoLm1heChjLWQsMCksbD1RLmRlZmVyKCksbT0wLG49MTtyZXR1cm4gaj8ocC5jYWxsKGksaikudGhlbihmdW5jdGlvbihhKXtpZihudWxsPT09YXx8dm9pZCAwPT09YSl7aWYoIWouaGFzT3duUHJvcGVydHkoXCJTZWdtZW50VGVtcGxhdGVcIikpdGhyb3dcIkV4cGVjdGVkIFNlZ21lbnRUZW1wbGF0ZSFcIjtqLlNlZ21lbnRUZW1wbGF0ZS5oYXNPd25Qcm9wZXJ0eShcInRpbWVzY2FsZVwiKSYmKG49ai5TZWdtZW50VGVtcGxhdGUudGltZXNjYWxlKSxoPWouU2VnbWVudFRlbXBsYXRlLmR1cmF0aW9uLGY9aC9ufWVsc2UgZz1hWzBdLGcuaGFzT3duUHJvcGVydHkoXCJ0aW1lc2NhbGVcIikmJihuPWcudGltZXNjYWxlKSxoPWcuZHVyYXRpb24sZj1oL247bT1NYXRoLmNlaWwoay9mKSxsLnJlc29sdmUobSl9LGZ1bmN0aW9uKCl7bC5yZXNvbHZlKDApfSksbC5wcm9taXNlKTpRLnJlamVjdChcIm5vIHJlcHJlc2VuYXRpb25cIil9LHg9ZnVuY3Rpb24oYixjKXt2YXIgZixnLGgsaSxqPXRoaXMsaz1lKGIsYyksbD0hMSxtPTEsbj0xLG89US5kZWZlcigpO3JldHVybiBrPyhnPWQsMD5nJiYobD1hLGc9MCkscC5jYWxsKGosaykudGhlbihmdW5jdGlvbihhKXtpZihudWxsPT09YXx8dm9pZCAwPT09YSl7aWYoIWsuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50VGVtcGxhdGVcIikpdGhyb3dcIkV4cGVjdGVkIFNlZ21lbnRUZW1wbGF0ZSFcIjtpPWsuU2VnbWVudFRlbXBsYXRlLmR1cmF0aW9uLGsuU2VnbWVudFRlbXBsYXRlLmhhc093blByb3BlcnR5KFwidGltZXNjYWxlXCIpJiYobT1rLlNlZ21lbnRUZW1wbGF0ZS50aW1lc2NhbGUpLGsuU2VnbWVudFRlbXBsYXRlLmhhc093blByb3BlcnR5KFwic3RhcnROdW1iZXJcIikmJihuPWsuU2VnbWVudFRlbXBsYXRlLnN0YXJ0TnVtYmVyKSxmPWkvbSpNYXRoLm1heChnLW4sMCl9ZWxzZShsfHxnPj1hLmxlbmd0aCkmJihnPWEubGVuZ3RoLTEpLGg9YVtnXS5zdGFydFRpbWUsaT1hW2ddLmR1cmF0aW9uLGFbZ10uaGFzT3duUHJvcGVydHkoXCJ0aW1lc2NhbGVcIikmJihtPWFbZ10udGltZXNjYWxlKSxmPWgvbTtvLnJlc29sdmUoZil9LGZ1bmN0aW9uKCl7by5yZWplY3QoKX0pLG8ucHJvbWlzZSk6US5yZWplY3QoXCJubyByZXByZXNlbmF0aW9uXCIpfTtyZXR1cm57ZGVidWc6dm9pZCAwLGJhc2VVUkxFeHQ6dm9pZCAwLG1hbmlmZXN0TW9kZWw6dm9pZCAwLG1hbmlmZXN0RXh0OnZvaWQgMCxlcnJIYW5kbGVyOnZvaWQgMCxnZXRUeXBlOmZ1bmN0aW9uKCl7cmV0dXJuIGN9LHNldFR5cGU6ZnVuY3Rpb24oYSl7Yz1hfSxnZXRJc0xpdmU6ZnVuY3Rpb24oKXtyZXR1cm4gYX0sc2V0SXNMaXZlOmZ1bmN0aW9uKGIpe2E9Yn0sZ2V0RHVyYXRpb246ZnVuY3Rpb24oKXtyZXR1cm4gYn0sc2V0RHVyYXRpb246ZnVuY3Rpb24oYSl7Yj1hfSxnZXRJbml0UmVxdWVzdDprLGdldFNlZ21lbnRSZXF1ZXN0Rm9yVGltZTp1LGdldE5leHRTZWdtZW50UmVxdWVzdDp2LGdldEN1cnJlbnRUaW1lOngsZ2V0U2VnbWVudENvdW50Rm9yRHVyYXRpb246d319LERhc2guZGVwZW5kZW5jaWVzLkRhc2hIYW5kbGVyLkVQU0lMT049LjAwMyxEYXNoLmRlcGVuZGVuY2llcy5EYXNoSGFuZGxlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOkRhc2guZGVwZW5kZW5jaWVzLkRhc2hIYW5kbGVyfSxEYXNoLmRlcGVuZGVuY2llcy5EYXNoTWFuaWZlc3RFeHRlbnNpb25zPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCJ9LERhc2guZGVwZW5kZW5jaWVzLkRhc2hNYW5pZmVzdEV4dGVuc2lvbnMucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpEYXNoLmRlcGVuZGVuY2llcy5EYXNoTWFuaWZlc3RFeHRlbnNpb25zLGdldElzQXVkaW86ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGIsYyxkLGU9YS5Db250ZW50Q29tcG9uZW50X2FzQXJyYXksZj0hMSxnPSExO2lmKGUpZm9yKGI9MCxjPWUubGVuZ3RoO2M+YjtiKz0xKVwiYXVkaW9cIj09PWVbYl0uY29udGVudFR5cGUmJihmPSEwLGc9ITApO2lmKGEuaGFzT3duUHJvcGVydHkoXCJtaW1lVHlwZVwiKSYmKGY9LTEhPT1hLm1pbWVUeXBlLmluZGV4T2YoXCJhdWRpb1wiKSxnPSEwKSwhZylmb3IoYj0wLGM9YS5SZXByZXNlbnRhdGlvbl9hc0FycmF5Lmxlbmd0aDshZyYmYz5iOylkPWEuUmVwcmVzZW50YXRpb25fYXNBcnJheVtiXSxkLmhhc093blByb3BlcnR5KFwibWltZVR5cGVcIikmJihmPS0xIT09ZC5taW1lVHlwZS5pbmRleE9mKFwiYXVkaW9cIiksZz0hMCksYis9MTtyZXR1cm4gZiYmKGEudHlwZT1cImF1ZGlvXCIpLFEud2hlbihmKX0sZ2V0SXNWaWRlbzpmdW5jdGlvbihhKXtcInVzZSBzdHJpY3RcIjt2YXIgYixjLGQsZT1hLkNvbnRlbnRDb21wb25lbnRfYXNBcnJheSxmPSExLGc9ITE7aWYoZSlmb3IoYj0wLGM9ZS5sZW5ndGg7Yz5iO2IrPTEpXCJ2aWRlb1wiPT09ZVtiXS5jb250ZW50VHlwZSYmKGY9ITAsZz0hMCk7aWYoYS5oYXNPd25Qcm9wZXJ0eShcIm1pbWVUeXBlXCIpJiYoZj0tMSE9PWEubWltZVR5cGUuaW5kZXhPZihcInZpZGVvXCIpLGc9ITApLCFnKWZvcihiPTAsYz1hLlJlcHJlc2VudGF0aW9uX2FzQXJyYXkubGVuZ3RoOyFnJiZjPmI7KWQ9YS5SZXByZXNlbnRhdGlvbl9hc0FycmF5W2JdLGQuaGFzT3duUHJvcGVydHkoXCJtaW1lVHlwZVwiKSYmKGY9LTEhPT1kLm1pbWVUeXBlLmluZGV4T2YoXCJ2aWRlb1wiKSxnPSEwKSxiKz0xO3JldHVybiBmJiYoYS50eXBlPVwidmlkZW9cIiksUS53aGVuKGYpfSxnZXRJc1RleHQ6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGIsYyxkLGU9YS5Db250ZW50Q29tcG9uZW50X2FzQXJyYXksZj0hMSxnPSExO2lmKGUpZm9yKGI9MCxjPWUubGVuZ3RoO2M+YjtiKz0xKVwidGV4dFwiPT09ZVtiXS5jb250ZW50VHlwZSYmKGY9ITAsZz0hMCk7aWYoYS5oYXNPd25Qcm9wZXJ0eShcIm1pbWVUeXBlXCIpJiYoZj0tMSE9PWEubWltZVR5cGUuaW5kZXhPZihcInRleHRcIiksZz0hMCksIWcpZm9yKGI9MCxjPWEuUmVwcmVzZW50YXRpb25fYXNBcnJheS5sZW5ndGg7IWcmJmM+YjspZD1hLlJlcHJlc2VudGF0aW9uX2FzQXJyYXlbYl0sZC5oYXNPd25Qcm9wZXJ0eShcIm1pbWVUeXBlXCIpJiYoZj0tMSE9PWQubWltZVR5cGUuaW5kZXhPZihcInRleHRcIiksZz0hMCksYis9MTtyZXR1cm4gUS53aGVuKGYpfSxnZXRJc1RleHRUcmFjazpmdW5jdGlvbihhKXtyZXR1cm5cInRleHQvdnR0XCI9PT1hfHxcImFwcGxpY2F0aW9uL3R0bWwreG1sXCI9PT1hfSxnZXRJc01haW46ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjtyZXR1cm4gUS53aGVuKCExKX0scHJvY2Vzc0FkYXB0YXRpb246ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIHZvaWQgMCE9PWEuUmVwcmVzZW50YXRpb25fYXNBcnJheSYmbnVsbCE9PWEuUmVwcmVzZW50YXRpb25fYXNBcnJheSYmYS5SZXByZXNlbnRhdGlvbl9hc0FycmF5LnNvcnQoZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5iYW5kd2lkdGgtYi5iYW5kd2lkdGh9KSxhfSxnZXREYXRhRm9ySWQ6ZnVuY3Rpb24oYSxiLGMpe1widXNlIHN0cmljdFwiO3ZhciBkLGUsZj1iLlBlcmlvZF9hc0FycmF5W2NdLkFkYXB0YXRpb25TZXRfYXNBcnJheTtmb3IoZD0wLGU9Zi5sZW5ndGg7ZT5kO2QrPTEpaWYoZltkXS5oYXNPd25Qcm9wZXJ0eShcImlkXCIpJiZmW2RdLmlkPT09YSlyZXR1cm4gUS53aGVuKGZbZF0pO3JldHVybiBRLndoZW4obnVsbCl9LGdldERhdGFGb3JJbmRleDpmdW5jdGlvbihhLGIsYyl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGQ9Yi5QZXJpb2RfYXNBcnJheVtjXS5BZGFwdGF0aW9uU2V0X2FzQXJyYXk7cmV0dXJuIFEud2hlbihkW2FdKX0sZ2V0RGF0YUluZGV4OmZ1bmN0aW9uKGEsYixjKXtcInVzZSBzdHJpY3RcIjt2YXIgZCxlLGY9Yi5QZXJpb2RfYXNBcnJheVtjXS5BZGFwdGF0aW9uU2V0X2FzQXJyYXk7Zm9yKGQ9MCxlPWYubGVuZ3RoO2U+ZDtkKz0xKWlmKGZbZF09PT1hKXJldHVybiBRLndoZW4oZCk7cmV0dXJuIFEud2hlbigtMSl9LGdldFZpZGVvRGF0YTpmdW5jdGlvbihhLGIpe1widXNlIHN0cmljdFwiO3ZhciBjLGQsZT10aGlzLGY9YS5QZXJpb2RfYXNBcnJheVtiXS5BZGFwdGF0aW9uU2V0X2FzQXJyYXksZz1RLmRlZmVyKCksaD1bXTtmb3IoYz0wLGQ9Zi5sZW5ndGg7ZD5jO2MrPTEpaC5wdXNoKHRoaXMuZ2V0SXNWaWRlbyhmW2NdKSk7cmV0dXJuIFEuYWxsKGgpLnRoZW4oZnVuY3Rpb24oYSl7dmFyIGI9ITE7Zm9yKGM9MCxkPWEubGVuZ3RoO2Q+YztjKz0xKWFbY109PT0hMCYmKGI9ITAsZy5yZXNvbHZlKGUucHJvY2Vzc0FkYXB0YXRpb24oZltjXSkpKTtifHxnLnJlc29sdmUobnVsbCl9KSxnLnByb21pc2V9LGdldFRleHREYXRhOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7dmFyIGMsZCxlPXRoaXMsZj1hLlBlcmlvZF9hc0FycmF5W2JdLkFkYXB0YXRpb25TZXRfYXNBcnJheSxnPVEuZGVmZXIoKSxoPVtdO2ZvcihjPTAsZD1mLmxlbmd0aDtkPmM7Yys9MSloLnB1c2godGhpcy5nZXRJc1RleHQoZltjXSkpO3JldHVybiBRLmFsbChoKS50aGVuKGZ1bmN0aW9uKGEpe3ZhciBiPSExO2ZvcihjPTAsZD1hLmxlbmd0aDtkPmM7Yys9MSlhW2NdPT09ITAmJihiPSEwLGcucmVzb2x2ZShlLnByb2Nlc3NBZGFwdGF0aW9uKGZbY10pKSk7Ynx8Zy5yZXNvbHZlKG51bGwpfSksZy5wcm9taXNlfSxnZXRBdWRpb0RhdGFzOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7dmFyIGMsZCxlPXRoaXMsZj1hLlBlcmlvZF9hc0FycmF5W2JdLkFkYXB0YXRpb25TZXRfYXNBcnJheSxnPVEuZGVmZXIoKSxoPVtdO2ZvcihjPTAsZD1mLmxlbmd0aDtkPmM7Yys9MSloLnB1c2godGhpcy5nZXRJc0F1ZGlvKGZbY10pKTtyZXR1cm4gUS5hbGwoaCkudGhlbihmdW5jdGlvbihhKXt2YXIgYj1bXTtmb3IoYz0wLGQ9YS5sZW5ndGg7ZD5jO2MrPTEpYVtjXT09PSEwJiZiLnB1c2goZS5wcm9jZXNzQWRhcHRhdGlvbihmW2NdKSk7Zy5yZXNvbHZlKGIpfSksZy5wcm9taXNlfSxnZXRQcmltYXJ5QXVkaW9EYXRhOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7dmFyIGMsZCxlPVEuZGVmZXIoKSxmPVtdLGc9dGhpcztyZXR1cm4gdGhpcy5nZXRBdWRpb0RhdGFzKGEsYikudGhlbihmdW5jdGlvbihhKXtmb3IoYSYmMCE9PWEubGVuZ3RofHxlLnJlc29sdmUobnVsbCksYz0wLGQ9YS5sZW5ndGg7ZD5jO2MrPTEpZi5wdXNoKGcuZ2V0SXNNYWluKGFbY10pKTtRLmFsbChmKS50aGVuKGZ1bmN0aW9uKGIpe3ZhciBmPSExO2ZvcihjPTAsZD1iLmxlbmd0aDtkPmM7Yys9MSliW2NdPT09ITAmJihmPSEwLGUucmVzb2x2ZShnLnByb2Nlc3NBZGFwdGF0aW9uKGFbY10pKSk7Znx8ZS5yZXNvbHZlKGFbMF0pfSl9KSxlLnByb21pc2V9LGdldENvZGVjOmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3ZhciBiPWEuUmVwcmVzZW50YXRpb25fYXNBcnJheVswXSxjPWIubWltZVR5cGUrJztjb2RlY3M9XCInK2IuY29kZWNzKydcIic7cmV0dXJuIFEud2hlbihjKX0sZ2V0TWltZVR5cGU6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIFEud2hlbihhLlJlcHJlc2VudGF0aW9uX2FzQXJyYXlbMF0ubWltZVR5cGUpfSxnZXRLSUQ6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIGEmJmEuaGFzT3duUHJvcGVydHkoXCJjZW5jOmRlZmF1bHRfS0lEXCIpP2FbXCJjZW5jOmRlZmF1bHRfS0lEXCJdOm51bGx9LGdldENvbnRlbnRQcm90ZWN0aW9uRGF0YTpmdW5jdGlvbihhKXtcInVzZSBzdHJpY3RcIjtyZXR1cm4gYSYmYS5oYXNPd25Qcm9wZXJ0eShcIkNvbnRlbnRQcm90ZWN0aW9uX2FzQXJyYXlcIikmJjAhPT1hLkNvbnRlbnRQcm90ZWN0aW9uX2FzQXJyYXkubGVuZ3RoP1Eud2hlbihhLkNvbnRlbnRQcm90ZWN0aW9uX2FzQXJyYXkpOlEud2hlbihudWxsKX0sZ2V0U2VnbWVudEluZm9Gb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50QmFzZVwiKT9hLlNlZ21lbnRCYXNlOmEuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50TGlzdFwiKT9hLlNlZ21lbnRMaXN0OmEuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50VGVtcGxhdGVcIik/YS5TZWdtZW50VGVtcGxhdGU6bnVsbH0sZ2V0TGl2ZU9mZnNldDpmdW5jdGlvbihhKXtcInVzZSBzdHJpY3RcIjt2YXIgYj0xNTtyZXR1cm4gYS5oYXNPd25Qcm9wZXJ0eShcInN1Z2dlc3RlZFByZXNlbnRhdGlvbkRlbGF5XCIpJiYoYj1hLnN1Z2dlc3RlZFByZXNlbnRhdGlvbkRlbGF5KSxRLndoZW4oYil9LGdldExpdmVTdGFydDpmdW5jdGlvbihhLGIpe3ZhciBjLGQsZT0wLGY9MSxnPTEsaD1udWxsLGk9bnVsbDtyZXR1cm4gZD1hLlBlcmlvZF9hc0FycmF5W2JdLkFkYXB0YXRpb25TZXRfYXNBcnJheVsxXS5SZXByZXNlbnRhdGlvbl9hc0FycmF5WzBdLGQuaGFzT3duUHJvcGVydHkoXCJTZWdtZW50TGlzdFwiKT8oaD1kLlNlZ21lbnRMaXN0LGguaGFzT3duUHJvcGVydHkoXCJzdGFydE51bWJlclwiKSYmKGY9TWF0aC5tYXgoaC5zdGFydE51bWJlciwxKSksaC5oYXNPd25Qcm9wZXJ0eShcInRpbWVzY2FsZVwiKSYmKGc9aC50aW1lc2NhbGUpLGM9aC5kdXJhdGlvbixlPShmLTEpKmMvZyk6ZC5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUZW1wbGF0ZVwiKSYmKGk9ZC5TZWdtZW50VGVtcGxhdGUsaS5oYXNPd25Qcm9wZXJ0eShcInN0YXJ0TnVtYmVyXCIpJiYoZj1NYXRoLm1heChpLnN0YXJ0TnVtYmVyLDEpKSxpLmhhc093blByb3BlcnR5KFwidGltZXNjYWxlXCIpJiYoZz1pLnRpbWVzY2FsZSksYz1pLmR1cmF0aW9uLGU9aS5oYXNPd25Qcm9wZXJ0eShcIlNlZ21lbnRUaW1lbGluZVwiKT9pLlNlZ21lbnRUaW1lbGluZS5TX2FzQXJyYXlbMF0udC9nOihmLTEpKmMvZyksUS53aGVuKGUpfSxnZXRMaXZlRWRnZTpmdW5jdGlvbihhLGIpe1widXNlIHN0cmljdFwiO3ZhciBjLGQ9dGhpcyxlPVEuZGVmZXIoKSxmPTAsZz1uZXcgRGF0ZSxoPWEuYXZhaWxhYmlsaXR5U3RhcnRUaW1lO3JldHVybiBkLmdldExpdmVPZmZzZXQoYSkudGhlbihmdW5jdGlvbihpKXthLmhhc093blByb3BlcnR5KFwiYXZhaWxhYmlsaXR5RW5kVGltZVwiKT8oYz1hLmF2YWlsYWJpbGl0eUVuZFRpbWUsZj0oYy5nZXRUaW1lKCktaC5nZXRUaW1lKCkpLzFlMyk6Zj0oZy5nZXRUaW1lKCktaC5nZXRUaW1lKCkpLzFlMyxkLmdldExpdmVTdGFydChhLGIpLnRoZW4oZnVuY3Rpb24oYSl7Zis9YSxmLT1pLGUucmVzb2x2ZShmKX0pfSksZS5wcm9taXNlfSxnZXRQcmVzZW50YXRpb25PZmZzZXQ6ZnVuY3Rpb24oYSxiKXt2YXIgYyxkLGU9dGhpcyxmPVEuZGVmZXIoKSxnPTAsaD0xO3JldHVybiBlLmdldFJlcHJlc2VudGF0aW9uRm9yKGEsYikudGhlbihmdW5jdGlvbihhKXtkPWUuZ2V0U2VnbWVudEluZm9Gb3IoYSksbnVsbCE9PWQmJnZvaWQgMCE9PWQmJmQuaGFzT3duUHJvcGVydHkoXCJwcmVzZW50YXRpb25UaW1lT2Zmc2V0XCIpJiYoYz1kLnByZXNlbnRhdGlvblRpbWVPZmZzZXQsZC5oYXNPd25Qcm9wZXJ0eShcInRpbWVzY2FsZVwiKSYmKGg9ZC50aW1lc2NhbGUpLGc9Yy9oKSxmLnJlc29sdmUoZyl9KSxmLnByb21pc2V9LGdldElzTGl2ZTpmdW5jdGlvbihhKXtcInVzZSBzdHJpY3RcIjt2YXIgYj0hMSxjPVwiZHluYW1pY1wiO3JldHVybiBhLmhhc093blByb3BlcnR5KFwidHlwZVwiKSYmKGI9YS50eXBlPT09YyksYn0sZ2V0SXNEVlI6ZnVuY3Rpb24oYSxiKXtcInVzZSBzdHJpY3RcIjt2YXIgYyxkO3JldHVybiBjPSFpc05hTihhLnRpbWVTaGlmdEJ1ZmZlckRlcHRoKSxkPWImJmMsUS53aGVuKGQpfSxnZXRJc09uRGVtYW5kOmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3ZhciBiPSExO3JldHVybiBhLnByb2ZpbGVzJiZhLnByb2ZpbGVzLmxlbmd0aD4wJiYoYj0tMSE9PWEucHJvZmlsZXMuaW5kZXhPZihcInVybjptcGVnOmRhc2g6cHJvZmlsZTppc29mZi1vbi1kZW1hbmQ6MjAxMVwiKSksUS53aGVuKGIpfSxnZXREdXJhdGlvbjpmdW5jdGlvbihhLGIpe1widXNlIHN0cmljdFwiO3ZhciBjPTAvMDtyZXR1cm4gYj9jPU51bWJlci5QT1NJVElWRV9JTkZJTklUWTphLm1lZGlhUHJlc2VudGF0aW9uRHVyYXRpb24/Yz1hLm1lZGlhUHJlc2VudGF0aW9uRHVyYXRpb246YS5hdmFpbGFiaWxpdHlFbmRUaW1lJiZhLmF2YWlsYWJpbGl0eVN0YXJ0VGltZSYmKGM9YS5hdmFpbGFiaWxpdHlFbmRUaW1lLmdldFRpbWUoKS1hLmF2YWlsYWJpbGl0eVN0YXJ0VGltZS5nZXRUaW1lKCkpLFEud2hlbihjKX0sZ2V0RHVyYXRpb25Gb3JQZXJpb2Q6ZnVuY3Rpb24oYSxiLGMpe1widXNlIHN0cmljdFwiO3ZhciBkPTAvMDtyZXR1cm4gYz9kPU51bWJlci5QT1NJVElWRV9JTkZJTklUWTpiLlBlcmlvZF9hc0FycmF5Lmxlbmd0aD4xJiZ2b2lkIDAhPT1iLlBlcmlvZF9hc0FycmF5W2FdLmR1cmF0aW9uP2Q9Yi5QZXJpb2RfYXNBcnJheVthXS5kdXJhdGlvbjpiLm1lZGlhUHJlc2VudGF0aW9uRHVyYXRpb24/ZD1iLm1lZGlhUHJlc2VudGF0aW9uRHVyYXRpb246Yi5hdmFpbGFiaWxpdHlFbmRUaW1lJiZiLmF2YWlsYWJpbGl0eVN0YXJ0VGltZSYmKGQ9Yi5hdmFpbGFiaWxpdHlFbmRUaW1lLmdldFRpbWUoKS1iLmF2YWlsYWJpbGl0eVN0YXJ0VGltZS5nZXRUaW1lKCkpLFEud2hlbihkKX0sZ2V0QmFuZHdpZHRoOmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3JldHVybiBRLndoZW4oYS5iYW5kd2lkdGgpfSxnZXRSZWZyZXNoRGVsYXk6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGI9MC8wO3JldHVybiBhLmhhc093blByb3BlcnR5KFwibWluaW11bVVwZGF0ZVBlcmlvZFwiKSYmKGI9cGFyc2VGbG9hdChhLm1pbmltdW1VcGRhdGVQZXJpb2QpKSxRLndoZW4oYil9LGdldFJlcHJlc2VudGF0aW9uQ291bnQ6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIFEud2hlbihhLlJlcHJlc2VudGF0aW9uX2FzQXJyYXkubGVuZ3RoKX0sZ2V0UmVwcmVzZW50YXRpb25Gb3I6ZnVuY3Rpb24oYSxiKXtcInVzZSBzdHJpY3RcIjtyZXR1cm4gUS53aGVuKGIuUmVwcmVzZW50YXRpb25fYXNBcnJheVthXSl9LGdldFBlcmlvZENvdW50OmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3JldHVybiBRLndoZW4oYS5QZXJpb2RfYXNBcnJheS5sZW5ndGgpfSxnZXRUaW1lc3RhbXBPZmZzZXRGb3JQZXJpb2Q6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGUsZj10aGlzLGc9US5kZWZlcigpO3JldHVybiBmLmdldFByZXNlbnRhdGlvbk9mZnNldChjLGQpLnRoZW4oZnVuY3Rpb24oYyl7Zi5nZXRQZXJpb2RTdGFydChiLGEpLnRoZW4oZnVuY3Rpb24oYSl7ZT1hLWMsZy5yZXNvbHZlKGUpfSl9KSxnLnByb21pc2V9LGdldFBlcmlvZFN0YXJ0OmZ1bmN0aW9uKGEsYil7dmFyIGMsZCxlPXRoaXMsZj1lLmdldElzTGl2ZShhKSxnPW51bGwsaD1udWxsLGk9bnVsbDtmb3IoYz0wO2I+PWM7Yys9MSlnPWEuUGVyaW9kX2FzQXJyYXlbY10sZy5oYXNPd25Qcm9wZXJ0eShcInN0YXJ0XCIpP2Q9Zy5zdGFydDpudWxsIT09aCYmbnVsbCE9PWk/ZD1oK2k6MCE9PWN8fGZ8fChkPTApLGcuaGFzT3duUHJvcGVydHkoXCJkdXJhdGlvblwiKSYmKGk9Zy5kdXJhdGlvbiksaD1kO3JldHVybiBRLndoZW4oZCl9fSxEYXNoLmRlcGVuZGVuY2llcy5EYXNoTWV0cmljc0V4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT1mdW5jdGlvbihhLGIpe3ZhciBjLGQsZSxmLGcsaCxpLGo7Zm9yKGg9MDtoPGEubGVuZ3RoO2grPTEpZm9yKGM9YVtoXSxlPWMuQWRhcHRhdGlvblNldF9hc0FycmF5LGk9MDtpPGUubGVuZ3RoO2krPTEpZm9yKGQ9ZVtpXSxnPWQuUmVwcmVzZW50YXRpb25fYXNBcnJheSxqPTA7ajxnLmxlbmd0aDtqKz0xKWlmKGY9Z1tqXSxiPT09Zi5pZClyZXR1cm4gajtyZXR1cm4tMX0sYj1mdW5jdGlvbihhLGIpe3ZhciBjLGQsZSxmLGcsaCxpLGo7Zm9yKGg9MDtoPGEubGVuZ3RoO2grPTEpZm9yKGM9YVtoXSxlPWMuQWRhcHRhdGlvblNldF9hc0FycmF5LGk9MDtpPGUubGVuZ3RoO2krPTEpZm9yKGQ9ZVtpXSxnPWQuUmVwcmVzZW50YXRpb25fYXNBcnJheSxqPTA7ajxnLmxlbmd0aDtqKz0xKWlmKGY9Z1tqXSxiPT09Zi5pZClyZXR1cm4gZjtyZXR1cm4gbnVsbH0sYz1mdW5jdGlvbihhLGIpe3ZhciBjPSExO3JldHVyblwidmlkZW9cIj09PWI/KHRoaXMubWFuaWZlc3RFeHQuZ2V0SXNWaWRlbyhhKSxcInZpZGVvXCI9PT1hLnR5cGUmJihjPSEwKSk6XCJhdWRpb1wiPT09Yj8odGhpcy5tYW5pZmVzdEV4dC5nZXRJc0F1ZGlvKGEpLFwiYXVkaW9cIj09PWEudHlwZSYmKGM9ITApKTpjPSExLGN9LGQ9ZnVuY3Rpb24oYSxiKXt2YXIgZCxlLGYsZyxoLGk7Zm9yKGg9MDtoPGEubGVuZ3RoO2grPTEpZm9yKGQ9YVtoXSxmPWQuQWRhcHRhdGlvblNldF9hc0FycmF5LGk9MDtpPGYubGVuZ3RoO2krPTEpaWYoZT1mW2ldLGc9ZS5SZXByZXNlbnRhdGlvbl9hc0FycmF5LGMuY2FsbCh0aGlzLGUsYikpcmV0dXJuIGcubGVuZ3RoO3JldHVybi0xfSxlPWZ1bmN0aW9uKGEpe3ZhciBjLGQ9dGhpcyxlPWQubWFuaWZlc3RNb2RlbC5nZXRWYWx1ZSgpLGY9ZS5QZXJpb2RfYXNBcnJheTtyZXR1cm4gYz1iLmNhbGwoZCxmLGEpLG51bGw9PT1jP251bGw6Yy5iYW5kd2lkdGh9LGY9ZnVuY3Rpb24oYil7dmFyIGMsZD10aGlzLGU9ZC5tYW5pZmVzdE1vZGVsLmdldFZhbHVlKCksZj1lLlBlcmlvZF9hc0FycmF5O3JldHVybiBjPWEuY2FsbChkLGYsYil9LGc9ZnVuY3Rpb24oYSl7dmFyIGIsYz10aGlzLGU9Yy5tYW5pZmVzdE1vZGVsLmdldFZhbHVlKCksZj1lLlBlcmlvZF9hc0FycmF5O3JldHVybiBiPWQuY2FsbCh0aGlzLGYsYSl9LGg9ZnVuY3Rpb24oYSl7aWYobnVsbD09PWEpcmV0dXJuIG51bGw7dmFyIGIsYyxkLGU9YS5SZXBTd2l0Y2hMaXN0O3JldHVybiBudWxsPT09ZXx8ZS5sZW5ndGg8PTA/bnVsbDooYj1lLmxlbmd0aCxjPWItMSxkPWVbY10pfSxpPWZ1bmN0aW9uKGEpe2lmKG51bGw9PT1hKXJldHVybiBudWxsO3ZhciBiLGMsZCxlPWEuQnVmZmVyTGV2ZWw7cmV0dXJuIG51bGw9PT1lfHxlLmxlbmd0aDw9MD9udWxsOihiPWUubGVuZ3RoLGM9Yi0xLGQ9ZVtjXSl9LGo9ZnVuY3Rpb24oYSl7aWYobnVsbD09PWEpcmV0dXJuIG51bGw7dmFyIGIsYyxkLGU9YS5IdHRwTGlzdDtyZXR1cm4gbnVsbD09PWV8fGUubGVuZ3RoPD0wP251bGw6KGI9ZS5sZW5ndGgsYz1iLTEsZD1lW2NdKX0saz1mdW5jdGlvbihhKXtpZihudWxsPT09YSlyZXR1cm4gbnVsbDt2YXIgYixjLGQsZT1hLkRyb3BwZWRGcmFtZXM7cmV0dXJuIG51bGw9PT1lfHxlLmxlbmd0aDw9MD9udWxsOihiPWUubGVuZ3RoLGM9Yi0xLGQ9ZVtjXSl9O3JldHVybnttYW5pZmVzdE1vZGVsOnZvaWQgMCxtYW5pZmVzdEV4dDp2b2lkIDAsZ2V0QmFuZHdpZHRoRm9yUmVwcmVzZW50YXRpb246ZSxnZXRJbmRleEZvclJlcHJlc2VudGF0aW9uOmYsZ2V0TWF4SW5kZXhGb3JCdWZmZXJUeXBlOmcsZ2V0Q3VycmVudFJlcHJlc2VudGF0aW9uU3dpdGNoOmgsZ2V0Q3VycmVudEJ1ZmZlckxldmVsOmksZ2V0Q3VycmVudEh0dHBSZXF1ZXN0OmosZ2V0Q3VycmVudERyb3BwZWRGcmFtZXM6a319LERhc2guZGVwZW5kZW5jaWVzLkRhc2hNZXRyaWNzRXh0ZW5zaW9ucy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOkRhc2guZGVwZW5kZW5jaWVzLkRhc2hNZXRyaWNzRXh0ZW5zaW9uc30sRGFzaC5kZXBlbmRlbmNpZXMuRGFzaFBhcnNlcj1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPTMxNTM2ZTMsYj0yNTkyZTMsYz04NjQwMCxkPTM2MDAsZT02MCxmPS9eUCgoW1xcZC5dKilZKT8oKFtcXGQuXSopTSk/KChbXFxkLl0qKUQpP1QoKFtcXGQuXSopSCk/KChbXFxkLl0qKU0pPygoW1xcZC5dKilTKT8vLGc9L14oXFxkezR9XFwtXFxkXFxkXFwtXFxkXFxkKFt0VF1bXFxkOlxcLl0qKT8pKFt6Wl18KFsrXFwtXSkoXFxkXFxkKTooXFxkXFxkKSk/JC8saD0vXlstK10/WzAtOV0rWy5dP1swLTldKihbZUVdWy0rXT9bMC05XSspPyQvLGk9W3t0eXBlOlwiZHVyYXRpb25cIix0ZXN0OmZ1bmN0aW9uKGEpe3JldHVybiBmLnRlc3QoYSl9LGNvbnZlcnRlcjpmdW5jdGlvbihnKXt2YXIgaD1mLmV4ZWMoZyk7cmV0dXJuIHBhcnNlRmxvYXQoaFsyXXx8MCkqYStwYXJzZUZsb2F0KGhbNF18fDApKmIrcGFyc2VGbG9hdChoWzZdfHwwKSpjK3BhcnNlRmxvYXQoaFs4XXx8MCkqZCtwYXJzZUZsb2F0KGhbMTBdfHwwKSplK3BhcnNlRmxvYXQoaFsxMl18fDApfX0se3R5cGU6XCJkYXRldGltZVwiLHRlc3Q6ZnVuY3Rpb24oYSl7cmV0dXJuIGcudGVzdChhKX0sY29udmVydGVyOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgRGF0ZShhKX19LHt0eXBlOlwibnVtZXJpY1wiLHRlc3Q6ZnVuY3Rpb24oYSl7cmV0dXJuIGgudGVzdChhKX0sY29udmVydGVyOmZ1bmN0aW9uKGEpe3JldHVybiBwYXJzZUZsb2F0KGEpfX1dLGo9ZnVuY3Rpb24oKXt2YXIgYSxiLGMsZDtyZXR1cm4gZD1be25hbWU6XCJwcm9maWxlc1wiLG1lcmdlOiExfSx7bmFtZTpcIndpZHRoXCIsbWVyZ2U6ITF9LHtuYW1lOlwiaGVpZ2h0XCIsbWVyZ2U6ITF9LHtuYW1lOlwic2FyXCIsbWVyZ2U6ITF9LHtuYW1lOlwiZnJhbWVSYXRlXCIsbWVyZ2U6ITF9LHtuYW1lOlwiYXVkaW9TYW1wbGluZ1JhdGVcIixtZXJnZTohMX0se25hbWU6XCJtaW1lVHlwZVwiLG1lcmdlOiExfSx7bmFtZTpcInNlZ21lbnRQcm9maWxlc1wiLG1lcmdlOiExfSx7bmFtZTpcImNvZGVjc1wiLG1lcmdlOiExfSx7bmFtZTpcIm1heGltdW1TQVBQZXJpb2RcIixtZXJnZTohMX0se25hbWU6XCJzdGFydHNXaXRoU2FwXCIsbWVyZ2U6ITF9LHtuYW1lOlwibWF4UGxheW91dFJhdGVcIixtZXJnZTohMX0se25hbWU6XCJjb2RpbmdEZXBlbmRlbmN5XCIsbWVyZ2U6ITF9LHtuYW1lOlwic2NhblR5cGVcIixtZXJnZTohMX0se25hbWU6XCJGcmFtZVBhY2tpbmdcIixtZXJnZTohMH0se25hbWU6XCJBdWRpb0NoYW5uZWxDb25maWd1cmF0aW9uXCIsbWVyZ2U6ITB9LHtuYW1lOlwiQ29udGVudFByb3RlY3Rpb25cIixtZXJnZTohMH1dLGE9e30sYS5uYW1lPVwiQWRhcHRhdGlvblNldFwiLGEuaXNSb290PSExLGEuaXNBcnJheT0hMCxhLnBhcmVudD1udWxsLGEuY2hpbGRyZW49W10sYS5wcm9wZXJ0aWVzPWQsYj17fSxiLm5hbWU9XCJSZXByZXNlbnRhdGlvblwiLGIuaXNSb290PSExLGIuaXNBcnJheT0hMCxiLnBhcmVudD1hLGIuY2hpbGRyZW49W10sYi5wcm9wZXJ0aWVzPWQsYS5jaGlsZHJlbi5wdXNoKGIpLGM9e30sYy5uYW1lPVwiU3ViUmVwcmVzZW50YXRpb25cIixjLmlzUm9vdD0hMSxjLmlzQXJyYXk9ITAsYy5wYXJlbnQ9YixjLmNoaWxkcmVuPVtdLGMucHJvcGVydGllcz1kLGIuY2hpbGRyZW4ucHVzaChjKSxhfSxrPWZ1bmN0aW9uKCl7dmFyIGEsYixjLGQ7cmV0dXJuIGQ9W3tuYW1lOlwiU2VnbWVudEJhc2VcIixtZXJnZTohMH0se25hbWU6XCJTZWdtZW50VGVtcGxhdGVcIixtZXJnZTohMH0se25hbWU6XCJTZWdtZW50TGlzdFwiLG1lcmdlOiEwfV0sYT17fSxhLm5hbWU9XCJQZXJpb2RcIixhLmlzUm9vdD0hMSxhLmlzQXJyYXk9ITAsYS5wYXJlbnQ9bnVsbCxhLmNoaWxkcmVuPVtdLGEucHJvcGVydGllcz1kLGI9e30sYi5uYW1lPVwiQWRhcHRhdGlvblNldFwiLGIuaXNSb290PSExLGIuaXNBcnJheT0hMCxiLnBhcmVudD1hLGIuY2hpbGRyZW49W10sYi5wcm9wZXJ0aWVzPWQsYS5jaGlsZHJlbi5wdXNoKGIpLGM9e30sYy5uYW1lPVwiUmVwcmVzZW50YXRpb25cIixjLmlzUm9vdD0hMSxjLmlzQXJyYXk9ITAsYy5wYXJlbnQ9YixjLmNoaWxkcmVuPVtdLGMucHJvcGVydGllcz1kLGIuY2hpbGRyZW4ucHVzaChjKSxhfSxsPWZ1bmN0aW9uKCl7dmFyIGEsYixjLGQsZTtyZXR1cm4gZT1be25hbWU6XCJCYXNlVVJMXCIsbWVyZ2U6ITAsbWVyZ2VGdW5jdGlvbjpmdW5jdGlvbihhLGIpe3ZhciBjO3JldHVybiBjPTA9PT1iLmluZGV4T2YoXCJodHRwOi8vXCIpP2I6YStifX1dLGE9e30sYS5uYW1lPVwibXBkXCIsYS5pc1Jvb3Q9ITAsYS5pc0FycmF5PSEwLGEucGFyZW50PW51bGwsYS5jaGlsZHJlbj1bXSxhLnByb3BlcnRpZXM9ZSxiPXt9LGIubmFtZT1cIlBlcmlvZFwiLGIuaXNSb290PSExLGIuaXNBcnJheT0hMCxiLnBhcmVudD1udWxsLGIuY2hpbGRyZW49W10sYi5wcm9wZXJ0aWVzPWUsYS5jaGlsZHJlbi5wdXNoKGIpLGM9e30sYy5uYW1lPVwiQWRhcHRhdGlvblNldFwiLGMuaXNSb290PSExLGMuaXNBcnJheT0hMCxjLnBhcmVudD1iLGMuY2hpbGRyZW49W10sYy5wcm9wZXJ0aWVzPWUsYi5jaGlsZHJlbi5wdXNoKGMpLGQ9e30sZC5uYW1lPVwiUmVwcmVzZW50YXRpb25cIixkLmlzUm9vdD0hMSxkLmlzQXJyYXk9ITAsZC5wYXJlbnQ9YyxkLmNoaWxkcmVuPVtdLGQucHJvcGVydGllcz1lLGMuY2hpbGRyZW4ucHVzaChkKSxhfSxtPWZ1bmN0aW9uKCl7dmFyIGE9W107cmV0dXJuIGEucHVzaChqKCkpLGEucHVzaChrKCkpLGEucHVzaChsKCkpLGF9LG49ZnVuY3Rpb24oYSxiKXt0aGlzLmRlYnVnLmxvZyhcIkRvaW5nIHBhcnNlLlwiKTt2YXIgYyxkPW5ldyBYMkpTKGksXCJcIiwhMCksZT1uZXcgT2JqZWN0SXJvbihtKCkpO3RyeXt0aGlzLmRlYnVnLmxvZyhcIkNvbnZlcnRpbmcgZnJvbSBYTUwuXCIpLGM9ZC54bWxfc3RyMmpzb24oYSksYy5oYXNPd25Qcm9wZXJ0eShcIkJhc2VVUkxcIik/KGMuQmFzZVVSTD1jLkJhc2VVUkxfYXNBcnJheVswXSwwIT09Yy5CYXNlVVJMLnRvU3RyaW5nKCkuaW5kZXhPZihcImh0dHBcIikmJihjLkJhc2VVUkw9YitjLkJhc2VVUkwpKToodGhpcy5kZWJ1Zy5sb2coXCJTZXR0aW5nIGJhc2VVUkw6IFwiK2IpLGMuQmFzZVVSTD1iKSx0aGlzLmRlYnVnLmxvZyhcIkZsYXR0ZW4gbWFuaWZlc3QgcHJvcGVydGllcy5cIiksZS5ydW4oYyksdGhpcy5kZWJ1Zy5sb2coXCJQYXJzaW5nIGNvbXBsZXRlLlwiKX1jYXRjaChmKXtyZXR1cm4gdGhpcy5lcnJIYW5kbGVyLm1hbmlmZXN0RXJyb3IoXCJwYXJzaW5nIHRoZSBtYW5pZmVzdCBmYWlsZWRcIixcInBhcnNlXCIsYSksUS5yZWplY3QoZil9cmV0dXJuIFEud2hlbihjKX07cmV0dXJue2RlYnVnOnZvaWQgMCxlcnJIYW5kbGVyOnZvaWQgMCxwYXJzZTpufX0sRGFzaC5kZXBlbmRlbmNpZXMuRGFzaFBhcnNlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOkRhc2guZGVwZW5kZW5jaWVzLkRhc2hQYXJzZXJ9LERhc2guZGVwZW5kZW5jaWVzLkZyYWdtZW50RXh0ZW5zaW9ucz1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPWZ1bmN0aW9uKGEpe2Zvcih2YXIgYixjLGQsZSxmLGcsaD1RLmRlZmVyKCksaT1uZXcgRGF0YVZpZXcoYSksaj0wO1widGZkdFwiIT09ZSYmajxpLmJ5dGVMZW5ndGg7KXtmb3IoZD1pLmdldFVpbnQzMihqKSxqKz00LGU9XCJcIixmPTA7ND5mO2YrPTEpZz1pLmdldEludDgoaiksZSs9U3RyaW5nLmZyb21DaGFyQ29kZShnKSxqKz0xO1wibW9vZlwiIT09ZSYmXCJ0cmFmXCIhPT1lJiZcInRmZHRcIiE9PWUmJihqKz1kLTgpfWlmKGo9PT1pLmJ5dGVMZW5ndGgpdGhyb3dcIkVycm9yIGZpbmRpbmcgbGl2ZSBvZmZzZXQuXCI7cmV0dXJuIGM9aS5nZXRVaW50OChqKSx0aGlzLmRlYnVnLmxvZyhcInBvc2l0aW9uOiBcIitqKSwwPT09Yz8oais9NCxiPWkuZ2V0VWludDMyKGosITEpKTooais9ZC0xNixiPXV0aWxzLk1hdGgudG82NEJpdE51bWJlcihpLmdldFVpbnQzMihqKzQsITEpLGkuZ2V0VWludDMyKGosITEpKSksaC5yZXNvbHZlKHt2ZXJzaW9uOmMsYmFzZV9tZWRpYV9kZWNvZGVfdGltZTpifSksaC5wcm9taXNlfSxiPWZ1bmN0aW9uKGEpe2Zvcih2YXIgYixjLGQsZSxmLGcsaCxpPW5ldyBEYXRhVmlldyhhKSxqPTA7XCJzaWR4XCIhPT1mJiZqPGkuYnl0ZUxlbmd0aDspe2ZvcihnPWkuZ2V0VWludDMyKGopLGorPTQsZj1cIlwiLGU9MDs0PmU7ZSs9MSloPWkuZ2V0SW50OChqKSxmKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGgpLGorPTE7XCJtb29mXCIhPT1mJiZcInRyYWZcIiE9PWYmJlwic2lkeFwiIT09Zj9qKz1nLTg6XCJzaWR4XCI9PT1mJiYoai09OCl9cmV0dXJuIGI9aS5nZXRVaW50OChqKzgpLGorPTEyLGM9aS5nZXRVaW50MzIoais0LCExKSxqKz04LGQ9MD09PWI/aS5nZXRVaW50MzIoaiwhMSk6dXRpbHMuTWF0aC50bzY0Qml0TnVtYmVyKGkuZ2V0VWludDMyKGorNCwhMSksaS5nZXRVaW50MzIoaiwhMSkpLFEud2hlbih7ZWFybGllc3RQcmVzZW50YXRpb25UaW1lOmQsdGltZXNjYWxlOmN9KX0sYz1mdW5jdGlvbihiKXt2YXIgYyxkLGUsZj1RLmRlZmVyKCksZz1uZXcgWE1MSHR0cFJlcXVlc3QsaD0hMTtyZXR1cm4gYz1iLGcub25sb2FkZW5kPWZ1bmN0aW9uKCl7aHx8KGQ9XCJFcnJvciBsb2FkaW5nIGZyYWdtZW50OiBcIitjLGYucmVqZWN0KGQpKX0sZy5vbmxvYWQ9ZnVuY3Rpb24oKXtoPSEwLGU9YShnLnJlc3BvbnNlKSxmLnJlc29sdmUoZSl9LGcub25lcnJvcj1mdW5jdGlvbigpe2Q9XCJFcnJvciBsb2FkaW5nIGZyYWdtZW50OiBcIitjLGYucmVqZWN0KGQpfSxnLnJlc3BvbnNlVHlwZT1cImFycmF5YnVmZmVyXCIsZy5vcGVuKFwiR0VUXCIsYyksZy5zZW5kKG51bGwpLGYucHJvbWlzZX07cmV0dXJue2RlYnVnOnZvaWQgMCxsb2FkRnJhZ21lbnQ6YyxwYXJzZVRGRFQ6YSxwYXJzZVNJRFg6Yn19LERhc2guZGVwZW5kZW5jaWVzLkZyYWdtZW50RXh0ZW5zaW9ucy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOkRhc2guZGVwZW5kZW5jaWVzLkZyYWdtZW50RXh0ZW5zaW9uc30sRGFzaC52by5TZWdtZW50PWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dGhpcy5pbmRleFJhbmdlPW51bGwsdGhpcy5pbmRleD1udWxsLHRoaXMubWVkaWFSYW5nZT1udWxsLHRoaXMubWVkaWE9bnVsbCx0aGlzLmR1cmF0aW9uPTAvMCx0aGlzLnN0YXJ0VGltZT0wLzAsdGhpcy50aW1lc2NhbGU9MC8wfSxEYXNoLnZvLlNlZ21lbnQucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpEYXNoLnZvLlNlZ21lbnR9LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5BYnJDb250cm9sbGVyPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9ITAsYj17fSxjPXt9LGQ9ZnVuY3Rpb24oYSl7dmFyIGM7cmV0dXJuIGIuaGFzT3duUHJvcGVydHkoYSl8fChiW2FdPTApLGM9YlthXX0sZT1mdW5jdGlvbihhLGMpe2JbYV09Y30sZj1mdW5jdGlvbihhKXt2YXIgYjtyZXR1cm4gYy5oYXNPd25Qcm9wZXJ0eShhKXx8KGNbYV09MCksYj1jW2FdfSxnPWZ1bmN0aW9uKGEsYil7Y1thXT1ifTtyZXR1cm57ZGVidWc6dm9pZCAwLGFiclJ1bGVzQ29sbGVjdGlvbjp2b2lkIDAsbWFuaWZlc3RFeHQ6dm9pZCAwLG1ldHJpY3NNb2RlbDp2b2lkIDAsZ2V0QXV0b1N3aXRjaEJpdHJhdGU6ZnVuY3Rpb24oKXtyZXR1cm4gYX0sc2V0QXV0b1N3aXRjaEJpdHJhdGU6ZnVuY3Rpb24oYil7YT1ifSxnZXRNZXRyaWNzRm9yOmZ1bmN0aW9uKGEpe3ZhciBiPVEuZGVmZXIoKSxjPXRoaXM7cmV0dXJuIGMubWFuaWZlc3RFeHQuZ2V0SXNWaWRlbyhhKS50aGVuKGZ1bmN0aW9uKGQpe2Q/Yi5yZXNvbHZlKGMubWV0cmljc01vZGVsLmdldE1ldHJpY3NGb3IoXCJ2aWRlb1wiKSk6Yy5tYW5pZmVzdEV4dC5nZXRJc0F1ZGlvKGEpLnRoZW4oZnVuY3Rpb24oYSl7YT9iLnJlc29sdmUoYy5tZXRyaWNzTW9kZWwuZ2V0TWV0cmljc0ZvcihcImF1ZGlvXCIpKTpiLnJlc29sdmUoYy5tZXRyaWNzTW9kZWwuZ2V0TWV0cmljc0ZvcihcInN0cmVhbVwiKSl9KX0pLGIucHJvbWlzZX0sZ2V0UGxheWJhY2tRdWFsaXR5OmZ1bmN0aW9uKGIsYyl7dmFyIGgsaSxqLGssbCxtLG49dGhpcyxvPVEuZGVmZXIoKSxwPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLk5PX0NIQU5HRSxxPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLk5PX0NIQU5HRSxyPVtdO3JldHVybiBsPWQoYiksbT1mKGIpLG4uZGVidWcubG9nKFwiQUJSIGVuYWJsZWQ/IChcIithK1wiKVwiKSxhPyhuLmRlYnVnLmxvZyhcIkNoZWNrIEFCUiBydWxlcy5cIiksbi5nZXRNZXRyaWNzRm9yKGMpLnRoZW4oZnVuY3Rpb24oYSl7bi5hYnJSdWxlc0NvbGxlY3Rpb24uZ2V0UnVsZXMoKS50aGVuKGZ1bmN0aW9uKGQpe2ZvcihoPTAsaT1kLmxlbmd0aDtpPmg7aCs9MSlyLnB1c2goZFtoXS5jaGVja0luZGV4KGwsYSxjKSk7XHJcblEuYWxsKHIpLnRoZW4oZnVuY3Rpb24oYSl7Zm9yKG4uZGVidWcubG9nKGEpLGs9e30sa1tNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkddPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLk5PX0NIQU5HRSxrW01lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLldFQUtdPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLk5PX0NIQU5HRSxrW01lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLkRFRkFVTFRdPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLk5PX0NIQU5HRSxoPTAsaT1hLmxlbmd0aDtpPmg7aCs9MSlqPWFbaF0sai5xdWFsaXR5IT09TWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuTk9fQ0hBTkdFJiYoa1tqLnByaW9yaXR5XT1NYXRoLm1pbihrW2oucHJpb3JpdHldLGoucXVhbGl0eSkpO2tbTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuV0VBS10hPT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5OT19DSEFOR0UmJihxPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLldFQUsscD1rW01lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLldFQUtdKSxrW01lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLkRFRkFVTFRdIT09TWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuTk9fQ0hBTkdFJiYocT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5ERUZBVUxULHA9a1tNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5ERUZBVUxUXSksa1tNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkddIT09TWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuTk9fQ0hBTkdFJiYocT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkcscD1rW01lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLlNUUk9OR10pLHAhPT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5OT19DSEFOR0UmJnZvaWQgMCE9PXAmJihsPXApLHEhPT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5OT19DSEFOR0UmJnZvaWQgMCE9PXEmJihtPXEpLG4ubWFuaWZlc3RFeHQuZ2V0UmVwcmVzZW50YXRpb25Db3VudChjKS50aGVuKGZ1bmN0aW9uKGEpezA+bCYmKGw9MCksbD49YSYmKGw9YS0xKSxtIT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkcmJm0hPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLldFQUsmJihtPU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLkRFRkFVTFQpLGUoYixsKSxuLmRlYnVnLmxvZyhcIk5ldyBxdWFsaXR5IG9mIFwiK2wpLGcoYixtKSxuLmRlYnVnLmxvZyhcIk5ldyBjb25maWRlbmNlIG9mIFwiK20pLG8ucmVzb2x2ZSh7cXVhbGl0eTpsLGNvbmZpZGVuY2U6bX0pfSl9KX0pfSkpOihuLmRlYnVnLmxvZyhcIlVuY2hhbmdlZCBxdWFsaXR5IG9mIFwiK2wpLG8ucmVzb2x2ZSh7cXVhbGl0eTpsLGNvbmZpZGVuY2U6bX0pKSxvLnByb21pc2V9LHNldFBsYXliYWNrUXVhbGl0eTpmdW5jdGlvbihhLGIpe3ZhciBjPWQoYSk7YiE9PWMmJmUoYSxiKX0sZ2V0UXVhbGl0eUZvcjpmdW5jdGlvbihhKXtyZXR1cm4gZChhKX19fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQWJyQ29udHJvbGxlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5BYnJDb250cm9sbGVyfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyQ29udHJvbGxlcj1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhLGIsYyxkLGU9LjUsZj0yMixnPVwiV0FJVElOR1wiLGg9XCJSRUFEWVwiLGk9XCJWQUxJREFUSU5HXCIsaj1cIkxPQURJTkdcIixrPWcsbD0hMSxtPSExLG49ITEsbz0hMCxwPVtdLHE9ITEscj0tMSxzPSEwLHQ9LTEsdT0hMSx2PSExLHc9ITEseD0hMSx5PVtdLHo9bnVsbCxBPVEuZGVmZXIoKSxCPW51bGwsQz1udWxsLEQ9LTEsRT0wLEY9MCxHPW51bGwsSD0wLEk9ITEsSj1udWxsLEs9MCxMPSExLE09bnVsbCxOPW51bGwsTz1udWxsLFA9bnVsbCxSPSEwLFM9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcztiLmRlYnVnLmxvZyhcIkJ1ZmZlckNvbnRyb2xsZXIgXCIrYytcIiBzZXRTdGF0ZSB0bzpcIithKSxrPWEsbnVsbCE9PUcmJmIuZnJhZ21lbnRDb250cm9sbGVyLm9uQnVmZmVyQ29udHJvbGxlclN0YXRlQ2hhbmdlKCl9LFQ9ZnVuY3Rpb24oYSxiKXt2YXIgYz0wLGQ9bnVsbDtSPT09ITEmJihkPVAuc3RhcnQsYz1hLmdldFRpbWUoKS1kLmdldFRpbWUoKSxQLmR1cmF0aW9uPWMsUC5zdG9wcmVhc29uPWIsUj0hMCl9LFU9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSxiPXRoaXMubWFuaWZlc3RFeHQuZ2V0SXNMaXZlKGEpO3JldHVybiB3PSEwLFEud2hlbihiKX0sVj1mdW5jdGlvbigpe2lmKGwmJm0pe3ZhciBhPXRoaXM7VS5jYWxsKHRoaXMpLnRoZW4oZnVuY3Rpb24oYil7dj1iLGEuZGVidWcubG9nKFwiQnVmZmVyQ29udHJvbGxlciBiZWdpbiBcIitjK1wiIHZhbGlkYXRpb25cIiksUy5jYWxsKGEsaCksYS5yZXF1ZXN0U2NoZWR1bGVyLnN0YXJ0U2NoZWR1bGluZyhhLHJiKSxHPWEuZnJhZ21lbnRDb250cm9sbGVyLmF0dGFjaEJ1ZmZlckNvbnRyb2xsZXIoYSl9KX19LFc9ZnVuY3Rpb24oKXt2YXIgYTt0aGlzLnJlcXVlc3RTY2hlZHVsZXIuaXNTY2hlZHVsZWQodGhpcyl8fChxPT09ITEmJihhPW5ldyBEYXRlLFQoYSxNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlLlVTRVJfUkVRVUVTVF9TVE9QX1JFQVNPTiksTz10aGlzLm1ldHJpY3NNb2RlbC5hZGRQbGF5TGlzdChjLGEsMCxNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LklOSVRJQUxfUExBWV9TVEFSVF9SRUFTT04pKSx0aGlzLmRlYnVnLmxvZyhcIkJ1ZmZlckNvbnRyb2xsZXIgXCIrYytcIiBzdGFydC5cIiksbT0hMCxuPSEwLFYuY2FsbCh0aGlzKSl9LFg9ZnVuY3Rpb24oYSl7dmFyIGI7dGhpcy5kZWJ1Zy5sb2coXCJCdWZmZXJDb250cm9sbGVyIFwiK2MrXCIgc2VlazogXCIrYSkscT0hMCxyPWEsYj1uZXcgRGF0ZSxUKGIsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZS5VU0VSX1JFUVVFU1RfU1RPUF9SRUFTT04pLE89dGhpcy5tZXRyaWNzTW9kZWwuYWRkUGxheUxpc3QoYyxiLHIsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5TRUVLX1NUQVJUX1JFQVNPTiksVy5jYWxsKHRoaXMpfSxZPWZ1bmN0aW9uKCl7ayE9PWcmJih0aGlzLmRlYnVnLmxvZyhcIkJ1ZmZlckNvbnRyb2xsZXIgXCIrYytcIiBzdG9wLlwiKSxTLmNhbGwodGhpcyxnKSx0aGlzLnJlcXVlc3RTY2hlZHVsZXIuc3RvcFNjaGVkdWxpbmcodGhpcyksdGhpcy5mcmFnbWVudENvbnRyb2xsZXIuY2FuY2VsUGVuZGluZ1JlcXVlc3RzRm9yTW9kZWwoRyksbT0hMSxuPSExLFQobmV3IERhdGUsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZS5VU0VSX1JFUVVFU1RfU1RPUF9SRUFTT04pKX0sWj1mdW5jdGlvbihhLGIpe3ZhciBjPW51bGw7cmV0dXJuIGImJmIuUmVwcmVzZW50YXRpb25fYXNBcnJheSYmYi5SZXByZXNlbnRhdGlvbl9hc0FycmF5Lmxlbmd0aD4wJiYoYz1iLlJlcHJlc2VudGF0aW9uX2FzQXJyYXlbYV0pLGN9LCQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzO2s9PT1qJiYodSYmKHU9ITEsdGhpcy52aWRlb01vZGVsLnN0YWxsU3RyZWFtKGMsdSkpLFMuY2FsbChhLGgpKX0sXz1mdW5jdGlvbihhKXtpZih0aGlzLmZyYWdtZW50Q29udHJvbGxlci5pc0luaXRpYWxpemF0aW9uUmVxdWVzdChhKSlTLmNhbGwodGhpcyxoKTtlbHNle1MuY2FsbCh0aGlzLGopO3ZhciBiPXRoaXMsYz1iLmZyYWdtZW50Q29udHJvbGxlci5nZXRMb2FkaW5nVGltZShiKTtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7KE18fE4pJiYoUy5jYWxsKGIsaCkscWIuY2FsbChiKSl9LGMpfX0sYWI9ZnVuY3Rpb24oYSxiKXt0aGlzLmZyYWdtZW50Q29udHJvbGxlci5pc0luaXRpYWxpemF0aW9uUmVxdWVzdChhKT9oYi5jYWxsKHRoaXMsYSxiKTpiYi5jYWxsKHRoaXMsYSxiKX0sYmI9ZnVuY3Rpb24oYSxiKXt2YXIgZD10aGlzO2QuZGVidWcubG9nKGMrXCIgQnl0ZXMgZmluaXNoZWQgbG9hZGluZzogXCIrYS51cmwpLEt8fGlzTmFOKGEuZHVyYXRpb24pfHwoSz1hLmR1cmF0aW9uKSxkLmZyYWdtZW50Q29udHJvbGxlci5wcm9jZXNzKGIuZGF0YSkudGhlbihmdW5jdGlvbihiKXtudWxsIT09YiYmbnVsbCE9PXo/US53aGVuKHoucHJvbWlzZSkudGhlbihmdW5jdGlvbigpe2NiLmNhbGwoZCxiLGEucXVhbGl0eSkudGhlbihmdW5jdGlvbigpe0EucHJvbWlzZS50aGVuKGZ1bmN0aW9uKGIpe2IuaW5kZXgtMSE9PWEuaW5kZXh8fHh8fCh4PSEwLHUmJih1PSExLGQudmlkZW9Nb2RlbC5zdGFsbFN0cmVhbShjLHUpKSxTLmNhbGwoZCxoKSxkLnN5c3RlbS5ub3RpZnkoXCJidWZmZXJpbmdDb21wbGV0ZWRcIikpfSl9KX0pOmQuZGVidWcubG9nKFwiTm8gXCIrYytcIiBieXRlcyB0byBwdXNoLlwiKX0pfSxjYj1mdW5jdGlvbihhLGIpe3ZhciBkPXRoaXMsZT1hPT1KLGg9ZT9COlEuZGVmZXIoKSxpPWU/eS5sZW5ndGg6eS5wdXNoKGgpLGo9Wih0LGQuZ2V0RGF0YSgpKSxsPWQudmlkZW9Nb2RlbC5nZXRDdXJyZW50VGltZSgpLG09bmV3IERhdGU7cmV0dXJuIGQuZGVidWcubG9nKFwiUHVzaCAoXCIrYytcIikgYnl0ZXM6IFwiK2EuYnl0ZUxlbmd0aCksUj09PSEwJiZrIT09ZyYmLTEhPT10JiYoUj0hMSxQPWQubWV0cmljc01vZGVsLmFwcGVuZFBsYXlMaXN0VHJhY2UoTyxqLmlkLG51bGwsbSxsLG51bGwsMSxudWxsKSksUS53aGVuKGV8fDI+aXx8eVtpLTJdLnByb21pc2UpLnRoZW4oZnVuY3Rpb24oKXtOJiZmYi5jYWxsKGQpLnRoZW4oZnVuY3Rpb24oKXtyZXR1cm4gYiE9PXQ/KGgucmVzb2x2ZSgpLGUmJihCPW51bGwsSj1udWxsKSx2b2lkIDApOihRLndoZW4oQz9DLnByb21pc2U6ITApLnRoZW4oZnVuY3Rpb24oKXtkLnNvdXJjZUJ1ZmZlckV4dC5hcHBlbmQoTixhLGQudmlkZW9Nb2RlbCkudGhlbihmdW5jdGlvbigpe2UmJihCPW51bGwsSj1udWxsKSxkLnJlcXVlc3RTY2hlZHVsZXIuaXNTY2hlZHVsZWQoZCl8fFcuY2FsbChkKSxJPSExLGRiLmNhbGwoZCkudGhlbihmdW5jdGlvbigpe2gucmVzb2x2ZSgpfSksTiYmZC5zb3VyY2VCdWZmZXJFeHQuZ2V0QWxsUmFuZ2VzKE4pLnRoZW4oZnVuY3Rpb24oYSl7aWYoYSYmKGQuZGVidWcubG9nKFwiQXBwZW5kIFwiK2MrXCIgY29tcGxldGU6IFwiK2EubGVuZ3RoKSxhLmxlbmd0aD4wKSl7dmFyIGIsZTtmb3IoZC5kZWJ1Zy5sb2coXCJOdW1iZXIgb2YgYnVmZmVyZWQgXCIrYytcIiByYW5nZXM6IFwiK2EubGVuZ3RoKSxiPTAsZT1hLmxlbmd0aDtlPmI7Yis9MSlkLmRlYnVnLmxvZyhcIkJ1ZmZlcmVkIFwiK2MrXCIgUmFuZ2U6IFwiK2Euc3RhcnQoYikrXCIgLSBcIithLmVuZChiKSl9fSl9LGZ1bmN0aW9uKGIpe2IuZXJyLmNvZGU9PT1mJiYoSj1hLEI9aCxJPSEwLEY9MCxZLmNhbGwoZCkpfSl9KSx2b2lkIDApfSl9KSxoLnByb21pc2V9LGRiPWZ1bmN0aW9uKCl7aWYoIU0mJiFOKXJldHVybiBRLndoZW4oITEpO3ZhciBhPXRoaXMsYj1RLmRlZmVyKCksZD1vYi5jYWxsKGEpO3JldHVybiBhLnNvdXJjZUJ1ZmZlckV4dC5nZXRCdWZmZXJMZW5ndGgoTixkKS50aGVuKGZ1bmN0aW9uKGQpe0g9ZCxhLm1ldHJpY3NNb2RlbC5hZGRCdWZmZXJMZXZlbChjLG5ldyBEYXRlLEgpLGViLmNhbGwoYSksYi5yZXNvbHZlKCl9KSxiLnByb21pc2V9LGViPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5idWZmZXJFeHQuZ2V0TGVhc3RCdWZmZXJMZXZlbCgpLGI9MipLLGM9SC1hO2M+YiYmIUM/KEY9MCxDPVEuZGVmZXIoKSk6Yj5jJiZDJiYoQy5yZXNvbHZlKCksQz1udWxsKX0sZmI9ZnVuY3Rpb24oKXt2YXIgYSxiPXRoaXMsYz1RLmRlZmVyKCksZD0wO3JldHVybiBJPyhhPWZ1bmN0aW9uKCl7Z2IuY2FsbChiKS50aGVuKGZ1bmN0aW9uKGIpe2QrPWIsZD49Sz9jLnJlc29sdmUoKTpzZXRUaW1lb3V0KGEsMWUzKkspfSl9LGEuY2FsbChiKSxjLnByb21pc2UpOlEud2hlbighMCl9LGdiPWZ1bmN0aW9uKCl7dmFyIGEsYyxkPXRoaXMsZT1RLmRlZmVyKCksZj1kLnZpZGVvTW9kZWwuZ2V0Q3VycmVudFRpbWUoKSxnPTA7cmV0dXJuIGM9ZC5mcmFnbWVudENvbnRyb2xsZXIuZ2V0RXhlY3V0ZWRSZXF1ZXN0Rm9yVGltZShHLGYpLGE9YyYmIWlzTmFOKGMuc3RhcnRUaW1lKT9jLnN0YXJ0VGltZTpNYXRoLmZsb29yKGYpLEs9YyYmIWlzTmFOKGMuZHVyYXRpb24pP2MuZHVyYXRpb246MSxkLnNvdXJjZUJ1ZmZlckV4dC5nZXRCdWZmZXJSYW5nZShOLGYpLnRoZW4oZnVuY3Rpb24oYyl7bnVsbD09PWMmJnI9PT1mJiZOLmJ1ZmZlcmVkLmxlbmd0aD4wJiYoYT1OLmJ1ZmZlcmVkLmVuZChOLmJ1ZmZlcmVkLmxlbmd0aC0xKSksZz1OLmJ1ZmZlcmVkLnN0YXJ0KDApLGQuc291cmNlQnVmZmVyRXh0LnJlbW92ZShOLGcsYSxFLGIpLnRoZW4oZnVuY3Rpb24oKXtkLmZyYWdtZW50Q29udHJvbGxlci5yZW1vdmVFeGVjdXRlZFJlcXVlc3RzQmVmb3JlVGltZShHLGEpLGUucmVzb2x2ZShhLWcpfSl9KSxlLnByb21pc2V9LGhiPWZ1bmN0aW9uKGEsYil7dmFyIGQ9dGhpcyxlPWIuZGF0YSxmPWEucXVhbGl0eTtkLmRlYnVnLmxvZyhjK1wiIEluaXRpYWxpemF0aW9uIGZpbmlzaGVkIGxvYWRpbmc6IFwiK2EudXJsKSxkLmZyYWdtZW50Q29udHJvbGxlci5wcm9jZXNzKGUpLnRoZW4oZnVuY3Rpb24oYil7bnVsbCE9PWI/KHBbZl09YixmPT09dCYmY2IuY2FsbChkLGIsYS5xdWFsaXR5KS50aGVuKGZ1bmN0aW9uKCl7ei5yZXNvbHZlKCl9KSk6ZC5kZWJ1Zy5sb2coXCJObyBcIitjK1wiIGJ5dGVzIHRvIHB1c2guXCIpfSl9LGliPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcyxiPWEubWFuaWZlc3RNb2RlbC5nZXRWYWx1ZSgpLGM9YS5tYW5pZmVzdEV4dC5nZXRJc0xpdmUoYik7az09PWomJlMuY2FsbChhLGgpLGN8fGEuc3lzdGVtLm5vdGlmeShcInNlZ21lbnRMb2FkaW5nRmFpbGVkXCIpfSxqYj1mdW5jdGlvbihhKXt0aGlzLmRlYnVnLmxvZyhjK1wiIFN0cmVhbSBpcyBjb21wbGV0ZS5cIiksVChuZXcgRGF0ZSxNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlLkVORF9PRl9DT05URU5UX1NUT1BfUkVBU09OKSxZLmNhbGwodGhpcyksQS5yZXNvbHZlKGEpfSxrYj1mdW5jdGlvbihhLGIpe3ZhciBkLGU9bnVsbCxmPXRoaXMuYnVmZmVyRXh0LmdldFRvcFF1YWxpdHlJbmRleChjKSxnPVtdO2lmKG8mJih0aGlzLmRlYnVnLmxvZyhcIk1hcmtpbmcgYSBzcGVjaWFsIHNlZWsgZm9yIGluaXRpYWwgXCIrYytcIiBwbGF5YmFjay5cIikscXx8KHE9ITAscj0wKSxvPSExKSxzKXtmb3Ioej1RLmRlZmVyKCkscD1bXSxkPTA7Zj49ZDtkKz0xKWcucHVzaCh0aGlzLmluZGV4SGFuZGxlci5nZXRJbml0UmVxdWVzdChkLE0pKTt0PWIsZT1RLmFsbChnKX1lbHNlIGU9US53aGVuKG51bGwpLGEmJih6PVEuZGVmZXIoKSx0PWIscFtiXSYmY2IuY2FsbCh0aGlzLHBbYl0sYikudGhlbihmdW5jdGlvbigpe3oucmVzb2x2ZSgpfSkpO3JldHVybiBlfSxsYj1mdW5jdGlvbihiKXt2YXIgZCxlPXRoaXM7aWYocyYmIXEpZS5kZWJ1Zy5sb2coXCJEYXRhIGNoYW5nZWQgLSBsb2FkaW5nIHRoZSBcIitjK1wiIGZyYWdtZW50IGZvciB0aW1lOiBcIithKSxkPWUuaW5kZXhIYW5kbGVyLmdldFNlZ21lbnRSZXF1ZXN0Rm9yVGltZShhLGIsTSk7ZWxzZXt2YXIgZj1RLmRlZmVyKCksZz1lLnZpZGVvTW9kZWwuZ2V0Q3VycmVudFRpbWUoKTtkPWYucHJvbWlzZSxlLnNvdXJjZUJ1ZmZlckV4dC5nZXRCdWZmZXJSYW5nZShOLGcpLnRoZW4oZnVuY3Rpb24oYSl7cT0hMSxudWxsIT09YSYmKGc9YS5lbmQpLGUuZGVidWcubG9nKFwiTG9hZGluZyB0aGUgXCIrYytcIiBmcmFnbWVudCBmb3IgdGltZTogXCIrZyksZS5pbmRleEhhbmRsZXIuZ2V0U2VnbWVudFJlcXVlc3RGb3JUaW1lKGcsYixNKS50aGVuKGZ1bmN0aW9uKGEpe2YucmVzb2x2ZShhKX0sZnVuY3Rpb24oKXtmLnJlamVjdCgpfSl9LGZ1bmN0aW9uKCl7Zi5yZWplY3QoKX0pfXJldHVybiBzPSExLGR9LG1iPWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXM7bnVsbCE9PWE/Yi5mcmFnbWVudENvbnRyb2xsZXIuaXNGcmFnbWVudExvYWRlZE9yUGVuZGluZyhiLGEpP1wiY29tcGxldGVcIiE9PWEuYWN0aW9uP2IuaW5kZXhIYW5kbGVyLmdldE5leHRTZWdtZW50UmVxdWVzdCh0LE0pLnRoZW4obWIuYmluZChiKSk6KFkuY2FsbChiKSxTLmNhbGwoYixoKSk6KGIuZGVidWcubG9nKFwiTG9hZGluZyBhbiBcIitjK1wiIGZyYWdtZW50OiBcIithLnVybCksUS53aGVuKEM/Qy5wcm9taXNlOiEwKS50aGVuKGZ1bmN0aW9uKCl7Yi5mcmFnbWVudENvbnRyb2xsZXIucHJlcGFyZUZyYWdtZW50Rm9yTG9hZGluZyhiLGEsXyxhYixpYixqYikudGhlbihmdW5jdGlvbigpe1MuY2FsbChiLGgpfSl9KSk6Uy5jYWxsKGIsaCl9LG5iPWZ1bmN0aW9uKCl7biYmKGQ+SCYmZDxFLXRoaXMudmlkZW9Nb2RlbC5nZXRDdXJyZW50VGltZSgpP3V8fCh0aGlzLmRlYnVnLmxvZyhcIldhaXRpbmcgZm9yIG1vcmUgXCIrYytcIiBidWZmZXIgYmVmb3JlIHN0YXJ0aW5nIHBsYXliYWNrLlwiKSx1PSEwLHRoaXMudmlkZW9Nb2RlbC5zdGFsbFN0cmVhbShjLHUpKToodGhpcy5kZWJ1Zy5sb2coXCJHb3QgZW5vdWdoIFwiK2MrXCIgYnVmZmVyIHRvIHN0YXJ0LlwiKSxuPSExLHU9ITEsdGhpcy52aWRlb01vZGVsLnN0YWxsU3RyZWFtKGMsdSkpKX0sb2I9ZnVuY3Rpb24oKXt2YXIgYT0tMTtyZXR1cm4gYT10aGlzLnZpZGVvTW9kZWwuZ2V0Q3VycmVudFRpbWUoKX0scGI9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcyxjPWIudmlkZW9Nb2RlbC5nZXRQbGF5YmFja1JhdGUoKSxkPUgvTWF0aC5tYXgoYywxKSxlPVEuZGVmZXIoKTtyZXR1cm4gYi5idWZmZXJFeHQuZ2V0UmVxdWlyZWRCdWZmZXJMZW5ndGgobixiLnJlcXVlc3RTY2hlZHVsZXIuZ2V0RXhlY3V0ZUludGVydmFsKGIpLzFlMyx2LEUpLnRoZW4oZnVuY3Rpb24oYyl7Yi5pbmRleEhhbmRsZXIuZ2V0U2VnbWVudENvdW50Rm9yRHVyYXRpb24oYSxNLGMsZCkudGhlbihmdW5jdGlvbihhKXtlLnJlc29sdmUoYSl9KX0pLGUucHJvbWlzZX0scWI9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLGI9YS5mcmFnbWVudENvbnRyb2xsZXIuZ2V0UGVuZGluZ1JlcXVlc3RzKGEpLGM9YS5mcmFnbWVudENvbnRyb2xsZXIuZ2V0TG9hZGluZ1JlcXVlc3RzKGEpLGQ9KGI/Yi5sZW5ndGg6MCkrKGM/Yy5sZW5ndGg6MCk7Ri1kPjA/KEYtLSxsYi5jYWxsKGEsdCkudGhlbihtYi5iaW5kKGEpKSk6KGs9PT1pJiZTLmNhbGwoYSxoKSwkLmNhbGwoYSkpfSxyYj1mdW5jdGlvbigpe3ZhciBhLGI9dGhpcyxkPSExLGY9bnVsbCxnPW5ldyBEYXRlLGw9Yi52aWRlb01vZGVsLmdldEN1cnJlbnRUaW1lKCksbT1vYi5jYWxsKGIpO2lmKGIuZGVidWcubG9nKFwiQnVmZmVyQ29udHJvbGxlci52YWxpZGF0ZSgpIFwiK2MrXCIgfCBzdGF0ZTogXCIrayksYi5kZWJ1Zy5sb2coYytcIiBQbGF5YmFjayByYXRlOiBcIitiLnZpZGVvTW9kZWwuZ2V0RWxlbWVudCgpLnBsYXliYWNrUmF0ZSksYi5kZWJ1Zy5sb2coYytcIiBXb3JraW5nIHRpbWU6IFwiK20pLGIuZGVidWcubG9nKGMrXCIgVmlkZW8gdGltZTogXCIrbCksYi5kZWJ1Zy5sb2coXCJDdXJyZW50IFwiK2MrXCIgYnVmZmVyIGxlbmd0aDogXCIrSCksbmIuY2FsbChiKSxrPT09aiYmZT5IKXV8fChiLmRlYnVnLmxvZyhcIlN0YWxsaW5nIFwiK2MrXCIgQnVmZmVyOiBcIitjKSxUKG5ldyBEYXRlLE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUGxheUxpc3QuVHJhY2UuUkVCVUZGRVJJTkdfUkVBU09OKSx1PSEwLG49ITAsYi52aWRlb01vZGVsLnN0YWxsU3RyZWFtKGMsdSkpO2Vsc2UgaWYoaz09PWgpe1MuY2FsbChiLGkpO3ZhciBvPWIubWFuaWZlc3RNb2RlbC5nZXRWYWx1ZSgpLm1pbkJ1ZmZlclRpbWU7Yi5idWZmZXJFeHQuZGVjaWRlQnVmZmVyTGVuZ3RoKG8sRSxuKS50aGVuKGZ1bmN0aW9uKGEpe2IuZGVidWcubG9nKFwiQnVmZmVyIHRpbWU6IFwiK2EpLGIuc2V0TWluQnVmZmVyVGltZShhKSxiLnJlcXVlc3RTY2hlZHVsZXIuYWRqdXN0RXhlY3V0ZUludGVydmFsKCl9KSxiLmFickNvbnRyb2xsZXIuZ2V0UGxheWJhY2tRdWFsaXR5KGMsTSkudGhlbihmdW5jdGlvbihlKXt2YXIgaD1lLnF1YWxpdHk7aWYoYi5kZWJ1Zy5sb2coYytcIiBQbGF5YmFjayBxdWFsaXR5OiBcIitoKSxiLmRlYnVnLmxvZyhcIlBvcHVsYXRlIFwiK2MrXCIgYnVmZmVycy5cIiksdm9pZCAwIT09aCYmKGE9aCksZD1oIT09dCxkPT09ITApe2lmKGIuZnJhZ21lbnRDb250cm9sbGVyLmFib3J0UmVxdWVzdHNGb3JNb2RlbChHKSxmPVooYSxiLmdldERhdGEoKSksbnVsbD09PWZ8fHZvaWQgMD09PWYpdGhyb3dcIlVuZXhwZWN0ZWQgZXJyb3IhXCI7Yi5tYW5pZmVzdEV4dC5nZXRUaW1lc3RhbXBPZmZzZXRGb3JQZXJpb2QoRCxiLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSxoLE0pLnRoZW4oZnVuY3Rpb24oYSl7Ti50aW1lc3RhbXBPZmZzZXQhPT1hJiYoTi50aW1lc3RhbXBPZmZzZXQ9YSl9KSxUKG5ldyBEYXRlLE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUGxheUxpc3QuVHJhY2UuUkVQUkVTRU5UQVRJT05fU1dJVENIX1NUT1BfUkVBU09OKSxiLm1ldHJpY3NNb2RlbC5hZGRSZXByZXNlbnRhdGlvblN3aXRjaChjLGcsbCxmLmlkKX1yZXR1cm4gYi5kZWJ1Zy5sb2coZD9jK1wiIFF1YWxpdHkgY2hhbmdlZCB0bzogXCIraDpcIlF1YWxpdHkgZGlkbid0IGNoYW5nZS5cIikscGIuY2FsbChiLGgpfSkudGhlbihmdW5jdGlvbihlKXtGPWUsa2IuY2FsbChiLGQsYSkudGhlbihmdW5jdGlvbihhKXtpZihudWxsIT09YSl7dmFyIGQsZSxmPWEubGVuZ3RoO2ZvcihlPTA7Zj5lO2UrPTEpZD1hW2VdLGIuZGVidWcubG9nKFwiTG9hZGluZyBcIitjK1wiIGluaXRpYWxpemF0aW9uOiBcIitkLnVybCksYi5kZWJ1Zy5sb2coZCksYi5mcmFnbWVudENvbnRyb2xsZXIucHJlcGFyZUZyYWdtZW50Rm9yTG9hZGluZyhiLGQsXyxhYixpYixqYikudGhlbihmdW5jdGlvbigpe1MuY2FsbChiLGgpfSl9fSkscWIuY2FsbChiKX0pfWVsc2Ugaz09PWkmJlMuY2FsbChiLGgpfTtyZXR1cm57dmlkZW9Nb2RlbDp2b2lkIDAsbWV0cmljc01vZGVsOnZvaWQgMCxtYW5pZmVzdEV4dDp2b2lkIDAsbWFuaWZlc3RNb2RlbDp2b2lkIDAsYnVmZmVyRXh0OnZvaWQgMCxzb3VyY2VCdWZmZXJFeHQ6dm9pZCAwLGFickNvbnRyb2xsZXI6dm9pZCAwLGZyYWdtZW50RXh0OnZvaWQgMCxpbmRleEhhbmRsZXI6dm9pZCAwLGRlYnVnOnZvaWQgMCxzeXN0ZW06dm9pZCAwLGVyckhhbmRsZXI6dm9pZCAwLGluaXRpYWxpemU6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxoKXt2YXIgaT10aGlzLGo9aS5tYW5pZmVzdE1vZGVsLmdldFZhbHVlKCksaz1pLm1hbmlmZXN0RXh0LmdldElzTGl2ZShqKTtpLnNldE1lZGlhU291cmNlKGgpLGkuc2V0VmlkZW9Nb2RlbChlKSxpLnNldFR5cGUoYSksaS5zZXRQZXJpb2RJbmRleChiKSxpLnNldERhdGEoYykudGhlbihmdW5jdGlvbigpe2w9ITAsVi5jYWxsKGkpfSksaS5zZXRCdWZmZXIoZCksaS5zZXRTY2hlZHVsZXIoZiksaS5zZXRGcmFnbWVudENvbnRyb2xsZXIoZyksaS5pbmRleEhhbmRsZXIuc2V0SXNMaXZlKGspLGkubWFuaWZlc3RFeHQuZ2V0RHVyYXRpb25Gb3JQZXJpb2QoYixpLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSkudGhlbihmdW5jdGlvbihhKXtFPWEsaS5pbmRleEhhbmRsZXIuc2V0RHVyYXRpb24oYSksaS5idWZmZXJFeHQuZGVjaWRlQnVmZmVyTGVuZ3RoKGoubWluQnVmZmVyVGltZSxFLG4pLnRoZW4oZnVuY3Rpb24oYSl7aS5zZXRNaW5CdWZmZXJUaW1lKGEpfSl9KX0sZ2V0VHlwZTpmdW5jdGlvbigpe3JldHVybiBjfSxzZXRUeXBlOmZ1bmN0aW9uKGEpe2M9YSx2b2lkIDAhPT10aGlzLmluZGV4SGFuZGxlciYmdGhpcy5pbmRleEhhbmRsZXIuc2V0VHlwZShhKX0sZ2V0UGVyaW9kSW5kZXg6ZnVuY3Rpb24oKXtyZXR1cm4gRH0sc2V0UGVyaW9kSW5kZXg6ZnVuY3Rpb24oYSl7RD1hfSxnZXRWaWRlb01vZGVsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmlkZW9Nb2RlbH0sc2V0VmlkZW9Nb2RlbDpmdW5jdGlvbihhKXt0aGlzLnZpZGVvTW9kZWw9YX0sZ2V0U2NoZWR1bGVyOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVxdWVzdFNjaGVkdWxlcn0sc2V0U2NoZWR1bGVyOmZ1bmN0aW9uKGEpe3RoaXMucmVxdWVzdFNjaGVkdWxlcj1hfSxnZXRGcmFnbWVudENvbnRyb2xsZXI6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFnbWVudENvbnRyb2xsZXJ9LHNldEZyYWdtZW50Q29udHJvbGxlcjpmdW5jdGlvbihhKXt0aGlzLmZyYWdtZW50Q29udHJvbGxlcj1hfSxnZXRBdXRvU3dpdGNoQml0cmF0ZTpmdW5jdGlvbigpe3ZhciBhPXRoaXM7cmV0dXJuIGEuYWJyQ29udHJvbGxlci5nZXRBdXRvU3dpdGNoQml0cmF0ZSgpfSxzZXRBdXRvU3dpdGNoQml0cmF0ZTpmdW5jdGlvbihhKXt2YXIgYj10aGlzO2IuYWJyQ29udHJvbGxlci5zZXRBdXRvU3dpdGNoQml0cmF0ZShhKX0sZ2V0RGF0YTpmdW5jdGlvbigpe3JldHVybiBNfSxzZXREYXRhOmZ1bmN0aW9uKGIpe3ZhciBkPXRoaXMsZT1RLmRlZmVyKCksZj1NO3JldHVybiBmfHwoZj1iKSxkLmFickNvbnRyb2xsZXIuZ2V0UGxheWJhY2tRdWFsaXR5KGMsZikudGhlbihmdW5jdGlvbihnKXtkLmluZGV4SGFuZGxlci5nZXRDdXJyZW50VGltZShnLnF1YWxpdHksZikudGhlbihmdW5jdGlvbihmKXtzPSEwLGE9ZixNPWIsZC5zZWVrKGYpLGQuYnVmZmVyRXh0LnVwZGF0ZURhdGEoTSxjKSxlLnJlc29sdmUoKX0pfSksZS5wcm9taXNlfSxnZXRCdWZmZXI6ZnVuY3Rpb24oKXtyZXR1cm4gTn0sc2V0QnVmZmVyOmZ1bmN0aW9uKGEpe049YX0sZ2V0TWluQnVmZmVyVGltZTpmdW5jdGlvbigpe3JldHVybiBkfSxzZXRNaW5CdWZmZXJUaW1lOmZ1bmN0aW9uKGEpe2Q9YX0sc2V0TWVkaWFTb3VyY2U6ZnVuY3Rpb24oYSl7Yj1hfSxpc1JlYWR5OmZ1bmN0aW9uKCl7cmV0dXJuIGs9PT1ofSxpc0J1ZmZlcmluZ0NvbXBsZXRlZDpmdW5jdGlvbigpe3JldHVybiB4fSxjbGVhck1ldHJpY3M6ZnVuY3Rpb24oKXt2YXIgYT10aGlzO251bGwhPT1jJiZcIlwiIT09YyYmYS5tZXRyaWNzTW9kZWwuY2xlYXJDdXJyZW50TWV0cmljc0ZvclR5cGUoYyl9LHVwZGF0ZUJ1ZmZlclN0YXRlOmZ1bmN0aW9uKCl7dmFyIGE9dGhpcztJJiZKJiYhTD8oTD0hMCxjYi5jYWxsKGEsSix0KS50aGVuKGZ1bmN0aW9uKCl7TD0hMX0pKTpkYi5jYWxsKGEpfSxyZXNldDpmdW5jdGlvbihhKXt2YXIgYz10aGlzO1kuY2FsbChjKSxjLmNsZWFyTWV0cmljcygpLGMuZnJhZ21lbnRDb250cm9sbGVyLmFib3J0UmVxdWVzdHNGb3JNb2RlbChHKSxjLmZyYWdtZW50Q29udHJvbGxlci5kZXRhY2hCdWZmZXJDb250cm9sbGVyKEcpLEc9bnVsbCx5PVtdLHo9bnVsbCxwPVtdLEE9US5kZWZlcigpLGF8fChjLnNvdXJjZUJ1ZmZlckV4dC5hYm9ydChiLE4pLGMuc291cmNlQnVmZmVyRXh0LnJlbW92ZVNvdXJjZUJ1ZmZlcihiLE4pKSxNPW51bGwsTj1udWxsfSxzdGFydDpXLHNlZWs6WCxzdG9wOll9fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyQ29udHJvbGxlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJDb250cm9sbGVyfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucz1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhLGIsYz0wLGQ9MCxlPW51bGwsZj1udWxsLGc9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5tZXRyaWNzRXh0LmdldEN1cnJlbnRIdHRwUmVxdWVzdChhKTtyZXR1cm4gbnVsbCE9PWI/KGIudHJlc3BvbnNlLmdldFRpbWUoKS1iLnRyZXF1ZXN0LmdldFRpbWUoKSkvMWUzOjB9LGg9ZnVuY3Rpb24oKXt2YXIgYSxiPXRoaXMsZz1RLmRlZmVyKCk7cmV0dXJuIFEud2hlbihlP2IuYWJyQ29udHJvbGxlci5nZXRQbGF5YmFja1F1YWxpdHkoXCJhdWRpb1wiLGUpOmMpLnRoZW4oZnVuY3Rpb24oZSl7US53aGVuKGY/Yi5hYnJDb250cm9sbGVyLmdldFBsYXliYWNrUXVhbGl0eShcInZpZGVvXCIsZik6ZCkudGhlbihmdW5jdGlvbihiKXthPWUucXVhbGl0eT09PWMmJmIucXVhbGl0eT09PWQsYT1hfHxlLmNvbmZpZGVuY2U9PT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkcmJmIuY29uZmlkZW5jZT09PU1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlLlNUUk9ORyxnLnJlc29sdmUoYSl9KX0pLGcucHJvbWlzZX07cmV0dXJue3N5c3RlbTp2b2lkIDAsdmlkZW9Nb2RlbDp2b2lkIDAsbWFuaWZlc3RFeHQ6dm9pZCAwLG1ldHJpY3NFeHQ6dm9pZCAwLG1ldHJpY3NNb2RlbDp2b2lkIDAsYWJyQ29udHJvbGxlcjp2b2lkIDAsYnVmZmVyTWF4OnZvaWQgMCx1cGRhdGVEYXRhOmZ1bmN0aW9uKGEsYil7dmFyIGc9YS5SZXByZXNlbnRhdGlvbl9hc0FycmF5Lmxlbmd0aC0xO1wiYXVkaW9cIj09PWI/KGM9ZyxlPWEpOlwidmlkZW9cIj09PWImJihkPWcsZj1hKX0sZ2V0VG9wUXVhbGl0eUluZGV4OmZ1bmN0aW9uKGEpe3ZhciBiPW51bGw7cmV0dXJuXCJhdWRpb1wiPT09YT9iPWM6XCJ2aWRlb1wiPT09YSYmKGI9ZCksYn0sZGVjaWRlQnVmZmVyTGVuZ3RoOmZ1bmN0aW9uKGIsYyl7cmV0dXJuIGE9TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuREVGQVVMVF9NSU5fQlVGRkVSX1RJTUU8YyYmYz5iP01hdGgubWF4KE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zLkRFRkFVTFRfTUlOX0JVRkZFUl9USU1FLGIpOmI+PWM/TWF0aC5taW4oYyxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5ERUZBVUxUX01JTl9CVUZGRVJfVElNRSk6TWF0aC5taW4oYyxiKSxRLndoZW4oYSl9LGdldExlYXN0QnVmZmVyTGV2ZWw6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLm1ldHJpY3NNb2RlbC5nZXRSZWFkT25seU1ldHJpY3NGb3IoXCJ2aWRlb1wiKSxiPXRoaXMubWV0cmljc0V4dC5nZXRDdXJyZW50QnVmZmVyTGV2ZWwoYSksYz10aGlzLm1ldHJpY3NNb2RlbC5nZXRSZWFkT25seU1ldHJpY3NGb3IoXCJhdWRpb1wiKSxkPXRoaXMubWV0cmljc0V4dC5nZXRDdXJyZW50QnVmZmVyTGV2ZWwoYyksZT1udWxsO3JldHVybiBlPW51bGw9PT1ifHxudWxsPT09ZD9udWxsIT09ZD9kLmxldmVsOm51bGwhPT1iP2IubGV2ZWw6bnVsbDpNYXRoLm1pbihkLmxldmVsLGIubGV2ZWwpfSxnZXRSZXF1aXJlZEJ1ZmZlckxlbmd0aDpmdW5jdGlvbihjLGQsZSxmKXt2YXIgaSxqPXRoaXMsaz1qLm1ldHJpY3NNb2RlbC5nZXRSZWFkT25seU1ldHJpY3NGb3IoXCJ2aWRlb1wiKSxsPWoubWV0cmljc01vZGVsLmdldFJlYWRPbmx5TWV0cmljc0ZvcihcImF1ZGlvXCIpLG09Zj49TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuTE9OR19GT1JNX0NPTlRFTlRfRFVSQVRJT05fVEhSRVNIT0xELG49US5kZWZlcigpLG89bnVsbDtyZXR1cm4gai5idWZmZXJNYXg9PT1NZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5CVUZGRVJfU0laRV9NSU4/KGk9YSxuLnJlc29sdmUoaSkpOmouYnVmZmVyTWF4PT09TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuQlVGRkVSX1NJWkVfSU5GSU5JVFk/KGk9ZixuLnJlc29sdmUoaSkpOmouYnVmZmVyTWF4PT09TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuQlVGRkVSX1NJWkVfUkVRVUlSRUQ/KGI9YSxlfHxjfHwobz1oLmNhbGwoaikpLFEud2hlbihvKS50aGVuKGZ1bmN0aW9uKGEpe2EmJihiPW0/TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuQlVGRkVSX1RJTUVfQVRfVE9QX1FVQUxJVFlfTE9OR19GT1JNOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zLkJVRkZFUl9USU1FX0FUX1RPUF9RVUFMSVRZKSxpPWIrZCtNYXRoLm1heChnLmNhbGwoaixrKSxnLmNhbGwoaixsKSksbi5yZXNvbHZlKGkpfSkpOm4ucmVqZWN0KFwiaW52YWxpZCBidWZmZXJNYXggdmFsdWU6IFwiK2ouYnVmZmVyTWF4KSxuLnByb21pc2V9LGdldEJ1ZmZlclRhcmdldDpmdW5jdGlvbigpe3JldHVybiB2b2lkIDA9PT1iP2E6Yn19fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5CVUZGRVJfU0laRV9SRVFVSVJFRD1cInJlcXVpcmVkXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuQlVGRkVSX1NJWkVfTUlOPVwibWluXCIsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuQlVGRkVSX1NJWkVfSU5GSU5JVFk9XCJpbmZpbml0eVwiLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zLkJVRkZFUl9USU1FX0FUX1NUQVJUVVA9MSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5ERUZBVUxUX01JTl9CVUZGRVJfVElNRT04LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zLkJVRkZFUl9USU1FX0FUX1RPUF9RVUFMSVRZPTMwLE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5CdWZmZXJFeHRlbnNpb25zLkJVRkZFUl9USU1FX0FUX1RPUF9RVUFMSVRZX0xPTkdfRk9STT0zMDAsTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMuTE9OR19GT1JNX0NPTlRFTlRfRFVSQVRJT05fVEhSRVNIT0xEPTYwMCxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuQnVmZmVyRXh0ZW5zaW9ucy5wcm90b3R5cGUuY29uc3RydWN0b3I9TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkJ1ZmZlckV4dGVuc2lvbnMsTWVkaWFQbGF5ZXIudXRpbHMuQ2FwYWJpbGl0aWVzPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCJ9LE1lZGlhUGxheWVyLnV0aWxzLkNhcGFiaWxpdGllcy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLnV0aWxzLkNhcGFiaWxpdGllcyxzdXBwb3J0c01lZGlhU291cmNlOmZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9XCJXZWJLaXRNZWRpYVNvdXJjZVwiaW4gd2luZG93LGI9XCJNZWRpYVNvdXJjZVwiaW4gd2luZG93O3JldHVybiBhfHxifSxzdXBwb3J0c01lZGlhS2V5czpmdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPVwiV2ViS2l0TWVkaWFLZXlzXCJpbiB3aW5kb3csYj1cIk1TTWVkaWFLZXlzXCJpbiB3aW5kb3csYz1cIk1lZGlhS2V5c1wiaW4gd2luZG93O3JldHVybiBhfHxifHxjfSxzdXBwb3J0c0NvZGVjOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7aWYoIShhIGluc3RhbmNlb2YgSFRNTFZpZGVvRWxlbWVudCkpdGhyb3dcImVsZW1lbnQgbXVzdCBiZSBvZiB0eXBlIEhUTUxWaWRlb0VsZW1lbnQuXCI7dmFyIGM9YS5jYW5QbGF5VHlwZShiKTtyZXR1cm5cInByb2JhYmx5XCI9PT1jfX0sTWVkaWFQbGF5ZXIudXRpbHMuRGVidWc9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT0hMDtyZXR1cm57ZXZlbnRCdXM6dm9pZCAwLHNldExvZ1RvQnJvd3NlckNvbnNvbGU6ZnVuY3Rpb24oYil7YT1ifSxnZXRMb2dUb0Jyb3dzZXJDb25zb2xlOmZ1bmN0aW9uKCl7cmV0dXJuIGF9LGxvZzpmdW5jdGlvbihiKXthJiZjb25zb2xlLmxvZyhiKSx0aGlzLmV2ZW50QnVzLmRpc3BhdGNoRXZlbnQoe3R5cGU6XCJsb2dcIixtZXNzYWdlOmJ9KX19fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRXJyb3JIYW5kbGVyPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJue2V2ZW50QnVzOnZvaWQgMCxjYXBhYmlsaXR5RXJyb3I6ZnVuY3Rpb24oYSl7dGhpcy5ldmVudEJ1cy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwiZXJyb3JcIixlcnJvcjpcImNhcGFiaWxpdHlcIixldmVudDphfSl9LGRvd25sb2FkRXJyb3I6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuZXZlbnRCdXMuZGlzcGF0Y2hFdmVudCh7dHlwZTpcImVycm9yXCIsZXJyb3I6XCJkb3dubG9hZFwiLGV2ZW50OntpZDphLHVybDpiLHJlcXVlc3Q6Y319KX0sbWFuaWZlc3RFcnJvcjpmdW5jdGlvbihhLGIsYyl7dGhpcy5ldmVudEJ1cy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwiZXJyb3JcIixlcnJvcjpcIm1hbmlmZXN0RXJyb3JcIixldmVudDp7bWVzc2FnZTphLGlkOmIsbWFuaWZlc3Q6Y319KX0sbWVkaWFTb3VyY2VFcnJvcjpmdW5jdGlvbihhKXt0aGlzLmV2ZW50QnVzLmRpc3BhdGNoRXZlbnQoe3R5cGU6XCJlcnJvclwiLGVycm9yOlwibWVkaWFzb3VyY2VcIixldmVudDphfSl9LG1lZGlhS2V5U2Vzc2lvbkVycm9yOmZ1bmN0aW9uKGEpe3RoaXMuZXZlbnRCdXMuZGlzcGF0Y2hFdmVudCh7dHlwZTpcImVycm9yXCIsZXJyb3I6XCJrZXlfc2Vzc2lvblwiLGV2ZW50OmF9KX0sbWVkaWFLZXlNZXNzYWdlRXJyb3I6ZnVuY3Rpb24oYSl7dGhpcy5ldmVudEJ1cy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwiZXJyb3JcIixlcnJvcjpcImtleV9tZXNzYWdlXCIsZXZlbnQ6YX0pfSxtZWRpYUtleVN5c3RlbVNlbGVjdGlvbkVycm9yOmZ1bmN0aW9uKGEpe3RoaXMuZXZlbnRCdXMuZGlzcGF0Y2hFdmVudCh7dHlwZTpcImVycm9yXCIsZXJyb3I6XCJrZXlfc3lzdGVtX3NlbGVjdGlvblwiLGV2ZW50OmF9KX19fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRXJyb3JIYW5kbGVyLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkVycm9ySGFuZGxlcn0sTWVkaWFQbGF5ZXIudXRpbHMuRXZlbnRCdXM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYSxiPWZ1bmN0aW9uKGIsYyl7dmFyIGQ9KGM/XCIxXCI6XCIwXCIpK2I7cmV0dXJuIGQgaW4gYXx8KGFbZF09W10pLGFbZF19LGM9ZnVuY3Rpb24oKXthPXt9fTtyZXR1cm4gYygpLHthZGRFdmVudExpc3RlbmVyOmZ1bmN0aW9uKGEsYyxkKXt2YXIgZT1iKGEsZCksZj1lLmluZGV4T2YoYyk7LTE9PT1mJiZlLnB1c2goYyl9LHJlbW92ZUV2ZW50TGlzdGVuZXI6ZnVuY3Rpb24oYSxjLGQpe3ZhciBlPWIoYSxkKSxmPWUuaW5kZXhPZihjKTstMSE9PWYmJmUuc3BsaWNlKGYsMSl9LGRpc3BhdGNoRXZlbnQ6ZnVuY3Rpb24oYSl7Zm9yKHZhciBjPWIoYS50eXBlLCExKS5zbGljZSgpLGQ9MDtkPGMubGVuZ3RoO2QrKyljW2RdLmNhbGwodGhpcyxhKTtyZXR1cm4hYS5kZWZhdWx0UHJldmVudGVkfX19LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5GcmFnbWVudENvbnRyb2xsZXI9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT1bXSxiPWZ1bmN0aW9uKGIpe2Zvcih2YXIgYz1hLmxlbmd0aCxkPTA7Yz5kO2QrKylpZihhW2RdLmdldENvbnRleHQoKT09YilyZXR1cm4gYVtkXTtyZXR1cm4gbnVsbH0sYz1mdW5jdGlvbigpe2Zvcih2YXIgYj0hMCxjPWEubGVuZ3RoLGQ9MDtjPmQ7ZCsrKWlmKCFhW2RdLmlzUmVhZHkoKSl7Yj0hMTticmVha31yZXR1cm4gYn0sZD1mdW5jdGlvbigpe2Zvcih2YXIgYj0wO2I8YS5sZW5ndGg7YisrKWFbYl0uZXhlY3V0ZUN1cnJlbnRSZXF1ZXN0KCl9O3JldHVybntzeXN0ZW06dm9pZCAwLGRlYnVnOnZvaWQgMCxwcm9jZXNzOmZ1bmN0aW9uKGEpe3ZhciBiPW51bGw7cmV0dXJuIG51bGwhPT1hJiZ2b2lkIDAhPT1hJiZhLmJ5dGVMZW5ndGg+MCYmKGI9bmV3IFVpbnQ4QXJyYXkoYSkpLFEud2hlbihiKX0sYXR0YWNoQnVmZmVyQ29udHJvbGxlcjpmdW5jdGlvbihjKXtpZighYylyZXR1cm4gbnVsbDt2YXIgZD1iKGMpO3JldHVybiBkfHwoZD10aGlzLnN5c3RlbS5nZXRPYmplY3QoXCJmcmFnbWVudE1vZGVsXCIpLGQuc2V0Q29udGV4dChjKSxhLnB1c2goZCkpLGR9LGRldGFjaEJ1ZmZlckNvbnRyb2xsZXI6ZnVuY3Rpb24oYil7dmFyIGM9YS5pbmRleE9mKGIpO2M+LTEmJmEuc3BsaWNlKGMsMSl9LG9uQnVmZmVyQ29udHJvbGxlclN0YXRlQ2hhbmdlOmZ1bmN0aW9uKCl7YygpJiZkLmNhbGwodGhpcyl9LGlzRnJhZ21lbnRMb2FkZWRPclBlbmRpbmc6ZnVuY3Rpb24oYSxjKXt2YXIgZCxlPWIoYSk7cmV0dXJuIGU/ZD1lLmlzRnJhZ21lbnRMb2FkZWRPclBlbmRpbmcoYyk6ITF9LGdldFBlbmRpbmdSZXF1ZXN0czpmdW5jdGlvbihhKXt2YXIgYz1iKGEpO3JldHVybiBjP2MuZ2V0UGVuZGluZ1JlcXVlc3RzKCk6bnVsbH0sZ2V0TG9hZGluZ1JlcXVlc3RzOmZ1bmN0aW9uKGEpe3ZhciBjPWIoYSk7cmV0dXJuIGM/Yy5nZXRMb2FkaW5nUmVxdWVzdHMoKTpudWxsfSxpc0luaXRpYWxpemF0aW9uUmVxdWVzdDpmdW5jdGlvbihhKXtyZXR1cm4gYSYmYS50eXBlJiZcImluaXRpYWxpemF0aW9uIHNlZ21lbnRcIj09PWEudHlwZS50b0xvd2VyQ2FzZSgpfSxnZXRMb2FkaW5nVGltZTpmdW5jdGlvbihhKXt2YXIgYz1iKGEpO3JldHVybiBjP2MuZ2V0TG9hZGluZ1RpbWUoKTpudWxsfSxnZXRFeGVjdXRlZFJlcXVlc3RGb3JUaW1lOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE/YS5nZXRFeGVjdXRlZFJlcXVlc3RGb3JUaW1lKGIpOm51bGx9LHJlbW92ZUV4ZWN1dGVkUmVxdWVzdDpmdW5jdGlvbihhLGIpe2EmJmEucmVtb3ZlRXhlY3V0ZWRSZXF1ZXN0KGIpfSxyZW1vdmVFeGVjdXRlZFJlcXVlc3RzQmVmb3JlVGltZTpmdW5jdGlvbihhLGIpe2EmJmEucmVtb3ZlRXhlY3V0ZWRSZXF1ZXN0c0JlZm9yZVRpbWUoYil9LGNhbmNlbFBlbmRpbmdSZXF1ZXN0c0Zvck1vZGVsOmZ1bmN0aW9uKGEpe2EmJmEuY2FuY2VsUGVuZGluZ1JlcXVlc3RzKCl9LGFib3J0UmVxdWVzdHNGb3JNb2RlbDpmdW5jdGlvbihhKXthJiZhLmFib3J0UmVxdWVzdHMoKX0scHJlcGFyZUZyYWdtZW50Rm9yTG9hZGluZzpmdW5jdGlvbihhLGMsZCxlLGYsZyl7dmFyIGg9YihhKTtyZXR1cm4gaCYmYyYmIXRoaXMuaXNGcmFnbWVudExvYWRlZE9yUGVuZGluZyhhLGMpPyhoLmFkZFJlcXVlc3QoYyksaC5zZXRDYWxsYmFja3MoZCxlLGYsZyksUS53aGVuKCEwKSk6US53aGVuKG51bGwpfX19LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5GcmFnbWVudENvbnRyb2xsZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRnJhZ21lbnRDb250cm9sbGVyfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRnJhZ21lbnRMb2FkZXI9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT0zLGI9NTAwLGM9W10sZD1mdW5jdGlvbihhLGUpe3ZhciBmPW5ldyBYTUxIdHRwUmVxdWVzdCxnPW51bGwsaD0hMCxpPSEwLGo9dGhpcztjLnB1c2goZiksYS5yZXF1ZXN0U3RhcnREYXRlPW5ldyBEYXRlLGEuZmlyc3RCeXRlRGF0ZT1hLnJlcXVlc3RTdGFydERhdGUsZi5vcGVuKFwiR0VUXCIsYS51cmwsITApLGYucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIixhLnJhbmdlJiZmLnNldFJlcXVlc3RIZWFkZXIoXCJSYW5nZVwiLFwiYnl0ZXM9XCIrYS5yYW5nZSksZi5vbnByb2dyZXNzPWZ1bmN0aW9uKGIpe2gmJihoPSExLCghYi5sZW5ndGhDb21wdXRhYmxlfHxiLmxlbmd0aENvbXB1dGFibGUmJmIudG90YWwhPWIubG9hZGVkKSYmKGEuZmlyc3RCeXRlRGF0ZT1uZXcgRGF0ZSkpfSxmLm9ubG9hZD1mdW5jdGlvbigpe2lmKCEoZi5zdGF0dXM8MjAwfHxmLnN0YXR1cz4yOTkpKXtpPSExLGEucmVxdWVzdEVuZERhdGU9bmV3IERhdGU7dmFyIGI9YS5yZXF1ZXN0RW5kRGF0ZSxjPWYucmVzcG9uc2UsZD1hLmZpcnN0Qnl0ZURhdGUuZ2V0VGltZSgpLWEucmVxdWVzdFN0YXJ0RGF0ZS5nZXRUaW1lKCksZT1hLnJlcXVlc3RFbmREYXRlLmdldFRpbWUoKS1hLmZpcnN0Qnl0ZURhdGUuZ2V0VGltZSgpLGg9YS5yZXF1ZXN0RW5kRGF0ZS5nZXRUaW1lKCktYS5yZXF1ZXN0U3RhcnREYXRlLmdldFRpbWUoKTtqLmRlYnVnLmxvZyhcInNlZ21lbnQgbG9hZGVkOiAoXCIrZi5zdGF0dXMrXCIsIFwiK2QrXCJtcywgXCIrZStcIm1zLCBcIitoK1wibXMpIFwiK2EudXJsKSxnPWoubWV0cmljc01vZGVsLmFkZEh0dHBSZXF1ZXN0KGEuc3RyZWFtVHlwZSxudWxsLGEudHlwZSxhLnVybCxudWxsLGEucmFuZ2UsYS5yZXF1ZXN0U3RhcnREYXRlLGEuZmlyc3RCeXRlRGF0ZSxhLnJlcXVlc3RFbmREYXRlLGYuc3RhdHVzLG51bGwsYS5kdXJhdGlvbiksai5tZXRyaWNzTW9kZWwuYXBwZW5kSHR0cFRyYWNlKGcsYiwobmV3IERhdGUpLmdldFRpbWUoKS1iLmdldFRpbWUoKSxbYy5ieXRlTGVuZ3RoXSksYS5kZWZlcnJlZC5yZXNvbHZlKHtkYXRhOmMscmVxdWVzdDphfSl9fSxmLm9ubG9hZGVuZD1mLm9uZXJyb3I9ZnVuY3Rpb24oKXtpZigtMSE9PWMuaW5kZXhPZihmKSYmKGMuc3BsaWNlKGMuaW5kZXhPZihmKSwxKSxpKSl7aT0hMSxhLnJlcXVlc3RFbmREYXRlPW5ldyBEYXRlO3ZhciBoPWEuZmlyc3RCeXRlRGF0ZS5nZXRUaW1lKCktYS5yZXF1ZXN0U3RhcnREYXRlLmdldFRpbWUoKSxrPWEucmVxdWVzdEVuZERhdGUuZ2V0VGltZSgpLWEuZmlyc3RCeXRlRGF0ZS5nZXRUaW1lKCksbD1hLnJlcXVlc3RFbmREYXRlLmdldFRpbWUoKS1hLnJlcXVlc3RTdGFydERhdGUuZ2V0VGltZSgpO2ouZGVidWcubG9nKFwic2VnbWVudCBsb2FkZWQ6IChcIitmLnN0YXR1cytcIiwgXCIraCtcIm1zLCBcIitrK1wibXMsIFwiK2wrXCJtcykgXCIrYS51cmwpLGc9ai5tZXRyaWNzTW9kZWwuYWRkSHR0cFJlcXVlc3QoYS5zdHJlYW1UeXBlLG51bGwsYS50eXBlLGEudXJsLG51bGwsYS5yYW5nZSxhLnJlcXVlc3RTdGFydERhdGUsYS5maXJzdEJ5dGVEYXRlLGEucmVxdWVzdEVuZERhdGUsZi5zdGF0dXMsbnVsbCxhLmR1cmF0aW9uKSxlPjA/KGouZGVidWcubG9nKFwiRmFpbGVkIGxvYWRpbmcgc2VnbWVudDogXCIrYS51cmwrXCIsIHJldHJ5IGluIFwiK2IrXCJtc1wiK1wiIGF0dGVtcHRzOiBcIitlKSxlLS0sc2V0VGltZW91dChmdW5jdGlvbigpe2QuY2FsbChqLGEsZSl9LGIpKTooai5kZWJ1Zy5sb2coXCJGYWlsZWQgbG9hZGluZyBzZWdtZW50OiBcIithLnVybCtcIiBubyByZXRyeSBhdHRlbXB0cyBsZWZ0XCIpLGouZXJySGFuZGxlci5kb3dubG9hZEVycm9yKFwiY29udGVudFwiLGEudXJsLGYpLGEuZGVmZXJyZWQucmVqZWN0KGYpKX19LGYuc2VuZCgpfTtyZXR1cm57bWV0cmljc01vZGVsOnZvaWQgMCxlcnJIYW5kbGVyOnZvaWQgMCxkZWJ1Zzp2b2lkIDAsbG9hZDpmdW5jdGlvbihiKXtyZXR1cm4gYj8oYi5kZWZlcnJlZD1RLmRlZmVyKCksZC5jYWxsKHRoaXMsYixhKSxiLmRlZmVycmVkLnByb21pc2UpOlEud2hlbihudWxsKX0sYWJvcnQ6ZnVuY3Rpb24oKXt2YXIgYSxiLGQ9Yy5sZW5ndGg7Zm9yKGE9MDtkPmE7YSs9MSliPWNbYV0sY1thXT1udWxsLGIuYWJvcnQoKSxiPW51bGw7Yz1bXX19fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRnJhZ21lbnRMb2FkZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRnJhZ21lbnRMb2FkZXJ9LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5GcmFnbWVudE1vZGVsPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGEsYixjLGQsZSxmPVtdLGc9W10saD1bXSxpPTUsaj1mdW5jdGlvbihlKXt2YXIgZyxpPXRoaXM7Yi5jYWxsKGEsZSksZz1mdW5jdGlvbihiLGQpe2guc3BsaWNlKGguaW5kZXhPZihiKSwxKSxmLnB1c2goYiksYy5jYWxsKGEsYixkKSxiLmRlZmVycmVkPW51bGx9LGkuZnJhZ21lbnRMb2FkZXIubG9hZChlKS50aGVuKGcuYmluZChhLGUpLGQuYmluZChhLGUpKX0saz1mdW5jdGlvbihhLGIpe3ZhciBjPWZ1bmN0aW9uKGEsYyl7cmV0dXJuIGFbYl08Y1tiXT8tMTphW2JdPmNbYl0/MTowfTthLnNvcnQoYyl9LGw9ZnVuY3Rpb24oYSxiKXt2YXIgYyxkLGU9YS5sZW5ndGgtMTtmb3IoZD1lO2Q+PTA7ZC09MSlpZihjPWFbZF0sYy51cmw9PT1iLnVybCYmYy5zdGFydFRpbWU9PT1iLnN0YXJ0VGltZSlyZXR1cm4hMDtyZXR1cm4hMX0sbT1mdW5jdGlvbihhKXt2YXIgYj1mLmluZGV4T2YoYSk7LTEhPT1iJiZmLnNwbGljZShiLDEpfTtyZXR1cm57c3lzdGVtOnZvaWQgMCxkZWJ1Zzp2b2lkIDAsZnJhZ21lbnRMb2FkZXI6dm9pZCAwLHNldENvbnRleHQ6ZnVuY3Rpb24oYil7YT1ifSxnZXRDb250ZXh0OmZ1bmN0aW9uKCl7cmV0dXJuIGF9LGFkZFJlcXVlc3Q6ZnVuY3Rpb24oYSl7YSYmKGcucHVzaChhKSxrLmNhbGwodGhpcyxnLFwiaW5kZXhcIikpfSxzZXRDYWxsYmFja3M6ZnVuY3Rpb24oYSxmLGcsaCl7Yj1hLGU9aCxkPWcsYz1mfSxpc0ZyYWdtZW50TG9hZGVkT3JQZW5kaW5nOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYixjPXRoaXMsZD0hMSxlPWYubGVuZ3RoLTEsaT1lO2k+PTA7aS09MSlpZihiPWZbaV0sYS5zdGFydFRpbWU9PT1iLnN0YXJ0VGltZXx8XCJjb21wbGV0ZVwiPT09Yi5hY3Rpb24mJmEuYWN0aW9uPT09Yi5hY3Rpb24pe2lmKGMuZGVidWcubG9nKGEuc3RyZWFtVHlwZStcIiBGcmFnbWVudCBhbHJlYWR5IGxvYWRlZCBmb3IgdGltZTogXCIrYS5zdGFydFRpbWUpLGEudXJsPT09Yi51cmwpe2MuZGVidWcubG9nKGEuc3RyZWFtVHlwZStcIiBGcmFnbWVudCB1cmwgYWxyZWFkeSBsb2FkZWQ6IFwiK2EudXJsKSxkPSEwO2JyZWFrfW0oYSl9cmV0dXJuIGR8fChkPWwuY2FsbChjLGcsYSl8fGwuY2FsbChjLGgsYSkpLGR9LGlzUmVhZHk6ZnVuY3Rpb24oKXtyZXR1cm4gYS5pc1JlYWR5KCl9LGdldFBlbmRpbmdSZXF1ZXN0czpmdW5jdGlvbigpe3JldHVybiBnfSxnZXRMb2FkaW5nUmVxdWVzdHM6ZnVuY3Rpb24oKXtyZXR1cm4gaH0sZ2V0TG9hZGluZ1RpbWU6ZnVuY3Rpb24oKXt2YXIgYSxiLGM9MDtmb3IoYj1mLmxlbmd0aC0xO2I+PTA7Yi09MSlpZihhPWZbYl0sYS5yZXF1ZXN0RW5kRGF0ZSBpbnN0YW5jZW9mIERhdGUmJmEuZmlyc3RCeXRlRGF0ZSBpbnN0YW5jZW9mIERhdGUpe2M9YS5yZXF1ZXN0RW5kRGF0ZS5nZXRUaW1lKCktYS5maXJzdEJ5dGVEYXRlLmdldFRpbWUoKTticmVha31yZXR1cm4gY30sZ2V0RXhlY3V0ZWRSZXF1ZXN0Rm9yVGltZTpmdW5jdGlvbihhKXt2YXIgYixjPWYubGVuZ3RoLTEsZD0wLzAsZT0wLzAsZz1udWxsO2ZvcihiPWM7Yj49MDtiLT0xKWlmKGc9ZltiXSxkPWcuc3RhcnRUaW1lLGU9ZCtnLmR1cmF0aW9uLCFpc05hTihkKSYmIWlzTmFOKGUpJiZhPmQmJmU+YSlyZXR1cm4gZztyZXR1cm4gbnVsbH0scmVtb3ZlRXhlY3V0ZWRSZXF1ZXN0OmZ1bmN0aW9uKGEpe20uY2FsbCh0aGlzLGEpfSxyZW1vdmVFeGVjdXRlZFJlcXVlc3RzQmVmb3JlVGltZTpmdW5jdGlvbihhKXt2YXIgYixjPWYubGVuZ3RoLTEsZD0wLzAsZT1udWxsO2ZvcihiPWM7Yj49MDtiLT0xKWU9ZltiXSxkPWUuc3RhcnRUaW1lLCFpc05hTihkKSYmYT5kJiZtLmNhbGwodGhpcyxlKX0sY2FuY2VsUGVuZGluZ1JlcXVlc3RzOmZ1bmN0aW9uKCl7Zz1bXX0sYWJvcnRSZXF1ZXN0czpmdW5jdGlvbigpe3RoaXMuZnJhZ21lbnRMb2FkZXIuYWJvcnQoKSxoPVtdfSxleGVjdXRlQ3VycmVudFJlcXVlc3Q6ZnVuY3Rpb24oKXt2YXIgYixjPXRoaXM7aWYoMCE9PWcubGVuZ3RoJiYhKGgubGVuZ3RoPj1pKSlzd2l0Y2goYj1nLnNoaWZ0KCksYi5hY3Rpb24pe2Nhc2VcImNvbXBsZXRlXCI6Zi5wdXNoKGIpLGUuY2FsbChhLGIpO2JyZWFrO2Nhc2VcImRvd25sb2FkXCI6aC5wdXNoKGIpLGouY2FsbChjLGIpO2JyZWFrO2RlZmF1bHQ6dGhpcy5kZWJ1Zy5sb2coXCJVbmtub3duIHJlcXVlc3QgYWN0aW9uLlwiKX19fX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLkZyYWdtZW50TW9kZWwucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuRnJhZ21lbnRNb2RlbH0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0TG9hZGVyPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9MyxiPTUwMCxjPW51bGwsZD1mdW5jdGlvbihhKXt2YXIgYj1udWxsO3JldHVybi0xIT09YS5pbmRleE9mKFwiL1wiKSYmKGI9YS5zdWJzdHJpbmcoMCxhLmxhc3RJbmRleE9mKFwiL1wiKSsxKSksYn0sZT1mdW5jdGlvbihhLGYpe3ZhciBnPWQoYSksaD1uZXcgWE1MSHR0cFJlcXVlc3QsaT1uZXcgRGF0ZSxqPSEwLGs9dGhpczt0aGlzLmRlYnVnLmxvZyhcIlN0YXJ0IGxvYWRpbmcgbWFuaWZlc3Q6IFwiK2EpLGgub3BlbihcIkdFVFwiLGEsITApLGgub25sb2FkPWZ1bmN0aW9uKCl7aC5zdGF0dXM8MjAwfHxoLnN0YXR1cz4yOTl8fChqPSExLGsubWV0cmljc01vZGVsLmFkZEh0dHBSZXF1ZXN0KFwic3RyZWFtXCIsbnVsbCxcIk1QRFwiLGEsbnVsbCxudWxsLGksbmV3IERhdGUsaC5zdGF0dXMsbnVsbCxudWxsKSxrLnBhcnNlci5wYXJzZShoLnJlc3BvbnNlVGV4dCxnKS50aGVuKGZ1bmN0aW9uKGIpe2IubXBkVXJsPWEsYy5yZXNvbHZlKGIpfSxmdW5jdGlvbigpe2MucmVqZWN0KGgpfSkpfSxoLm9ubG9hZGVuZD1oLm9uZXJyb3I9ZnVuY3Rpb24oKXtqJiYoaj0hMSxrLm1ldHJpY3NNb2RlbC5hZGRIdHRwUmVxdWVzdChcInN0cmVhbVwiLG51bGwsXCJNUERcIixhLG51bGwsbnVsbCxpLG5ldyBEYXRlLGguc3RhdHVzLG51bGwsbnVsbCksZj4wPyhrLmRlYnVnLmxvZyhcIkZhaWxlZCBsb2FkaW5nIG1hbmlmZXN0OiBcIithK1wiLCByZXRyeSBpbiBcIitiK1wibXNcIitcIiBhdHRlbXB0czogXCIrZiksZi0tLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtlLmNhbGwoayxhLGYpfSxiKSk6KGsuZGVidWcubG9nKFwiRmFpbGVkIGxvYWRpbmcgbWFuaWZlc3Q6IFwiK2ErXCIgbm8gcmV0cnkgYXR0ZW1wdHMgbGVmdFwiKSxrLmVyckhhbmRsZXIuZG93bmxvYWRFcnJvcihcIm1hbmlmZXN0XCIsYSxoKSxjLnJlamVjdChoKSkpfSxoLnNlbmQoKX07cmV0dXJue2RlYnVnOnZvaWQgMCxwYXJzZXI6dm9pZCAwLGVyckhhbmRsZXI6dm9pZCAwLG1ldHJpY3NNb2RlbDp2b2lkIDAsbG9hZDpmdW5jdGlvbihiKXtyZXR1cm4gYz1RLmRlZmVyKCksZS5jYWxsKHRoaXMsYixhKSxjLnByb21pc2V9fX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0TG9hZGVyLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0TG9hZGVyfSxNZWRpYVBsYXllci5tb2RlbHMuTWFuaWZlc3RNb2RlbD1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhO3JldHVybntnZXRWYWx1ZTpmdW5jdGlvbigpe3JldHVybiBhfSxzZXRWYWx1ZTpmdW5jdGlvbihiKXthPWJ9fX0sTWVkaWFQbGF5ZXIubW9kZWxzLk1hbmlmZXN0TW9kZWwucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5tb2RlbHMuTWFuaWZlc3RNb2RlbH0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0VXBkYXRlcj1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPTAvMCxiPW51bGwsYz1udWxsLGQ9ZnVuY3Rpb24oKXtudWxsIT09YiYmKGNsZWFySW50ZXJ2YWwoYiksYj1udWxsKX0sZT1mdW5jdGlvbigpe2QuY2FsbCh0aGlzKSxpc05hTihhKXx8KHRoaXMuZGVidWcubG9nKFwiUmVmcmVzaCBtYW5pZmVzdCBpbiBcIithK1wiIHNlY29uZHMuXCIpLGI9c2V0SW50ZXJ2YWwoYy5iaW5kKHRoaXMpLDFlMyphLHRoaXMpKX0sZj1mdW5jdGlvbigpe3ZhciBiPXRoaXMsYz1iLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKTt2b2lkIDAhPT1jJiZudWxsIT09YyYmYi5tYW5pZmVzdEV4dC5nZXRSZWZyZXNoRGVsYXkoYykudGhlbihmdW5jdGlvbihjKXthPWMsZS5jYWxsKGIpfSl9O3JldHVybiBjPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcyxiPWEubWFuaWZlc3RNb2RlbC5nZXRWYWx1ZSgpLGM9Yi5tcGRVcmw7Yi5oYXNPd25Qcm9wZXJ0eShcIkxvY2F0aW9uXCIpJiYoYz1iLkxvY2F0aW9uKSxhLmRlYnVnLmxvZyhcIlJlZnJlc2ggbWFuaWZlc3QgQCBcIitjKSxhLm1hbmlmZXN0TG9hZGVyLmxvYWQoYykudGhlbihmdW5jdGlvbihiKXthLm1hbmlmZXN0TW9kZWwuc2V0VmFsdWUoYiksYS5kZWJ1Zy5sb2coXCJNYW5pZmVzdCBoYXMgYmVlbiByZWZyZXNoZWQuXCIpLGEuZGVidWcubG9nKGIpLGYuY2FsbChhKSxhLnN5c3RlbS5ub3RpZnkoXCJtYW5pZmVzdFVwZGF0ZWRcIil9KX0se2RlYnVnOnZvaWQgMCxzeXN0ZW06dm9pZCAwLG1hbmlmZXN0TW9kZWw6dm9pZCAwLG1hbmlmZXN0RXh0OnZvaWQgMCxtYW5pZmVzdExvYWRlcjp2b2lkIDAsc2V0dXA6ZnVuY3Rpb24oKXtmLmNhbGwodGhpcyl9LGluaXQ6ZnVuY3Rpb24oKXtmLmNhbGwodGhpcyl9LHN0b3A6ZnVuY3Rpb24oKXtkLmNhbGwodGhpcyl9fX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1hbmlmZXN0VXBkYXRlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5NYW5pZmVzdFVwZGF0ZXJ9LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5NZWRpYVNvdXJjZUV4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIn0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLk1lZGlhU291cmNlRXh0ZW5zaW9ucy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5NZWRpYVNvdXJjZUV4dGVuc2lvbnMsY3JlYXRlTWVkaWFTb3VyY2U6ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT1cIldlYktpdE1lZGlhU291cmNlXCJpbiB3aW5kb3csYj1cIk1lZGlhU291cmNlXCJpbiB3aW5kb3c7cmV0dXJuIGI/US53aGVuKG5ldyBNZWRpYVNvdXJjZSk6YT9RLndoZW4obmV3IFdlYktpdE1lZGlhU291cmNlKTpudWxsfSxhdHRhY2hNZWRpYVNvdXJjZTpmdW5jdGlvbihhLGIpe1widXNlIHN0cmljdFwiO3JldHVybiBiLnNldFNvdXJjZSh3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChhKSksUS53aGVuKCEwKX0sZGV0YWNoTWVkaWFTb3VyY2U6ZnVuY3Rpb24oYSl7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIGEuc2V0U291cmNlKFwiXCIpLFEud2hlbighMCl9LHNldER1cmF0aW9uOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7cmV0dXJuIGEuZHVyYXRpb249YixRLndoZW4oYS5kdXJhdGlvbil9LHNpZ25hbEVuZE9mU3RyZWFtOmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3JldHVybiBhLmVuZE9mU3RyZWFtKCksUS53aGVuKCEwKX19LE1lZGlhUGxheWVyLm1vZGVscy5NZXRyaWNzTW9kZWw9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjtyZXR1cm57c3lzdGVtOnZvaWQgMCxzdHJlYW1NZXRyaWNzOnt9LGNsZWFyQ3VycmVudE1ldHJpY3NGb3JUeXBlOmZ1bmN0aW9uKGEpe2RlbGV0ZSB0aGlzLnN0cmVhbU1ldHJpY3NbYV19LGNsZWFyQWxsQ3VycmVudE1ldHJpY3M6ZnVuY3Rpb24oKXt0aGlzLnN0cmVhbU1ldHJpY3M9e319LGdldFJlYWRPbmx5TWV0cmljc0ZvcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5zdHJlYW1NZXRyaWNzLmhhc093blByb3BlcnR5KGEpP3RoaXMuc3RyZWFtTWV0cmljc1thXTpudWxsfSxnZXRNZXRyaWNzRm9yOmZ1bmN0aW9uKGEpe3ZhciBiO3JldHVybiB0aGlzLnN0cmVhbU1ldHJpY3MuaGFzT3duUHJvcGVydHkoYSk/Yj10aGlzLnN0cmVhbU1ldHJpY3NbYV06KGI9dGhpcy5zeXN0ZW0uZ2V0T2JqZWN0KFwibWV0cmljc1wiKSx0aGlzLnN0cmVhbU1ldHJpY3NbYV09YiksYn0sYWRkVGNwQ29ubmVjdGlvbjpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIGc9bmV3IE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuVENQQ29ubmVjdGlvbjtyZXR1cm4gZy50Y3BpZD1iLGcuZGVzdD1jLGcudG9wZW49ZCxnLnRjbG9zZT1lLGcudGNvbm5lY3Q9Zix0aGlzLmdldE1ldHJpY3NGb3IoYSkuVGNwTGlzdC5wdXNoKGcpLGd9LGFkZEh0dHBSZXF1ZXN0OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpLGosayxsKXt2YXIgbT1uZXcgTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5IVFRQUmVxdWVzdDtyZXR1cm4gbS50Y3BpZD1iLG0udHlwZT1jLG0udXJsPWQsbS5hY3R1YWx1cmw9ZSxtLnJhbmdlPWYsbS50cmVxdWVzdD1nLG0udHJlc3BvbnNlPWgsbS50ZmluaXNoPWksbS5yZXNwb25zZWNvZGU9aixtLmludGVydmFsPWssbS5tZWRpYWR1cmF0aW9uPWwsdGhpcy5nZXRNZXRyaWNzRm9yKGEpLkh0dHBMaXN0LnB1c2gobSksbX0sYXBwZW5kSHR0cFRyYWNlOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPW5ldyBNZWRpYVBsYXllci52by5tZXRyaWNzLkhUVFBSZXF1ZXN0LlRyYWNlO3JldHVybiBlLnM9YixlLmQ9YyxlLmI9ZCxhLnRyYWNlLnB1c2goZSksZX0sYWRkUmVwcmVzZW50YXRpb25Td2l0Y2g6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgZj1uZXcgTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5SZXByZXNlbnRhdGlvblN3aXRjaDtyZXR1cm4gZi50PWIsZi5tdD1jLGYudG89ZCxmLmx0bz1lLHRoaXMuZ2V0TWV0cmljc0ZvcihhKS5SZXBTd2l0Y2hMaXN0LnB1c2goZiksZn0sYWRkQnVmZmVyTGV2ZWw6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPW5ldyBNZWRpYVBsYXllci52by5tZXRyaWNzLkJ1ZmZlckxldmVsO3JldHVybiBkLnQ9YixkLmxldmVsPWMsdGhpcy5nZXRNZXRyaWNzRm9yKGEpLkJ1ZmZlckxldmVsLnB1c2goZCksZH0sYWRkUGxheUxpc3Q6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bmV3IE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUGxheUxpc3Q7cmV0dXJuIGUuc3RhcnQ9YixlLm1zdGFydD1jLGUuc3RhcnR0eXBlPWQsdGhpcy5nZXRNZXRyaWNzRm9yKGEpLlBsYXlMaXN0LnB1c2goZSksZX0sYXBwZW5kUGxheUxpc3RUcmFjZTpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgpe3ZhciBpPW5ldyBNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlO3JldHVybiBpLnJlcHJlc2VudGF0aW9uaWQ9YixpLnN1YnJlcGxldmVsPWMsaS5zdGFydD1kLGkubXN0YXJ0PWUsaS5kdXJhdGlvbj1mLGkucGxheWJhY2tzcGVlZD1nLGkuc3RvcHJlYXNvbj1oLGEudHJhY2UucHVzaChpKSxpfX19LE1lZGlhUGxheWVyLm1vZGVscy5NZXRyaWNzTW9kZWwucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5tb2RlbHMuTWV0cmljc01vZGVsfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuUHJvdGVjdGlvbkNvbnRyb2xsZXI9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT1udWxsLGI9bnVsbCxjPWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXM7Yi5wcm90ZWN0aW9uTW9kZWwucmVtb3ZlS2V5U3lzdGVtKGEpfSxkPWZ1bmN0aW9uKGEsYyl7Zm9yKHZhciBkPXRoaXMsZT0wO2U8Yi5sZW5ndGg7KytlKWZvcih2YXIgZj0wO2Y8Yy5sZW5ndGg7KytmKWlmKGJbZV0uaXNTdXBwb3J0ZWQoY1tmXSkmJmQucHJvdGVjdGlvbkV4dC5zdXBwb3J0c0NvZGVjKGJbZV0ua2V5c1R5cGVTdHJpbmcsYSkpe3ZhciBnPWQubWFuaWZlc3RFeHQuZ2V0S0lEKGNbZl0pO3JldHVybiBnfHwoZz1cInVua25vd25cIiksZC5wcm90ZWN0aW9uTW9kZWwuYWRkS2V5U3lzdGVtKGcsY1tmXSxiW2VdKSxkLmRlYnVnLmxvZyhcIkRSTTogU2VsZWN0ZWQgS2V5IFN5c3RlbTogXCIrYltlXS5rZXlzVHlwZVN0cmluZytcIiBGb3IgS0lEOiBcIitnKSxnfXRocm93IG5ldyBFcnJvcihcIkRSTTogVGhlIHByb3RlY3Rpb24gc3lzdGVtIGZvciB0aGlzIGNvbnRlbnQgaXMgbm90IHN1cHBvcnRlZC5cIil9LGU9ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPXRoaXMsZT1udWxsLGY9bnVsbDtkLnByb3RlY3Rpb25Nb2RlbC5uZWVkVG9BZGRLZXlTZXNzaW9uKGEpJiYoZj1kLnByb3RlY3Rpb25Nb2RlbC5nZXRJbml0RGF0YShhKSwhZiYmYz8oZj1jLGQuZGVidWcubG9nKFwiRFJNOiBVc2luZyBpbml0ZGF0YSBmcm9tIG5lZWRza2V5IGV2ZW50LiBsZW5ndGg6IFwiK2YubGVuZ3RoKSk6ZiYmZC5kZWJ1Zy5sb2coXCJEUk06IFVzaW5nIGluaXRkYXRhIGZyb20gcHJoZWFkZXIgaW4gbXBkLiBsZW5ndGg6IFwiK2YubGVuZ3RoKSxmPyhlPWQucHJvdGVjdGlvbk1vZGVsLmFkZEtleVNlc3Npb24oYSxiLGYpLGQuZGVidWcubG9nKFwiRFJNOiBBZGRlZCBLZXkgU2Vzc2lvbiBbXCIrZS5zZXNzaW9uSWQrXCJdIGZvciBLSUQ6IFwiK2ErXCIgdHlwZTogXCIrYitcIiBpbml0RGF0YSBsZW5ndGg6IFwiK2YubGVuZ3RoKSk6ZC5kZWJ1Zy5sb2coXCJEUk06IGluaXRkYXRhIGlzIG51bGwuXCIpKX0sZj1mdW5jdGlvbihhLGIsYyxkKXt2YXIgZSxmPXRoaXM7cmV0dXJuIGU9Zi5wcm90ZWN0aW9uTW9kZWwudXBkYXRlRnJvbU1lc3NhZ2UoYSxjLGQpLGUudGhlbihmdW5jdGlvbihhKXtiLnVwZGF0ZShhKX0pLGV9O3JldHVybntzeXN0ZW06dm9pZCAwLGRlYnVnOnZvaWQgMCxtYW5pZmVzdEV4dDp2b2lkIDAsY2FwYWJpbGl0aWVzOnZvaWQgMCx2aWRlb01vZGVsOnZvaWQgMCxwcm90ZWN0aW9uTW9kZWw6dm9pZCAwLHByb3RlY3Rpb25FeHQ6dm9pZCAwLHNldHVwOmZ1bmN0aW9uKCl7Yj10aGlzLnByb3RlY3Rpb25FeHQuZ2V0S2V5U3lzdGVtcygpfSxpbml0OmZ1bmN0aW9uKGIsYyl7dGhpcy52aWRlb01vZGVsPWIsdGhpcy5wcm90ZWN0aW9uTW9kZWw9YyxhPXRoaXMudmlkZW9Nb2RlbC5nZXRFbGVtZW50KClcclxufSxzZWxlY3RLZXlTeXN0ZW06ZCxlbnN1cmVLZXlTZXNzaW9uOmUsdXBkYXRlRnJvbU1lc3NhZ2U6Zix0ZWFyZG93bktleVN5c3RlbTpjfX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25Db250cm9sbGVyLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25Db250cm9sbGVyfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuUHJvdGVjdGlvbkV4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIn0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25FeHRlbnNpb25zLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlByb3RlY3Rpb25FeHRlbnNpb25zLHN1cHBvcnRzQ29kZWM6ZnVuY3Rpb24oYSxiKXtcInVzZSBzdHJpY3RcIjt2YXIgYz1cIldlYktpdE1lZGlhS2V5c1wiaW4gd2luZG93LGQ9XCJNU01lZGlhS2V5c1wiaW4gd2luZG93LGU9XCJNZWRpYUtleXNcImluIHdpbmRvdztyZXR1cm4gZT9NZWRpYUtleXMuaXNUeXBlU3VwcG9ydGVkKGEsYik6Yz9XZWJLaXRNZWRpYUtleXMuaXNUeXBlU3VwcG9ydGVkKGEsYik6ZD9NU01lZGlhS2V5cy5pc1R5cGVTdXBwb3J0ZWQoYSxiKTohMX0sY3JlYXRlTWVkaWFLZXlzOmZ1bmN0aW9uKGEpe1widXNlIHN0cmljdFwiO3ZhciBiPVwiV2ViS2l0TWVkaWFLZXlzXCJpbiB3aW5kb3csYz1cIk1TTWVkaWFLZXlzXCJpbiB3aW5kb3csZD1cIk1lZGlhS2V5c1wiaW4gd2luZG93O3JldHVybiBkP25ldyBNZWRpYUtleXMoYSk6Yj9uZXcgV2ViS2l0TWVkaWFLZXlzKGEpOmM/bmV3IE1TTWVkaWFLZXlzKGEpOm51bGx9LHNldE1lZGlhS2V5OmZ1bmN0aW9uKGEsYil7dmFyIGM9XCJXZWJLaXRTZXRNZWRpYUtleXNcImluIGEsZD1cIm1zU2V0TWVkaWFLZXlzXCJpbiBhLGU9XCJTZXRNZWRpYUtleXNcImluIGE7cmV0dXJuIGU/YS5TZXRNZWRpYUtleXMoYik6Yz9hLldlYktpdFNldE1lZGlhS2V5cyhiKTpkP2EubXNTZXRNZWRpYUtleXMoYik6KHRoaXMuZGVidWcubG9nKFwibm8gc2V0bWVkaWFrZXlzIGZ1bmN0aW9uIGluIGVsZW1lbnRcIiksdm9pZCAwKX0sY3JlYXRlU2Vzc2lvbjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGEuY3JlYXRlU2Vzc2lvbihiLGMpfSxnZXRLZXlTeXN0ZW1zOmZ1bmN0aW9uKCl7dmFyIGE9ZnVuY3Rpb24oYSxiKXt2YXIgYz1RLmRlZmVyKCksZD1udWxsLGU9W10sZj1uZXcgRE9NUGFyc2VyLGc9Zi5wYXJzZUZyb21TdHJpbmcoYSxcImFwcGxpY2F0aW9uL3htbFwiKTtpZighZy5nZXRFbGVtZW50c0J5VGFnTmFtZShcIkNoYWxsZW5nZVwiKVswXSlyZXR1cm4gYy5yZWplY3QoXCJEUk06IHBsYXlyZWFkeSB1cGRhdGUsIGNhbiBub3QgZmluZCBDaGFsbGVuZ2UgaW4ga2V5TWVzc2FnZVwiKSxjLnByb21pc2U7dmFyIGg9Zy5nZXRFbGVtZW50c0J5VGFnTmFtZShcIkNoYWxsZW5nZVwiKVswXS5jaGlsZE5vZGVzWzBdLm5vZGVWYWx1ZTtoJiYoZD1CQVNFNjQuZGVjb2RlKGgpKTt2YXIgaT1nLmdldEVsZW1lbnRzQnlUYWdOYW1lKFwibmFtZVwiKSxqPWcuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJ2YWx1ZVwiKTtpZihpLmxlbmd0aCE9ai5sZW5ndGgpcmV0dXJuIGMucmVqZWN0KFwiRFJNOiBwbGF5cmVhZHkgdXBkYXRlLCBpbnZhbGlkIGhlYWRlciBuYW1lL3ZhbHVlIHBhaXIgaW4ga2V5TWVzc2FnZVwiKSxjLnByb21pc2U7Zm9yKHZhciBrPTA7azxpLmxlbmd0aDtrKyspZVtrXT17bmFtZTppW2tdLmNoaWxkTm9kZXNbMF0ubm9kZVZhbHVlLHZhbHVlOmpba10uY2hpbGROb2Rlc1swXS5ub2RlVmFsdWV9O3ZhciBsPW5ldyBYTUxIdHRwUmVxdWVzdDtyZXR1cm4gbC5vbmxvYWQ9ZnVuY3Rpb24oKXsyMDA9PWwuc3RhdHVzP2MucmVzb2x2ZShuZXcgVWludDhBcnJheShsLnJlc3BvbnNlKSk6Yy5yZWplY3QoJ0RSTTogcGxheXJlYWR5IHVwZGF0ZSwgWEhSIHN0YXR1cyBpcyBcIicrbC5zdGF0dXNUZXh0KydcIiAoJytsLnN0YXR1cytcIiksIGV4cGVjdGVkIHRvIGJlIDIwMC4gcmVhZHlTdGF0ZSBpcyBcIitsLnJlYWR5U3RhdGUpfSxsLm9uYWJvcnQ9ZnVuY3Rpb24oKXtjLnJlamVjdCgnRFJNOiBwbGF5cmVhZHkgdXBkYXRlLCBYSFIgYWJvcnRlZC4gc3RhdHVzIGlzIFwiJytsLnN0YXR1c1RleHQrJ1wiICgnK2wuc3RhdHVzK1wiKSwgcmVhZHlTdGF0ZSBpcyBcIitsLnJlYWR5U3RhdGUpfSxsLm9uZXJyb3I9ZnVuY3Rpb24oKXtjLnJlamVjdCgnRFJNOiBwbGF5cmVhZHkgdXBkYXRlLCBYSFIgZXJyb3IuIHN0YXR1cyBpcyBcIicrbC5zdGF0dXNUZXh0KydcIiAoJytsLnN0YXR1cytcIiksIHJlYWR5U3RhdGUgaXMgXCIrbC5yZWFkeVN0YXRlKX0sbC5vcGVuKFwiUE9TVFwiLGIpLGwucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIixlJiZlLmZvckVhY2goZnVuY3Rpb24oYSl7bC5zZXRSZXF1ZXN0SGVhZGVyKGEubmFtZSxhLnZhbHVlKX0pLGwuc2VuZChkKSxjLnByb21pc2V9LGI9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbD09PWEmJjA9PT1iLmxlbmd0aH0sYz1mdW5jdGlvbihhKXt2YXIgYj0wLGM9MCxkPTAsZT1uZXcgVWludDhBcnJheShbMTEyLDExNSwxMTUsMTA0LDAsMCwwLDBdKSxmPW5ldyBVaW50OEFycmF5KFsxNTQsNCwyNDAsMTIxLDE1Miw2NCw2NiwxMzQsMTcxLDE0NiwyMzAsOTEsMjI0LDEzNiw5NSwxNDldKSxnPW51bGwsaD1udWxsLGk9bnVsbCxqPW51bGw7aWYoXCJwcm9cImluIGEpZz1CQVNFNjQuZGVjb2RlQXJyYXkoYS5wcm8uX190ZXh0KTtlbHNle2lmKCEoXCJwcmhlYWRlclwiaW4gYSkpcmV0dXJuIG51bGw7Zz1CQVNFNjQuZGVjb2RlQXJyYXkoYS5wcmhlYWRlci5fX3RleHQpfXJldHVybiBjPWcubGVuZ3RoLGQ9NCtlLmxlbmd0aCtmLmxlbmd0aCs0K2MsaD1uZXcgQXJyYXlCdWZmZXIoZCksaT1uZXcgVWludDhBcnJheShoKSxqPW5ldyBEYXRhVmlldyhoKSxqLnNldFVpbnQzMihiLGQpLGIrPTQsaS5zZXQoZSxiKSxiKz1lLmxlbmd0aCxpLnNldChmLGIpLGIrPWYubGVuZ3RoLGouc2V0VWludDMyKGIsYyksYis9NCxpLnNldChnLGIpLGIrPWMsaX07cmV0dXJuW3tzY2hlbWVJZFVyaTpcInVybjp1dWlkOjlhMDRmMDc5LTk4NDAtNDI4Ni1hYjkyLWU2NWJlMDg4NWY5NVwiLGtleXNUeXBlU3RyaW5nOlwiY29tLm1pY3Jvc29mdC5wbGF5cmVhZHlcIixpc1N1cHBvcnRlZDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5zY2hlbWVJZFVyaT09PWEuc2NoZW1lSWRVcmkudG9Mb3dlckNhc2UoKX0sbmVlZFRvQWRkS2V5U2Vzc2lvbjpiLGdldEluaXREYXRhOmMsZ2V0VXBkYXRlOmF9LHtzY2hlbWVJZFVyaTpcInVybjptcGVnOmRhc2g6bXA0cHJvdGVjdGlvbjoyMDExXCIsa2V5c1R5cGVTdHJpbmc6XCJjb20ubWljcm9zb2Z0LnBsYXlyZWFkeVwiLGlzU3VwcG9ydGVkOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnNjaGVtZUlkVXJpPT09YS5zY2hlbWVJZFVyaS50b0xvd2VyQ2FzZSgpJiZcImNlbmNcIj09PWEudmFsdWUudG9Mb3dlckNhc2UoKX0sbmVlZFRvQWRkS2V5U2Vzc2lvbjpiLGdldEluaXREYXRhOmZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGdldFVwZGF0ZTphfSx7c2NoZW1lSWRVcmk6XCJ1cm46dXVpZDowMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDBcIixrZXlzVHlwZVN0cmluZzpcIndlYmtpdC1vcmcudzMuY2xlYXJrZXlcIixpc1N1cHBvcnRlZDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5zY2hlbWVJZFVyaT09PWEuc2NoZW1lSWRVcmkudG9Mb3dlckNhc2UoKX0sbmVlZFRvQWRkS2V5U2Vzc2lvbjpmdW5jdGlvbigpe3JldHVybiEwfSxnZXRJbml0RGF0YTpmdW5jdGlvbigpe3JldHVybiBudWxsfSxnZXRVcGRhdGU6ZnVuY3Rpb24oYSl7cmV0dXJuIFEud2hlbihhKX19XX0sYWRkS2V5OmZ1bmN0aW9uKGEsYixjLGQsZSl7YS53ZWJraXRBZGRLZXkoYixjLGQsZSl9LGdlbmVyYXRlS2V5UmVxdWVzdDpmdW5jdGlvbihhLGIsYyl7YS53ZWJraXRHZW5lcmF0ZUtleVJlcXVlc3QoYixjKX0sbGlzdGVuVG9OZWVkS2V5OmZ1bmN0aW9uKGEsYil7YS5saXN0ZW4oXCJ3ZWJraXRuZWVka2V5XCIsYiksYS5saXN0ZW4oXCJtc25lZWRrZXlcIixiKSxhLmxpc3RlbihcIm5lZWRLZXlcIixiKX0sbGlzdGVuVG9LZXlFcnJvcjpmdW5jdGlvbihhLGIpe2EuYWRkRXZlbnRMaXN0ZW5lcihcIndlYmtpdGtleWVycm9yXCIsYiwhMSksYS5hZGRFdmVudExpc3RlbmVyKFwibXNrZXllcnJvclwiLGIsITEpLGEuYWRkRXZlbnRMaXN0ZW5lcihcImtleWVycm9yXCIsYiwhMSl9LGxpc3RlblRvS2V5TWVzc2FnZTpmdW5jdGlvbihhLGIpe2EuYWRkRXZlbnRMaXN0ZW5lcihcIndlYmtpdGtleW1lc3NhZ2VcIixiLCExKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJtc2tleW1lc3NhZ2VcIixiLCExKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJrZXltZXNzYWdlXCIsYiwhMSl9LGxpc3RlblRvS2V5QWRkZWQ6ZnVuY3Rpb24oYSxiKXthLmFkZEV2ZW50TGlzdGVuZXIoXCJ3ZWJraXRrZXlhZGRlZFwiLGIsITEpLGEuYWRkRXZlbnRMaXN0ZW5lcihcIm1za2V5YWRkZWRcIixiLCExKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJrZXlhZGRlZFwiLGIsITEpfSx1bmxpc3RlblRvS2V5RXJyb3I6ZnVuY3Rpb24oYSxiKXthLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJ3ZWJraXRrZXllcnJvclwiLGIpLGEucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1za2V5ZXJyb3JcIixiKSxhLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXllcnJvclwiLGIpfSx1bmxpc3RlblRvS2V5TWVzc2FnZTpmdW5jdGlvbihhLGIpe2EucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIndlYmtpdGtleW1lc3NhZ2VcIixiKSxhLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtc2tleW1lc3NhZ2VcIixiKSxhLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXltZXNzYWdlXCIsYil9LHVubGlzdGVuVG9LZXlBZGRlZDpmdW5jdGlvbihhLGIpe2EucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIndlYmtpdGtleWFkZGVkXCIsYiksYS5yZW1vdmVFdmVudExpc3RlbmVyKFwibXNrZXlhZGRlZFwiLGIpLGEucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImtleWFkZGVkXCIsYil9fSxNZWRpYVBsYXllci5tb2RlbHMuUHJvdGVjdGlvbk1vZGVsPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9bnVsbCxiPW51bGwsYz1udWxsLGQ9bnVsbCxlPVtdO3JldHVybntzeXN0ZW06dm9pZCAwLHZpZGVvTW9kZWw6dm9pZCAwLHByb3RlY3Rpb25FeHQ6dm9pZCAwLHNldHVwOmZ1bmN0aW9uKCl7YT10aGlzLnZpZGVvTW9kZWwuZ2V0RWxlbWVudCgpfSxpbml0OmZ1bmN0aW9uKGIpe3RoaXMudmlkZW9Nb2RlbD1iLGE9dGhpcy52aWRlb01vZGVsLmdldEVsZW1lbnQoKX0sYWRkS2V5U2Vzc2lvbjpmdW5jdGlvbihhLGYsZyl7dmFyIGg9bnVsbDtyZXR1cm4gaD10aGlzLnByb3RlY3Rpb25FeHQuY3JlYXRlU2Vzc2lvbihlW2FdLmtleXMsZixnKSx0aGlzLnByb3RlY3Rpb25FeHQubGlzdGVuVG9LZXlBZGRlZChoLGIpLHRoaXMucHJvdGVjdGlvbkV4dC5saXN0ZW5Ub0tleUVycm9yKGgsYyksdGhpcy5wcm90ZWN0aW9uRXh0Lmxpc3RlblRvS2V5TWVzc2FnZShoLGQpLGVbYV0uaW5pdERhdGE9ZyxlW2FdLmtleVNlc3Npb25zLnB1c2goaCksaH0sYWRkS2V5U3lzdGVtOmZ1bmN0aW9uKGIsYyxkKXt2YXIgZj1udWxsO2Y9dGhpcy5wcm90ZWN0aW9uRXh0LmNyZWF0ZU1lZGlhS2V5cyhkLmtleXNUeXBlU3RyaW5nKSx0aGlzLnByb3RlY3Rpb25FeHQuc2V0TWVkaWFLZXkoYSxmKSxlW2JdPXtrSUQ6Yixjb250ZW50UHJvdGVjdGlvbjpjLGtleVN5c3RlbTpkLGtleXM6Zixpbml0RGF0YTpudWxsLGtleVNlc3Npb25zOltdfX0scmVtb3ZlS2V5U3lzdGVtOmZ1bmN0aW9uKGEpe2lmKG51bGwhPT1hJiZ2b2lkIDAhPT1lW2FdJiYwIT09ZVthXS5rZXlTZXNzaW9ucy5sZW5ndGgpe2Zvcih2YXIgZj1lW2FdLmtleVNlc3Npb25zLGc9MDtnPGYubGVuZ3RoOysrZyl0aGlzLnByb3RlY3Rpb25FeHQudW5saXN0ZW5Ub0tleUVycm9yKGZbZ10sYyksdGhpcy5wcm90ZWN0aW9uRXh0LnVubGlzdGVuVG9LZXlBZGRlZChmW2ddLGIpLHRoaXMucHJvdGVjdGlvbkV4dC51bmxpc3RlblRvS2V5TWVzc2FnZShmW2ddLGQpLGZbZ10uY2xvc2UoKTtlW2FdPXZvaWQgMH19LG5lZWRUb0FkZEtleVNlc3Npb246ZnVuY3Rpb24oYSl7dmFyIGI9bnVsbDtyZXR1cm4gYj1lW2FdLGIua2V5U3lzdGVtLm5lZWRUb0FkZEtleVNlc3Npb24oYi5pbml0RGF0YSxiLmtleVNlc3Npb25zKX0sZ2V0SW5pdERhdGE6ZnVuY3Rpb24oYSl7dmFyIGI9bnVsbDtyZXR1cm4gYj1lW2FdLGIua2V5U3lzdGVtLmdldEluaXREYXRhKGIuY29udGVudFByb3RlY3Rpb24pfSx1cGRhdGVGcm9tTWVzc2FnZTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGVbYV0ua2V5U3lzdGVtLmdldFVwZGF0ZShiLGMpfSxsaXN0ZW5Ub05lZWRLZXk6ZnVuY3Rpb24oYSl7dGhpcy5wcm90ZWN0aW9uRXh0Lmxpc3RlblRvTmVlZEtleSh0aGlzLnZpZGVvTW9kZWwsYSl9LGxpc3RlblRvS2V5RXJyb3I6ZnVuY3Rpb24oYSl7Yz1hO2Zvcih2YXIgYj0wO2I8ZS5sZW5ndGg7KytiKWZvcih2YXIgZD1lW2JdLmtleVNlc3Npb25zLGY9MDtmPGQubGVuZ3RoOysrZil0aGlzLnByb3RlY3Rpb25FeHQubGlzdGVuVG9LZXlFcnJvcihkW2ZdLGEpfSxsaXN0ZW5Ub0tleU1lc3NhZ2U6ZnVuY3Rpb24oYSl7ZD1hO2Zvcih2YXIgYj0wO2I8ZS5sZW5ndGg7KytiKWZvcih2YXIgYz1lW2JdLmtleVNlc3Npb25zLGY9MDtmPGMubGVuZ3RoOysrZil0aGlzLnByb3RlY3Rpb25FeHQubGlzdGVuVG9LZXlNZXNzYWdlKGNbZl0sYSl9LGxpc3RlblRvS2V5QWRkZWQ6ZnVuY3Rpb24oYSl7Yj1hO2Zvcih2YXIgYz0wO2M8ZS5sZW5ndGg7KytjKWZvcih2YXIgZD1lW2NdLmtleVNlc3Npb25zLGY9MDtmPGQubGVuZ3RoOysrZil0aGlzLnByb3RlY3Rpb25FeHQubGlzdGVuVG9LZXlBZGRlZChkW2ZdLGEpfX19LE1lZGlhUGxheWVyLm1vZGVscy5Qcm90ZWN0aW9uTW9kZWwucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5tb2RlbHMuUHJvdGVjdGlvbk1vZGVsfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuUmVxdWVzdFNjaGVkdWxlcj1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhPVtdLGI9bnVsbCxjPW51bGwsZD1mdW5jdGlvbihhLGIpe2lmKGEmJmIpe3ZhciBjPWcoYSk7Y3x8KGM9ZS5jYWxsKHRoaXMsYSkpLGMuc2V0SXNTY2hlZHVsZWQoITApLGMuc2V0U2NoZWR1bGVkVGFzayhiKSxqLmNhbGwodGhpcyksYi5jYWxsKGEpfX0sZT1mdW5jdGlvbihiKXtpZighYilyZXR1cm4gbnVsbDt2YXIgYz10aGlzLnN5c3RlbS5nZXRPYmplY3QoXCJzY2hlZHVsZXJNb2RlbFwiKTtyZXR1cm4gYy5zZXRDb250ZXh0KGIpLGEucHVzaChjKSxjfSxmPWZ1bmN0aW9uKGIpe3ZhciBjPWEuaW5kZXhPZihiKTstMSE9PWMmJmEuc3BsaWNlKGMsMSl9LGc9ZnVuY3Rpb24oYil7Zm9yKHZhciBjPTA7YzxhLmxlbmd0aDtjKyspaWYoYVtjXS5nZXRDb250ZXh0KCk9PT1iKXJldHVybiBhW2NdO3JldHVybiBudWxsfSxoPWZ1bmN0aW9uKCl7aS5jYWxsKHRoaXMpfSxpPWZ1bmN0aW9uKCl7Zm9yKHZhciBiLGM9MDtjPGEubGVuZ3RoO2MrKyliPWFbY10sYi5nZXRJc1NjaGVkdWxlZCgpJiZiLmV4ZWN1dGVTY2hlZHVsZWRUYXNrKCl9LGo9ZnVuY3Rpb24oKXtudWxsPT09YyYmKHRoaXMuYWRqdXN0RXhlY3V0ZUludGVydmFsKCksYz1zZXRJbnRlcnZhbChoLmJpbmQodGhpcyksYikpfSxrPWZ1bmN0aW9uKGIpe3ZhciBjPWcoYik7YyYmKGYoYyksMD09PWEubGVuZ3RoJiZsLmNhbGwodGhpcykpfSxsPWZ1bmN0aW9uKCl7Y2xlYXJJbnRlcnZhbChjKSxjPW51bGx9O3JldHVybntzeXN0ZW06dm9pZCAwLGRlYnVnOnZvaWQgMCxzY2hlZHVsZXJFeHQ6dm9pZCAwLGlzU2NoZWR1bGVkOmZ1bmN0aW9uKGEpe3ZhciBiPWcoYSk7cmV0dXJuISFiJiZiLmdldElzU2NoZWR1bGVkKCl9LGdldEV4ZWN1dGVJbnRlcnZhbDpmdW5jdGlvbigpe3JldHVybiBifSxhZGp1c3RFeGVjdXRlSW50ZXJ2YWw6ZnVuY3Rpb24oKXtpZighKGEubGVuZ3RoPDEpKXt2YXIgZD10aGlzLnNjaGVkdWxlckV4dC5nZXRFeGVjdXRlSW50ZXJ2YWwoYVswXS5nZXRDb250ZXh0KCkpO2IhPT1kJiYoYj1kLG51bGwhPT1jJiYodGhpcy5kZWJ1Zy5sb2coXCJDaGFuZ2luZyBleGVjdXRlIGludGVydmFsOiBcIitiKSxjbGVhckludGVydmFsKGMpLGM9c2V0SW50ZXJ2YWwoaC5iaW5kKHRoaXMpLGIpKSl9fSxzdGFydFNjaGVkdWxpbmc6ZCxzdG9wU2NoZWR1bGluZzprfX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlJlcXVlc3RTY2hlZHVsZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuUmVxdWVzdFNjaGVkdWxlcn0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNjaGVkdWxlckV4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIn0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNjaGVkdWxlckV4dGVuc2lvbnMucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU2NoZWR1bGVyRXh0ZW5zaW9ucyxnZXRFeGVjdXRlSW50ZXJ2YWw6ZnVuY3Rpb24oYSl7dmFyIGI9MWUzO3JldHVyblwidW5kZWZpbmVkXCIhPXR5cGVvZiBhLmdldE1pbkJ1ZmZlclRpbWUmJihiPTFlMyphLmdldE1pbkJ1ZmZlclRpbWUoKS80LGI9TWF0aC5tYXgoYiwxZTMpKSxifX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNjaGVkdWxlck1vZGVsPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGEsYixjPSExO3JldHVybntzeXN0ZW06dm9pZCAwLGRlYnVnOnZvaWQgMCxzY2hlZHVsZXJFeHQ6dm9pZCAwLHNldENvbnRleHQ6ZnVuY3Rpb24oYil7YT1ifSxnZXRDb250ZXh0OmZ1bmN0aW9uKCl7cmV0dXJuIGF9LHNldFNjaGVkdWxlZFRhc2s6ZnVuY3Rpb24oYSl7Yj1hfSxleGVjdXRlU2NoZWR1bGVkVGFzazpmdW5jdGlvbigpe2IuY2FsbChhKX0sc2V0SXNTY2hlZHVsZWQ6ZnVuY3Rpb24oYSl7Yz1hfSxnZXRJc1NjaGVkdWxlZDpmdW5jdGlvbigpe3JldHVybiBjfX19LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5TY2hlZHVsZXJNb2RlbC5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5TY2hlZHVsZXJNb2RlbH0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNvdXJjZUJ1ZmZlckV4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt0aGlzLnN5c3RlbT12b2lkIDAsdGhpcy5tYW5pZmVzdEV4dD12b2lkIDB9LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5Tb3VyY2VCdWZmZXJFeHRlbnNpb25zLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlNvdXJjZUJ1ZmZlckV4dGVuc2lvbnMsY3JlYXRlU291cmNlQnVmZmVyOmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7dmFyIGM9US5kZWZlcigpLGQ9dGhpczt0cnl7Yy5yZXNvbHZlKGEuYWRkU291cmNlQnVmZmVyKGIpKX1jYXRjaChlKXtkLm1hbmlmZXN0RXh0LmdldElzVGV4dFRyYWNrKGIpP2MucmVzb2x2ZShkLnN5c3RlbS5nZXRPYmplY3QoXCJ0ZXh0VlRUU291cmNlQnVmZmVyXCIpKTpjLnJlamVjdChlLmRlc2NyaXB0aW9uKX1yZXR1cm4gYy5wcm9taXNlfSxyZW1vdmVTb3VyY2VCdWZmZXI6ZnVuY3Rpb24oYSxiKXtcInVzZSBzdHJpY3RcIjt2YXIgYz1RLmRlZmVyKCk7dHJ5e2MucmVzb2x2ZShhLnJlbW92ZVNvdXJjZUJ1ZmZlcihiKSl9Y2F0Y2goZCl7Yy5yZWplY3QoZC5kZXNjcmlwdGlvbil9cmV0dXJuIGMucHJvbWlzZX0sZ2V0QnVmZmVyUmFuZ2U6ZnVuY3Rpb24oYSxiLGMpe1widXNlIHN0cmljdFwiO3ZhciBkLGUsZj1udWxsLGc9MCxoPTAsaT1udWxsLGo9bnVsbCxrPTAsbD1jfHwuMTU7dHJ5e2Y9YS5idWZmZXJlZH1jYXRjaChtKXtyZXR1cm4gUS53aGVuKG51bGwpfWlmKG51bGwhPT1mKXtmb3IoZT0wLGQ9Zi5sZW5ndGg7ZD5lO2UrPTEpaWYoZz1mLnN0YXJ0KGUpLGg9Zi5lbmQoZSksbnVsbD09PWkpe2lmKGs9TWF0aC5hYnMoZy1iKSxiPj1nJiZoPmIpe2k9ZyxqPWg7Y29udGludWV9aWYobD49ayl7aT1nLGo9aDtjb250aW51ZX19ZWxzZXtpZihrPWctaiwhKGw+PWspKWJyZWFrO2o9aH1pZihudWxsIT09aSlyZXR1cm4gUS53aGVuKHtzdGFydDppLGVuZDpqfSl9cmV0dXJuIFEud2hlbihudWxsKX0sZ2V0QWxsUmFuZ2VzOmZ1bmN0aW9uKGEpe3ZhciBiPW51bGw7dHJ5e3JldHVybiBiPWEuYnVmZmVyZWQsUS53aGVuKGIpfWNhdGNoKGMpe3JldHVybiBRLndoZW4obnVsbCl9fSxnZXRCdWZmZXJMZW5ndGg6ZnVuY3Rpb24oYSxiLGMpe1widXNlIHN0cmljdFwiO3ZhciBkPXRoaXMsZT1RLmRlZmVyKCk7cmV0dXJuIGQuZ2V0QnVmZmVyUmFuZ2UoYSxiLGMpLnRoZW4oZnVuY3Rpb24oYSl7bnVsbD09PWE/ZS5yZXNvbHZlKDApOmUucmVzb2x2ZShhLmVuZC1iKX0pLGUucHJvbWlzZX0sd2FpdEZvclVwZGF0ZUVuZDpmdW5jdGlvbihhKXtcInVzZSBzdHJpY3RcIjt2YXIgYixjPVEuZGVmZXIoKSxkPTUwLGU9ZnVuY3Rpb24oKXthLnVwZGF0aW5nfHwoY2xlYXJJbnRlcnZhbChiKSxjLnJlc29sdmUoITApKX0sZj1mdW5jdGlvbigpe2EucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInVwZGF0ZWVuZFwiLGYsITEpLGMucmVzb2x2ZSghMCl9O2lmKGEuaGFzT3duUHJvcGVydHkoXCJhZGRFdmVudExpc3RlbmVyXCIpKXRyeXthLmFkZEV2ZW50TGlzdGVuZXIoXCJ1cGRhdGVlbmRcIixmLCExKX1jYXRjaChnKXtiPXNldEludGVydmFsKGUsZCl9ZWxzZSBiPXNldEludGVydmFsKGUsZCk7cmV0dXJuIGMucHJvbWlzZX0sYXBwZW5kOmZ1bmN0aW9uKGEsYil7dmFyIGM9US5kZWZlcigpO3RyeXtcImFwcGVuZFwiaW4gYT9hLmFwcGVuZChiKTpcImFwcGVuZEJ1ZmZlclwiaW4gYSYmYS5hcHBlbmRCdWZmZXIoYiksdGhpcy53YWl0Rm9yVXBkYXRlRW5kKGEpLnRoZW4oZnVuY3Rpb24oKXtjLnJlc29sdmUoKX0pfWNhdGNoKGQpe2MucmVqZWN0KHtlcnI6ZCxkYXRhOmJ9KX1yZXR1cm4gYy5wcm9taXNlfSxyZW1vdmU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgZj1RLmRlZmVyKCk7dHJ5e2I+PTAmJmQ+YiYmYz5iJiZcImVuZGVkXCIhPT1lLnJlYWR5U3RhdGUmJmEucmVtb3ZlKGIsYyksdGhpcy53YWl0Rm9yVXBkYXRlRW5kKGEpLnRoZW4oZnVuY3Rpb24oKXtmLnJlc29sdmUoKX0pfWNhdGNoKGcpe2YucmVqZWN0KGcpfXJldHVybiBmLnByb21pc2V9LGFib3J0OmZ1bmN0aW9uKGEsYil7XCJ1c2Ugc3RyaWN0XCI7dmFyIGM9US5kZWZlcigpO3RyeXtcIm9wZW5cIj09PWEucmVhZHlTdGF0ZSYmYi5hYm9ydCgpLGMucmVzb2x2ZSgpfWNhdGNoKGQpe2MucmVqZWN0KGQuZGVzY3JpcHRpb24pfXJldHVybiBjLnByb21pc2V9fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU3RyZWFtPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGEsYixjLGQsZSxmLGcsaCxpLGosayxsLG0sbixvLHAscT1udWxsLHI9bnVsbCxzPW51bGwsdD1udWxsLHU9LTEsdj1udWxsLHc9LTEseD1udWxsLHk9LTEsej0hMCxBPSExLEI9ITEsQz1udWxsLEQ9W10sRT0tMSxGPW51bGwsRz1mdW5jdGlvbigpe3RoaXMuZGVidWcubG9nKFwiQXR0ZW1wdGluZyBwbGF5Li4uXCIpLEEmJih0aGlzLmRlYnVnLmxvZyhcIkRvIHBsYXkuXCIpLHRoaXMudmlkZW9Nb2RlbC5wbGF5KCkpfSxIPWZ1bmN0aW9uKCl7dGhpcy5kZWJ1Zy5sb2coXCJEbyBwYXVzZS5cIiksdGhpcy52aWRlb01vZGVsLnBhdXNlKCl9LEk9ZnVuY3Rpb24oYSl7dGhpcy5kZWJ1Zy5sb2coXCJBdHRlbXB0aW5nIHNlZWsuLi5cIiksQSYmKHRoaXMuZGVidWcubG9nKFwiRG8gc2VlazogXCIrYSksdGhpcy5zeXN0ZW0ubm90aWZ5KFwic2V0Q3VycmVudFRpbWVcIiksdGhpcy52aWRlb01vZGVsLnNldEN1cnJlbnRUaW1lKGEpLHQmJnQuc2VlayhhKSx2JiZ2LnNlZWsoYSkpfSxKPWZ1bmN0aW9uKGEpe3ZhciBiLGM9dGhpcztpZihiPVwibXNuZWVka2V5XCIhPT1hLnR5cGU/YS50eXBlOnEsRC5wdXNoKHt0eXBlOmIsaW5pdERhdGE6YS5pbml0RGF0YX0pLHRoaXMuZGVidWcubG9nKFwiRFJNOiBLZXkgcmVxdWlyZWQgZm9yIC0gXCIrYikscyYmcSYmIUMpdHJ5e0M9Yy5wcm90ZWN0aW9uQ29udHJvbGxlci5zZWxlY3RLZXlTeXN0ZW0ocSxzKX1jYXRjaChkKXtILmNhbGwoYyksYy5kZWJ1Zy5sb2coZCksYy5lcnJIYW5kbGVyLm1lZGlhS2V5U3lzdGVtU2VsZWN0aW9uRXJyb3IoZCl9QyYmYy5wcm90ZWN0aW9uQ29udHJvbGxlci5lbnN1cmVLZXlTZXNzaW9uKEMsYixhLmluaXREYXRhKX0sSz1mdW5jdGlvbihhKXt2YXIgYj10aGlzLGM9bnVsbCxkPW51bGwsZT1udWxsLGY9bnVsbDt0aGlzLmRlYnVnLmxvZyhcIkRSTTogR290IGEga2V5IG1lc3NhZ2UuLi5cIiksYz1hLnRhcmdldCxkPW5ldyBVaW50MTZBcnJheShhLm1lc3NhZ2UuYnVmZmVyKSxlPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxkKSxmPWEuZGVzdGluYXRpb25VUkwsYi5wcm90ZWN0aW9uQ29udHJvbGxlci51cGRhdGVGcm9tTWVzc2FnZShDLGMsZSxmKS5mYWlsKGZ1bmN0aW9uKGEpe0guY2FsbChiKSxiLmRlYnVnLmxvZyhhKSxiLmVyckhhbmRsZXIubWVkaWFLZXlNZXNzYWdlRXJyb3IoYSl9KX0sTD1mdW5jdGlvbigpe3RoaXMuZGVidWcubG9nKFwiRFJNOiBLZXkgYWRkZWQuXCIpfSxNPWZ1bmN0aW9uKCl7dmFyIGEsYj1ldmVudC50YXJnZXQ7c3dpdGNoKGE9XCJEUk06IE1lZGlhS2V5RXJyb3IgLSBzZXNzaW9uSWQ6IFwiK2Iuc2Vzc2lvbklkK1wiIGVycm9yQ29kZTogXCIrYi5lcnJvci5jb2RlK1wiIHN5c3RlbUVycm9yQ29kZTogXCIrYi5lcnJvci5zeXN0ZW1Db2RlK1wiIFtcIixiLmVycm9yLmNvZGUpe2Nhc2UgMTphKz1cIk1FRElBX0tFWUVSUl9VTktOT1dOIC0gQW4gdW5zcGVjaWZpZWQgZXJyb3Igb2NjdXJyZWQuIFRoaXMgdmFsdWUgaXMgdXNlZCBmb3IgZXJyb3JzIHRoYXQgZG9uJ3QgbWF0Y2ggYW55IG9mIHRoZSBvdGhlciBjb2Rlcy5cIjticmVhaztjYXNlIDI6YSs9XCJNRURJQV9LRVlFUlJfQ0xJRU5UIC0gVGhlIEtleSBTeXN0ZW0gY291bGQgbm90IGJlIGluc3RhbGxlZCBvciB1cGRhdGVkLlwiO2JyZWFrO2Nhc2UgMzphKz1cIk1FRElBX0tFWUVSUl9TRVJWSUNFIC0gVGhlIG1lc3NhZ2UgcGFzc2VkIGludG8gdXBkYXRlIGluZGljYXRlZCBhbiBlcnJvciBmcm9tIHRoZSBsaWNlbnNlIHNlcnZpY2UuXCI7YnJlYWs7Y2FzZSA0OmErPVwiTUVESUFfS0VZRVJSX09VVFBVVCAtIFRoZXJlIGlzIG5vIGF2YWlsYWJsZSBvdXRwdXQgZGV2aWNlIHdpdGggdGhlIHJlcXVpcmVkIGNoYXJhY3RlcmlzdGljcyBmb3IgdGhlIGNvbnRlbnQgcHJvdGVjdGlvbiBzeXN0ZW0uXCI7YnJlYWs7Y2FzZSA1OmErPVwiTUVESUFfS0VZRVJSX0hBUkRXQVJFQ0hBTkdFIC0gQSBoYXJkd2FyZSBjb25maWd1cmF0aW9uIGNoYW5nZSBjYXVzZWQgYSBjb250ZW50IHByb3RlY3Rpb24gZXJyb3IuXCI7YnJlYWs7Y2FzZSA2OmErPVwiTUVESUFfS0VZRVJSX0RPTUFJTiAtIEFuIGVycm9yIG9jY3VycmVkIGluIGEgbXVsdGktZGV2aWNlIGRvbWFpbiBsaWNlbnNpbmcgY29uZmlndXJhdGlvbi4gVGhlIG1vc3QgY29tbW9uIGVycm9yIGlzIGEgZmFpbHVyZSB0byBqb2luIHRoZSBkb21haW4uXCJ9YSs9XCJdXCIsdGhpcy5kZWJ1Zy5sb2coYSksdGhpcy5lcnJIYW5kbGVyLm1lZGlhS2V5U2Vzc2lvbkVycm9yKGEpfSxOPWZ1bmN0aW9uKGEpe3ZhciBiPVEuZGVmZXIoKSxjPXRoaXMsZD1mdW5jdGlvbihlKXtjLmRlYnVnLmxvZyhcIk1lZGlhU291cmNlIGlzIG9wZW4hXCIpLGMuZGVidWcubG9nKGUpLGEucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInNvdXJjZW9wZW5cIixkKSxhLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJ3ZWJraXRzb3VyY2VvcGVuXCIsZCksYi5yZXNvbHZlKGEpfTtyZXR1cm4gYy5kZWJ1Zy5sb2coXCJNZWRpYVNvdXJjZSBzaG91bGQgYmUgY2xvc2VkLiBUaGUgYWN0dWFsIHJlYWR5U3RhdGUgaXM6IFwiK2EucmVhZHlTdGF0ZSksYS5hZGRFdmVudExpc3RlbmVyKFwic291cmNlb3BlblwiLGQsITEpLGEuYWRkRXZlbnRMaXN0ZW5lcihcIndlYmtpdHNvdXJjZW9wZW5cIixkLCExKSxjLm1lZGlhU291cmNlRXh0LmF0dGFjaE1lZGlhU291cmNlKGEsYy52aWRlb01vZGVsKSxjLmRlYnVnLmxvZyhcIk1lZGlhU291cmNlIGF0dGFjaGVkIHRvIHZpZGVvLiAgV2FpdGluZyBvbiBvcGVuLi4uXCIpLGIucHJvbWlzZX0sTz1mdW5jdGlvbigpe3ZhciBjPXRoaXM7dCYmdC5yZXNldChCKSx2JiZ2LnJlc2V0KEIpLGImJmMubWVkaWFTb3VyY2VFeHQuZGV0YWNoTWVkaWFTb3VyY2UoYy52aWRlb01vZGVsKSxBPSExLEM9bnVsbCxEPVtdLHM9bnVsbCx0PW51bGwsdj1udWxsLHg9bnVsbCxxPW51bGwscj1udWxsLGI9bnVsbCxhPW51bGx9LFA9ZnVuY3Rpb24oYixjLGQsZSl7aWYoYiYmYyYmZClpZihudWxsPT09dCYmbnVsbD09PXYmJm51bGw9PT14KXt2YXIgZj1cIk5vIHN0cmVhbXMgdG8gcGxheS5cIjt0aGlzLmVyckhhbmRsZXIubWFuaWZlc3RFcnJvcihmLFwibm9zdHJlYW1zXCIsYSksdGhpcy5kZWJ1Zy5sb2coZiksZS5yZWplY3QoKX1lbHNlIHRoaXMuZGVidWcubG9nKFwiTWVkaWFTb3VyY2UgaW5pdGlhbGl6ZWQhXCIpLGUucmVzb2x2ZSghMCl9LFI9ZnVuY3Rpb24oKXt0aGlzLmRlYnVnLmxvZyhcIkdldHRpbmcgTWVkaWFTb3VyY2UgcmVhZHkuLi5cIik7dmFyIGE9US5kZWZlcigpLGM9ITEsZD0hMSxlPSExLGY9dGhpcyxnPWYubWFuaWZlc3RNb2RlbC5nZXRWYWx1ZSgpLGg9Zi5tYW5pZmVzdEV4dC5nZXRJc0xpdmUoZyk7cmV0dXJuIGYuZGVidWcubG9nKFwiR2F0aGVyaW5nIGluZm9ybWF0aW9uIGZvciBidWZmZXJzLiAoMSlcIiksZi5tYW5pZmVzdEV4dC5nZXREdXJhdGlvbihnLGgpLnRoZW4oZnVuY3Rpb24oKXtmLm1hbmlmZXN0RXh0LmdldFZpZGVvRGF0YShnLEUpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIG51bGwhPT1oPyhmLmRlYnVnLmxvZyhcIkNyZWF0ZSB2aWRlbyBidWZmZXIuXCIpLGYubWFuaWZlc3RFeHQuZ2V0RGF0YUluZGV4KGgsZyxFKS50aGVuKGZ1bmN0aW9uKGEpe3U9YSxmLmRlYnVnLmxvZyhcIlNhdmUgdmlkZW8gdHJhY2s6IFwiK3UpfSksZi5tYW5pZmVzdEV4dC5nZXRDb2RlYyhoKS50aGVuKGZ1bmN0aW9uKGEpe3JldHVybiBmLmRlYnVnLmxvZyhcIlZpZGVvIGNvZGVjOiBcIithKSxxPWEsZi5tYW5pZmVzdEV4dC5nZXRDb250ZW50UHJvdGVjdGlvbkRhdGEoaCkudGhlbihmdW5jdGlvbihjKXtpZihmLmRlYnVnLmxvZyhcIlZpZGVvIGNvbnRlbnRQcm90ZWN0aW9uXCIpLGMmJiFmLmNhcGFiaWxpdGllcy5zdXBwb3J0c01lZGlhS2V5cygpKXJldHVybiBmLmVyckhhbmRsZXIuY2FwYWJpbGl0eUVycm9yKFwibWVkaWFrZXlzXCIpLFEud2hlbihudWxsKTtpZihzPWMsIWYuY2FwYWJpbGl0aWVzLnN1cHBvcnRzQ29kZWMoZi52aWRlb01vZGVsLmdldEVsZW1lbnQoKSxhKSl7dmFyIGQ9XCJWaWRlbyBDb2RlYyAoXCIrYStcIikgaXMgbm90IHN1cHBvcnRlZC5cIjtyZXR1cm4gZi5lcnJIYW5kbGVyLm1hbmlmZXN0RXJyb3IoZCxcImNvZGVjXCIsZyksZi5kZWJ1Zy5sb2coZCksUS53aGVuKG51bGwpfXJldHVybiBmLnNvdXJjZUJ1ZmZlckV4dC5jcmVhdGVTb3VyY2VCdWZmZXIoYixhKX0pfSkudGhlbihmdW5jdGlvbihnKXtudWxsPT09Zz9mLmRlYnVnLmxvZyhcIk5vIGJ1ZmZlciB3YXMgY3JlYXRlZCwgc2tpcHBpbmcgdmlkZW8gc3RyZWFtLlwiKToodD1mLnN5c3RlbS5nZXRPYmplY3QoXCJidWZmZXJDb250cm9sbGVyXCIpLHQuaW5pdGlhbGl6ZShcInZpZGVvXCIsRSxoLGcsZi52aWRlb01vZGVsLGYucmVxdWVzdFNjaGVkdWxlcixmLmZyYWdtZW50Q29udHJvbGxlcixiKSxmLmRlYnVnLmxvZyhcIlZpZGVvIGlzIHJlYWR5IVwiKSksYz0hMCxQLmNhbGwoZixjLGQsZSxhKX0sZnVuY3Rpb24oKXtmLmVyckhhbmRsZXIubWVkaWFTb3VyY2VFcnJvcihcIkVycm9yIGNyZWF0aW5nIHZpZGVvIHNvdXJjZSBidWZmZXIuXCIpLGM9ITAsUC5jYWxsKGYsYyxkLGUsYSl9KSk6KGYuZGVidWcubG9nKFwiTm8gdmlkZW8gZGF0YS5cIiksYz0hMCxQLmNhbGwoZixjLGQsZSxhKSksZi5tYW5pZmVzdEV4dC5nZXRBdWRpb0RhdGFzKGcsRSl9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBudWxsIT09aCYmaC5sZW5ndGg+MD8oZi5kZWJ1Zy5sb2coXCJIYXZlIGF1ZGlvIHN0cmVhbXM6IFwiK2gubGVuZ3RoKSxmLm1hbmlmZXN0RXh0LmdldFByaW1hcnlBdWRpb0RhdGEoZyxFKS50aGVuKGZ1bmN0aW9uKGgpe2YubWFuaWZlc3RFeHQuZ2V0RGF0YUluZGV4KGgsZyxFKS50aGVuKGZ1bmN0aW9uKGEpe3c9YSxmLmRlYnVnLmxvZyhcIlNhdmUgYXVkaW8gdHJhY2s6IFwiK3cpfSksZi5tYW5pZmVzdEV4dC5nZXRDb2RlYyhoKS50aGVuKGZ1bmN0aW9uKGEpe3JldHVybiBmLmRlYnVnLmxvZyhcIkF1ZGlvIGNvZGVjOiBcIithKSxyPWEsZi5tYW5pZmVzdEV4dC5nZXRDb250ZW50UHJvdGVjdGlvbkRhdGEoaCkudGhlbihmdW5jdGlvbihjKXtpZihmLmRlYnVnLmxvZyhcIkF1ZGlvIGNvbnRlbnRQcm90ZWN0aW9uXCIpLGMmJiFmLmNhcGFiaWxpdGllcy5zdXBwb3J0c01lZGlhS2V5cygpKXJldHVybiBmLmVyckhhbmRsZXIuY2FwYWJpbGl0eUVycm9yKFwibWVkaWFrZXlzXCIpLFEud2hlbihudWxsKTtpZihzPWMsIWYuY2FwYWJpbGl0aWVzLnN1cHBvcnRzQ29kZWMoZi52aWRlb01vZGVsLmdldEVsZW1lbnQoKSxhKSl7dmFyIGQ9XCJBdWRpbyBDb2RlYyAoXCIrYStcIikgaXMgbm90IHN1cHBvcnRlZC5cIjtyZXR1cm4gZi5lcnJIYW5kbGVyLm1hbmlmZXN0RXJyb3IoZCxcImNvZGVjXCIsZyksZi5kZWJ1Zy5sb2coZCksUS53aGVuKG51bGwpfXJldHVybiBmLnNvdXJjZUJ1ZmZlckV4dC5jcmVhdGVTb3VyY2VCdWZmZXIoYixhKX0pfSkudGhlbihmdW5jdGlvbihnKXtudWxsPT09Zz9mLmRlYnVnLmxvZyhcIk5vIGJ1ZmZlciB3YXMgY3JlYXRlZCwgc2tpcHBpbmcgYXVkaW8gc3RyZWFtLlwiKToodj1mLnN5c3RlbS5nZXRPYmplY3QoXCJidWZmZXJDb250cm9sbGVyXCIpLHYuaW5pdGlhbGl6ZShcImF1ZGlvXCIsRSxoLGcsZi52aWRlb01vZGVsLGYucmVxdWVzdFNjaGVkdWxlcixmLmZyYWdtZW50Q29udHJvbGxlcixiKSxmLmRlYnVnLmxvZyhcIkF1ZGlvIGlzIHJlYWR5IVwiKSksZD0hMCxQLmNhbGwoZixjLGQsZSxhKX0sZnVuY3Rpb24oKXtmLmVyckhhbmRsZXIubWVkaWFTb3VyY2VFcnJvcihcIkVycm9yIGNyZWF0aW5nIGF1ZGlvIHNvdXJjZSBidWZmZXIuXCIpLGQ9ITAsUC5jYWxsKGYsYyxkLGUsYSl9KX0pKTooZi5kZWJ1Zy5sb2coXCJObyBhdWRpbyBzdHJlYW1zLlwiKSxkPSEwLFAuY2FsbChmLGMsZCxlLGEpKSxmLm1hbmlmZXN0RXh0LmdldFRleHREYXRhKGcsRSl9KS50aGVuKGZ1bmN0aW9uKGgpe3ZhciBpO251bGwhPT1oPyhmLm1hbmlmZXN0RXh0LmdldERhdGFJbmRleChoLGcsRSkudGhlbihmdW5jdGlvbihhKXt5PWEsZi5kZWJ1Zy5sb2coXCJTYXZlIHRleHQgdHJhY2s6IFwiK3kpfSksZi5tYW5pZmVzdEV4dC5nZXRNaW1lVHlwZShoKS50aGVuKGZ1bmN0aW9uKGEpe3JldHVybiBpPWEsZi5zb3VyY2VCdWZmZXJFeHQuY3JlYXRlU291cmNlQnVmZmVyKGIsaSl9KS50aGVuKGZ1bmN0aW9uKGIpe251bGw9PT1iP2YuZGVidWcubG9nKFwiU291cmNlIGJ1ZmZlciB3YXMgbm90IGNyZWF0ZWQgZm9yIHRleHQgdHJhY2tcIik6KHg9Zi5zeXN0ZW0uZ2V0T2JqZWN0KFwidGV4dENvbnRyb2xsZXJcIikseC5pbml0aWFsaXplKEUsaCxiLGYudmlkZW9Nb2RlbCksYi5oYXNPd25Qcm9wZXJ0eShcImluaXRpYWxpemVcIikmJmIuaW5pdGlhbGl6ZShpLHgpLGYuZGVidWcubG9nKFwiVGV4dCBpcyByZWFkeSFcIiksZT0hMCxQLmNhbGwoZixjLGQsZSxhKSl9LGZ1bmN0aW9uKGIpe2YuZGVidWcubG9nKFwiRXJyb3IgY3JlYXRpbmcgdGV4dCBzb3VyY2UgYnVmZmVyOlwiKSxmLmRlYnVnLmxvZyhiKSxmLmVyckhhbmRsZXIubWVkaWFTb3VyY2VFcnJvcihcIkVycm9yIGNyZWF0aW5nIHRleHQgc291cmNlIGJ1ZmZlci5cIiksZT0hMCxQLmNhbGwoZixjLGQsZSxhKX0pKTooZi5kZWJ1Zy5sb2coXCJObyB0ZXh0IHRyYWNrcy5cIiksZT0hMCxQLmNhbGwoZixjLGQsZSxhKSl9KX0pLGEucHJvbWlzZX0sUz1mdW5jdGlvbigpe3ZhciBhPXRoaXMsYz1RLmRlZmVyKCksZD1hLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSxlPWEubWFuaWZlc3RFeHQuZ2V0SXNMaXZlKGQpO3JldHVybiBhLmRlYnVnLmxvZyhcIkdldHRpbmcgcmVhZHkgZm9yIHBsYXliYWNrLi4uXCIpLGEubWFuaWZlc3RFeHQuZ2V0RHVyYXRpb25Gb3JQZXJpb2QoRSxhLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSxlKS50aGVuKGZ1bmN0aW9uKGEpe2w9YX0pLGEubWFuaWZlc3RFeHQuZ2V0RHVyYXRpb24oYS5tYW5pZmVzdE1vZGVsLmdldFZhbHVlKCksZSkudGhlbihmdW5jdGlvbihjKXtyZXR1cm4gYS5kZWJ1Zy5sb2coXCJTZXR0aW5nIGR1cmF0aW9uOiBcIitjKSxhLm1lZGlhU291cmNlRXh0LnNldER1cmF0aW9uKGIsYyl9KS50aGVuKGZ1bmN0aW9uKCl7cmV0dXJuIGEuZGVidWcubG9nKFwiRHVyYXRpb24gc3VjY2Vzc2Z1bGx5IHNldC5cIiksYS5tYW5pZmVzdEV4dC5nZXRQZXJpb2RTdGFydChhLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSxFKX0pLnRoZW4oZnVuY3Rpb24oYSl7Rj1hLEE9ITAsYy5yZXNvbHZlKCEwKX0pLGMucHJvbWlzZX0sVD1mdW5jdGlvbigpe3ZhciBhPXRoaXM7YS5kZWJ1Zy5sb2coXCJHb3QgbG9hZG1ldGFkYXRhIGV2ZW50LlwiKSxjLnJlc29sdmUobnVsbCl9LFU9ZnVuY3Rpb24oKXt0aGlzLmRlYnVnLmxvZyhcIkdvdCBwbGF5IGV2ZW50LlwiKSxBJiYobnVsbCE9PUY/KHRoaXMuZGVidWcubG9nKFwiU3RhcnRpbmcgc2VnbWVudCBsb2FkaW5nIGF0IG9mZnNldDogXCIrRiksdCYmdC5zZWVrKEYpLHYmJnYuc2VlayhGKSx4JiZ4LnNlZWsoRikpOih0JiZ0LnN0YXJ0KCksdiYmdi5zdGFydCgpLHgmJnguc3RhcnQoKSkpfSxWPWZ1bmN0aW9uKCl7dGhpcy5kZWJ1Zy5sb2coXCJHb3QgcGF1c2UgZXZlbnQuXCIpLHRoaXMuc2NoZWR1bGVXaGlsZVBhdXNlZHx8YWIuY2FsbCh0aGlzKX0sVz1mdW5jdGlvbihhKXt2YXIgYj1hLnNyY0VsZW1lbnQuZXJyb3IsYz1iLmNvZGUsZD1cIlwiO2lmKC0xIT09Yyl7c3dpdGNoKGMpe2Nhc2UgMTpkPVwiTUVESUFfRVJSX0FCT1JURURcIjticmVhaztjYXNlIDI6ZD1cIk1FRElBX0VSUl9ORVRXT1JLXCI7YnJlYWs7Y2FzZSAzOmQ9XCJNRURJQV9FUlJfREVDT0RFXCI7YnJlYWs7Y2FzZSA0OmQ9XCJNRURJQV9FUlJfU1JDX05PVF9TVVBQT1JURURcIjticmVhaztjYXNlIDU6ZD1cIk1FRElBX0VSUl9FTkNSWVBURURcIn1CPSEwLHRoaXMuZGVidWcubG9nKFwiVmlkZW8gRWxlbWVudCBFcnJvcjogXCIrZCksdGhpcy5kZWJ1Zy5sb2coYiksdGhpcy5lcnJIYW5kbGVyLm1lZGlhU291cmNlRXJyb3IoZCksdGhpcy5yZXNldCgpfX0sWD1mdW5jdGlvbigpe3RoaXMuZGVidWcubG9nKFwiR290IHNlZWtpbmcgZXZlbnQuXCIpO3ZhciBhPXRoaXMudmlkZW9Nb2RlbC5nZXRDdXJyZW50VGltZSgpO3QmJnQuc2VlayhhKSx2JiZ2LnNlZWsoYSl9LFk9ZnVuY3Rpb24oKXt0aGlzLmRlYnVnLmxvZyhcIlNlZWsgY29tcGxldGUuXCIpLHRoaXMudmlkZW9Nb2RlbC5saXN0ZW4oXCJzZWVraW5nXCIsaCksdGhpcy52aWRlb01vZGVsLnVubGlzdGVuKFwic2Vla2VkXCIsaSl9LFo9ZnVuY3Rpb24oKXtfLmNhbGwodGhpcyl9LCQ9ZnVuY3Rpb24oKXtfLmNhbGwodGhpcyl9LF89ZnVuY3Rpb24oKXt0JiZ0LnVwZGF0ZUJ1ZmZlclN0YXRlKCksdiYmdi51cGRhdGVCdWZmZXJTdGF0ZSgpfSxhYj1mdW5jdGlvbigpe3QmJnQuc3RvcCgpLHYmJnYuc3RvcCgpfSxiYj1mdW5jdGlvbihkKXt2YXIgZT10aGlzO3JldHVybiBlLmRlYnVnLmxvZyhcIlN0cmVhbSBzdGFydCBsb2FkaW5nLlwiKSxhPWQsZS5tZWRpYVNvdXJjZUV4dC5jcmVhdGVNZWRpYVNvdXJjZSgpLnRoZW4oZnVuY3Rpb24oYSl7cmV0dXJuIGUuZGVidWcubG9nKFwiTWVkaWFTb3VyY2UgY3JlYXRlZC5cIiksTi5jYWxsKGUsYSl9KS50aGVuKGZ1bmN0aW9uKGEpe3JldHVybiBiPWEsZS5kZWJ1Zy5sb2coXCJNZWRpYVNvdXJjZSBzZXQgdXAuXCIpLFIuY2FsbChlKX0pLnRoZW4oZnVuY3Rpb24oKXtyZXR1cm4gZS5kZWJ1Zy5sb2coXCJTdGFydCBpbml0aWFsaXppbmcgcGxheWJhY2suXCIpLFMuY2FsbChlKX0pLnRoZW4oZnVuY3Rpb24oKXtyZXR1cm4gej8oZS5kZWJ1Zy5sb2coXCJQbGF5YmFjayBpbml0aWFsaXplZCFcIiksYy5wcm9taXNlKTp2b2lkIDB9KS50aGVuKGZ1bmN0aW9uKCl7ZS5kZWJ1Zy5sb2coXCJlbGVtZW50IGxvYWRlZCFcIiksMD09PUUmJkcuY2FsbChlKX0pfSxjYj1mdW5jdGlvbigpe3RoaXMuZGVidWcubG9nKFwiQ3VycmVudCB0aW1lIGhhcyBjaGFuZ2VkLCBibG9jayBwcm9ncmFtbWF0aWMgc2Vlay5cIiksdGhpcy52aWRlb01vZGVsLnVubGlzdGVuKFwic2Vla2luZ1wiLGgpLHRoaXMudmlkZW9Nb2RlbC5saXN0ZW4oXCJzZWVrZWRcIixpKX0sZGI9ZnVuY3Rpb24oKXt0JiYhdC5pc0J1ZmZlcmluZ0NvbXBsZXRlZCgpfHx2JiYhdi5pc0J1ZmZlcmluZ0NvbXBsZXRlZCgpfHxiJiZ0aGlzLm1lZGlhU291cmNlRXh0LnNpZ25hbEVuZE9mU3RyZWFtKGIpfSxlYj1mdW5jdGlvbigpe2FiLmNhbGwodGhpcyl9LGZiPWZ1bmN0aW9uKCl7dmFyIGEsYixjPXRoaXMsZD1jLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKTtjLmRlYnVnLmxvZyhcIk1hbmlmZXN0IHVwZGF0ZWQuLi4gc2V0IG5ldyBkYXRhIG9uIGJ1ZmZlcnMuXCIpLHQmJihhPXQuZ2V0RGF0YSgpLGEmJmEuaGFzT3duUHJvcGVydHkoXCJpZFwiKT9jLm1hbmlmZXN0RXh0LmdldERhdGFGb3JJZChhLmlkLGQsRSkudGhlbihmdW5jdGlvbihhKXt0LnNldERhdGEoYSl9KTpjLm1hbmlmZXN0RXh0LmdldERhdGFGb3JJbmRleCh1LGQsRSkudGhlbihmdW5jdGlvbihhKXt0LnNldERhdGEoYSl9KSksdiYmKGI9di5nZXREYXRhKCksYiYmYi5oYXNPd25Qcm9wZXJ0eShcImlkXCIpP2MubWFuaWZlc3RFeHQuZ2V0RGF0YUZvcklkKGIuaWQsZCxFKS50aGVuKGZ1bmN0aW9uKGEpe3Yuc2V0RGF0YShhKX0pOmMubWFuaWZlc3RFeHQuZ2V0RGF0YUZvckluZGV4KHcsZCxFKS50aGVuKGZ1bmN0aW9uKGEpe3Yuc2V0RGF0YShhKX0pKX07cmV0dXJue3N5c3RlbTp2b2lkIDAsdmlkZW9Nb2RlbDp2b2lkIDAsbWFuaWZlc3RMb2FkZXI6dm9pZCAwLG1hbmlmZXN0TW9kZWw6dm9pZCAwLG1lZGlhU291cmNlRXh0OnZvaWQgMCxzb3VyY2VCdWZmZXJFeHQ6dm9pZCAwLGJ1ZmZlckV4dDp2b2lkIDAsbWFuaWZlc3RFeHQ6dm9pZCAwLGZyYWdtZW50Q29udHJvbGxlcjp2b2lkIDAsYWJyQ29udHJvbGxlcjp2b2lkIDAsZnJhZ21lbnRFeHQ6dm9pZCAwLHByb3RlY3Rpb25Nb2RlbDp2b2lkIDAscHJvdGVjdGlvbkNvbnRyb2xsZXI6dm9pZCAwLHByb3RlY3Rpb25FeHQ6dm9pZCAwLGNhcGFiaWxpdGllczp2b2lkIDAsZGVidWc6dm9pZCAwLG1ldHJpY3NFeHQ6dm9pZCAwLGVyckhhbmRsZXI6dm9pZCAwLHJlcXVlc3RTY2hlZHVsZXI6dm9pZCAwLHNjaGVkdWxlV2hpbGVQYXVzZWQ6dm9pZCAwLHNldHVwOmZ1bmN0aW9uKCl7dGhpcy5zeXN0ZW0ubWFwSGFuZGxlcihcIm1hbmlmZXN0VXBkYXRlZFwiLHZvaWQgMCxmYi5iaW5kKHRoaXMpKSx0aGlzLnN5c3RlbS5tYXBIYW5kbGVyKFwic2V0Q3VycmVudFRpbWVcIix2b2lkIDAsY2IuYmluZCh0aGlzKSksdGhpcy5zeXN0ZW0ubWFwSGFuZGxlcihcImJ1ZmZlcmluZ0NvbXBsZXRlZFwiLHZvaWQgMCxkYi5iaW5kKHRoaXMpKSx0aGlzLnN5c3RlbS5tYXBIYW5kbGVyKFwic2VnbWVudExvYWRpbmdGYWlsZWRcIix2b2lkIDAsZWIuYmluZCh0aGlzKSksYz1RLmRlZmVyKCksZT1VLmJpbmQodGhpcyksZj1WLmJpbmQodGhpcyksZz1XLmJpbmQodGhpcyksaD1YLmJpbmQodGhpcyksaT1ZLmJpbmQodGhpcyksaz1aLmJpbmQodGhpcyksaj0kLmJpbmQodGhpcyksZD1ULmJpbmQodGhpcyl9LGxvYWQ6ZnVuY3Rpb24oYSxiKXtFPWIsYmIuY2FsbCh0aGlzLGEpfSxzZXRWaWRlb01vZGVsOmZ1bmN0aW9uKGEpe3RoaXMudmlkZW9Nb2RlbD1hLHRoaXMudmlkZW9Nb2RlbC5saXN0ZW4oXCJwbGF5XCIsZSksdGhpcy52aWRlb01vZGVsLmxpc3RlbihcInBhdXNlXCIsZiksdGhpcy52aWRlb01vZGVsLmxpc3RlbihcImVycm9yXCIsZyksdGhpcy52aWRlb01vZGVsLmxpc3RlbihcInNlZWtpbmdcIixoKSx0aGlzLnZpZGVvTW9kZWwubGlzdGVuKFwidGltZXVwZGF0ZVwiLGopLHRoaXMudmlkZW9Nb2RlbC5saXN0ZW4oXCJwcm9ncmVzc1wiLGspLHRoaXMudmlkZW9Nb2RlbC5saXN0ZW4oXCJsb2FkZWRtZXRhZGF0YVwiLGQpfSxpbml0UHJvdGVjdGlvbjpmdW5jdGlvbigpe209Si5iaW5kKHRoaXMpLG49Sy5iaW5kKHRoaXMpLG89TC5iaW5kKHRoaXMpLHA9TS5iaW5kKHRoaXMpLHRoaXMucHJvdGVjdGlvbk1vZGVsPXRoaXMuc3lzdGVtLmdldE9iamVjdChcInByb3RlY3Rpb25Nb2RlbFwiKSx0aGlzLnByb3RlY3Rpb25Nb2RlbC5pbml0KHRoaXMuZ2V0VmlkZW9Nb2RlbCgpKSx0aGlzLnByb3RlY3Rpb25Db250cm9sbGVyPXRoaXMuc3lzdGVtLmdldE9iamVjdChcInByb3RlY3Rpb25Db250cm9sbGVyXCIpLHRoaXMucHJvdGVjdGlvbkNvbnRyb2xsZXIuaW5pdCh0aGlzLnZpZGVvTW9kZWwsdGhpcy5wcm90ZWN0aW9uTW9kZWwpLHRoaXMucHJvdGVjdGlvbk1vZGVsLmxpc3RlblRvTmVlZEtleShtKSx0aGlzLnByb3RlY3Rpb25Nb2RlbC5saXN0ZW5Ub0tleU1lc3NhZ2UobiksdGhpcy5wcm90ZWN0aW9uTW9kZWwubGlzdGVuVG9LZXlFcnJvcihwKSx0aGlzLnByb3RlY3Rpb25Nb2RlbC5saXN0ZW5Ub0tleUFkZGVkKG8pfSxnZXRWaWRlb01vZGVsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmlkZW9Nb2RlbH0sZ2V0TWFuaWZlc3RFeHQ6ZnVuY3Rpb24oKXt2YXIgYT10aGlzO3JldHVybiBhLm1hbmlmZXN0RXh0fSxzZXRBdXRvUGxheTpmdW5jdGlvbihhKXt6PWF9LGdldEF1dG9QbGF5OmZ1bmN0aW9uKCl7cmV0dXJuIHp9LHJlc2V0OmZ1bmN0aW9uKCl7SC5jYWxsKHRoaXMpLHRoaXMudmlkZW9Nb2RlbC51bmxpc3RlbihcInBsYXlcIixlKSx0aGlzLnZpZGVvTW9kZWwudW5saXN0ZW4oXCJwYXVzZVwiLGYpLHRoaXMudmlkZW9Nb2RlbC51bmxpc3RlbihcImVycm9yXCIsZyksdGhpcy52aWRlb01vZGVsLnVubGlzdGVuKFwic2Vla2luZ1wiLGgpLHRoaXMudmlkZW9Nb2RlbC51bmxpc3RlbihcInRpbWV1cGRhdGVcIixqKSx0aGlzLnZpZGVvTW9kZWwudW5saXN0ZW4oXCJwcm9ncmVzc1wiLGspLHRoaXMudmlkZW9Nb2RlbC51bmxpc3RlbihcImxvYWRlZG1ldGFkYXRhXCIsZCksTy5jYWxsKHRoaXMpLHRoaXMucHJvdGVjdGlvbkNvbnRyb2xsZXImJnRoaXMucHJvdGVjdGlvbkNvbnRyb2xsZXIudGVhcmRvd25LZXlTeXN0ZW0oQyksdGhpcy5wcm90ZWN0aW9uQ29udHJvbGxlcj12b2lkIDAsdGhpcy5wcm90ZWN0aW9uTW9kZWw9dm9pZCAwLHRoaXMuZnJhZ21lbnRDb250cm9sbGVyPXZvaWQgMCx0aGlzLnJlcXVlc3RTY2hlZHVsZXI9dm9pZCAwLGM9US5kZWZlcigpfSxnZXREdXJhdGlvbjpmdW5jdGlvbigpe3JldHVybiBsfSxzZXRQZXJpb2RJbmRleDpmdW5jdGlvbihhKXtFPWF9LGdldFBlcmlvZEluZGV4OmZ1bmN0aW9uKCl7cmV0dXJuIEV9LGdldFN0YXJ0VGltZTpmdW5jdGlvbigpe3JldHVybiBGfSxwbGF5Okcsc2VlazpJLHBhdXNlOkh9fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU3RyZWFtLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlN0cmVhbX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlN0cmVhbUNvbnRyb2xsZXI9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYSxiPVtdLGM9NCxkPTMsZT0hMCxmPW51bGwsZz1mdW5jdGlvbigpe2EucGxheSgpfSxoPWZ1bmN0aW9uKCl7YS5wYXVzZSgpfSxpPWZ1bmN0aW9uKGIpe2Euc2VlayhiKX0saj1mdW5jdGlvbihhLGIpe3ZhciBjPWEuZ2V0RWxlbWVudCgpLGQ9Yi5nZXRFbGVtZW50KCk7cmV0dXJuIGQucGFyZW50Tm9kZXx8Yy5wYXJlbnROb2RlLmluc2VydEJlZm9yZShkLGMpLGMuc3R5bGUud2lkdGg9XCIwcHhcIixkLnN0eWxlLndpZHRoPVwiMTAwJVwiLG0oYyxkKSxsKGEpLGsoYiksUS53aGVuKCEwKX0saz1mdW5jdGlvbihhKXthLmxpc3RlbihcInNlZWtpbmdcIixwKSxhLmxpc3RlbihcInByb2dyZXNzXCIsbikscigpJiZhLmxpc3RlbihcInRpbWV1cGRhdGVcIixvKX0sbD1mdW5jdGlvbihhKXthLnVubGlzdGVuKFwic2Vla2luZ1wiLHApLGEudW5saXN0ZW4oXCJwcm9ncmVzc1wiLG4pLGEudW5saXN0ZW4oXCJ0aW1ldXBkYXRlXCIsbyl9LG09ZnVuY3Rpb24oYSxiKXtbXCJjb250cm9sc1wiLFwibG9vcFwiLFwibXV0ZWRcIixcInBsYXliYWNrUmF0ZVwiLFwidm9sdW1lXCJdLmZvckVhY2goZnVuY3Rpb24oYyl7YltjXT1hW2NdfSl9LG49ZnVuY3Rpb24oKXt2YXIgYj1hLmdldFZpZGVvTW9kZWwoKS5nZXRFbGVtZW50KCkuYnVmZmVyZWQ7aWYoYi5sZW5ndGgpe3ZhciBkPWIubGVuZ3RoLTEsZT1iLmVuZChkKSxmPWEuZ2V0U3RhcnRUaW1lKCkrYS5nZXREdXJhdGlvbigpLWU7Yz5mJiYoYS5nZXRWaWRlb01vZGVsKCkudW5saXN0ZW4oXCJwcm9ncmVzc1wiLG4pLHEoKSl9fSxvPWZ1bmN0aW9uKCl7aWYoIWEuZ2V0VmlkZW9Nb2RlbCgpLmdldEVsZW1lbnQoKS5zZWVraW5nKXt2YXIgYj1hLmdldFN0YXJ0VGltZSgpK2EuZ2V0RHVyYXRpb24oKSxjPWEuZ2V0VmlkZW9Nb2RlbCgpLmdldEN1cnJlbnRUaW1lKCk7ZD5iLWMmJnYoYSxyKCkpfX0scD1mdW5jdGlvbigpe3ZhciBiPWEuZ2V0VmlkZW9Nb2RlbCgpLmdldEN1cnJlbnRUaW1lKCksYz1zKGIpO2MmJmMhPT1hJiZ2KGEsYyxiKX0scT1mdW5jdGlvbigpe3ZhciBhPXIoKTthJiZhLnNlZWsoYS5nZXRTdGFydFRpbWUoKSl9LHI9ZnVuY3Rpb24oKXt2YXIgYz1hLmdldFBlcmlvZEluZGV4KCkrMTtyZXR1cm4gYzxiLmxlbmd0aD9iW2NdOm51bGx9LHM9ZnVuY3Rpb24oYSl7Zm9yKHZhciBjPTAsZD1udWxsLGU9MCxmPWIubGVuZ3RoO2Y+ZTtlKyspaWYoZD1iW2VdLGMrPWQuZ2V0RHVyYXRpb24oKSxjPmEpcmV0dXJuIGR9LHQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnN5c3RlbS5nZXRPYmplY3QoXCJ2aWRlb01vZGVsXCIpLGI9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInZpZGVvXCIpO3JldHVybiBhLnNldEVsZW1lbnQoYiksYX0sdT1mdW5jdGlvbihhKXthLnBhcmVudE5vZGUmJmEucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChhKX0sdj1mdW5jdGlvbihiLGMsZCl7YiYmYyYmYiE9PWMmJlEud2hlbihmfHwhMCkudGhlbihmdW5jdGlvbigpe2IucGF1c2UoKSxhPWMsZj1qKGIuZ2V0VmlkZW9Nb2RlbCgpLGMuZ2V0VmlkZW9Nb2RlbCgpKSxkP2koYi5nZXRWaWRlb01vZGVsKCkuZ2V0Q3VycmVudFRpbWUoKSk6aShjLmdldFN0YXJ0VGltZSgpKSxnKCl9KX07cmV0dXJue3N5c3RlbTp2b2lkIDAsdmlkZW9Nb2RlbDp2b2lkIDAsbWFuaWZlc3RMb2FkZXI6dm9pZCAwLG1hbmlmZXN0VXBkYXRlcjp2b2lkIDAsbWFuaWZlc3RNb2RlbDp2b2lkIDAsbWVkaWFTb3VyY2VFeHQ6dm9pZCAwLHNvdXJjZUJ1ZmZlckV4dDp2b2lkIDAsYnVmZmVyRXh0OnZvaWQgMCxtYW5pZmVzdEV4dDp2b2lkIDAsZnJhZ21lbnRDb250cm9sbGVyOnZvaWQgMCxhYnJDb250cm9sbGVyOnZvaWQgMCxmcmFnbWVudEV4dDp2b2lkIDAsY2FwYWJpbGl0aWVzOnZvaWQgMCxkZWJ1Zzp2b2lkIDAsbWV0cmljc0V4dDp2b2lkIDAsZXJySGFuZGxlcjp2b2lkIDAsZ2V0TWFuaWZlc3RFeHQ6ZnVuY3Rpb24oKXtyZXR1cm4gYS5nZXRNYW5pZmVzdEV4dCgpfSxzZXRBdXRvUGxheTpmdW5jdGlvbihhKXtlPWF9LGdldEF1dG9QbGF5OmZ1bmN0aW9uKCl7cmV0dXJuIGV9LGdldFZpZGVvTW9kZWw6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy52aWRlb01vZGVsfSxzZXRWaWRlb01vZGVsOmZ1bmN0aW9uKGEpe3RoaXMudmlkZW9Nb2RlbD1hfSxsb2FkOmZ1bmN0aW9uKGMpe3ZhciBkLGY9dGhpcztmLm1hbmlmZXN0TG9hZGVyLmxvYWQoYykudGhlbihmdW5jdGlvbihjKXtmLm1hbmlmZXN0TW9kZWwuc2V0VmFsdWUoYyksZi5kZWJ1Zy5sb2coXCJNYW5pZmVzdCBoYXMgbG9hZGVkLlwiKSxmLmRlYnVnLmxvZyhmLm1hbmlmZXN0TW9kZWwuZ2V0VmFsdWUoKSksZi5tYW5pZmVzdFVwZGF0ZXIuaW5pdCgpLGYubWFuaWZlc3RFeHQuZ2V0UGVyaW9kQ291bnQoYykudGhlbihmdW5jdGlvbihnKXtmb3IodmFyIGg9MDtnPmg7aCsrKWQ9Zi5zeXN0ZW0uZ2V0T2JqZWN0KFwic3RyZWFtXCIpLGQuc2V0VmlkZW9Nb2RlbCgwPT09aD9mLnZpZGVvTW9kZWw6dC5jYWxsKGYpKSxkLmluaXRQcm90ZWN0aW9uKCksZC5zZXRBdXRvUGxheShlKSxkLmxvYWQoYyxoKSxiLnB1c2goZCk7YT1iWzBdLGsoYS5nZXRWaWRlb01vZGVsKCkpfSl9LGZ1bmN0aW9uKCl7Zi5yZXNldCgpfSl9LHJlc2V0OmZ1bmN0aW9uKCl7YSYmbChhLmdldFZpZGVvTW9kZWwoKSk7Zm9yKHZhciBjPTAsZD1iLmxlbmd0aDtkPmM7YysrKXt2YXIgZT1iW2NdO2UucmVzZXQoKSxlIT09YSYmdShlLmdldFZpZGVvTW9kZWwoKS5nZXRFbGVtZW50KCkpfWI9W10sdGhpcy5tYW5pZmVzdFVwZGF0ZXIuc3RvcCgpLHRoaXMubWFuaWZlc3RNb2RlbC5zZXRWYWx1ZShudWxsKSxmPW51bGwsYT1udWxsfSxwbGF5Omcsc2VlazppLHBhdXNlOmh9fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuU3RyZWFtQ29udHJvbGxlci5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5TdHJlYW1Db250cm9sbGVyfSxNZWRpYVBsYXllci5tb2RlbHMuVmlkZW9Nb2RlbD1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBhLGI9W10sYz1mdW5jdGlvbigpe3JldHVybiBiLmxlbmd0aD4wfSxkPWZ1bmN0aW9uKGMpe251bGwhPT1jJiZiW2NdIT09ITAmJihiLnB1c2goYyksYltjXT0hMCxhLnBsYXliYWNrUmF0ZT0wKX0sZT1mdW5jdGlvbihkKXtpZihudWxsIT09ZCl7YltkXT0hMTt2YXIgZT1iLmluZGV4T2YoZCk7LTEhPT1lJiZiLnNwbGljZShlLDEpLGMoKT09PSExJiYoYS5wbGF5YmFja1JhdGU9MSl9fSxmPWZ1bmN0aW9uKGEsYil7Yj9kKGEpOmUoYSl9O3JldHVybntzeXN0ZW06dm9pZCAwLHNldHVwOmZ1bmN0aW9uKCl7fSxwbGF5OmZ1bmN0aW9uKCl7YS5wbGF5KCl9LHBhdXNlOmZ1bmN0aW9uKCl7YS5wYXVzZSgpfSxpc1BhdXNlZDpmdW5jdGlvbigpe3JldHVybiBhLnBhdXNlZH0sZ2V0UGxheWJhY2tSYXRlOmZ1bmN0aW9uKCl7cmV0dXJuIGEucGxheWJhY2tSYXRlfSxzZXRQbGF5YmFja1JhdGU6ZnVuY3Rpb24oYil7YS5wbGF5YmFja1JhdGU9Yn0sZ2V0Q3VycmVudFRpbWU6ZnVuY3Rpb24oKXtyZXR1cm4gYS5jdXJyZW50VGltZX0sc2V0Q3VycmVudFRpbWU6ZnVuY3Rpb24oYil7YS5jdXJyZW50VGltZSE9YiYmKGEuY3VycmVudFRpbWU9Yil9LGxpc3RlbjpmdW5jdGlvbihiLGMpe2EuYWRkRXZlbnRMaXN0ZW5lcihiLGMsITEpfSx1bmxpc3RlbjpmdW5jdGlvbihiLGMpe2EucmVtb3ZlRXZlbnRMaXN0ZW5lcihiLGMsITEpfSxnZXRFbGVtZW50OmZ1bmN0aW9uKCl7cmV0dXJuIGF9LHNldEVsZW1lbnQ6ZnVuY3Rpb24oYil7YT1ifSxzZXRTb3VyY2U6ZnVuY3Rpb24oYil7YS5zcmM9Yn0sc3RhbGxTdHJlYW06Zixpc1N0YWxsZWQ6Y319LE1lZGlhUGxheWVyLm1vZGVscy5WaWRlb01vZGVsLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIubW9kZWxzLlZpZGVvTW9kZWx9LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5WaWRlb01vZGVsRXh0ZW5zaW9ucz1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3JldHVybntnZXREcm9wcGVkRnJhbWVzOmZ1bmN0aW9uKGEpe3ZhciBiPW51bGwhPT1hLndlYmtpdERyb3BwZWRGcmFtZUNvdW50LGM9LTE7cmV0dXJuIGImJihjPWEud2Via2l0RHJvcHBlZEZyYW1lQ291bnQpLGN9fX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlZpZGVvTW9kZWxFeHRlbnNpb25zLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlZpZGVvTW9kZWxFeHRlbnNpb25zfSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuVGV4dENvbnRyb2xsZXI9ZnVuY3Rpb24oKXt2YXIgYSxiLGM9XCJMT0FESU5HXCIsZD1cIlJFQURZXCIsZT0hMSxmPS0xLGc9ZCxoPWZ1bmN0aW9uKGEpe3RoaXMuZGVidWcubG9nKFwiVGV4dENvbnRyb2xsZXIgc2V0U3RhdGUgdG86XCIrYSksZz1hfSxpPWZ1bmN0aW9uKCl7aWYoZSYmZz09PWQpe3ZhciBiPXRoaXM7aC5jYWxsKGIsYyksYi5pbmRleEhhbmRsZXIuZ2V0SW5pdFJlcXVlc3QoMCxhKS50aGVuKGZ1bmN0aW9uKGEpe2IuZGVidWcubG9nKFwiTG9hZGluZyB0ZXh0IHRyYWNrIGluaXRpYWxpemF0aW9uOiBcIithLnVybCksYi5kZWJ1Zy5sb2coYSksYi5mcmFnbWVudExvYWRlci5sb2FkKGEpLnRoZW4oay5iaW5kKGIsYSksbC5iaW5kKGIsYSkpLGguY2FsbChiLGMpfSl9fSxqPWZ1bmN0aW9uKCl7aS5jYWxsKHRoaXMpfSxrPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9dGhpcztkLmRlYnVnLmxvZyhcIiBUZXh0IHRyYWNrIEJ5dGVzIGZpbmlzaGVkIGxvYWRpbmc6IFwiK2EudXJsKSxkLmZyYWdtZW50Q29udHJvbGxlci5wcm9jZXNzKGMuZGF0YSkudGhlbihmdW5jdGlvbihhKXtudWxsIT09YSYmKGQuZGVidWcubG9nKFwiUHVzaCB0ZXh0IHRyYWNrIGJ5dGVzOiBcIithLmJ5dGVMZW5ndGgpLGQuc291cmNlQnVmZmVyRXh0LmFwcGVuZChiLGEsZC52aWRlb01vZGVsKSl9KX0sbD1mdW5jdGlvbigpe307cmV0dXJue3ZpZGVvTW9kZWw6dm9pZCAwLGZyYWdtZW50TG9hZGVyOnZvaWQgMCxmcmFnbWVudENvbnRyb2xsZXI6dm9pZCAwLGluZGV4SGFuZGxlcjp2b2lkIDAsc291cmNlQnVmZmVyRXh0OnZvaWQgMCxkZWJ1Zzp2b2lkIDAsaW5pdGlhbGl6ZTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgZj10aGlzO2Yuc2V0VmlkZW9Nb2RlbChkKSxmLnNldFBlcmlvZEluZGV4KGEpLGYuc2V0RGF0YShiKSxmLnNldEJ1ZmZlcihjKSxlPSEwfSxnZXRQZXJpb2RJbmRleDpmdW5jdGlvbigpe3JldHVybiBmfSxzZXRQZXJpb2RJbmRleDpmdW5jdGlvbihhKXtmPWF9LGdldFZpZGVvTW9kZWw6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy52aWRlb01vZGVsfSxzZXRWaWRlb01vZGVsOmZ1bmN0aW9uKGEpe3RoaXMudmlkZW9Nb2RlbD1hfSxnZXREYXRhOmZ1bmN0aW9uKCl7cmV0dXJuIGF9LHNldERhdGE6ZnVuY3Rpb24oYil7YT1ifSxnZXRCdWZmZXI6ZnVuY3Rpb24oKXtyZXR1cm4gYn0sc2V0QnVmZmVyOmZ1bmN0aW9uKGEpe2I9YX0scmVzZXQ6ZnVuY3Rpb24oYSxjKXthfHwodGhpcy5zb3VyY2VCdWZmZXJFeHQuYWJvcnQoYyxiKSx0aGlzLnNvdXJjZUJ1ZmZlckV4dC5yZW1vdmVTb3VyY2VCdWZmZXIoYyxiKSl9LHN0YXJ0Omp9fSxNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuVGV4dENvbnRyb2xsZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuVGV4dENvbnRyb2xsZXJ9LE1lZGlhUGxheWVyLnV0aWxzLlRleHRUcmFja0V4dGVuc2lvbnM9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjtyZXR1cm57YWRkVGV4dFRyYWNrOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIGY9YS5hZGRUZXh0VHJhY2soXCJjYXB0aW9uc1wiLGMsZCk7Zi5kZWZhdWx0PWUsZi5tb2RlPVwic2hvd2luZ1wiO2Zvcih2YXIgZyBpbiBiKXt2YXIgaD1iW2ddO2YuYWRkQ3VlKG5ldyBUZXh0VHJhY2tDdWUoaC5zdGFydCxoLmVuZCxoLmRhdGEpKX1yZXR1cm4gUS53aGVuKGYpfSxkZWxldGVDdWVzOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj1hLnRleHRUcmFja3NbMF0sYz1iLmN1ZXMsZD1jLmxlbmd0aDtkPj0wO2QtLSliLnJlbW92ZUN1ZShjW2RdKTtiLm1vZGU9XCJkaXNhYmxlZFwifX19LE1lZGlhUGxheWVyLmRlcGVuZGVuY2llcy5UZXh0VlRUU291cmNlQnVmZmVyPWZ1bmN0aW9uKCl7dmFyIGEsYixjO3JldHVybntzeXN0ZW06dm9pZCAwLGV2ZW50QnVzOnZvaWQgMCxpbml0aWFsaXplOmZ1bmN0aW9uKGQsZSl7Yz1kLGE9ZS5nZXRWaWRlb01vZGVsKCkuZ2V0RWxlbWVudCgpLGI9ZS5nZXREYXRhKCl9LGFwcGVuZDpmdW5jdGlvbihjKXt2YXIgZD10aGlzO2QuZ2V0UGFyc2VyKCkucGFyc2UoU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLG5ldyBVaW50MTZBcnJheShjKSkpLnRoZW4oZnVuY3Rpb24oYyl7dmFyIGU9Yi5SZXByZXNlbnRhdGlvbl9hc0FycmF5WzBdLmlkLGY9Yi5sYW5nO2QuZ2V0VGV4dFRyYWNrRXh0ZW5zaW9ucygpLmFkZFRleHRUcmFjayhhLGMsZSxmLCEwKS50aGVuKGZ1bmN0aW9uKCl7ZC5ldmVudEJ1cy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwidXBkYXRlZW5kXCJ9KX0pfSl9LGFib3J0OmZ1bmN0aW9uKCl7dGhpcy5nZXRUZXh0VHJhY2tFeHRlbnNpb25zKCkuZGVsZXRlQ3VlcyhhKX0sZ2V0UGFyc2VyOmZ1bmN0aW9uKCl7dmFyIGE7cmV0dXJuXCJ0ZXh0L3Z0dFwiPT09YyYmKGE9dGhpcy5zeXN0ZW0uZ2V0T2JqZWN0KFwidnR0UGFyc2VyXCIpKSxhfSxnZXRUZXh0VHJhY2tFeHRlbnNpb25zOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc3lzdGVtLmdldE9iamVjdChcInRleHRUcmFja0V4dGVuc2lvbnNcIil9LGFkZEV2ZW50TGlzdGVuZXI6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuZXZlbnRCdXMuYWRkRXZlbnRMaXN0ZW5lcihhLGIsYyl9LHJlbW92ZUV2ZW50TGlzdGVuZXI6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuZXZlbnRCdXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihhLGIsYyl9fX0sTWVkaWFQbGF5ZXIuZGVwZW5kZW5jaWVzLlRleHRWVFRTb3VyY2VCdWZmZXIucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5kZXBlbmRlbmNpZXMuVGV4dFZUVFNvdXJjZUJ1ZmZlcn0sTWVkaWFQbGF5ZXIudXRpbHMuVlRUUGFyc2VyPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9ZnVuY3Rpb24oYSl7dmFyIGI9YS5zcGxpdChcIjpcIiksYz1iLmxlbmd0aC0xO3JldHVybiBhPTYwKnBhcnNlSW50KGJbYy0xXSwxMCkrcGFyc2VGbG9hdChiW2NdLDEwKSwyPT09YyYmKGErPTM2MDAqcGFyc2VJbnQoYlswXSwxMCkpLGF9O3JldHVybntwYXJzZTpmdW5jdGlvbihiKXt2YXIgYyxkPS8oPzpcXHJcXG58XFxyfFxcbikvZ20sZT0vLS0+LyxmPS8oXltcXHNdK3xbXFxzXSskKS9nLGc9W107Yj1iLnNwbGl0KGQpLGM9Yi5sZW5ndGg7Zm9yKHZhciBoPTA7Yz5oO2grKyl7dmFyIGk9YltoXTtpZihpLmxlbmd0aD4wJiZcIldFQlZUVFwiIT09aSYmaS5tYXRjaChlKSl7dmFyIGo9aS5zcGxpdChlKSxrPWJbaCsxXTtnLnB1c2goe3N0YXJ0OmEoalswXS5yZXBsYWNlKGYsXCJcIikpLGVuZDphKGpbMV0ucmVwbGFjZShmLFwiXCIpKSxkYXRhOmt9KX19cmV0dXJuIFEud2hlbihnKX19fSxNZWRpYVBsYXllci5ydWxlcy5CYXNlUnVsZXNDb2xsZWN0aW9uPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGE9W107cmV0dXJue2Rvd25sb2FkUmF0aW9SdWxlOnZvaWQgMCxpbnN1ZmZpY2llbnRCdWZmZXJSdWxlOnZvaWQgMCxnZXRSdWxlczpmdW5jdGlvbigpe3JldHVybiBRLndoZW4oYSl9LHNldHVwOmZ1bmN0aW9uKCl7dmFyIGE9dGhpczthLmdldFJ1bGVzKCkudGhlbihmdW5jdGlvbihiKXtiLnB1c2goYS5kb3dubG9hZFJhdGlvUnVsZSksYi5wdXNoKGEuaW5zdWZmaWNpZW50QnVmZmVyUnVsZSl9KX19fSxNZWRpYVBsYXllci5ydWxlcy5CYXNlUnVsZXNDb2xsZWN0aW9uLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIucnVsZXMuQmFzZVJ1bGVzQ29sbGVjdGlvbn0sTWVkaWFQbGF5ZXIucnVsZXMuRG93bmxvYWRSYXRpb1J1bGU9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT1mdW5jdGlvbihhLGIsYyl7dmFyIGQ9dGhpcyxlPVEuZGVmZXIoKTtyZXR1cm4gZC5tYW5pZmVzdEV4dC5nZXRSZXByZXNlbnRhdGlvbkZvcihhLGMpLnRoZW4oZnVuY3Rpb24oYSl7ZC5tYW5pZmVzdEV4dC5nZXRCYW5kd2lkdGgoYSkudGhlbihmdW5jdGlvbihhKXtlLnJlc29sdmUoYS9iKX0pfSksZS5wcm9taXNlfTtyZXR1cm57ZGVidWc6dm9pZCAwLG1hbmlmZXN0RXh0OnZvaWQgMCxjaGVja0luZGV4OmZ1bmN0aW9uKGIsYyxkKXt2YXIgZSxmLGcsaCxpLGosayxsLG0sbixvPXRoaXMscD1jLkh0dHBMaXN0LHE9Ljc1O3JldHVybiBvLmRlYnVnLmxvZyhcIkNoZWNraW5nIGRvd25sb2FkIHJhdGlvIHJ1bGUuLi5cIiksYz9udWxsPT09cHx8dm9pZCAwPT09cHx8MD09PXAubGVuZ3RoPyhvLmRlYnVnLmxvZyhcIk5vIHJlcXVlc3RzIG1hZGUgZm9yIHRoaXMgc3RyZWFtIHlldCwgYmFpbGluZy5cIiksUS53aGVuKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KSk6KGU9cFtwLmxlbmd0aC0xXSxnPShlLnRmaW5pc2guZ2V0VGltZSgpLWUudHJlcXVlc3QuZ2V0VGltZSgpKS8xZTMsZj0oZS50ZmluaXNoLmdldFRpbWUoKS1lLnRyZXNwb25zZS5nZXRUaW1lKCkpLzFlMywwPj1nPyhvLmRlYnVnLmxvZyhcIkRvbid0IGtub3cgaG93IGxvbmcgdGhlIGRvd25sb2FkIG9mIHRoZSBsYXN0IGZyYWdtZW50IHRvb2ssIGJhaWxpbmcuXCIpLFEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdCkpOm51bGw9PT1lLm1lZGlhZHVyYXRpb258fHZvaWQgMD09PWUubWVkaWFkdXJhdGlvbnx8ZS5tZWRpYWR1cmF0aW9uPD0wPyhvLmRlYnVnLmxvZyhcIkRvbid0IGtub3cgdGhlIGR1cmF0aW9uIG9mIHRoZSBsYXN0IG1lZGlhIGZyYWdtZW50LCBiYWlsaW5nLlwiKSxRLndoZW4obmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QpKTooaz1RLmRlZmVyKCksaT1lLm1lZGlhZHVyYXRpb24vZyxoPWUubWVkaWFkdXJhdGlvbi9mKnEsaXNOYU4oaCl8fGlzTmFOKGkpPyhvLmRlYnVnLmxvZyhcIlRvdGFsIHRpbWU6IFwiK2crXCJzXCIpLG8uZGVidWcubG9nKFwiRG93bmxvYWQgdGltZTogXCIrZitcInNcIiksby5kZWJ1Zy5sb2coXCJUaGUgcmF0aW9zIGFyZSBOYU4sIGJhaWxpbmcuXCIpLFEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdCkpOihvLmRlYnVnLmxvZyhcIlRvdGFsIHJhdGlvOiBcIitpKSxvLmRlYnVnLmxvZyhcIkRvd25sb2FkIHJhdGlvOiBcIitoKSxvLmRlYnVnLmxvZyhcIkRvd25sb2FkIHJhdGlvOiBcIitoKSxpc05hTihoKT8oby5kZWJ1Zy5sb2coXCJJbnZhbGlkIHJhdGlvLCBiYWlsaW5nLlwiKSxrLnJlc29sdmUobmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QpKToxPmg/KG8uZGVidWcubG9nKFwiRG93bmxvYWQgcmF0aW8gaXMgcG9vci5cIiksYj4wPyhvLmRlYnVnLmxvZyhcIldlIGFyZSBub3QgYXQgdGhlIGxvd2VzdCBiaXRyYXRlLCBzbyBzd2l0Y2ggZG93bi5cIiksby5tYW5pZmVzdEV4dC5nZXRSZXByZXNlbnRhdGlvbkZvcihiLTEsZCkudGhlbihmdW5jdGlvbihhKXtvLm1hbmlmZXN0RXh0LmdldEJhbmR3aWR0aChhKS50aGVuKGZ1bmN0aW9uKGEpe28ubWFuaWZlc3RFeHQuZ2V0UmVwcmVzZW50YXRpb25Gb3IoYixkKS50aGVuKGZ1bmN0aW9uKGMpe28ubWFuaWZlc3RFeHQuZ2V0QmFuZHdpZHRoKGMpLnRoZW4oZnVuY3Rpb24oYyl7aj1hL2Msby5kZWJ1Zy5sb2coXCJTd2l0Y2ggcmF0aW86IFwiK2opLGo+aD8oby5kZWJ1Zy5sb2coXCJUaGluZ3MgbXVzdCBiZSBnb2luZyBwcmV0dHkgYmFkLCBzd2l0Y2ggYWxsIHRoZSB3YXkgZG93bi5cIiksay5yZXNvbHZlKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KDApKSk6KG8uZGVidWcubG9nKFwiVGhpbmdzIGNvdWxkIGJlIGJldHRlciwgc28ganVzdCBzd2l0Y2ggZG93biBvbmUgaW5kZXguXCIpLGsucmVzb2x2ZShuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChiLTEpKSlcclxufSl9KX0pfSkpOihvLmRlYnVnLmxvZyhcIldlIGFyZSBhdCB0aGUgbG93ZXN0IGJpdHJhdGUgYW5kIGNhbm5vdCBzd2l0Y2ggZG93biwgdXNlIGN1cnJlbnQuXCIpLGsucmVzb2x2ZShuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChiKSkpKTooby5kZWJ1Zy5sb2coXCJEb3dubG9hZCByYXRpbyBpcyBnb29kLlwiKSxvLm1hbmlmZXN0RXh0LmdldFJlcHJlc2VudGF0aW9uQ291bnQoZCkudGhlbihmdW5jdGlvbihjKXtjLT0xLGM+Yj8oby5kZWJ1Zy5sb2coXCJXZSBhcmUgbm90IGF0IHRoZSBoaWdoZXN0IGJpdHJhdGUsIHNvIHN3aXRjaCB1cC5cIiksby5tYW5pZmVzdEV4dC5nZXRSZXByZXNlbnRhdGlvbkZvcihiKzEsZCkudGhlbihmdW5jdGlvbihlKXtvLm1hbmlmZXN0RXh0LmdldEJhbmR3aWR0aChlKS50aGVuKGZ1bmN0aW9uKGUpe28ubWFuaWZlc3RFeHQuZ2V0UmVwcmVzZW50YXRpb25Gb3IoYixkKS50aGVuKGZ1bmN0aW9uKGYpe28ubWFuaWZlc3RFeHQuZ2V0QmFuZHdpZHRoKGYpLnRoZW4oZnVuY3Rpb24oZil7aWYoaj1lL2Ysby5kZWJ1Zy5sb2coXCJTd2l0Y2ggcmF0aW86IFwiK2opLGg+PWopaWYoaD4xZTMpby5kZWJ1Zy5sb2coXCJUb25zIG9mIGJhbmR3aWR0aCBhdmFpbGFibGUsIGdvIGFsbCB0aGUgd2F5IHVwLlwiKSxrLnJlc29sdmUobmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QoYy0xKSk7ZWxzZSBpZihoPjEwMClvLmRlYnVnLmxvZyhcIkp1c3QgZW5vdWdoIGJhbmR3aWR0aCBhdmFpbGFibGUsIHN3aXRjaCB1cCBvbmUuXCIpLGsucmVzb2x2ZShuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChiKzEpKTtlbHNle2ZvcihvLmRlYnVnLmxvZyhcIk5vdCBleGFjdGx5IHN1cmUgd2hlcmUgdG8gZ28sIHNvIGRvIHNvbWUgbWF0aC5cIiksbT0tMSxsPVtdOyhtKz0xKTxjOylsLnB1c2goYS5jYWxsKG8sbSxmLGQpKTtRLmFsbChsKS50aGVuKGZ1bmN0aW9uKGEpe2ZvcihtPTAsbj1hLmxlbmd0aDtuPm0mJiEoaDxhW21dKTttKz0xKTtvLmRlYnVnLmxvZyhcIkNhbGN1bGF0ZWQgaWRlYWwgbmV3IHF1YWxpdHkgaW5kZXggaXM6IFwiK20pLGsucmVzb2x2ZShuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChtKSl9KX1lbHNlIG8uZGVidWcubG9nKFwiTm90IGVub3VnaCBiYW5kd2lkdGggdG8gc3dpdGNoIHVwLlwiKSxrLnJlc29sdmUobmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QpfSl9KX0pfSkpOihvLmRlYnVnLmxvZyhcIldlIGFyZSBhdCB0aGUgaGlnaGVzdCBiaXRyYXRlIGFuZCBjYW5ub3Qgc3dpdGNoIHVwLCB1c2UgY3VycmVudC5cIiksay5yZXNvbHZlKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KGMpKSl9KSksay5wcm9taXNlKSkpOihvLmRlYnVnLmxvZyhcIk5vIG1ldHJpY3MsIGJhaWxpbmcuXCIpLFEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdCkpfX19LE1lZGlhUGxheWVyLnJ1bGVzLkRvd25sb2FkUmF0aW9SdWxlLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIucnVsZXMuRG93bmxvYWRSYXRpb1J1bGV9LE1lZGlhUGxheWVyLnJ1bGVzLkluc3VmZmljaWVudEJ1ZmZlclJ1bGU9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT0wLGI9MztyZXR1cm57ZGVidWc6dm9pZCAwLGNoZWNrSW5kZXg6ZnVuY3Rpb24oYyxkKXt2YXIgZSxmLGc9dGhpcyxoPSExLGk9TWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuREVGQVVMVDtyZXR1cm4gZy5kZWJ1Zy5sb2coXCJDaGVja2luZyBpbnN1ZmZpY2llbnQgYnVmZmVyIHJ1bGUuLi5cIiksbnVsbD09PWQuUGxheUxpc3R8fHZvaWQgMD09PWQuUGxheUxpc3R8fDA9PT1kLlBsYXlMaXN0Lmxlbmd0aD8oZy5kZWJ1Zy5sb2coXCJOb3QgZW5vdWdoIGluZm9ybWF0aW9uIGZvciBydWxlLlwiKSxRLndoZW4obmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QpKTooZT1kLlBsYXlMaXN0W2QuUGxheUxpc3QubGVuZ3RoLTFdLG51bGw9PT1lfHx2b2lkIDA9PT1lfHwwPT09ZS50cmFjZS5sZW5ndGg/KGcuZGVidWcubG9nKFwiTm90IGVub3VnaCBpbmZvcm1hdGlvbiBmb3IgcnVsZS5cIiksUS53aGVuKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KSk6KGY9ZS50cmFjZVtlLnRyYWNlLmxlbmd0aC0yXSxudWxsPT09Znx8dm9pZCAwPT09Znx8bnVsbD09PWYuc3RvcHJlYXNvbnx8dm9pZCAwPT09Zi5zdG9wcmVhc29uPyhnLmRlYnVnLmxvZyhcIk5vdCBlbm91Z2ggaW5mb3JtYXRpb24gZm9yIHJ1bGUuXCIpLFEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdCkpOihmLnN0b3ByZWFzb249PT1NZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlLlJFQlVGRkVSSU5HX1JFQVNPTiYmKGg9ITAsYSs9MSxnLmRlYnVnLmxvZyhcIk51bWJlciBvZiB0aW1lcyB0aGUgYnVmZmVyIGhhcyBydW4gZHJ5OiBcIithKSksYT5iJiYoaT1NZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkcsZy5kZWJ1Zy5sb2coXCJBcHBseSBTVFJPTkcgdG8gYnVmZmVyIHJ1bGUuXCIpKSxoPyhnLmRlYnVnLmxvZyhcIlRoZSBidWZmZXIgcmFuIGRyeSByZWNlbnRseSwgc3dpdGNoIGRvd24uXCIpLFEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChjLTEsaSkpKTphPmI/KGcuZGVidWcubG9nKFwiVG9vIG1hbnkgZHJ5IGJ1ZmZlciBoaXRzLCBxdWl0IHN3aXRjaGluZyBiaXRyYXRlcy5cIiksUS53aGVuKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KGMsaSkpKTpRLndoZW4obmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QoTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuTk9fQ0hBTkdFLGkpKSkpKX19fSxNZWRpYVBsYXllci5ydWxlcy5JbnN1ZmZpY2llbnRCdWZmZXJSdWxlLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIucnVsZXMuSW5zdWZmaWNpZW50QnVmZmVyUnVsZX0sTWVkaWFQbGF5ZXIucnVsZXMuTGltaXRTd2l0Y2hlc1J1bGU9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt2YXIgYT0xMCxiPTJlNCxjPTUsZD0wO3JldHVybntkZWJ1Zzp2b2lkIDAsY2hlY2tJbmRleDpmdW5jdGlvbihlLGYpe2lmKGQ+MClyZXR1cm4gZC09MSxRLndoZW4obmV3IE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QoZSxNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5TVFJPTkcpKTt2YXIgZyxoLGksaj10aGlzLGs9ITEsbD0obmV3IERhdGUpLmdldFRpbWUoKSxtPWYuUmVwU3dpdGNoTGlzdC5sZW5ndGg7Zm9yKGouZGVidWcubG9nKFwiQ2hlY2tpbmcgbGltaXQgc3dpdGNoZXMgcnVsZS4uLlwiKSxpPW0tMTtpPj0wO2ktPTEpe2lmKGc9Zi5SZXBTd2l0Y2hMaXN0W2ldLGg9bC1nLnQuZ2V0VGltZSgpLGg+PWIpe2ouZGVidWcubG9nKFwiUmVhY2hlZCB0aW1lIGxpbWl0LCBiYWlsaW5nLlwiKTticmVha31pZihpPj1hKXtqLmRlYnVnLmxvZyhcIkZvdW5kIHRvbyBtYW55IHN3aXRjaGVzIHdpdGhpbiB2YWxpZGF0aW9uIHRpbWUsIGZvcmNlIHRoZSBzdHJlYW0gdG8gbm90IGNoYW5nZS5cIiksaz0hMDticmVha319cmV0dXJuIGs/KGouZGVidWcubG9nKFwiV2FpdCBzb21lIHRpbWUgYmVmb3JlIGFsbG93aW5nIGFub3RoZXIgc3dpdGNoLlwiKSxkPWMsUS53aGVuKG5ldyBNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0KGUsTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuU1RST05HKSkpOlEud2hlbihuZXcgTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdChNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LnByb3RvdHlwZS5OT19DSEFOR0UsTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdC5wcm90b3R5cGUuU1RST05HKSl9fX0sTWVkaWFQbGF5ZXIucnVsZXMuTGltaXRTd2l0Y2hlc1J1bGUucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5ydWxlcy5MaW1pdFN3aXRjaGVzUnVsZX0sTWVkaWFQbGF5ZXIucnVsZXMuU3dpdGNoUmVxdWVzdD1mdW5jdGlvbihhLGIpe1widXNlIHN0cmljdFwiO3RoaXMucXVhbGl0eT1hLHRoaXMucHJpb3JpdHk9Yix2b2lkIDA9PT10aGlzLnF1YWxpdHkmJih0aGlzLnF1YWxpdHk9OTk5KSx2b2lkIDA9PT10aGlzLnByaW9yaXR5JiYodGhpcy5wcmlvcml0eT0uNSl9LE1lZGlhUGxheWVyLnJ1bGVzLlN3aXRjaFJlcXVlc3QucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci5ydWxlcy5Td2l0Y2hSZXF1ZXN0LE5PX0NIQU5HRTo5OTksREVGQVVMVDouNSxTVFJPTkc6MSxXRUFLOjB9LE1lZGlhUGxheWVyLm1vZGVscy5NZXRyaWNzTGlzdD1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3JldHVybntUY3BMaXN0OltdLEh0dHBMaXN0OltdLFJlcFN3aXRjaExpc3Q6W10sQnVmZmVyTGV2ZWw6W10sUGxheUxpc3Q6W10sRHJvcHBlZEZyYW1lczpbXX19LE1lZGlhUGxheWVyLm1vZGVscy5NZXRyaWNzTGlzdC5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLm1vZGVscy5NZXRyaWNzTGlzdH0sTWVkaWFQbGF5ZXIudm8uU2VnbWVudFJlcXVlc3Q9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt0aGlzLmFjdGlvbj1cImRvd25sb2FkXCIsdGhpcy5zdGFydFRpbWU9MC8wLHRoaXMuc3RyZWFtVHlwZT1udWxsLHRoaXMudHlwZT1udWxsLHRoaXMuZHVyYXRpb249MC8wLHRoaXMudGltZXNjYWxlPTAvMCx0aGlzLnJhbmdlPW51bGwsdGhpcy51cmw9bnVsbCx0aGlzLnJlcXVlc3RTdGFydERhdGU9bnVsbCx0aGlzLmZpcnN0Qnl0ZURhdGU9bnVsbCx0aGlzLnJlcXVlc3RFbmREYXRlPW51bGwsdGhpcy5kZWZlcnJlZD1udWxsLHRoaXMucXVhbGl0eT0wLzAsdGhpcy5pbmRleD0wLzB9LE1lZGlhUGxheWVyLnZvLlNlZ21lbnRSZXF1ZXN0LnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIudm8uU2VnbWVudFJlcXVlc3QsQUNUSU9OX0RPV05MT0FEOlwiZG93bmxvYWRcIixBQ1RJT05fQ09NUExFVEU6XCJjb21wbGV0ZVwifSxNZWRpYVBsYXllci52by5tZXRyaWNzLkJ1ZmZlckxldmVsPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dGhpcy50PW51bGwsdGhpcy5sZXZlbD1udWxsfSxNZWRpYVBsYXllci52by5tZXRyaWNzLkJ1ZmZlckxldmVsLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIudm8ubWV0cmljcy5CdWZmZXJMZXZlbH0sTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5Ecm9wcGVkRnJhbWVzPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dGhpcy50aW1lPW51bGwsdGhpcy5kcm9wcGVkRnJhbWVzPW51bGx9LE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuRHJvcHBlZEZyYW1lcy5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOk1lZGlhUGxheWVyLnZvLm1ldHJpY3MuRHJvcHBlZEZyYW1lc30sTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5IVFRQUmVxdWVzdD1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3RoaXMudGNwaWQ9bnVsbCx0aGlzLnR5cGU9bnVsbCx0aGlzLnVybD1udWxsLHRoaXMuYWN0dWFsdXJsPW51bGwsdGhpcy5yYW5nZT1udWxsLHRoaXMudHJlcXVlc3Q9bnVsbCx0aGlzLnRyZXNwb25zZT1udWxsLHRoaXMudGZpbmlzaD1udWxsLHRoaXMucmVzcG9uc2Vjb2RlPW51bGwsdGhpcy5pbnRlcnZhbD1udWxsLHRoaXMubWVkaWFkdXJhdGlvbj1udWxsLHRoaXMudHJhY2U9W119LE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuSFRUUFJlcXVlc3QucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci52by5tZXRyaWNzLkhUVFBSZXF1ZXN0fSxNZWRpYVBsYXllci52by5tZXRyaWNzLkhUVFBSZXF1ZXN0LlRyYWNlPWZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7dGhpcy5zPW51bGwsdGhpcy5kPW51bGwsdGhpcy5iPVtdfSxNZWRpYVBsYXllci52by5tZXRyaWNzLkhUVFBSZXF1ZXN0LlRyYWNlLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIudm8ubWV0cmljcy5IVFRQUmVxdWVzdC5UcmFjZX0sTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdD1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3RoaXMuc3RhcnQ9bnVsbCx0aGlzLm1zdGFydD1udWxsLHRoaXMuc3RhcnR0eXBlPW51bGwsdGhpcy50cmFjZT1bXX0sTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZT1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3RoaXMucmVwcmVzZW50YXRpb25pZD1udWxsLHRoaXMuc3VicmVwbGV2ZWw9bnVsbCx0aGlzLnN0YXJ0PW51bGwsdGhpcy5tc3RhcnQ9bnVsbCx0aGlzLmR1cmF0aW9uPW51bGwsdGhpcy5wbGF5YmFja3NwZWVkPW51bGwsdGhpcy5zdG9wcmVhc29uPW51bGx9LE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUGxheUxpc3QucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0fSxNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LklOSVRJQUxfUExBWV9TVEFSVF9SRUFTT049XCJpbml0aWFsX3N0YXJ0XCIsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5TRUVLX1NUQVJUX1JFQVNPTj1cInNlZWtcIixNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlLnByb3RvdHlwZT17Y29uc3RydWN0b3I6TWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZSgpfSxNZWRpYVBsYXllci52by5tZXRyaWNzLlBsYXlMaXN0LlRyYWNlLlVTRVJfUkVRVUVTVF9TVE9QX1JFQVNPTj1cInVzZXJfcmVxdWVzdFwiLE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUGxheUxpc3QuVHJhY2UuUkVQUkVTRU5UQVRJT05fU1dJVENIX1NUT1BfUkVBU09OPVwicmVwcmVzZW50YXRpb25fc3dpdGNoXCIsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZS5FTkRfT0ZfQ09OVEVOVF9TVE9QX1JFQVNPTj1cImVuZF9vZl9jb250ZW50XCIsTWVkaWFQbGF5ZXIudm8ubWV0cmljcy5QbGF5TGlzdC5UcmFjZS5SRUJVRkZFUklOR19SRUFTT049XCJyZWJ1ZmZlcmluZ1wiLE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUmVwcmVzZW50YXRpb25Td2l0Y2g9ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt0aGlzLnQ9bnVsbCx0aGlzLm10PW51bGwsdGhpcy50bz1udWxsLHRoaXMubHRvPW51bGx9LE1lZGlhUGxheWVyLnZvLm1ldHJpY3MuUmVwcmVzZW50YXRpb25Td2l0Y2gucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci52by5tZXRyaWNzLlJlcHJlc2VudGF0aW9uU3dpdGNofSxNZWRpYVBsYXllci52by5tZXRyaWNzLlRDUENvbm5lY3Rpb249ZnVuY3Rpb24oKXtcInVzZSBzdHJpY3RcIjt0aGlzLnRjcGlkPW51bGwsdGhpcy5kZXN0PW51bGwsdGhpcy50b3Blbj1udWxsLHRoaXMudGNsb3NlPW51bGwsdGhpcy50Y29ubmVjdD1udWxsfSxNZWRpYVBsYXllci52by5tZXRyaWNzLlRDUENvbm5lY3Rpb24ucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpNZWRpYVBsYXllci52by5tZXRyaWNzLlRDUENvbm5lY3Rpb259OyJdLCJmaWxlIjoiZGFzaC5hbGwuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.min.js new file mode 100644 index 000000000..48284b9f5 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/dash.all.min.js @@ -0,0 +1,6 @@ +function X2JS(e,t,n){function r(e){var t=e.localName;return null==t&&(t=e.baseName),(null==t||""==t)&&(t=e.nodeName),t}function i(e){return e.prefix}function o(e){return"string"==typeof e?e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):e}function a(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(///g,"/")}function s(o){if(o.nodeType==b.DOCUMENT_NODE){var u,l,d,c=o.firstChild;for(l=0,d=o.childNodes.length;d>l;l+=1)if(o.childNodes[l].nodeType!==b.COMMENT_NODE){c=o.childNodes[l];break}if(n)u=s(c);else{u={};var f=r(c);u[f]=s(c)}return u}if(o.nodeType==b.ELEMENT_NODE){var u=new Object;u.__cnt=0;for(var g=o.childNodes,h=0;hS;S++){var P=e[S];P.test.call(this,v.value)&&(E=P.converter.call(this,v.value))}u[t+v.name]=E}var T=i(o);return null!=T&&""!=T&&(u.__cnt++,u.__prefix=T),1==u.__cnt&&null!=u["#text"]&&(u=u["#text"]),null!=u["#text"]&&(u.__text=u["#text"],M&&(u.__text=a(u.__text)),delete u["#text"],delete u["#text_asArray"]),null!=u["#cdata-section"]&&(u.__cdata=u["#cdata-section"],delete u["#cdata-section"],delete u["#cdata-section_asArray"]),(null!=u.__text||null!=u.__cdata)&&(u.toString=function(){return(null!=this.__text?this.__text:"")+(null!=this.__cdata?this.__cdata:"")}),u}return o.nodeType==b.TEXT_NODE||o.nodeType==b.CDATA_SECTION_NODE?o.nodeValue:o.nodeType==b.COMMENT_NODE?null:void 0}function u(e,t,n,r){var i="<"+(null!=e&&null!=e.__prefix?e.__prefix+":":"")+t;if(null!=n)for(var o=0;o":">"}function l(e,t){return""+(null!=e.__prefix?e.__prefix+":":"")+t+">"}function d(e,t){return-1!==e.indexOf(t,e.length-t.length)}function c(e,t){return d(t.toString(),"_asArray")||0==t.toString().indexOf("_")||e[t]instanceof Function?!0:!1}function f(e){var t=0;if(e instanceof Object)for(var n in e)c(e,n)||t++;return t}function g(e){var t=[];if(e instanceof Object)for(var n in e)-1==n.toString().indexOf("__")&&0==n.toString().indexOf("_")&&t.push(n);return t}function h(e){var t="";return null!=e.__cdata&&(t+=""),null!=e.__text&&(t+=M?o(e.__text):e.__text),t}function p(e){var t="";return e instanceof Object?t+=h(e):null!=e&&(t+=M?o(e):e),t}function m(e,t,n){var r="";if(0==e.length)r+=u(e,t,n,!0);else for(var i=0;i0)for(var r in e)if(!c(e,r)){var i=e[r],o=g(i);if(null==i||void 0==i)t+=u(i,r,o,!0);else if(i instanceof Object)if(i instanceof Array)t+=m(i,r,o);else{var a=f(i);a>0||null!=i.__text||null!=i.__cdata?(t+=u(i,r,o,!1),t+=y(i),t+=l(i,r)):t+=u(i,r,o,!0)}else t+=u(i,r,o,!1),t+=p(i),t+=l(i,r)}return t+=p(e)}(null===t||void 0===t)&&(t="_"),(null===n||void 0===n)&&(n=!1);var v="1.0.11",M=!1,b={ELEMENT_NODE:1,TEXT_NODE:3,CDATA_SECTION_NODE:4,COMMENT_NODE:8,DOCUMENT_NODE:9};this.parseXmlString=function(e){var t;if(window.DOMParser){var n=new window.DOMParser;t=n.parseFromString(e,"text/xml")}else 0==e.indexOf("")&&(e=e.substr(e.indexOf("?>")+2)),t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e);return t},this.xml2json=function(e){return s(e)},this.xml_str2json=function(e){var t=this.parseXmlString(e);return this.xml2json(t)},this.json2xml_str=function(e){return y(e)},this.json2xml=function(e){var t=this.json2xml_str(e);return this.parseXmlString(t)},this.getVersion=function(){return v},this.escapeMode=function(e){M=e}}function ObjectIron(e){var t;for(t=[],i=0,len=e.length;len>i;i+=1)t.push(e[i].isRoot?"root":e[i].name);var n=function(e,t){var n;if(null!==e&&null!==t)for(n in e)e.hasOwnProperty(n)&&(t.hasOwnProperty(n)||(t[n]=e[n]))},r=function(e,t,r){var i,o,a,s,u;if(null!==e&&0!==e.length)for(i=0,o=e.length;o>i;i+=1)a=e[i],t.hasOwnProperty(a.name)&&(r.hasOwnProperty(a.name)?a.merge&&(s=t[a.name],u=r[a.name],"object"==typeof s&&"object"==typeof u?n(s,u):r[a.name]=null!=a.mergeFunction?a.mergeFunction(s,u):s+u):r[a.name]=t[a.name])},o=function(e,t){var n,i,a,s,u,l,d,c=e;if(null!==c.children&&0!==c.children.length)for(n=0,i=c.children.length;i>n;n+=1)if(l=c.children[n],t.hasOwnProperty(l.name))if(l.isArray)for(u=t[l.name+"_asArray"],a=0,s=u.length;s>a;a+=1)d=u[a],r(c.properties,t,d),o(l,d);else d=t[l.name],r(c.properties,t,d),o(l,d)},a=function(n){var r,i,s,u,l,d,c;if(null===n)return n;if("object"!=typeof n)return n;for(r=0,i=t.length;i>r;r+=1)"root"===t[r]&&(l=e[r],d=n,o(l,d));for(u in n)if(n.hasOwnProperty(u)){if(s=t.indexOf(u),-1!==s)if(l=e[s],l.isArray)for(c=n[u+"_asArray"],r=0,i=c.length;i>r;r+=1)d=c[r],o(l,d);else d=n[u],o(l,d);a(n[u])}return n};return{run:a}}if(function(e){e(void 0,Q={})}(function(e,t){function n(e,t){t.stack&&"object"==typeof e&&null!==e&&e.stack&&-1===e.stack.indexOf(F)&&(e.stack=r(e.stack)+"\n"+F+"\n"+r(t.stack))}function r(e){for(var e=e.split("\n"),t=[],n=0;n=w&&K>=o}else r=!1;!r&&!(-1!==i.indexOf("(module.js:")||-1!==i.indexOf("(node.js:"))&&t.push(i)}return t.join("\n")}function i(){if(Error.captureStackTrace){var e,t,n=Error.prepareStackTrace;return Error.prepareStackTrace=function(n,r){e=r[1].getFileName(),t=r[1].getLineNumber()},Error().stack,Error.prepareStackTrace=n,S=e,t}}function o(e,t,n){return function(){return"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(t+" is deprecated, use "+n+" instead.",Error("").stack),e.apply(e,arguments)}}function a(){function e(e){n&&(t=g(e),A(n,function(e,n){R(function(){t.promiseDispatch.apply(t,n)})},void 0),r=n=void 0)}var t,n=[],r=[],i=I(a.prototype),o=I(s.prototype);return o.promiseDispatch=function(e,i,o){var a=C(arguments);n?(n.push(a),"when"===i&&o[1]&&r.push(o[1])):R(function(){t.promiseDispatch.apply(t,a)})},o.valueOf=function(){return n?o:t.valueOf()},Error.captureStackTrace&&(Error.captureStackTrace(o,a),o.stack=o.stack.substring(o.stack.indexOf("\n")+1)),T(o),i.promise=o,i.resolve=e,i.reject=function(t){e(f(t))},i.notify=function(e){n&&A(r,function(t,n){R(function(){n(e)})},void 0)},i}function s(e,t,n,r){void 0===t&&(t=function(e){return f(Error("Promise does not support operation: "+e))});var i=I(s.prototype);return i.promiseDispatch=function(n,r,o){var a;try{a=e[r]?e[r].apply(i,o):t.call(i,r,o)}catch(s){a=f(s)}n&&n(a)},n&&(i.valueOf=n),r&&(i.exception=r),T(i),i}function u(e){return l(e)?e.valueOf():e}function l(e){return e&&"function"==typeof e.promiseDispatch}function d(e){return!l(u(e))}function c(e){return e=u(e),l(e)&&"exception"in e}function f(e){var e=e||Error(),t=s({when:function(t){if(t){var n=B(Q,this);-1!==n&&(j.splice(n,1),Q.splice(n,1))}return t?t(e):f(e)}},function(){return f(e)},function(){return this},e);return!U&&"undefined"!=typeof window&&!window.Touch&&window.console&&console.log("Should be empty:",j),U=!0,Q.push(t),j.push(e),t}function g(e){if(l(e))return e;if((e=u(e))&&"function"==typeof e.then){var t=a();return e.then(t.resolve,t.reject,t.notify),t.promise}return s({when:function(){return e},get:function(t){return e[t]},put:function(t,n){return e[t]=n,e},del:function(t){return delete e[t],e},post:function(t,n){return e[t].apply(e,n)},apply:function(t){return e.apply(void 0,t)},keys:function(){return q(e)}},void 0,function(){return e})}function h(e,t,r,i){function o(e){try{return t?t(e):e}catch(n){return f(n)}}function s(e){if(r){n(e,d);try{return r(e)}catch(t){return f(t)}}return f(e)}var u=a(),l=!1,d=g(e);return R(function(){d.promiseDispatch(function(e){l||(l=!0,u.resolve(o(e)))},"when",[function(e){l||(l=!0,u.resolve(s(e)))}])}),d.promiseDispatch(void 0,"when",[void 0,function(e){u.notify(i?i(e):e)}]),u.promise}function p(e,t,n){return h(e,function(e){return M(e).then(function(e){return t.apply(void 0,e)},n)},n)}function m(e,t,n){var r=a();return R(function(){g(e).promiseDispatch(r.resolve,t,n)}),r.promise}function y(e){return function(t){var n=C(arguments,1);return m(t,e,n)}}function v(e){var t=C(arguments,1);return V(e,t)}function M(e){return h(e,function(e){var t=e.length;if(0===t)return g(e);var n=a();return A(e,function(r,i,o){d(i)?(e[o]=u(i),0===--t&&n.resolve(e)):h(i,function(r){e[o]=r,0===--t&&n.resolve(e)}).fail(n.reject)},void 0),n.promise})}function b(e,t){return h(e,void 0,t)}function E(e,t){var n=C(arguments,2),r=a();return n.push(r.makeNodeResolver()),H(e,t,n).fail(r.reject),r.promise}var S,w=i(),P=function(){},T=Object.freeze||P;"undefined"!=typeof cajaVM&&(T=cajaVM.def);var R;if("undefined"!=typeof process)R=process.nextTick;else if("function"==typeof setImmediate)R=setImmediate;else if("undefined"!=typeof MessageChannel){var _=new MessageChannel,L={},x=L;_.port1.onmessage=function(){L=L.next;var e=L.task;delete L.task,e()},R=function(e){x=x.next={task:e},_.port2.postMessage(0)}}else R=function(e){setTimeout(e,0)};var O;Function.prototype.bind?(O=Function.prototype.bind,O=O.bind(O.call)):O=function(e){return function(){return e.call.apply(e,arguments)}};var D,C=O(Array.prototype.slice),A=O(Array.prototype.reduce||function(e,t){var n=0,r=this.length;if(1===arguments.length)for(;;){if(n in this){t=this[n++];break}if(++n>=r)throw new TypeError}for(;r>n;n++)n in this&&(t=e(t,this[n],n));return t}),B=O(Array.prototype.indexOf||function(e){for(var t=0;t2?C(arguments,1):n)}},t.promise=function(e){var t=a();return v(e,t.resolve,t.reject,t.notify).fail(t.reject),t.promise},t.makePromise=s,s.prototype.then=function(e,t,n){return h(this,e,t,n)},s.prototype.thenResolve=function(e){return h(this,function(){return e})},A("isResolved isFulfilled isRejected dispatch when spread get put del post send invoke keys fapply fcall fbind all allResolved timeout delay catch finally fail fin progress end done nfcall nfapply nfbind ncall napply nbind npost nsend ninvoke nend nodeify".split(" "),function(e,n){s.prototype[n]=function(){return t[n].apply(t,[this].concat(C(arguments)))}},void 0),s.prototype.toSource=function(){return this.toString()},s.prototype.toString=function(){return"[object Promise]"},T(s.prototype),t.nearer=u,t.isPromise=l,t.isResolved=function(e){return d(e)||c(e)},t.isFulfilled=d,t.isRejected=c;var U,Q=[],j=[];t.reject=f,t.resolve=g,t.master=function(e){return s({isDef:function(){}},function(t,n){return m(e,t,n)},function(){return u(e)})},t.when=h,t.spread=p,t.async=function(e){return function(){function t(e,t){var o;try{o=n[e](t)}catch(a){return"[object StopIteration]"===k(a)||a instanceof D?a.value:f(a)}return h(o,r,i)}var n=e.apply(this,arguments),r=t.bind(t,"send"),i=t.bind(t,"throw");return r()}},t["return"]=function(e){throw new D(e)},t.promised=function(e){return function(){return p([this,M(arguments)],function(t,n){return e.apply(t,n)})}},t.dispatch=m,t.dispatcher=y,t.get=y("get"),t.put=y("put"),t["delete"]=t.del=y("del");var H=t.post=y("post");t.send=function(e,t){var n=C(arguments,2);return H(e,t,n)},t.invoke=o(t.send,"invoke","send");var V=t.fapply=y("apply");t["try"]=v,t.fcall=v,t.fbind=function(e){var t=C(arguments,1);return function(){var n=t.concat(C(arguments));return V(e,n)}},t.keys=y("keys"),t.all=M,t.allResolved=function(e){return h(e,function(e){return h(M(N(e,function(e){return h(e,P,P)})),function(){return N(e,g)})})},t["catch"]=t.fail=b,t.progress=function(e,t){return h(e,void 0,void 0,t)},t["finally"]=t.fin=function(e,t){return h(e,function(e){return h(t(),function(){return e})},function(e){return h(t(),function(){return f(e)})})},t.done=function(e,r,i,o){r=r||i||o?h(e,r,i,o):e,b(r,function(r){R(function(){if(n(r,e),!t.onerror)throw r;t.onerror(r)})})},t.timeout=function(e,t){var n=a(),r=setTimeout(function(){n.reject(Error("Timed out after "+t+" ms"))},t);return h(e,function(e){clearTimeout(r),n.resolve(e)},function(e){clearTimeout(r),n.reject(e)}),n.promise},t.delay=function(e,t){void 0===t&&(t=e,e=void 0);var n=a();return setTimeout(function(){n.resolve(e)},t),n.promise},t.nfapply=function(e,t){var n=C(t),r=a();return n.push(r.makeNodeResolver()),V(e,n).fail(r.reject),r.promise},t.nfcall=function(e){var t=C(arguments,1),n=a();return t.push(n.makeNodeResolver()),V(e,t).fail(n.reject),n.promise},t.nfbind=function(e){var t=C(arguments,1);return function(){var n=t.concat(C(arguments)),r=a();return n.push(r.makeNodeResolver()),V(e,n).fail(r.reject),r.promise}},t.npost=function(e,t,n){var n=C(n),r=a();return n.push(r.makeNodeResolver()),H(e,t,n).fail(r.reject),r.promise},t.nsend=E,t.ninvoke=o(E,"ninvoke","nsend"),t.nodeify=function(e,t){return t?void e.then(function(e){R(function(){t(null,e)})},function(e){R(function(){t(e)})}):e};var K=i()}),function(e){"use strict";var t={VERSION:"0.5.3"};t.System=function(){this._mappings={},this._outlets={},this._handlers={},this.strictInjections=!0,this.autoMapOutlets=!1,this.postInjectionHook="setup"},t.System.prototype={_createAndSetupInstance:function(e,t){var n=new t;return this.injectInto(n,e),n},_retrieveFromCacheOrCreate:function(e,t){"undefined"==typeof t&&(t=!1);var n;if(!this._mappings.hasOwnProperty(e))throw new Error(1e3);var r=this._mappings[e];return!t&&r.isSingleton?(null==r.object&&(r.object=this._createAndSetupInstance(e,r.clazz)),n=r.object):n=r.clazz?this._createAndSetupInstance(e,r.clazz):r.object,n},mapOutlet:function(e,t,n){if("undefined"==typeof e)throw new Error(1010);return t=t||"global",n=n||e,this._outlets.hasOwnProperty(t)||(this._outlets[t]={}),this._outlets[t][n]=e,this},getObject:function(e){if("undefined"==typeof e)throw new Error(1020);return this._retrieveFromCacheOrCreate(e)},mapValue:function(e,t){if("undefined"==typeof e)throw new Error(1030);return this._mappings[e]={clazz:null,object:t,isSingleton:!0},this.autoMapOutlets&&this.mapOutlet(e),this.hasMapping(e)&&this.injectInto(t,e),this},hasMapping:function(e){if("undefined"==typeof e)throw new Error(1040);return this._mappings.hasOwnProperty(e)},mapClass:function(e,t){if("undefined"==typeof e)throw new Error(1050);if("undefined"==typeof t)throw new Error(1051);return this._mappings[e]={clazz:t,object:null,isSingleton:!1},this.autoMapOutlets&&this.mapOutlet(e),this},mapSingleton:function(e,t){if("undefined"==typeof e)throw new Error(1060);if("undefined"==typeof t)throw new Error(1061);return this._mappings[e]={clazz:t,object:null,isSingleton:!0},this.autoMapOutlets&&this.mapOutlet(e),this},instantiate:function(e){if("undefined"==typeof e)throw new Error(1070);return this._retrieveFromCacheOrCreate(e,!0)},injectInto:function(e,t){if("undefined"==typeof e)throw new Error(1080);if("object"==typeof e){var n=[];this._outlets.hasOwnProperty("global")&&n.push(this._outlets.global),"undefined"!=typeof t&&this._outlets.hasOwnProperty(t)&&n.push(this._outlets[t]);for(var r in n){var i=n[r];for(var o in i){var a=i[o];(!this.strictInjections||o in e)&&(e[o]=this.getObject(a))}}"setup"in e&&e.setup.call(e)}return this},unmap:function(e){if("undefined"==typeof e)throw new Error(1090);return delete this._mappings[e],this},unmapOutlet:function(e,t){if("undefined"==typeof e)throw new Error(1100);if("undefined"==typeof t)throw new Error(1101);return delete this._outlets[e][t],this},mapHandler:function(e,t,n,r,i){if("undefined"==typeof e)throw new Error(1110);return t=t||"global",n=n||e,"undefined"==typeof r&&(r=!1),"undefined"==typeof i&&(i=!1),this._handlers.hasOwnProperty(e)||(this._handlers[e]={}),this._handlers[e].hasOwnProperty(t)||(this._handlers[e][t]=[]),this._handlers[e][t].push({handler:n,oneShot:r,passEvent:i}),this},unmapHandler:function(e,t,n){if("undefined"==typeof e)throw new Error(1120);if(t=t||"global",n=n||e,this._handlers.hasOwnProperty(e)&&this._handlers[e].hasOwnProperty(t)){var r=this._handlers[e][t];for(var i in r){var o=r[i];if(o.handler===n){r.splice(i,1);break}}}return this},notify:function(e){if("undefined"==typeof e)throw new Error(1130);var t=Array.prototype.slice.call(arguments),n=t.slice(1);if(this._handlers.hasOwnProperty(e)){var r=this._handlers[e];for(var i in r){var o,a=r[i];"global"!==i&&(o=this.getObject(i));var s,u,l=[];for(s=0,u=a.length;u>s;s++){var d,c=a[s];d=o&&"string"==typeof c.handler?o[c.handler]:c.handler,c.oneShot&&l.unshift(s),c.passEvent?d.apply(o,t):d.apply(o,n)}for(s=0,u=l.length;u>s;s++)a.splice(l[s],1)}}return this}},e.dijon=t}(this),"undefined"==typeof utils)var utils={};"undefined"==typeof utils.Math&&(utils.Math={}),utils.Math.to64BitNumber=function(e,t){var n,r,i;return n=new goog.math.Long(0,t),r=new goog.math.Long(e,0),i=n.add(r),i.toNumber()},goog={},goog.math={},goog.math.Long=function(e,t){this.low_=0|e,this.high_=0|t},goog.math.Long.IntCache_={},goog.math.Long.fromInt=function(e){if(e>=-128&&128>e){var t=goog.math.Long.IntCache_[e];if(t)return t}var n=new goog.math.Long(0|e,0>e?-1:0);return e>=-128&&128>e&&(goog.math.Long.IntCache_[e]=n),n},goog.math.Long.fromNumber=function(e){return isNaN(e)||!isFinite(e)?goog.math.Long.ZERO:e<=-goog.math.Long.TWO_PWR_63_DBL_?goog.math.Long.MIN_VALUE:e+1>=goog.math.Long.TWO_PWR_63_DBL_?goog.math.Long.MAX_VALUE:0>e?goog.math.Long.fromNumber(-e).negate():new goog.math.Long(0|e%goog.math.Long.TWO_PWR_32_DBL_,0|e/goog.math.Long.TWO_PWR_32_DBL_)},goog.math.Long.fromBits=function(e,t){return new goog.math.Long(e,t)},goog.math.Long.fromString=function(e,t){if(0==e.length)throw Error("number format error: empty string");var n=t||10;if(2>n||n>36)throw Error("radix out of range: "+n);if("-"==e.charAt(0))return goog.math.Long.fromString(e.substring(1),n).negate();if(e.indexOf("-")>=0)throw Error('number format error: interior "-" character: '+e);for(var r=goog.math.Long.fromNumber(Math.pow(n,8)),i=goog.math.Long.ZERO,o=0;oa){var u=goog.math.Long.fromNumber(Math.pow(n,a));i=i.multiply(u).add(goog.math.Long.fromNumber(s))}else i=i.multiply(r),i=i.add(goog.math.Long.fromNumber(s))}return i},goog.math.Long.TWO_PWR_16_DBL_=65536,goog.math.Long.TWO_PWR_24_DBL_=1<<24,goog.math.Long.TWO_PWR_32_DBL_=goog.math.Long.TWO_PWR_16_DBL_*goog.math.Long.TWO_PWR_16_DBL_,goog.math.Long.TWO_PWR_31_DBL_=goog.math.Long.TWO_PWR_32_DBL_/2,goog.math.Long.TWO_PWR_48_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_16_DBL_,goog.math.Long.TWO_PWR_64_DBL_=goog.math.Long.TWO_PWR_32_DBL_*goog.math.Long.TWO_PWR_32_DBL_,goog.math.Long.TWO_PWR_63_DBL_=goog.math.Long.TWO_PWR_64_DBL_/2,goog.math.Long.ZERO=goog.math.Long.fromInt(0),goog.math.Long.ONE=goog.math.Long.fromInt(1),goog.math.Long.NEG_ONE=goog.math.Long.fromInt(-1),goog.math.Long.MAX_VALUE=goog.math.Long.fromBits(-1,2147483647),goog.math.Long.MIN_VALUE=goog.math.Long.fromBits(0,-2147483648),goog.math.Long.TWO_PWR_24_=goog.math.Long.fromInt(1<<24),goog.math.Long.prototype.toInt=function(){return this.low_},goog.math.Long.prototype.toNumber=function(){return this.high_*goog.math.Long.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()},goog.math.Long.prototype.toString=function(e){var t=e||10;if(2>t||t>36)throw Error("radix out of range: "+t);if(this.isZero())return"0";if(this.isNegative()){if(this.equals(goog.math.Long.MIN_VALUE)){var n=goog.math.Long.fromNumber(t),r=this.div(n),i=r.multiply(n).subtract(this);return r.toString(t)+i.toInt().toString(t)}return"-"+this.negate().toString(t)}for(var o=goog.math.Long.fromNumber(Math.pow(t,6)),i=this,a="";;){var s=i.div(o),u=i.subtract(s.multiply(o)).toInt(),l=u.toString(t);if(i=s,i.isZero())return l+a;for(;l.length<6;)l="0"+l;a=""+l+a}},goog.math.Long.prototype.getHighBits=function(){return this.high_},goog.math.Long.prototype.getLowBits=function(){return this.low_},goog.math.Long.prototype.getLowBitsUnsigned=function(){return this.low_>=0?this.low_:goog.math.Long.TWO_PWR_32_DBL_+this.low_},goog.math.Long.prototype.getNumBitsAbs=function(){if(this.isNegative())return this.equals(goog.math.Long.MIN_VALUE)?64:this.negate().getNumBitsAbs();for(var e=0!=this.high_?this.high_:this.low_,t=31;t>0&&0==(e&1<0},goog.math.Long.prototype.greaterThanOrEqual=function(e){return this.compare(e)>=0},goog.math.Long.prototype.compare=function(e){if(this.equals(e))return 0;var t=this.isNegative(),n=e.isNegative();return t&&!n?-1:!t&&n?1:this.subtract(e).isNegative()?-1:1},goog.math.Long.prototype.negate=function(){return this.equals(goog.math.Long.MIN_VALUE)?goog.math.Long.MIN_VALUE:this.not().add(goog.math.Long.ONE)},goog.math.Long.prototype.add=function(e){var t=this.high_>>>16,n=65535&this.high_,r=this.low_>>>16,i=65535&this.low_,o=e.high_>>>16,a=65535&e.high_,s=e.low_>>>16,u=65535&e.low_,l=0,d=0,c=0,f=0;return f+=i+u,c+=f>>>16,f&=65535,c+=r+s,d+=c>>>16,c&=65535,d+=n+a,l+=d>>>16,d&=65535,l+=t+o,l&=65535,goog.math.Long.fromBits(c<<16|f,l<<16|d)},goog.math.Long.prototype.subtract=function(e){return this.add(e.negate())},goog.math.Long.prototype.multiply=function(e){if(this.isZero())return goog.math.Long.ZERO;if(e.isZero())return goog.math.Long.ZERO;if(this.equals(goog.math.Long.MIN_VALUE))return e.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO;if(e.equals(goog.math.Long.MIN_VALUE))return this.isOdd()?goog.math.Long.MIN_VALUE:goog.math.Long.ZERO;if(this.isNegative())return e.isNegative()?this.negate().multiply(e.negate()):this.negate().multiply(e).negate();if(e.isNegative())return this.multiply(e.negate()).negate();if(this.lessThan(goog.math.Long.TWO_PWR_24_)&&e.lessThan(goog.math.Long.TWO_PWR_24_))return goog.math.Long.fromNumber(this.toNumber()*e.toNumber());var t=this.high_>>>16,n=65535&this.high_,r=this.low_>>>16,i=65535&this.low_,o=e.high_>>>16,a=65535&e.high_,s=e.low_>>>16,u=65535&e.low_,l=0,d=0,c=0,f=0;return f+=i*u,c+=f>>>16,f&=65535,c+=r*u,d+=c>>>16,c&=65535,c+=i*s,d+=c>>>16,c&=65535,d+=n*u,l+=d>>>16,d&=65535,d+=r*s,l+=d>>>16,d&=65535,d+=i*a,l+=d>>>16,d&=65535,l+=t*u+n*s+r*a+i*o,l&=65535,goog.math.Long.fromBits(c<<16|f,l<<16|d)},goog.math.Long.prototype.div=function(e){if(e.isZero())throw Error("division by zero");if(this.isZero())return goog.math.Long.ZERO;if(this.equals(goog.math.Long.MIN_VALUE)){if(e.equals(goog.math.Long.ONE)||e.equals(goog.math.Long.NEG_ONE))return goog.math.Long.MIN_VALUE;if(e.equals(goog.math.Long.MIN_VALUE))return goog.math.Long.ONE;var t=this.shiftRight(1),n=t.div(e).shiftLeft(1);if(n.equals(goog.math.Long.ZERO))return e.isNegative()?goog.math.Long.ONE:goog.math.Long.NEG_ONE;var r=this.subtract(e.multiply(n)),i=n.add(r.div(e));return i}if(e.equals(goog.math.Long.MIN_VALUE))return goog.math.Long.ZERO;if(this.isNegative())return e.isNegative()?this.negate().div(e.negate()):this.negate().div(e).negate();if(e.isNegative())return this.div(e.negate()).negate();for(var o=goog.math.Long.ZERO,r=this;r.greaterThanOrEqual(e);){for(var n=Math.max(1,Math.floor(r.toNumber()/e.toNumber())),a=Math.ceil(Math.log(n)/Math.LN2),s=48>=a?1:Math.pow(2,a-48),u=goog.math.Long.fromNumber(n),l=u.multiply(e);l.isNegative()||l.greaterThan(r);)n-=s,u=goog.math.Long.fromNumber(n),l=u.multiply(e);u.isZero()&&(u=goog.math.Long.ONE),o=o.add(u),r=r.subtract(l)}return o},goog.math.Long.prototype.modulo=function(e){return this.subtract(this.div(e).multiply(e))},goog.math.Long.prototype.not=function(){return goog.math.Long.fromBits(~this.low_,~this.high_)},goog.math.Long.prototype.and=function(e){return goog.math.Long.fromBits(this.low_&e.low_,this.high_&e.high_)},goog.math.Long.prototype.or=function(e){return goog.math.Long.fromBits(this.low_|e.low_,this.high_|e.high_)},goog.math.Long.prototype.xor=function(e){return goog.math.Long.fromBits(this.low_^e.low_,this.high_^e.high_)},goog.math.Long.prototype.shiftLeft=function(e){if(e&=63,0==e)return this;var t=this.low_;if(32>e){var n=this.high_;return goog.math.Long.fromBits(t<>>32-e)}return goog.math.Long.fromBits(0,t<e){var n=this.low_;return goog.math.Long.fromBits(n>>>e|t<<32-e,t>>e)}return goog.math.Long.fromBits(t>>e-32,t>=0?0:-1)},goog.math.Long.prototype.shiftRightUnsigned=function(e){if(e&=63,0==e)return this;var t=this.high_;if(32>e){var n=this.low_;return goog.math.Long.fromBits(n>>>e|t<<32-e,t>>>e)}return 32==e?goog.math.Long.fromBits(t,0):goog.math.Long.fromBits(t>>>e-32,0)};var UTF8={};UTF8.encode=function(e){for(var t=[],n=0;nr?t.push(r):2048>r?(t.push(192|r>>6),t.push(128|63&r)):65536>r?(t.push(224|r>>12),t.push(128|63&r>>6),t.push(128|63&r)):(t.push(240|r>>18),t.push(128|63&r>>12),t.push(128|63&r>>6),t.push(128|63&r))}return t},UTF8.decode=function(e){for(var t=[],n=0;nr||(224>r?(r=(31&r)<<6,r|=63&e[n++]):240>r?(r=(15&r)<<12,r|=(63&e[n++])<<6,r|=63&e[n++]):(r=(7&r)<<18,r|=(63&e[n++])<<12,r|=(63&e[n++])<<6,r|=63&e[n++])),t.push(String.fromCharCode(r))}return t.join("")};var BASE64={};if(function(e){var t=function(t){for(var n=0,r=[],i=0|t.length/3;0>18)),r.push(e.charAt(63&o>>12)),r.push(e.charAt(63&o>>6)),r.push(e.charAt(63&o))}if(2==t.length-n){var o=(t[n]<<16)+(t[n+1]<<8);r.push(e.charAt(63&o>>18)),r.push(e.charAt(63&o>>12)),r.push(e.charAt(63&o>>6)),r.push("=")}else if(1==t.length-n){var o=t[n]<<16;r.push(e.charAt(63&o>>18)),r.push(e.charAt(63&o>>12)),r.push("==")}return r.join("")},n=function(){for(var t=[],n=0;n>16),r.push(255&o>>8),r.push(255&o),t+=4}return r&&("="==e.charAt(t-2)?(r.pop(),r.pop()):"="==e.charAt(t-1)&&r.pop()),r},i={};i.encode=function(e){for(var t=[],n=0;no;o+=1)c=f.getInt8(h),l+=String.fromCharCode(c),h+=1;"moof"!==l&&"traf"!==l&&"sidx"!==l?h+=d-8:"sidx"===l&&(h-=8)}if(i=f.getUint32(h,!1)+h,i>e.byteLength)throw"sidx terminates after array buffer";for(g.version=f.getUint8(h+8),h+=12,g.timescale=f.getUint32(h+4,!1),h+=8,0===g.version?(g.earliest_presentation_time=f.getUint32(h,!1),g.first_offset=f.getUint32(h+4,!1),h+=8):(g.earliest_presentation_time=utils.Math.to64BitNumber(f.getUint32(h+4,!1),f.getUint32(h,!1)),g.first_offset=(f.getUint32(h+8,!1)<<32)+f.getUint32(h+12,!1),h+=16),g.first_offset+=i+(t||0),g.reference_count=f.getUint16(h+2,!1),h+=4,g.references=[],n=g.first_offset,r=g.earliest_presentation_time,o=0;o>>31,s=2147483647&s,u=f.getUint32(h+4,!1),h+=12,g.references.push({size:s,type:a,offset:n,duration:u,time:r,timescale:g.timescale}),n+=s,r+=u;if(h!==i)throw"Error: final pos "+h+" differs from SIDX end "+i;return g},t=function(t,n,r){var i,o,a,s,u,l,d,c;for(i=e.call(this,t,r),o=i.references,a=[],u=0,l=o.length;l>u;u+=1)s=new Dash.vo.Segment,s.duration=o[u].duration,s.media=n,s.startTime=o[u].time,s.timescale=o[u].timescale,d=o[u].offset,c=o[u].offset+o[u].size-1,s.mediaRange=d+"-"+c,a.push(s);return this.debug.log("Parsed SIDX box: "+a.length+" segments."),Q.when(a)},n=function(e,t){var r,i,o,a,s,u,l,d=Q.defer(),c=new DataView(e),f=0,g="",h=0,p=!1,m=this;for(m.debug.log("Searching for initialization.");"moov"!==g&&fa;a+=1)s=c.getInt8(f),g+=String.fromCharCode(s),f+=1;"moov"!==g&&(f+=h-8)}return o=c.byteLength-f,"moov"!==g?(m.debug.log("Loading more bytes to find initialization."),t.range.start=0,t.range.end=t.bytesLoaded+t.bytesToLoad,u=new XMLHttpRequest,u.onloadend=function(){p||d.reject("Error loading initialization.")},u.onload=function(){p=!0,t.bytesLoaded=t.range.end,n.call(m,u.response).then(function(e){d.resolve(e)})},u.onerror=function(){d.reject("Error loading initialization.")},u.open("GET",t.url),u.responseType="arraybuffer",u.setRequestHeader("Range","bytes="+t.range.start+"-"+t.range.end),u.send(null)):(r=f-8,i=r+h-1,l=r+"-"+i,m.debug.log("Found the initialization. Range: "+l),d.resolve(l)),d.promise},r=function(e){var t=Q.defer(),r=new XMLHttpRequest,i=!0,o=this,a={url:e,range:{},searching:!1,bytesLoaded:0,bytesToLoad:1500,request:r};return o.debug.log("Start searching for initialization."),a.range.start=0,a.range.end=a.bytesToLoad,r.onload=function(){r.status<200||r.status>299||(i=!1,a.bytesLoaded=a.range.end,n.call(o,r.response,a).then(function(e){t.resolve(e)}))},r.onloadend=r.onerror=function(){i&&(i=!1,o.errHandler.downloadError("initialization",a.url,r),t.reject(r))},r.open("GET",a.url),r.responseType="arraybuffer",r.setRequestHeader("Range","bytes="+a.range.start+"-"+a.range.end),r.send(null),o.debug.log("Perform init search: "+a.url),t.promise},i=function(e,n){var r,o,a,s,u,l,d,c,f=Q.defer(),g=new DataView(e),h=new XMLHttpRequest,p=0,m="",y=0,v=!0,M=!1,b=this;for(b.debug.log("Searching for SIDX box."),b.debug.log(n.bytesLoaded+" bytes loaded.");"sidx"!==m&&pu;u+=1)l=g.getInt8(p),m+=String.fromCharCode(l),p+=1;"sidx"!==m&&(p+=y-8)}if(r=g.byteLength-p,"sidx"!==m)f.reject();else if(y-8>r)b.debug.log("Found SIDX but we don't have all of it."),n.range.start=0,n.range.end=n.bytesLoaded+(y-r),h.onload=function(){h.status<200||h.status>299||(v=!1,n.bytesLoaded=n.range.end,i.call(b,h.response,n).then(function(e){f.resolve(e)}))},h.onloadend=h.onerror=function(){v&&(v=!1,b.errHandler.downloadError("SIDX",n.url,h),f.reject(h))},h.open("GET",n.url),h.responseType="arraybuffer",h.setRequestHeader("Range","bytes="+n.range.start+"-"+n.range.end),h.send(null);else if(n.range.start=p-8,n.range.end=n.range.start+y,b.debug.log("Found the SIDX box. Start: "+n.range.start+" | End: "+n.range.end),o=new ArrayBuffer(n.range.end-n.range.start),s=new Uint8Array(o),a=new Uint8Array(e,n.range.start,n.range.end-n.range.start),s.set(a),d=this.parseSIDX.call(this,o,n.range.start),c=d.references,null!==c&&void 0!==c&&c.length>0&&(M=1===c[0].type),M){b.debug.log("Initiate multiple SIDX load.");var E,S,w,P,T,R,_=[];for(E=0,S=c.length;S>E;E+=1)w=c[E].offset,P=c[E].offset+c[E].size-1,T=w+"-"+P,_.push(this.loadSegments.call(b,n.url,T));Q.all(_).then(function(e){for(R=[],E=0,S=e.length;S>E;E+=1)R=R.concat(e[E]);f.resolve(R)},function(e){f.reject(e)})}else b.debug.log("Parsing segments from SIDX."),t.call(b,o,n.url,n.range.start).then(function(e){f.resolve(e)});return f.promise},o=function(e,n){var r,o=Q.defer(),a=new XMLHttpRequest,s=!0,u=this,l={url:e,range:{},searching:!1,bytesLoaded:0,bytesToLoad:1500,request:a};return null===n?(u.debug.log("No known range for SIDX request."),l.searching=!0,l.range.start=0,l.range.end=l.bytesToLoad):(r=n.split("-"),l.range.start=parseFloat(r[0]),l.range.end=parseFloat(r[1])),a.onload=function(){a.status<200||a.status>299||(s=!1,l.searching?(l.bytesLoaded=l.range.end,i.call(u,a.response,l).then(function(e){o.resolve(e)})):t.call(u,a.response,l.url,l.range.start).then(function(e){o.resolve(e)}))},a.onloadend=a.onerror=function(){s&&(s=!1,u.errHandler.downloadError("SIDX",l.url,a),o.reject(a))},a.open("GET",l.url),a.responseType="arraybuffer",a.setRequestHeader("Range","bytes="+l.range.start+"-"+l.range.end),a.send(null),u.debug.log("Perform SIDX load: "+l.url),o.promise};return{debug:void 0,errHandler:void 0,loadSegments:o,loadInitialization:r,parseSegments:t,parseSIDX:e,findSIDX:i}},Dash.dependencies.BaseURLExtensions.prototype={constructor:Dash.dependencies.BaseURLExtensions},Dash.dependencies.DashHandler=function(){"use strict";var e,t,n,r=-1,i=function(e,t){var n=null;return t&&t.Representation_asArray&&t.Representation_asArray.length>0&&(n=t.Representation_asArray[e]),n},o=function(e,t){var n=t.toString();return e.split("$Number$").join(n)},a=function(e,t){var n=t.toString();return e.split("$Time$").join(n)},s=function(e,t){var n=t.toString();return e.split("$Bandwidth$").join(n)},u=function(e,t){if(null===t||-1===e.indexOf("$RepresentationID$"))return e;var n=t.toString();return e.split("$RepresentationID$").join(n)},l=function(e,t){var n;return n=e===t?e:-1!==e.indexOf("http://")?e:t+e},d=function(e,t){var r=Q.defer(),o=i(e,t),a=null,d=null,c=null,f=null,g=this;return o?(g.debug.log("Getting the initialization request."),o.hasOwnProperty("SegmentTemplate")?o.SegmentTemplate.hasOwnProperty("initialization")&&(d=o.SegmentTemplate.initialization,d=s(d,o.bandwidth),d=u(d,o.id)):o.hasOwnProperty("SegmentList")&&o.SegmentList.hasOwnProperty("Initialization")&&o.SegmentList.Initialization.hasOwnProperty("range")?(d=o.SegmentList.Initialization.hasOwnProperty("sourceURL")?o.SegmentList.Initialization.sourceURL:o.BaseURL,f=o.SegmentList.Initialization.range):o.hasOwnProperty("SegmentList")&&o.SegmentList.hasOwnProperty("Initialization")&&o.SegmentList.Initialization.hasOwnProperty("sourceURL")?d=o.SegmentList.Initialization.sourceURL:o.hasOwnProperty("SegmentBase")&&o.SegmentBase.hasOwnProperty("Initialization")&&o.SegmentBase.Initialization.hasOwnProperty("range")?(d=o.BaseURL,f=o.SegmentBase.Initialization.range):o.hasOwnProperty("mimeType")&&g.manifestExt.getIsTextTrack(o.mimeType)?(d=o.BaseURL,f=0):(c=o.BaseURL,g.baseURLExt.loadInitialization(c).then(function(t){g.debug.log("Got an initialization."),a=new MediaPlayer.vo.SegmentRequest,a.streamType=n,a.type="Initialization Segment",a.url=l(c,o.BaseURL),a.range=t,a.quality=e,r.resolve(a)},function(e){r.reject(e)})),d&&d.length>0&&(g.debug.log("Got an initialization."),a=new MediaPlayer.vo.SegmentRequest,a.streamType=n,a.type="Initialization Segment",a.url=l(d,o.BaseURL),a.range=f,a.quality=e,r.resolve(a)),r.promise):Q.reject("no represenation")},c=function(n){var i,o,a,s,u,l,d=!1;return this.debug.log("Checking for stream end..."),e?(this.debug.log("Live never ends! (TODO)"),d=!1):n.hasOwnProperty("segments")&&null!==n.segments?(this.debug.log("Segments: "+r+" / "+n.segments.length),d=r>=n.segments.length):n.hasOwnProperty("SegmentTemplate")&&!n.SegmentTemplate.hasOwnProperty("SegmentTimeline")&&(o=1,u=1,s=t,n.SegmentTemplate.hasOwnProperty("duration")&&(i=n.SegmentTemplate.duration,n.SegmentTemplate.hasOwnProperty("timescale")&&(o=n.SegmentTemplate.timescale),n.SegmentTemplate.hasOwnProperty("startNumber")&&(u=n.SegmentTemplate.startNumber),a=i/o,l=r-u,this.debug.log("SegmentTemplate: "+a+" * "+l+" = "+a*l+" / "+s),d=a*l>=s)),Q.when(d)},f=function(e,n){var r,i,s,u,l,d,c,f,g=[],h=0,p=1,m=1;for(e.hasOwnProperty("startNumber")&&(p=e.startNumber),e.hasOwnProperty("timescale")&&(m=e.timescale),r=n.S_asArray,s=0,u=r.length;u>s;s+=1)for(i=r[s],d=0,i.hasOwnProperty("r")&&(d=i.r),0>d&&(d=(t-h/m)/(i.d/m)-1),l=0;d>=l;l+=1)c=new Dash.vo.Segment,c.timescale=m,0===l&&i.hasOwnProperty("t")?(c.startTime=i.t,h=i.t):c.startTime=h,c.duration=i.d,f=e.media,f=o(f,p),f=a(f,c.startTime),c.media=f,g.push(c),h+=c.duration,p+=1;return Q.when(g)},g=function(e){var t,n,r,i,o,a=[],s=1;for(e.hasOwnProperty("startNumber")&&(s=Math.max(e.startNumber,1)),o=(s-1)*e.duration,t=0,n=e.SegmentURL_asArray.length;n>t;t+=1)i=e.SegmentURL_asArray[t],r=new Dash.vo.Segment,r.media=i.media,r.mediaRange=i.mediaRange,r.index=i.index,r.indexRange=i.indexRange,r.timescale=e.timescale,r.duration=e.duration,r.startTime=o+t*e.duration,a.push(r);return Q.when(a)},h=function(e){var t=e.BaseURL,n=null;return e.hasOwnProperty("SegmentBase")&&e.SegmentBase.hasOwnProperty("indexRange")&&(n=e.SegmentBase.indexRange),this.baseURLExt.loadSegments(t,n)},p=function(e){var t;return t=e.hasOwnProperty("SegmentTemplate")&&!e.SegmentTemplate.hasOwnProperty("SegmentTimeline")?Q.when(null):e.hasOwnProperty("segments")&&null!==e.segments?Q.when(e.segments):e.hasOwnProperty("SegmentTemplate")&&e.SegmentTemplate.hasOwnProperty("SegmentTimeline")?f.call(this,e.SegmentTemplate,e.SegmentTemplate.SegmentTimeline):e.hasOwnProperty("SegmentList")?g.call(this,e.SegmentList):h.call(this,e)},m=function(e,t){var n,r,i,o,a=-1;if(t&&t.length>0)for(o=t.length-1;o>=0;o--){if(n=t[o],r=n.startTime/n.timescale,i=n.duration/n.timescale,e+Dash.dependencies.DashHandler.EPSILON>=r&&e-Dash.dependencies.DashHandler.EPSILON<=r+i){a=o;break}-1===a&&e-Dash.dependencies.DashHandler.EPSILON>r+i&&(a=o+1)}return-1===a&&(console.log("Couldn't figure out a time!"),console.log("Time: "+e),console.log(t)),Q.when(a)},y=function(e,t){var n,r,i=-1,o=1,a=1;if(!t.hasOwnProperty("duration"))throw"Expected 'duration' attribute on SegmentTemplate!";return n=t.duration,t.hasOwnProperty("timescale")&&(o=t.timescale),t.hasOwnProperty("startNumber")&&(a=t.startNumber),r=n/o,i=Math.floor(e/r),i+=a,Q.when(i)},v=function(e,t,r,i){var d,c,f=new MediaPlayer.vo.SegmentRequest,g=1,h=1;return t.hasOwnProperty("timescale")&&(g=t.timescale),t.hasOwnProperty("startNumber")&&(h=t.startNumber),c=t.duration*e/g,c=Math.floor(c),d=t.media,d=o(d,e),d=a(d,c),d=s(d,r.bandwidth),d=u(d,r.id),f.streamType=n,f.type="Media Segment",f.url=l(d,r.BaseURL),f.duration=t.duration/g,f.timescale=g,f.startTime=(e-h)*t.duration/g,f.quality=i,f.index=e,Q.when(f)},M=function(e,t,r,i){if(null===t||void 0===t)return Q.when(null);var d,c=new MediaPlayer.vo.SegmentRequest;return d=l(t.media,r.BaseURL),d=o(d,e),d=a(d,t.startTime),d=s(d,r.bandwidth),d=u(d,r.id),c.streamType=n,c.type="Media Segment",c.url=d,c.range=t.mediaRange,c.startTime=t.startTime/t.timescale,c.duration=t.duration/t.timescale,c.timescale=t.timescale,c.quality=i,c.index=e,Q.when(c)},b=function(e,t,n){var o,a,s,u=i(t,n),l=!1,d=this;return u?(d.debug.log("Getting the request for time: "+e),o=Q.defer(),p.call(d,u).then(function(t){var n;if(d.debug.log("Got segments."),d.debug.log(t),null===t){if(!u.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";l=!0,d.debug.log("No segments found, so we must be using a SegmentTemplate."),n=y.call(d,e,u.SegmentTemplate)}else d.debug.log("Got a list of segments, so dig deeper."),u.segments=t,l=!1,n=m.call(d,e,t);return n},function(){o.reject()}).then(function(t){return d.debug.log("Index for time "+e+" is "+t),r=t,c.call(d,u)}).then(function(e){var n=null;return d.debug.log("Stream finished? "+e),e?(a=new MediaPlayer.vo.SegmentRequest,a.action=a.ACTION_COMPLETE,a.index=r,d.debug.log("Signal complete."),d.debug.log(a),o.resolve(a)):l?n=v.call(d,r,u.SegmentTemplate,u,t):(s=u.segments[r],n=M.call(d,r,s,u,t)),n}).then(function(e){d.debug.log("Got a request."),d.debug.log(e),o.resolve(e)}),o.promise):Q.reject("no represenation")},E=function(e,t){var n,o,a,s=i(e,t),u=this;if(!s)return Q.reject("no represenation");if(u.debug.log("Getting the next request."),-1===r)throw"You must call getSegmentRequestForTime first.";return r+=1,u.debug.log("New index: "+r),n=Q.defer(),c.call(u,s).then(function(t){u.debug.log("Stream finished? "+t),t?(o=new MediaPlayer.vo.SegmentRequest,o.action=o.ACTION_COMPLETE,o.index=r,u.debug.log("Signal complete."),u.debug.log(o),n.resolve(o)):p.call(u,s).then(function(t){var n;if(u.debug.log("Got segments."),u.debug.log(t),null===t){if(!s.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";u.debug.log("No segments found, so we must be using a SegmentTemplate."),n=v.call(u,r,s.SegmentTemplate,s,e)}else s.segments=t,a=s.segments[r],n=M.call(u,r,a,s,e);return n},function(){n.reject()}).then(function(e){u.debug.log("Got a request."),u.debug.log(e),n.resolve(e)})}),n.promise},S=function(e,t,n,r){var o,a,s,u=this,l=i(e,t),d=Math.max(n-r,0),c=Q.defer(),f=0,g=1;return l?(p.call(u,l).then(function(e){if(null===e||void 0===e){if(!l.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";l.SegmentTemplate.hasOwnProperty("timescale")&&(g=l.SegmentTemplate.timescale),s=l.SegmentTemplate.duration,o=s/g}else a=e[0],a.hasOwnProperty("timescale")&&(g=a.timescale),s=a.duration,o=s/g;f=Math.ceil(d/o),c.resolve(f)},function(){c.resolve(0)}),c.promise):Q.reject("no represenation")},w=function(t,n){var o,a,s,u,l=this,d=i(t,n),c=!1,f=1,g=1,h=Q.defer();return d?(a=r,0>a&&(c=e,a=0),p.call(l,d).then(function(e){if(null===e||void 0===e){if(!d.hasOwnProperty("SegmentTemplate"))throw"Expected SegmentTemplate!";u=d.SegmentTemplate.duration,d.SegmentTemplate.hasOwnProperty("timescale")&&(f=d.SegmentTemplate.timescale),d.SegmentTemplate.hasOwnProperty("startNumber")&&(g=d.SegmentTemplate.startNumber),o=u/f*Math.max(a-g,0)}else(c||a>=e.length)&&(a=e.length-1),s=e[a].startTime,u=e[a].duration,e[a].hasOwnProperty("timescale")&&(f=e[a].timescale),o=s/f;h.resolve(o)},function(){h.reject()}),h.promise):Q.reject("no represenation")};return{debug:void 0,baseURLExt:void 0,manifestModel:void 0,manifestExt:void 0,errHandler:void 0,getType:function(){return n},setType:function(e){n=e},getIsLive:function(){return e},setIsLive:function(t){e=t},getDuration:function(){return t},setDuration:function(e){t=e},getInitRequest:d,getSegmentRequestForTime:b,getNextSegmentRequest:E,getCurrentTime:w,getSegmentCountForDuration:S}},Dash.dependencies.DashHandler.EPSILON=.003,Dash.dependencies.DashHandler.prototype={constructor:Dash.dependencies.DashHandler},Dash.dependencies.DashManifestExtensions=function(){"use strict"},Dash.dependencies.DashManifestExtensions.prototype={constructor:Dash.dependencies.DashManifestExtensions,getIsAudio:function(e){"use strict";var t,n,r,i=e.ContentComponent_asArray,o=!1,a=!1;if(i)for(t=0,n=i.length;n>t;t+=1)"audio"===i[t].contentType&&(o=!0,a=!0);if(e.hasOwnProperty("mimeType")&&(o=-1!==e.mimeType.indexOf("audio"),a=!0),!a)for(t=0,n=e.Representation_asArray.length;!a&&n>t;)r=e.Representation_asArray[t],r.hasOwnProperty("mimeType")&&(o=-1!==r.mimeType.indexOf("audio"),a=!0),t+=1;return o&&(e.type="audio"),Q.when(o)},getIsVideo:function(e){"use strict";var t,n,r,i=e.ContentComponent_asArray,o=!1,a=!1;if(i)for(t=0,n=i.length;n>t;t+=1)"video"===i[t].contentType&&(o=!0,a=!0);if(e.hasOwnProperty("mimeType")&&(o=-1!==e.mimeType.indexOf("video"),a=!0),!a)for(t=0,n=e.Representation_asArray.length;!a&&n>t;)r=e.Representation_asArray[t],r.hasOwnProperty("mimeType")&&(o=-1!==r.mimeType.indexOf("video"),a=!0),t+=1;return o&&(e.type="video"),Q.when(o)},getIsText:function(e){"use strict";var t,n,r,i=e.ContentComponent_asArray,o=!1,a=!1;if(i)for(t=0,n=i.length;n>t;t+=1)"text"===i[t].contentType&&(o=!0,a=!0);if(e.hasOwnProperty("mimeType")&&(o=-1!==e.mimeType.indexOf("text"),a=!0),!a)for(t=0,n=e.Representation_asArray.length;!a&&n>t;)r=e.Representation_asArray[t],r.hasOwnProperty("mimeType")&&(o=-1!==r.mimeType.indexOf("text"),a=!0),t+=1;return Q.when(o)},getIsTextTrack:function(e){return"text/vtt"===e||"application/ttml+xml"===e},getIsMain:function(){"use strict";return Q.when(!1)},processAdaptation:function(e){"use strict";return void 0!==e.Representation_asArray&&null!==e.Representation_asArray&&e.Representation_asArray.sort(function(e,t){return e.bandwidth-t.bandwidth}),e},getDataForId:function(e,t,n){"use strict";var r,i,o=t.Period_asArray[n].AdaptationSet_asArray;for(r=0,i=o.length;i>r;r+=1)if(o[r].hasOwnProperty("id")&&o[r].id===e)return Q.when(o[r]);return Q.when(null)},getDataForIndex:function(e,t,n){"use strict";var r=t.Period_asArray[n].AdaptationSet_asArray;return Q.when(r[e])},getDataIndex:function(e,t,n){"use strict";var r,i,o=t.Period_asArray[n].AdaptationSet_asArray;for(r=0,i=o.length;i>r;r+=1)if(o[r]===e)return Q.when(r);return Q.when(-1)},getVideoData:function(e,t){"use strict";var n,r,i=this,o=e.Period_asArray[t].AdaptationSet_asArray,a=Q.defer(),s=[];for(n=0,r=o.length;r>n;n+=1)s.push(this.getIsVideo(o[n]));return Q.all(s).then(function(e){var t=!1;for(n=0,r=e.length;r>n;n+=1)e[n]===!0&&(t=!0,a.resolve(i.processAdaptation(o[n])));t||a.resolve(null)}),a.promise},getTextData:function(e,t){"use strict";var n,r,i=this,o=e.Period_asArray[t].AdaptationSet_asArray,a=Q.defer(),s=[];for(n=0,r=o.length;r>n;n+=1)s.push(this.getIsText(o[n]));return Q.all(s).then(function(e){var t=!1;for(n=0,r=e.length;r>n;n+=1)e[n]===!0&&(t=!0,a.resolve(i.processAdaptation(o[n])));t||a.resolve(null)}),a.promise},getAudioDatas:function(e,t){"use strict";var n,r,i=this,o=e.Period_asArray[t].AdaptationSet_asArray,a=Q.defer(),s=[];for(n=0,r=o.length;r>n;n+=1)s.push(this.getIsAudio(o[n]));return Q.all(s).then(function(e){var t=[];for(n=0,r=e.length;r>n;n+=1)e[n]===!0&&t.push(i.processAdaptation(o[n]));a.resolve(t)}),a.promise},getPrimaryAudioData:function(e,t){"use strict";var n,r,i=Q.defer(),o=[],a=this;return this.getAudioDatas(e,t).then(function(e){for(e&&0!==e.length||i.resolve(null),n=0,r=e.length;r>n;n+=1)o.push(a.getIsMain(e[n]));Q.all(o).then(function(t){var o=!1;for(n=0,r=t.length;r>n;n+=1)t[n]===!0&&(o=!0,i.resolve(a.processAdaptation(e[n])));o||i.resolve(e[0])})}),i.promise},getCodec:function(e){"use strict";var t=e.Representation_asArray[0],n=t.mimeType+';codecs="'+t.codecs+'"';return Q.when(n)},getMimeType:function(e){"use strict";return Q.when(e.Representation_asArray[0].mimeType)},getKID:function(e){"use strict";return e&&e.hasOwnProperty("cenc:default_KID")?e["cenc:default_KID"]:null},getContentProtectionData:function(e){"use strict";return Q.when(e&&e.hasOwnProperty("ContentProtection_asArray")&&0!==e.ContentProtection_asArray.length?e.ContentProtection_asArray:null)},getSegmentInfoFor:function(e){return e.hasOwnProperty("SegmentBase")?e.SegmentBase:e.hasOwnProperty("SegmentList")?e.SegmentList:e.hasOwnProperty("SegmentTemplate")?e.SegmentTemplate:null},getLiveOffset:function(e){"use strict";var t=15;return e.hasOwnProperty("suggestedPresentationDelay")&&(t=e.suggestedPresentationDelay),Q.when(t)},getLiveStart:function(e,t){var n,r,i=0,o=1,a=1,s=null,u=null;return r=e.Period_asArray[t].AdaptationSet_asArray[1].Representation_asArray[0],r.hasOwnProperty("SegmentList")?(s=r.SegmentList,s.hasOwnProperty("startNumber")&&(o=Math.max(s.startNumber,1)),s.hasOwnProperty("timescale")&&(a=s.timescale),n=s.duration,i=(o-1)*n/a):r.hasOwnProperty("SegmentTemplate")&&(u=r.SegmentTemplate,u.hasOwnProperty("startNumber")&&(o=Math.max(u.startNumber,1)),u.hasOwnProperty("timescale")&&(a=u.timescale),n=u.duration,i=u.hasOwnProperty("SegmentTimeline")?u.SegmentTimeline.S_asArray[0].t/a:(o-1)*n/a),Q.when(i)},getLiveEdge:function(e,t){"use strict";var n,r=this,i=Q.defer(),o=0,a=new Date,s=e.availabilityStartTime;return r.getLiveOffset(e).then(function(u){e.hasOwnProperty("availabilityEndTime")?(n=e.availabilityEndTime,o=(n.getTime()-s.getTime())/1e3):o=(a.getTime()-s.getTime())/1e3,r.getLiveStart(e,t).then(function(e){o+=e,o-=u,i.resolve(o)})}),i.promise},getPresentationOffset:function(e,t){var n,r,i=this,o=Q.defer(),a=0,s=1;return i.getRepresentationFor(e,t).then(function(e){r=i.getSegmentInfoFor(e),null!==r&&void 0!==r&&r.hasOwnProperty("presentationTimeOffset")&&(n=r.presentationTimeOffset,r.hasOwnProperty("timescale")&&(s=r.timescale),a=n/s),o.resolve(a)}),o.promise},getIsLive:function(e){"use strict";var t=!1,n="dynamic";return e.hasOwnProperty("type")&&(t=e.type===n),t},getIsDVR:function(e,t){"use strict";var n,r;return n=!isNaN(e.timeShiftBufferDepth),r=t&&n,Q.when(r)},getIsOnDemand:function(e){"use strict";var t=!1;return e.profiles&&e.profiles.length>0&&(t=-1!==e.profiles.indexOf("urn:mpeg:dash:profile:isoff-on-demand:2011")),Q.when(t)},getDuration:function(e,t){"use strict";var n=0/0;return t?n=Number.POSITIVE_INFINITY:e.mediaPresentationDuration?n=e.mediaPresentationDuration:e.availabilityEndTime&&e.availabilityStartTime&&(n=e.availabilityEndTime.getTime()-e.availabilityStartTime.getTime()),Q.when(n)},getDurationForPeriod:function(e,t,n){"use strict";var r=0/0;return n?r=Number.POSITIVE_INFINITY:t.Period_asArray.length>1&&void 0!==t.Period_asArray[e].duration?r=t.Period_asArray[e].duration:t.mediaPresentationDuration?r=t.mediaPresentationDuration:t.availabilityEndTime&&t.availabilityStartTime&&(r=t.availabilityEndTime.getTime()-t.availabilityStartTime.getTime()),Q.when(r)},getBandwidth:function(e){"use strict";return Q.when(e.bandwidth)},getRefreshDelay:function(e){"use strict";var t=0/0;return e.hasOwnProperty("minimumUpdatePeriod")&&(t=parseFloat(e.minimumUpdatePeriod)),Q.when(t)},getRepresentationCount:function(e){"use strict";return Q.when(e.Representation_asArray.length)},getRepresentationFor:function(e,t){"use strict";return Q.when(t.Representation_asArray[e])},getPeriodCount:function(e){"use strict";return Q.when(e.Period_asArray.length)},getTimestampOffsetForPeriod:function(e,t,n,r){var i,o=this,a=Q.defer();return o.getPresentationOffset(n,r).then(function(n){o.getPeriodStart(t,e).then(function(e){i=e-n,a.resolve(i)})}),a.promise},getPeriodStart:function(e,t){var n,r,i=this,o=i.getIsLive(e),a=null,s=null,u=null;for(n=0;t>=n;n+=1)a=e.Period_asArray[n],a.hasOwnProperty("start")?r=a.start:null!==s&&null!==u?r=s+u:0!==n||o||(r=0),a.hasOwnProperty("duration")&&(u=a.duration),s=r;return Q.when(r)}},Dash.dependencies.DashMetricsExtensions=function(){"use strict";var e=function(e,t){var n,r,i,o,a,s,u,l;for(s=0;so;o+=1)a=u.getInt8(l),i+=String.fromCharCode(a),l+=1;"moof"!==i&&"traf"!==i&&"tfdt"!==i&&(l+=r-8)}if(l===u.byteLength)throw"Error finding live offset.";return n=u.getUint8(l),this.debug.log("position: "+l),0===n?(l+=4,t=u.getUint32(l,!1)):(l+=r-16,t=utils.Math.to64BitNumber(u.getUint32(l+4,!1),u.getUint32(l,!1))),s.resolve({version:n,base_media_decode_time:t}),s.promise},t=function(e){for(var t,n,r,i,o,a,s,u=new DataView(e),l=0;"sidx"!==o&&li;i+=1)s=u.getInt8(l),o+=String.fromCharCode(s),l+=1;"moof"!==o&&"traf"!==o&&"sidx"!==o?l+=a-8:"sidx"===o&&(l-=8)}return t=u.getUint8(l+8),l+=12,n=u.getUint32(l+4,!1),l+=8,r=0===t?u.getUint32(l,!1):utils.Math.to64BitNumber(u.getUint32(l+4,!1),u.getUint32(l,!1)),Q.when({earliestPresentationTime:r,timescale:n})},n=function(t){var n,r,i,o=Q.defer(),a=new XMLHttpRequest,s=!1;return n=t,a.onloadend=function(){s||(r="Error loading fragment: "+n,o.reject(r))},a.onload=function(){s=!0,i=e(a.response),o.resolve(i)},a.onerror=function(){r="Error loading fragment: "+n,o.reject(r)},a.responseType="arraybuffer",a.open("GET",n),a.send(null),o.promise};return{debug:void 0,loadFragment:n,parseTFDT:e,parseSIDX:t}},Dash.dependencies.FragmentExtensions.prototype={constructor:Dash.dependencies.FragmentExtensions},Dash.vo.Segment=function(){"use strict";this.indexRange=null,this.index=null,this.mediaRange=null,this.media=null,this.duration=0/0,this.startTime=0/0,this.timescale=0/0},Dash.vo.Segment.prototype={constructor:Dash.vo.Segment},MediaPlayer.dependencies.AbrController=function(){"use strict";var e=!0,t={},n={},r=function(e){ +var n;return t.hasOwnProperty(e)||(t[e]=0),n=t[e]},i=function(e,n){t[e]=n},o=function(e){var t;return n.hasOwnProperty(e)||(n[e]=0),t=n[e]},a=function(e,t){n[e]=t};return{debug:void 0,abrRulesCollection:void 0,manifestExt:void 0,metricsModel:void 0,getAutoSwitchBitrate:function(){return e},setAutoSwitchBitrate:function(t){e=t},getMetricsFor:function(e){var t=Q.defer(),n=this;return n.manifestExt.getIsVideo(e).then(function(r){r?t.resolve(n.metricsModel.getMetricsFor("video")):n.manifestExt.getIsAudio(e).then(function(e){t.resolve(e?n.metricsModel.getMetricsFor("audio"):n.metricsModel.getMetricsFor("stream"))})}),t.promise},getPlaybackQuality:function(t,n){var s,u,l,d,c,f,g=this,h=Q.defer(),p=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,m=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,y=[];return c=r(t),f=o(t),g.debug.log("ABR enabled? ("+e+")"),e?(g.debug.log("Check ABR rules."),g.getMetricsFor(n).then(function(e){g.abrRulesCollection.getRules().then(function(r){for(s=0,u=r.length;u>s;s+=1)y.push(r[s].checkIndex(c,e,n));Q.all(y).then(function(e){for(g.debug.log(e),d={},d[MediaPlayer.rules.SwitchRequest.prototype.STRONG]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,d[MediaPlayer.rules.SwitchRequest.prototype.WEAK]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,d[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]=MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,s=0,u=e.length;u>s;s+=1)l=e[s],l.quality!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(d[l.priority]=Math.min(d[l.priority],l.quality));d[MediaPlayer.rules.SwitchRequest.prototype.WEAK]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(m=MediaPlayer.rules.SwitchRequest.prototype.WEAK,p=d[MediaPlayer.rules.SwitchRequest.prototype.WEAK]),d[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(m=MediaPlayer.rules.SwitchRequest.prototype.DEFAULT,p=d[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT]),d[MediaPlayer.rules.SwitchRequest.prototype.STRONG]!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&(m=MediaPlayer.rules.SwitchRequest.prototype.STRONG,p=d[MediaPlayer.rules.SwitchRequest.prototype.STRONG]),p!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&void 0!==p&&(c=p),m!==MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE&&void 0!==m&&(f=m),g.manifestExt.getRepresentationCount(n).then(function(e){0>c&&(c=0),c>=e&&(c=e-1),f!=MediaPlayer.rules.SwitchRequest.prototype.STRONG&&f!=MediaPlayer.rules.SwitchRequest.prototype.WEAK&&(f=MediaPlayer.rules.SwitchRequest.prototype.DEFAULT),i(t,c),g.debug.log("New quality of "+c),a(t,f),g.debug.log("New confidence of "+f),h.resolve({quality:c,confidence:f})})})})})):(g.debug.log("Unchanged quality of "+c),h.resolve({quality:c,confidence:f})),h.promise},setPlaybackQuality:function(e,t){var n=r(e);t!==n&&i(e,t)},getQualityFor:function(e){return r(e)}}},MediaPlayer.dependencies.AbrController.prototype={constructor:MediaPlayer.dependencies.AbrController},MediaPlayer.dependencies.BufferController=function(){"use strict";var e,t,n,r,i=.5,o=22,a="WAITING",s="READY",u="VALIDATING",l="LOADING",d=a,c=!1,f=!1,g=!1,h=!0,p=[],m=!1,y=-1,v=!0,M=-1,b=!1,E=!1,S=!1,w=!1,P=[],T=null,R=Q.defer(),_=null,L=null,x=-1,O=0,D=0,C=null,A=0,B=!1,N=null,I=0,q=!1,k=null,F=null,U=null,j=null,H=!0,V=function(e){var t=this;t.debug.log("BufferController "+n+" setState to:"+e),d=e,null!==C&&t.fragmentController.onBufferControllerStateChange()},K=function(e,t){var n=0,r=null;H===!1&&(r=j.start,n=e.getTime()-r.getTime(),j.duration=n,j.stopreason=t,H=!0)},W=function(){var e=this.manifestModel.getValue(),t=this.manifestExt.getIsLive(e);return S=!0,Q.when(t)},G=function(){if(c&&f){var e=this;W.call(this).then(function(t){E=t,e.debug.log("BufferController begin "+n+" validation"),V.call(e,s),e.requestScheduler.startScheduling(e,ye),C=e.fragmentController.attachBufferController(e)})}},z=function(){var e;this.requestScheduler.isScheduled(this)||(m===!1&&(e=new Date,K(e,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON),U=this.metricsModel.addPlayList(n,e,0,MediaPlayer.vo.metrics.PlayList.INITIAL_PLAY_START_REASON)),this.debug.log("BufferController "+n+" start."),f=!0,g=!0,G.call(this))},X=function(e){var t;this.debug.log("BufferController "+n+" seek: "+e),m=!0,y=e,t=new Date,K(t,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON),U=this.metricsModel.addPlayList(n,t,y,MediaPlayer.vo.metrics.PlayList.SEEK_START_REASON),z.call(this)},Z=function(){d!==a&&(this.debug.log("BufferController "+n+" stop."),V.call(this,a),this.requestScheduler.stopScheduling(this),this.fragmentController.cancelPendingRequestsForModel(C),f=!1,g=!1,K(new Date,MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON))},Y=function(e,t){var n=null;return t&&t.Representation_asArray&&t.Representation_asArray.length>0&&(n=t.Representation_asArray[e]),n},$=function(){var e=this;d===l&&(b&&(b=!1,this.videoModel.stallStream(n,b)),V.call(e,s))},J=function(e){if(this.fragmentController.isInitializationRequest(e))V.call(this,s);else{V.call(this,l);var t=this,n=t.fragmentController.getLoadingTime(t);setTimeout(function(){(k||F)&&(V.call(t,s),me.call(t))},n)}},ee=function(e,t){this.fragmentController.isInitializationRequest(e)?se.call(this,e,t):te.call(this,e,t)},te=function(e,t){var r=this;r.debug.log(n+" Bytes finished loading: "+e.url),I||isNaN(e.duration)||(I=e.duration),r.fragmentController.process(t.data).then(function(t){null!==t&&null!==T?Q.when(T.promise).then(function(){ne.call(r,t,e.quality).then(function(){R.promise.then(function(t){t.index-1!==e.index||w||(w=!0,b&&(b=!1,r.videoModel.stallStream(n,b)),V.call(r,s),r.system.notify("bufferingCompleted"))})})}):r.debug.log("No "+n+" bytes to push.")})},ne=function(e,t){var r=this,i=e==N,s=i?_:Q.defer(),u=i?P.length:P.push(s),l=Y(M,r.getData()),c=r.videoModel.getCurrentTime(),f=new Date;return r.debug.log("Push ("+n+") bytes: "+e.byteLength),H===!0&&d!==a&&-1!==M&&(H=!1,j=r.metricsModel.appendPlayListTrace(U,l.id,null,f,c,null,1,null)),Q.when(i||2>u||P[u-2].promise).then(function(){F&&oe.call(r).then(function(){return t!==M?(s.resolve(),void(i&&(_=null,N=null))):void Q.when(L?L.promise:!0).then(function(){r.sourceBufferExt.append(F,e,r.videoModel).then(function(){i&&(_=null,N=null),r.requestScheduler.isScheduled(r)||z.call(r),B=!1,re.call(r).then(function(){s.resolve()}),F&&r.sourceBufferExt.getAllRanges(F).then(function(e){if(e&&(r.debug.log("Append "+n+" complete: "+e.length),e.length>0)){var t,i;for(r.debug.log("Number of buffered "+n+" ranges: "+e.length),t=0,i=e.length;i>t;t+=1)r.debug.log("Buffered "+n+" Range: "+e.start(t)+" - "+e.end(t))}})},function(t){t.err.code===o&&(N=e,_=s,B=!0,D=0,Z.call(r))})})})}),s.promise},re=function(){if(!k&&!F)return Q.when(!1);var e=this,t=Q.defer(),r=he.call(e);return e.sourceBufferExt.getBufferLength(F,r).then(function(r){A=r,e.metricsModel.addBufferLevel(n,new Date,A),ie.call(e),t.resolve()}),t.promise},ie=function(){var e=this.bufferExt.getLeastBufferLevel(),t=2*I,n=A-e;n>t&&!L?(D=0,L=Q.defer()):t>n&&L&&(L.resolve(),L=null)},oe=function(){var e,t=this,n=Q.defer(),r=0;return B?(e=function(){ae.call(t).then(function(t){r+=t,r>=I?n.resolve():setTimeout(e,1e3*I)})},e.call(t),n.promise):Q.when(!0)},ae=function(){var e,n,r=this,i=Q.defer(),o=r.videoModel.getCurrentTime(),a=0;return n=r.fragmentController.getExecutedRequestForTime(C,o),e=n&&!isNaN(n.startTime)?n.startTime:Math.floor(o),I=n&&!isNaN(n.duration)?n.duration:1,r.sourceBufferExt.getBufferRange(F,o).then(function(n){null===n&&y===o&&F.buffered.length>0&&(e=F.buffered.end(F.buffered.length-1)),a=F.buffered.start(0),r.sourceBufferExt.remove(F,a,e,O,t).then(function(){r.fragmentController.removeExecutedRequestsBeforeTime(C,e),i.resolve(e-a)})}),i.promise},se=function(e,t){var r=this,i=t.data,o=e.quality;r.debug.log(n+" Initialization finished loading: "+e.url),r.fragmentController.process(i).then(function(t){null!==t?(p[o]=t,o===M&&ne.call(r,t,e.quality).then(function(){T.resolve()})):r.debug.log("No "+n+" bytes to push.")})},ue=function(){var e=this,t=e.manifestModel.getValue(),n=e.manifestExt.getIsLive(t);d===l&&V.call(e,s),n||e.system.notify("segmentLoadingFailed")},le=function(e){this.debug.log(n+" Stream is complete."),K(new Date,MediaPlayer.vo.metrics.PlayList.Trace.END_OF_CONTENT_STOP_REASON),Z.call(this),R.resolve(e)},de=function(e,t){var r,i=null,o=this.bufferExt.getTopQualityIndex(n),a=[];if(h&&(this.debug.log("Marking a special seek for initial "+n+" playback."),m||(m=!0,y=0),h=!1),v){for(T=Q.defer(),p=[],r=0;o>=r;r+=1)a.push(this.indexHandler.getInitRequest(r,k));M=t,i=Q.all(a)}else i=Q.when(null),e&&(T=Q.defer(),M=t,p[t]&&ne.call(this,p[t],t).then(function(){T.resolve()}));return i},ce=function(t){var r,i=this;if(v&&!m)i.debug.log("Data changed - loading the "+n+" fragment for time: "+e),r=i.indexHandler.getSegmentRequestForTime(e,t,k);else{var o=Q.defer(),a=i.videoModel.getCurrentTime();r=o.promise,i.sourceBufferExt.getBufferRange(F,a).then(function(e){m=!1,null!==e&&(a=e.end),i.debug.log("Loading the "+n+" fragment for time: "+a),i.indexHandler.getSegmentRequestForTime(a,t,k).then(function(e){o.resolve(e)},function(){o.reject()})},function(){o.reject()})}return v=!1,r},fe=function(e){var t=this;null!==e?t.fragmentController.isFragmentLoadedOrPending(t,e)?"complete"!==e.action?t.indexHandler.getNextSegmentRequest(M,k).then(fe.bind(t)):(Z.call(t),V.call(t,s)):(t.debug.log("Loading an "+n+" fragment: "+e.url),Q.when(L?L.promise:!0).then(function(){t.fragmentController.prepareFragmentForLoading(t,e,J,ee,ue,le).then(function(){V.call(t,s)})})):V.call(t,s)},ge=function(){g&&(r>A&&r0?(D--,ce.call(e,M).then(fe.bind(e))):(d===u&&V.call(e,s),$.call(e))},ye=function(){var e,t=this,r=!1,o=null,a=new Date,c=t.videoModel.getCurrentTime(),f=he.call(t);if(t.debug.log("BufferController.validate() "+n+" | state: "+d),t.debug.log(n+" Playback rate: "+t.videoModel.getElement().playbackRate),t.debug.log(n+" Working time: "+f),t.debug.log(n+" Video time: "+c),t.debug.log("Current "+n+" buffer length: "+A),ge.call(t),d===l&&i>A)b||(t.debug.log("Stalling "+n+" Buffer: "+n),K(new Date,MediaPlayer.vo.metrics.PlayList.Trace.REBUFFERING_REASON),b=!0,g=!0,t.videoModel.stallStream(n,b));else if(d===s){V.call(t,u);var h=t.manifestModel.getValue().minBufferTime;t.bufferExt.decideBufferLength(h,O,g).then(function(e){t.debug.log("Buffer time: "+e),t.setMinBufferTime(e),t.requestScheduler.adjustExecuteInterval()}),t.abrController.getPlaybackQuality(n,k).then(function(i){var s=i.quality;if(t.debug.log(n+" Playback quality: "+s),t.debug.log("Populate "+n+" buffers."),void 0!==s&&(e=s),r=s!==M,r===!0){if(t.fragmentController.abortRequestsForModel(C),o=Y(e,t.getData()),null===o||void 0===o)throw"Unexpected error!";t.manifestExt.getTimestampOffsetForPeriod(x,t.manifestModel.getValue(),s,k).then(function(e){F.timestampOffset!==e&&(F.timestampOffset=e)}),K(new Date,MediaPlayer.vo.metrics.PlayList.Trace.REPRESENTATION_SWITCH_STOP_REASON),t.metricsModel.addRepresentationSwitch(n,a,c,o.id)}return t.debug.log(r?n+" Quality changed to: "+s:"Quality didn't change."),pe.call(t,s)}).then(function(i){D=i,de.call(t,r,e).then(function(e){if(null!==e){var r,i,o=e.length;for(i=0;o>i;i+=1)r=e[i],t.debug.log("Loading "+n+" initialization: "+r.url),t.debug.log(r),t.fragmentController.prepareFragmentForLoading(t,r,J,ee,ue,le).then(function(){V.call(t,s)})}}),me.call(t)})}else d===u&&V.call(t,s)};return{videoModel:void 0,metricsModel:void 0,manifestExt:void 0,manifestModel:void 0,bufferExt:void 0,sourceBufferExt:void 0,abrController:void 0,fragmentExt:void 0,indexHandler:void 0,debug:void 0,system:void 0,errHandler:void 0,initialize:function(e,t,n,r,i,o,a,s){var u=this,l=u.manifestModel.getValue(),d=u.manifestExt.getIsLive(l);u.setMediaSource(s),u.setVideoModel(i),u.setType(e),u.setPeriodIndex(t),u.setData(n).then(function(){c=!0,G.call(u)}),u.setBuffer(r),u.setScheduler(o),u.setFragmentController(a),u.indexHandler.setIsLive(d),u.manifestExt.getDurationForPeriod(t,u.manifestModel.getValue()).then(function(e){O=e,u.indexHandler.setDuration(e),u.bufferExt.decideBufferLength(l.minBufferTime,O,g).then(function(e){u.setMinBufferTime(e)})})},getType:function(){return n},setType:function(e){n=e,void 0!==this.indexHandler&&this.indexHandler.setType(e)},getPeriodIndex:function(){return x},setPeriodIndex:function(e){x=e},getVideoModel:function(){return this.videoModel},setVideoModel:function(e){this.videoModel=e},getScheduler:function(){return this.requestScheduler},setScheduler:function(e){this.requestScheduler=e},getFragmentController:function(){return this.fragmentController},setFragmentController:function(e){this.fragmentController=e},getAutoSwitchBitrate:function(){var e=this;return e.abrController.getAutoSwitchBitrate()},setAutoSwitchBitrate:function(e){var t=this;t.abrController.setAutoSwitchBitrate(e)},getData:function(){return k},setData:function(t){var r=this,i=Q.defer(),o=k;return o||(o=t),r.abrController.getPlaybackQuality(n,o).then(function(a){r.indexHandler.getCurrentTime(a.quality,o).then(function(o){v=!0,e=o,k=t,r.seek(o),r.bufferExt.updateData(k,n),i.resolve()})}),i.promise},getBuffer:function(){return F},setBuffer:function(e){F=e},getMinBufferTime:function(){return r},setMinBufferTime:function(e){r=e},setMediaSource:function(e){t=e},isReady:function(){return d===s},isBufferingCompleted:function(){return w},clearMetrics:function(){var e=this;null!==n&&""!==n&&e.metricsModel.clearCurrentMetricsForType(n)},updateBufferState:function(){var e=this;B&&N&&!q?(q=!0,ne.call(e,N,M).then(function(){q=!1})):re.call(e)},reset:function(e){var n=this;Z.call(n),n.clearMetrics(),n.fragmentController.abortRequestsForModel(C),n.fragmentController.detachBufferController(C),C=null,P=[],T=null,p=[],R=Q.defer(),e||(n.sourceBufferExt.abort(t,F),n.sourceBufferExt.removeSourceBuffer(t,F)),k=null,F=null},start:z,seek:X,stop:Z}},MediaPlayer.dependencies.BufferController.prototype={constructor:MediaPlayer.dependencies.BufferController},MediaPlayer.dependencies.BufferExtensions=function(){"use strict";var e,t,n=0,r=0,i=null,o=null,a=function(e){var t=this.metricsExt.getCurrentHttpRequest(e);return null!==t?(t.tresponse.getTime()-t.trequest.getTime())/1e3:0},s=function(){var e,t=this,a=Q.defer();return Q.when(i?t.abrController.getPlaybackQuality("audio",i):n).then(function(i){Q.when(o?t.abrController.getPlaybackQuality("video",o):r).then(function(t){e=i.quality===n&&t.quality===r,e=e||i.confidence===MediaPlayer.rules.SwitchRequest.prototype.STRONG&&t.confidence===MediaPlayer.rules.SwitchRequest.prototype.STRONG,a.resolve(e)})}),a.promise};return{system:void 0,videoModel:void 0,manifestExt:void 0,metricsExt:void 0,metricsModel:void 0,abrController:void 0,bufferMax:void 0,updateData:function(e,t){var a=e.Representation_asArray.length-1;"audio"===t?(n=a,i=e):"video"===t&&(r=a,o=e)},getTopQualityIndex:function(e){var t=null;return"audio"===e?t=n:"video"===e&&(t=r),t},decideBufferLength:function(t,n){return e=MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIMEt?Math.max(MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME,t):t>=n?Math.min(n,MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME):Math.min(n,t),Q.when(e)},getLeastBufferLevel:function(){var e=this.metricsModel.getReadOnlyMetricsFor("video"),t=this.metricsExt.getCurrentBufferLevel(e),n=this.metricsModel.getReadOnlyMetricsFor("audio"),r=this.metricsExt.getCurrentBufferLevel(n),i=null;return i=null===t||null===r?null!==r?r.level:null!==t?t.level:null:Math.min(r.level,t.level)},getRequiredBufferLength:function(n,r,i,o){var u,l=this,d=l.metricsModel.getReadOnlyMetricsFor("video"),c=l.metricsModel.getReadOnlyMetricsFor("audio"),f=o>=MediaPlayer.dependencies.BufferExtensions.LONG_FORM_CONTENT_DURATION_THRESHOLD,g=Q.defer(),h=null;return l.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_MIN?(u=e,g.resolve(u)):l.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_INFINITY?(u=o,g.resolve(u)):l.bufferMax===MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_REQUIRED?(t=e,i||n||(h=s.call(l)),Q.when(h).then(function(e){e&&(t=f?MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM:MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY),u=t+r+Math.max(a.call(l,d),a.call(l,c)),g.resolve(u)})):g.reject("invalid bufferMax value: "+l.bufferMax),g.promise},getBufferTarget:function(){return void 0===t?e:t}}},MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_REQUIRED="required",MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_MIN="min",MediaPlayer.dependencies.BufferExtensions.BUFFER_SIZE_INFINITY="infinity",MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_STARTUP=1,MediaPlayer.dependencies.BufferExtensions.DEFAULT_MIN_BUFFER_TIME=8,MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY=30,MediaPlayer.dependencies.BufferExtensions.BUFFER_TIME_AT_TOP_QUALITY_LONG_FORM=300,MediaPlayer.dependencies.BufferExtensions.LONG_FORM_CONTENT_DURATION_THRESHOLD=600,MediaPlayer.dependencies.BufferExtensions.prototype.constructor=MediaPlayer.dependencies.BufferExtensions,MediaPlayer.utils.Capabilities=function(){"use strict"},MediaPlayer.utils.Capabilities.prototype={constructor:MediaPlayer.utils.Capabilities,supportsMediaSource:function(){"use strict";var e="WebKitMediaSource"in window,t="MediaSource"in window;return e||t},supportsMediaKeys:function(){"use strict";var e="WebKitMediaKeys"in window,t="MSMediaKeys"in window,n="MediaKeys"in window;return e||t||n},supportsCodec:function(e,t){"use strict";if(!(e instanceof HTMLVideoElement))throw"element must be of type HTMLVideoElement.";var n=e.canPlayType(t);return"probably"===n}},MediaPlayer.utils.Debug=function(){"use strict";var e=!0;return{eventBus:void 0,setLogToBrowserConsole:function(t){e=t},getLogToBrowserConsole:function(){return e},log:function(t){e&&console.log(t),this.eventBus.dispatchEvent({type:"log",message:t})}}},MediaPlayer.dependencies.ErrorHandler=function(){"use strict";return{eventBus:void 0,capabilityError:function(e){this.eventBus.dispatchEvent({type:"error",error:"capability",event:e})},downloadError:function(e,t,n){this.eventBus.dispatchEvent({type:"error",error:"download",event:{id:e,url:t,request:n}})},manifestError:function(e,t,n){this.eventBus.dispatchEvent({type:"error",error:"manifestError",event:{message:e,id:t,manifest:n}})},mediaSourceError:function(e){this.eventBus.dispatchEvent({type:"error",error:"mediasource",event:e})},mediaKeySessionError:function(e){this.eventBus.dispatchEvent({type:"error",error:"key_session",event:e})},mediaKeyMessageError:function(e){this.eventBus.dispatchEvent({type:"error",error:"key_message",event:e})},mediaKeySystemSelectionError:function(e){this.eventBus.dispatchEvent({type:"error",error:"key_system_selection",event:e})}}},MediaPlayer.dependencies.ErrorHandler.prototype={constructor:MediaPlayer.dependencies.ErrorHandler},MediaPlayer.utils.EventBus=function(){"use strict";var e,t=function(t,n){var r=(n?"1":"0")+t;return r in e||(e[r]=[]),e[r]},n=function(){e={}};return n(),{addEventListener:function(e,n,r){var i=t(e,r),o=i.indexOf(n);-1===o&&i.push(n)},removeEventListener:function(e,n,r){var i=t(e,r),o=i.indexOf(n);-1!==o&&i.splice(o,1)},dispatchEvent:function(e){for(var n=t(e.type,!1).slice(),r=0;rr;r++)if(e[r].getContext()==t)return e[r];return null},n=function(){for(var t=!0,n=e.length,r=0;n>r;r++)if(!e[r].isReady()){t=!1;break}return t},r=function(){for(var t=0;t0&&(t=new Uint8Array(e)),Q.when(t)},attachBufferController:function(n){if(!n)return null;var r=t(n);return r||(r=this.system.getObject("fragmentModel"),r.setContext(n),e.push(r)),r},detachBufferController:function(t){var n=e.indexOf(t);n>-1&&e.splice(n,1)},onBufferControllerStateChange:function(){n()&&r.call(this)},isFragmentLoadedOrPending:function(e,n){var r,i=t(e);return i?r=i.isFragmentLoadedOrPending(n):!1},getPendingRequests:function(e){var n=t(e);return n?n.getPendingRequests():null},getLoadingRequests:function(e){var n=t(e);return n?n.getLoadingRequests():null},isInitializationRequest:function(e){return e&&e.type&&"initialization segment"===e.type.toLowerCase()},getLoadingTime:function(e){var n=t(e);return n?n.getLoadingTime():null},getExecutedRequestForTime:function(e,t){return e?e.getExecutedRequestForTime(t):null},removeExecutedRequest:function(e,t){e&&e.removeExecutedRequest(t)},removeExecutedRequestsBeforeTime:function(e,t){e&&e.removeExecutedRequestsBeforeTime(t)},cancelPendingRequestsForModel:function(e){e&&e.cancelPendingRequests()},abortRequestsForModel:function(e){e&&e.abortRequests()},prepareFragmentForLoading:function(e,n,r,i,o,a){var s=t(e);return s&&n&&!this.isFragmentLoadedOrPending(e,n)?(s.addRequest(n),s.setCallbacks(r,i,o,a),Q.when(!0)):Q.when(null)}}},MediaPlayer.dependencies.FragmentController.prototype={constructor:MediaPlayer.dependencies.FragmentController},MediaPlayer.dependencies.FragmentLoader=function(){"use strict";var e=3,t=500,n=[],r=function(e,i){var o=new XMLHttpRequest,a=null,s=!0,u=!0,l=this;n.push(o),e.requestStartDate=new Date,e.firstByteDate=e.requestStartDate,o.open("GET",e.url,!0),o.responseType="arraybuffer",e.range&&o.setRequestHeader("Range","bytes="+e.range),o.onprogress=function(t){s&&(s=!1,(!t.lengthComputable||t.lengthComputable&&t.total!=t.loaded)&&(e.firstByteDate=new Date))},o.onload=function(){if(!(o.status<200||o.status>299)){u=!1,e.requestEndDate=new Date;var t=e.requestEndDate,n=o.response,r=e.firstByteDate.getTime()-e.requestStartDate.getTime(),i=e.requestEndDate.getTime()-e.firstByteDate.getTime(),s=e.requestEndDate.getTime()-e.requestStartDate.getTime();l.debug.log("segment loaded: ("+o.status+", "+r+"ms, "+i+"ms, "+s+"ms) "+e.url),a=l.metricsModel.addHttpRequest(e.streamType,null,e.type,e.url,null,e.range,e.requestStartDate,e.firstByteDate,e.requestEndDate,o.status,null,e.duration),l.metricsModel.appendHttpTrace(a,t,(new Date).getTime()-t.getTime(),[n.byteLength]),e.deferred.resolve({data:n,request:e})}},o.onloadend=o.onerror=function(){if(-1!==n.indexOf(o)&&(n.splice(n.indexOf(o),1),u)){u=!1,e.requestEndDate=new Date;var s=e.firstByteDate.getTime()-e.requestStartDate.getTime(),d=e.requestEndDate.getTime()-e.firstByteDate.getTime(),c=e.requestEndDate.getTime()-e.requestStartDate.getTime();l.debug.log("segment loaded: ("+o.status+", "+s+"ms, "+d+"ms, "+c+"ms) "+e.url),a=l.metricsModel.addHttpRequest(e.streamType,null,e.type,e.url,null,e.range,e.requestStartDate,e.firstByteDate,e.requestEndDate,o.status,null,e.duration),i>0?(l.debug.log("Failed loading segment: "+e.url+", retry in "+t+"ms attempts: "+i),i--,setTimeout(function(){r.call(l,e,i)},t)):(l.debug.log("Failed loading segment: "+e.url+" no retry attempts left"),l.errHandler.downloadError("content",e.url,o),e.deferred.reject(o))}},o.send()};return{metricsModel:void 0,errHandler:void 0,debug:void 0,load:function(t){return t?(t.deferred=Q.defer(),r.call(this,t,e),t.deferred.promise):Q.when(null)},abort:function(){var e,t,r=n.length;for(e=0;r>e;e+=1)t=n[e],n[e]=null,t.abort(),t=null;n=[]}}},MediaPlayer.dependencies.FragmentLoader.prototype={constructor:MediaPlayer.dependencies.FragmentLoader},MediaPlayer.dependencies.FragmentModel=function(){"use strict";var e,t,n,r,i,o=[],a=[],s=[],u=5,l=function(i){var a,u=this;t.call(e,i),a=function(t,r){s.splice(s.indexOf(t),1),o.push(t),n.call(e,t,r),t.deferred=null},u.fragmentLoader.load(i).then(a.bind(e,i),r.bind(e,i))},d=function(e,t){var n=function(e,n){return e[t]n[t]?1:0};e.sort(n)},c=function(e,t){var n,r,i=e.length-1;for(r=i;r>=0;r-=1)if(n=e[r],n.url===t.url&&n.startTime===t.startTime)return!0;return!1},f=function(e){var t=o.indexOf(e);-1!==t&&o.splice(t,1)};return{system:void 0,debug:void 0,fragmentLoader:void 0,setContext:function(t){e=t},getContext:function(){return e},addRequest:function(e){e&&(a.push(e),d.call(this,a,"index"))},setCallbacks:function(e,o,a,s){t=e,i=s,r=a,n=o},isFragmentLoadedOrPending:function(e){for(var t,n=this,r=!1,i=o.length-1,u=i;u>=0;u-=1)if(t=o[u],e.startTime===t.startTime||"complete"===t.action&&e.action===t.action){if(n.debug.log(e.streamType+" Fragment already loaded for time: "+e.startTime),e.url===t.url){n.debug.log(e.streamType+" Fragment url already loaded: "+e.url),r=!0;break}f(e)}return r||(r=c.call(n,a,e)||c.call(n,s,e)),r},isReady:function(){return e.isReady()},getPendingRequests:function(){return a},getLoadingRequests:function(){return s},getLoadingTime:function(){var e,t,n=0;for(t=o.length-1;t>=0;t-=1)if(e=o[t],e.requestEndDate instanceof Date&&e.firstByteDate instanceof Date){n=e.requestEndDate.getTime()-e.firstByteDate.getTime();break}return n},getExecutedRequestForTime:function(e){var t,n=o.length-1,r=0/0,i=0/0,a=null;for(t=n;t>=0;t-=1)if(a=o[t],r=a.startTime,i=r+a.duration,!isNaN(r)&&!isNaN(i)&&e>r&&i>e)return a;return null},removeExecutedRequest:function(e){f.call(this,e)},removeExecutedRequestsBeforeTime:function(e){var t,n=o.length-1,r=0/0,i=null;for(t=n;t>=0;t-=1)i=o[t],r=i.startTime,!isNaN(r)&&e>r&&f.call(this,i)},cancelPendingRequests:function(){a=[]},abortRequests:function(){this.fragmentLoader.abort(),s=[]},executeCurrentRequest:function(){var t,n=this;if(0!==a.length&&!(s.length>=u))switch(t=a.shift(),t.action){case"complete":o.push(t),i.call(e,t);break;case"download":s.push(t),l.call(n,t);break;default:this.debug.log("Unknown request action.")}}}},MediaPlayer.dependencies.FragmentModel.prototype={constructor:MediaPlayer.dependencies.FragmentModel},MediaPlayer.dependencies.ManifestLoader=function(){"use strict";var e=3,t=500,n=null,r=function(e){var t=null;return-1!==e.indexOf("/")&&(t=e.substring(0,e.lastIndexOf("/")+1)),t},i=function(e,o){var a=r(e),s=new XMLHttpRequest,u=new Date,l=!0,d=this;this.debug.log("Start loading manifest: "+e),s.open("GET",e,!0),s.onload=function(){s.status<200||s.status>299||(l=!1,d.metricsModel.addHttpRequest("stream",null,"MPD",e,null,null,u,new Date,s.status,null,null),d.parser.parse(s.responseText,a).then(function(t){t.mpdUrl=e,n.resolve(t)},function(){n.reject(s)}))},s.onloadend=s.onerror=function(){l&&(l=!1,d.metricsModel.addHttpRequest("stream",null,"MPD",e,null,null,u,new Date,s.status,null,null),o>0?(d.debug.log("Failed loading manifest: "+e+", retry in "+t+"ms attempts: "+o),o--,setTimeout(function(){i.call(d,e,o)},t)):(d.debug.log("Failed loading manifest: "+e+" no retry attempts left"),d.errHandler.downloadError("manifest",e,s),n.reject(s)))},s.send()};return{debug:void 0,parser:void 0,errHandler:void 0,metricsModel:void 0,load:function(t){return n=Q.defer(),i.call(this,t,e),n.promise}}},MediaPlayer.dependencies.ManifestLoader.prototype={constructor:MediaPlayer.dependencies.ManifestLoader},MediaPlayer.models.ManifestModel=function(){"use strict";var e;return{getValue:function(){return e},setValue:function(t){e=t}}},MediaPlayer.models.ManifestModel.prototype={constructor:MediaPlayer.models.ManifestModel},MediaPlayer.dependencies.ManifestUpdater=function(){"use strict";var e=0/0,t=null,n=null,r=function(){null!==t&&(clearInterval(t),t=null)},i=function(){r.call(this),isNaN(e)||(this.debug.log("Refresh manifest in "+e+" seconds."),t=setInterval(n.bind(this),1e3*e,this))},o=function(){var t=this,n=t.manifestModel.getValue();void 0!==n&&null!==n&&t.manifestExt.getRefreshDelay(n).then(function(n){e=n,i.call(t)})};return n=function(){var e=this,t=e.manifestModel.getValue(),n=t.mpdUrl;t.hasOwnProperty("Location")&&(n=t.Location),e.debug.log("Refresh manifest @ "+n),e.manifestLoader.load(n).then(function(t){e.manifestModel.setValue(t),e.debug.log("Manifest has been refreshed."),e.debug.log(t),o.call(e),e.system.notify("manifestUpdated")})},{debug:void 0,system:void 0,manifestModel:void 0,manifestExt:void 0,manifestLoader:void 0,setup:function(){o.call(this)},init:function(){o.call(this)},stop:function(){r.call(this)}}},MediaPlayer.dependencies.ManifestUpdater.prototype={constructor:MediaPlayer.dependencies.ManifestUpdater},MediaPlayer.dependencies.MediaSourceExtensions=function(){"use strict"},MediaPlayer.dependencies.MediaSourceExtensions.prototype={constructor:MediaPlayer.dependencies.MediaSourceExtensions,createMediaSource:function(){"use strict";var e="WebKitMediaSource"in window,t="MediaSource"in window;return t?Q.when(new MediaSource):e?Q.when(new WebKitMediaSource):null},attachMediaSource:function(e,t){"use strict";return t.setSource(window.URL.createObjectURL(e)),Q.when(!0)},detachMediaSource:function(e){"use strict";return e.setSource(""),Q.when(!0)},setDuration:function(e,t){"use strict";return e.duration=t,Q.when(e.duration)},signalEndOfStream:function(e){"use strict";return e.endOfStream(),Q.when(!0)}},MediaPlayer.models.MetricsModel=function(){"use strict";return{system:void 0,streamMetrics:{},clearCurrentMetricsForType:function(e){delete this.streamMetrics[e]},clearAllCurrentMetrics:function(){this.streamMetrics={}},getReadOnlyMetricsFor:function(e){return this.streamMetrics.hasOwnProperty(e)?this.streamMetrics[e]:null},getMetricsFor:function(e){var t;return this.streamMetrics.hasOwnProperty(e)?t=this.streamMetrics[e]:(t=this.system.getObject("metrics"),this.streamMetrics[e]=t),t},addTcpConnection:function(e,t,n,r,i,o){var a=new MediaPlayer.vo.metrics.TCPConnection;return a.tcpid=t,a.dest=n,a.topen=r,a.tclose=i,a.tconnect=o,this.getMetricsFor(e).TcpList.push(a),a},addHttpRequest:function(e,t,n,r,i,o,a,s,u,l,d,c){var f=new MediaPlayer.vo.metrics.HTTPRequest;return f.tcpid=t,f.type=n,f.url=r,f.actualurl=i,f.range=o,f.trequest=a,f.tresponse=s,f.tfinish=u,f.responsecode=l,f.interval=d,f.mediaduration=c,this.getMetricsFor(e).HttpList.push(f),f},appendHttpTrace:function(e,t,n,r){var i=new MediaPlayer.vo.metrics.HTTPRequest.Trace;return i.s=t,i.d=n,i.b=r,e.trace.push(i),i},addRepresentationSwitch:function(e,t,n,r,i){var o=new MediaPlayer.vo.metrics.RepresentationSwitch;return o.t=t,o.mt=n,o.to=r,o.lto=i,this.getMetricsFor(e).RepSwitchList.push(o),o},addBufferLevel:function(e,t,n){var r=new MediaPlayer.vo.metrics.BufferLevel;return r.t=t,r.level=n,this.getMetricsFor(e).BufferLevel.push(r),r},addPlayList:function(e,t,n,r){var i=new MediaPlayer.vo.metrics.PlayList;return i.start=t,i.mstart=n,i.starttype=r,this.getMetricsFor(e).PlayList.push(i),i},appendPlayListTrace:function(e,t,n,r,i,o,a,s){var u=new MediaPlayer.vo.metrics.PlayList.Trace;return u.representationid=t,u.subreplevel=n,u.start=r,u.mstart=i,u.duration=o,u.playbackspeed=a,u.stopreason=s,e.trace.push(u),u}}},MediaPlayer.models.MetricsModel.prototype={constructor:MediaPlayer.models.MetricsModel},MediaPlayer.dependencies.ProtectionController=function(){"use strict";var e=null,t=null,n=function(e){var t=this;t.protectionModel.removeKeySystem(e)},r=function(e,n){for(var r=this,i=0;ii;i+=1)if(a=o.start(i),s=o.end(i),null===u){if(d=Math.abs(a-t),t>=a&&s>t){u=a,l=s;continue}if(c>=d){u=a,l=s;continue}}else{if(d=a-l,!(c>=d))break;l=s}if(null!==u)return Q.when({start:u,end:l})}return Q.when(null)},getAllRanges:function(e){var t=null;try{return t=e.buffered,Q.when(t)}catch(n){return Q.when(null)}},getBufferLength:function(e,t,n){"use strict";var r=this,i=Q.defer();return r.getBufferRange(e,t,n).then(function(e){i.resolve(null===e?0:e.end-t)}),i.promise},waitForUpdateEnd:function(e){"use strict";var t,n=Q.defer(),r=50,i=function(){e.updating||(clearInterval(t),n.resolve(!0))},o=function(){e.removeEventListener("updateend",o,!1),n.resolve(!0)};if(e.hasOwnProperty("addEventListener"))try{e.addEventListener("updateend",o,!1)}catch(a){t=setInterval(i,r)}else t=setInterval(i,r);return n.promise},append:function(e,t){var n=Q.defer();try{"append"in e?e.append(t):"appendBuffer"in e&&e.appendBuffer(t),this.waitForUpdateEnd(e).then(function(){n.resolve()})}catch(r){n.reject({err:r,data:t})}return n.promise},remove:function(e,t,n,r,i){var o=Q.defer();try{t>=0&&r>t&&n>t&&"ended"!==i.readyState&&e.remove(t,n),this.waitForUpdateEnd(e).then(function(){o.resolve()})}catch(a){o.reject(a)}return o.promise},abort:function(e,t){"use strict";var n=Q.defer();try{"open"===e.readyState&&t.abort(),n.resolve()}catch(r){n.reject(r.description)}return n.promise}},MediaPlayer.dependencies.Stream=function(){"use strict";var e,t,n,r,i,o,a,s,u,l,d,c,f,g,h,p,m=null,y=null,v=null,M=null,b=-1,E=null,S=-1,w=null,P=-1,T=!0,R=!1,_=!1,L=null,x=[],O=-1,D=null,C=function(){this.debug.log("Attempting play..."),R&&(this.debug.log("Do play."),this.videoModel.play())},A=function(){this.debug.log("Do pause."),this.videoModel.pause()},B=function(e){this.debug.log("Attempting seek..."),R&&(this.debug.log("Do seek: "+e),this.system.notify("setCurrentTime"),this.videoModel.setCurrentTime(e),M&&M.seek(e),E&&E.seek(e))},N=function(e){var t,n=this;if(t="msneedkey"!==e.type?e.type:m,x.push({type:t,initData:e.initData}),this.debug.log("DRM: Key required for - "+t),v&&m&&!L)try{L=n.protectionController.selectKeySystem(m,v)}catch(r){A.call(n),n.debug.log(r),n.errHandler.mediaKeySystemSelectionError(r)}L&&n.protectionController.ensureKeySession(L,t,e.initData)},I=function(e){var t=this,n=null,r=null,i=null,o=null;this.debug.log("DRM: Got a key message..."),n=e.target,r=new Uint16Array(e.message.buffer),i=String.fromCharCode.apply(null,r),o=e.destinationURL,t.protectionController.updateFromMessage(L,n,i,o).fail(function(e){A.call(t),t.debug.log(e),t.errHandler.mediaKeyMessageError(e)})},q=function(){this.debug.log("DRM: Key added.")},k=function(){var e,t=event.target;switch(e="DRM: MediaKeyError - sessionId: "+t.sessionId+" errorCode: "+t.error.code+" systemErrorCode: "+t.error.systemCode+" [",t.error.code){case 1:e+="MEDIA_KEYERR_UNKNOWN - An unspecified error occurred. This value is used for errors that don't match any of the other codes.";break;case 2:e+="MEDIA_KEYERR_CLIENT - The Key System could not be installed or updated.";break;case 3:e+="MEDIA_KEYERR_SERVICE - The message passed into update indicated an error from the license service.";break;case 4:e+="MEDIA_KEYERR_OUTPUT - There is no available output device with the required characteristics for the content protection system.";break;case 5:e+="MEDIA_KEYERR_HARDWARECHANGE - A hardware configuration change caused a content protection error.";break;case 6:e+="MEDIA_KEYERR_DOMAIN - An error occurred in a multi-device domain licensing configuration. The most common error is a failure to join the domain."}e+="]",this.debug.log(e),this.errHandler.mediaKeySessionError(e)},F=function(e){var t=Q.defer(),n=this,r=function(i){n.debug.log("MediaSource is open!"),n.debug.log(i),e.removeEventListener("sourceopen",r),e.removeEventListener("webkitsourceopen",r),t.resolve(e)};return n.debug.log("MediaSource should be closed. The actual readyState is: "+e.readyState),e.addEventListener("sourceopen",r,!1),e.addEventListener("webkitsourceopen",r,!1),n.mediaSourceExt.attachMediaSource(e,n.videoModel),n.debug.log("MediaSource attached to video. Waiting on open..."),t.promise},U=function(){var n=this;M&&M.reset(_),E&&E.reset(_),t&&n.mediaSourceExt.detachMediaSource(n.videoModel),R=!1,L=null,x=[],v=null,M=null,E=null,w=null,m=null,y=null,t=null,e=null},j=function(t,n,r,i){if(t&&n&&r)if(null===M&&null===E&&null===w){var o="No streams to play.";this.errHandler.manifestError(o,"nostreams",e),this.debug.log(o),i.reject()}else this.debug.log("MediaSource initialized!"),i.resolve(!0)},H=function(){this.debug.log("Getting MediaSource ready...");var e=Q.defer(),n=!1,r=!1,i=!1,o=this,a=o.manifestModel.getValue(),s=o.manifestExt.getIsLive(a);return o.debug.log("Gathering information for buffers. (1)"),o.manifestExt.getDuration(a,s).then(function(){o.manifestExt.getVideoData(a,O).then(function(s){return null!==s?(o.debug.log("Create video buffer."),o.manifestExt.getDataIndex(s,a,O).then(function(e){b=e,o.debug.log("Save video track: "+b)}),o.manifestExt.getCodec(s).then(function(e){return o.debug.log("Video codec: "+e),m=e,o.manifestExt.getContentProtectionData(s).then(function(n){if(o.debug.log("Video contentProtection"),n&&!o.capabilities.supportsMediaKeys())return o.errHandler.capabilityError("mediakeys"),Q.when(null);if(v=n,!o.capabilities.supportsCodec(o.videoModel.getElement(),e)){var r="Video Codec ("+e+") is not supported.";return o.errHandler.manifestError(r,"codec",a),o.debug.log(r),Q.when(null)}return o.sourceBufferExt.createSourceBuffer(t,e)})}).then(function(a){null===a?o.debug.log("No buffer was created, skipping video stream."):(M=o.system.getObject("bufferController"),M.initialize("video",O,s,a,o.videoModel,o.requestScheduler,o.fragmentController,t),o.debug.log("Video is ready!")),n=!0,j.call(o,n,r,i,e)},function(){o.errHandler.mediaSourceError("Error creating video source buffer."),n=!0,j.call(o,n,r,i,e)})):(o.debug.log("No video data."),n=!0,j.call(o,n,r,i,e)),o.manifestExt.getAudioDatas(a,O)}).then(function(s){return null!==s&&s.length>0?(o.debug.log("Have audio streams: "+s.length),o.manifestExt.getPrimaryAudioData(a,O).then(function(s){o.manifestExt.getDataIndex(s,a,O).then(function(e){S=e,o.debug.log("Save audio track: "+S)}),o.manifestExt.getCodec(s).then(function(e){return o.debug.log("Audio codec: "+e),y=e,o.manifestExt.getContentProtectionData(s).then(function(n){if(o.debug.log("Audio contentProtection"),n&&!o.capabilities.supportsMediaKeys())return o.errHandler.capabilityError("mediakeys"),Q.when(null);if(v=n,!o.capabilities.supportsCodec(o.videoModel.getElement(),e)){var r="Audio Codec ("+e+") is not supported.";return o.errHandler.manifestError(r,"codec",a),o.debug.log(r),Q.when(null)}return o.sourceBufferExt.createSourceBuffer(t,e)})}).then(function(a){null===a?o.debug.log("No buffer was created, skipping audio stream."):(E=o.system.getObject("bufferController"),E.initialize("audio",O,s,a,o.videoModel,o.requestScheduler,o.fragmentController,t),o.debug.log("Audio is ready!")),r=!0,j.call(o,n,r,i,e)},function(){o.errHandler.mediaSourceError("Error creating audio source buffer."),r=!0,j.call(o,n,r,i,e)})})):(o.debug.log("No audio streams."),r=!0,j.call(o,n,r,i,e)),o.manifestExt.getTextData(a,O)}).then(function(s){var u;null!==s?(o.manifestExt.getDataIndex(s,a,O).then(function(e){P=e,o.debug.log("Save text track: "+P)}),o.manifestExt.getMimeType(s).then(function(e){return u=e,o.sourceBufferExt.createSourceBuffer(t,u)}).then(function(t){null===t?o.debug.log("Source buffer was not created for text track"):(w=o.system.getObject("textController"),w.initialize(O,s,t,o.videoModel),t.hasOwnProperty("initialize")&&t.initialize(u,w),o.debug.log("Text is ready!"),i=!0,j.call(o,n,r,i,e))},function(t){o.debug.log("Error creating text source buffer:"),o.debug.log(t),o.errHandler.mediaSourceError("Error creating text source buffer."),i=!0,j.call(o,n,r,i,e)})):(o.debug.log("No text tracks."),i=!0,j.call(o,n,r,i,e))})}),e.promise},V=function(){var e=this,n=Q.defer(),r=e.manifestModel.getValue(),i=e.manifestExt.getIsLive(r);return e.debug.log("Getting ready for playback..."),e.manifestExt.getDurationForPeriod(O,e.manifestModel.getValue(),i).then(function(e){c=e}),e.manifestExt.getDuration(e.manifestModel.getValue(),i).then(function(n){return e.debug.log("Setting duration: "+n),e.mediaSourceExt.setDuration(t,n)}).then(function(){return e.debug.log("Duration successfully set."),e.manifestExt.getPeriodStart(e.manifestModel.getValue(),O)}).then(function(e){D=e,R=!0,n.resolve(!0)}),n.promise},K=function(){var e=this;e.debug.log("Got loadmetadata event."),n.resolve(null)},W=function(){this.debug.log("Got play event."),R&&(null!==D?(this.debug.log("Starting segment loading at offset: "+D),M&&M.seek(D),E&&E.seek(D),w&&w.seek(D)):(M&&M.start(),E&&E.start(),w&&w.start()))},G=function(){this.debug.log("Got pause event."),this.scheduleWhilePaused||ee.call(this)},z=function(e){var t=e.srcElement.error,n=t.code,r="";if(-1!==n){switch(n){case 1:r="MEDIA_ERR_ABORTED";break;case 2:r="MEDIA_ERR_NETWORK";break;case 3:r="MEDIA_ERR_DECODE";break;case 4:r="MEDIA_ERR_SRC_NOT_SUPPORTED";break;case 5:r="MEDIA_ERR_ENCRYPTED"}_=!0,this.debug.log("Video Element Error: "+r),this.debug.log(t),this.errHandler.mediaSourceError(r),this.reset()}},X=function(){this.debug.log("Got seeking event.");var e=this.videoModel.getCurrentTime();M&&M.seek(e),E&&E.seek(e)},Z=function(){this.debug.log("Seek complete."),this.videoModel.listen("seeking",s),this.videoModel.unlisten("seeked",u)},Y=function(){J.call(this)},$=function(){J.call(this)},J=function(){M&&M.updateBufferState(),E&&E.updateBufferState()},ee=function(){M&&M.stop(),E&&E.stop()},te=function(r){var i=this;return i.debug.log("Stream start loading."),e=r,i.mediaSourceExt.createMediaSource().then(function(e){return i.debug.log("MediaSource created."),F.call(i,e)}).then(function(e){return t=e,i.debug.log("MediaSource set up."),H.call(i)}).then(function(){return i.debug.log("Start initializing playback."),V.call(i)}).then(function(){return T?(i.debug.log("Playback initialized!"),n.promise):void 0}).then(function(){i.debug.log("element loaded!"),0===O&&C.call(i)})},ne=function(){this.debug.log("Current time has changed, block programmatic seek."),this.videoModel.unlisten("seeking",s),this.videoModel.listen("seeked",u)},re=function(){M&&!M.isBufferingCompleted()||E&&!E.isBufferingCompleted()||t&&this.mediaSourceExt.signalEndOfStream(t)},ie=function(){ee.call(this)},oe=function(){var e,t,n=this,r=n.manifestModel.getValue();n.debug.log("Manifest updated... set new data on buffers."),M&&(e=M.getData(),e&&e.hasOwnProperty("id")?n.manifestExt.getDataForId(e.id,r,O).then(function(e){M.setData(e)}):n.manifestExt.getDataForIndex(b,r,O).then(function(e){M.setData(e)})),E&&(t=E.getData(),t&&t.hasOwnProperty("id")?n.manifestExt.getDataForId(t.id,r,O).then(function(e){E.setData(e)}):n.manifestExt.getDataForIndex(S,r,O).then(function(e){E.setData(e)}))};return{system:void 0,videoModel:void 0,manifestLoader:void 0,manifestModel:void 0,mediaSourceExt:void 0,sourceBufferExt:void 0,bufferExt:void 0,manifestExt:void 0,fragmentController:void 0,abrController:void 0,fragmentExt:void 0,protectionModel:void 0,protectionController:void 0,protectionExt:void 0,capabilities:void 0,debug:void 0,metricsExt:void 0,errHandler:void 0,requestScheduler:void 0,scheduleWhilePaused:void 0,setup:function(){this.system.mapHandler("manifestUpdated",void 0,oe.bind(this)),this.system.mapHandler("setCurrentTime",void 0,ne.bind(this)),this.system.mapHandler("bufferingCompleted",void 0,re.bind(this)),this.system.mapHandler("segmentLoadingFailed",void 0,ie.bind(this)),n=Q.defer(),i=W.bind(this),o=G.bind(this),a=z.bind(this),s=X.bind(this),u=Z.bind(this),d=Y.bind(this),l=$.bind(this),r=K.bind(this)},load:function(e,t){O=t,te.call(this,e)},setVideoModel:function(e){this.videoModel=e,this.videoModel.listen("play",i),this.videoModel.listen("pause",o),this.videoModel.listen("error",a),this.videoModel.listen("seeking",s),this.videoModel.listen("timeupdate",l),this.videoModel.listen("progress",d),this.videoModel.listen("loadedmetadata",r)},initProtection:function(){f=N.bind(this),g=I.bind(this),h=q.bind(this),p=k.bind(this),this.protectionModel=this.system.getObject("protectionModel"),this.protectionModel.init(this.getVideoModel()),this.protectionController=this.system.getObject("protectionController"),this.protectionController.init(this.videoModel,this.protectionModel),this.protectionModel.listenToNeedKey(f),this.protectionModel.listenToKeyMessage(g),this.protectionModel.listenToKeyError(p),this.protectionModel.listenToKeyAdded(h)},getVideoModel:function(){return this.videoModel},getManifestExt:function(){var e=this;return e.manifestExt},setAutoPlay:function(e){T=e},getAutoPlay:function(){return T},reset:function(){A.call(this),this.videoModel.unlisten("play",i),this.videoModel.unlisten("pause",o),this.videoModel.unlisten("error",a),this.videoModel.unlisten("seeking",s),this.videoModel.unlisten("timeupdate",l),this.videoModel.unlisten("progress",d),this.videoModel.unlisten("loadedmetadata",r),U.call(this),this.protectionController&&this.protectionController.teardownKeySystem(L),this.protectionController=void 0,this.protectionModel=void 0,this.fragmentController=void 0,this.requestScheduler=void 0,n=Q.defer()},getDuration:function(){return c},setPeriodIndex:function(e){O=e},getPeriodIndex:function(){return O},getStartTime:function(){return D},play:C,seek:B,pause:A}},MediaPlayer.dependencies.Stream.prototype={constructor:MediaPlayer.dependencies.Stream},MediaPlayer.dependencies.StreamController=function(){"use strict";var e,t=[],n=4,r=3,i=!0,o=null,a=function(){e.play()},s=function(){e.pause()},u=function(t){e.seek(t)},l=function(e,t){var n=e.getElement(),r=t.getElement();return r.parentNode||n.parentNode.insertBefore(r,n),n.style.width="0px",r.style.width="100%",f(n,r),c(e),d(t),Q.when(!0)},d=function(e){e.listen("seeking",p),e.listen("progress",g),y()&&e.listen("timeupdate",h)},c=function(e){e.unlisten("seeking",p),e.unlisten("progress",g),e.unlisten("timeupdate",h)},f=function(e,t){["controls","loop","muted","playbackRate","volume"].forEach(function(n){t[n]=e[n]})},g=function(){var t=e.getVideoModel().getElement().buffered;if(t.length){var r=t.length-1,i=t.end(r),o=e.getStartTime()+e.getDuration()-i;n>o&&(e.getVideoModel().unlisten("progress",g),m())}},h=function(){if(!e.getVideoModel().getElement().seeking){var t=e.getStartTime()+e.getDuration(),n=e.getVideoModel().getCurrentTime();r>t-n&&E(e,y())}},p=function(){var t=e.getVideoModel().getCurrentTime(),n=v(t);n&&n!==e&&E(e,n,t)},m=function(){var e=y();e&&e.seek(e.getStartTime())},y=function(){var n=e.getPeriodIndex()+1;return ni;i++)if(r=t[i],n+=r.getDuration(),n>e)return r},M=function(){var e=this.system.getObject("videoModel"),t=document.createElement("video");return e.setElement(t),e},b=function(e){e.parentNode&&e.parentNode.removeChild(e)},E=function(t,n,r){t&&n&&t!==n&&Q.when(o||!0).then(function(){t.pause(),e=n,o=l(t.getVideoModel(),n.getVideoModel()),u(r?t.getVideoModel().getCurrentTime():n.getStartTime()),a()})};return{system:void 0,videoModel:void 0,manifestLoader:void 0,manifestUpdater:void 0,manifestModel:void 0,mediaSourceExt:void 0,sourceBufferExt:void 0,bufferExt:void 0,manifestExt:void 0,fragmentController:void 0,abrController:void 0,fragmentExt:void 0,capabilities:void 0,debug:void 0,metricsExt:void 0,errHandler:void 0,getManifestExt:function(){return e.getManifestExt()},setAutoPlay:function(e){i=e},getAutoPlay:function(){return i},getVideoModel:function(){return this.videoModel},setVideoModel:function(e){this.videoModel=e},load:function(n){var r,o=this;o.manifestLoader.load(n).then(function(n){o.manifestModel.setValue(n),o.debug.log("Manifest has loaded."),o.debug.log(o.manifestModel.getValue()),o.manifestUpdater.init(),o.manifestExt.getPeriodCount(n).then(function(a){for(var s=0;a>s;s++)r=o.system.getObject("stream"),r.setVideoModel(0===s?o.videoModel:M.call(o)),r.initProtection(),r.setAutoPlay(i),r.load(n,s),t.push(r);e=t[0],d(e.getVideoModel())})},function(){o.reset()})},reset:function(){e&&c(e.getVideoModel());for(var n=0,r=t.length;r>n;n++){var i=t[n];i.reset(),i!==e&&b(i.getVideoModel().getElement())}t=[],this.manifestUpdater.stop(),this.manifestModel.setValue(null),o=null,e=null},play:a,seek:u,pause:s}},MediaPlayer.dependencies.StreamController.prototype={constructor:MediaPlayer.dependencies.StreamController},MediaPlayer.models.VideoModel=function(){"use strict";var e,t=[],n=function(){return t.length>0},r=function(n){null!==n&&t[n]!==!0&&(t.push(n),t[n]=!0,e.playbackRate=0)},i=function(r){if(null!==r){t[r]=!1;var i=t.indexOf(r);-1!==i&&t.splice(i,1),n()===!1&&(e.playbackRate=1)}},o=function(e,t){t?r(e):i(e)};return{system:void 0,setup:function(){},play:function(){e.play()},pause:function(){e.pause()},isPaused:function(){return e.paused},getPlaybackRate:function(){return e.playbackRate},setPlaybackRate:function(t){e.playbackRate=t},getCurrentTime:function(){return e.currentTime},setCurrentTime:function(t){e.currentTime!=t&&(e.currentTime=t)},listen:function(t,n){e.addEventListener(t,n,!1)},unlisten:function(t,n){e.removeEventListener(t,n,!1)},getElement:function(){return e},setElement:function(t){e=t},setSource:function(t){e.src=t},stallStream:o,isStalled:n}},MediaPlayer.models.VideoModel.prototype={constructor:MediaPlayer.models.VideoModel},MediaPlayer.dependencies.VideoModelExtensions=function(){"use strict";return{getDroppedFrames:function(e){var t=null!==e.webkitDroppedFrameCount,n=-1;return t&&(n=e.webkitDroppedFrameCount),n}}},MediaPlayer.dependencies.VideoModelExtensions.prototype={constructor:MediaPlayer.dependencies.VideoModelExtensions},MediaPlayer.dependencies.TextController=function(){var e,t,n="LOADING",r="READY",i=!1,o=-1,a=r,s=function(e){this.debug.log("TextController setState to:"+e),a=e},u=function(){if(i&&a===r){var t=this;s.call(t,n),t.indexHandler.getInitRequest(0,e).then(function(e){t.debug.log("Loading text track initialization: "+e.url),t.debug.log(e),t.fragmentLoader.load(e).then(d.bind(t,e),c.bind(t,e)),s.call(t,n)})}},l=function(){u.call(this)},d=function(e,n){var r=this;r.debug.log(" Text track Bytes finished loading: "+e.url),r.fragmentController.process(n.data).then(function(e){null!==e&&(r.debug.log("Push text track bytes: "+e.byteLength),r.sourceBufferExt.append(t,e,r.videoModel))})},c=function(){};return{videoModel:void 0,fragmentLoader:void 0,fragmentController:void 0,indexHandler:void 0,sourceBufferExt:void 0,debug:void 0,initialize:function(e,t,n,r){var o=this;o.setVideoModel(r),o.setPeriodIndex(e),o.setData(t),o.setBuffer(n),i=!0},getPeriodIndex:function(){return o},setPeriodIndex:function(e){o=e},getVideoModel:function(){return this.videoModel},setVideoModel:function(e){this.videoModel=e},getData:function(){return e},setData:function(t){e=t},getBuffer:function(){return t},setBuffer:function(e){t=e},reset:function(e,n){e||(this.sourceBufferExt.abort(n,t),this.sourceBufferExt.removeSourceBuffer(n,t))},start:l}},MediaPlayer.dependencies.TextController.prototype={constructor:MediaPlayer.dependencies.TextController},MediaPlayer.utils.TextTrackExtensions=function(){"use strict";return{addTextTrack:function(e,t,n,r,i){var o=e.addTextTrack("captions",n,r);o["default"]=i,o.mode="showing";for(var a in t){var s=t[a];o.addCue(new TextTrackCue(s.start,s.end,s.data))}return Q.when(o)},deleteCues:function(e){for(var t=e.textTracks[0],n=t.cues,r=n.length;r>=0;r--)t.removeCue(n[r]);t.mode="disabled"}}},MediaPlayer.dependencies.TextVTTSourceBuffer=function(){var e,t,n;return{system:void 0,eventBus:void 0,initialize:function(r,i){n=r,e=i.getVideoModel().getElement(),t=i.getData()},append:function(n){var r=this;r.getParser().parse(String.fromCharCode.apply(null,new Uint16Array(n))).then(function(n){var i=t.Representation_asArray[0].id,o=t.lang;r.getTextTrackExtensions().addTextTrack(e,n,i,o,!0).then(function(){r.eventBus.dispatchEvent({type:"updateend"})})})},abort:function(){this.getTextTrackExtensions().deleteCues(e)},getParser:function(){var e;return"text/vtt"===n&&(e=this.system.getObject("vttParser")),e},getTextTrackExtensions:function(){return this.system.getObject("textTrackExtensions")},addEventListener:function(e,t,n){this.eventBus.addEventListener(e,t,n)},removeEventListener:function(e,t,n){this.eventBus.removeEventListener(e,t,n)}}},MediaPlayer.dependencies.TextVTTSourceBuffer.prototype={constructor:MediaPlayer.dependencies.TextVTTSourceBuffer},MediaPlayer.utils.VTTParser=function(){"use strict";var e=function(e){var t=e.split(":"),n=t.length-1;return e=60*parseInt(t[n-1],10)+parseFloat(t[n],10),2===n&&(e+=3600*parseInt(t[0],10)),e};return{parse:function(t){var n,r=/(?:\r\n|\r|\n)/gm,i=/-->/,o=/(^[\s]+|[\s]+$)/g,a=[];t=t.split(r),n=t.length;for(var s=0;n>s;s++){var u=t[s];if(u.length>0&&"WEBVTT"!==u&&u.match(i)){var l=u.split(i),d=t[s+1];a.push({start:e(l[0].replace(o,"")),end:e(l[1].replace(o,"")),data:d})}}return Q.when(a)}}},MediaPlayer.rules.BaseRulesCollection=function(){ +"use strict";var e=[];return{downloadRatioRule:void 0,insufficientBufferRule:void 0,getRules:function(){return Q.when(e)},setup:function(){var e=this;e.getRules().then(function(t){t.push(e.downloadRatioRule),t.push(e.insufficientBufferRule)})}}},MediaPlayer.rules.BaseRulesCollection.prototype={constructor:MediaPlayer.rules.BaseRulesCollection},MediaPlayer.rules.DownloadRatioRule=function(){"use strict";var e=function(e,t,n){var r=this,i=Q.defer();return r.manifestExt.getRepresentationFor(e,n).then(function(e){r.manifestExt.getBandwidth(e).then(function(e){i.resolve(e/t)})}),i.promise};return{debug:void 0,manifestExt:void 0,checkIndex:function(t,n,r){var i,o,a,s,u,l,d,c,f,g,h=this,p=n.HttpList,m=.75;return h.debug.log("Checking download ratio rule..."),n?null===p||void 0===p||0===p.length?(h.debug.log("No requests made for this stream yet, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(i=p[p.length-1],a=(i.tfinish.getTime()-i.trequest.getTime())/1e3,o=(i.tfinish.getTime()-i.tresponse.getTime())/1e3,0>=a?(h.debug.log("Don't know how long the download of the last fragment took, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):null===i.mediaduration||void 0===i.mediaduration||i.mediaduration<=0?(h.debug.log("Don't know the duration of the last media fragment, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(d=Q.defer(),u=i.mediaduration/a,s=i.mediaduration/o*m,isNaN(s)||isNaN(u)?(h.debug.log("Total time: "+a+"s"),h.debug.log("Download time: "+o+"s"),h.debug.log("The ratios are NaN, bailing."),Q.when(new MediaPlayer.rules.SwitchRequest)):(h.debug.log("Total ratio: "+u),h.debug.log("Download ratio: "+s),h.debug.log("Download ratio: "+s),isNaN(s)?(h.debug.log("Invalid ratio, bailing."),d.resolve(new MediaPlayer.rules.SwitchRequest)):1>s?(h.debug.log("Download ratio is poor."),t>0?(h.debug.log("We are not at the lowest bitrate, so switch down."),h.manifestExt.getRepresentationFor(t-1,r).then(function(e){h.manifestExt.getBandwidth(e).then(function(e){h.manifestExt.getRepresentationFor(t,r).then(function(n){h.manifestExt.getBandwidth(n).then(function(n){l=e/n,h.debug.log("Switch ratio: "+l),l>s?(h.debug.log("Things must be going pretty bad, switch all the way down."),d.resolve(new MediaPlayer.rules.SwitchRequest(0))):(h.debug.log("Things could be better, so just switch down one index."),d.resolve(new MediaPlayer.rules.SwitchRequest(t-1)))})})})})):(h.debug.log("We are at the lowest bitrate and cannot switch down, use current."),d.resolve(new MediaPlayer.rules.SwitchRequest(t)))):(h.debug.log("Download ratio is good."),h.manifestExt.getRepresentationCount(r).then(function(n){n-=1,n>t?(h.debug.log("We are not at the highest bitrate, so switch up."),h.manifestExt.getRepresentationFor(t+1,r).then(function(i){h.manifestExt.getBandwidth(i).then(function(i){h.manifestExt.getRepresentationFor(t,r).then(function(o){h.manifestExt.getBandwidth(o).then(function(o){if(l=i/o,h.debug.log("Switch ratio: "+l),s>=l)if(s>1e3)h.debug.log("Tons of bandwidth available, go all the way up."),d.resolve(new MediaPlayer.rules.SwitchRequest(n-1));else if(s>100)h.debug.log("Just enough bandwidth available, switch up one."),d.resolve(new MediaPlayer.rules.SwitchRequest(t+1));else{for(h.debug.log("Not exactly sure where to go, so do some math."),f=-1,c=[];(f+=1)f&&!(st&&(u=MediaPlayer.rules.SwitchRequest.prototype.STRONG,a.debug.log("Apply STRONG to buffer rule.")),s?(a.debug.log("The buffer ran dry recently, switch down."),Q.when(new MediaPlayer.rules.SwitchRequest(n-1,u))):e>t?(a.debug.log("Too many dry buffer hits, quit switching bitrates."),Q.when(new MediaPlayer.rules.SwitchRequest(n,u))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,u)))))}}},MediaPlayer.rules.InsufficientBufferRule.prototype={constructor:MediaPlayer.rules.InsufficientBufferRule},MediaPlayer.rules.LimitSwitchesRule=function(){"use strict";var e=10,t=2e4,n=5,r=0;return{debug:void 0,checkIndex:function(i,o){if(r>0)return r-=1,Q.when(new MediaPlayer.rules.SwitchRequest(i,MediaPlayer.rules.SwitchRequest.prototype.STRONG));var a,s,u,l=this,d=!1,c=(new Date).getTime(),f=o.RepSwitchList.length;for(l.debug.log("Checking limit switches rule..."),u=f-1;u>=0;u-=1){if(a=o.RepSwitchList[u],s=c-a.t.getTime(),s>=t){l.debug.log("Reached time limit, bailing.");break}if(u>=e){l.debug.log("Found too many switches within validation time, force the stream to not change."),d=!0;break}}return d?(l.debug.log("Wait some time before allowing another switch."),r=n,Q.when(new MediaPlayer.rules.SwitchRequest(i,MediaPlayer.rules.SwitchRequest.prototype.STRONG))):Q.when(new MediaPlayer.rules.SwitchRequest(MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,MediaPlayer.rules.SwitchRequest.prototype.STRONG))}}},MediaPlayer.rules.LimitSwitchesRule.prototype={constructor:MediaPlayer.rules.LimitSwitchesRule},MediaPlayer.rules.SwitchRequest=function(e,t){"use strict";this.quality=e,this.priority=t,void 0===this.quality&&(this.quality=999),void 0===this.priority&&(this.priority=.5)},MediaPlayer.rules.SwitchRequest.prototype={constructor:MediaPlayer.rules.SwitchRequest,NO_CHANGE:999,DEFAULT:.5,STRONG:1,WEAK:0},MediaPlayer.models.MetricsList=function(){"use strict";return{TcpList:[],HttpList:[],RepSwitchList:[],BufferLevel:[],PlayList:[],DroppedFrames:[]}},MediaPlayer.models.MetricsList.prototype={constructor:MediaPlayer.models.MetricsList},MediaPlayer.vo.SegmentRequest=function(){"use strict";this.action="download",this.startTime=0/0,this.streamType=null,this.type=null,this.duration=0/0,this.timescale=0/0,this.range=null,this.url=null,this.requestStartDate=null,this.firstByteDate=null,this.requestEndDate=null,this.deferred=null,this.quality=0/0,this.index=0/0},MediaPlayer.vo.SegmentRequest.prototype={constructor:MediaPlayer.vo.SegmentRequest,ACTION_DOWNLOAD:"download",ACTION_COMPLETE:"complete"},MediaPlayer.vo.metrics.BufferLevel=function(){"use strict";this.t=null,this.level=null},MediaPlayer.vo.metrics.BufferLevel.prototype={constructor:MediaPlayer.vo.metrics.BufferLevel},MediaPlayer.vo.metrics.DroppedFrames=function(){"use strict";this.time=null,this.droppedFrames=null},MediaPlayer.vo.metrics.DroppedFrames.prototype={constructor:MediaPlayer.vo.metrics.DroppedFrames},MediaPlayer.vo.metrics.HTTPRequest=function(){"use strict";this.tcpid=null,this.type=null,this.url=null,this.actualurl=null,this.range=null,this.trequest=null,this.tresponse=null,this.tfinish=null,this.responsecode=null,this.interval=null,this.mediaduration=null,this.trace=[]},MediaPlayer.vo.metrics.HTTPRequest.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest},MediaPlayer.vo.metrics.HTTPRequest.Trace=function(){"use strict";this.s=null,this.d=null,this.b=[]},MediaPlayer.vo.metrics.HTTPRequest.Trace.prototype={constructor:MediaPlayer.vo.metrics.HTTPRequest.Trace},MediaPlayer.vo.metrics.PlayList=function(){"use strict";this.start=null,this.mstart=null,this.starttype=null,this.trace=[]},MediaPlayer.vo.metrics.PlayList.Trace=function(){"use strict";this.representationid=null,this.subreplevel=null,this.start=null,this.mstart=null,this.duration=null,this.playbackspeed=null,this.stopreason=null},MediaPlayer.vo.metrics.PlayList.prototype={constructor:MediaPlayer.vo.metrics.PlayList},MediaPlayer.vo.metrics.PlayList.INITIAL_PLAY_START_REASON="initial_start",MediaPlayer.vo.metrics.PlayList.SEEK_START_REASON="seek",MediaPlayer.vo.metrics.PlayList.Trace.prototype={constructor:MediaPlayer.vo.metrics.PlayList.Trace()},MediaPlayer.vo.metrics.PlayList.Trace.USER_REQUEST_STOP_REASON="user_request",MediaPlayer.vo.metrics.PlayList.Trace.REPRESENTATION_SWITCH_STOP_REASON="representation_switch",MediaPlayer.vo.metrics.PlayList.Trace.END_OF_CONTENT_STOP_REASON="end_of_content",MediaPlayer.vo.metrics.PlayList.Trace.REBUFFERING_REASON="rebuffering",MediaPlayer.vo.metrics.RepresentationSwitch=function(){"use strict";this.t=null,this.mt=null,this.to=null,this.lto=null},MediaPlayer.vo.metrics.RepresentationSwitch.prototype={constructor:MediaPlayer.vo.metrics.RepresentationSwitch},MediaPlayer.vo.metrics.TCPConnection=function(){"use strict";this.tcpid=null,this.dest=null,this.topen=null,this.tclose=null,this.tconnect=null},MediaPlayer.vo.metrics.TCPConnection.prototype={constructor:MediaPlayer.vo.metrics.TCPConnection}; \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.js new file mode 100644 index 000000000..9887b62ab --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.js @@ -0,0 +1,621 @@ +/*! + * jQuery blockUI plugin + * Version 2.66.0-2013.10.09 + * Requires jQuery v1.7 or later + * + * Examples at: http://malsup.com/jquery/block/ + * Copyright (c) 2007-2013 M. Alsup + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Thanks to Amir-Hossein Sobhi for some excellent contributions! + */ + +;(function() { +/*jshint eqeqeq:false curly:false latedef:false */ +"use strict"; + + function setup($) { + $.fn._fadeIn = $.fn.fadeIn; + + var noOp = $.noop || function() {}; + + // this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle + // confusing userAgent strings on Vista) + var msie = /MSIE/.test(navigator.userAgent); + var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent); + var mode = document.documentMode || 0; + var setExpr = $.isFunction( document.createElement('div').style.setExpression ); + + // global $ methods for blocking/unblocking the entire page + $.blockUI = function(opts) { install(window, opts); }; + $.unblockUI = function(opts) { remove(window, opts); }; + + // convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) + $.growlUI = function(title, message, timeout, onClose) { + var $m = $(''); + if (title) $m.append(''+title+''); + if (message) $m.append(''+message+''); + if (timeout === undefined) timeout = 3000; + + // Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications + var callBlock = function(opts) { + opts = opts || {}; + + $.blockUI({ + message: $m, + fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700, + fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000, + timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout, + centerY: false, + showOverlay: false, + onUnblock: onClose, + css: $.blockUI.defaults.growlCSS + }); + }; + + callBlock(); + var nonmousedOpacity = $m.css('opacity'); + $m.mouseover(function() { + callBlock({ + fadeIn: 0, + timeout: 30000 + }); + + var displayBlock = $('.blockMsg'); + displayBlock.stop(); // cancel fadeout if it has started + displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency + }).mouseout(function() { + $('.blockMsg').fadeOut(1000); + }); + // End konapun additions + }; + + // plugin method for blocking element content + $.fn.block = function(opts) { + if ( this[0] === window ) { + $.blockUI( opts ); + return this; + } + var fullOpts = $.extend({}, $.blockUI.defaults, opts || {}); + this.each(function() { + var $el = $(this); + if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked')) + return; + $el.unblock({ fadeOut: 0 }); + }); + + return this.each(function() { + if ($.css(this,'position') == 'static') { + this.style.position = 'relative'; + $(this).data('blockUI.static', true); + } + this.style.zoom = 1; // force 'hasLayout' in ie + install(this, opts); + }); + }; + + // plugin method for unblocking element content + $.fn.unblock = function(opts) { + if ( this[0] === window ) { + $.unblockUI( opts ); + return this; + } + return this.each(function() { + remove(this, opts); + }); + }; + + $.blockUI.version = 2.66; // 2nd generation blocking at no extra cost! + + // override these in your code to change the default behavior and style + $.blockUI.defaults = { + // message displayed when blocking (use null for no message) + message: 'Please wait...', + + title: null, // title string; only used when theme == true + draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) + + theme: false, // set to true to use with jQuery UI themes + + // styles for the message when blocking; if you wish to disable + // these and use an external stylesheet then do this in your code: + // $.blockUI.defaults.css = {}; + css: { + padding: 0, + margin: 0, + width: '30%', + top: '40%', + left: '35%', + textAlign: 'center', + color: '#000', + border: '3px solid #aaa', + backgroundColor:'#fff', + cursor: 'wait' + }, + + // minimal style set used when themes are used + themedCSS: { + width: '30%', + top: '40%', + left: '35%' + }, + + // styles for the overlay + overlayCSS: { + backgroundColor: '#000', + opacity: 0.6, + cursor: 'wait' + }, + + // style to replace wait cursor before unblocking to correct issue + // of lingering wait cursor + cursorReset: 'default', + + // styles applied when using $.growlUI + growlCSS: { + width: '350px', + top: '10px', + left: '', + right: '10px', + border: 'none', + padding: '5px', + opacity: 0.6, + cursor: 'default', + color: '#fff', + backgroundColor: '#000', + '-webkit-border-radius':'10px', + '-moz-border-radius': '10px', + 'border-radius': '10px' + }, + + // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w + // (hat tip to Jorge H. N. de Vasconcelos) + /*jshint scripturl:true */ + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', + + // force usage of iframe in non-IE browsers (handy for blocking applets) + forceIframe: false, + + // z-index for the blocking overlay + baseZ: 1000, + + // set these to true to have the message automatically centered + centerX: true, // <-- only effects element blocking (page block controlled via css above) + centerY: true, + + // allow body element to be stetched in ie6; this makes blocking look better + // on "short" pages. disable if you wish to prevent changes to the body height + allowBodyStretch: true, + + // enable if you want key and mouse events to be disabled for content that is blocked + bindEvents: true, + + // be default blockUI will supress tab navigation from leaving blocking content + // (if bindEvents is true) + constrainTabKey: true, + + // fadeIn time in millis; set to 0 to disable fadeIn on block + fadeIn: 200, + + // fadeOut time in millis; set to 0 to disable fadeOut on unblock + fadeOut: 400, + + // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock + timeout: 0, + + // disable if you don't want to show the overlay + showOverlay: true, + + // if true, focus will be placed in the first available input field when + // page blocking + focusInput: true, + + // elements that can receive focus + focusableElements: ':input:enabled:visible', + + // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) + // no longer needed in 2012 + // applyPlatformOpacityRules: true, + + // callback method invoked when fadeIn has completed and blocking message is visible + onBlock: null, + + // callback method invoked when unblocking has completed; the callback is + // passed the element that has been unblocked (which is the window object for page + // blocks) and the options that were passed to the unblock call: + // onUnblock(element, options) + onUnblock: null, + + // callback method invoked when the overlay area is clicked. + // setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used. + onOverlayClick: null, + + // don't ask; if you really must know: http://groups.google.com/requiredUploads/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 + quirksmodeOffsetHack: 4, + + // class name of the message block + blockMsgClass: 'blockMsg', + + // if it is already blocked, then ignore it (don't unblock and reblock) + ignoreIfBlocked: false + }; + + // private data and functions follow... + + var pageBlock = null; + var pageBlockEls = []; + + function install(el, opts) { + var css, themedCSS; + var full = (el == window); + var msg = (opts && opts.message !== undefined ? opts.message : undefined); + opts = $.extend({}, $.blockUI.defaults, opts || {}); + + if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked')) + return; + + opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); + css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); + if (opts.onOverlayClick) + opts.overlayCSS.cursor = 'pointer'; + + themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); + msg = msg === undefined ? opts.message : msg; + + // remove the current block (if there is one) + if (full && pageBlock) + remove(window, {fadeOut:0}); + + // if an existing element is being used as the blocking content then we capture + // its current place in the DOM (and current display style) so we can restore + // it when we unblock + if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { + var node = msg.jquery ? msg[0] : msg; + var data = {}; + $(el).data('blockUI.history', data); + data.el = node; + data.parent = node.parentNode; + data.display = node.style.display; + data.position = node.style.position; + if (data.parent) + data.parent.removeChild(node); + } + + $(el).data('blockUI.onUnblock', opts.onUnblock); + var z = opts.baseZ; + + // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; + // layer1 is the iframe layer which is used to supress bleed through of underlying content + // layer2 is the overlay layer which has opacity and a wait cursor (by default) + // layer3 is the message content that is displayed while blocking + var lyr1, lyr2, lyr3, s; + if (msie || opts.forceIframe) + lyr1 = $(''); + else + lyr1 = $(''); + + if (opts.theme) + lyr2 = $(''); + else + lyr2 = $(''); + + if (opts.theme && full) { + s = ''; + if ( opts.title ) { + s += ''+(opts.title || ' ')+''; + } + s += ''; + s += ''; + } + else if (opts.theme) { + s = ''; + if ( opts.title ) { + s += ''+(opts.title || ' ')+''; + } + s += ''; + s += ''; + } + else if (full) { + s = ''; + } + else { + s = ''; + } + lyr3 = $(s); + + // if we have a message, style it + if (msg) { + if (opts.theme) { + lyr3.css(themedCSS); + lyr3.addClass('ui-widget-content'); + } + else + lyr3.css(css); + } + + // style the overlay + if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/) + lyr2.css(opts.overlayCSS); + lyr2.css('position', full ? 'fixed' : 'absolute'); + + // make iframe layer transparent in IE + if (msie || opts.forceIframe) + lyr1.css('opacity',0.0); + + //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); + var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); + $.each(layers, function() { + this.appendTo($par); + }); + + if (opts.theme && opts.draggable && $.fn.draggable) { + lyr3.draggable({ + handle: '.ui-dialog-titlebar', + cancel: 'li' + }); + } + + // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) + var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0); + if (ie6 || expr) { + // give body 100% height + if (full && opts.allowBodyStretch && $.support.boxModel) + $('html,body').css('height','100%'); + + // fix ie6 issue when blocked element has a border width + if ((ie6 || !$.support.boxModel) && !full) { + var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); + var fixT = t ? '(0 - '+t+')' : 0; + var fixL = l ? '(0 - '+l+')' : 0; + } + + // simulate fixed position + $.each(layers, function(i,o) { + var s = o[0].style; + s.position = 'absolute'; + if (i < 2) { + if (full) + s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"'); + else + s.setExpression('height','this.parentNode.offsetHeight + "px"'); + if (full) + s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'); + else + s.setExpression('width','this.parentNode.offsetWidth + "px"'); + if (fixL) s.setExpression('left', fixL); + if (fixT) s.setExpression('top', fixT); + } + else if (opts.centerY) { + if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); + s.marginTop = 0; + } + else if (!opts.centerY && full) { + var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0; + var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; + s.setExpression('top',expression); + } + }); + } + + // show the message + if (msg) { + if (opts.theme) + lyr3.find('.ui-widget-content').append(msg); + else + lyr3.append(msg); + if (msg.jquery || msg.nodeType) + $(msg).show(); + } + + if ((msie || opts.forceIframe) && opts.showOverlay) + lyr1.show(); // opacity is zero + if (opts.fadeIn) { + var cb = opts.onBlock ? opts.onBlock : noOp; + var cb1 = (opts.showOverlay && !msg) ? cb : noOp; + var cb2 = msg ? cb : noOp; + if (opts.showOverlay) + lyr2._fadeIn(opts.fadeIn, cb1); + if (msg) + lyr3._fadeIn(opts.fadeIn, cb2); + } + else { + if (opts.showOverlay) + lyr2.show(); + if (msg) + lyr3.show(); + if (opts.onBlock) + opts.onBlock(); + } + + // bind key and mouse events + bind(1, el, opts); + + if (full) { + pageBlock = lyr3[0]; + pageBlockEls = $(opts.focusableElements,pageBlock); + if (opts.focusInput) + setTimeout(focus, 20); + } + else + center(lyr3[0], opts.centerX, opts.centerY); + + if (opts.timeout) { + // auto-unblock + var to = setTimeout(function() { + if (full) + $.unblockUI(opts); + else + $(el).unblock(opts); + }, opts.timeout); + $(el).data('blockUI.timeout', to); + } + } + + // remove the block + function remove(el, opts) { + var count; + var full = (el == window); + var $el = $(el); + var data = $el.data('blockUI.history'); + var to = $el.data('blockUI.timeout'); + if (to) { + clearTimeout(to); + $el.removeData('blockUI.timeout'); + } + opts = $.extend({}, $.blockUI.defaults, opts || {}); + bind(0, el, opts); // unbind events + + if (opts.onUnblock === null) { + opts.onUnblock = $el.data('blockUI.onUnblock'); + $el.removeData('blockUI.onUnblock'); + } + + var els; + if (full) // crazy selector to handle odd field errors in ie6/7 + els = $('body').children().filter('.blockUI').add('body > .blockUI'); + else + els = $el.find('>.blockUI'); + + // fix cursor issue + if ( opts.cursorReset ) { + if ( els.length > 1 ) + els[1].style.cursor = opts.cursorReset; + if ( els.length > 2 ) + els[2].style.cursor = opts.cursorReset; + } + + if (full) + pageBlock = pageBlockEls = null; + + if (opts.fadeOut) { + count = els.length; + els.stop().fadeOut(opts.fadeOut, function() { + if ( --count === 0) + reset(els,data,opts,el); + }); + } + else + reset(els, data, opts, el); + } + + // move blocking element back into the DOM where it started + function reset(els,data,opts,el) { + var $el = $(el); + if ( $el.data('blockUI.isBlocked') ) + return; + + els.each(function(i,o) { + // remove via DOM calls so we don't lose event handlers + if (this.parentNode) + this.parentNode.removeChild(this); + }); + + if (data && data.el) { + data.el.style.display = data.display; + data.el.style.position = data.position; + if (data.parent) + data.parent.appendChild(data.el); + $el.removeData('blockUI.history'); + } + + if ($el.data('blockUI.static')) { + $el.css('position', 'static'); // #22 + } + + if (typeof opts.onUnblock == 'function') + opts.onUnblock(el,opts); + + // fix issue in Safari 6 where block artifacts remain until reflow + var body = $(document.body), w = body.width(), cssW = body[0].style.width; + body.width(w-1).width(w); + body[0].style.width = cssW; + } + + // bind/unbind the handler + function bind(b, el, opts) { + var full = el == window, $el = $(el); + + // don't bother unbinding if there is nothing to unbind + if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) + return; + + $el.data('blockUI.isBlocked', b); + + // don't bind events when overlay is not in use or if bindEvents is false + if (!full || !opts.bindEvents || (b && !opts.showOverlay)) + return; + + // bind anchors and inputs for mouse and key events + var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove'; + if (b) + $(document).bind(events, opts, handler); + else + $(document).unbind(events, handler); + + // former impl... + // var $e = $('a,:input'); + // b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); + } + + // event handler to suppress keyboard/mouse events when blocking + function handler(e) { + // allow tab navigation (conditionally) + if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) { + if (pageBlock && e.data.constrainTabKey) { + var els = pageBlockEls; + var fwd = !e.shiftKey && e.target === els[els.length-1]; + var back = e.shiftKey && e.target === els[0]; + if (fwd || back) { + setTimeout(function(){focus(back);},10); + return false; + } + } + } + var opts = e.data; + var target = $(e.target); + if (target.hasClass('blockOverlay') && opts.onOverlayClick) + opts.onOverlayClick(e); + + // allow events within the message content + if (target.parents('div.' + opts.blockMsgClass).length > 0) + return true; + + // allow events for content that is not being blocked + return target.parents().children().filter('div.blockUI').length === 0; + } + + function focus(back) { + if (!pageBlockEls) + return; + var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; + if (e) + e.focus(); + } + + function center(el, x, y) { + var p = el.parentNode, s = el.style; + var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); + var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); + if (x) s.left = l > 0 ? (l+'px') : '0'; + if (y) s.top = t > 0 ? (t+'px') : '0'; + } + + function sz(el, p) { + return parseInt($.css(el,p),10)||0; + } + + } + + + /*global define:true */ + if (typeof define === 'function' && define.amd && define.amd.jQuery) { + define(['jquery'], setup); + } else { + setup(jQuery); + } + +})(); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnkuYmxvY2tVSS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcclxuICogalF1ZXJ5IGJsb2NrVUkgcGx1Z2luXHJcbiAqIFZlcnNpb24gMi42Ni4wLTIwMTMuMTAuMDlcclxuICogUmVxdWlyZXMgalF1ZXJ5IHYxLjcgb3IgbGF0ZXJcclxuICpcclxuICogRXhhbXBsZXMgYXQ6IGh0dHA6Ly9tYWxzdXAuY29tL2pxdWVyeS9ibG9jay9cclxuICogQ29weXJpZ2h0IChjKSAyMDA3LTIwMTMgTS4gQWxzdXBcclxuICogRHVhbCBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGFuZCBHUEwgbGljZW5zZXM6XHJcbiAqIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXHJcbiAqIGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy9ncGwuaHRtbFxyXG4gKlxyXG4gKiBUaGFua3MgdG8gQW1pci1Ib3NzZWluIFNvYmhpIGZvciBzb21lIGV4Y2VsbGVudCBjb250cmlidXRpb25zIVxyXG4gKi9cclxuXHJcbjsoZnVuY3Rpb24oKSB7XHJcbi8qanNoaW50IGVxZXFlcTpmYWxzZSBjdXJseTpmYWxzZSBsYXRlZGVmOmZhbHNlICovXHJcblwidXNlIHN0cmljdFwiO1xyXG5cclxuXHRmdW5jdGlvbiBzZXR1cCgkKSB7XHJcblx0XHQkLmZuLl9mYWRlSW4gPSAkLmZuLmZhZGVJbjtcclxuXHJcblx0XHR2YXIgbm9PcCA9ICQubm9vcCB8fCBmdW5jdGlvbigpIHt9O1xyXG5cclxuXHRcdC8vIHRoaXMgYml0IGlzIHRvIGVuc3VyZSB3ZSBkb24ndCBjYWxsIHNldEV4cHJlc3Npb24gd2hlbiB3ZSBzaG91bGRuJ3QgKHdpdGggZXh0cmEgbXVzY2xlIHRvIGhhbmRsZVxyXG5cdFx0Ly8gY29uZnVzaW5nIHVzZXJBZ2VudCBzdHJpbmdzIG9uIFZpc3RhKVxyXG5cdFx0dmFyIG1zaWUgPSAvTVNJRS8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcclxuXHRcdHZhciBpZTYgID0gL01TSUUgNi4wLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmICEgL01TSUUgOC4wLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xyXG5cdFx0dmFyIG1vZGUgPSBkb2N1bWVudC5kb2N1bWVudE1vZGUgfHwgMDtcclxuXHRcdHZhciBzZXRFeHByID0gJC5pc0Z1bmN0aW9uKCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKS5zdHlsZS5zZXRFeHByZXNzaW9uICk7XHJcblxyXG5cdFx0Ly8gZ2xvYmFsICQgbWV0aG9kcyBmb3IgYmxvY2tpbmcvdW5ibG9ja2luZyB0aGUgZW50aXJlIHBhZ2VcclxuXHRcdCQuYmxvY2tVSSAgID0gZnVuY3Rpb24ob3B0cykgeyBpbnN0YWxsKHdpbmRvdywgb3B0cyk7IH07XHJcblx0XHQkLnVuYmxvY2tVSSA9IGZ1bmN0aW9uKG9wdHMpIHsgcmVtb3ZlKHdpbmRvdywgb3B0cyk7IH07XHJcblxyXG5cdFx0Ly8gY29udmVuaWVuY2UgbWV0aG9kIGZvciBxdWljayBncm93bC1saWtlIG5vdGlmaWNhdGlvbnMgIChodHRwOi8vd3d3Lmdvb2dsZS5jb20vc2VhcmNoP3E9Z3Jvd2wpXHJcblx0XHQkLmdyb3dsVUkgPSBmdW5jdGlvbih0aXRsZSwgbWVzc2FnZSwgdGltZW91dCwgb25DbG9zZSkge1xyXG5cdFx0XHR2YXIgJG0gPSAkKCc8ZGl2IGNsYXNzPVwiZ3Jvd2xVSVwiPjwvZGl2PicpO1xyXG5cdFx0XHRpZiAodGl0bGUpICRtLmFwcGVuZCgnPGgxPicrdGl0bGUrJzwvaDE+Jyk7XHJcblx0XHRcdGlmIChtZXNzYWdlKSAkbS5hcHBlbmQoJzxoMj4nK21lc3NhZ2UrJzwvaDI+Jyk7XHJcblx0XHRcdGlmICh0aW1lb3V0ID09PSB1bmRlZmluZWQpIHRpbWVvdXQgPSAzMDAwO1xyXG5cclxuXHRcdFx0Ly8gQWRkZWQgYnkga29uYXB1bjogU2V0IHRpbWVvdXQgdG8gMzAgc2Vjb25kcyBpZiB0aGlzIGdyb3dsIGlzIG1vdXNlZCBvdmVyLCBsaWtlIG5vcm1hbCB0b2FzdCBub3RpZmljYXRpb25zXHJcblx0XHRcdHZhciBjYWxsQmxvY2sgPSBmdW5jdGlvbihvcHRzKSB7XHJcblx0XHRcdFx0b3B0cyA9IG9wdHMgfHwge307XHJcblxyXG5cdFx0XHRcdCQuYmxvY2tVSSh7XHJcblx0XHRcdFx0XHRtZXNzYWdlOiAkbSxcclxuXHRcdFx0XHRcdGZhZGVJbiA6IHR5cGVvZiBvcHRzLmZhZGVJbiAgIT09ICd1bmRlZmluZWQnID8gb3B0cy5mYWRlSW4gIDogNzAwLFxyXG5cdFx0XHRcdFx0ZmFkZU91dDogdHlwZW9mIG9wdHMuZmFkZU91dCAhPT0gJ3VuZGVmaW5lZCcgPyBvcHRzLmZhZGVPdXQgOiAxMDAwLFxyXG5cdFx0XHRcdFx0dGltZW91dDogdHlwZW9mIG9wdHMudGltZW91dCAhPT0gJ3VuZGVmaW5lZCcgPyBvcHRzLnRpbWVvdXQgOiB0aW1lb3V0LFxyXG5cdFx0XHRcdFx0Y2VudGVyWTogZmFsc2UsXHJcblx0XHRcdFx0XHRzaG93T3ZlcmxheTogZmFsc2UsXHJcblx0XHRcdFx0XHRvblVuYmxvY2s6IG9uQ2xvc2UsXHJcblx0XHRcdFx0XHRjc3M6ICQuYmxvY2tVSS5kZWZhdWx0cy5ncm93bENTU1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9O1xyXG5cclxuXHRcdFx0Y2FsbEJsb2NrKCk7XHJcblx0XHRcdHZhciBub25tb3VzZWRPcGFjaXR5ID0gJG0uY3NzKCdvcGFjaXR5Jyk7XHJcblx0XHRcdCRtLm1vdXNlb3ZlcihmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRjYWxsQmxvY2soe1xyXG5cdFx0XHRcdFx0ZmFkZUluOiAwLFxyXG5cdFx0XHRcdFx0dGltZW91dDogMzAwMDBcclxuXHRcdFx0XHR9KTtcclxuXHJcblx0XHRcdFx0dmFyIGRpc3BsYXlCbG9jayA9ICQoJy5ibG9ja01zZycpO1xyXG5cdFx0XHRcdGRpc3BsYXlCbG9jay5zdG9wKCk7IC8vIGNhbmNlbCBmYWRlb3V0IGlmIGl0IGhhcyBzdGFydGVkXHJcblx0XHRcdFx0ZGlzcGxheUJsb2NrLmZhZGVUbygzMDAsIDEpOyAvLyBtYWtlIGl0IGVhc2llciB0byByZWFkIHRoZSBtZXNzYWdlIGJ5IHJlbW92aW5nIHRyYW5zcGFyZW5jeVxyXG5cdFx0XHR9KS5tb3VzZW91dChmdW5jdGlvbigpIHtcclxuXHRcdFx0XHQkKCcuYmxvY2tNc2cnKS5mYWRlT3V0KDEwMDApO1xyXG5cdFx0XHR9KTtcclxuXHRcdFx0Ly8gRW5kIGtvbmFwdW4gYWRkaXRpb25zXHJcblx0XHR9O1xyXG5cclxuXHRcdC8vIHBsdWdpbiBtZXRob2QgZm9yIGJsb2NraW5nIGVsZW1lbnQgY29udGVudFxyXG5cdFx0JC5mbi5ibG9jayA9IGZ1bmN0aW9uKG9wdHMpIHtcclxuXHRcdFx0aWYgKCB0aGlzWzBdID09PSB3aW5kb3cgKSB7XHJcblx0XHRcdFx0JC5ibG9ja1VJKCBvcHRzICk7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHRcdH1cclxuXHRcdFx0dmFyIGZ1bGxPcHRzID0gJC5leHRlbmQoe30sICQuYmxvY2tVSS5kZWZhdWx0cywgb3B0cyB8fCB7fSk7XHJcblx0XHRcdHRoaXMuZWFjaChmdW5jdGlvbigpIHtcclxuXHRcdFx0XHR2YXIgJGVsID0gJCh0aGlzKTtcclxuXHRcdFx0XHRpZiAoZnVsbE9wdHMuaWdub3JlSWZCbG9ja2VkICYmICRlbC5kYXRhKCdibG9ja1VJLmlzQmxvY2tlZCcpKVxyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdCRlbC51bmJsb2NrKHsgZmFkZU91dDogMCB9KTtcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdGlmICgkLmNzcyh0aGlzLCdwb3NpdGlvbicpID09ICdzdGF0aWMnKSB7XHJcblx0XHRcdFx0XHR0aGlzLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcclxuXHRcdFx0XHRcdCQodGhpcykuZGF0YSgnYmxvY2tVSS5zdGF0aWMnLCB0cnVlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0dGhpcy5zdHlsZS56b29tID0gMTsgLy8gZm9yY2UgJ2hhc0xheW91dCcgaW4gaWVcclxuXHRcdFx0XHRpbnN0YWxsKHRoaXMsIG9wdHMpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH07XHJcblxyXG5cdFx0Ly8gcGx1Z2luIG1ldGhvZCBmb3IgdW5ibG9ja2luZyBlbGVtZW50IGNvbnRlbnRcclxuXHRcdCQuZm4udW5ibG9jayA9IGZ1bmN0aW9uKG9wdHMpIHtcclxuXHRcdFx0aWYgKCB0aGlzWzBdID09PSB3aW5kb3cgKSB7XHJcblx0XHRcdFx0JC51bmJsb2NrVUkoIG9wdHMgKTtcclxuXHRcdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdHJlbW92ZSh0aGlzLCBvcHRzKTtcclxuXHRcdFx0fSk7XHJcblx0XHR9O1xyXG5cclxuXHRcdCQuYmxvY2tVSS52ZXJzaW9uID0gMi42NjsgLy8gMm5kIGdlbmVyYXRpb24gYmxvY2tpbmcgYXQgbm8gZXh0cmEgY29zdCFcclxuXHJcblx0XHQvLyBvdmVycmlkZSB0aGVzZSBpbiB5b3VyIGNvZGUgdG8gY2hhbmdlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIGFuZCBzdHlsZVxyXG5cdFx0JC5ibG9ja1VJLmRlZmF1bHRzID0ge1xyXG5cdFx0XHQvLyBtZXNzYWdlIGRpc3BsYXllZCB3aGVuIGJsb2NraW5nICh1c2UgbnVsbCBmb3Igbm8gbWVzc2FnZSlcclxuXHRcdFx0bWVzc2FnZTogICc8aDE+UGxlYXNlIHdhaXQuLi48L2gxPicsXHJcblxyXG5cdFx0XHR0aXRsZTogbnVsbCxcdFx0Ly8gdGl0bGUgc3RyaW5nOyBvbmx5IHVzZWQgd2hlbiB0aGVtZSA9PSB0cnVlXHJcblx0XHRcdGRyYWdnYWJsZTogdHJ1ZSxcdC8vIG9ubHkgdXNlZCB3aGVuIHRoZW1lID09IHRydWUgKHJlcXVpcmVzIGpxdWVyeS11aS5qcyB0byBiZSBsb2FkZWQpXHJcblxyXG5cdFx0XHR0aGVtZTogZmFsc2UsIC8vIHNldCB0byB0cnVlIHRvIHVzZSB3aXRoIGpRdWVyeSBVSSB0aGVtZXNcclxuXHJcblx0XHRcdC8vIHN0eWxlcyBmb3IgdGhlIG1lc3NhZ2Ugd2hlbiBibG9ja2luZzsgaWYgeW91IHdpc2ggdG8gZGlzYWJsZVxyXG5cdFx0XHQvLyB0aGVzZSBhbmQgdXNlIGFuIGV4dGVybmFsIHN0eWxlc2hlZXQgdGhlbiBkbyB0aGlzIGluIHlvdXIgY29kZTpcclxuXHRcdFx0Ly8gJC5ibG9ja1VJLmRlZmF1bHRzLmNzcyA9IHt9O1xyXG5cdFx0XHRjc3M6IHtcclxuXHRcdFx0XHRwYWRkaW5nOlx0MCxcclxuXHRcdFx0XHRtYXJnaW46XHRcdDAsXHJcblx0XHRcdFx0d2lkdGg6XHRcdCczMCUnLFxyXG5cdFx0XHRcdHRvcDpcdFx0JzQwJScsXHJcblx0XHRcdFx0bGVmdDpcdFx0JzM1JScsXHJcblx0XHRcdFx0dGV4dEFsaWduOlx0J2NlbnRlcicsXHJcblx0XHRcdFx0Y29sb3I6XHRcdCcjMDAwJyxcclxuXHRcdFx0XHRib3JkZXI6XHRcdCczcHggc29saWQgI2FhYScsXHJcblx0XHRcdFx0YmFja2dyb3VuZENvbG9yOicjZmZmJyxcclxuXHRcdFx0XHRjdXJzb3I6XHRcdCd3YWl0J1xyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0Ly8gbWluaW1hbCBzdHlsZSBzZXQgdXNlZCB3aGVuIHRoZW1lcyBhcmUgdXNlZFxyXG5cdFx0XHR0aGVtZWRDU1M6IHtcclxuXHRcdFx0XHR3aWR0aDpcdCczMCUnLFxyXG5cdFx0XHRcdHRvcDpcdCc0MCUnLFxyXG5cdFx0XHRcdGxlZnQ6XHQnMzUlJ1xyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0Ly8gc3R5bGVzIGZvciB0aGUgb3ZlcmxheVxyXG5cdFx0XHRvdmVybGF5Q1NTOiAge1xyXG5cdFx0XHRcdGJhY2tncm91bmRDb2xvcjpcdCcjMDAwJyxcclxuXHRcdFx0XHRvcGFjaXR5Olx0XHRcdDAuNixcclxuXHRcdFx0XHRjdXJzb3I6XHRcdFx0XHQnd2FpdCdcclxuXHRcdFx0fSxcclxuXHJcblx0XHRcdC8vIHN0eWxlIHRvIHJlcGxhY2Ugd2FpdCBjdXJzb3IgYmVmb3JlIHVuYmxvY2tpbmcgdG8gY29ycmVjdCBpc3N1ZVxyXG5cdFx0XHQvLyBvZiBsaW5nZXJpbmcgd2FpdCBjdXJzb3JcclxuXHRcdFx0Y3Vyc29yUmVzZXQ6ICdkZWZhdWx0JyxcclxuXHJcblx0XHRcdC8vIHN0eWxlcyBhcHBsaWVkIHdoZW4gdXNpbmcgJC5ncm93bFVJXHJcblx0XHRcdGdyb3dsQ1NTOiB7XHJcblx0XHRcdFx0d2lkdGg6XHRcdCczNTBweCcsXHJcblx0XHRcdFx0dG9wOlx0XHQnMTBweCcsXHJcblx0XHRcdFx0bGVmdDpcdFx0JycsXHJcblx0XHRcdFx0cmlnaHQ6XHRcdCcxMHB4JyxcclxuXHRcdFx0XHRib3JkZXI6XHRcdCdub25lJyxcclxuXHRcdFx0XHRwYWRkaW5nOlx0JzVweCcsXHJcblx0XHRcdFx0b3BhY2l0eTpcdDAuNixcclxuXHRcdFx0XHRjdXJzb3I6XHRcdCdkZWZhdWx0JyxcclxuXHRcdFx0XHRjb2xvcjpcdFx0JyNmZmYnLFxyXG5cdFx0XHRcdGJhY2tncm91bmRDb2xvcjogJyMwMDAnLFxyXG5cdFx0XHRcdCctd2Via2l0LWJvcmRlci1yYWRpdXMnOicxMHB4JyxcclxuXHRcdFx0XHQnLW1vei1ib3JkZXItcmFkaXVzJzpcdCcxMHB4JyxcclxuXHRcdFx0XHQnYm9yZGVyLXJhZGl1cyc6XHRcdCcxMHB4J1xyXG5cdFx0XHR9LFxyXG5cclxuXHRcdFx0Ly8gSUUgaXNzdWVzOiAnYWJvdXQ6YmxhbmsnIGZhaWxzIG9uIEhUVFBTIGFuZCBqYXZhc2NyaXB0OmZhbHNlIGlzIHMtbC1vLXdcclxuXHRcdFx0Ly8gKGhhdCB0aXAgdG8gSm9yZ2UgSC4gTi4gZGUgVmFzY29uY2Vsb3MpXHJcblx0XHRcdC8qanNoaW50IHNjcmlwdHVybDp0cnVlICovXHJcblx0XHRcdGlmcmFtZVNyYzogL15odHRwcy9pLnRlc3Qod2luZG93LmxvY2F0aW9uLmhyZWYgfHwgJycpID8gJ2phdmFzY3JpcHQ6ZmFsc2UnIDogJ2Fib3V0OmJsYW5rJyxcclxuXHJcblx0XHRcdC8vIGZvcmNlIHVzYWdlIG9mIGlmcmFtZSBpbiBub24tSUUgYnJvd3NlcnMgKGhhbmR5IGZvciBibG9ja2luZyBhcHBsZXRzKVxyXG5cdFx0XHRmb3JjZUlmcmFtZTogZmFsc2UsXHJcblxyXG5cdFx0XHQvLyB6LWluZGV4IGZvciB0aGUgYmxvY2tpbmcgb3ZlcmxheVxyXG5cdFx0XHRiYXNlWjogMTAwMCxcclxuXHJcblx0XHRcdC8vIHNldCB0aGVzZSB0byB0cnVlIHRvIGhhdmUgdGhlIG1lc3NhZ2UgYXV0b21hdGljYWxseSBjZW50ZXJlZFxyXG5cdFx0XHRjZW50ZXJYOiB0cnVlLCAvLyA8LS0gb25seSBlZmZlY3RzIGVsZW1lbnQgYmxvY2tpbmcgKHBhZ2UgYmxvY2sgY29udHJvbGxlZCB2aWEgY3NzIGFib3ZlKVxyXG5cdFx0XHRjZW50ZXJZOiB0cnVlLFxyXG5cclxuXHRcdFx0Ly8gYWxsb3cgYm9keSBlbGVtZW50IHRvIGJlIHN0ZXRjaGVkIGluIGllNjsgdGhpcyBtYWtlcyBibG9ja2luZyBsb29rIGJldHRlclxyXG5cdFx0XHQvLyBvbiBcInNob3J0XCIgcGFnZXMuICBkaXNhYmxlIGlmIHlvdSB3aXNoIHRvIHByZXZlbnQgY2hhbmdlcyB0byB0aGUgYm9keSBoZWlnaHRcclxuXHRcdFx0YWxsb3dCb2R5U3RyZXRjaDogdHJ1ZSxcclxuXHJcblx0XHRcdC8vIGVuYWJsZSBpZiB5b3Ugd2FudCBrZXkgYW5kIG1vdXNlIGV2ZW50cyB0byBiZSBkaXNhYmxlZCBmb3IgY29udGVudCB0aGF0IGlzIGJsb2NrZWRcclxuXHRcdFx0YmluZEV2ZW50czogdHJ1ZSxcclxuXHJcblx0XHRcdC8vIGJlIGRlZmF1bHQgYmxvY2tVSSB3aWxsIHN1cHJlc3MgdGFiIG5hdmlnYXRpb24gZnJvbSBsZWF2aW5nIGJsb2NraW5nIGNvbnRlbnRcclxuXHRcdFx0Ly8gKGlmIGJpbmRFdmVudHMgaXMgdHJ1ZSlcclxuXHRcdFx0Y29uc3RyYWluVGFiS2V5OiB0cnVlLFxyXG5cclxuXHRcdFx0Ly8gZmFkZUluIHRpbWUgaW4gbWlsbGlzOyBzZXQgdG8gMCB0byBkaXNhYmxlIGZhZGVJbiBvbiBibG9ja1xyXG5cdFx0XHRmYWRlSW46ICAyMDAsXHJcblxyXG5cdFx0XHQvLyBmYWRlT3V0IHRpbWUgaW4gbWlsbGlzOyBzZXQgdG8gMCB0byBkaXNhYmxlIGZhZGVPdXQgb24gdW5ibG9ja1xyXG5cdFx0XHRmYWRlT3V0OiAgNDAwLFxyXG5cclxuXHRcdFx0Ly8gdGltZSBpbiBtaWxsaXMgdG8gd2FpdCBiZWZvcmUgYXV0by11bmJsb2NraW5nOyBzZXQgdG8gMCB0byBkaXNhYmxlIGF1dG8tdW5ibG9ja1xyXG5cdFx0XHR0aW1lb3V0OiAwLFxyXG5cclxuXHRcdFx0Ly8gZGlzYWJsZSBpZiB5b3UgZG9uJ3Qgd2FudCB0byBzaG93IHRoZSBvdmVybGF5XHJcblx0XHRcdHNob3dPdmVybGF5OiB0cnVlLFxyXG5cclxuXHRcdFx0Ly8gaWYgdHJ1ZSwgZm9jdXMgd2lsbCBiZSBwbGFjZWQgaW4gdGhlIGZpcnN0IGF2YWlsYWJsZSBpbnB1dCBmaWVsZCB3aGVuXHJcblx0XHRcdC8vIHBhZ2UgYmxvY2tpbmdcclxuXHRcdFx0Zm9jdXNJbnB1dDogdHJ1ZSxcclxuXHJcbiAgICAgICAgICAgIC8vIGVsZW1lbnRzIHRoYXQgY2FuIHJlY2VpdmUgZm9jdXNcclxuICAgICAgICAgICAgZm9jdXNhYmxlRWxlbWVudHM6ICc6aW5wdXQ6ZW5hYmxlZDp2aXNpYmxlJyxcclxuXHJcblx0XHRcdC8vIHN1cHByZXNzZXMgdGhlIHVzZSBvZiBvdmVybGF5IHN0eWxlcyBvbiBGRi9MaW51eCAoZHVlIHRvIHBlcmZvcm1hbmNlIGlzc3VlcyB3aXRoIG9wYWNpdHkpXHJcblx0XHRcdC8vIG5vIGxvbmdlciBuZWVkZWQgaW4gMjAxMlxyXG5cdFx0XHQvLyBhcHBseVBsYXRmb3JtT3BhY2l0eVJ1bGVzOiB0cnVlLFxyXG5cclxuXHRcdFx0Ly8gY2FsbGJhY2sgbWV0aG9kIGludm9rZWQgd2hlbiBmYWRlSW4gaGFzIGNvbXBsZXRlZCBhbmQgYmxvY2tpbmcgbWVzc2FnZSBpcyB2aXNpYmxlXHJcblx0XHRcdG9uQmxvY2s6IG51bGwsXHJcblxyXG5cdFx0XHQvLyBjYWxsYmFjayBtZXRob2QgaW52b2tlZCB3aGVuIHVuYmxvY2tpbmcgaGFzIGNvbXBsZXRlZDsgdGhlIGNhbGxiYWNrIGlzXHJcblx0XHRcdC8vIHBhc3NlZCB0aGUgZWxlbWVudCB0aGF0IGhhcyBiZWVuIHVuYmxvY2tlZCAod2hpY2ggaXMgdGhlIHdpbmRvdyBvYmplY3QgZm9yIHBhZ2VcclxuXHRcdFx0Ly8gYmxvY2tzKSBhbmQgdGhlIG9wdGlvbnMgdGhhdCB3ZXJlIHBhc3NlZCB0byB0aGUgdW5ibG9jayBjYWxsOlxyXG5cdFx0XHQvL1x0b25VbmJsb2NrKGVsZW1lbnQsIG9wdGlvbnMpXHJcblx0XHRcdG9uVW5ibG9jazogbnVsbCxcclxuXHJcblx0XHRcdC8vIGNhbGxiYWNrIG1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIG92ZXJsYXkgYXJlYSBpcyBjbGlja2VkLlxyXG5cdFx0XHQvLyBzZXR0aW5nIHRoaXMgd2lsbCB0dXJuIHRoZSBjdXJzb3IgdG8gYSBwb2ludGVyLCBvdGhlcndpc2UgY3Vyc29yIGRlZmluZWQgaW4gb3ZlcmxheUNzcyB3aWxsIGJlIHVzZWQuXHJcblx0XHRcdG9uT3ZlcmxheUNsaWNrOiBudWxsLFxyXG5cclxuXHRcdFx0Ly8gZG9uJ3QgYXNrOyBpZiB5b3UgcmVhbGx5IG11c3Qga25vdzogaHR0cDovL2dyb3Vwcy5nb29nbGUuY29tL3JlcXVpcmVkVXBsb2Fkcy9qcXVlcnktZW4vYnJvd3NlX3RocmVhZC90aHJlYWQvMzY2NDBhODczMDUwMzU5NS8yZjZhNzlhNzdhNzhlNDkzIzJmNmE3OWE3N2E3OGU0OTNcclxuXHRcdFx0cXVpcmtzbW9kZU9mZnNldEhhY2s6IDQsXHJcblxyXG5cdFx0XHQvLyBjbGFzcyBuYW1lIG9mIHRoZSBtZXNzYWdlIGJsb2NrXHJcblx0XHRcdGJsb2NrTXNnQ2xhc3M6ICdibG9ja01zZycsXHJcblxyXG5cdFx0XHQvLyBpZiBpdCBpcyBhbHJlYWR5IGJsb2NrZWQsIHRoZW4gaWdub3JlIGl0IChkb24ndCB1bmJsb2NrIGFuZCByZWJsb2NrKVxyXG5cdFx0XHRpZ25vcmVJZkJsb2NrZWQ6IGZhbHNlXHJcblx0XHR9O1xyXG5cclxuXHRcdC8vIHByaXZhdGUgZGF0YSBhbmQgZnVuY3Rpb25zIGZvbGxvdy4uLlxyXG5cclxuXHRcdHZhciBwYWdlQmxvY2sgPSBudWxsO1xyXG5cdFx0dmFyIHBhZ2VCbG9ja0VscyA9IFtdO1xyXG5cclxuXHRcdGZ1bmN0aW9uIGluc3RhbGwoZWwsIG9wdHMpIHtcclxuXHRcdFx0dmFyIGNzcywgdGhlbWVkQ1NTO1xyXG5cdFx0XHR2YXIgZnVsbCA9IChlbCA9PSB3aW5kb3cpO1xyXG5cdFx0XHR2YXIgbXNnID0gKG9wdHMgJiYgb3B0cy5tZXNzYWdlICE9PSB1bmRlZmluZWQgPyBvcHRzLm1lc3NhZ2UgOiB1bmRlZmluZWQpO1xyXG5cdFx0XHRvcHRzID0gJC5leHRlbmQoe30sICQuYmxvY2tVSS5kZWZhdWx0cywgb3B0cyB8fCB7fSk7XHJcblxyXG5cdFx0XHRpZiAob3B0cy5pZ25vcmVJZkJsb2NrZWQgJiYgJChlbCkuZGF0YSgnYmxvY2tVSS5pc0Jsb2NrZWQnKSlcclxuXHRcdFx0XHRyZXR1cm47XHJcblxyXG5cdFx0XHRvcHRzLm92ZXJsYXlDU1MgPSAkLmV4dGVuZCh7fSwgJC5ibG9ja1VJLmRlZmF1bHRzLm92ZXJsYXlDU1MsIG9wdHMub3ZlcmxheUNTUyB8fCB7fSk7XHJcblx0XHRcdGNzcyA9ICQuZXh0ZW5kKHt9LCAkLmJsb2NrVUkuZGVmYXVsdHMuY3NzLCBvcHRzLmNzcyB8fCB7fSk7XHJcblx0XHRcdGlmIChvcHRzLm9uT3ZlcmxheUNsaWNrKVxyXG5cdFx0XHRcdG9wdHMub3ZlcmxheUNTUy5jdXJzb3IgPSAncG9pbnRlcic7XHJcblxyXG5cdFx0XHR0aGVtZWRDU1MgPSAkLmV4dGVuZCh7fSwgJC5ibG9ja1VJLmRlZmF1bHRzLnRoZW1lZENTUywgb3B0cy50aGVtZWRDU1MgfHwge30pO1xyXG5cdFx0XHRtc2cgPSBtc2cgPT09IHVuZGVmaW5lZCA/IG9wdHMubWVzc2FnZSA6IG1zZztcclxuXHJcblx0XHRcdC8vIHJlbW92ZSB0aGUgY3VycmVudCBibG9jayAoaWYgdGhlcmUgaXMgb25lKVxyXG5cdFx0XHRpZiAoZnVsbCAmJiBwYWdlQmxvY2spXHJcblx0XHRcdFx0cmVtb3ZlKHdpbmRvdywge2ZhZGVPdXQ6MH0pO1xyXG5cclxuXHRcdFx0Ly8gaWYgYW4gZXhpc3RpbmcgZWxlbWVudCBpcyBiZWluZyB1c2VkIGFzIHRoZSBibG9ja2luZyBjb250ZW50IHRoZW4gd2UgY2FwdHVyZVxyXG5cdFx0XHQvLyBpdHMgY3VycmVudCBwbGFjZSBpbiB0aGUgRE9NIChhbmQgY3VycmVudCBkaXNwbGF5IHN0eWxlKSBzbyB3ZSBjYW4gcmVzdG9yZVxyXG5cdFx0XHQvLyBpdCB3aGVuIHdlIHVuYmxvY2tcclxuXHRcdFx0aWYgKG1zZyAmJiB0eXBlb2YgbXNnICE9ICdzdHJpbmcnICYmIChtc2cucGFyZW50Tm9kZSB8fCBtc2cuanF1ZXJ5KSkge1xyXG5cdFx0XHRcdHZhciBub2RlID0gbXNnLmpxdWVyeSA/IG1zZ1swXSA6IG1zZztcclxuXHRcdFx0XHR2YXIgZGF0YSA9IHt9O1xyXG5cdFx0XHRcdCQoZWwpLmRhdGEoJ2Jsb2NrVUkuaGlzdG9yeScsIGRhdGEpO1xyXG5cdFx0XHRcdGRhdGEuZWwgPSBub2RlO1xyXG5cdFx0XHRcdGRhdGEucGFyZW50ID0gbm9kZS5wYXJlbnROb2RlO1xyXG5cdFx0XHRcdGRhdGEuZGlzcGxheSA9IG5vZGUuc3R5bGUuZGlzcGxheTtcclxuXHRcdFx0XHRkYXRhLnBvc2l0aW9uID0gbm9kZS5zdHlsZS5wb3NpdGlvbjtcclxuXHRcdFx0XHRpZiAoZGF0YS5wYXJlbnQpXHJcblx0XHRcdFx0XHRkYXRhLnBhcmVudC5yZW1vdmVDaGlsZChub2RlKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0JChlbCkuZGF0YSgnYmxvY2tVSS5vblVuYmxvY2snLCBvcHRzLm9uVW5ibG9jayk7XHJcblx0XHRcdHZhciB6ID0gb3B0cy5iYXNlWjtcclxuXHJcblx0XHRcdC8vIGJsb2NrVUkgdXNlcyAzIGxheWVycyBmb3IgYmxvY2tpbmcsIGZvciBzaW1wbGljaXR5IHRoZXkgYXJlIGFsbCB1c2VkIG9uIGV2ZXJ5IHBsYXRmb3JtO1xyXG5cdFx0XHQvLyBsYXllcjEgaXMgdGhlIGlmcmFtZSBsYXllciB3aGljaCBpcyB1c2VkIHRvIHN1cHJlc3MgYmxlZWQgdGhyb3VnaCBvZiB1bmRlcmx5aW5nIGNvbnRlbnRcclxuXHRcdFx0Ly8gbGF5ZXIyIGlzIHRoZSBvdmVybGF5IGxheWVyIHdoaWNoIGhhcyBvcGFjaXR5IGFuZCBhIHdhaXQgY3Vyc29yIChieSBkZWZhdWx0KVxyXG5cdFx0XHQvLyBsYXllcjMgaXMgdGhlIG1lc3NhZ2UgY29udGVudCB0aGF0IGlzIGRpc3BsYXllZCB3aGlsZSBibG9ja2luZ1xyXG5cdFx0XHR2YXIgbHlyMSwgbHlyMiwgbHlyMywgcztcclxuXHRcdFx0aWYgKG1zaWUgfHwgb3B0cy5mb3JjZUlmcmFtZSlcclxuXHRcdFx0XHRseXIxID0gJCgnPGlmcmFtZSBjbGFzcz1cImJsb2NrVUlcIiBzdHlsZT1cInotaW5kZXg6JysgKHorKykgKyc7ZGlzcGxheTpub25lO2JvcmRlcjpub25lO21hcmdpbjowO3BhZGRpbmc6MDtwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDoxMDAlO2hlaWdodDoxMDAlO3RvcDowO2xlZnQ6MFwiIHNyYz1cIicrb3B0cy5pZnJhbWVTcmMrJ1wiPjwvaWZyYW1lPicpO1xyXG5cdFx0XHRlbHNlXHJcblx0XHRcdFx0bHlyMSA9ICQoJzxkaXYgY2xhc3M9XCJibG9ja1VJXCIgc3R5bGU9XCJkaXNwbGF5Om5vbmVcIj48L2Rpdj4nKTtcclxuXHJcblx0XHRcdGlmIChvcHRzLnRoZW1lKVxyXG5cdFx0XHRcdGx5cjIgPSAkKCc8ZGl2IGNsYXNzPVwiYmxvY2tVSSBibG9ja092ZXJsYXkgdWktd2lkZ2V0LW92ZXJsYXlcIiBzdHlsZT1cInotaW5kZXg6JysgKHorKykgKyc7ZGlzcGxheTpub25lXCI+PC9kaXY+Jyk7XHJcblx0XHRcdGVsc2VcclxuXHRcdFx0XHRseXIyID0gJCgnPGRpdiBjbGFzcz1cImJsb2NrVUkgYmxvY2tPdmVybGF5XCIgc3R5bGU9XCJ6LWluZGV4OicrICh6KyspICsnO2Rpc3BsYXk6bm9uZTtib3JkZXI6bm9uZTttYXJnaW46MDtwYWRkaW5nOjA7d2lkdGg6MTAwJTtoZWlnaHQ6MTAwJTt0b3A6MDtsZWZ0OjBcIj48L2Rpdj4nKTtcclxuXHJcblx0XHRcdGlmIChvcHRzLnRoZW1lICYmIGZ1bGwpIHtcclxuXHRcdFx0XHRzID0gJzxkaXYgY2xhc3M9XCJibG9ja1VJICcgKyBvcHRzLmJsb2NrTXNnQ2xhc3MgKyAnIGJsb2NrUGFnZSB1aS1kaWFsb2cgdWktd2lkZ2V0IHVpLWNvcm5lci1hbGxcIiBzdHlsZT1cInotaW5kZXg6JysoeisxMCkrJztkaXNwbGF5Om5vbmU7cG9zaXRpb246Zml4ZWRcIj4nO1xyXG5cdFx0XHRcdGlmICggb3B0cy50aXRsZSApIHtcclxuXHRcdFx0XHRcdHMgKz0gJzxkaXYgY2xhc3M9XCJ1aS13aWRnZXQtaGVhZGVyIHVpLWRpYWxvZy10aXRsZWJhciB1aS1jb3JuZXItYWxsIGJsb2NrVGl0bGVcIj4nKyhvcHRzLnRpdGxlIHx8ICcmbmJzcDsnKSsnPC9kaXY+JztcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cyArPSAnPGRpdiBjbGFzcz1cInVpLXdpZGdldC1jb250ZW50IHVpLWRpYWxvZy1jb250ZW50XCI+PC9kaXY+JztcclxuXHRcdFx0XHRzICs9ICc8L2Rpdj4nO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKG9wdHMudGhlbWUpIHtcclxuXHRcdFx0XHRzID0gJzxkaXYgY2xhc3M9XCJibG9ja1VJICcgKyBvcHRzLmJsb2NrTXNnQ2xhc3MgKyAnIGJsb2NrRWxlbWVudCB1aS1kaWFsb2cgdWktd2lkZ2V0IHVpLWNvcm5lci1hbGxcIiBzdHlsZT1cInotaW5kZXg6JysoeisxMCkrJztkaXNwbGF5Om5vbmU7cG9zaXRpb246YWJzb2x1dGVcIj4nO1xyXG5cdFx0XHRcdGlmICggb3B0cy50aXRsZSApIHtcclxuXHRcdFx0XHRcdHMgKz0gJzxkaXYgY2xhc3M9XCJ1aS13aWRnZXQtaGVhZGVyIHVpLWRpYWxvZy10aXRsZWJhciB1aS1jb3JuZXItYWxsIGJsb2NrVGl0bGVcIj4nKyhvcHRzLnRpdGxlIHx8ICcmbmJzcDsnKSsnPC9kaXY+JztcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cyArPSAnPGRpdiBjbGFzcz1cInVpLXdpZGdldC1jb250ZW50IHVpLWRpYWxvZy1jb250ZW50XCI+PC9kaXY+JztcclxuXHRcdFx0XHRzICs9ICc8L2Rpdj4nO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKGZ1bGwpIHtcclxuXHRcdFx0XHRzID0gJzxkaXYgY2xhc3M9XCJibG9ja1VJICcgKyBvcHRzLmJsb2NrTXNnQ2xhc3MgKyAnIGJsb2NrUGFnZVwiIHN0eWxlPVwiei1pbmRleDonKyh6KzEwKSsnO2Rpc3BsYXk6bm9uZTtwb3NpdGlvbjpmaXhlZFwiPjwvZGl2Pic7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0cyA9ICc8ZGl2IGNsYXNzPVwiYmxvY2tVSSAnICsgb3B0cy5ibG9ja01zZ0NsYXNzICsgJyBibG9ja0VsZW1lbnRcIiBzdHlsZT1cInotaW5kZXg6JysoeisxMCkrJztkaXNwbGF5Om5vbmU7cG9zaXRpb246YWJzb2x1dGVcIj48L2Rpdj4nO1xyXG5cdFx0XHR9XHJcblx0XHRcdGx5cjMgPSAkKHMpO1xyXG5cclxuXHRcdFx0Ly8gaWYgd2UgaGF2ZSBhIG1lc3NhZ2UsIHN0eWxlIGl0XHJcblx0XHRcdGlmIChtc2cpIHtcclxuXHRcdFx0XHRpZiAob3B0cy50aGVtZSkge1xyXG5cdFx0XHRcdFx0bHlyMy5jc3ModGhlbWVkQ1NTKTtcclxuXHRcdFx0XHRcdGx5cjMuYWRkQ2xhc3MoJ3VpLXdpZGdldC1jb250ZW50Jyk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2VcclxuXHRcdFx0XHRcdGx5cjMuY3NzKGNzcyk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIHN0eWxlIHRoZSBvdmVybGF5XHJcblx0XHRcdGlmICghb3B0cy50aGVtZSAvKiYmICghb3B0cy5hcHBseVBsYXRmb3JtT3BhY2l0eVJ1bGVzKSovKVxyXG5cdFx0XHRcdGx5cjIuY3NzKG9wdHMub3ZlcmxheUNTUyk7XHJcblx0XHRcdGx5cjIuY3NzKCdwb3NpdGlvbicsIGZ1bGwgPyAnZml4ZWQnIDogJ2Fic29sdXRlJyk7XHJcblxyXG5cdFx0XHQvLyBtYWtlIGlmcmFtZSBsYXllciB0cmFuc3BhcmVudCBpbiBJRVxyXG5cdFx0XHRpZiAobXNpZSB8fCBvcHRzLmZvcmNlSWZyYW1lKVxyXG5cdFx0XHRcdGx5cjEuY3NzKCdvcGFjaXR5JywwLjApO1xyXG5cclxuXHRcdFx0Ly8kKFtseXIxWzBdLGx5cjJbMF0sbHlyM1swXV0pLmFwcGVuZFRvKGZ1bGwgPyAnYm9keScgOiBlbCk7XHJcblx0XHRcdHZhciBsYXllcnMgPSBbbHlyMSxseXIyLGx5cjNdLCAkcGFyID0gZnVsbCA/ICQoJ2JvZHknKSA6ICQoZWwpO1xyXG5cdFx0XHQkLmVhY2gobGF5ZXJzLCBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHR0aGlzLmFwcGVuZFRvKCRwYXIpO1xyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdGlmIChvcHRzLnRoZW1lICYmIG9wdHMuZHJhZ2dhYmxlICYmICQuZm4uZHJhZ2dhYmxlKSB7XHJcblx0XHRcdFx0bHlyMy5kcmFnZ2FibGUoe1xyXG5cdFx0XHRcdFx0aGFuZGxlOiAnLnVpLWRpYWxvZy10aXRsZWJhcicsXHJcblx0XHRcdFx0XHRjYW5jZWw6ICdsaSdcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gaWU3IG11c3QgdXNlIGFic29sdXRlIHBvc2l0aW9uaW5nIGluIHF1aXJrcyBtb2RlIGFuZCB0byBhY2NvdW50IGZvciBhY3RpdmV4IGlzc3VlcyAod2hlbiBzY3JvbGxpbmcpXHJcblx0XHRcdHZhciBleHByID0gc2V0RXhwciAmJiAoISQuc3VwcG9ydC5ib3hNb2RlbCB8fCAkKCdvYmplY3QsZW1iZWQnLCBmdWxsID8gbnVsbCA6IGVsKS5sZW5ndGggPiAwKTtcclxuXHRcdFx0aWYgKGllNiB8fCBleHByKSB7XHJcblx0XHRcdFx0Ly8gZ2l2ZSBib2R5IDEwMCUgaGVpZ2h0XHJcblx0XHRcdFx0aWYgKGZ1bGwgJiYgb3B0cy5hbGxvd0JvZHlTdHJldGNoICYmICQuc3VwcG9ydC5ib3hNb2RlbClcclxuXHRcdFx0XHRcdCQoJ2h0bWwsYm9keScpLmNzcygnaGVpZ2h0JywnMTAwJScpO1xyXG5cclxuXHRcdFx0XHQvLyBmaXggaWU2IGlzc3VlIHdoZW4gYmxvY2tlZCBlbGVtZW50IGhhcyBhIGJvcmRlciB3aWR0aFxyXG5cdFx0XHRcdGlmICgoaWU2IHx8ICEkLnN1cHBvcnQuYm94TW9kZWwpICYmICFmdWxsKSB7XHJcblx0XHRcdFx0XHR2YXIgdCA9IHN6KGVsLCdib3JkZXJUb3BXaWR0aCcpLCBsID0gc3ooZWwsJ2JvcmRlckxlZnRXaWR0aCcpO1xyXG5cdFx0XHRcdFx0dmFyIGZpeFQgPSB0ID8gJygwIC0gJyt0KycpJyA6IDA7XHJcblx0XHRcdFx0XHR2YXIgZml4TCA9IGwgPyAnKDAgLSAnK2wrJyknIDogMDtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIHNpbXVsYXRlIGZpeGVkIHBvc2l0aW9uXHJcblx0XHRcdFx0JC5lYWNoKGxheWVycywgZnVuY3Rpb24oaSxvKSB7XHJcblx0XHRcdFx0XHR2YXIgcyA9IG9bMF0uc3R5bGU7XHJcblx0XHRcdFx0XHRzLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcclxuXHRcdFx0XHRcdGlmIChpIDwgMikge1xyXG5cdFx0XHRcdFx0XHRpZiAoZnVsbClcclxuXHRcdFx0XHRcdFx0XHRzLnNldEV4cHJlc3Npb24oJ2hlaWdodCcsJ01hdGgubWF4KGRvY3VtZW50LmJvZHkuc2Nyb2xsSGVpZ2h0LCBkb2N1bWVudC5ib2R5Lm9mZnNldEhlaWdodCkgLSAoalF1ZXJ5LnN1cHBvcnQuYm94TW9kZWw/MDonK29wdHMucXVpcmtzbW9kZU9mZnNldEhhY2srJykgKyBcInB4XCInKTtcclxuXHRcdFx0XHRcdFx0ZWxzZVxyXG5cdFx0XHRcdFx0XHRcdHMuc2V0RXhwcmVzc2lvbignaGVpZ2h0JywndGhpcy5wYXJlbnROb2RlLm9mZnNldEhlaWdodCArIFwicHhcIicpO1xyXG5cdFx0XHRcdFx0XHRpZiAoZnVsbClcclxuXHRcdFx0XHRcdFx0XHRzLnNldEV4cHJlc3Npb24oJ3dpZHRoJywnalF1ZXJ5LnN1cHBvcnQuYm94TW9kZWwgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoIHx8IGRvY3VtZW50LmJvZHkuY2xpZW50V2lkdGggKyBcInB4XCInKTtcclxuXHRcdFx0XHRcdFx0ZWxzZVxyXG5cdFx0XHRcdFx0XHRcdHMuc2V0RXhwcmVzc2lvbignd2lkdGgnLCd0aGlzLnBhcmVudE5vZGUub2Zmc2V0V2lkdGggKyBcInB4XCInKTtcclxuXHRcdFx0XHRcdFx0aWYgKGZpeEwpIHMuc2V0RXhwcmVzc2lvbignbGVmdCcsIGZpeEwpO1xyXG5cdFx0XHRcdFx0XHRpZiAoZml4VCkgcy5zZXRFeHByZXNzaW9uKCd0b3AnLCBmaXhUKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2UgaWYgKG9wdHMuY2VudGVyWSkge1xyXG5cdFx0XHRcdFx0XHRpZiAoZnVsbCkgcy5zZXRFeHByZXNzaW9uKCd0b3AnLCcoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCB8fCBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodCkgLyAyIC0gKHRoaXMub2Zmc2V0SGVpZ2h0IC8gMikgKyAoYmxhaCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgPyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIDogZG9jdW1lbnQuYm9keS5zY3JvbGxUb3ApICsgXCJweFwiJyk7XHJcblx0XHRcdFx0XHRcdHMubWFyZ2luVG9wID0gMDtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2UgaWYgKCFvcHRzLmNlbnRlclkgJiYgZnVsbCkge1xyXG5cdFx0XHRcdFx0XHR2YXIgdG9wID0gKG9wdHMuY3NzICYmIG9wdHMuY3NzLnRvcCkgPyBwYXJzZUludChvcHRzLmNzcy50b3AsIDEwKSA6IDA7XHJcblx0XHRcdFx0XHRcdHZhciBleHByZXNzaW9uID0gJygoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCA/IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgOiBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCkgKyAnK3RvcCsnKSArIFwicHhcIic7XHJcblx0XHRcdFx0XHRcdHMuc2V0RXhwcmVzc2lvbigndG9wJyxleHByZXNzaW9uKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gc2hvdyB0aGUgbWVzc2FnZVxyXG5cdFx0XHRpZiAobXNnKSB7XHJcblx0XHRcdFx0aWYgKG9wdHMudGhlbWUpXHJcblx0XHRcdFx0XHRseXIzLmZpbmQoJy51aS13aWRnZXQtY29udGVudCcpLmFwcGVuZChtc2cpO1xyXG5cdFx0XHRcdGVsc2VcclxuXHRcdFx0XHRcdGx5cjMuYXBwZW5kKG1zZyk7XHJcblx0XHRcdFx0aWYgKG1zZy5qcXVlcnkgfHwgbXNnLm5vZGVUeXBlKVxyXG5cdFx0XHRcdFx0JChtc2cpLnNob3coKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKChtc2llIHx8IG9wdHMuZm9yY2VJZnJhbWUpICYmIG9wdHMuc2hvd092ZXJsYXkpXHJcblx0XHRcdFx0bHlyMS5zaG93KCk7IC8vIG9wYWNpdHkgaXMgemVyb1xyXG5cdFx0XHRpZiAob3B0cy5mYWRlSW4pIHtcclxuXHRcdFx0XHR2YXIgY2IgPSBvcHRzLm9uQmxvY2sgPyBvcHRzLm9uQmxvY2sgOiBub09wO1xyXG5cdFx0XHRcdHZhciBjYjEgPSAob3B0cy5zaG93T3ZlcmxheSAmJiAhbXNnKSA/IGNiIDogbm9PcDtcclxuXHRcdFx0XHR2YXIgY2IyID0gbXNnID8gY2IgOiBub09wO1xyXG5cdFx0XHRcdGlmIChvcHRzLnNob3dPdmVybGF5KVxyXG5cdFx0XHRcdFx0bHlyMi5fZmFkZUluKG9wdHMuZmFkZUluLCBjYjEpO1xyXG5cdFx0XHRcdGlmIChtc2cpXHJcblx0XHRcdFx0XHRseXIzLl9mYWRlSW4ob3B0cy5mYWRlSW4sIGNiMik7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0aWYgKG9wdHMuc2hvd092ZXJsYXkpXHJcblx0XHRcdFx0XHRseXIyLnNob3coKTtcclxuXHRcdFx0XHRpZiAobXNnKVxyXG5cdFx0XHRcdFx0bHlyMy5zaG93KCk7XHJcblx0XHRcdFx0aWYgKG9wdHMub25CbG9jaylcclxuXHRcdFx0XHRcdG9wdHMub25CbG9jaygpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBiaW5kIGtleSBhbmQgbW91c2UgZXZlbnRzXHJcblx0XHRcdGJpbmQoMSwgZWwsIG9wdHMpO1xyXG5cclxuXHRcdFx0aWYgKGZ1bGwpIHtcclxuXHRcdFx0XHRwYWdlQmxvY2sgPSBseXIzWzBdO1xyXG5cdFx0XHRcdHBhZ2VCbG9ja0VscyA9ICQob3B0cy5mb2N1c2FibGVFbGVtZW50cyxwYWdlQmxvY2spO1xyXG5cdFx0XHRcdGlmIChvcHRzLmZvY3VzSW5wdXQpXHJcblx0XHRcdFx0XHRzZXRUaW1lb3V0KGZvY3VzLCAyMCk7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZVxyXG5cdFx0XHRcdGNlbnRlcihseXIzWzBdLCBvcHRzLmNlbnRlclgsIG9wdHMuY2VudGVyWSk7XHJcblxyXG5cdFx0XHRpZiAob3B0cy50aW1lb3V0KSB7XHJcblx0XHRcdFx0Ly8gYXV0by11bmJsb2NrXHJcblx0XHRcdFx0dmFyIHRvID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRcdGlmIChmdWxsKVxyXG5cdFx0XHRcdFx0XHQkLnVuYmxvY2tVSShvcHRzKTtcclxuXHRcdFx0XHRcdGVsc2VcclxuXHRcdFx0XHRcdFx0JChlbCkudW5ibG9jayhvcHRzKTtcclxuXHRcdFx0XHR9LCBvcHRzLnRpbWVvdXQpO1xyXG5cdFx0XHRcdCQoZWwpLmRhdGEoJ2Jsb2NrVUkudGltZW91dCcsIHRvKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIHJlbW92ZSB0aGUgYmxvY2tcclxuXHRcdGZ1bmN0aW9uIHJlbW92ZShlbCwgb3B0cykge1xyXG5cdFx0XHR2YXIgY291bnQ7XHJcblx0XHRcdHZhciBmdWxsID0gKGVsID09IHdpbmRvdyk7XHJcblx0XHRcdHZhciAkZWwgPSAkKGVsKTtcclxuXHRcdFx0dmFyIGRhdGEgPSAkZWwuZGF0YSgnYmxvY2tVSS5oaXN0b3J5Jyk7XHJcblx0XHRcdHZhciB0byA9ICRlbC5kYXRhKCdibG9ja1VJLnRpbWVvdXQnKTtcclxuXHRcdFx0aWYgKHRvKSB7XHJcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRvKTtcclxuXHRcdFx0XHQkZWwucmVtb3ZlRGF0YSgnYmxvY2tVSS50aW1lb3V0Jyk7XHJcblx0XHRcdH1cclxuXHRcdFx0b3B0cyA9ICQuZXh0ZW5kKHt9LCAkLmJsb2NrVUkuZGVmYXVsdHMsIG9wdHMgfHwge30pO1xyXG5cdFx0XHRiaW5kKDAsIGVsLCBvcHRzKTsgLy8gdW5iaW5kIGV2ZW50c1xyXG5cclxuXHRcdFx0aWYgKG9wdHMub25VbmJsb2NrID09PSBudWxsKSB7XHJcblx0XHRcdFx0b3B0cy5vblVuYmxvY2sgPSAkZWwuZGF0YSgnYmxvY2tVSS5vblVuYmxvY2snKTtcclxuXHRcdFx0XHQkZWwucmVtb3ZlRGF0YSgnYmxvY2tVSS5vblVuYmxvY2snKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0dmFyIGVscztcclxuXHRcdFx0aWYgKGZ1bGwpIC8vIGNyYXp5IHNlbGVjdG9yIHRvIGhhbmRsZSBvZGQgZmllbGQgZXJyb3JzIGluIGllNi83XHJcblx0XHRcdFx0ZWxzID0gJCgnYm9keScpLmNoaWxkcmVuKCkuZmlsdGVyKCcuYmxvY2tVSScpLmFkZCgnYm9keSA+IC5ibG9ja1VJJyk7XHJcblx0XHRcdGVsc2VcclxuXHRcdFx0XHRlbHMgPSAkZWwuZmluZCgnPi5ibG9ja1VJJyk7XHJcblxyXG5cdFx0XHQvLyBmaXggY3Vyc29yIGlzc3VlXHJcblx0XHRcdGlmICggb3B0cy5jdXJzb3JSZXNldCApIHtcclxuXHRcdFx0XHRpZiAoIGVscy5sZW5ndGggPiAxIClcclxuXHRcdFx0XHRcdGVsc1sxXS5zdHlsZS5jdXJzb3IgPSBvcHRzLmN1cnNvclJlc2V0O1xyXG5cdFx0XHRcdGlmICggZWxzLmxlbmd0aCA+IDIgKVxyXG5cdFx0XHRcdFx0ZWxzWzJdLnN0eWxlLmN1cnNvciA9IG9wdHMuY3Vyc29yUmVzZXQ7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmIChmdWxsKVxyXG5cdFx0XHRcdHBhZ2VCbG9jayA9IHBhZ2VCbG9ja0VscyA9IG51bGw7XHJcblxyXG5cdFx0XHRpZiAob3B0cy5mYWRlT3V0KSB7XHJcblx0XHRcdFx0Y291bnQgPSBlbHMubGVuZ3RoO1xyXG5cdFx0XHRcdGVscy5zdG9wKCkuZmFkZU91dChvcHRzLmZhZGVPdXQsIGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdFx0aWYgKCAtLWNvdW50ID09PSAwKVxyXG5cdFx0XHRcdFx0XHRyZXNldChlbHMsZGF0YSxvcHRzLGVsKTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlXHJcblx0XHRcdFx0cmVzZXQoZWxzLCBkYXRhLCBvcHRzLCBlbCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gbW92ZSBibG9ja2luZyBlbGVtZW50IGJhY2sgaW50byB0aGUgRE9NIHdoZXJlIGl0IHN0YXJ0ZWRcclxuXHRcdGZ1bmN0aW9uIHJlc2V0KGVscyxkYXRhLG9wdHMsZWwpIHtcclxuXHRcdFx0dmFyICRlbCA9ICQoZWwpO1xyXG5cdFx0XHRpZiAoICRlbC5kYXRhKCdibG9ja1VJLmlzQmxvY2tlZCcpIClcclxuXHRcdFx0XHRyZXR1cm47XHJcblxyXG5cdFx0XHRlbHMuZWFjaChmdW5jdGlvbihpLG8pIHtcclxuXHRcdFx0XHQvLyByZW1vdmUgdmlhIERPTSBjYWxscyBzbyB3ZSBkb24ndCBsb3NlIGV2ZW50IGhhbmRsZXJzXHJcblx0XHRcdFx0aWYgKHRoaXMucGFyZW50Tm9kZSlcclxuXHRcdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzKTtcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHRpZiAoZGF0YSAmJiBkYXRhLmVsKSB7XHJcblx0XHRcdFx0ZGF0YS5lbC5zdHlsZS5kaXNwbGF5ID0gZGF0YS5kaXNwbGF5O1xyXG5cdFx0XHRcdGRhdGEuZWwuc3R5bGUucG9zaXRpb24gPSBkYXRhLnBvc2l0aW9uO1xyXG5cdFx0XHRcdGlmIChkYXRhLnBhcmVudClcclxuXHRcdFx0XHRcdGRhdGEucGFyZW50LmFwcGVuZENoaWxkKGRhdGEuZWwpO1xyXG5cdFx0XHRcdCRlbC5yZW1vdmVEYXRhKCdibG9ja1VJLmhpc3RvcnknKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKCRlbC5kYXRhKCdibG9ja1VJLnN0YXRpYycpKSB7XHJcblx0XHRcdFx0JGVsLmNzcygncG9zaXRpb24nLCAnc3RhdGljJyk7IC8vICMyMlxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAodHlwZW9mIG9wdHMub25VbmJsb2NrID09ICdmdW5jdGlvbicpXHJcblx0XHRcdFx0b3B0cy5vblVuYmxvY2soZWwsb3B0cyk7XHJcblxyXG5cdFx0XHQvLyBmaXggaXNzdWUgaW4gU2FmYXJpIDYgd2hlcmUgYmxvY2sgYXJ0aWZhY3RzIHJlbWFpbiB1bnRpbCByZWZsb3dcclxuXHRcdFx0dmFyIGJvZHkgPSAkKGRvY3VtZW50LmJvZHkpLCB3ID0gYm9keS53aWR0aCgpLCBjc3NXID0gYm9keVswXS5zdHlsZS53aWR0aDtcclxuXHRcdFx0Ym9keS53aWR0aCh3LTEpLndpZHRoKHcpO1xyXG5cdFx0XHRib2R5WzBdLnN0eWxlLndpZHRoID0gY3NzVztcclxuXHRcdH1cclxuXHJcblx0XHQvLyBiaW5kL3VuYmluZCB0aGUgaGFuZGxlclxyXG5cdFx0ZnVuY3Rpb24gYmluZChiLCBlbCwgb3B0cykge1xyXG5cdFx0XHR2YXIgZnVsbCA9IGVsID09IHdpbmRvdywgJGVsID0gJChlbCk7XHJcblxyXG5cdFx0XHQvLyBkb24ndCBib3RoZXIgdW5iaW5kaW5nIGlmIHRoZXJlIGlzIG5vdGhpbmcgdG8gdW5iaW5kXHJcblx0XHRcdGlmICghYiAmJiAoZnVsbCAmJiAhcGFnZUJsb2NrIHx8ICFmdWxsICYmICEkZWwuZGF0YSgnYmxvY2tVSS5pc0Jsb2NrZWQnKSkpXHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cclxuXHRcdFx0JGVsLmRhdGEoJ2Jsb2NrVUkuaXNCbG9ja2VkJywgYik7XHJcblxyXG5cdFx0XHQvLyBkb24ndCBiaW5kIGV2ZW50cyB3aGVuIG92ZXJsYXkgaXMgbm90IGluIHVzZSBvciBpZiBiaW5kRXZlbnRzIGlzIGZhbHNlXHJcblx0XHRcdGlmICghZnVsbCB8fCAhb3B0cy5iaW5kRXZlbnRzIHx8IChiICYmICFvcHRzLnNob3dPdmVybGF5KSlcclxuXHRcdFx0XHRyZXR1cm47XHJcblxyXG5cdFx0XHQvLyBiaW5kIGFuY2hvcnMgYW5kIGlucHV0cyBmb3IgbW91c2UgYW5kIGtleSBldmVudHNcclxuXHRcdFx0dmFyIGV2ZW50cyA9ICdtb3VzZWRvd24gbW91c2V1cCBrZXlkb3duIGtleXByZXNzIGtleXVwIHRvdWNoc3RhcnQgdG91Y2hlbmQgdG91Y2htb3ZlJztcclxuXHRcdFx0aWYgKGIpXHJcblx0XHRcdFx0JChkb2N1bWVudCkuYmluZChldmVudHMsIG9wdHMsIGhhbmRsZXIpO1xyXG5cdFx0XHRlbHNlXHJcblx0XHRcdFx0JChkb2N1bWVudCkudW5iaW5kKGV2ZW50cywgaGFuZGxlcik7XHJcblxyXG5cdFx0Ly8gZm9ybWVyIGltcGwuLi5cclxuXHRcdC8vXHRcdHZhciAkZSA9ICQoJ2EsOmlucHV0Jyk7XHJcblx0XHQvL1x0XHRiID8gJGUuYmluZChldmVudHMsIG9wdHMsIGhhbmRsZXIpIDogJGUudW5iaW5kKGV2ZW50cywgaGFuZGxlcik7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gZXZlbnQgaGFuZGxlciB0byBzdXBwcmVzcyBrZXlib2FyZC9tb3VzZSBldmVudHMgd2hlbiBibG9ja2luZ1xyXG5cdFx0ZnVuY3Rpb24gaGFuZGxlcihlKSB7XHJcblx0XHRcdC8vIGFsbG93IHRhYiBuYXZpZ2F0aW9uIChjb25kaXRpb25hbGx5KVxyXG5cdFx0XHRpZiAoZS50eXBlID09PSAna2V5ZG93bicgJiYgZS5rZXlDb2RlICYmIGUua2V5Q29kZSA9PSA5KSB7XHJcblx0XHRcdFx0aWYgKHBhZ2VCbG9jayAmJiBlLmRhdGEuY29uc3RyYWluVGFiS2V5KSB7XHJcblx0XHRcdFx0XHR2YXIgZWxzID0gcGFnZUJsb2NrRWxzO1xyXG5cdFx0XHRcdFx0dmFyIGZ3ZCA9ICFlLnNoaWZ0S2V5ICYmIGUudGFyZ2V0ID09PSBlbHNbZWxzLmxlbmd0aC0xXTtcclxuXHRcdFx0XHRcdHZhciBiYWNrID0gZS5zaGlmdEtleSAmJiBlLnRhcmdldCA9PT0gZWxzWzBdO1xyXG5cdFx0XHRcdFx0aWYgKGZ3ZCB8fCBiYWNrKSB7XHJcblx0XHRcdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtmb2N1cyhiYWNrKTt9LDEwKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHR2YXIgb3B0cyA9IGUuZGF0YTtcclxuXHRcdFx0dmFyIHRhcmdldCA9ICQoZS50YXJnZXQpO1xyXG5cdFx0XHRpZiAodGFyZ2V0Lmhhc0NsYXNzKCdibG9ja092ZXJsYXknKSAmJiBvcHRzLm9uT3ZlcmxheUNsaWNrKVxyXG5cdFx0XHRcdG9wdHMub25PdmVybGF5Q2xpY2soZSk7XHJcblxyXG5cdFx0XHQvLyBhbGxvdyBldmVudHMgd2l0aGluIHRoZSBtZXNzYWdlIGNvbnRlbnRcclxuXHRcdFx0aWYgKHRhcmdldC5wYXJlbnRzKCdkaXYuJyArIG9wdHMuYmxvY2tNc2dDbGFzcykubGVuZ3RoID4gMClcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHJcblx0XHRcdC8vIGFsbG93IGV2ZW50cyBmb3IgY29udGVudCB0aGF0IGlzIG5vdCBiZWluZyBibG9ja2VkXHJcblx0XHRcdHJldHVybiB0YXJnZXQucGFyZW50cygpLmNoaWxkcmVuKCkuZmlsdGVyKCdkaXYuYmxvY2tVSScpLmxlbmd0aCA9PT0gMDtcclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiBmb2N1cyhiYWNrKSB7XHJcblx0XHRcdGlmICghcGFnZUJsb2NrRWxzKVxyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0dmFyIGUgPSBwYWdlQmxvY2tFbHNbYmFjaz09PXRydWUgPyBwYWdlQmxvY2tFbHMubGVuZ3RoLTEgOiAwXTtcclxuXHRcdFx0aWYgKGUpXHJcblx0XHRcdFx0ZS5mb2N1cygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGZ1bmN0aW9uIGNlbnRlcihlbCwgeCwgeSkge1xyXG5cdFx0XHR2YXIgcCA9IGVsLnBhcmVudE5vZGUsIHMgPSBlbC5zdHlsZTtcclxuXHRcdFx0dmFyIGwgPSAoKHAub2Zmc2V0V2lkdGggLSBlbC5vZmZzZXRXaWR0aCkvMikgLSBzeihwLCdib3JkZXJMZWZ0V2lkdGgnKTtcclxuXHRcdFx0dmFyIHQgPSAoKHAub2Zmc2V0SGVpZ2h0IC0gZWwub2Zmc2V0SGVpZ2h0KS8yKSAtIHN6KHAsJ2JvcmRlclRvcFdpZHRoJyk7XHJcblx0XHRcdGlmICh4KSBzLmxlZnQgPSBsID4gMCA/IChsKydweCcpIDogJzAnO1xyXG5cdFx0XHRpZiAoeSkgcy50b3AgID0gdCA+IDAgPyAodCsncHgnKSA6ICcwJztcclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiBzeihlbCwgcCkge1xyXG5cdFx0XHRyZXR1cm4gcGFyc2VJbnQoJC5jc3MoZWwscCksMTApfHwwO1xyXG5cdFx0fVxyXG5cclxuXHR9XHJcblxyXG5cclxuXHQvKmdsb2JhbCBkZWZpbmU6dHJ1ZSAqL1xyXG5cdGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgJiYgZGVmaW5lLmFtZC5qUXVlcnkpIHtcclxuXHRcdGRlZmluZShbJ2pxdWVyeSddLCBzZXR1cCk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHNldHVwKGpRdWVyeSk7XHJcblx0fVxyXG5cclxufSkoKTtcclxuIl0sImZpbGUiOiJqcXVlcnkuYmxvY2tVSS5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.min.js new file mode 100644 index 000000000..fa14fb14a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.blockUI.min.js @@ -0,0 +1 @@ +!function(){"use strict";function e(e){function t(t,n){var s,h,k=t==window,y=n&&void 0!==n.message?n.message:void 0;if(n=e.extend({},e.blockUI.defaults,n||{}),!n.ignoreIfBlocked||!e(t).data("blockUI.isBlocked")){if(n.overlayCSS=e.extend({},e.blockUI.defaults.overlayCSS,n.overlayCSS||{}),s=e.extend({},e.blockUI.defaults.css,n.css||{}),n.onOverlayClick&&(n.overlayCSS.cursor="pointer"),h=e.extend({},e.blockUI.defaults.themedCSS,n.themedCSS||{}),y=void 0===y?n.message:y,k&&p&&o(window,{fadeOut:0}),y&&"string"!=typeof y&&(y.parentNode||y.jquery)){var m=y.jquery?y[0]:y,v={};e(t).data("blockUI.history",v),v.el=m,v.parent=m.parentNode,v.display=m.style.display,v.position=m.style.position,v.parent&&v.parent.removeChild(m)}e(t).data("blockUI.onUnblock",n.onUnblock);var g,I,w,U,x=n.baseZ;g=e(r||n.forceIframe?'':''),I=e(n.theme?'':''),n.theme&&k?(U='',n.title&&(U+=''+(n.title||" ")+""),U+='',U+=""):n.theme?(U='',n.title&&(U+=''+(n.title||" ")+""),U+='',U+=""):U=k?'':'',w=e(U),y&&(n.theme?(w.css(h),w.addClass("ui-widget-content")):w.css(s)),n.theme||I.css(n.overlayCSS),I.css("position",k?"fixed":"absolute"),(r||n.forceIframe)&&g.css("opacity",0);var C=[g,I,w],S=e(k?"body":t);e.each(C,function(){this.appendTo(S)}),n.theme&&n.draggable&&e.fn.draggable&&w.draggable({handle:".ui-dialog-titlebar",cancel:"li"});var O=f&&(!e.support.boxModel||e("object,embed",k?null:t).length>0);if(u||O){if(k&&n.allowBodyStretch&&e.support.boxModel&&e("html,body").css("height","100%"),(u||!e.support.boxModel)&&!k)var E=d(t,"borderTopWidth"),T=d(t,"borderLeftWidth"),M=E?"(0 - "+E+")":0,B=T?"(0 - "+T+")":0;e.each(C,function(e,t){var o=t[0].style;if(o.position="absolute",2>e)k?o.setExpression("height","Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:"+n.quirksmodeOffsetHack+') + "px"'):o.setExpression("height",'this.parentNode.offsetHeight + "px"'),k?o.setExpression("width",'jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'):o.setExpression("width",'this.parentNode.offsetWidth + "px"'),B&&o.setExpression("left",B),M&&o.setExpression("top",M);else if(n.centerY)k&&o.setExpression("top",'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'),o.marginTop=0;else if(!n.centerY&&k){var i=n.css&&n.css.top?parseInt(n.css.top,10):0,s="((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "+i+') + "px"';o.setExpression("top",s)}})}if(y&&(n.theme?w.find(".ui-widget-content").append(y):w.append(y),(y.jquery||y.nodeType)&&e(y).show()),(r||n.forceIframe)&&n.showOverlay&&g.show(),n.fadeIn){var j=n.onBlock?n.onBlock:c,H=n.showOverlay&&!y?j:c,z=y?j:c;n.showOverlay&&I._fadeIn(n.fadeIn,H),y&&w._fadeIn(n.fadeIn,z)}else n.showOverlay&&I.show(),y&&w.show(),n.onBlock&&n.onBlock();if(i(1,t,n),k?(p=w[0],b=e(n.focusableElements,p),n.focusInput&&setTimeout(l,20)):a(w[0],n.centerX,n.centerY),n.timeout){var W=setTimeout(function(){k?e.unblockUI(n):e(t).unblock(n)},n.timeout);e(t).data("blockUI.timeout",W)}}}function o(t,o){var s,l=t==window,a=e(t),d=a.data("blockUI.history"),c=a.data("blockUI.timeout");c&&(clearTimeout(c),a.removeData("blockUI.timeout")),o=e.extend({},e.blockUI.defaults,o||{}),i(0,t,o),null===o.onUnblock&&(o.onUnblock=a.data("blockUI.onUnblock"),a.removeData("blockUI.onUnblock"));var r;r=l?e("body").children().filter(".blockUI").add("body > .blockUI"):a.find(">.blockUI"),o.cursorReset&&(r.length>1&&(r[1].style.cursor=o.cursorReset),r.length>2&&(r[2].style.cursor=o.cursorReset)),l&&(p=b=null),o.fadeOut?(s=r.length,r.stop().fadeOut(o.fadeOut,function(){0===--s&&n(r,d,o,t)})):n(r,d,o,t)}function n(t,o,n,i){var s=e(i);if(!s.data("blockUI.isBlocked")){t.each(function(e,t){this.parentNode&&this.parentNode.removeChild(this)}),o&&o.el&&(o.el.style.display=o.display,o.el.style.position=o.position,o.parent&&o.parent.appendChild(o.el),s.removeData("blockUI.history")),s.data("blockUI.static")&&s.css("position","static"),"function"==typeof n.onUnblock&&n.onUnblock(i,n);var l=e(document.body),a=l.width(),d=l[0].style.width;l.width(a-1).width(a),l[0].style.width=d}}function i(t,o,n){var i=o==window,l=e(o);if((t||(!i||p)&&(i||l.data("blockUI.isBlocked")))&&(l.data("blockUI.isBlocked",t),i&&n.bindEvents&&(!t||n.showOverlay))){var a="mousedown mouseup keydown keypress keyup touchstart touchend touchmove";t?e(document).bind(a,n,s):e(document).unbind(a,s)}}function s(t){if("keydown"===t.type&&t.keyCode&&9==t.keyCode&&p&&t.data.constrainTabKey){var o=b,n=!t.shiftKey&&t.target===o[o.length-1],i=t.shiftKey&&t.target===o[0];if(n||i)return setTimeout(function(){l(i)},10),!1}var s=t.data,a=e(t.target);return a.hasClass("blockOverlay")&&s.onOverlayClick&&s.onOverlayClick(t),a.parents("div."+s.blockMsgClass).length>0?!0:0===a.parents().children().filter("div.blockUI").length}function l(e){if(b){var t=b[e===!0?b.length-1:0];t&&t.focus()}}function a(e,t,o){var n=e.parentNode,i=e.style,s=(n.offsetWidth-e.offsetWidth)/2-d(n,"borderLeftWidth"),l=(n.offsetHeight-e.offsetHeight)/2-d(n,"borderTopWidth");t&&(i.left=s>0?s+"px":"0"),o&&(i.top=l>0?l+"px":"0")}function d(t,o){return parseInt(e.css(t,o),10)||0}e.fn._fadeIn=e.fn.fadeIn;var c=e.noop||function(){},r=/MSIE/.test(navigator.userAgent),u=/MSIE 6.0/.test(navigator.userAgent)&&!/MSIE 8.0/.test(navigator.userAgent),f=(document.documentMode||0,e.isFunction(document.createElement("div").style.setExpression));e.blockUI=function(e){t(window,e)},e.unblockUI=function(e){o(window,e)},e.growlUI=function(t,o,n,i){var s=e('');t&&s.append(""+t+""),o&&s.append(""+o+""),void 0===n&&(n=3e3);var l=function(t){t=t||{},e.blockUI({message:s,fadeIn:"undefined"!=typeof t.fadeIn?t.fadeIn:700,fadeOut:"undefined"!=typeof t.fadeOut?t.fadeOut:1e3,timeout:"undefined"!=typeof t.timeout?t.timeout:n,centerY:!1,showOverlay:!1,onUnblock:i,css:e.blockUI.defaults.growlCSS})};l();s.css("opacity");s.mouseover(function(){l({fadeIn:0,timeout:3e4});var t=e(".blockMsg");t.stop(),t.fadeTo(300,1)}).mouseout(function(){e(".blockMsg").fadeOut(1e3)})},e.fn.block=function(o){if(this[0]===window)return e.blockUI(o),this;var n=e.extend({},e.blockUI.defaults,o||{});return this.each(function(){var t=e(this);n.ignoreIfBlocked&&t.data("blockUI.isBlocked")||t.unblock({fadeOut:0})}),this.each(function(){"static"==e.css(this,"position")&&(this.style.position="relative",e(this).data("blockUI.static",!0)),this.style.zoom=1,t(this,o)})},e.fn.unblock=function(t){return this[0]===window?(e.unblockUI(t),this):this.each(function(){o(this,t)})},e.blockUI.version=2.66,e.blockUI.defaults={message:"Please wait...",title:null,draggable:!0,theme:!1,css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px solid #aaa",backgroundColor:"#fff",cursor:"wait"},themedCSS:{width:"30%",top:"40%",left:"35%"},overlayCSS:{backgroundColor:"#000",opacity:.6,cursor:"wait"},cursorReset:"default",growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:.6,cursor:"default",color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px","border-radius":"10px"},iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",forceIframe:!1,baseZ:1e3,centerX:!0,centerY:!0,allowBodyStretch:!0,bindEvents:!0,constrainTabKey:!0,fadeIn:200,fadeOut:400,timeout:0,showOverlay:!0,focusInput:!0,focusableElements:":input:enabled:visible",onBlock:null,onUnblock:null,onOverlayClick:null,quirksmodeOffsetHack:4,blockMsgClass:"blockMsg",ignoreIfBlocked:!1};var p=null,b=[]}"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],e):e(jQuery)}(); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.js new file mode 100644 index 000000000..464c2e0c0 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.js @@ -0,0 +1,174 @@ +/* + * jQuery File Upload Processing Plugin 1.3.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/* jshint nomen:false */ +/* global define, window */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + './jquery.fileupload' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery + ); + } +}(function ($) { + 'use strict'; + + var originalAdd = $.blueimp.fileupload.prototype.options.add; + + // The File Upload Processing plugin extends the fileupload widget + // with file processing functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The list of processing actions: + processQueue: [ + /* + { + action: 'log', + type: 'debug' + } + */ + ], + add: function (e, data) { + var $this = $(this); + data.process(function () { + return $this.fileupload('process', data); + }); + originalAdd.call(this, e, data); + } + }, + + processActions: { + /* + log: function (data, options) { + console[options.type]( + 'Processing "' + data.files[data.index].name + '"' + ); + } + */ + }, + + _processFile: function (data, originalData) { + var that = this, + dfd = $.Deferred().resolveWith(that, [data]), + chain = dfd.promise(); + this._trigger('process', null, data); + $.each(data.processQueue, function (i, settings) { + var func = function (data) { + if (originalData.errorThrown) { + return $.Deferred() + .rejectWith(that, [originalData]).promise(); + } + return that.processActions[settings.action].call( + that, + data, + settings + ); + }; + chain = chain.pipe(func, settings.always && func); + }); + chain + .done(function () { + that._trigger('processdone', null, data); + that._trigger('processalways', null, data); + }) + .fail(function () { + that._trigger('processfail', null, data); + that._trigger('processalways', null, data); + }); + return chain; + }, + + // Replaces the settings of each processQueue item that + // are strings starting with an "@", using the remaining + // substring as key for the option map, + // e.g. "@autoUpload" is replaced with options.autoUpload: + _transformProcessQueue: function (options) { + var processQueue = []; + $.each(options.processQueue, function () { + var settings = {}, + action = this.action, + prefix = this.prefix === true ? action : this.prefix; + $.each(this, function (key, value) { + if ($.type(value) === 'string' && + value.charAt(0) === '@') { + settings[key] = options[ + value.slice(1) || (prefix ? prefix + + key.charAt(0).toUpperCase() + key.slice(1) : key) + ]; + } else { + settings[key] = value; + } + + }); + processQueue.push(settings); + }); + options.processQueue = processQueue; + }, + + // Returns the number of files currently in the processsing queue: + processing: function () { + return this._processing; + }, + + // Processes the files given as files property of the data parameter, + // returns a Promise object that allows to bind callbacks: + process: function (data) { + var that = this, + options = $.extend({}, this.options, data); + if (options.processQueue && options.processQueue.length) { + this._transformProcessQueue(options); + if (this._processing === 0) { + this._trigger('processstart'); + } + $.each(data.files, function (index) { + var opts = index ? $.extend({}, options) : options, + func = function () { + if (data.errorThrown) { + return $.Deferred() + .rejectWith(that, [data]).promise(); + } + return that._processFile(opts, data); + }; + opts.index = index; + that._processing += 1; + that._processingQueue = that._processingQueue.pipe(func, func) + .always(function () { + that._processing -= 1; + if (that._processing === 0) { + that._trigger('processstop'); + } + }); + }); + } + return this._processingQueue; + }, + + _create: function () { + this._super(); + this._processing = 0; + this._processingQueue = $.Deferred().resolveWith(this) + .promise(); + } + + }); + +})); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnkuZmlsZXVwbG9hZC1wcm9jZXNzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIGpRdWVyeSBGaWxlIFVwbG9hZCBQcm9jZXNzaW5nIFBsdWdpbiAxLjMuMFxyXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYmx1ZWltcC9qUXVlcnktRmlsZS1VcGxvYWRcclxuICpcclxuICogQ29weXJpZ2h0IDIwMTIsIFNlYmFzdGlhbiBUc2NoYW5cclxuICogaHR0cHM6Ly9ibHVlaW1wLm5ldFxyXG4gKlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2U6XHJcbiAqIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlUXHJcbiAqL1xyXG5cclxuLyoganNoaW50IG5vbWVuOmZhbHNlICovXHJcbi8qIGdsb2JhbCBkZWZpbmUsIHdpbmRvdyAqL1xyXG5cclxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XHJcbiAgICAndXNlIHN0cmljdCc7XHJcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XHJcbiAgICAgICAgLy8gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIEFNRCBtb2R1bGU6XHJcbiAgICAgICAgZGVmaW5lKFtcclxuICAgICAgICAgICAgJ2pxdWVyeScsXHJcbiAgICAgICAgICAgICcuL2pxdWVyeS5maWxldXBsb2FkJ1xyXG4gICAgICAgIF0sIGZhY3RvcnkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBCcm93c2VyIGdsb2JhbHM6XHJcbiAgICAgICAgZmFjdG9yeShcclxuICAgICAgICAgICAgd2luZG93LmpRdWVyeVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0oZnVuY3Rpb24gKCQpIHtcclxuICAgICd1c2Ugc3RyaWN0JztcclxuXHJcbiAgICB2YXIgb3JpZ2luYWxBZGQgPSAkLmJsdWVpbXAuZmlsZXVwbG9hZC5wcm90b3R5cGUub3B0aW9ucy5hZGQ7XHJcblxyXG4gICAgLy8gVGhlIEZpbGUgVXBsb2FkIFByb2Nlc3NpbmcgcGx1Z2luIGV4dGVuZHMgdGhlIGZpbGV1cGxvYWQgd2lkZ2V0XHJcbiAgICAvLyB3aXRoIGZpbGUgcHJvY2Vzc2luZyBmdW5jdGlvbmFsaXR5OlxyXG4gICAgJC53aWRnZXQoJ2JsdWVpbXAuZmlsZXVwbG9hZCcsICQuYmx1ZWltcC5maWxldXBsb2FkLCB7XHJcblxyXG4gICAgICAgIG9wdGlvbnM6IHtcclxuICAgICAgICAgICAgLy8gVGhlIGxpc3Qgb2YgcHJvY2Vzc2luZyBhY3Rpb25zOlxyXG4gICAgICAgICAgICBwcm9jZXNzUXVldWU6IFtcclxuICAgICAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiAnbG9nJyxcclxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZGVidWcnXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICBhZGQ6IGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgJHRoaXMgPSAkKHRoaXMpO1xyXG4gICAgICAgICAgICAgICAgZGF0YS5wcm9jZXNzKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJHRoaXMuZmlsZXVwbG9hZCgncHJvY2VzcycsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICBvcmlnaW5hbEFkZC5jYWxsKHRoaXMsIGUsIGRhdGEpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgcHJvY2Vzc0FjdGlvbnM6IHtcclxuICAgICAgICAgICAgLypcclxuICAgICAgICAgICAgbG9nOiBmdW5jdGlvbiAoZGF0YSwgb3B0aW9ucykge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZVtvcHRpb25zLnR5cGVdKFxyXG4gICAgICAgICAgICAgICAgICAgICdQcm9jZXNzaW5nIFwiJyArIGRhdGEuZmlsZXNbZGF0YS5pbmRleF0ubmFtZSArICdcIidcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKi9cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfcHJvY2Vzc0ZpbGU6IGZ1bmN0aW9uIChkYXRhLCBvcmlnaW5hbERhdGEpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgICAgICAgZGZkID0gJC5EZWZlcnJlZCgpLnJlc29sdmVXaXRoKHRoYXQsIFtkYXRhXSksXHJcbiAgICAgICAgICAgICAgICBjaGFpbiA9IGRmZC5wcm9taXNlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXIoJ3Byb2Nlc3MnLCBudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgJC5lYWNoKGRhdGEucHJvY2Vzc1F1ZXVlLCBmdW5jdGlvbiAoaSwgc2V0dGluZ3MpIHtcclxuICAgICAgICAgICAgICAgIHZhciBmdW5jID0gZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAob3JpZ2luYWxEYXRhLmVycm9yVGhyb3duKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkLkRlZmVycmVkKClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVqZWN0V2l0aCh0aGF0LCBbb3JpZ2luYWxEYXRhXSkucHJvbWlzZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5wcm9jZXNzQWN0aW9uc1tzZXR0aW5ncy5hY3Rpb25dLmNhbGwoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldHRpbmdzXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICBjaGFpbiA9IGNoYWluLnBpcGUoZnVuYywgc2V0dGluZ3MuYWx3YXlzICYmIGZ1bmMpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgY2hhaW5cclxuICAgICAgICAgICAgICAgIC5kb25lKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll90cmlnZ2VyKCdwcm9jZXNzZG9uZScsIG51bGwsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuX3RyaWdnZXIoJ3Byb2Nlc3NhbHdheXMnLCBudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAuZmFpbChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fdHJpZ2dlcigncHJvY2Vzc2ZhaWwnLCBudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll90cmlnZ2VyKCdwcm9jZXNzYWx3YXlzJywgbnVsbCwgZGF0YSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIGNoYWluO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIFJlcGxhY2VzIHRoZSBzZXR0aW5ncyBvZiBlYWNoIHByb2Nlc3NRdWV1ZSBpdGVtIHRoYXRcclxuICAgICAgICAvLyBhcmUgc3RyaW5ncyBzdGFydGluZyB3aXRoIGFuIFwiQFwiLCB1c2luZyB0aGUgcmVtYWluaW5nXHJcbiAgICAgICAgLy8gc3Vic3RyaW5nIGFzIGtleSBmb3IgdGhlIG9wdGlvbiBtYXAsXHJcbiAgICAgICAgLy8gZS5nLiBcIkBhdXRvVXBsb2FkXCIgaXMgcmVwbGFjZWQgd2l0aCBvcHRpb25zLmF1dG9VcGxvYWQ6XHJcbiAgICAgICAgX3RyYW5zZm9ybVByb2Nlc3NRdWV1ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdmFyIHByb2Nlc3NRdWV1ZSA9IFtdO1xyXG4gICAgICAgICAgICAkLmVhY2gob3B0aW9ucy5wcm9jZXNzUXVldWUsIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBzZXR0aW5ncyA9IHt9LFxyXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbiA9IHRoaXMuYWN0aW9uLFxyXG4gICAgICAgICAgICAgICAgICAgIHByZWZpeCA9IHRoaXMucHJlZml4ID09PSB0cnVlID8gYWN0aW9uIDogdGhpcy5wcmVmaXg7XHJcbiAgICAgICAgICAgICAgICAkLmVhY2godGhpcywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoJC50eXBlKHZhbHVlKSA9PT0gJ3N0cmluZycgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLmNoYXJBdCgwKSA9PT0gJ0AnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldHRpbmdzW2tleV0gPSBvcHRpb25zW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuc2xpY2UoMSkgfHwgKHByZWZpeCA/IHByZWZpeCArXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnNsaWNlKDEpIDoga2V5KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBdO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldHRpbmdzW2tleV0gPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzUXVldWUucHVzaChzZXR0aW5ncyk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBvcHRpb25zLnByb2Nlc3NRdWV1ZSA9IHByb2Nlc3NRdWV1ZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICAvLyBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZmlsZXMgY3VycmVudGx5IGluIHRoZSBwcm9jZXNzc2luZyBxdWV1ZTpcclxuICAgICAgICBwcm9jZXNzaW5nOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzaW5nO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIFByb2Nlc3NlcyB0aGUgZmlsZXMgZ2l2ZW4gYXMgZmlsZXMgcHJvcGVydHkgb2YgdGhlIGRhdGEgcGFyYW1ldGVyLFxyXG4gICAgICAgIC8vIHJldHVybnMgYSBQcm9taXNlIG9iamVjdCB0aGF0IGFsbG93cyB0byBiaW5kIGNhbGxiYWNrczpcclxuICAgICAgICBwcm9jZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xyXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAgICAgICBvcHRpb25zID0gJC5leHRlbmQoe30sIHRoaXMub3B0aW9ucywgZGF0YSk7XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnByb2Nlc3NRdWV1ZSAmJiBvcHRpb25zLnByb2Nlc3NRdWV1ZS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zZm9ybVByb2Nlc3NRdWV1ZShvcHRpb25zKTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9wcm9jZXNzaW5nID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlcigncHJvY2Vzc3N0YXJ0Jyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAkLmVhY2goZGF0YS5maWxlcywgZnVuY3Rpb24gKGluZGV4KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9wdHMgPSBpbmRleCA/ICQuZXh0ZW5kKHt9LCBvcHRpb25zKSA6IG9wdGlvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5lcnJvclRocm93bikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkLkRlZmVycmVkKClcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZWplY3RXaXRoKHRoYXQsIFtkYXRhXSkucHJvbWlzZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQuX3Byb2Nlc3NGaWxlKG9wdHMsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgIG9wdHMuaW5kZXggPSBpbmRleDtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll9wcm9jZXNzaW5nICs9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fcHJvY2Vzc2luZ1F1ZXVlID0gdGhhdC5fcHJvY2Vzc2luZ1F1ZXVlLnBpcGUoZnVuYywgZnVuYylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFsd2F5cyhmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9wcm9jZXNzaW5nIC09IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5fcHJvY2Vzc2luZyA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX3RyaWdnZXIoJ3Byb2Nlc3NzdG9wJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Byb2Nlc3NpbmdRdWV1ZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfY3JlYXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3N1cGVyKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NpbmcgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLl9wcm9jZXNzaW5nUXVldWUgPSAkLkRlZmVycmVkKCkucmVzb2x2ZVdpdGgodGhpcylcclxuICAgICAgICAgICAgICAgIC5wcm9taXNlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIH0pO1xyXG5cclxufSkpO1xyXG4iXSwiZmlsZSI6ImpxdWVyeS5maWxldXBsb2FkLXByb2Nlc3MuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.min.js new file mode 100644 index 000000000..beee5454a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-process.min.js @@ -0,0 +1 @@ +!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./jquery.fileupload"],e):e(window.jQuery)}(function(e){"use strict";var s=e.blueimp.fileupload.prototype.options.add;e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{processQueue:[],add:function(r,i){var o=e(this);i.process(function(){return o.fileupload("process",i)}),s.call(this,r,i)}},processActions:{},_processFile:function(s,r){var i=this,o=e.Deferred().resolveWith(i,[s]),t=o.promise();return this._trigger("process",null,s),e.each(s.processQueue,function(s,o){var n=function(s){return r.errorThrown?e.Deferred().rejectWith(i,[r]).promise():i.processActions[o.action].call(i,s,o)};t=t.pipe(n,o.always&&n)}),t.done(function(){i._trigger("processdone",null,s),i._trigger("processalways",null,s)}).fail(function(){i._trigger("processfail",null,s),i._trigger("processalways",null,s)}),t},_transformProcessQueue:function(s){var r=[];e.each(s.processQueue,function(){var i={},o=this.action,t=this.prefix===!0?o:this.prefix;e.each(this,function(r,o){i[r]="string"===e.type(o)&&"@"===o.charAt(0)?s[o.slice(1)||(t?t+r.charAt(0).toUpperCase()+r.slice(1):r)]:o}),r.push(i)}),s.processQueue=r},processing:function(){return this._processing},process:function(s){var r=this,i=e.extend({},this.options,s);return i.processQueue&&i.processQueue.length&&(this._transformProcessQueue(i),0===this._processing&&this._trigger("processstart"),e.each(s.files,function(o){var t=o?e.extend({},i):i,n=function(){return s.errorThrown?e.Deferred().rejectWith(r,[s]).promise():r._processFile(t,s)};t.index=o,r._processing+=1,r._processingQueue=r._processingQueue.pipe(n,n).always(function(){r._processing-=1,0===r._processing&&r._trigger("processstop")})})),this._processingQueue},_create:function(){this._super(),this._processing=0,this._processingQueue=e.Deferred().resolveWith(this).promise()}})}); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.js new file mode 100644 index 000000000..4a522257a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.js @@ -0,0 +1,121 @@ +/* + * jQuery File Upload Validation Plugin 1.1.2 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/* global define, window */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + './jquery.fileupload-process' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery + ); + } +}(function ($) { + 'use strict'; + + // Append to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.push( + { + action: 'validate', + // Always trigger this action, + // even if the previous action was rejected: + always: true, + // Options taken from the global options map: + acceptFileTypes: '@', + maxFileSize: '@', + minFileSize: '@', + maxNumberOfFiles: '@', + disabled: '@disableValidation' + } + ); + + // The File Upload Validation plugin extends the fileupload widget + // with file validation functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + /* + // The regular expression for allowed file types, matches + // against either file type or file name: + acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, + // The maximum allowed file size in bytes: + maxFileSize: 10000000, // 10 MB + // The minimum allowed file size in bytes: + minFileSize: undefined, // No minimal file size + // The limit of files to be uploaded: + maxNumberOfFiles: 10, + */ + + // Function returning the current number of files, + // has to be overriden for maxNumberOfFiles validation: + getNumberOfFiles: $.noop, + + // Error and info messages: + messages: { + maxNumberOfFiles: 'Maximum number of files exceeded', + acceptFileTypes: 'File type not allowed', + maxFileSize: 'File is too large', + minFileSize: 'File is too small' + } + }, + + processActions: { + + validate: function (data, options) { + if (options.disabled) { + return data; + } + var dfd = $.Deferred(), + settings = this.options, + file = data.files[data.index], + fileSize; + if (options.minFileSize || options.maxFileSize) { + fileSize = file.size; + } + if ($.type(options.maxNumberOfFiles) === 'number' && + (settings.getNumberOfFiles() || 0) + data.files.length > + options.maxNumberOfFiles) { + file.error = settings.i18n('maxNumberOfFiles'); + } else if (options.acceptFileTypes && + !(options.acceptFileTypes.test(file.type) || + options.acceptFileTypes.test(file.name))) { + file.error = settings.i18n('acceptFileTypes'); + } else if (fileSize > options.maxFileSize) { + file.error = settings.i18n('maxFileSize'); + } else if ($.type(fileSize) === 'number' && + fileSize < options.minFileSize) { + file.error = settings.i18n('minFileSize'); + } else { + delete file.error; + } + if (file.error || data.files.error) { + data.files.error = true; + dfd.rejectWith(this, [data]); + } else { + dfd.resolveWith(this, [data]); + } + return dfd.promise(); + } + + } + + }); + +})); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnkuZmlsZXVwbG9hZC12YWxpZGF0ZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBqUXVlcnkgRmlsZSBVcGxvYWQgVmFsaWRhdGlvbiBQbHVnaW4gMS4xLjJcclxuICogaHR0cHM6Ly9naXRodWIuY29tL2JsdWVpbXAvalF1ZXJ5LUZpbGUtVXBsb2FkXHJcbiAqXHJcbiAqIENvcHlyaWdodCAyMDEzLCBTZWJhc3RpYW4gVHNjaGFuXHJcbiAqIGh0dHBzOi8vYmx1ZWltcC5uZXRcclxuICpcclxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlOlxyXG4gKiBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL01JVFxyXG4gKi9cclxuXHJcbi8qIGdsb2JhbCBkZWZpbmUsIHdpbmRvdyAqL1xyXG5cclxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XHJcbiAgICAndXNlIHN0cmljdCc7XHJcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XHJcbiAgICAgICAgLy8gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIEFNRCBtb2R1bGU6XHJcbiAgICAgICAgZGVmaW5lKFtcclxuICAgICAgICAgICAgJ2pxdWVyeScsXHJcbiAgICAgICAgICAgICcuL2pxdWVyeS5maWxldXBsb2FkLXByb2Nlc3MnXHJcbiAgICAgICAgXSwgZmFjdG9yeSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIEJyb3dzZXIgZ2xvYmFsczpcclxuICAgICAgICBmYWN0b3J5KFxyXG4gICAgICAgICAgICB3aW5kb3cualF1ZXJ5XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufShmdW5jdGlvbiAoJCkge1xyXG4gICAgJ3VzZSBzdHJpY3QnO1xyXG5cclxuICAgIC8vIEFwcGVuZCB0byB0aGUgZGVmYXVsdCBwcm9jZXNzUXVldWU6XHJcbiAgICAkLmJsdWVpbXAuZmlsZXVwbG9hZC5wcm90b3R5cGUub3B0aW9ucy5wcm9jZXNzUXVldWUucHVzaChcclxuICAgICAgICB7XHJcbiAgICAgICAgICAgIGFjdGlvbjogJ3ZhbGlkYXRlJyxcclxuICAgICAgICAgICAgLy8gQWx3YXlzIHRyaWdnZXIgdGhpcyBhY3Rpb24sXHJcbiAgICAgICAgICAgIC8vIGV2ZW4gaWYgdGhlIHByZXZpb3VzIGFjdGlvbiB3YXMgcmVqZWN0ZWQ6IFxyXG4gICAgICAgICAgICBhbHdheXM6IHRydWUsXHJcbiAgICAgICAgICAgIC8vIE9wdGlvbnMgdGFrZW4gZnJvbSB0aGUgZ2xvYmFsIG9wdGlvbnMgbWFwOlxyXG4gICAgICAgICAgICBhY2NlcHRGaWxlVHlwZXM6ICdAJyxcclxuICAgICAgICAgICAgbWF4RmlsZVNpemU6ICdAJyxcclxuICAgICAgICAgICAgbWluRmlsZVNpemU6ICdAJyxcclxuICAgICAgICAgICAgbWF4TnVtYmVyT2ZGaWxlczogJ0AnLFxyXG4gICAgICAgICAgICBkaXNhYmxlZDogJ0BkaXNhYmxlVmFsaWRhdGlvbidcclxuICAgICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIC8vIFRoZSBGaWxlIFVwbG9hZCBWYWxpZGF0aW9uIHBsdWdpbiBleHRlbmRzIHRoZSBmaWxldXBsb2FkIHdpZGdldFxyXG4gICAgLy8gd2l0aCBmaWxlIHZhbGlkYXRpb24gZnVuY3Rpb25hbGl0eTpcclxuICAgICQud2lkZ2V0KCdibHVlaW1wLmZpbGV1cGxvYWQnLCAkLmJsdWVpbXAuZmlsZXVwbG9hZCwge1xyXG5cclxuICAgICAgICBvcHRpb25zOiB7XHJcbiAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgIC8vIFRoZSByZWd1bGFyIGV4cHJlc3Npb24gZm9yIGFsbG93ZWQgZmlsZSB0eXBlcywgbWF0Y2hlc1xyXG4gICAgICAgICAgICAvLyBhZ2FpbnN0IGVpdGhlciBmaWxlIHR5cGUgb3IgZmlsZSBuYW1lOlxyXG4gICAgICAgICAgICBhY2NlcHRGaWxlVHlwZXM6IC8oXFwufFxcLykoZ2lmfGpwZT9nfHBuZykkL2ksXHJcbiAgICAgICAgICAgIC8vIFRoZSBtYXhpbXVtIGFsbG93ZWQgZmlsZSBzaXplIGluIGJ5dGVzOlxyXG4gICAgICAgICAgICBtYXhGaWxlU2l6ZTogMTAwMDAwMDAsIC8vIDEwIE1CXHJcbiAgICAgICAgICAgIC8vIFRoZSBtaW5pbXVtIGFsbG93ZWQgZmlsZSBzaXplIGluIGJ5dGVzOlxyXG4gICAgICAgICAgICBtaW5GaWxlU2l6ZTogdW5kZWZpbmVkLCAvLyBObyBtaW5pbWFsIGZpbGUgc2l6ZVxyXG4gICAgICAgICAgICAvLyBUaGUgbGltaXQgb2YgZmlsZXMgdG8gYmUgdXBsb2FkZWQ6XHJcbiAgICAgICAgICAgIG1heE51bWJlck9mRmlsZXM6IDEwLFxyXG4gICAgICAgICAgICAqL1xyXG5cclxuICAgICAgICAgICAgLy8gRnVuY3Rpb24gcmV0dXJuaW5nIHRoZSBjdXJyZW50IG51bWJlciBvZiBmaWxlcyxcclxuICAgICAgICAgICAgLy8gaGFzIHRvIGJlIG92ZXJyaWRlbiBmb3IgbWF4TnVtYmVyT2ZGaWxlcyB2YWxpZGF0aW9uOlxyXG4gICAgICAgICAgICBnZXROdW1iZXJPZkZpbGVzOiAkLm5vb3AsXHJcblxyXG4gICAgICAgICAgICAvLyBFcnJvciBhbmQgaW5mbyBtZXNzYWdlczpcclxuICAgICAgICAgICAgbWVzc2FnZXM6IHtcclxuICAgICAgICAgICAgICAgIG1heE51bWJlck9mRmlsZXM6ICdNYXhpbXVtIG51bWJlciBvZiBmaWxlcyBleGNlZWRlZCcsXHJcbiAgICAgICAgICAgICAgICBhY2NlcHRGaWxlVHlwZXM6ICdGaWxlIHR5cGUgbm90IGFsbG93ZWQnLFxyXG4gICAgICAgICAgICAgICAgbWF4RmlsZVNpemU6ICdGaWxlIGlzIHRvbyBsYXJnZScsXHJcbiAgICAgICAgICAgICAgICBtaW5GaWxlU2l6ZTogJ0ZpbGUgaXMgdG9vIHNtYWxsJ1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgcHJvY2Vzc0FjdGlvbnM6IHtcclxuXHJcbiAgICAgICAgICAgIHZhbGlkYXRlOiBmdW5jdGlvbiAoZGF0YSwgb3B0aW9ucykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHZhciBkZmQgPSAkLkRlZmVycmVkKCksXHJcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MgPSB0aGlzLm9wdGlvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZSA9IGRhdGEuZmlsZXNbZGF0YS5pbmRleF0sXHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZVNpemU7XHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5taW5GaWxlU2l6ZSB8fCBvcHRpb25zLm1heEZpbGVTaXplKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZVNpemUgPSBmaWxlLnNpemU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoJC50eXBlKG9wdGlvbnMubWF4TnVtYmVyT2ZGaWxlcykgPT09ICdudW1iZXInICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChzZXR0aW5ncy5nZXROdW1iZXJPZkZpbGVzKCkgfHwgMCkgKyBkYXRhLmZpbGVzLmxlbmd0aCA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLm1heE51bWJlck9mRmlsZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICBmaWxlLmVycm9yID0gc2V0dGluZ3MuaTE4bignbWF4TnVtYmVyT2ZGaWxlcycpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmFjY2VwdEZpbGVUeXBlcyAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAhKG9wdGlvbnMuYWNjZXB0RmlsZVR5cGVzLnRlc3QoZmlsZS50eXBlKSB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmFjY2VwdEZpbGVUeXBlcy50ZXN0KGZpbGUubmFtZSkpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZS5lcnJvciA9IHNldHRpbmdzLmkxOG4oJ2FjY2VwdEZpbGVUeXBlcycpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmaWxlU2l6ZSA+IG9wdGlvbnMubWF4RmlsZVNpemUpIHtcclxuICAgICAgICAgICAgICAgICAgICBmaWxlLmVycm9yID0gc2V0dGluZ3MuaTE4bignbWF4RmlsZVNpemUnKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJC50eXBlKGZpbGVTaXplKSA9PT0gJ251bWJlcicgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZVNpemUgPCBvcHRpb25zLm1pbkZpbGVTaXplKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZS5lcnJvciA9IHNldHRpbmdzLmkxOG4oJ21pbkZpbGVTaXplJyk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBmaWxlLmVycm9yO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGZpbGUuZXJyb3IgfHwgZGF0YS5maWxlcy5lcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuZmlsZXMuZXJyb3IgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGRmZC5yZWplY3RXaXRoKHRoaXMsIFtkYXRhXSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGRmZC5yZXNvbHZlV2l0aCh0aGlzLCBbZGF0YV0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRmZC5wcm9taXNlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfVxyXG5cclxuICAgIH0pO1xyXG5cclxufSkpO1xyXG4iXSwiZmlsZSI6ImpxdWVyeS5maWxldXBsb2FkLXZhbGlkYXRlLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.min.js new file mode 100644 index 000000000..ea3f06422 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload-validate.min.js @@ -0,0 +1 @@ +!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","./jquery.fileupload-process"],e):e(window.jQuery)}(function(e){"use strict";e.blueimp.fileupload.prototype.options.processQueue.push({action:"validate",always:!0,acceptFileTypes:"@",maxFileSize:"@",minFileSize:"@",maxNumberOfFiles:"@",disabled:"@disableValidation"}),e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{getNumberOfFiles:e.noop,messages:{maxNumberOfFiles:"Maximum number of files exceeded",acceptFileTypes:"File type not allowed",maxFileSize:"File is too large",minFileSize:"File is too small"}},processActions:{validate:function(i,l){if(l.disabled)return i;var r,s=e.Deferred(),t=this.options,o=i.files[i.index];return(l.minFileSize||l.maxFileSize)&&(r=o.size),"number"===e.type(l.maxNumberOfFiles)&&(t.getNumberOfFiles()||0)+i.files.length>l.maxNumberOfFiles?o.error=t.i18n("maxNumberOfFiles"):!l.acceptFileTypes||l.acceptFileTypes.test(o.type)||l.acceptFileTypes.test(o.name)?r>l.maxFileSize?o.error=t.i18n("maxFileSize"):"number"===e.type(r)&&r').prop('disabled')); + + // The FileReader API is not actually used, but works as feature detection, + // as some Safari versions (5?) support XHR file uploads via the FormData API, + // but not non-multipart XHR file uploads. + // window.XMLHttpRequestUpload is not available on IE10, so we check for + // window.ProgressEvent instead to detect XHR2 file upload capability: + $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader); + $.support.xhrFormDataFileUpload = !!window.FormData; + + // Detect support for Blob slicing (required for chunked uploads): + $.support.blobSlice = window.Blob && (Blob.prototype.slice || + Blob.prototype.webkitSlice || Blob.prototype.mozSlice); + + // The fileupload widget listens for change events on file input fields defined + // via fileInput setting and paste or drop events of the given dropZone. + // In addition to the default jQuery Widget methods, the fileupload widget + // exposes the "add" and "send" methods, to add or directly send files using + // the fileupload API. + // By default, files added via file input selection, paste, drag & drop or + // "add" method are uploaded immediately, but it is possible to override + // the "add" callback option to queue file uploads. + $.widget('blueimp.fileupload', { + + options: { + // The drop target element(s), by the default the complete document. + // Set to null to disable drag & drop support: + dropZone: $(document), + // The paste target element(s), by the default the complete document. + // Set to null to disable paste support: + pasteZone: $(document), + // The file input field(s), that are listened to for change events. + // If undefined, it is set to the file input fields inside + // of the widget element on plugin initialization. + // Set to null to disable the change listener. + fileInput: undefined, + // By default, the file input field is replaced with a clone after + // each input field change event. This is required for iframe transport + // queues and allows change events to be fired for the same file + // selection, but can be disabled by setting the following option to false: + replaceFileInput: true, + // The parameter name for the file form data (the request argument name). + // If undefined or empty, the name property of the file input field is + // used, or "files[]" if the file input name property is also empty, + // can be a string or an array of strings: + paramName: undefined, + // By default, each file of a selection is uploaded using an individual + // request for XHR type uploads. Set to false to upload file + // selections in one request each: + singleFileUploads: true, + // To limit the number of files uploaded with one XHR request, + // set the following option to an integer greater than 0: + limitMultiFileUploads: undefined, + // The following option limits the number of files uploaded with one + // XHR request to keep the request size under or equal to the defined + // limit in bytes: + limitMultiFileUploadSize: undefined, + // Multipart file uploads add a number of bytes to each uploaded file, + // therefore the following option adds an overhead for each file used + // in the limitMultiFileUploadSize configuration: + limitMultiFileUploadSizeOverhead: 512, + // Set the following option to true to issue all file upload requests + // in a sequential order: + sequentialUploads: false, + // To limit the number of concurrent uploads, + // set the following option to an integer greater than 0: + limitConcurrentUploads: undefined, + // Set the following option to true to force iframe transport uploads: + forceIframeTransport: false, + // Set the following option to the location of a redirect url on the + // origin server, for cross-domain iframe transport uploads: + redirect: undefined, + // The parameter name for the redirect url, sent as part of the form + // data and set to 'redirect' if this option is empty: + redirectParamName: undefined, + // Set the following option to the location of a postMessage window, + // to enable postMessage transport uploads: + postMessage: undefined, + // By default, XHR file uploads are sent as multipart/form-data. + // The iframe transport is always using multipart/form-data. + // Set to false to enable non-multipart XHR uploads: + multipart: true, + // To upload large files in smaller chunks, set the following option + // to a preferred maximum chunk size. If set to 0, null or undefined, + // or the browser does not support the required Blob API, files will + // be uploaded as a whole. + maxChunkSize: undefined, + // When a non-multipart upload or a chunked multipart upload has been + // aborted, this option can be used to resume the upload by setting + // it to the size of the already uploaded bytes. This option is most + // useful when modifying the options object inside of the "add" or + // "send" callbacks, as the options are cloned for each file upload. + uploadedBytes: undefined, + // By default, failed (abort or error) file uploads are removed from the + // global progress calculation. Set the following option to false to + // prevent recalculating the global progress data: + recalculateProgress: true, + // Interval in milliseconds to calculate and trigger progress events: + progressInterval: 100, + // Interval in milliseconds to calculate progress bitrate: + bitrateInterval: 500, + // By default, uploads are started automatically when adding files: + autoUpload: true, + + // Error and info messages: + messages: { + uploadedBytes: 'Uploaded bytes exceed file size' + }, + + // Translation function, gets the message key to be translated + // and an object with context specific data as arguments: + i18n: function (message, context) { + message = this.messages[message] || message.toString(); + if (context) { + $.each(context, function (key, value) { + message = message.replace('{' + key + '}', value); + }); + } + return message; + }, + + // Additional form data to be sent along with the file uploads can be set + // using this option, which accepts an array of objects with name and + // value properties, a function returning such an array, a FormData + // object (for XHR file uploads), or a simple object. + // The form of the first fileInput is given as parameter to the function: + formData: function (form) { + return form.serializeArray(); + }, + + // The add callback is invoked as soon as files are added to the fileupload + // widget (via file input selection, drag & drop, paste or add API call). + // If the singleFileUploads option is enabled, this callback will be + // called once for each file in the selection for XHR file uploads, else + // once for each file selection. + // + // The upload starts when the submit method is invoked on the data parameter. + // The data object contains a files property holding the added files + // and allows you to override plugin options as well as define ajax settings. + // + // Listeners for this callback can also be bound the following way: + // .bind('fileuploadadd', func); + // + // data.submit() returns a Promise object and allows to attach additional + // handlers using jQuery's Deferred callbacks: + // data.submit().done(func).fail(func).always(func); + add: function (e, data) { + if (e.isDefaultPrevented()) { + return false; + } + if (data.autoUpload || (data.autoUpload !== false && + $(this).fileupload('option', 'autoUpload'))) { + data.process().done(function () { + data.submit(); + }); + } + }, + + // Other callbacks: + + // Callback for the submit event of each file upload: + // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); + + // Callback for the start of each file upload request: + // send: function (e, data) {}, // .bind('fileuploadsend', func); + + // Callback for successful uploads: + // done: function (e, data) {}, // .bind('fileuploaddone', func); + + // Callback for failed (abort or error) uploads: + // fail: function (e, data) {}, // .bind('fileuploadfail', func); + + // Callback for completed (success, abort or error) requests: + // always: function (e, data) {}, // .bind('fileuploadalways', func); + + // Callback for upload progress events: + // progress: function (e, data) {}, // .bind('fileuploadprogress', func); + + // Callback for global upload progress events: + // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); + + // Callback for uploads start, equivalent to the global ajaxStart event: + // start: function (e) {}, // .bind('fileuploadstart', func); + + // Callback for uploads stop, equivalent to the global ajaxStop event: + // stop: function (e) {}, // .bind('fileuploadstop', func); + + // Callback for change events of the fileInput(s): + // change: function (e, data) {}, // .bind('fileuploadchange', func); + + // Callback for paste events to the pasteZone(s): + // paste: function (e, data) {}, // .bind('fileuploadpaste', func); + + // Callback for drop events of the dropZone(s): + // drop: function (e, data) {}, // .bind('fileuploaddrop', func); + + // Callback for dragover events of the dropZone(s): + // dragover: function (e) {}, // .bind('fileuploaddragover', func); + + // Callback for the start of each chunk upload request: + // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func); + + // Callback for successful chunk uploads: + // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func); + + // Callback for failed (abort or error) chunk uploads: + // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func); + + // Callback for completed (success, abort or error) chunk upload requests: + // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func); + + // The plugin options are used as settings object for the ajax calls. + // The following are jQuery ajax settings required for the file uploads: + processData: false, + contentType: false, + cache: false + }, + + // A list of options that require reinitializing event listeners and/or + // special initialization code: + _specialOptions: [ + 'fileInput', + 'dropZone', + 'pasteZone', + 'multipart', + 'forceIframeTransport' + ], + + _blobSlice: $.support.blobSlice && function () { + var slice = this.slice || this.webkitSlice || this.mozSlice; + return slice.apply(this, arguments); + }, + + _BitrateTimer: function () { + this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); + this.loaded = 0; + this.bitrate = 0; + this.getBitrate = function (now, loaded, interval) { + var timeDiff = now - this.timestamp; + if (!this.bitrate || !interval || timeDiff > interval) { + this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; + this.loaded = loaded; + this.timestamp = now; + } + return this.bitrate; + }; + }, + + _isXHRUpload: function (options) { + return !options.forceIframeTransport && + ((!options.multipart && $.support.xhrFileUpload) || + $.support.xhrFormDataFileUpload); + }, + + _getFormData: function (options) { + var formData; + if ($.type(options.formData) === 'function') { + return options.formData(options.form); + } + if ($.isArray(options.formData)) { + return options.formData; + } + if ($.type(options.formData) === 'object') { + formData = []; + $.each(options.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + _getTotal: function (files) { + var total = 0; + $.each(files, function (index, file) { + total += file.size || 1; + }); + return total; + }, + + _initProgressObject: function (obj) { + var progress = { + loaded: 0, + total: 0, + bitrate: 0 + }; + if (obj._progress) { + $.extend(obj._progress, progress); + } else { + obj._progress = progress; + } + }, + + _initResponseObject: function (obj) { + var prop; + if (obj._response) { + for (prop in obj._response) { + if (obj._response.hasOwnProperty(prop)) { + delete obj._response[prop]; + } + } + } else { + obj._response = {}; + } + }, + + _onProgress: function (e, data) { + if (e.lengthComputable) { + var now = ((Date.now) ? Date.now() : (new Date()).getTime()), + loaded; + if (data._time && data.progressInterval && + (now - data._time < data.progressInterval) && + e.loaded !== e.total) { + return; + } + data._time = now; + loaded = Math.floor( + e.loaded / e.total * (data.chunkSize || data._progress.total) + ) + (data.uploadedBytes || 0); + // Add the difference from the previously loaded state + // to the global loaded counter: + this._progress.loaded += (loaded - data._progress.loaded); + this._progress.bitrate = this._bitrateTimer.getBitrate( + now, + this._progress.loaded, + data.bitrateInterval + ); + data._progress.loaded = data.loaded = loaded; + data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate( + now, + loaded, + data.bitrateInterval + ); + // Trigger a custom progress event with a total data property set + // to the file size(s) of the current upload and a loaded data + // property calculated accordingly: + this._trigger( + 'progress', + $.Event('progress', {delegatedEvent: e}), + data + ); + // Trigger a global progress event for all current file uploads, + // including ajax calls queued for sequential file uploads: + this._trigger( + 'progressall', + $.Event('progressall', {delegatedEvent: e}), + this._progress + ); + } + }, + + _initProgressListener: function (options) { + var that = this, + xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); + // Accesss to the native XHR object is required to add event listeners + // for the upload progress event: + if (xhr.upload) { + $(xhr.upload).bind('progress', function (e) { + var oe = e.originalEvent; + // Make sure the progress event properties get copied over: + e.lengthComputable = oe.lengthComputable; + e.loaded = oe.loaded; + e.total = oe.total; + that._onProgress(e, options); + }); + options.xhr = function () { + return xhr; + }; + } + }, + + _isInstanceOf: function (type, obj) { + // Cross-frame instanceof check + return Object.prototype.toString.call(obj) === '[object ' + type + ']'; + }, + + _initXHRData: function (options) { + var that = this, + formData, + file = options.files[0], + // Ignore non-multipart setting if not supported: + multipart = options.multipart || !$.support.xhrFileUpload, + paramName = $.type(options.paramName) === 'array' ? + options.paramName[0] : options.paramName; + options.headers = $.extend({}, options.headers); + if (options.contentRange) { + options.headers['Content-Range'] = options.contentRange; + } + if (!multipart || options.blob || !this._isInstanceOf('File', file)) { + options.headers['Content-Disposition'] = 'attachment; filename="' + + encodeURI(file.name) + '"'; + } + if (!multipart) { + options.contentType = file.type || 'application/octet-stream'; + options.data = options.blob || file; + } else if ($.support.xhrFormDataFileUpload) { + if (options.postMessage) { + // window.postMessage does not allow sending FormData + // objects, so we just add the File/Blob objects to + // the formData array and let the postMessage window + // create the FormData object out of this array: + formData = this._getFormData(options); + if (options.blob) { + formData.push({ + name: paramName, + value: options.blob + }); + } else { + $.each(options.files, function (index, file) { + formData.push({ + name: ($.type(options.paramName) === 'array' && + options.paramName[index]) || paramName, + value: file + }); + }); + } + } else { + if (that._isInstanceOf('FormData', options.formData)) { + formData = options.formData; + } else { + formData = new FormData(); + $.each(this._getFormData(options), function (index, field) { + formData.append(field.name, field.value); + }); + } + if (options.blob) { + formData.append(paramName, options.blob, file.name); + } else { + $.each(options.files, function (index, file) { + // This check allows the tests to run with + // dummy objects: + if (that._isInstanceOf('File', file) || + that._isInstanceOf('Blob', file)) { + formData.append( + ($.type(options.paramName) === 'array' && + options.paramName[index]) || paramName, + file, + file.uploadName || file.name + ); + } + }); + } + } + options.data = formData; + } + // Blob reference is not needed anymore, free memory: + options.blob = null; + }, + + _initIframeSettings: function (options) { + var targetHost = $('').prop('href', options.url).prop('host'); + // Setting the dataType to iframe enables the iframe transport: + options.dataType = 'iframe ' + (options.dataType || ''); + // The iframe transport accepts a serialized array as form data: + options.formData = this._getFormData(options); + // Add redirect url to form data on cross-domain uploads: + if (options.redirect && targetHost && targetHost !== location.host) { + options.formData.push({ + name: options.redirectParamName || 'redirect', + value: options.redirect + }); + } + }, + + _initDataSettings: function (options) { + if (this._isXHRUpload(options)) { + if (!this._chunkedUpload(options, true)) { + if (!options.data) { + this._initXHRData(options); + } + this._initProgressListener(options); + } + if (options.postMessage) { + // Setting the dataType to postmessage enables the + // postMessage transport: + options.dataType = 'postmessage ' + (options.dataType || ''); + } + } else { + this._initIframeSettings(options); + } + }, + + _getParamName: function (options) { + var fileInput = $(options.fileInput), + paramName = options.paramName; + if (!paramName) { + paramName = []; + fileInput.each(function () { + var input = $(this), + name = input.prop('name') || 'files[]', + i = (input.prop('files') || [1]).length; + while (i) { + paramName.push(name); + i -= 1; + } + }); + if (!paramName.length) { + paramName = [fileInput.prop('name') || 'files[]']; + } + } else if (!$.isArray(paramName)) { + paramName = [paramName]; + } + return paramName; + }, + + _initFormSettings: function (options) { + // Retrieve missing options from the input field and the + // associated form, if available: + if (!options.form || !options.form.length) { + options.form = $(options.fileInput.prop('form')); + // If the given file input doesn't have an associated form, + // use the default widget file input's form: + if (!options.form.length) { + options.form = $(this.options.fileInput.prop('form')); + } + } + options.paramName = this._getParamName(options); + if (!options.url) { + options.url = options.form.prop('action') || location.href; + } + // The HTTP request method must be "POST" or "PUT": + options.type = (options.type || + ($.type(options.form.prop('method')) === 'string' && + options.form.prop('method')) || '' + ).toUpperCase(); + if (options.type !== 'POST' && options.type !== 'PUT' && + options.type !== 'PATCH') { + options.type = 'POST'; + } + if (!options.formAcceptCharset) { + options.formAcceptCharset = options.form.attr('accept-charset'); + } + }, + + _getAJAXSettings: function (data) { + var options = $.extend({}, this.options, data); + this._initFormSettings(options); + this._initDataSettings(options); + return options; + }, + + // jQuery 1.6 doesn't provide .state(), + // while jQuery 1.8+ removed .isRejected() and .isResolved(): + _getDeferredState: function (deferred) { + if (deferred.state) { + return deferred.state(); + } + if (deferred.isResolved()) { + return 'resolved'; + } + if (deferred.isRejected()) { + return 'rejected'; + } + return 'pending'; + }, + + // Maps jqXHR callbacks to the equivalent + // methods of the given Promise object: + _enhancePromise: function (promise) { + promise.success = promise.done; + promise.error = promise.fail; + promise.complete = promise.always; + return promise; + }, + + // Creates and returns a Promise object enhanced with + // the jqXHR methods abort, success, error and complete: + _getXHRPromise: function (resolveOrReject, context, args) { + var dfd = $.Deferred(), + promise = dfd.promise(); + context = context || this.options.context || promise; + if (resolveOrReject === true) { + dfd.resolveWith(context, args); + } else if (resolveOrReject === false) { + dfd.rejectWith(context, args); + } + promise.abort = dfd.promise; + return this._enhancePromise(promise); + }, + + // Adds convenience methods to the data callback argument: + _addConvenienceMethods: function (e, data) { + var that = this, + getPromise = function (args) { + return $.Deferred().resolveWith(that, args).promise(); + }; + data.process = function (resolveFunc, rejectFunc) { + if (resolveFunc || rejectFunc) { + data._processQueue = this._processQueue = + (this._processQueue || getPromise([this])).pipe( + function () { + if (data.errorThrown) { + return $.Deferred() + .rejectWith(that, [data]).promise(); + } + return getPromise(arguments); + } + ).pipe(resolveFunc, rejectFunc); + } + return this._processQueue || getPromise([this]); + }; + data.submit = function () { + if (this.state() !== 'pending') { + data.jqXHR = this.jqXHR = + (that._trigger( + 'submit', + $.Event('submit', {delegatedEvent: e}), + this + ) !== false) && that._onSend(e, this); + } + return this.jqXHR || that._getXHRPromise(); + }; + data.abort = function () { + if (this.jqXHR) { + return this.jqXHR.abort(); + } + this.errorThrown = 'abort'; + that._trigger('fail', null, this); + return that._getXHRPromise(false); + }; + data.state = function () { + if (this.jqXHR) { + return that._getDeferredState(this.jqXHR); + } + if (this._processQueue) { + return that._getDeferredState(this._processQueue); + } + }; + data.processing = function () { + return !this.jqXHR && this._processQueue && that + ._getDeferredState(this._processQueue) === 'pending'; + }; + data.progress = function () { + return this._progress; + }; + data.response = function () { + return this._response; + }; + }, + + // Parses the Range header from the server response + // and returns the uploaded bytes: + _getUploadedBytes: function (jqXHR) { + var range = jqXHR.getResponseHeader('Range'), + parts = range && range.split('-'), + upperBytesPos = parts && parts.length > 1 && + parseInt(parts[1], 10); + return upperBytesPos && upperBytesPos + 1; + }, + + // Uploads a file in multiple, sequential requests + // by splitting the file up in multiple blob chunks. + // If the second parameter is true, only tests if the file + // should be uploaded in chunks, but does not invoke any + // upload requests: + _chunkedUpload: function (options, testOnly) { + options.uploadedBytes = options.uploadedBytes || 0; + var that = this, + file = options.files[0], + fs = file.size, + ub = options.uploadedBytes, + mcs = options.maxChunkSize || fs, + slice = this._blobSlice, + dfd = $.Deferred(), + promise = dfd.promise(), + jqXHR, + upload; + if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || + options.data) { + return false; + } + if (testOnly) { + return true; + } + if (ub >= fs) { + file.error = options.i18n('uploadedBytes'); + return this._getXHRPromise( + false, + options.context, + [null, 'error', file.error] + ); + } + // The chunk upload method: + upload = function () { + // Clone the options object for each chunk upload: + var o = $.extend({}, options), + currentLoaded = o._progress.loaded; + o.blob = slice.call( + file, + ub, + ub + mcs, + file.type + ); + // Store the current chunk size, as the blob itself + // will be dereferenced after data processing: + o.chunkSize = o.blob.size; + // Expose the chunk bytes position range: + o.contentRange = 'bytes ' + ub + '-' + + (ub + o.chunkSize - 1) + '/' + fs; + // Process the upload data (the blob and potential form data): + that._initXHRData(o); + // Add progress listeners for this chunk upload: + that._initProgressListener(o); + jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) || + that._getXHRPromise(false, o.context)) + .done(function (result, textStatus, jqXHR) { + ub = that._getUploadedBytes(jqXHR) || + (ub + o.chunkSize); + // Create a progress event if no final progress event + // with loaded equaling total has been triggered + // for this chunk: + if (currentLoaded + o.chunkSize - o._progress.loaded) { + that._onProgress($.Event('progress', { + lengthComputable: true, + loaded: ub - o.uploadedBytes, + total: ub - o.uploadedBytes + }), o); + } + options.uploadedBytes = o.uploadedBytes = ub; + o.result = result; + o.textStatus = textStatus; + o.jqXHR = jqXHR; + that._trigger('chunkdone', null, o); + that._trigger('chunkalways', null, o); + if (ub < fs) { + // File upload not yet complete, + // continue with the next chunk: + upload(); + } else { + dfd.resolveWith( + o.context, + [result, textStatus, jqXHR] + ); + } + }) + .fail(function (jqXHR, textStatus, errorThrown) { + o.jqXHR = jqXHR; + o.textStatus = textStatus; + o.errorThrown = errorThrown; + that._trigger('chunkfail', null, o); + that._trigger('chunkalways', null, o); + dfd.rejectWith( + o.context, + [jqXHR, textStatus, errorThrown] + ); + }); + }; + this._enhancePromise(promise); + promise.abort = function () { + return jqXHR.abort(); + }; + upload(); + return promise; + }, + + _beforeSend: function (e, data) { + if (this._active === 0) { + // the start callback is triggered when an upload starts + // and no other uploads are currently running, + // equivalent to the global ajaxStart event: + this._trigger('start'); + // Set timer for global bitrate progress calculation: + this._bitrateTimer = new this._BitrateTimer(); + // Reset the global progress values: + this._progress.loaded = this._progress.total = 0; + this._progress.bitrate = 0; + } + // Make sure the container objects for the .response() and + // .progress() methods on the data object are available + // and reset to their initial state: + this._initResponseObject(data); + this._initProgressObject(data); + data._progress.loaded = data.loaded = data.uploadedBytes || 0; + data._progress.total = data.total = this._getTotal(data.files) || 1; + data._progress.bitrate = data.bitrate = 0; + this._active += 1; + // Initialize the global progress values: + this._progress.loaded += data.loaded; + this._progress.total += data.total; + }, + + _onDone: function (result, textStatus, jqXHR, options) { + var total = options._progress.total, + response = options._response; + if (options._progress.loaded < total) { + // Create a progress event if no final progress event + // with loaded equaling total has been triggered: + this._onProgress($.Event('progress', { + lengthComputable: true, + loaded: total, + total: total + }), options); + } + response.result = options.result = result; + response.textStatus = options.textStatus = textStatus; + response.jqXHR = options.jqXHR = jqXHR; + this._trigger('done', null, options); + }, + + _onFail: function (jqXHR, textStatus, errorThrown, options) { + var response = options._response; + if (options.recalculateProgress) { + // Remove the failed (error or abort) file upload from + // the global progress calculation: + this._progress.loaded -= options._progress.loaded; + this._progress.total -= options._progress.total; + } + response.jqXHR = options.jqXHR = jqXHR; + response.textStatus = options.textStatus = textStatus; + response.errorThrown = options.errorThrown = errorThrown; + this._trigger('fail', null, options); + }, + + _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { + // jqXHRorResult, textStatus and jqXHRorError are added to the + // options object via done and fail callbacks + this._trigger('always', null, options); + }, + + _onSend: function (e, data) { + if (!data.submit) { + this._addConvenienceMethods(e, data); + } + var that = this, + jqXHR, + aborted, + slot, + pipe, + options = that._getAJAXSettings(data), + send = function () { + that._sending += 1; + // Set timer for bitrate progress calculation: + options._bitrateTimer = new that._BitrateTimer(); + jqXHR = jqXHR || ( + ((aborted || that._trigger( + 'send', + $.Event('send', {delegatedEvent: e}), + options + ) === false) && + that._getXHRPromise(false, options.context, aborted)) || + that._chunkedUpload(options) || $.ajax(options) + ).done(function (result, textStatus, jqXHR) { + that._onDone(result, textStatus, jqXHR, options); + }).fail(function (jqXHR, textStatus, errorThrown) { + that._onFail(jqXHR, textStatus, errorThrown, options); + }).always(function (jqXHRorResult, textStatus, jqXHRorError) { + that._onAlways( + jqXHRorResult, + textStatus, + jqXHRorError, + options + ); + that._sending -= 1; + that._active -= 1; + if (options.limitConcurrentUploads && + options.limitConcurrentUploads > that._sending) { + // Start the next queued upload, + // that has not been aborted: + var nextSlot = that._slots.shift(); + while (nextSlot) { + if (that._getDeferredState(nextSlot) === 'pending') { + nextSlot.resolve(); + break; + } + nextSlot = that._slots.shift(); + } + } + if (that._active === 0) { + // The stop callback is triggered when all uploads have + // been completed, equivalent to the global ajaxStop event: + that._trigger('stop'); + } + }); + return jqXHR; + }; + this._beforeSend(e, options); + if (this.options.sequentialUploads || + (this.options.limitConcurrentUploads && + this.options.limitConcurrentUploads <= this._sending)) { + if (this.options.limitConcurrentUploads > 1) { + slot = $.Deferred(); + this._slots.push(slot); + pipe = slot.pipe(send); + } else { + this._sequence = this._sequence.pipe(send, send); + pipe = this._sequence; + } + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe.abort = function () { + aborted = [undefined, 'abort', 'abort']; + if (!jqXHR) { + if (slot) { + slot.rejectWith(options.context, aborted); + } + return send(); + } + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + } + return send(); + }, + + _onAdd: function (e, data) { + var that = this, + result = true, + options = $.extend({}, this.options, data), + files = data.files, + filesLength = files.length, + limit = options.limitMultiFileUploads, + limitSize = options.limitMultiFileUploadSize, + overhead = options.limitMultiFileUploadSizeOverhead, + batchSize = 0, + paramName = this._getParamName(options), + paramNameSet, + paramNameSlice, + fileSet, + i, + j = 0; + if (limitSize && (!filesLength || files[0].size === undefined)) { + limitSize = undefined; + } + if (!(options.singleFileUploads || limit || limitSize) || + !this._isXHRUpload(options)) { + fileSet = [files]; + paramNameSet = [paramName]; + } else if (!(options.singleFileUploads || limitSize) && limit) { + fileSet = []; + paramNameSet = []; + for (i = 0; i < filesLength; i += limit) { + fileSet.push(files.slice(i, i + limit)); + paramNameSlice = paramName.slice(i, i + limit); + if (!paramNameSlice.length) { + paramNameSlice = paramName; + } + paramNameSet.push(paramNameSlice); + } + } else if (!options.singleFileUploads && limitSize) { + fileSet = []; + paramNameSet = []; + for (i = 0; i < filesLength; i = i + 1) { + batchSize += files[i].size + overhead; + if (i + 1 === filesLength || + ((batchSize + files[i + 1].size + overhead) > limitSize) || + (limit && i + 1 - j >= limit)) { + fileSet.push(files.slice(j, i + 1)); + paramNameSlice = paramName.slice(j, i + 1); + if (!paramNameSlice.length) { + paramNameSlice = paramName; + } + paramNameSet.push(paramNameSlice); + j = i + 1; + batchSize = 0; + } + } + } else { + paramNameSet = paramName; + } + data.originalFiles = files; + $.each(fileSet || files, function (index, element) { + var newData = $.extend({}, data); + newData.files = fileSet ? element : [element]; + newData.paramName = paramNameSet[index]; + that._initResponseObject(newData); + that._initProgressObject(newData); + that._addConvenienceMethods(e, newData); + result = that._trigger( + 'add', + $.Event('add', {delegatedEvent: e}), + newData + ); + return result; + }); + return result; + }, + + _replaceFileInput: function (input) { + var inputClone = input.clone(true); + $('').append(inputClone)[0].reset(); + // Detaching allows to insert the fileInput on another form + // without loosing the file input value: + input.after(inputClone).detach(); + // Avoid memory leaks with the detached file input: + $.cleanData(input.unbind('remove')); + // Replace the original file input element in the fileInput + // elements set with the clone, which has been copied including + // event handlers: + this.options.fileInput = this.options.fileInput.map(function (i, el) { + if (el === input[0]) { + return inputClone[0]; + } + return el; + }); + // If the widget has been initialized on the file input itself, + // override this.element with the file input clone: + if (input[0] === this.element[0]) { + this.element = inputClone; + } + }, + + _handleFileTreeEntry: function (entry, path) { + var that = this, + dfd = $.Deferred(), + errorHandler = function (e) { + if (e && !e.entry) { + e.entry = entry; + } + // Since $.when returns immediately if one + // Deferred is rejected, we use resolve instead. + // This allows valid files and invalid items + // to be returned together in one set: + dfd.resolve([e]); + }, + dirReader; + path = path || ''; + if (entry.isFile) { + if (entry._file) { + // Workaround for Chrome bug #149735 + entry._file.relativePath = path; + dfd.resolve(entry._file); + } else { + entry.file(function (file) { + file.relativePath = path; + dfd.resolve(file); + }, errorHandler); + } + } else if (entry.isDirectory) { + dirReader = entry.createReader(); + dirReader.readEntries(function (entries) { + that._handleFileTreeEntries( + entries, + path + entry.name + '/' + ).done(function (files) { + dfd.resolve(files); + }).fail(errorHandler); + }, errorHandler); + } else { + // Return an empy list for file system items + // other than files or directories: + dfd.resolve([]); + } + return dfd.promise(); + }, + + _handleFileTreeEntries: function (entries, path) { + var that = this; + return $.when.apply( + $, + $.map(entries, function (entry) { + return that._handleFileTreeEntry(entry, path); + }) + ).pipe(function () { + return Array.prototype.concat.apply( + [], + arguments + ); + }); + }, + + _getDroppedFiles: function (dataTransfer) { + dataTransfer = dataTransfer || {}; + var items = dataTransfer.items; + if (items && items.length && (items[0].webkitGetAsEntry || + items[0].getAsEntry)) { + return this._handleFileTreeEntries( + $.map(items, function (item) { + var entry; + if (item.webkitGetAsEntry) { + entry = item.webkitGetAsEntry(); + if (entry) { + // Workaround for Chrome bug #149735: + entry._file = item.getAsFile(); + } + return entry; + } + return item.getAsEntry(); + }) + ); + } + return $.Deferred().resolve( + $.makeArray(dataTransfer.files) + ).promise(); + }, + + _getSingleFileInputFiles: function (fileInput) { + fileInput = $(fileInput); + var entries = fileInput.prop('webkitEntries') || + fileInput.prop('entries'), + files, + value; + if (entries && entries.length) { + return this._handleFileTreeEntries(entries); + } + files = $.makeArray(fileInput.prop('files')); + if (!files.length) { + value = fileInput.prop('value'); + if (!value) { + return $.Deferred().resolve([]).promise(); + } + // If the files property is not available, the browser does not + // support the File API and we add a pseudo File object with + // the input value as name with path information removed: + files = [{name: value.replace(/^.*\\/, '')}]; + } else if (files[0].name === undefined && files[0].fileName) { + // File normalization for Safari 4 and Firefox 3: + $.each(files, function (index, file) { + file.name = file.fileName; + file.size = file.fileSize; + }); + } + return $.Deferred().resolve(files).promise(); + }, + + _getFileInputFiles: function (fileInput) { + if (!(fileInput instanceof $) || fileInput.length === 1) { + return this._getSingleFileInputFiles(fileInput); + } + return $.when.apply( + $, + $.map(fileInput, this._getSingleFileInputFiles) + ).pipe(function () { + return Array.prototype.concat.apply( + [], + arguments + ); + }); + }, + + _onChange: function (e) { + var that = this, + data = { + fileInput: $(e.target), + form: $(e.target.form) + }; + this._getFileInputFiles(data.fileInput).always(function (files) { + data.files = files; + if (that.options.replaceFileInput) { + that._replaceFileInput(data.fileInput); + } + if (that._trigger( + 'change', + $.Event('change', {delegatedEvent: e}), + data + ) !== false) { + that._onAdd(e, data); + } + }); + }, + + _onPaste: function (e) { + var items = e.originalEvent && e.originalEvent.clipboardData && + e.originalEvent.clipboardData.items, + data = {files: []}; + if (items && items.length) { + $.each(items, function (index, item) { + var file = item.getAsFile && item.getAsFile(); + if (file) { + data.files.push(file); + } + }); + if (this._trigger( + 'paste', + $.Event('paste', {delegatedEvent: e}), + data + ) !== false) { + this._onAdd(e, data); + } + } + }, + + _onDrop: function (e) { + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; + var that = this, + dataTransfer = e.dataTransfer, + data = {}; + if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { + e.preventDefault(); + this._getDroppedFiles(dataTransfer).always(function (files) { + data.files = files; + if (that._trigger( + 'drop', + $.Event('drop', {delegatedEvent: e}), + data + ) !== false) { + that._onAdd(e, data); + } + }); + } + }, + + _onDragOver: function (e) { + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; + var dataTransfer = e.dataTransfer; + if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && + this._trigger( + 'dragover', + $.Event('dragover', {delegatedEvent: e}) + ) !== false) { + e.preventDefault(); + dataTransfer.dropEffect = 'copy'; + } + }, + + _initEventHandlers: function () { + if (this._isXHRUpload(this.options)) { + this._on(this.options.dropZone, { + dragover: this._onDragOver, + drop: this._onDrop + }); + this._on(this.options.pasteZone, { + paste: this._onPaste + }); + } + if ($.support.fileInput) { + this._on(this.options.fileInput, { + change: this._onChange + }); + } + }, + + _destroyEventHandlers: function () { + this._off(this.options.dropZone, 'dragover drop'); + this._off(this.options.pasteZone, 'paste'); + this._off(this.options.fileInput, 'change'); + }, + + _setOption: function (key, value) { + var reinit = $.inArray(key, this._specialOptions) !== -1; + if (reinit) { + this._destroyEventHandlers(); + } + this._super(key, value); + if (reinit) { + this._initSpecialOptions(); + this._initEventHandlers(); + } + }, + + _initSpecialOptions: function () { + var options = this.options; + if (options.fileInput === undefined) { + options.fileInput = this.element.is('input[type="file"]') ? + this.element : this.element.find('input[type="file"]'); + } else if (!(options.fileInput instanceof $)) { + options.fileInput = $(options.fileInput); + } + if (!(options.dropZone instanceof $)) { + options.dropZone = $(options.dropZone); + } + if (!(options.pasteZone instanceof $)) { + options.pasteZone = $(options.pasteZone); + } + }, + + _getRegExp: function (str) { + var parts = str.split('/'), + modifiers = parts.pop(); + parts.shift(); + return new RegExp(parts.join('/'), modifiers); + }, + + _isRegExpOption: function (key, value) { + return key !== 'url' && $.type(value) === 'string' && + /^\/.*\/[igm]{0,3}$/.test(value); + }, + + _initDataAttributes: function () { + var that = this, + options = this.options, + clone = $(this.element[0].cloneNode(false)); + // Initialize options set via HTML5 data-attributes: + $.each( + clone.data(), + function (key, value) { + var dataAttributeName = 'data-' + + // Convert camelCase to hyphen-ated key: + key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + if (clone.attr(dataAttributeName)) { + if (that._isRegExpOption(key, value)) { + value = that._getRegExp(value); + } + options[key] = value; + } + } + ); + }, + + _create: function () { + this._initDataAttributes(); + this._initSpecialOptions(); + this._slots = []; + this._sequence = this._getXHRPromise(true); + this._sending = this._active = 0; + this._initProgressObject(this); + this._initEventHandlers(); + }, + + // This method is exposed to the widget API and allows to query + // the number of active uploads: + active: function () { + return this._active; + }, + + // This method is exposed to the widget API and allows to query + // the widget upload progress. + // It returns an object with loaded, total and bitrate properties + // for the running uploads: + progress: function () { + return this._progress; + }, + + // This method is exposed to the widget API and allows adding files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('add', {files: filesList}); + add: function (data) { + var that = this; + if (!data || this.options.disabled) { + return; + } + if (data.fileInput && !data.files) { + this._getFileInputFiles(data.fileInput).always(function (files) { + data.files = files; + that._onAdd(null, data); + }); + } else { + data.files = $.makeArray(data.files); + this._onAdd(null, data); + } + }, + + // This method is exposed to the widget API and allows sending files + // using the fileupload API. The data parameter accepts an object which + // must have a files or fileInput property and can contain additional options: + // .fileupload('send', {files: filesList}); + // The method returns a Promise object for the file upload call. + send: function (data) { + if (data && !this.options.disabled) { + if (data.fileInput && !data.files) { + var that = this, + dfd = $.Deferred(), + promise = dfd.promise(), + jqXHR, + aborted; + promise.abort = function () { + aborted = true; + if (jqXHR) { + return jqXHR.abort(); + } + dfd.reject(null, 'abort', 'abort'); + return promise; + }; + this._getFileInputFiles(data.fileInput).always( + function (files) { + if (aborted) { + return; + } + if (!files.length) { + dfd.reject(); + return; + } + data.files = files; + jqXHR = that._onSend(null, data).then( + function (result, textStatus, jqXHR) { + dfd.resolve(result, textStatus, jqXHR); + }, + function (jqXHR, textStatus, errorThrown) { + dfd.reject(jqXHR, textStatus, errorThrown); + } + ); + } + ); + return this._enhancePromise(promise); + } + data.files = $.makeArray(data.files); + if (data.files.length) { + return this._onSend(null, data); + } + } + return this._getXHRPromise(false, data && data.context); + } + + }); + +})); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqcXVlcnkuZmlsZXVwbG9hZC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBqUXVlcnkgRmlsZSBVcGxvYWQgUGx1Z2luIDUuNDAuMVxyXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYmx1ZWltcC9qUXVlcnktRmlsZS1VcGxvYWRcclxuICpcclxuICogQ29weXJpZ2h0IDIwMTAsIFNlYmFzdGlhbiBUc2NoYW5cclxuICogaHR0cHM6Ly9ibHVlaW1wLm5ldFxyXG4gKlxyXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2U6XHJcbiAqIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlUXHJcbiAqL1xyXG5cclxuLyoganNoaW50IG5vbWVuOmZhbHNlICovXHJcbi8qIGdsb2JhbCBkZWZpbmUsIHdpbmRvdywgZG9jdW1lbnQsIGxvY2F0aW9uLCBCbG9iLCBGb3JtRGF0YSAqL1xyXG5cclxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XHJcbiAgICAndXNlIHN0cmljdCc7XHJcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XHJcbiAgICAgICAgLy8gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIEFNRCBtb2R1bGU6XHJcbiAgICAgICAgZGVmaW5lKFtcclxuICAgICAgICAgICAgJ2pxdWVyeScsXHJcbiAgICAgICAgICAgICdqcXVlcnkudWkud2lkZ2V0J1xyXG4gICAgICAgIF0sIGZhY3RvcnkpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBCcm93c2VyIGdsb2JhbHM6XHJcbiAgICAgICAgZmFjdG9yeSh3aW5kb3cualF1ZXJ5KTtcclxuICAgIH1cclxufShmdW5jdGlvbiAoJCkge1xyXG4gICAgJ3VzZSBzdHJpY3QnO1xyXG5cclxuICAgIC8vIERldGVjdCBmaWxlIGlucHV0IHN1cHBvcnQsIGJhc2VkIG9uXHJcbiAgICAvLyBodHRwOi8vdmlsamFtaXMuY29tL2Jsb2cvMjAxMi9maWxlLXVwbG9hZC1zdXBwb3J0LW9uLW1vYmlsZS9cclxuICAgICQuc3VwcG9ydC5maWxlSW5wdXQgPSAhKG5ldyBSZWdFeHAoXHJcbiAgICAgICAgLy8gSGFuZGxlIGRldmljZXMgd2hpY2ggZ2l2ZSBmYWxzZSBwb3NpdGl2ZXMgZm9yIHRoZSBmZWF0dXJlIGRldGVjdGlvbjpcclxuICAgICAgICAnKEFuZHJvaWQgKDFcXFxcLlswMTU2XXwyXFxcXC5bMDFdKSknICtcclxuICAgICAgICAgICAgJ3woV2luZG93cyBQaG9uZSAoT1MgN3w4XFxcXC4wKSl8KFhCTFdQKXwoWnVuZVdQKXwoV1BEZXNrdG9wKScgK1xyXG4gICAgICAgICAgICAnfCh3KGViKT9PU0Jyb3dzZXIpfCh3ZWJPUyknICtcclxuICAgICAgICAgICAgJ3woS2luZGxlLygxXFxcXC4wfDJcXFxcLlswNV18M1xcXFwuMCkpJ1xyXG4gICAgKS50ZXN0KHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50KSB8fFxyXG4gICAgICAgIC8vIEZlYXR1cmUgZGV0ZWN0aW9uIGZvciBhbGwgb3RoZXIgZGV2aWNlczpcclxuICAgICAgICAkKCc8aW5wdXQgdHlwZT1cImZpbGVcIj4nKS5wcm9wKCdkaXNhYmxlZCcpKTtcclxuXHJcbiAgICAvLyBUaGUgRmlsZVJlYWRlciBBUEkgaXMgbm90IGFjdHVhbGx5IHVzZWQsIGJ1dCB3b3JrcyBhcyBmZWF0dXJlIGRldGVjdGlvbixcclxuICAgIC8vIGFzIHNvbWUgU2FmYXJpIHZlcnNpb25zICg1Pykgc3VwcG9ydCBYSFIgZmlsZSB1cGxvYWRzIHZpYSB0aGUgRm9ybURhdGEgQVBJLFxyXG4gICAgLy8gYnV0IG5vdCBub24tbXVsdGlwYXJ0IFhIUiBmaWxlIHVwbG9hZHMuXHJcbiAgICAvLyB3aW5kb3cuWE1MSHR0cFJlcXVlc3RVcGxvYWQgaXMgbm90IGF2YWlsYWJsZSBvbiBJRTEwLCBzbyB3ZSBjaGVjayBmb3JcclxuICAgIC8vIHdpbmRvdy5Qcm9ncmVzc0V2ZW50IGluc3RlYWQgdG8gZGV0ZWN0IFhIUjIgZmlsZSB1cGxvYWQgY2FwYWJpbGl0eTpcclxuICAgICQuc3VwcG9ydC54aHJGaWxlVXBsb2FkID0gISEod2luZG93LlByb2dyZXNzRXZlbnQgJiYgd2luZG93LkZpbGVSZWFkZXIpO1xyXG4gICAgJC5zdXBwb3J0LnhockZvcm1EYXRhRmlsZVVwbG9hZCA9ICEhd2luZG93LkZvcm1EYXRhO1xyXG5cclxuICAgIC8vIERldGVjdCBzdXBwb3J0IGZvciBCbG9iIHNsaWNpbmcgKHJlcXVpcmVkIGZvciBjaHVua2VkIHVwbG9hZHMpOlxyXG4gICAgJC5zdXBwb3J0LmJsb2JTbGljZSA9IHdpbmRvdy5CbG9iICYmIChCbG9iLnByb3RvdHlwZS5zbGljZSB8fFxyXG4gICAgICAgIEJsb2IucHJvdG90eXBlLndlYmtpdFNsaWNlIHx8IEJsb2IucHJvdG90eXBlLm1velNsaWNlKTtcclxuXHJcbiAgICAvLyBUaGUgZmlsZXVwbG9hZCB3aWRnZXQgbGlzdGVucyBmb3IgY2hhbmdlIGV2ZW50cyBvbiBmaWxlIGlucHV0IGZpZWxkcyBkZWZpbmVkXHJcbiAgICAvLyB2aWEgZmlsZUlucHV0IHNldHRpbmcgYW5kIHBhc3RlIG9yIGRyb3AgZXZlbnRzIG9mIHRoZSBnaXZlbiBkcm9wWm9uZS5cclxuICAgIC8vIEluIGFkZGl0aW9uIHRvIHRoZSBkZWZhdWx0IGpRdWVyeSBXaWRnZXQgbWV0aG9kcywgdGhlIGZpbGV1cGxvYWQgd2lkZ2V0XHJcbiAgICAvLyBleHBvc2VzIHRoZSBcImFkZFwiIGFuZCBcInNlbmRcIiBtZXRob2RzLCB0byBhZGQgb3IgZGlyZWN0bHkgc2VuZCBmaWxlcyB1c2luZ1xyXG4gICAgLy8gdGhlIGZpbGV1cGxvYWQgQVBJLlxyXG4gICAgLy8gQnkgZGVmYXVsdCwgZmlsZXMgYWRkZWQgdmlhIGZpbGUgaW5wdXQgc2VsZWN0aW9uLCBwYXN0ZSwgZHJhZyAmIGRyb3Agb3JcclxuICAgIC8vIFwiYWRkXCIgbWV0aG9kIGFyZSB1cGxvYWRlZCBpbW1lZGlhdGVseSwgYnV0IGl0IGlzIHBvc3NpYmxlIHRvIG92ZXJyaWRlXHJcbiAgICAvLyB0aGUgXCJhZGRcIiBjYWxsYmFjayBvcHRpb24gdG8gcXVldWUgZmlsZSB1cGxvYWRzLlxyXG4gICAgJC53aWRnZXQoJ2JsdWVpbXAuZmlsZXVwbG9hZCcsIHtcclxuXHJcbiAgICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgICAgICAvLyBUaGUgZHJvcCB0YXJnZXQgZWxlbWVudChzKSwgYnkgdGhlIGRlZmF1bHQgdGhlIGNvbXBsZXRlIGRvY3VtZW50LlxyXG4gICAgICAgICAgICAvLyBTZXQgdG8gbnVsbCB0byBkaXNhYmxlIGRyYWcgJiBkcm9wIHN1cHBvcnQ6XHJcbiAgICAgICAgICAgIGRyb3Bab25lOiAkKGRvY3VtZW50KSxcclxuICAgICAgICAgICAgLy8gVGhlIHBhc3RlIHRhcmdldCBlbGVtZW50KHMpLCBieSB0aGUgZGVmYXVsdCB0aGUgY29tcGxldGUgZG9jdW1lbnQuXHJcbiAgICAgICAgICAgIC8vIFNldCB0byBudWxsIHRvIGRpc2FibGUgcGFzdGUgc3VwcG9ydDpcclxuICAgICAgICAgICAgcGFzdGVab25lOiAkKGRvY3VtZW50KSxcclxuICAgICAgICAgICAgLy8gVGhlIGZpbGUgaW5wdXQgZmllbGQocyksIHRoYXQgYXJlIGxpc3RlbmVkIHRvIGZvciBjaGFuZ2UgZXZlbnRzLlxyXG4gICAgICAgICAgICAvLyBJZiB1bmRlZmluZWQsIGl0IGlzIHNldCB0byB0aGUgZmlsZSBpbnB1dCBmaWVsZHMgaW5zaWRlXHJcbiAgICAgICAgICAgIC8vIG9mIHRoZSB3aWRnZXQgZWxlbWVudCBvbiBwbHVnaW4gaW5pdGlhbGl6YXRpb24uXHJcbiAgICAgICAgICAgIC8vIFNldCB0byBudWxsIHRvIGRpc2FibGUgdGhlIGNoYW5nZSBsaXN0ZW5lci5cclxuICAgICAgICAgICAgZmlsZUlucHV0OiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIHRoZSBmaWxlIGlucHV0IGZpZWxkIGlzIHJlcGxhY2VkIHdpdGggYSBjbG9uZSBhZnRlclxyXG4gICAgICAgICAgICAvLyBlYWNoIGlucHV0IGZpZWxkIGNoYW5nZSBldmVudC4gVGhpcyBpcyByZXF1aXJlZCBmb3IgaWZyYW1lIHRyYW5zcG9ydFxyXG4gICAgICAgICAgICAvLyBxdWV1ZXMgYW5kIGFsbG93cyBjaGFuZ2UgZXZlbnRzIHRvIGJlIGZpcmVkIGZvciB0aGUgc2FtZSBmaWxlXHJcbiAgICAgICAgICAgIC8vIHNlbGVjdGlvbiwgYnV0IGNhbiBiZSBkaXNhYmxlZCBieSBzZXR0aW5nIHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIGZhbHNlOlxyXG4gICAgICAgICAgICByZXBsYWNlRmlsZUlucHV0OiB0cnVlLFxyXG4gICAgICAgICAgICAvLyBUaGUgcGFyYW1ldGVyIG5hbWUgZm9yIHRoZSBmaWxlIGZvcm0gZGF0YSAodGhlIHJlcXVlc3QgYXJndW1lbnQgbmFtZSkuXHJcbiAgICAgICAgICAgIC8vIElmIHVuZGVmaW5lZCBvciBlbXB0eSwgdGhlIG5hbWUgcHJvcGVydHkgb2YgdGhlIGZpbGUgaW5wdXQgZmllbGQgaXNcclxuICAgICAgICAgICAgLy8gdXNlZCwgb3IgXCJmaWxlc1tdXCIgaWYgdGhlIGZpbGUgaW5wdXQgbmFtZSBwcm9wZXJ0eSBpcyBhbHNvIGVtcHR5LFxyXG4gICAgICAgICAgICAvLyBjYW4gYmUgYSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5nczpcclxuICAgICAgICAgICAgcGFyYW1OYW1lOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIGVhY2ggZmlsZSBvZiBhIHNlbGVjdGlvbiBpcyB1cGxvYWRlZCB1c2luZyBhbiBpbmRpdmlkdWFsXHJcbiAgICAgICAgICAgIC8vIHJlcXVlc3QgZm9yIFhIUiB0eXBlIHVwbG9hZHMuIFNldCB0byBmYWxzZSB0byB1cGxvYWQgZmlsZVxyXG4gICAgICAgICAgICAvLyBzZWxlY3Rpb25zIGluIG9uZSByZXF1ZXN0IGVhY2g6XHJcbiAgICAgICAgICAgIHNpbmdsZUZpbGVVcGxvYWRzOiB0cnVlLFxyXG4gICAgICAgICAgICAvLyBUbyBsaW1pdCB0aGUgbnVtYmVyIG9mIGZpbGVzIHVwbG9hZGVkIHdpdGggb25lIFhIUiByZXF1ZXN0LFxyXG4gICAgICAgICAgICAvLyBzZXQgdGhlIGZvbGxvd2luZyBvcHRpb24gdG8gYW4gaW50ZWdlciBncmVhdGVyIHRoYW4gMDpcclxuICAgICAgICAgICAgbGltaXRNdWx0aUZpbGVVcGxvYWRzOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgb3B0aW9uIGxpbWl0cyB0aGUgbnVtYmVyIG9mIGZpbGVzIHVwbG9hZGVkIHdpdGggb25lXHJcbiAgICAgICAgICAgIC8vIFhIUiByZXF1ZXN0IHRvIGtlZXAgdGhlIHJlcXVlc3Qgc2l6ZSB1bmRlciBvciBlcXVhbCB0byB0aGUgZGVmaW5lZFxyXG4gICAgICAgICAgICAvLyBsaW1pdCBpbiBieXRlczpcclxuICAgICAgICAgICAgbGltaXRNdWx0aUZpbGVVcGxvYWRTaXplOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIC8vIE11bHRpcGFydCBmaWxlIHVwbG9hZHMgYWRkIGEgbnVtYmVyIG9mIGJ5dGVzIHRvIGVhY2ggdXBsb2FkZWQgZmlsZSxcclxuICAgICAgICAgICAgLy8gdGhlcmVmb3JlIHRoZSBmb2xsb3dpbmcgb3B0aW9uIGFkZHMgYW4gb3ZlcmhlYWQgZm9yIGVhY2ggZmlsZSB1c2VkXHJcbiAgICAgICAgICAgIC8vIGluIHRoZSBsaW1pdE11bHRpRmlsZVVwbG9hZFNpemUgY29uZmlndXJhdGlvbjpcclxuICAgICAgICAgICAgbGltaXRNdWx0aUZpbGVVcGxvYWRTaXplT3ZlcmhlYWQ6IDUxMixcclxuICAgICAgICAgICAgLy8gU2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIHRydWUgdG8gaXNzdWUgYWxsIGZpbGUgdXBsb2FkIHJlcXVlc3RzXHJcbiAgICAgICAgICAgIC8vIGluIGEgc2VxdWVudGlhbCBvcmRlcjpcclxuICAgICAgICAgICAgc2VxdWVudGlhbFVwbG9hZHM6IGZhbHNlLFxyXG4gICAgICAgICAgICAvLyBUbyBsaW1pdCB0aGUgbnVtYmVyIG9mIGNvbmN1cnJlbnQgdXBsb2FkcyxcclxuICAgICAgICAgICAgLy8gc2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIGFuIGludGVnZXIgZ3JlYXRlciB0aGFuIDA6XHJcbiAgICAgICAgICAgIGxpbWl0Q29uY3VycmVudFVwbG9hZHM6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgLy8gU2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIHRydWUgdG8gZm9yY2UgaWZyYW1lIHRyYW5zcG9ydCB1cGxvYWRzOlxyXG4gICAgICAgICAgICBmb3JjZUlmcmFtZVRyYW5zcG9ydDogZmFsc2UsXHJcbiAgICAgICAgICAgIC8vIFNldCB0aGUgZm9sbG93aW5nIG9wdGlvbiB0byB0aGUgbG9jYXRpb24gb2YgYSByZWRpcmVjdCB1cmwgb24gdGhlXHJcbiAgICAgICAgICAgIC8vIG9yaWdpbiBzZXJ2ZXIsIGZvciBjcm9zcy1kb21haW4gaWZyYW1lIHRyYW5zcG9ydCB1cGxvYWRzOlxyXG4gICAgICAgICAgICByZWRpcmVjdDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAvLyBUaGUgcGFyYW1ldGVyIG5hbWUgZm9yIHRoZSByZWRpcmVjdCB1cmwsIHNlbnQgYXMgcGFydCBvZiB0aGUgZm9ybVxyXG4gICAgICAgICAgICAvLyBkYXRhIGFuZCBzZXQgdG8gJ3JlZGlyZWN0JyBpZiB0aGlzIG9wdGlvbiBpcyBlbXB0eTpcclxuICAgICAgICAgICAgcmVkaXJlY3RQYXJhbU5hbWU6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgLy8gU2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIHRoZSBsb2NhdGlvbiBvZiBhIHBvc3RNZXNzYWdlIHdpbmRvdyxcclxuICAgICAgICAgICAgLy8gdG8gZW5hYmxlIHBvc3RNZXNzYWdlIHRyYW5zcG9ydCB1cGxvYWRzOlxyXG4gICAgICAgICAgICBwb3N0TWVzc2FnZTogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAvLyBCeSBkZWZhdWx0LCBYSFIgZmlsZSB1cGxvYWRzIGFyZSBzZW50IGFzIG11bHRpcGFydC9mb3JtLWRhdGEuXHJcbiAgICAgICAgICAgIC8vIFRoZSBpZnJhbWUgdHJhbnNwb3J0IGlzIGFsd2F5cyB1c2luZyBtdWx0aXBhcnQvZm9ybS1kYXRhLlxyXG4gICAgICAgICAgICAvLyBTZXQgdG8gZmFsc2UgdG8gZW5hYmxlIG5vbi1tdWx0aXBhcnQgWEhSIHVwbG9hZHM6XHJcbiAgICAgICAgICAgIG11bHRpcGFydDogdHJ1ZSxcclxuICAgICAgICAgICAgLy8gVG8gdXBsb2FkIGxhcmdlIGZpbGVzIGluIHNtYWxsZXIgY2h1bmtzLCBzZXQgdGhlIGZvbGxvd2luZyBvcHRpb25cclxuICAgICAgICAgICAgLy8gdG8gYSBwcmVmZXJyZWQgbWF4aW11bSBjaHVuayBzaXplLiBJZiBzZXQgdG8gMCwgbnVsbCBvciB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgIC8vIG9yIHRoZSBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgdGhlIHJlcXVpcmVkIEJsb2IgQVBJLCBmaWxlcyB3aWxsXHJcbiAgICAgICAgICAgIC8vIGJlIHVwbG9hZGVkIGFzIGEgd2hvbGUuXHJcbiAgICAgICAgICAgIG1heENodW5rU2l6ZTogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAvLyBXaGVuIGEgbm9uLW11bHRpcGFydCB1cGxvYWQgb3IgYSBjaHVua2VkIG11bHRpcGFydCB1cGxvYWQgaGFzIGJlZW5cclxuICAgICAgICAgICAgLy8gYWJvcnRlZCwgdGhpcyBvcHRpb24gY2FuIGJlIHVzZWQgdG8gcmVzdW1lIHRoZSB1cGxvYWQgYnkgc2V0dGluZ1xyXG4gICAgICAgICAgICAvLyBpdCB0byB0aGUgc2l6ZSBvZiB0aGUgYWxyZWFkeSB1cGxvYWRlZCBieXRlcy4gVGhpcyBvcHRpb24gaXMgbW9zdFxyXG4gICAgICAgICAgICAvLyB1c2VmdWwgd2hlbiBtb2RpZnlpbmcgdGhlIG9wdGlvbnMgb2JqZWN0IGluc2lkZSBvZiB0aGUgXCJhZGRcIiBvclxyXG4gICAgICAgICAgICAvLyBcInNlbmRcIiBjYWxsYmFja3MsIGFzIHRoZSBvcHRpb25zIGFyZSBjbG9uZWQgZm9yIGVhY2ggZmlsZSB1cGxvYWQuXHJcbiAgICAgICAgICAgIHVwbG9hZGVkQnl0ZXM6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgLy8gQnkgZGVmYXVsdCwgZmFpbGVkIChhYm9ydCBvciBlcnJvcikgZmlsZSB1cGxvYWRzIGFyZSByZW1vdmVkIGZyb20gdGhlXHJcbiAgICAgICAgICAgIC8vIGdsb2JhbCBwcm9ncmVzcyBjYWxjdWxhdGlvbi4gU2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9uIHRvIGZhbHNlIHRvXHJcbiAgICAgICAgICAgIC8vIHByZXZlbnQgcmVjYWxjdWxhdGluZyB0aGUgZ2xvYmFsIHByb2dyZXNzIGRhdGE6XHJcbiAgICAgICAgICAgIHJlY2FsY3VsYXRlUHJvZ3Jlc3M6IHRydWUsXHJcbiAgICAgICAgICAgIC8vIEludGVydmFsIGluIG1pbGxpc2Vjb25kcyB0byBjYWxjdWxhdGUgYW5kIHRyaWdnZXIgcHJvZ3Jlc3MgZXZlbnRzOlxyXG4gICAgICAgICAgICBwcm9ncmVzc0ludGVydmFsOiAxMDAsXHJcbiAgICAgICAgICAgIC8vIEludGVydmFsIGluIG1pbGxpc2Vjb25kcyB0byBjYWxjdWxhdGUgcHJvZ3Jlc3MgYml0cmF0ZTpcclxuICAgICAgICAgICAgYml0cmF0ZUludGVydmFsOiA1MDAsXHJcbiAgICAgICAgICAgIC8vIEJ5IGRlZmF1bHQsIHVwbG9hZHMgYXJlIHN0YXJ0ZWQgYXV0b21hdGljYWxseSB3aGVuIGFkZGluZyBmaWxlczpcclxuICAgICAgICAgICAgYXV0b1VwbG9hZDogdHJ1ZSxcclxuXHJcbiAgICAgICAgICAgIC8vIEVycm9yIGFuZCBpbmZvIG1lc3NhZ2VzOlxyXG4gICAgICAgICAgICBtZXNzYWdlczoge1xyXG4gICAgICAgICAgICAgICAgdXBsb2FkZWRCeXRlczogJ1VwbG9hZGVkIGJ5dGVzIGV4Y2VlZCBmaWxlIHNpemUnXHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAvLyBUcmFuc2xhdGlvbiBmdW5jdGlvbiwgZ2V0cyB0aGUgbWVzc2FnZSBrZXkgdG8gYmUgdHJhbnNsYXRlZFxyXG4gICAgICAgICAgICAvLyBhbmQgYW4gb2JqZWN0IHdpdGggY29udGV4dCBzcGVjaWZpYyBkYXRhIGFzIGFyZ3VtZW50czpcclxuICAgICAgICAgICAgaTE4bjogZnVuY3Rpb24gKG1lc3NhZ2UsIGNvbnRleHQpIHtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2VzW21lc3NhZ2VdIHx8IG1lc3NhZ2UudG9TdHJpbmcoKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb250ZXh0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgJC5lYWNoKGNvbnRleHQsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBtZXNzYWdlLnJlcGxhY2UoJ3snICsga2V5ICsgJ30nLCB2YWx1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIC8vIEFkZGl0aW9uYWwgZm9ybSBkYXRhIHRvIGJlIHNlbnQgYWxvbmcgd2l0aCB0aGUgZmlsZSB1cGxvYWRzIGNhbiBiZSBzZXRcclxuICAgICAgICAgICAgLy8gdXNpbmcgdGhpcyBvcHRpb24sIHdoaWNoIGFjY2VwdHMgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoIG5hbWUgYW5kXHJcbiAgICAgICAgICAgIC8vIHZhbHVlIHByb3BlcnRpZXMsIGEgZnVuY3Rpb24gcmV0dXJuaW5nIHN1Y2ggYW4gYXJyYXksIGEgRm9ybURhdGFcclxuICAgICAgICAgICAgLy8gb2JqZWN0IChmb3IgWEhSIGZpbGUgdXBsb2FkcyksIG9yIGEgc2ltcGxlIG9iamVjdC5cclxuICAgICAgICAgICAgLy8gVGhlIGZvcm0gb2YgdGhlIGZpcnN0IGZpbGVJbnB1dCBpcyBnaXZlbiBhcyBwYXJhbWV0ZXIgdG8gdGhlIGZ1bmN0aW9uOlxyXG4gICAgICAgICAgICBmb3JtRGF0YTogZnVuY3Rpb24gKGZvcm0pIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtLnNlcmlhbGl6ZUFycmF5KCk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAvLyBUaGUgYWRkIGNhbGxiYWNrIGlzIGludm9rZWQgYXMgc29vbiBhcyBmaWxlcyBhcmUgYWRkZWQgdG8gdGhlIGZpbGV1cGxvYWRcclxuICAgICAgICAgICAgLy8gd2lkZ2V0ICh2aWEgZmlsZSBpbnB1dCBzZWxlY3Rpb24sIGRyYWcgJiBkcm9wLCBwYXN0ZSBvciBhZGQgQVBJIGNhbGwpLlxyXG4gICAgICAgICAgICAvLyBJZiB0aGUgc2luZ2xlRmlsZVVwbG9hZHMgb3B0aW9uIGlzIGVuYWJsZWQsIHRoaXMgY2FsbGJhY2sgd2lsbCBiZVxyXG4gICAgICAgICAgICAvLyBjYWxsZWQgb25jZSBmb3IgZWFjaCBmaWxlIGluIHRoZSBzZWxlY3Rpb24gZm9yIFhIUiBmaWxlIHVwbG9hZHMsIGVsc2VcclxuICAgICAgICAgICAgLy8gb25jZSBmb3IgZWFjaCBmaWxlIHNlbGVjdGlvbi5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gVGhlIHVwbG9hZCBzdGFydHMgd2hlbiB0aGUgc3VibWl0IG1ldGhvZCBpcyBpbnZva2VkIG9uIHRoZSBkYXRhIHBhcmFtZXRlci5cclxuICAgICAgICAgICAgLy8gVGhlIGRhdGEgb2JqZWN0IGNvbnRhaW5zIGEgZmlsZXMgcHJvcGVydHkgaG9sZGluZyB0aGUgYWRkZWQgZmlsZXNcclxuICAgICAgICAgICAgLy8gYW5kIGFsbG93cyB5b3UgdG8gb3ZlcnJpZGUgcGx1Z2luIG9wdGlvbnMgYXMgd2VsbCBhcyBkZWZpbmUgYWpheCBzZXR0aW5ncy5cclxuICAgICAgICAgICAgLy9cclxuICAgICAgICAgICAgLy8gTGlzdGVuZXJzIGZvciB0aGlzIGNhbGxiYWNrIGNhbiBhbHNvIGJlIGJvdW5kIHRoZSBmb2xsb3dpbmcgd2F5OlxyXG4gICAgICAgICAgICAvLyAuYmluZCgnZmlsZXVwbG9hZGFkZCcsIGZ1bmMpO1xyXG4gICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAvLyBkYXRhLnN1Ym1pdCgpIHJldHVybnMgYSBQcm9taXNlIG9iamVjdCBhbmQgYWxsb3dzIHRvIGF0dGFjaCBhZGRpdGlvbmFsXHJcbiAgICAgICAgICAgIC8vIGhhbmRsZXJzIHVzaW5nIGpRdWVyeSdzIERlZmVycmVkIGNhbGxiYWNrczpcclxuICAgICAgICAgICAgLy8gZGF0YS5zdWJtaXQoKS5kb25lKGZ1bmMpLmZhaWwoZnVuYykuYWx3YXlzKGZ1bmMpO1xyXG4gICAgICAgICAgICBhZGQ6IGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChkYXRhLmF1dG9VcGxvYWQgfHwgKGRhdGEuYXV0b1VwbG9hZCAhPT0gZmFsc2UgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgJCh0aGlzKS5maWxldXBsb2FkKCdvcHRpb24nLCAnYXV0b1VwbG9hZCcpKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEucHJvY2VzcygpLmRvbmUoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnN1Ym1pdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgLy8gT3RoZXIgY2FsbGJhY2tzOlxyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIHRoZSBzdWJtaXQgZXZlbnQgb2YgZWFjaCBmaWxlIHVwbG9hZDpcclxuICAgICAgICAgICAgLy8gc3VibWl0OiBmdW5jdGlvbiAoZSwgZGF0YSkge30sIC8vIC5iaW5kKCdmaWxldXBsb2Fkc3VibWl0JywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgdGhlIHN0YXJ0IG9mIGVhY2ggZmlsZSB1cGxvYWQgcmVxdWVzdDpcclxuICAgICAgICAgICAgLy8gc2VuZDogZnVuY3Rpb24gKGUsIGRhdGEpIHt9LCAvLyAuYmluZCgnZmlsZXVwbG9hZHNlbmQnLCBmdW5jKTtcclxuXHJcbiAgICAgICAgICAgIC8vIENhbGxiYWNrIGZvciBzdWNjZXNzZnVsIHVwbG9hZHM6XHJcbiAgICAgICAgICAgIC8vIGRvbmU6IGZ1bmN0aW9uIChlLCBkYXRhKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRkb25lJywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgZmFpbGVkIChhYm9ydCBvciBlcnJvcikgdXBsb2FkczpcclxuICAgICAgICAgICAgLy8gZmFpbDogZnVuY3Rpb24gKGUsIGRhdGEpIHt9LCAvLyAuYmluZCgnZmlsZXVwbG9hZGZhaWwnLCBmdW5jKTtcclxuXHJcbiAgICAgICAgICAgIC8vIENhbGxiYWNrIGZvciBjb21wbGV0ZWQgKHN1Y2Nlc3MsIGFib3J0IG9yIGVycm9yKSByZXF1ZXN0czpcclxuICAgICAgICAgICAgLy8gYWx3YXlzOiBmdW5jdGlvbiAoZSwgZGF0YSkge30sIC8vIC5iaW5kKCdmaWxldXBsb2FkYWx3YXlzJywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgdXBsb2FkIHByb2dyZXNzIGV2ZW50czpcclxuICAgICAgICAgICAgLy8gcHJvZ3Jlc3M6IGZ1bmN0aW9uIChlLCBkYXRhKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRwcm9ncmVzcycsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIGdsb2JhbCB1cGxvYWQgcHJvZ3Jlc3MgZXZlbnRzOlxyXG4gICAgICAgICAgICAvLyBwcm9ncmVzc2FsbDogZnVuY3Rpb24gKGUsIGRhdGEpIHt9LCAvLyAuYmluZCgnZmlsZXVwbG9hZHByb2dyZXNzYWxsJywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgdXBsb2FkcyBzdGFydCwgZXF1aXZhbGVudCB0byB0aGUgZ2xvYmFsIGFqYXhTdGFydCBldmVudDpcclxuICAgICAgICAgICAgLy8gc3RhcnQ6IGZ1bmN0aW9uIChlKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRzdGFydCcsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIHVwbG9hZHMgc3RvcCwgZXF1aXZhbGVudCB0byB0aGUgZ2xvYmFsIGFqYXhTdG9wIGV2ZW50OlxyXG4gICAgICAgICAgICAvLyBzdG9wOiBmdW5jdGlvbiAoZSkge30sIC8vIC5iaW5kKCdmaWxldXBsb2Fkc3RvcCcsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIGNoYW5nZSBldmVudHMgb2YgdGhlIGZpbGVJbnB1dChzKTpcclxuICAgICAgICAgICAgLy8gY2hhbmdlOiBmdW5jdGlvbiAoZSwgZGF0YSkge30sIC8vIC5iaW5kKCdmaWxldXBsb2FkY2hhbmdlJywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgcGFzdGUgZXZlbnRzIHRvIHRoZSBwYXN0ZVpvbmUocyk6XHJcbiAgICAgICAgICAgIC8vIHBhc3RlOiBmdW5jdGlvbiAoZSwgZGF0YSkge30sIC8vIC5iaW5kKCdmaWxldXBsb2FkcGFzdGUnLCBmdW5jKTtcclxuXHJcbiAgICAgICAgICAgIC8vIENhbGxiYWNrIGZvciBkcm9wIGV2ZW50cyBvZiB0aGUgZHJvcFpvbmUocyk6XHJcbiAgICAgICAgICAgIC8vIGRyb3A6IGZ1bmN0aW9uIChlLCBkYXRhKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRkcm9wJywgZnVuYyk7XHJcblxyXG4gICAgICAgICAgICAvLyBDYWxsYmFjayBmb3IgZHJhZ292ZXIgZXZlbnRzIG9mIHRoZSBkcm9wWm9uZShzKTpcclxuICAgICAgICAgICAgLy8gZHJhZ292ZXI6IGZ1bmN0aW9uIChlKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRkcmFnb3ZlcicsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIHRoZSBzdGFydCBvZiBlYWNoIGNodW5rIHVwbG9hZCByZXF1ZXN0OlxyXG4gICAgICAgICAgICAvLyBjaHVua3NlbmQ6IGZ1bmN0aW9uIChlLCBkYXRhKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRjaHVua3NlbmQnLCBmdW5jKTtcclxuXHJcbiAgICAgICAgICAgIC8vIENhbGxiYWNrIGZvciBzdWNjZXNzZnVsIGNodW5rIHVwbG9hZHM6XHJcbiAgICAgICAgICAgIC8vIGNodW5rZG9uZTogZnVuY3Rpb24gKGUsIGRhdGEpIHt9LCAvLyAuYmluZCgnZmlsZXVwbG9hZGNodW5rZG9uZScsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIGZhaWxlZCAoYWJvcnQgb3IgZXJyb3IpIGNodW5rIHVwbG9hZHM6XHJcbiAgICAgICAgICAgIC8vIGNodW5rZmFpbDogZnVuY3Rpb24gKGUsIGRhdGEpIHt9LCAvLyAuYmluZCgnZmlsZXVwbG9hZGNodW5rZmFpbCcsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gQ2FsbGJhY2sgZm9yIGNvbXBsZXRlZCAoc3VjY2VzcywgYWJvcnQgb3IgZXJyb3IpIGNodW5rIHVwbG9hZCByZXF1ZXN0czpcclxuICAgICAgICAgICAgLy8gY2h1bmthbHdheXM6IGZ1bmN0aW9uIChlLCBkYXRhKSB7fSwgLy8gLmJpbmQoJ2ZpbGV1cGxvYWRjaHVua2Fsd2F5cycsIGZ1bmMpO1xyXG5cclxuICAgICAgICAgICAgLy8gVGhlIHBsdWdpbiBvcHRpb25zIGFyZSB1c2VkIGFzIHNldHRpbmdzIG9iamVjdCBmb3IgdGhlIGFqYXggY2FsbHMuXHJcbiAgICAgICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgYXJlIGpRdWVyeSBhamF4IHNldHRpbmdzIHJlcXVpcmVkIGZvciB0aGUgZmlsZSB1cGxvYWRzOlxyXG4gICAgICAgICAgICBwcm9jZXNzRGF0YTogZmFsc2UsXHJcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBmYWxzZSxcclxuICAgICAgICAgICAgY2FjaGU6IGZhbHNlXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8gQSBsaXN0IG9mIG9wdGlvbnMgdGhhdCByZXF1aXJlIHJlaW5pdGlhbGl6aW5nIGV2ZW50IGxpc3RlbmVycyBhbmQvb3JcclxuICAgICAgICAvLyBzcGVjaWFsIGluaXRpYWxpemF0aW9uIGNvZGU6XHJcbiAgICAgICAgX3NwZWNpYWxPcHRpb25zOiBbXHJcbiAgICAgICAgICAgICdmaWxlSW5wdXQnLFxyXG4gICAgICAgICAgICAnZHJvcFpvbmUnLFxyXG4gICAgICAgICAgICAncGFzdGVab25lJyxcclxuICAgICAgICAgICAgJ211bHRpcGFydCcsXHJcbiAgICAgICAgICAgICdmb3JjZUlmcmFtZVRyYW5zcG9ydCdcclxuICAgICAgICBdLFxyXG5cclxuICAgICAgICBfYmxvYlNsaWNlOiAkLnN1cHBvcnQuYmxvYlNsaWNlICYmIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHNsaWNlID0gdGhpcy5zbGljZSB8fCB0aGlzLndlYmtpdFNsaWNlIHx8IHRoaXMubW96U2xpY2U7XHJcbiAgICAgICAgICAgIHJldHVybiBzbGljZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9CaXRyYXRlVGltZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdGhpcy50aW1lc3RhbXAgPSAoKERhdGUubm93KSA/IERhdGUubm93KCkgOiAobmV3IERhdGUoKSkuZ2V0VGltZSgpKTtcclxuICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLmJpdHJhdGUgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLmdldEJpdHJhdGUgPSBmdW5jdGlvbiAobm93LCBsb2FkZWQsIGludGVydmFsKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGltZURpZmYgPSBub3cgLSB0aGlzLnRpbWVzdGFtcDtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5iaXRyYXRlIHx8ICFpbnRlcnZhbCB8fCB0aW1lRGlmZiA+IGludGVydmFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5iaXRyYXRlID0gKGxvYWRlZCAtIHRoaXMubG9hZGVkKSAqICgxMDAwIC8gdGltZURpZmYpICogODtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRlZCA9IGxvYWRlZDtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnRpbWVzdGFtcCA9IG5vdztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmJpdHJhdGU7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2lzWEhSVXBsb2FkOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICByZXR1cm4gIW9wdGlvbnMuZm9yY2VJZnJhbWVUcmFuc3BvcnQgJiZcclxuICAgICAgICAgICAgICAgICgoIW9wdGlvbnMubXVsdGlwYXJ0ICYmICQuc3VwcG9ydC54aHJGaWxlVXBsb2FkKSB8fFxyXG4gICAgICAgICAgICAgICAgJC5zdXBwb3J0LnhockZvcm1EYXRhRmlsZVVwbG9hZCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2dldEZvcm1EYXRhOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICB2YXIgZm9ybURhdGE7XHJcbiAgICAgICAgICAgIGlmICgkLnR5cGUob3B0aW9ucy5mb3JtRGF0YSkgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmZvcm1EYXRhKG9wdGlvbnMuZm9ybSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCQuaXNBcnJheShvcHRpb25zLmZvcm1EYXRhKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuZm9ybURhdGE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCQudHlwZShvcHRpb25zLmZvcm1EYXRhKSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgICAgICAgIGZvcm1EYXRhID0gW107XHJcbiAgICAgICAgICAgICAgICAkLmVhY2gob3B0aW9ucy5mb3JtRGF0YSwgZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9ybURhdGEucHVzaCh7bmFtZTogbmFtZSwgdmFsdWU6IHZhbHVlfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtRGF0YTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2dldFRvdGFsOiBmdW5jdGlvbiAoZmlsZXMpIHtcclxuICAgICAgICAgICAgdmFyIHRvdGFsID0gMDtcclxuICAgICAgICAgICAgJC5lYWNoKGZpbGVzLCBmdW5jdGlvbiAoaW5kZXgsIGZpbGUpIHtcclxuICAgICAgICAgICAgICAgIHRvdGFsICs9IGZpbGUuc2l6ZSB8fCAxO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIHRvdGFsO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9pbml0UHJvZ3Jlc3NPYmplY3Q6IGZ1bmN0aW9uIChvYmopIHtcclxuICAgICAgICAgICAgdmFyIHByb2dyZXNzID0ge1xyXG4gICAgICAgICAgICAgICAgbG9hZGVkOiAwLFxyXG4gICAgICAgICAgICAgICAgdG90YWw6IDAsXHJcbiAgICAgICAgICAgICAgICBiaXRyYXRlOiAwXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGlmIChvYmouX3Byb2dyZXNzKSB7XHJcbiAgICAgICAgICAgICAgICAkLmV4dGVuZChvYmouX3Byb2dyZXNzLCBwcm9ncmVzcyk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBvYmouX3Byb2dyZXNzID0gcHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfaW5pdFJlc3BvbnNlT2JqZWN0OiBmdW5jdGlvbiAob2JqKSB7XHJcbiAgICAgICAgICAgIHZhciBwcm9wO1xyXG4gICAgICAgICAgICBpZiAob2JqLl9yZXNwb25zZSkge1xyXG4gICAgICAgICAgICAgICAgZm9yIChwcm9wIGluIG9iai5fcmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAob2JqLl9yZXNwb25zZS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqLl9yZXNwb25zZVtwcm9wXTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBvYmouX3Jlc3BvbnNlID0ge307XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfb25Qcm9ncmVzczogZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuICAgICAgICAgICAgaWYgKGUubGVuZ3RoQ29tcHV0YWJsZSkge1xyXG4gICAgICAgICAgICAgICAgdmFyIG5vdyA9ICgoRGF0ZS5ub3cpID8gRGF0ZS5ub3coKSA6IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkpLFxyXG4gICAgICAgICAgICAgICAgICAgIGxvYWRlZDtcclxuICAgICAgICAgICAgICAgIGlmIChkYXRhLl90aW1lICYmIGRhdGEucHJvZ3Jlc3NJbnRlcnZhbCAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAobm93IC0gZGF0YS5fdGltZSA8IGRhdGEucHJvZ3Jlc3NJbnRlcnZhbCkgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgZS5sb2FkZWQgIT09IGUudG90YWwpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBkYXRhLl90aW1lID0gbm93O1xyXG4gICAgICAgICAgICAgICAgbG9hZGVkID0gTWF0aC5mbG9vcihcclxuICAgICAgICAgICAgICAgICAgICBlLmxvYWRlZCAvIGUudG90YWwgKiAoZGF0YS5jaHVua1NpemUgfHwgZGF0YS5fcHJvZ3Jlc3MudG90YWwpXHJcbiAgICAgICAgICAgICAgICApICsgKGRhdGEudXBsb2FkZWRCeXRlcyB8fCAwKTtcclxuICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgZGlmZmVyZW5jZSBmcm9tIHRoZSBwcmV2aW91c2x5IGxvYWRlZCBzdGF0ZVxyXG4gICAgICAgICAgICAgICAgLy8gdG8gdGhlIGdsb2JhbCBsb2FkZWQgY291bnRlcjpcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Byb2dyZXNzLmxvYWRlZCArPSAobG9hZGVkIC0gZGF0YS5fcHJvZ3Jlc3MubG9hZGVkKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Byb2dyZXNzLmJpdHJhdGUgPSB0aGlzLl9iaXRyYXRlVGltZXIuZ2V0Qml0cmF0ZShcclxuICAgICAgICAgICAgICAgICAgICBub3csXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3MubG9hZGVkLFxyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuYml0cmF0ZUludGVydmFsXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgZGF0YS5fcHJvZ3Jlc3MubG9hZGVkID0gZGF0YS5sb2FkZWQgPSBsb2FkZWQ7XHJcbiAgICAgICAgICAgICAgICBkYXRhLl9wcm9ncmVzcy5iaXRyYXRlID0gZGF0YS5iaXRyYXRlID0gZGF0YS5fYml0cmF0ZVRpbWVyLmdldEJpdHJhdGUoXHJcbiAgICAgICAgICAgICAgICAgICAgbm93LFxyXG4gICAgICAgICAgICAgICAgICAgIGxvYWRlZCxcclxuICAgICAgICAgICAgICAgICAgICBkYXRhLmJpdHJhdGVJbnRlcnZhbFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIC8vIFRyaWdnZXIgYSBjdXN0b20gcHJvZ3Jlc3MgZXZlbnQgd2l0aCBhIHRvdGFsIGRhdGEgcHJvcGVydHkgc2V0XHJcbiAgICAgICAgICAgICAgICAvLyB0byB0aGUgZmlsZSBzaXplKHMpIG9mIHRoZSBjdXJyZW50IHVwbG9hZCBhbmQgYSBsb2FkZWQgZGF0YVxyXG4gICAgICAgICAgICAgICAgLy8gcHJvcGVydHkgY2FsY3VsYXRlZCBhY2NvcmRpbmdseTpcclxuICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgJ3Byb2dyZXNzJyxcclxuICAgICAgICAgICAgICAgICAgICAkLkV2ZW50KCdwcm9ncmVzcycsIHtkZWxlZ2F0ZWRFdmVudDogZX0pLFxyXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGEgZ2xvYmFsIHByb2dyZXNzIGV2ZW50IGZvciBhbGwgY3VycmVudCBmaWxlIHVwbG9hZHMsXHJcbiAgICAgICAgICAgICAgICAvLyBpbmNsdWRpbmcgYWpheCBjYWxscyBxdWV1ZWQgZm9yIHNlcXVlbnRpYWwgZmlsZSB1cGxvYWRzOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlcihcclxuICAgICAgICAgICAgICAgICAgICAncHJvZ3Jlc3NhbGwnLFxyXG4gICAgICAgICAgICAgICAgICAgICQuRXZlbnQoJ3Byb2dyZXNzYWxsJywge2RlbGVnYXRlZEV2ZW50OiBlfSksXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3NcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfaW5pdFByb2dyZXNzTGlzdGVuZXI6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgICAgICAgIHhociA9IG9wdGlvbnMueGhyID8gb3B0aW9ucy54aHIoKSA6ICQuYWpheFNldHRpbmdzLnhocigpO1xyXG4gICAgICAgICAgICAvLyBBY2Nlc3NzIHRvIHRoZSBuYXRpdmUgWEhSIG9iamVjdCBpcyByZXF1aXJlZCB0byBhZGQgZXZlbnQgbGlzdGVuZXJzXHJcbiAgICAgICAgICAgIC8vIGZvciB0aGUgdXBsb2FkIHByb2dyZXNzIGV2ZW50OlxyXG4gICAgICAgICAgICBpZiAoeGhyLnVwbG9hZCkge1xyXG4gICAgICAgICAgICAgICAgJCh4aHIudXBsb2FkKS5iaW5kKCdwcm9ncmVzcycsIGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9lID0gZS5vcmlnaW5hbEV2ZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0aGUgcHJvZ3Jlc3MgZXZlbnQgcHJvcGVydGllcyBnZXQgY29waWVkIG92ZXI6XHJcbiAgICAgICAgICAgICAgICAgICAgZS5sZW5ndGhDb21wdXRhYmxlID0gb2UubGVuZ3RoQ29tcHV0YWJsZTtcclxuICAgICAgICAgICAgICAgICAgICBlLmxvYWRlZCA9IG9lLmxvYWRlZDtcclxuICAgICAgICAgICAgICAgICAgICBlLnRvdGFsID0gb2UudG90YWw7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fb25Qcm9ncmVzcyhlLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy54aHIgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHhocjtcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfaXNJbnN0YW5jZU9mOiBmdW5jdGlvbiAodHlwZSwgb2JqKSB7XHJcbiAgICAgICAgICAgIC8vIENyb3NzLWZyYW1lIGluc3RhbmNlb2YgY2hlY2tcclxuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCAnICsgdHlwZSArICddJztcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfaW5pdFhIUkRhdGE6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgICAgICAgIGZvcm1EYXRhLFxyXG4gICAgICAgICAgICAgICAgZmlsZSA9IG9wdGlvbnMuZmlsZXNbMF0sXHJcbiAgICAgICAgICAgICAgICAvLyBJZ25vcmUgbm9uLW11bHRpcGFydCBzZXR0aW5nIGlmIG5vdCBzdXBwb3J0ZWQ6XHJcbiAgICAgICAgICAgICAgICBtdWx0aXBhcnQgPSBvcHRpb25zLm11bHRpcGFydCB8fCAhJC5zdXBwb3J0LnhockZpbGVVcGxvYWQsXHJcbiAgICAgICAgICAgICAgICBwYXJhbU5hbWUgPSAkLnR5cGUob3B0aW9ucy5wYXJhbU5hbWUpID09PSAnYXJyYXknID9cclxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLnBhcmFtTmFtZVswXSA6IG9wdGlvbnMucGFyYW1OYW1lO1xyXG4gICAgICAgICAgICBvcHRpb25zLmhlYWRlcnMgPSAkLmV4dGVuZCh7fSwgb3B0aW9ucy5oZWFkZXJzKTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY29udGVudFJhbmdlKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmhlYWRlcnNbJ0NvbnRlbnQtUmFuZ2UnXSA9IG9wdGlvbnMuY29udGVudFJhbmdlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghbXVsdGlwYXJ0IHx8IG9wdGlvbnMuYmxvYiB8fCAhdGhpcy5faXNJbnN0YW5jZU9mKCdGaWxlJywgZmlsZSkpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuaGVhZGVyc1snQ29udGVudC1EaXNwb3NpdGlvbiddID0gJ2F0dGFjaG1lbnQ7IGZpbGVuYW1lPVwiJyArXHJcbiAgICAgICAgICAgICAgICAgICAgZW5jb2RlVVJJKGZpbGUubmFtZSkgKyAnXCInO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghbXVsdGlwYXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmNvbnRlbnRUeXBlID0gZmlsZS50eXBlIHx8ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nO1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5kYXRhID0gb3B0aW9ucy5ibG9iIHx8IGZpbGU7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoJC5zdXBwb3J0LnhockZvcm1EYXRhRmlsZVVwbG9hZCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMucG9zdE1lc3NhZ2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyB3aW5kb3cucG9zdE1lc3NhZ2UgZG9lcyBub3QgYWxsb3cgc2VuZGluZyBGb3JtRGF0YVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIG9iamVjdHMsIHNvIHdlIGp1c3QgYWRkIHRoZSBGaWxlL0Jsb2Igb2JqZWN0cyB0b1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmb3JtRGF0YSBhcnJheSBhbmQgbGV0IHRoZSBwb3N0TWVzc2FnZSB3aW5kb3dcclxuICAgICAgICAgICAgICAgICAgICAvLyBjcmVhdGUgdGhlIEZvcm1EYXRhIG9iamVjdCBvdXQgb2YgdGhpcyBhcnJheTpcclxuICAgICAgICAgICAgICAgICAgICBmb3JtRGF0YSA9IHRoaXMuX2dldEZvcm1EYXRhKG9wdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmJsb2IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybURhdGEucHVzaCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBwYXJhbU5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogb3B0aW9ucy5ibG9iXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICQuZWFjaChvcHRpb25zLmZpbGVzLCBmdW5jdGlvbiAoaW5kZXgsIGZpbGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1EYXRhLnB1c2goe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICgkLnR5cGUob3B0aW9ucy5wYXJhbU5hbWUpID09PSAnYXJyYXknICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMucGFyYW1OYW1lW2luZGV4XSkgfHwgcGFyYW1OYW1lLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBmaWxlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5faXNJbnN0YW5jZU9mKCdGb3JtRGF0YScsIG9wdGlvbnMuZm9ybURhdGEpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1EYXRhID0gb3B0aW9ucy5mb3JtRGF0YTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2godGhpcy5fZ2V0Rm9ybURhdGEob3B0aW9ucyksIGZ1bmN0aW9uIChpbmRleCwgZmllbGQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChmaWVsZC5uYW1lLCBmaWVsZC52YWx1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5ibG9iKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChwYXJhbU5hbWUsIG9wdGlvbnMuYmxvYiwgZmlsZS5uYW1lKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAkLmVhY2gob3B0aW9ucy5maWxlcywgZnVuY3Rpb24gKGluZGV4LCBmaWxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGNoZWNrIGFsbG93cyB0aGUgdGVzdHMgdG8gcnVuIHdpdGhcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGR1bW15IG9iamVjdHM6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5faXNJbnN0YW5jZU9mKCdGaWxlJywgZmlsZSkgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5faXNJbnN0YW5jZU9mKCdCbG9iJywgZmlsZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtRGF0YS5hcHBlbmQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgkLnR5cGUob3B0aW9ucy5wYXJhbU5hbWUpID09PSAnYXJyYXknICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLnBhcmFtTmFtZVtpbmRleF0pIHx8IHBhcmFtTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZS51cGxvYWROYW1lIHx8IGZpbGUubmFtZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZGF0YSA9IGZvcm1EYXRhO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIEJsb2IgcmVmZXJlbmNlIGlzIG5vdCBuZWVkZWQgYW55bW9yZSwgZnJlZSBtZW1vcnk6XHJcbiAgICAgICAgICAgIG9wdGlvbnMuYmxvYiA9IG51bGw7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2luaXRJZnJhbWVTZXR0aW5nczogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdmFyIHRhcmdldEhvc3QgPSAkKCc8YT48L2E+JykucHJvcCgnaHJlZicsIG9wdGlvbnMudXJsKS5wcm9wKCdob3N0Jyk7XHJcbiAgICAgICAgICAgIC8vIFNldHRpbmcgdGhlIGRhdGFUeXBlIHRvIGlmcmFtZSBlbmFibGVzIHRoZSBpZnJhbWUgdHJhbnNwb3J0OlxyXG4gICAgICAgICAgICBvcHRpb25zLmRhdGFUeXBlID0gJ2lmcmFtZSAnICsgKG9wdGlvbnMuZGF0YVR5cGUgfHwgJycpO1xyXG4gICAgICAgICAgICAvLyBUaGUgaWZyYW1lIHRyYW5zcG9ydCBhY2NlcHRzIGEgc2VyaWFsaXplZCBhcnJheSBhcyBmb3JtIGRhdGE6XHJcbiAgICAgICAgICAgIG9wdGlvbnMuZm9ybURhdGEgPSB0aGlzLl9nZXRGb3JtRGF0YShvcHRpb25zKTtcclxuICAgICAgICAgICAgLy8gQWRkIHJlZGlyZWN0IHVybCB0byBmb3JtIGRhdGEgb24gY3Jvc3MtZG9tYWluIHVwbG9hZHM6XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zLnJlZGlyZWN0ICYmIHRhcmdldEhvc3QgJiYgdGFyZ2V0SG9zdCAhPT0gbG9jYXRpb24uaG9zdCkge1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5mb3JtRGF0YS5wdXNoKHtcclxuICAgICAgICAgICAgICAgICAgICBuYW1lOiBvcHRpb25zLnJlZGlyZWN0UGFyYW1OYW1lIHx8ICdyZWRpcmVjdCcsXHJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG9wdGlvbnMucmVkaXJlY3RcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2luaXREYXRhU2V0dGluZ3M6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9pc1hIUlVwbG9hZChvcHRpb25zKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9jaHVua2VkVXBsb2FkKG9wdGlvbnMsIHRydWUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvcHRpb25zLmRhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5pdFhIUkRhdGEob3B0aW9ucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2luaXRQcm9ncmVzc0xpc3RlbmVyKG9wdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMucG9zdE1lc3NhZ2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBTZXR0aW5nIHRoZSBkYXRhVHlwZSB0byBwb3N0bWVzc2FnZSBlbmFibGVzIHRoZVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHBvc3RNZXNzYWdlIHRyYW5zcG9ydDpcclxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmRhdGFUeXBlID0gJ3Bvc3RtZXNzYWdlICcgKyAob3B0aW9ucy5kYXRhVHlwZSB8fCAnJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0SWZyYW1lU2V0dGluZ3Mob3B0aW9ucyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfZ2V0UGFyYW1OYW1lOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICB2YXIgZmlsZUlucHV0ID0gJChvcHRpb25zLmZpbGVJbnB1dCksXHJcbiAgICAgICAgICAgICAgICBwYXJhbU5hbWUgPSBvcHRpb25zLnBhcmFtTmFtZTtcclxuICAgICAgICAgICAgaWYgKCFwYXJhbU5hbWUpIHtcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZSA9IFtdO1xyXG4gICAgICAgICAgICAgICAgZmlsZUlucHV0LmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9ICQodGhpcyksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBpbnB1dC5wcm9wKCduYW1lJykgfHwgJ2ZpbGVzW10nLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpID0gKGlucHV0LnByb3AoJ2ZpbGVzJykgfHwgWzFdKS5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lLnB1c2gobmFtZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGkgLT0gMTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIGlmICghcGFyYW1OYW1lLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtTmFtZSA9IFtmaWxlSW5wdXQucHJvcCgnbmFtZScpIHx8ICdmaWxlc1tdJ107XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoISQuaXNBcnJheShwYXJhbU5hbWUpKSB7XHJcbiAgICAgICAgICAgICAgICBwYXJhbU5hbWUgPSBbcGFyYW1OYW1lXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gcGFyYW1OYW1lO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9pbml0Rm9ybVNldHRpbmdzOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICAvLyBSZXRyaWV2ZSBtaXNzaW5nIG9wdGlvbnMgZnJvbSB0aGUgaW5wdXQgZmllbGQgYW5kIHRoZVxyXG4gICAgICAgICAgICAvLyBhc3NvY2lhdGVkIGZvcm0sIGlmIGF2YWlsYWJsZTpcclxuICAgICAgICAgICAgaWYgKCFvcHRpb25zLmZvcm0gfHwgIW9wdGlvbnMuZm9ybS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZm9ybSA9ICQob3B0aW9ucy5maWxlSW5wdXQucHJvcCgnZm9ybScpKTtcclxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBnaXZlbiBmaWxlIGlucHV0IGRvZXNuJ3QgaGF2ZSBhbiBhc3NvY2lhdGVkIGZvcm0sXHJcbiAgICAgICAgICAgICAgICAvLyB1c2UgdGhlIGRlZmF1bHQgd2lkZ2V0IGZpbGUgaW5wdXQncyBmb3JtOlxyXG4gICAgICAgICAgICAgICAgaWYgKCFvcHRpb25zLmZvcm0ubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5mb3JtID0gJCh0aGlzLm9wdGlvbnMuZmlsZUlucHV0LnByb3AoJ2Zvcm0nKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5wYXJhbU5hbWUgPSB0aGlzLl9nZXRQYXJhbU5hbWUob3B0aW9ucyk7XHJcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy51cmwpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMudXJsID0gb3B0aW9ucy5mb3JtLnByb3AoJ2FjdGlvbicpIHx8IGxvY2F0aW9uLmhyZWY7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gVGhlIEhUVFAgcmVxdWVzdCBtZXRob2QgbXVzdCBiZSBcIlBPU1RcIiBvciBcIlBVVFwiOlxyXG4gICAgICAgICAgICBvcHRpb25zLnR5cGUgPSAob3B0aW9ucy50eXBlIHx8XHJcbiAgICAgICAgICAgICAgICAoJC50eXBlKG9wdGlvbnMuZm9ybS5wcm9wKCdtZXRob2QnKSkgPT09ICdzdHJpbmcnICYmXHJcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5mb3JtLnByb3AoJ21ldGhvZCcpKSB8fCAnJ1xyXG4gICAgICAgICAgICAgICAgKS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy50eXBlICE9PSAnUE9TVCcgJiYgb3B0aW9ucy50eXBlICE9PSAnUFVUJyAmJlxyXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMudHlwZSAhPT0gJ1BBVENIJykge1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy50eXBlID0gJ1BPU1QnO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5mb3JtQWNjZXB0Q2hhcnNldCkge1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5mb3JtQWNjZXB0Q2hhcnNldCA9IG9wdGlvbnMuZm9ybS5hdHRyKCdhY2NlcHQtY2hhcnNldCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2dldEFKQVhTZXR0aW5nczogZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgICAgICAgICAgdmFyIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zLCBkYXRhKTtcclxuICAgICAgICAgICAgdGhpcy5faW5pdEZvcm1TZXR0aW5ncyhvcHRpb25zKTtcclxuICAgICAgICAgICAgdGhpcy5faW5pdERhdGFTZXR0aW5ncyhvcHRpb25zKTtcclxuICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnM7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8galF1ZXJ5IDEuNiBkb2Vzbid0IHByb3ZpZGUgLnN0YXRlKCksXHJcbiAgICAgICAgLy8gd2hpbGUgalF1ZXJ5IDEuOCsgcmVtb3ZlZCAuaXNSZWplY3RlZCgpIGFuZCAuaXNSZXNvbHZlZCgpOlxyXG4gICAgICAgIF9nZXREZWZlcnJlZFN0YXRlOiBmdW5jdGlvbiAoZGVmZXJyZWQpIHtcclxuICAgICAgICAgICAgaWYgKGRlZmVycmVkLnN0YXRlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVmZXJyZWQuc3RhdGUoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoZGVmZXJyZWQuaXNSZXNvbHZlZCgpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3Jlc29sdmVkJztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoZGVmZXJyZWQuaXNSZWplY3RlZCgpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3JlamVjdGVkJztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gJ3BlbmRpbmcnO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIE1hcHMganFYSFIgY2FsbGJhY2tzIHRvIHRoZSBlcXVpdmFsZW50XHJcbiAgICAgICAgLy8gbWV0aG9kcyBvZiB0aGUgZ2l2ZW4gUHJvbWlzZSBvYmplY3Q6XHJcbiAgICAgICAgX2VuaGFuY2VQcm9taXNlOiBmdW5jdGlvbiAocHJvbWlzZSkge1xyXG4gICAgICAgICAgICBwcm9taXNlLnN1Y2Nlc3MgPSBwcm9taXNlLmRvbmU7XHJcbiAgICAgICAgICAgIHByb21pc2UuZXJyb3IgPSBwcm9taXNlLmZhaWw7XHJcbiAgICAgICAgICAgIHByb21pc2UuY29tcGxldGUgPSBwcm9taXNlLmFsd2F5cztcclxuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlcyBhbmQgcmV0dXJucyBhIFByb21pc2Ugb2JqZWN0IGVuaGFuY2VkIHdpdGhcclxuICAgICAgICAvLyB0aGUganFYSFIgbWV0aG9kcyBhYm9ydCwgc3VjY2VzcywgZXJyb3IgYW5kIGNvbXBsZXRlOlxyXG4gICAgICAgIF9nZXRYSFJQcm9taXNlOiBmdW5jdGlvbiAocmVzb2x2ZU9yUmVqZWN0LCBjb250ZXh0LCBhcmdzKSB7XHJcbiAgICAgICAgICAgIHZhciBkZmQgPSAkLkRlZmVycmVkKCksXHJcbiAgICAgICAgICAgICAgICBwcm9taXNlID0gZGZkLnByb21pc2UoKTtcclxuICAgICAgICAgICAgY29udGV4dCA9IGNvbnRleHQgfHwgdGhpcy5vcHRpb25zLmNvbnRleHQgfHwgcHJvbWlzZTtcclxuICAgICAgICAgICAgaWYgKHJlc29sdmVPclJlamVjdCA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgZGZkLnJlc29sdmVXaXRoKGNvbnRleHQsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHJlc29sdmVPclJlamVjdCA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgIGRmZC5yZWplY3RXaXRoKGNvbnRleHQsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHByb21pc2UuYWJvcnQgPSBkZmQucHJvbWlzZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2VuaGFuY2VQcm9taXNlKHByb21pc2UpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIEFkZHMgY29udmVuaWVuY2UgbWV0aG9kcyB0byB0aGUgZGF0YSBjYWxsYmFjayBhcmd1bWVudDpcclxuICAgICAgICBfYWRkQ29udmVuaWVuY2VNZXRob2RzOiBmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAgICAgICBnZXRQcm9taXNlID0gZnVuY3Rpb24gKGFyZ3MpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJC5EZWZlcnJlZCgpLnJlc29sdmVXaXRoKHRoYXQsIGFyZ3MpLnByb21pc2UoKTtcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGRhdGEucHJvY2VzcyA9IGZ1bmN0aW9uIChyZXNvbHZlRnVuYywgcmVqZWN0RnVuYykge1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlc29sdmVGdW5jIHx8IHJlamVjdEZ1bmMpIHtcclxuICAgICAgICAgICAgICAgICAgICBkYXRhLl9wcm9jZXNzUXVldWUgPSB0aGlzLl9wcm9jZXNzUXVldWUgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5fcHJvY2Vzc1F1ZXVlIHx8IGdldFByb21pc2UoW3RoaXNdKSkucGlwZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5lcnJvclRocm93bikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJC5EZWZlcnJlZCgpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVqZWN0V2l0aCh0aGF0LCBbZGF0YV0pLnByb21pc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldFByb21pc2UoYXJndW1lbnRzKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgKS5waXBlKHJlc29sdmVGdW5jLCByZWplY3RGdW5jKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzUXVldWUgfHwgZ2V0UHJvbWlzZShbdGhpc10pO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBkYXRhLnN1Ym1pdCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlKCkgIT09ICdwZW5kaW5nJykge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuanFYSFIgPSB0aGlzLmpxWEhSID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgKHRoYXQuX3RyaWdnZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnc3VibWl0JyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuRXZlbnQoJ3N1Ym1pdCcsIHtkZWxlZ2F0ZWRFdmVudDogZX0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICApICE9PSBmYWxzZSkgJiYgdGhhdC5fb25TZW5kKGUsIHRoaXMpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuanFYSFIgfHwgdGhhdC5fZ2V0WEhSUHJvbWlzZSgpO1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBkYXRhLmFib3J0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuanFYSFIpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5qcVhIUi5hYm9ydCgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvclRocm93biA9ICdhYm9ydCc7XHJcbiAgICAgICAgICAgICAgICB0aGF0Ll90cmlnZ2VyKCdmYWlsJywgbnVsbCwgdGhpcyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5fZ2V0WEhSUHJvbWlzZShmYWxzZSk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGRhdGEuc3RhdGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5qcVhIUikge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGF0Ll9nZXREZWZlcnJlZFN0YXRlKHRoaXMuanFYSFIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3Byb2Nlc3NRdWV1ZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGF0Ll9nZXREZWZlcnJlZFN0YXRlKHRoaXMuX3Byb2Nlc3NRdWV1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGRhdGEucHJvY2Vzc2luZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5qcVhIUiAmJiB0aGlzLl9wcm9jZXNzUXVldWUgJiYgdGhhdFxyXG4gICAgICAgICAgICAgICAgICAgIC5fZ2V0RGVmZXJyZWRTdGF0ZSh0aGlzLl9wcm9jZXNzUXVldWUpID09PSAncGVuZGluZyc7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGRhdGEucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGRhdGEucmVzcG9uc2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVzcG9uc2U7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8gUGFyc2VzIHRoZSBSYW5nZSBoZWFkZXIgZnJvbSB0aGUgc2VydmVyIHJlc3BvbnNlXHJcbiAgICAgICAgLy8gYW5kIHJldHVybnMgdGhlIHVwbG9hZGVkIGJ5dGVzOlxyXG4gICAgICAgIF9nZXRVcGxvYWRlZEJ5dGVzOiBmdW5jdGlvbiAoanFYSFIpIHtcclxuICAgICAgICAgICAgdmFyIHJhbmdlID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoJ1JhbmdlJyksXHJcbiAgICAgICAgICAgICAgICBwYXJ0cyA9IHJhbmdlICYmIHJhbmdlLnNwbGl0KCctJyksXHJcbiAgICAgICAgICAgICAgICB1cHBlckJ5dGVzUG9zID0gcGFydHMgJiYgcGFydHMubGVuZ3RoID4gMSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIHBhcnNlSW50KHBhcnRzWzFdLCAxMCk7XHJcbiAgICAgICAgICAgIHJldHVybiB1cHBlckJ5dGVzUG9zICYmIHVwcGVyQnl0ZXNQb3MgKyAxO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIFVwbG9hZHMgYSBmaWxlIGluIG11bHRpcGxlLCBzZXF1ZW50aWFsIHJlcXVlc3RzXHJcbiAgICAgICAgLy8gYnkgc3BsaXR0aW5nIHRoZSBmaWxlIHVwIGluIG11bHRpcGxlIGJsb2IgY2h1bmtzLlxyXG4gICAgICAgIC8vIElmIHRoZSBzZWNvbmQgcGFyYW1ldGVyIGlzIHRydWUsIG9ubHkgdGVzdHMgaWYgdGhlIGZpbGVcclxuICAgICAgICAvLyBzaG91bGQgYmUgdXBsb2FkZWQgaW4gY2h1bmtzLCBidXQgZG9lcyBub3QgaW52b2tlIGFueVxyXG4gICAgICAgIC8vIHVwbG9hZCByZXF1ZXN0czpcclxuICAgICAgICBfY2h1bmtlZFVwbG9hZDogZnVuY3Rpb24gKG9wdGlvbnMsIHRlc3RPbmx5KSB7XHJcbiAgICAgICAgICAgIG9wdGlvbnMudXBsb2FkZWRCeXRlcyA9IG9wdGlvbnMudXBsb2FkZWRCeXRlcyB8fCAwO1xyXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAgICAgICBmaWxlID0gb3B0aW9ucy5maWxlc1swXSxcclxuICAgICAgICAgICAgICAgIGZzID0gZmlsZS5zaXplLFxyXG4gICAgICAgICAgICAgICAgdWIgPSBvcHRpb25zLnVwbG9hZGVkQnl0ZXMsXHJcbiAgICAgICAgICAgICAgICBtY3MgPSBvcHRpb25zLm1heENodW5rU2l6ZSB8fCBmcyxcclxuICAgICAgICAgICAgICAgIHNsaWNlID0gdGhpcy5fYmxvYlNsaWNlLFxyXG4gICAgICAgICAgICAgICAgZGZkID0gJC5EZWZlcnJlZCgpLFxyXG4gICAgICAgICAgICAgICAgcHJvbWlzZSA9IGRmZC5wcm9taXNlKCksXHJcbiAgICAgICAgICAgICAgICBqcVhIUixcclxuICAgICAgICAgICAgICAgIHVwbG9hZDtcclxuICAgICAgICAgICAgaWYgKCEodGhpcy5faXNYSFJVcGxvYWQob3B0aW9ucykgJiYgc2xpY2UgJiYgKHViIHx8IG1jcyA8IGZzKSkgfHxcclxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmRhdGEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGVzdE9ubHkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh1YiA+PSBmcykge1xyXG4gICAgICAgICAgICAgICAgZmlsZS5lcnJvciA9IG9wdGlvbnMuaTE4bigndXBsb2FkZWRCeXRlcycpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldFhIUlByb21pc2UoXHJcbiAgICAgICAgICAgICAgICAgICAgZmFsc2UsXHJcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5jb250ZXh0LFxyXG4gICAgICAgICAgICAgICAgICAgIFtudWxsLCAnZXJyb3InLCBmaWxlLmVycm9yXVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvLyBUaGUgY2h1bmsgdXBsb2FkIG1ldGhvZDpcclxuICAgICAgICAgICAgdXBsb2FkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgLy8gQ2xvbmUgdGhlIG9wdGlvbnMgb2JqZWN0IGZvciBlYWNoIGNodW5rIHVwbG9hZDpcclxuICAgICAgICAgICAgICAgIHZhciBvID0gJC5leHRlbmQoe30sIG9wdGlvbnMpLFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRMb2FkZWQgPSBvLl9wcm9ncmVzcy5sb2FkZWQ7XHJcbiAgICAgICAgICAgICAgICBvLmJsb2IgPSBzbGljZS5jYWxsKFxyXG4gICAgICAgICAgICAgICAgICAgIGZpbGUsXHJcbiAgICAgICAgICAgICAgICAgICAgdWIsXHJcbiAgICAgICAgICAgICAgICAgICAgdWIgKyBtY3MsXHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZS50eXBlXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIGN1cnJlbnQgY2h1bmsgc2l6ZSwgYXMgdGhlIGJsb2IgaXRzZWxmXHJcbiAgICAgICAgICAgICAgICAvLyB3aWxsIGJlIGRlcmVmZXJlbmNlZCBhZnRlciBkYXRhIHByb2Nlc3Npbmc6XHJcbiAgICAgICAgICAgICAgICBvLmNodW5rU2l6ZSA9IG8uYmxvYi5zaXplO1xyXG4gICAgICAgICAgICAgICAgLy8gRXhwb3NlIHRoZSBjaHVuayBieXRlcyBwb3NpdGlvbiByYW5nZTpcclxuICAgICAgICAgICAgICAgIG8uY29udGVudFJhbmdlID0gJ2J5dGVzICcgKyB1YiArICctJyArXHJcbiAgICAgICAgICAgICAgICAgICAgKHViICsgby5jaHVua1NpemUgLSAxKSArICcvJyArIGZzO1xyXG4gICAgICAgICAgICAgICAgLy8gUHJvY2VzcyB0aGUgdXBsb2FkIGRhdGEgKHRoZSBibG9iIGFuZCBwb3RlbnRpYWwgZm9ybSBkYXRhKTpcclxuICAgICAgICAgICAgICAgIHRoYXQuX2luaXRYSFJEYXRhKG8pO1xyXG4gICAgICAgICAgICAgICAgLy8gQWRkIHByb2dyZXNzIGxpc3RlbmVycyBmb3IgdGhpcyBjaHVuayB1cGxvYWQ6XHJcbiAgICAgICAgICAgICAgICB0aGF0Ll9pbml0UHJvZ3Jlc3NMaXN0ZW5lcihvKTtcclxuICAgICAgICAgICAgICAgIGpxWEhSID0gKCh0aGF0Ll90cmlnZ2VyKCdjaHVua3NlbmQnLCBudWxsLCBvKSAhPT0gZmFsc2UgJiYgJC5hamF4KG8pKSB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9nZXRYSFJQcm9taXNlKGZhbHNlLCBvLmNvbnRleHQpKVxyXG4gICAgICAgICAgICAgICAgICAgIC5kb25lKGZ1bmN0aW9uIChyZXN1bHQsIHRleHRTdGF0dXMsIGpxWEhSKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHViID0gdGhhdC5fZ2V0VXBsb2FkZWRCeXRlcyhqcVhIUikgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh1YiArIG8uY2h1bmtTaXplKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgcHJvZ3Jlc3MgZXZlbnQgaWYgbm8gZmluYWwgcHJvZ3Jlc3MgZXZlbnRcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2l0aCBsb2FkZWQgZXF1YWxpbmcgdG90YWwgaGFzIGJlZW4gdHJpZ2dlcmVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvciB0aGlzIGNodW5rOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudExvYWRlZCArIG8uY2h1bmtTaXplIC0gby5fcHJvZ3Jlc3MubG9hZGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9vblByb2dyZXNzKCQuRXZlbnQoJ3Byb2dyZXNzJywge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aENvbXB1dGFibGU6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiB1YiAtIG8udXBsb2FkZWRCeXRlcyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbDogdWIgLSBvLnVwbG9hZGVkQnl0ZXNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLCBvKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLnVwbG9hZGVkQnl0ZXMgPSBvLnVwbG9hZGVkQnl0ZXMgPSB1YjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgby5yZXN1bHQgPSByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG8udGV4dFN0YXR1cyA9IHRleHRTdGF0dXM7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG8uanFYSFIgPSBqcVhIUjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5fdHJpZ2dlcignY2h1bmtkb25lJywgbnVsbCwgbyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX3RyaWdnZXIoJ2NodW5rYWx3YXlzJywgbnVsbCwgbyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1YiA8IGZzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaWxlIHVwbG9hZCBub3QgeWV0IGNvbXBsZXRlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29udGludWUgd2l0aCB0aGUgbmV4dCBjaHVuazpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwbG9hZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZkLnJlc29sdmVXaXRoKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8uY29udGV4dCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcmVzdWx0LCB0ZXh0U3RhdHVzLCBqcVhIUl1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgIC5mYWlsKGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgby5qcVhIUiA9IGpxWEhSO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBvLnRleHRTdGF0dXMgPSB0ZXh0U3RhdHVzO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBvLmVycm9yVGhyb3duID0gZXJyb3JUaHJvd247XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX3RyaWdnZXIoJ2NodW5rZmFpbCcsIG51bGwsIG8pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll90cmlnZ2VyKCdjaHVua2Fsd2F5cycsIG51bGwsIG8pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkZmQucmVqZWN0V2l0aChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG8uY29udGV4dCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd25dXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHRoaXMuX2VuaGFuY2VQcm9taXNlKHByb21pc2UpO1xyXG4gICAgICAgICAgICBwcm9taXNlLmFib3J0ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGpxWEhSLmFib3J0KCk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHVwbG9hZCgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfYmVmb3JlU2VuZDogZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZSA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgLy8gdGhlIHN0YXJ0IGNhbGxiYWNrIGlzIHRyaWdnZXJlZCB3aGVuIGFuIHVwbG9hZCBzdGFydHNcclxuICAgICAgICAgICAgICAgIC8vIGFuZCBubyBvdGhlciB1cGxvYWRzIGFyZSBjdXJyZW50bHkgcnVubmluZyxcclxuICAgICAgICAgICAgICAgIC8vIGVxdWl2YWxlbnQgdG8gdGhlIGdsb2JhbCBhamF4U3RhcnQgZXZlbnQ6XHJcbiAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyKCdzdGFydCcpO1xyXG4gICAgICAgICAgICAgICAgLy8gU2V0IHRpbWVyIGZvciBnbG9iYWwgYml0cmF0ZSBwcm9ncmVzcyBjYWxjdWxhdGlvbjpcclxuICAgICAgICAgICAgICAgIHRoaXMuX2JpdHJhdGVUaW1lciA9IG5ldyB0aGlzLl9CaXRyYXRlVGltZXIoKTtcclxuICAgICAgICAgICAgICAgIC8vIFJlc2V0IHRoZSBnbG9iYWwgcHJvZ3Jlc3MgdmFsdWVzOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3MubG9hZGVkID0gdGhpcy5fcHJvZ3Jlc3MudG90YWwgPSAwO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3MuYml0cmF0ZSA9IDA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBjb250YWluZXIgb2JqZWN0cyBmb3IgdGhlIC5yZXNwb25zZSgpIGFuZFxyXG4gICAgICAgICAgICAvLyAucHJvZ3Jlc3MoKSBtZXRob2RzIG9uIHRoZSBkYXRhIG9iamVjdCBhcmUgYXZhaWxhYmxlXHJcbiAgICAgICAgICAgIC8vIGFuZCByZXNldCB0byB0aGVpciBpbml0aWFsIHN0YXRlOlxyXG4gICAgICAgICAgICB0aGlzLl9pbml0UmVzcG9uc2VPYmplY3QoZGF0YSk7XHJcbiAgICAgICAgICAgIHRoaXMuX2luaXRQcm9ncmVzc09iamVjdChkYXRhKTtcclxuICAgICAgICAgICAgZGF0YS5fcHJvZ3Jlc3MubG9hZGVkID0gZGF0YS5sb2FkZWQgPSBkYXRhLnVwbG9hZGVkQnl0ZXMgfHwgMDtcclxuICAgICAgICAgICAgZGF0YS5fcHJvZ3Jlc3MudG90YWwgPSBkYXRhLnRvdGFsID0gdGhpcy5fZ2V0VG90YWwoZGF0YS5maWxlcykgfHwgMTtcclxuICAgICAgICAgICAgZGF0YS5fcHJvZ3Jlc3MuYml0cmF0ZSA9IGRhdGEuYml0cmF0ZSA9IDA7XHJcbiAgICAgICAgICAgIHRoaXMuX2FjdGl2ZSArPSAxO1xyXG4gICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBnbG9iYWwgcHJvZ3Jlc3MgdmFsdWVzOlxyXG4gICAgICAgICAgICB0aGlzLl9wcm9ncmVzcy5sb2FkZWQgKz0gZGF0YS5sb2FkZWQ7XHJcbiAgICAgICAgICAgIHRoaXMuX3Byb2dyZXNzLnRvdGFsICs9IGRhdGEudG90YWw7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX29uRG9uZTogZnVuY3Rpb24gKHJlc3VsdCwgdGV4dFN0YXR1cywganFYSFIsIG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgdmFyIHRvdGFsID0gb3B0aW9ucy5fcHJvZ3Jlc3MudG90YWwsXHJcbiAgICAgICAgICAgICAgICByZXNwb25zZSA9IG9wdGlvbnMuX3Jlc3BvbnNlO1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5fcHJvZ3Jlc3MubG9hZGVkIDwgdG90YWwpIHtcclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIHByb2dyZXNzIGV2ZW50IGlmIG5vIGZpbmFsIHByb2dyZXNzIGV2ZW50XHJcbiAgICAgICAgICAgICAgICAvLyB3aXRoIGxvYWRlZCBlcXVhbGluZyB0b3RhbCBoYXMgYmVlbiB0cmlnZ2VyZWQ6XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9vblByb2dyZXNzKCQuRXZlbnQoJ3Byb2dyZXNzJywge1xyXG4gICAgICAgICAgICAgICAgICAgIGxlbmd0aENvbXB1dGFibGU6IHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiB0b3RhbCxcclxuICAgICAgICAgICAgICAgICAgICB0b3RhbDogdG90YWxcclxuICAgICAgICAgICAgICAgIH0pLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXNwb25zZS5yZXN1bHQgPSBvcHRpb25zLnJlc3VsdCA9IHJlc3VsdDtcclxuICAgICAgICAgICAgcmVzcG9uc2UudGV4dFN0YXR1cyA9IG9wdGlvbnMudGV4dFN0YXR1cyA9IHRleHRTdGF0dXM7XHJcbiAgICAgICAgICAgIHJlc3BvbnNlLmpxWEhSID0gb3B0aW9ucy5qcVhIUiA9IGpxWEhSO1xyXG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyKCdkb25lJywgbnVsbCwgb3B0aW9ucyk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX29uRmFpbDogZnVuY3Rpb24gKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93biwgb3B0aW9ucykge1xyXG4gICAgICAgICAgICB2YXIgcmVzcG9uc2UgPSBvcHRpb25zLl9yZXNwb25zZTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVjYWxjdWxhdGVQcm9ncmVzcykge1xyXG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBmYWlsZWQgKGVycm9yIG9yIGFib3J0KSBmaWxlIHVwbG9hZCBmcm9tXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgZ2xvYmFsIHByb2dyZXNzIGNhbGN1bGF0aW9uOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3MubG9hZGVkIC09IG9wdGlvbnMuX3Byb2dyZXNzLmxvYWRlZDtcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Byb2dyZXNzLnRvdGFsIC09IG9wdGlvbnMuX3Byb2dyZXNzLnRvdGFsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlc3BvbnNlLmpxWEhSID0gb3B0aW9ucy5qcVhIUiA9IGpxWEhSO1xyXG4gICAgICAgICAgICByZXNwb25zZS50ZXh0U3RhdHVzID0gb3B0aW9ucy50ZXh0U3RhdHVzID0gdGV4dFN0YXR1cztcclxuICAgICAgICAgICAgcmVzcG9uc2UuZXJyb3JUaHJvd24gPSBvcHRpb25zLmVycm9yVGhyb3duID0gZXJyb3JUaHJvd247XHJcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXIoJ2ZhaWwnLCBudWxsLCBvcHRpb25zKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfb25BbHdheXM6IGZ1bmN0aW9uIChqcVhIUm9yUmVzdWx0LCB0ZXh0U3RhdHVzLCBqcVhIUm9yRXJyb3IsIG9wdGlvbnMpIHtcclxuICAgICAgICAgICAgLy8ganFYSFJvclJlc3VsdCwgdGV4dFN0YXR1cyBhbmQganFYSFJvckVycm9yIGFyZSBhZGRlZCB0byB0aGVcclxuICAgICAgICAgICAgLy8gb3B0aW9ucyBvYmplY3QgdmlhIGRvbmUgYW5kIGZhaWwgY2FsbGJhY2tzXHJcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXIoJ2Fsd2F5cycsIG51bGwsIG9wdGlvbnMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9vblNlbmQ6IGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcbiAgICAgICAgICAgIGlmICghZGF0YS5zdWJtaXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2FkZENvbnZlbmllbmNlTWV0aG9kcyhlLCBkYXRhKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAgICAgICBqcVhIUixcclxuICAgICAgICAgICAgICAgIGFib3J0ZWQsXHJcbiAgICAgICAgICAgICAgICBzbG90LFxyXG4gICAgICAgICAgICAgICAgcGlwZSxcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB0aGF0Ll9nZXRBSkFYU2V0dGluZ3MoZGF0YSksXHJcbiAgICAgICAgICAgICAgICBzZW5kID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuX3NlbmRpbmcgKz0gMTtcclxuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdGltZXIgZm9yIGJpdHJhdGUgcHJvZ3Jlc3MgY2FsY3VsYXRpb246XHJcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5fYml0cmF0ZVRpbWVyID0gbmV3IHRoYXQuX0JpdHJhdGVUaW1lcigpO1xyXG4gICAgICAgICAgICAgICAgICAgIGpxWEhSID0ganFYSFIgfHwgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAoKGFib3J0ZWQgfHwgdGhhdC5fdHJpZ2dlcihcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzZW5kJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQuRXZlbnQoJ3NlbmQnLCB7ZGVsZWdhdGVkRXZlbnQ6IGV9KSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnNcclxuICAgICAgICAgICAgICAgICAgICAgICAgKSA9PT0gZmFsc2UpICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX2dldFhIUlByb21pc2UoZmFsc2UsIG9wdGlvbnMuY29udGV4dCwgYWJvcnRlZCkpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX2NodW5rZWRVcGxvYWQob3B0aW9ucykgfHwgJC5hamF4KG9wdGlvbnMpXHJcbiAgICAgICAgICAgICAgICAgICAgKS5kb25lKGZ1bmN0aW9uIChyZXN1bHQsIHRleHRTdGF0dXMsIGpxWEhSKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuX29uRG9uZShyZXN1bHQsIHRleHRTdGF0dXMsIGpxWEhSLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgICAgICAgICB9KS5mYWlsKGZ1bmN0aW9uIChqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5fb25GYWlsKGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93biwgb3B0aW9ucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSkuYWx3YXlzKGZ1bmN0aW9uIChqcVhIUm9yUmVzdWx0LCB0ZXh0U3RhdHVzLCBqcVhIUm9yRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5fb25BbHdheXMoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqcVhIUm9yUmVzdWx0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dFN0YXR1cyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpxWEhSb3JFcnJvcixcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnNcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5fc2VuZGluZyAtPSAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9hY3RpdmUgLT0gMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubGltaXRDb25jdXJyZW50VXBsb2FkcyAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubGltaXRDb25jdXJyZW50VXBsb2FkcyA+IHRoYXQuX3NlbmRpbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0YXJ0IHRoZSBuZXh0IHF1ZXVlZCB1cGxvYWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGF0IGhhcyBub3QgYmVlbiBhYm9ydGVkOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRTbG90ID0gdGhhdC5fc2xvdHMuc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChuZXh0U2xvdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGF0Ll9nZXREZWZlcnJlZFN0YXRlKG5leHRTbG90KSA9PT0gJ3BlbmRpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHRTbG90LnJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHRTbG90ID0gdGhhdC5fc2xvdHMuc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5fYWN0aXZlID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgc3RvcCBjYWxsYmFjayBpcyB0cmlnZ2VyZWQgd2hlbiBhbGwgdXBsb2FkcyBoYXZlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiZWVuIGNvbXBsZXRlZCwgZXF1aXZhbGVudCB0byB0aGUgZ2xvYmFsIGFqYXhTdG9wIGV2ZW50OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5fdHJpZ2dlcignc3RvcCcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGpxWEhSO1xyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5fYmVmb3JlU2VuZChlLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zZXF1ZW50aWFsVXBsb2FkcyB8fFxyXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLm9wdGlvbnMubGltaXRDb25jdXJyZW50VXBsb2FkcyAmJlxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub3B0aW9ucy5saW1pdENvbmN1cnJlbnRVcGxvYWRzIDw9IHRoaXMuX3NlbmRpbmcpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmxpbWl0Q29uY3VycmVudFVwbG9hZHMgPiAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2xvdCA9ICQuRGVmZXJyZWQoKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zbG90cy5wdXNoKHNsb3QpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBpcGUgPSBzbG90LnBpcGUoc2VuZCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NlcXVlbmNlID0gdGhpcy5fc2VxdWVuY2UucGlwZShzZW5kLCBzZW5kKTtcclxuICAgICAgICAgICAgICAgICAgICBwaXBlID0gdGhpcy5fc2VxdWVuY2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvLyBSZXR1cm4gdGhlIHBpcGVkIFByb21pc2Ugb2JqZWN0LCBlbmhhbmNlZCB3aXRoIGFuIGFib3J0IG1ldGhvZCxcclxuICAgICAgICAgICAgICAgIC8vIHdoaWNoIGlzIGRlbGVnYXRlZCB0byB0aGUganFYSFIgb2JqZWN0IG9mIHRoZSBjdXJyZW50IHVwbG9hZCxcclxuICAgICAgICAgICAgICAgIC8vIGFuZCBqcVhIUiBjYWxsYmFja3MgbWFwcGVkIHRvIHRoZSBlcXVpdmFsZW50IFByb21pc2UgbWV0aG9kczpcclxuICAgICAgICAgICAgICAgIHBpcGUuYWJvcnQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYWJvcnRlZCA9IFt1bmRlZmluZWQsICdhYm9ydCcsICdhYm9ydCddO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghanFYSFIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNsb3QpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QucmVqZWN0V2l0aChvcHRpb25zLmNvbnRleHQsIGFib3J0ZWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZW5kKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBqcVhIUi5hYm9ydCgpO1xyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9lbmhhbmNlUHJvbWlzZShwaXBlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gc2VuZCgpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9vbkFkZDogZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZSxcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zLCBkYXRhKSxcclxuICAgICAgICAgICAgICAgIGZpbGVzID0gZGF0YS5maWxlcyxcclxuICAgICAgICAgICAgICAgIGZpbGVzTGVuZ3RoID0gZmlsZXMubGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgbGltaXQgPSBvcHRpb25zLmxpbWl0TXVsdGlGaWxlVXBsb2FkcyxcclxuICAgICAgICAgICAgICAgIGxpbWl0U2l6ZSA9IG9wdGlvbnMubGltaXRNdWx0aUZpbGVVcGxvYWRTaXplLFxyXG4gICAgICAgICAgICAgICAgb3ZlcmhlYWQgPSBvcHRpb25zLmxpbWl0TXVsdGlGaWxlVXBsb2FkU2l6ZU92ZXJoZWFkLFxyXG4gICAgICAgICAgICAgICAgYmF0Y2hTaXplID0gMCxcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZSA9IHRoaXMuX2dldFBhcmFtTmFtZShvcHRpb25zKSxcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNldCxcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNsaWNlLFxyXG4gICAgICAgICAgICAgICAgZmlsZVNldCxcclxuICAgICAgICAgICAgICAgIGksXHJcbiAgICAgICAgICAgICAgICBqID0gMDtcclxuICAgICAgICAgICAgaWYgKGxpbWl0U2l6ZSAmJiAoIWZpbGVzTGVuZ3RoIHx8IGZpbGVzWzBdLnNpemUgPT09IHVuZGVmaW5lZCkpIHtcclxuICAgICAgICAgICAgICAgIGxpbWl0U2l6ZSA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoIShvcHRpb25zLnNpbmdsZUZpbGVVcGxvYWRzIHx8IGxpbWl0IHx8IGxpbWl0U2l6ZSkgfHxcclxuICAgICAgICAgICAgICAgICAgICAhdGhpcy5faXNYSFJVcGxvYWQob3B0aW9ucykpIHtcclxuICAgICAgICAgICAgICAgIGZpbGVTZXQgPSBbZmlsZXNdO1xyXG4gICAgICAgICAgICAgICAgcGFyYW1OYW1lU2V0ID0gW3BhcmFtTmFtZV07XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIShvcHRpb25zLnNpbmdsZUZpbGVVcGxvYWRzIHx8IGxpbWl0U2l6ZSkgJiYgbGltaXQpIHtcclxuICAgICAgICAgICAgICAgIGZpbGVTZXQgPSBbXTtcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNldCA9IFtdO1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGZpbGVzTGVuZ3RoOyBpICs9IGxpbWl0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZVNldC5wdXNoKGZpbGVzLnNsaWNlKGksIGkgKyBsaW1pdCkpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNsaWNlID0gcGFyYW1OYW1lLnNsaWNlKGksIGkgKyBsaW1pdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJhbU5hbWVTbGljZS5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lU2xpY2UgPSBwYXJhbU5hbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNldC5wdXNoKHBhcmFtTmFtZVNsaWNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmICghb3B0aW9ucy5zaW5nbGVGaWxlVXBsb2FkcyAmJiBsaW1pdFNpemUpIHtcclxuICAgICAgICAgICAgICAgIGZpbGVTZXQgPSBbXTtcclxuICAgICAgICAgICAgICAgIHBhcmFtTmFtZVNldCA9IFtdO1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGZpbGVzTGVuZ3RoOyBpID0gaSArIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICBiYXRjaFNpemUgKz0gZmlsZXNbaV0uc2l6ZSArIG92ZXJoZWFkO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpICsgMSA9PT0gZmlsZXNMZW5ndGggfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoYmF0Y2hTaXplICsgZmlsZXNbaSArIDFdLnNpemUgKyBvdmVyaGVhZCkgPiBsaW1pdFNpemUpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAobGltaXQgJiYgaSArIDEgLSBqID49IGxpbWl0KSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlU2V0LnB1c2goZmlsZXMuc2xpY2UoaiwgaSArIDEpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lU2xpY2UgPSBwYXJhbU5hbWUuc2xpY2UoaiwgaSArIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcmFtTmFtZVNsaWNlLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lU2xpY2UgPSBwYXJhbU5hbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1OYW1lU2V0LnB1c2gocGFyYW1OYW1lU2xpY2UpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBqID0gaSArIDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoU2l6ZSA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgcGFyYW1OYW1lU2V0ID0gcGFyYW1OYW1lO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRhdGEub3JpZ2luYWxGaWxlcyA9IGZpbGVzO1xyXG4gICAgICAgICAgICAkLmVhY2goZmlsZVNldCB8fCBmaWxlcywgZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgbmV3RGF0YSA9ICQuZXh0ZW5kKHt9LCBkYXRhKTtcclxuICAgICAgICAgICAgICAgIG5ld0RhdGEuZmlsZXMgPSBmaWxlU2V0ID8gZWxlbWVudCA6IFtlbGVtZW50XTtcclxuICAgICAgICAgICAgICAgIG5ld0RhdGEucGFyYW1OYW1lID0gcGFyYW1OYW1lU2V0W2luZGV4XTtcclxuICAgICAgICAgICAgICAgIHRoYXQuX2luaXRSZXNwb25zZU9iamVjdChuZXdEYXRhKTtcclxuICAgICAgICAgICAgICAgIHRoYXQuX2luaXRQcm9ncmVzc09iamVjdChuZXdEYXRhKTtcclxuICAgICAgICAgICAgICAgIHRoYXQuX2FkZENvbnZlbmllbmNlTWV0aG9kcyhlLCBuZXdEYXRhKTtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoYXQuX3RyaWdnZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgJ2FkZCcsXHJcbiAgICAgICAgICAgICAgICAgICAgJC5FdmVudCgnYWRkJywge2RlbGVnYXRlZEV2ZW50OiBlfSksXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3RGF0YVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9yZXBsYWNlRmlsZUlucHV0OiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgdmFyIGlucHV0Q2xvbmUgPSBpbnB1dC5jbG9uZSh0cnVlKTtcclxuICAgICAgICAgICAgJCgnPGZvcm0+PC9mb3JtPicpLmFwcGVuZChpbnB1dENsb25lKVswXS5yZXNldCgpO1xyXG4gICAgICAgICAgICAvLyBEZXRhY2hpbmcgYWxsb3dzIHRvIGluc2VydCB0aGUgZmlsZUlucHV0IG9uIGFub3RoZXIgZm9ybVxyXG4gICAgICAgICAgICAvLyB3aXRob3V0IGxvb3NpbmcgdGhlIGZpbGUgaW5wdXQgdmFsdWU6XHJcbiAgICAgICAgICAgIGlucHV0LmFmdGVyKGlucHV0Q2xvbmUpLmRldGFjaCgpO1xyXG4gICAgICAgICAgICAvLyBBdm9pZCBtZW1vcnkgbGVha3Mgd2l0aCB0aGUgZGV0YWNoZWQgZmlsZSBpbnB1dDpcclxuICAgICAgICAgICAgJC5jbGVhbkRhdGEoaW5wdXQudW5iaW5kKCdyZW1vdmUnKSk7XHJcbiAgICAgICAgICAgIC8vIFJlcGxhY2UgdGhlIG9yaWdpbmFsIGZpbGUgaW5wdXQgZWxlbWVudCBpbiB0aGUgZmlsZUlucHV0XHJcbiAgICAgICAgICAgIC8vIGVsZW1lbnRzIHNldCB3aXRoIHRoZSBjbG9uZSwgd2hpY2ggaGFzIGJlZW4gY29waWVkIGluY2x1ZGluZ1xyXG4gICAgICAgICAgICAvLyBldmVudCBoYW5kbGVyczpcclxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmZpbGVJbnB1dCA9IHRoaXMub3B0aW9ucy5maWxlSW5wdXQubWFwKGZ1bmN0aW9uIChpLCBlbCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGVsID09PSBpbnB1dFswXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dENsb25lWzBdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgLy8gSWYgdGhlIHdpZGdldCBoYXMgYmVlbiBpbml0aWFsaXplZCBvbiB0aGUgZmlsZSBpbnB1dCBpdHNlbGYsXHJcbiAgICAgICAgICAgIC8vIG92ZXJyaWRlIHRoaXMuZWxlbWVudCB3aXRoIHRoZSBmaWxlIGlucHV0IGNsb25lOlxyXG4gICAgICAgICAgICBpZiAoaW5wdXRbMF0gPT09IHRoaXMuZWxlbWVudFswXSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50ID0gaW5wdXRDbG9uZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9oYW5kbGVGaWxlVHJlZUVudHJ5OiBmdW5jdGlvbiAoZW50cnksIHBhdGgpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgICAgICAgZGZkID0gJC5EZWZlcnJlZCgpLFxyXG4gICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZSAmJiAhZS5lbnRyeSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlLmVudHJ5ID0gZW50cnk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFNpbmNlICQud2hlbiByZXR1cm5zIGltbWVkaWF0ZWx5IGlmIG9uZVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIERlZmVycmVkIGlzIHJlamVjdGVkLCB3ZSB1c2UgcmVzb2x2ZSBpbnN0ZWFkLlxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgYWxsb3dzIHZhbGlkIGZpbGVzIGFuZCBpbnZhbGlkIGl0ZW1zXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdG8gYmUgcmV0dXJuZWQgdG9nZXRoZXIgaW4gb25lIHNldDpcclxuICAgICAgICAgICAgICAgICAgICBkZmQucmVzb2x2ZShbZV0pO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIGRpclJlYWRlcjtcclxuICAgICAgICAgICAgcGF0aCA9IHBhdGggfHwgJyc7XHJcbiAgICAgICAgICAgIGlmIChlbnRyeS5pc0ZpbGUpIHtcclxuICAgICAgICAgICAgICAgIGlmIChlbnRyeS5fZmlsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIFdvcmthcm91bmQgZm9yIENocm9tZSBidWcgIzE0OTczNVxyXG4gICAgICAgICAgICAgICAgICAgIGVudHJ5Ll9maWxlLnJlbGF0aXZlUGF0aCA9IHBhdGg7XHJcbiAgICAgICAgICAgICAgICAgICAgZGZkLnJlc29sdmUoZW50cnkuX2ZpbGUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBlbnRyeS5maWxlKGZ1bmN0aW9uIChmaWxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGUucmVsYXRpdmVQYXRoID0gcGF0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGZkLnJlc29sdmUoZmlsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSwgZXJyb3JIYW5kbGVyKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChlbnRyeS5pc0RpcmVjdG9yeSkge1xyXG4gICAgICAgICAgICAgICAgZGlyUmVhZGVyID0gZW50cnkuY3JlYXRlUmVhZGVyKCk7XHJcbiAgICAgICAgICAgICAgICBkaXJSZWFkZXIucmVhZEVudHJpZXMoZnVuY3Rpb24gKGVudHJpZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll9oYW5kbGVGaWxlVHJlZUVudHJpZXMoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGggKyBlbnRyeS5uYW1lICsgJy8nXHJcbiAgICAgICAgICAgICAgICAgICAgKS5kb25lKGZ1bmN0aW9uIChmaWxlcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkZmQucmVzb2x2ZShmaWxlcyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSkuZmFpbChlcnJvckhhbmRsZXIpO1xyXG4gICAgICAgICAgICAgICAgfSwgZXJyb3JIYW5kbGVyKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIFJldHVybiBhbiBlbXB5IGxpc3QgZm9yIGZpbGUgc3lzdGVtIGl0ZW1zXHJcbiAgICAgICAgICAgICAgICAvLyBvdGhlciB0aGFuIGZpbGVzIG9yIGRpcmVjdG9yaWVzOlxyXG4gICAgICAgICAgICAgICAgZGZkLnJlc29sdmUoW10pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBkZmQucHJvbWlzZSgpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9oYW5kbGVGaWxlVHJlZUVudHJpZXM6IGZ1bmN0aW9uIChlbnRyaWVzLCBwYXRoKSB7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcclxuICAgICAgICAgICAgcmV0dXJuICQud2hlbi5hcHBseShcclxuICAgICAgICAgICAgICAgICQsXHJcbiAgICAgICAgICAgICAgICAkLm1hcChlbnRyaWVzLCBmdW5jdGlvbiAoZW50cnkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5faGFuZGxlRmlsZVRyZWVFbnRyeShlbnRyeSwgcGF0aCk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApLnBpcGUoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoXHJcbiAgICAgICAgICAgICAgICAgICAgW10sXHJcbiAgICAgICAgICAgICAgICAgICAgYXJndW1lbnRzXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfZ2V0RHJvcHBlZEZpbGVzOiBmdW5jdGlvbiAoZGF0YVRyYW5zZmVyKSB7XHJcbiAgICAgICAgICAgIGRhdGFUcmFuc2ZlciA9IGRhdGFUcmFuc2ZlciB8fCB7fTtcclxuICAgICAgICAgICAgdmFyIGl0ZW1zID0gZGF0YVRyYW5zZmVyLml0ZW1zO1xyXG4gICAgICAgICAgICBpZiAoaXRlbXMgJiYgaXRlbXMubGVuZ3RoICYmIChpdGVtc1swXS53ZWJraXRHZXRBc0VudHJ5IHx8XHJcbiAgICAgICAgICAgICAgICAgICAgaXRlbXNbMF0uZ2V0QXNFbnRyeSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVGaWxlVHJlZUVudHJpZXMoXHJcbiAgICAgICAgICAgICAgICAgICAgJC5tYXAoaXRlbXMsIGZ1bmN0aW9uIChpdGVtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0ud2Via2l0R2V0QXNFbnRyeSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkgPSBpdGVtLndlYmtpdEdldEFzRW50cnkoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdvcmthcm91bmQgZm9yIENocm9tZSBidWcgIzE0OTczNTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeS5fZmlsZSA9IGl0ZW0uZ2V0QXNGaWxlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZW50cnk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0QXNFbnRyeSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiAkLkRlZmVycmVkKCkucmVzb2x2ZShcclxuICAgICAgICAgICAgICAgICQubWFrZUFycmF5KGRhdGFUcmFuc2Zlci5maWxlcylcclxuICAgICAgICAgICAgKS5wcm9taXNlKCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2dldFNpbmdsZUZpbGVJbnB1dEZpbGVzOiBmdW5jdGlvbiAoZmlsZUlucHV0KSB7XHJcbiAgICAgICAgICAgIGZpbGVJbnB1dCA9ICQoZmlsZUlucHV0KTtcclxuICAgICAgICAgICAgdmFyIGVudHJpZXMgPSBmaWxlSW5wdXQucHJvcCgnd2Via2l0RW50cmllcycpIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZUlucHV0LnByb3AoJ2VudHJpZXMnKSxcclxuICAgICAgICAgICAgICAgIGZpbGVzLFxyXG4gICAgICAgICAgICAgICAgdmFsdWU7XHJcbiAgICAgICAgICAgIGlmIChlbnRyaWVzICYmIGVudHJpZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5faGFuZGxlRmlsZVRyZWVFbnRyaWVzKGVudHJpZXMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGZpbGVzID0gJC5tYWtlQXJyYXkoZmlsZUlucHV0LnByb3AoJ2ZpbGVzJykpO1xyXG4gICAgICAgICAgICBpZiAoIWZpbGVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBmaWxlSW5wdXQucHJvcCgndmFsdWUnKTtcclxuICAgICAgICAgICAgICAgIGlmICghdmFsdWUpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJC5EZWZlcnJlZCgpLnJlc29sdmUoW10pLnByb21pc2UoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBmaWxlcyBwcm9wZXJ0eSBpcyBub3QgYXZhaWxhYmxlLCB0aGUgYnJvd3NlciBkb2VzIG5vdFxyXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCB0aGUgRmlsZSBBUEkgYW5kIHdlIGFkZCBhIHBzZXVkbyBGaWxlIG9iamVjdCB3aXRoXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgaW5wdXQgdmFsdWUgYXMgbmFtZSB3aXRoIHBhdGggaW5mb3JtYXRpb24gcmVtb3ZlZDpcclxuICAgICAgICAgICAgICAgIGZpbGVzID0gW3tuYW1lOiB2YWx1ZS5yZXBsYWNlKC9eLipcXFxcLywgJycpfV07XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsZXNbMF0ubmFtZSA9PT0gdW5kZWZpbmVkICYmIGZpbGVzWzBdLmZpbGVOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBGaWxlIG5vcm1hbGl6YXRpb24gZm9yIFNhZmFyaSA0IGFuZCBGaXJlZm94IDM6XHJcbiAgICAgICAgICAgICAgICAkLmVhY2goZmlsZXMsIGZ1bmN0aW9uIChpbmRleCwgZmlsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbGUubmFtZSA9IGZpbGUuZmlsZU5hbWU7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlsZS5zaXplID0gZmlsZS5maWxlU2l6ZTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiAkLkRlZmVycmVkKCkucmVzb2x2ZShmaWxlcykucHJvbWlzZSgpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9nZXRGaWxlSW5wdXRGaWxlczogZnVuY3Rpb24gKGZpbGVJbnB1dCkge1xyXG4gICAgICAgICAgICBpZiAoIShmaWxlSW5wdXQgaW5zdGFuY2VvZiAkKSB8fCBmaWxlSW5wdXQubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZ2V0U2luZ2xlRmlsZUlucHV0RmlsZXMoZmlsZUlucHV0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gJC53aGVuLmFwcGx5KFxyXG4gICAgICAgICAgICAgICAgJCxcclxuICAgICAgICAgICAgICAgICQubWFwKGZpbGVJbnB1dCwgdGhpcy5fZ2V0U2luZ2xlRmlsZUlucHV0RmlsZXMpXHJcbiAgICAgICAgICAgICkucGlwZShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShcclxuICAgICAgICAgICAgICAgICAgICBbXSxcclxuICAgICAgICAgICAgICAgICAgICBhcmd1bWVudHNcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9vbkNoYW5nZTogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgICAgICAgZGF0YSA9IHtcclxuICAgICAgICAgICAgICAgICAgICBmaWxlSW5wdXQ6ICQoZS50YXJnZXQpLFxyXG4gICAgICAgICAgICAgICAgICAgIGZvcm06ICQoZS50YXJnZXQuZm9ybSlcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHRoaXMuX2dldEZpbGVJbnB1dEZpbGVzKGRhdGEuZmlsZUlucHV0KS5hbHdheXMoZnVuY3Rpb24gKGZpbGVzKSB7XHJcbiAgICAgICAgICAgICAgICBkYXRhLmZpbGVzID0gZmlsZXM7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhhdC5vcHRpb25zLnJlcGxhY2VGaWxlSW5wdXQpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll9yZXBsYWNlRmlsZUlucHV0KGRhdGEuZmlsZUlucHV0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICh0aGF0Ll90cmlnZ2VyKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAnY2hhbmdlJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJC5FdmVudCgnY2hhbmdlJywge2RlbGVnYXRlZEV2ZW50OiBlfSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFcclxuICAgICAgICAgICAgICAgICAgICApICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoYXQuX29uQWRkKGUsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfb25QYXN0ZTogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgdmFyIGl0ZW1zID0gZS5vcmlnaW5hbEV2ZW50ICYmIGUub3JpZ2luYWxFdmVudC5jbGlwYm9hcmREYXRhICYmXHJcbiAgICAgICAgICAgICAgICAgICAgZS5vcmlnaW5hbEV2ZW50LmNsaXBib2FyZERhdGEuaXRlbXMsXHJcbiAgICAgICAgICAgICAgICBkYXRhID0ge2ZpbGVzOiBbXX07XHJcbiAgICAgICAgICAgIGlmIChpdGVtcyAmJiBpdGVtcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICQuZWFjaChpdGVtcywgZnVuY3Rpb24gKGluZGV4LCBpdGVtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGUgPSBpdGVtLmdldEFzRmlsZSAmJiBpdGVtLmdldEFzRmlsZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZmlsZXMucHVzaChmaWxlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl90cmlnZ2VyKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAncGFzdGUnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkLkV2ZW50KCdwYXN0ZScsIHtkZWxlZ2F0ZWRFdmVudDogZX0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhXHJcbiAgICAgICAgICAgICAgICAgICAgKSAhPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbkFkZChlLCBkYXRhKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9vbkRyb3A6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgIGUuZGF0YVRyYW5zZmVyID0gZS5vcmlnaW5hbEV2ZW50ICYmIGUub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXI7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcyxcclxuICAgICAgICAgICAgICAgIGRhdGFUcmFuc2ZlciA9IGUuZGF0YVRyYW5zZmVyLFxyXG4gICAgICAgICAgICAgICAgZGF0YSA9IHt9O1xyXG4gICAgICAgICAgICBpZiAoZGF0YVRyYW5zZmVyICYmIGRhdGFUcmFuc2Zlci5maWxlcyAmJiBkYXRhVHJhbnNmZXIuZmlsZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9nZXREcm9wcGVkRmlsZXMoZGF0YVRyYW5zZmVyKS5hbHdheXMoZnVuY3Rpb24gKGZpbGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5maWxlcyA9IGZpbGVzO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGF0Ll90cmlnZ2VyKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2Ryb3AnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJC5FdmVudCgnZHJvcCcsIHtkZWxlZ2F0ZWRFdmVudDogZX0pLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVxyXG4gICAgICAgICAgICAgICAgICAgICAgICApICE9PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9vbkFkZChlLCBkYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9vbkRyYWdPdmVyOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICBlLmRhdGFUcmFuc2ZlciA9IGUub3JpZ2luYWxFdmVudCAmJiBlLm9yaWdpbmFsRXZlbnQuZGF0YVRyYW5zZmVyO1xyXG4gICAgICAgICAgICB2YXIgZGF0YVRyYW5zZmVyID0gZS5kYXRhVHJhbnNmZXI7XHJcbiAgICAgICAgICAgIGlmIChkYXRhVHJhbnNmZXIgJiYgJC5pbkFycmF5KCdGaWxlcycsIGRhdGFUcmFuc2Zlci50eXBlcykgIT09IC0xICYmXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlcihcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ2RyYWdvdmVyJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJC5FdmVudCgnZHJhZ292ZXInLCB7ZGVsZWdhdGVkRXZlbnQ6IGV9KVxyXG4gICAgICAgICAgICAgICAgICAgICkgIT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgICAgICBkYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdjb3B5JztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9pbml0RXZlbnRIYW5kbGVyczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5faXNYSFJVcGxvYWQodGhpcy5vcHRpb25zKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fb24odGhpcy5vcHRpb25zLmRyb3Bab25lLCB7XHJcbiAgICAgICAgICAgICAgICAgICAgZHJhZ292ZXI6IHRoaXMuX29uRHJhZ092ZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgZHJvcDogdGhpcy5fb25Ecm9wXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29uKHRoaXMub3B0aW9ucy5wYXN0ZVpvbmUsIHtcclxuICAgICAgICAgICAgICAgICAgICBwYXN0ZTogdGhpcy5fb25QYXN0ZVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCQuc3VwcG9ydC5maWxlSW5wdXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29uKHRoaXMub3B0aW9ucy5maWxlSW5wdXQsIHtcclxuICAgICAgICAgICAgICAgICAgICBjaGFuZ2U6IHRoaXMuX29uQ2hhbmdlXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9kZXN0cm95RXZlbnRIYW5kbGVyczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0aGlzLl9vZmYodGhpcy5vcHRpb25zLmRyb3Bab25lLCAnZHJhZ292ZXIgZHJvcCcpO1xyXG4gICAgICAgICAgICB0aGlzLl9vZmYodGhpcy5vcHRpb25zLnBhc3RlWm9uZSwgJ3Bhc3RlJyk7XHJcbiAgICAgICAgICAgIHRoaXMuX29mZih0aGlzLm9wdGlvbnMuZmlsZUlucHV0LCAnY2hhbmdlJyk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX3NldE9wdGlvbjogZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgICAgICAgdmFyIHJlaW5pdCA9ICQuaW5BcnJheShrZXksIHRoaXMuX3NwZWNpYWxPcHRpb25zKSAhPT0gLTE7XHJcbiAgICAgICAgICAgIGlmIChyZWluaXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lFdmVudEhhbmRsZXJzKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5fc3VwZXIoa2V5LCB2YWx1ZSk7XHJcbiAgICAgICAgICAgIGlmIChyZWluaXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2luaXRTcGVjaWFsT3B0aW9ucygpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdEV2ZW50SGFuZGxlcnMoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9pbml0U3BlY2lhbE9wdGlvbnM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmZpbGVJbnB1dCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmZpbGVJbnB1dCA9IHRoaXMuZWxlbWVudC5pcygnaW5wdXRbdHlwZT1cImZpbGVcIl0nKSA/XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudCA6IHRoaXMuZWxlbWVudC5maW5kKCdpbnB1dFt0eXBlPVwiZmlsZVwiXScpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKCEob3B0aW9ucy5maWxlSW5wdXQgaW5zdGFuY2VvZiAkKSkge1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5maWxlSW5wdXQgPSAkKG9wdGlvbnMuZmlsZUlucHV0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoIShvcHRpb25zLmRyb3Bab25lIGluc3RhbmNlb2YgJCkpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZHJvcFpvbmUgPSAkKG9wdGlvbnMuZHJvcFpvbmUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICghKG9wdGlvbnMucGFzdGVab25lIGluc3RhbmNlb2YgJCkpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMucGFzdGVab25lID0gJChvcHRpb25zLnBhc3RlWm9uZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfZ2V0UmVnRXhwOiBmdW5jdGlvbiAoc3RyKSB7XHJcbiAgICAgICAgICAgIHZhciBwYXJ0cyA9IHN0ci5zcGxpdCgnLycpLFxyXG4gICAgICAgICAgICAgICAgbW9kaWZpZXJzID0gcGFydHMucG9wKCk7XHJcbiAgICAgICAgICAgIHBhcnRzLnNoaWZ0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVnRXhwKHBhcnRzLmpvaW4oJy8nKSwgbW9kaWZpZXJzKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfaXNSZWdFeHBPcHRpb246IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBrZXkgIT09ICd1cmwnICYmICQudHlwZSh2YWx1ZSkgPT09ICdzdHJpbmcnICYmXHJcbiAgICAgICAgICAgICAgICAvXlxcLy4qXFwvW2lnbV17MCwzfSQvLnRlc3QodmFsdWUpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9pbml0RGF0YUF0dHJpYnV0ZXM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxyXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcclxuICAgICAgICAgICAgICAgIGNsb25lID0gJCh0aGlzLmVsZW1lbnRbMF0uY2xvbmVOb2RlKGZhbHNlKSk7XHJcbiAgICAgICAgICAgIC8vIEluaXRpYWxpemUgb3B0aW9ucyBzZXQgdmlhIEhUTUw1IGRhdGEtYXR0cmlidXRlczpcclxuICAgICAgICAgICAgJC5lYWNoKFxyXG4gICAgICAgICAgICAgICAgY2xvbmUuZGF0YSgpLFxyXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YUF0dHJpYnV0ZU5hbWUgPSAnZGF0YS0nICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29udmVydCBjYW1lbENhc2UgdG8gaHlwaGVuLWF0ZWQga2V5OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXkucmVwbGFjZSgvKFthLXpdKShbQS1aXSkvZywgJyQxLSQyJykudG9Mb3dlckNhc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY2xvbmUuYXR0cihkYXRhQXR0cmlidXRlTmFtZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuX2lzUmVnRXhwT3B0aW9uKGtleSwgdmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoYXQuX2dldFJlZ0V4cCh2YWx1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uc1trZXldID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9jcmVhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdGhpcy5faW5pdERhdGFBdHRyaWJ1dGVzKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX2luaXRTcGVjaWFsT3B0aW9ucygpO1xyXG4gICAgICAgICAgICB0aGlzLl9zbG90cyA9IFtdO1xyXG4gICAgICAgICAgICB0aGlzLl9zZXF1ZW5jZSA9IHRoaXMuX2dldFhIUlByb21pc2UodHJ1ZSk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NlbmRpbmcgPSB0aGlzLl9hY3RpdmUgPSAwO1xyXG4gICAgICAgICAgICB0aGlzLl9pbml0UHJvZ3Jlc3NPYmplY3QodGhpcyk7XHJcbiAgICAgICAgICAgIHRoaXMuX2luaXRFdmVudEhhbmRsZXJzKCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8gVGhpcyBtZXRob2QgaXMgZXhwb3NlZCB0byB0aGUgd2lkZ2V0IEFQSSBhbmQgYWxsb3dzIHRvIHF1ZXJ5XHJcbiAgICAgICAgLy8gdGhlIG51bWJlciBvZiBhY3RpdmUgdXBsb2FkczpcclxuICAgICAgICBhY3RpdmU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FjdGl2ZTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICAvLyBUaGlzIG1ldGhvZCBpcyBleHBvc2VkIHRvIHRoZSB3aWRnZXQgQVBJIGFuZCBhbGxvd3MgdG8gcXVlcnlcclxuICAgICAgICAvLyB0aGUgd2lkZ2V0IHVwbG9hZCBwcm9ncmVzcy5cclxuICAgICAgICAvLyBJdCByZXR1cm5zIGFuIG9iamVjdCB3aXRoIGxvYWRlZCwgdG90YWwgYW5kIGJpdHJhdGUgcHJvcGVydGllc1xyXG4gICAgICAgIC8vIGZvciB0aGUgcnVubmluZyB1cGxvYWRzOlxyXG4gICAgICAgIHByb2dyZXNzOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wcm9ncmVzcztcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICAvLyBUaGlzIG1ldGhvZCBpcyBleHBvc2VkIHRvIHRoZSB3aWRnZXQgQVBJIGFuZCBhbGxvd3MgYWRkaW5nIGZpbGVzXHJcbiAgICAgICAgLy8gdXNpbmcgdGhlIGZpbGV1cGxvYWQgQVBJLiBUaGUgZGF0YSBwYXJhbWV0ZXIgYWNjZXB0cyBhbiBvYmplY3Qgd2hpY2hcclxuICAgICAgICAvLyBtdXN0IGhhdmUgYSBmaWxlcyBwcm9wZXJ0eSBhbmQgY2FuIGNvbnRhaW4gYWRkaXRpb25hbCBvcHRpb25zOlxyXG4gICAgICAgIC8vIC5maWxldXBsb2FkKCdhZGQnLCB7ZmlsZXM6IGZpbGVzTGlzdH0pO1xyXG4gICAgICAgIGFkZDogZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xyXG4gICAgICAgICAgICBpZiAoIWRhdGEgfHwgdGhpcy5vcHRpb25zLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGRhdGEuZmlsZUlucHV0ICYmICFkYXRhLmZpbGVzKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9nZXRGaWxlSW5wdXRGaWxlcyhkYXRhLmZpbGVJbnB1dCkuYWx3YXlzKGZ1bmN0aW9uIChmaWxlcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEuZmlsZXMgPSBmaWxlcztcclxuICAgICAgICAgICAgICAgICAgICB0aGF0Ll9vbkFkZChudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZGF0YS5maWxlcyA9ICQubWFrZUFycmF5KGRhdGEuZmlsZXMpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fb25BZGQobnVsbCwgZGF0YSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICAvLyBUaGlzIG1ldGhvZCBpcyBleHBvc2VkIHRvIHRoZSB3aWRnZXQgQVBJIGFuZCBhbGxvd3Mgc2VuZGluZyBmaWxlc1xyXG4gICAgICAgIC8vIHVzaW5nIHRoZSBmaWxldXBsb2FkIEFQSS4gVGhlIGRhdGEgcGFyYW1ldGVyIGFjY2VwdHMgYW4gb2JqZWN0IHdoaWNoXHJcbiAgICAgICAgLy8gbXVzdCBoYXZlIGEgZmlsZXMgb3IgZmlsZUlucHV0IHByb3BlcnR5IGFuZCBjYW4gY29udGFpbiBhZGRpdGlvbmFsIG9wdGlvbnM6XHJcbiAgICAgICAgLy8gLmZpbGV1cGxvYWQoJ3NlbmQnLCB7ZmlsZXM6IGZpbGVzTGlzdH0pO1xyXG4gICAgICAgIC8vIFRoZSBtZXRob2QgcmV0dXJucyBhIFByb21pc2Ugb2JqZWN0IGZvciB0aGUgZmlsZSB1cGxvYWQgY2FsbC5cclxuICAgICAgICBzZW5kOiBmdW5jdGlvbiAoZGF0YSkge1xyXG4gICAgICAgICAgICBpZiAoZGF0YSAmJiAhdGhpcy5vcHRpb25zLmRpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5maWxlSW5wdXQgJiYgIWRhdGEuZmlsZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRmZCA9ICQuRGVmZXJyZWQoKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZSA9IGRmZC5wcm9taXNlKCksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGpxWEhSLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhYm9ydGVkO1xyXG4gICAgICAgICAgICAgICAgICAgIHByb21pc2UuYWJvcnQgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0ZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoanFYSFIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBqcVhIUi5hYm9ydCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRmZC5yZWplY3QobnVsbCwgJ2Fib3J0JywgJ2Fib3J0Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xyXG4gICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZ2V0RmlsZUlucHV0RmlsZXMoZGF0YS5maWxlSW5wdXQpLmFsd2F5cyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKGZpbGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWJvcnRlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZmlsZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZkLnJlamVjdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZmlsZXMgPSBmaWxlcztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGpxWEhSID0gdGhhdC5fb25TZW5kKG51bGwsIGRhdGEpLnRoZW4oXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJlc3VsdCwgdGV4dFN0YXR1cywganFYSFIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZkLnJlc29sdmUocmVzdWx0LCB0ZXh0U3RhdHVzLCBqcVhIUik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmZC5yZWplY3QoanFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZW5oYW5jZVByb21pc2UocHJvbWlzZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBkYXRhLmZpbGVzID0gJC5tYWtlQXJyYXkoZGF0YS5maWxlcyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5maWxlcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fb25TZW5kKG51bGwsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9nZXRYSFJQcm9taXNlKGZhbHNlLCBkYXRhICYmIGRhdGEuY29udGV4dCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIH0pO1xyXG5cclxufSkpO1xyXG4iXSwiZmlsZSI6ImpxdWVyeS5maWxldXBsb2FkLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload.min.js new file mode 100644 index 000000000..1838295fc --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jquery.fileupload.min.js @@ -0,0 +1 @@ +!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","jquery.ui.widget"],e):e(window.jQuery)}(function(e){"use strict";e.support.fileInput=!(new RegExp("(Android (1\\.[0156]|2\\.[01]))|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)|(w(eb)?OSBrowser)|(webOS)|(Kindle/(1\\.0|2\\.[05]|3\\.0))").test(window.navigator.userAgent)||e('').prop("disabled")),e.support.xhrFileUpload=!(!window.ProgressEvent||!window.FileReader),e.support.xhrFormDataFileUpload=!!window.FormData,e.support.blobSlice=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice),e.widget("blueimp.fileupload",{options:{dropZone:e(document),pasteZone:e(document),fileInput:void 0,replaceFileInput:!0,paramName:void 0,singleFileUploads:!0,limitMultiFileUploads:void 0,limitMultiFileUploadSize:void 0,limitMultiFileUploadSizeOverhead:512,sequentialUploads:!1,limitConcurrentUploads:void 0,forceIframeTransport:!1,redirect:void 0,redirectParamName:void 0,postMessage:void 0,multipart:!0,maxChunkSize:void 0,uploadedBytes:void 0,recalculateProgress:!0,progressInterval:100,bitrateInterval:500,autoUpload:!0,messages:{uploadedBytes:"Uploaded bytes exceed file size"},i18n:function(t,i){return t=this.messages[t]||t.toString(),i&&e.each(i,function(e,i){t=t.replace("{"+e+"}",i)}),t},formData:function(e){return e.serializeArray()},add:function(t,i){return t.isDefaultPrevented()?!1:void((i.autoUpload||i.autoUpload!==!1&&e(this).fileupload("option","autoUpload"))&&i.process().done(function(){i.submit()}))},processData:!1,contentType:!1,cache:!1},_specialOptions:["fileInput","dropZone","pasteZone","multipart","forceIframeTransport"],_blobSlice:e.support.blobSlice&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},_BitrateTimer:function(){this.timestamp=Date.now?Date.now():(new Date).getTime(),this.loaded=0,this.bitrate=0,this.getBitrate=function(e,t,i){var r=e-this.timestamp;return(!this.bitrate||!i||r>i)&&(this.bitrate=(t-this.loaded)*(1e3/r)*8,this.loaded=t,this.timestamp=e),this.bitrate}},_isXHRUpload:function(t){return!t.forceIframeTransport&&(!t.multipart&&e.support.xhrFileUpload||e.support.xhrFormDataFileUpload)},_getFormData:function(t){var i;return"function"===e.type(t.formData)?t.formData(t.form):e.isArray(t.formData)?t.formData:"object"===e.type(t.formData)?(i=[],e.each(t.formData,function(e,t){i.push({name:e,value:t})}),i):[]},_getTotal:function(t){var i=0;return e.each(t,function(e,t){i+=t.size||1}),i},_initProgressObject:function(t){var i={loaded:0,total:0,bitrate:0};t._progress?e.extend(t._progress,i):t._progress=i},_initResponseObject:function(e){var t;if(e._response)for(t in e._response)e._response.hasOwnProperty(t)&&delete e._response[t];else e._response={}},_onProgress:function(t,i){if(t.lengthComputable){var r,n=Date.now?Date.now():(new Date).getTime();if(i._time&&i.progressInterval&&n-i._time").prop("href",t.url).prop("host");t.dataType="iframe "+(t.dataType||""),t.formData=this._getFormData(t),t.redirect&&i&&i!==location.host&&t.formData.push({name:t.redirectParamName||"redirect",value:t.redirect})},_initDataSettings:function(e){this._isXHRUpload(e)?(this._chunkedUpload(e,!0)||(e.data||this._initXHRData(e),this._initProgressListener(e)),e.postMessage&&(e.dataType="postmessage "+(e.dataType||""))):this._initIframeSettings(e)},_getParamName:function(t){var i=e(t.fileInput),r=t.paramName;return r?e.isArray(r)||(r=[r]):(r=[],i.each(function(){for(var t=e(this),i=t.prop("name")||"files[]",n=(t.prop("files")||[1]).length;n;)r.push(i),n-=1}),r.length||(r=[i.prop("name")||"files[]"])),r},_initFormSettings:function(t){t.form&&t.form.length||(t.form=e(t.fileInput.prop("form")),t.form.length||(t.form=e(this.options.fileInput.prop("form")))),t.paramName=this._getParamName(t),t.url||(t.url=t.form.prop("action")||location.href),t.type=(t.type||"string"===e.type(t.form.prop("method"))&&t.form.prop("method")||"").toUpperCase(),"POST"!==t.type&&"PUT"!==t.type&&"PATCH"!==t.type&&(t.type="POST"),t.formAcceptCharset||(t.formAcceptCharset=t.form.attr("accept-charset"))},_getAJAXSettings:function(t){var i=e.extend({},this.options,t);return this._initFormSettings(i),this._initDataSettings(i),i},_getDeferredState:function(e){return e.state?e.state():e.isResolved()?"resolved":e.isRejected()?"rejected":"pending"},_enhancePromise:function(e){return e.success=e.done,e.error=e.fail,e.complete=e.always,e},_getXHRPromise:function(t,i,r){var n=e.Deferred(),s=n.promise();return i=i||this.options.context||s,t===!0?n.resolveWith(i,r):t===!1&&n.rejectWith(i,r),s.abort=n.promise,this._enhancePromise(s)},_addConvenienceMethods:function(t,i){var r=this,n=function(t){return e.Deferred().resolveWith(r,t).promise()};i.process=function(t,s){return(t||s)&&(i._processQueue=this._processQueue=(this._processQueue||n([this])).pipe(function(){return i.errorThrown?e.Deferred().rejectWith(r,[i]).promise():n(arguments)}).pipe(t,s)),this._processQueue||n([this])},i.submit=function(){return"pending"!==this.state()&&(i.jqXHR=this.jqXHR=r._trigger("submit",e.Event("submit",{delegatedEvent:t}),this)!==!1&&r._onSend(t,this)),this.jqXHR||r._getXHRPromise()},i.abort=function(){return this.jqXHR?this.jqXHR.abort():(this.errorThrown="abort",r._trigger("fail",null,this),r._getXHRPromise(!1))},i.state=function(){return this.jqXHR?r._getDeferredState(this.jqXHR):this._processQueue?r._getDeferredState(this._processQueue):void 0},i.processing=function(){return!this.jqXHR&&this._processQueue&&"pending"===r._getDeferredState(this._processQueue)},i.progress=function(){return this._progress},i.response=function(){return this._response}},_getUploadedBytes:function(e){var t=e.getResponseHeader("Range"),i=t&&t.split("-"),r=i&&i.length>1&&parseInt(i[1],10);return r&&r+1},_chunkedUpload:function(t,i){t.uploadedBytes=t.uploadedBytes||0;var r,n,s=this,o=t.files[0],a=o.size,l=t.uploadedBytes,p=t.maxChunkSize||a,u=this._blobSlice,d=e.Deferred(),h=d.promise();return this._isXHRUpload(t)&&u&&(l||a>p)&&!t.data?i?!0:l>=a?(o.error=t.i18n("uploadedBytes"),this._getXHRPromise(!1,t.context,[null,"error",o.error])):(n=function(){var i=e.extend({},t),h=i._progress.loaded;i.blob=u.call(o,l,l+p,o.type),i.chunkSize=i.blob.size,i.contentRange="bytes "+l+"-"+(l+i.chunkSize-1)+"/"+a,s._initXHRData(i),s._initProgressListener(i),r=(s._trigger("chunksend",null,i)!==!1&&e.ajax(i)||s._getXHRPromise(!1,i.context)).done(function(r,o,p){l=s._getUploadedBytes(p)||l+i.chunkSize,h+i.chunkSize-i._progress.loaded&&s._onProgress(e.Event("progress",{lengthComputable:!0,loaded:l-i.uploadedBytes,total:l-i.uploadedBytes}),i),t.uploadedBytes=i.uploadedBytes=l,i.result=r,i.textStatus=o,i.jqXHR=p,s._trigger("chunkdone",null,i),s._trigger("chunkalways",null,i),a>l?n():d.resolveWith(i.context,[r,o,p])}).fail(function(e,t,r){i.jqXHR=e,i.textStatus=t,i.errorThrown=r,s._trigger("chunkfail",null,i),s._trigger("chunkalways",null,i),d.rejectWith(i.context,[e,t,r])})},this._enhancePromise(h),h.abort=function(){return r.abort()},n(),h):!1},_beforeSend:function(e,t){0===this._active&&(this._trigger("start"),this._bitrateTimer=new this._BitrateTimer,this._progress.loaded=this._progress.total=0,this._progress.bitrate=0),this._initResponseObject(t),this._initProgressObject(t),t._progress.loaded=t.loaded=t.uploadedBytes||0,t._progress.total=t.total=this._getTotal(t.files)||1,t._progress.bitrate=t.bitrate=0,this._active+=1,this._progress.loaded+=t.loaded,this._progress.total+=t.total},_onDone:function(t,i,r,n){var s=n._progress.total,o=n._response;n._progress.loadeda._sending)for(var r=a._slots.shift();r;){if("pending"===a._getDeferredState(r)){r.resolve();break}r=a._slots.shift()}0===a._active&&a._trigger("stop")})};return this._beforeSend(t,l),this.options.sequentialUploads||this.options.limitConcurrentUploads&&this.options.limitConcurrentUploads<=this._sending?(this.options.limitConcurrentUploads>1?(s=e.Deferred(),this._slots.push(s),o=s.pipe(p)):(this._sequence=this._sequence.pipe(p,p),o=this._sequence),o.abort=function(){return n=[void 0,"abort","abort"],r?r.abort():(s&&s.rejectWith(l.context,n),p())},this._enhancePromise(o)):p()},_onAdd:function(t,i){var r,n,s,o,a=this,l=!0,p=e.extend({},this.options,i),u=i.files,d=u.length,h=p.limitMultiFileUploads,c=p.limitMultiFileUploadSize,f=p.limitMultiFileUploadSizeOverhead,g=0,_=this._getParamName(p),m=0;if(!c||d&&void 0!==u[0].size||(c=void 0),(p.singleFileUploads||h||c)&&this._isXHRUpload(p))if(p.singleFileUploads||c||!h)if(!p.singleFileUploads&&c)for(s=[],r=[],o=0;d>o;o+=1)g+=u[o].size+f,(o+1===d||g+u[o+1].size+f>c||h&&o+1-m>=h)&&(s.push(u.slice(m,o+1)),n=_.slice(m,o+1),n.length||(n=_),r.push(n),m=o+1,g=0);else r=_;else for(s=[],r=[],o=0;d>o;o+=h)s.push(u.slice(o,o+h)),n=_.slice(o,o+h),n.length||(n=_),r.push(n);else s=[u],r=[_];return i.originalFiles=u,e.each(s||u,function(n,o){var p=e.extend({},i);return p.files=s?o:[o],p.paramName=r[n],a._initResponseObject(p),a._initProgressObject(p),a._addConvenienceMethods(t,p),l=a._trigger("add",e.Event("add",{delegatedEvent:t}),p)}),l},_replaceFileInput:function(t){var i=t.clone(!0);e("").append(i)[0].reset(),t.after(i).detach(),e.cleanData(t.unbind("remove")),this.options.fileInput=this.options.fileInput.map(function(e,r){return r===t[0]?i[0]:r}),t[0]===this.element[0]&&(this.element=i)},_handleFileTreeEntry:function(t,i){var r,n=this,s=e.Deferred(),o=function(e){e&&!e.entry&&(e.entry=t),s.resolve([e])};return i=i||"",t.isFile?t._file?(t._file.relativePath=i,s.resolve(t._file)):t.file(function(e){e.relativePath=i,s.resolve(e)},o):t.isDirectory?(r=t.createReader(),r.readEntries(function(e){n._handleFileTreeEntries(e,i+t.name+"/").done(function(e){s.resolve(e)}).fail(o)},o)):s.resolve([]),s.promise()},_handleFileTreeEntries:function(t,i){var r=this;return e.when.apply(e,e.map(t,function(e){return r._handleFileTreeEntry(e,i)})).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_getDroppedFiles:function(t){t=t||{};var i=t.items;return i&&i.length&&(i[0].webkitGetAsEntry||i[0].getAsEntry)?this._handleFileTreeEntries(e.map(i,function(e){var t;return e.webkitGetAsEntry?(t=e.webkitGetAsEntry(),t&&(t._file=e.getAsFile()),t):e.getAsEntry()})):e.Deferred().resolve(e.makeArray(t.files)).promise()},_getSingleFileInputFiles:function(t){t=e(t);var i,r,n=t.prop("webkitEntries")||t.prop("entries");if(n&&n.length)return this._handleFileTreeEntries(n);if(i=e.makeArray(t.prop("files")),i.length)void 0===i[0].name&&i[0].fileName&&e.each(i,function(e,t){t.name=t.fileName,t.size=t.fileSize});else{if(r=t.prop("value"),!r)return e.Deferred().resolve([]).promise();i=[{name:r.replace(/^.*\\/,"")}]}return e.Deferred().resolve(i).promise()},_getFileInputFiles:function(t){return t instanceof e&&1!==t.length?e.when.apply(e,e.map(t,this._getSingleFileInputFiles)).pipe(function(){return Array.prototype.concat.apply([],arguments)}):this._getSingleFileInputFiles(t)},_onChange:function(t){var i=this,r={fileInput:e(t.target),form:e(t.target.form)};this._getFileInputFiles(r.fileInput).always(function(n){r.files=n,i.options.replaceFileInput&&i._replaceFileInput(r.fileInput),i._trigger("change",e.Event("change",{delegatedEvent:t}),r)!==!1&&i._onAdd(t,r)})},_onPaste:function(t){var i=t.originalEvent&&t.originalEvent.clipboardData&&t.originalEvent.clipboardData.items,r={files:[]};i&&i.length&&(e.each(i,function(e,t){var i=t.getAsFile&&t.getAsFile();i&&r.files.push(i)}),this._trigger("paste",e.Event("paste",{delegatedEvent:t}),r)!==!1&&this._onAdd(t,r))},_onDrop:function(t){t.dataTransfer=t.originalEvent&&t.originalEvent.dataTransfer;var i=this,r=t.dataTransfer,n={};r&&r.files&&r.files.length&&(t.preventDefault(),this._getDroppedFiles(r).always(function(r){n.files=r,i._trigger("drop",e.Event("drop",{delegatedEvent:t}),n)!==!1&&i._onAdd(t,n)}))},_onDragOver:function(t){t.dataTransfer=t.originalEvent&&t.originalEvent.dataTransfer;var i=t.dataTransfer;i&&-1!==e.inArray("Files",i.types)&&this._trigger("dragover",e.Event("dragover",{delegatedEvent:t}))!==!1&&(t.preventDefault(),i.dropEffect="copy")},_initEventHandlers:function(){this._isXHRUpload(this.options)&&(this._on(this.options.dropZone,{dragover:this._onDragOver,drop:this._onDrop}),this._on(this.options.pasteZone,{paste:this._onPaste})),e.support.fileInput&&this._on(this.options.fileInput,{change:this._onChange})},_destroyEventHandlers:function(){this._off(this.options.dropZone,"dragover drop"),this._off(this.options.pasteZone,"paste"),this._off(this.options.fileInput,"change")},_setOption:function(t,i){var r=-1!==e.inArray(t,this._specialOptions);r&&this._destroyEventHandlers(),this._super(t,i),r&&(this._initSpecialOptions(),this._initEventHandlers())},_initSpecialOptions:function(){var t=this.options;void 0===t.fileInput?t.fileInput=this.element.is('input[type="file"]')?this.element:this.element.find('input[type="file"]'):t.fileInput instanceof e||(t.fileInput=e(t.fileInput)),t.dropZone instanceof e||(t.dropZone=e(t.dropZone)),t.pasteZone instanceof e||(t.pasteZone=e(t.pasteZone))},_getRegExp:function(e){var t=e.split("/"),i=t.pop();return t.shift(),new RegExp(t.join("/"),i)},_isRegExpOption:function(t,i){return"url"!==t&&"string"===e.type(i)&&/^\/.*\/[igm]{0,3}$/.test(i)},_initDataAttributes:function(){var t=this,i=this.options,r=e(this.element[0].cloneNode(!1));e.each(r.data(),function(e,n){var s="data-"+e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();r.attr(s)&&(t._isRegExpOption(e,n)&&(n=t._getRegExp(n)),i[e]=n)})},_create:function(){this._initDataAttributes(),this._initSpecialOptions(),this._slots=[],this._sequence=this._getXHRPromise(!0),this._sending=this._active=0,this._initProgressObject(this),this._initEventHandlers()},active:function(){return this._active},progress:function(){return this._progress},add:function(t){var i=this;t&&!this.options.disabled&&(t.fileInput&&!t.files?this._getFileInputFiles(t.fileInput).always(function(e){t.files=e,i._onAdd(null,t)}):(t.files=e.makeArray(t.files),this._onAdd(null,t)))},send:function(t){if(t&&!this.options.disabled){if(t.fileInput&&!t.files){var i,r,n=this,s=e.Deferred(),o=s.promise();return o.abort=function(){return r=!0,i?i.abort():(s.reject(null,"abort","abort"),o)},this._getFileInputFiles(t.fileInput).always(function(e){if(!r){if(!e.length)return void s.reject();t.files=e,i=n._onSend(null,t).then(function(e,t,i){s.resolve(e,t,i)},function(e,t,i){s.reject(e,t,i)})}}),this._enhancePromise(o)}if(t.files=e.makeArray(t.files),t.files.length)return this._onSend(null,t)}return this._getXHRPromise(!1,t&&t.context)}})}); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.js new file mode 100644 index 000000000..4ec0a3423 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.js @@ -0,0 +1,5800 @@ +/*globals jQuery, define, exports, require, window, document */ +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } + else if(typeof exports === 'object') { + factory(require('jquery')); + } + else { + factory(jQuery); + } +}(function ($, undefined) { + "use strict"; +/*! + * jsTree 3.0.0 + * http://jstree.com/ + * + * Copyright (c) 2013 Ivan Bozhanov (http://vakata.com) + * + * Licensed same as jquery - under the terms of the MIT License + * http://www.opensource.org/licenses/mit-license.php + */ +/*! + * if using jslint please allow for the jQuery global and use following options: + * jslint: browser: true, ass: true, bitwise: true, continue: true, nomen: true, plusplus: true, regexp: true, unparam: true, todo: true, white: true + */ + + // prevent another load? maybe there is a better way? + if($.jstree) { + return; + } + + /** + * ### jsTree core functionality + */ + + // internal variables + var instance_counter = 0, + ccp_node = false, + ccp_mode = false, + ccp_inst = false, + themes_loaded = [], + src = $('script:last').attr('src'), + _d = document, _node = _d.createElement('LI'), _temp1, _temp2; + + _node.setAttribute('role', 'treeitem'); + _temp1 = _d.createElement('I'); + _temp1.className = 'jstree-icon jstree-ocl'; + _node.appendChild(_temp1); + _temp1 = _d.createElement('A'); + _temp1.className = 'jstree-anchor'; + _temp1.setAttribute('href','#'); + _temp2 = _d.createElement('I'); + _temp2.className = 'jstree-icon jstree-themeicon'; + _temp1.appendChild(_temp2); + _node.appendChild(_temp1); + _temp1 = _temp2 = null; + + + /** + * holds all jstree related functions and variables, including the actual class and methods to create, access and manipulate instances. + * @name $.jstree + */ + $.jstree = { + /** + * specifies the jstree version in use + * @name $.jstree.version + */ + version : '3.0.0-beta9', + /** + * holds all the default options used when creating new instances + * @name $.jstree.defaults + */ + defaults : { + /** + * configure which plugins will be active on an instance. Should be an array of strings, where each element is a plugin name. The default is `[]` + * @name $.jstree.defaults.plugins + */ + plugins : [] + }, + /** + * stores all loaded jstree plugins (used internally) + * @name $.jstree.plugins + */ + plugins : {}, + path : src && src.indexOf('/') !== -1 ? src.replace(/\/[^\/]+$/,'') : '' + }; + /** + * creates a jstree instance + * @name $.jstree.create(el [, options]) + * @param {DOMElement|jQuery|String} el the element to create the instance on, can be jQuery extended or a selector + * @param {Object} options options for this instance (extends `$.jstree.defaults`) + * @return {jsTree} the new instance + */ + $.jstree.create = function (el, options) { + var tmp = new $.jstree.core(++instance_counter), + opt = options; + options = $.extend(true, {}, $.jstree.defaults, options); + if(opt && opt.plugins) { + options.plugins = opt.plugins; + } + $.each(options.plugins, function (i, k) { + if(i !== 'core') { + tmp = tmp.plugin(k, options[k]); + } + }); + tmp.init(el, options); + return tmp; + }; + /** + * the jstree class constructor, used only internally + * @private + * @name $.jstree.core(id) + * @param {Number} id this instance's index + */ + $.jstree.core = function (id) { + this._id = id; + this._cnt = 0; + this._data = { + core : { + themes : { + name : false, + dots : false, + icons : false + }, + selected : [], + last_error : {} + } + }; + }; + /** + * get a reference to an existing instance + * + * __Examples__ + * + * // provided a container with an ID of "tree", and a nested node with an ID of "branch" + * // all of there will return the same instance + * $.jstree.reference('tree'); + * $.jstree.reference('#tree'); + * $.jstree.reference($('#tree')); + * $.jstree.reference(document.getElementByID('tree')); + * $.jstree.reference('branch'); + * $.jstree.reference('#branch'); + * $.jstree.reference($('#branch')); + * $.jstree.reference(document.getElementByID('branch')); + * + * @name $.jstree.reference(needle) + * @param {DOMElement|jQuery|String} needle + * @return {jsTree|null} the instance or `null` if not found + */ + $.jstree.reference = function (needle) { + if(needle && !$(needle).length) { + if(needle.id) { + needle = needle.id; + } + var tmp = null; + $('.jstree').each(function () { + var inst = $(this).data('jstree'); + if(inst && inst._model.data[needle]) { + tmp = inst; + return false; + } + }); + return tmp; + } + return $(needle).closest('.jstree').data('jstree'); + }; + /** + * Create an instance, get an instance or invoke a command on a instance. + * + * If there is no instance associated with the current node a new one is created and `arg` is used to extend `$.jstree.defaults` for this new instance. There would be no return value (chaining is not broken). + * + * If there is an existing instance and `arg` is a string the command specified by `arg` is executed on the instance, with any additional arguments passed to the function. If the function returns a value it will be returned (chaining could break depending on function). + * + * If there is an existing instance and `arg` is not a string the instance itself is returned (similar to `$.jstree.reference`). + * + * In any other case - nothing is returned and chaining is not broken. + * + * __Examples__ + * + * $('#tree1').jstree(); // creates an instance + * $('#tree2').jstree({ plugins : [] }); // create an instance with some options + * $('#tree1').jstree('open_node', '#branch_1'); // call a method on an existing instance, passing additional arguments + * $('#tree2').jstree(); // get an existing instance (or create an instance) + * $('#tree2').jstree(true); // get an existing instance (will not create new instance) + * $('#branch_1').jstree().select_node('#branch_1'); // get an instance (using a nested element and call a method) + * + * @name $().jstree([arg]) + * @param {String|Object} arg + * @return {Mixed} + */ + $.fn.jstree = function (arg) { + // check for string argument + var is_method = (typeof arg === 'string'), + args = Array.prototype.slice.call(arguments, 1), + result = null; + this.each(function () { + // get the instance (if there is one) and method (if it exists) + var instance = $.jstree.reference(this), + method = is_method && instance ? instance[arg] : null; + // if calling a method, and method is available - execute on the instance + result = is_method && method ? + method.apply(instance, args) : + null; + // if there is no instance and no method is being called - create one + if(!instance && !is_method && (arg === undefined || $.isPlainObject(arg))) { + $(this).data('jstree', new $.jstree.create(this, arg)); + } + // if there is an instance and no method is called - return the instance + if(instance && !is_method) { + result = instance; + } + // if there was a method call which returned a result - break and return the value + if(result !== null && result !== undefined) { + return false; + } + }); + // if there was a method call with a valid return value - return that, otherwise continue the chain + return result !== null && result !== undefined ? + result : this; + }; + /** + * used to find elements containing an instance + * + * __Examples__ + * + * $('div:jstree').each(function () { + * $(this).jstree('destroy'); + * }); + * + * @name $(':jstree') + * @return {jQuery} + */ + $.expr[':'].jstree = $.expr.createPseudo(function(search) { + return function(a) { + return $(a).hasClass('jstree') && + $(a).data('jstree') !== undefined; + }; + }); + + /** + * stores all defaults for the core + * @name $.jstree.defaults.core + */ + $.jstree.defaults.core = { + /** + * data configuration + * + * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items). + * + * You can also pass in a HTML string or a JSON array here. + * + * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree. + * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used. + * + * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result. + * + * __Examples__ + * + * // AJAX + * $('#tree').jstree({ + * 'core' : { + * 'data' : { + * 'url' : '/get/children/', + * 'data' : function (node) { + * return { 'id' : node.id }; + * } + * } + * }); + * + * // direct data + * $('#tree').jstree({ + * 'core' : { + * 'data' : [ + * 'Simple root node', + * { + * 'id' : 'node_2', + * 'text' : 'Root node with options', + * 'state' : { 'opened' : true, 'selected' : true }, + * 'children' : [ { 'text' : 'Child 1' }, 'Child 2'] + * } + * ] + * }); + * + * // function + * $('#tree').jstree({ + * 'core' : { + * 'data' : function (obj, callback) { + * callback.call(this, ['Root 1', 'Root 2']); + * } + * }); + * + * @name $.jstree.defaults.core.data + */ + data : false, + /** + * configure the various strings used throughout the tree + * + * You can use an object where the key is the string you need to replace and the value is your replacement. + * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement. + * If left as `false` no replacement is made. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'strings' : { + * 'Loading...' : 'Please wait ...' + * } + * } + * }); + * + * @name $.jstree.defaults.core.strings + */ + strings : false, + /** + * determines what happens when a user tries to modify the structure of the tree + * If left as `false` all operations like create, rename, delete, move or copy are prevented. + * You can set this to `true` to allow all interactions or use a function to have better control. + * + * __Examples__ + * + * $('#tree').jstree({ + * 'core' : { + * 'check_callback' : function (operation, node, node_parent, node_position) { + * // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node' + * // in case of 'rename_node' node_position is filled with the new node name + * return operation === 'rename_node' ? true : false; + * } + * } + * }); + * + * @name $.jstree.defaults.core.check_callback + */ + check_callback : false, + /** + * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc) + * @name $.jstree.defaults.core.error + */ + error : $.noop, + /** + * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`) + * @name $.jstree.defaults.core.animation + */ + animation : 200, + /** + * a boolean indicating if multiple nodes can be selected + * @name $.jstree.defaults.core.multiple + */ + multiple : true, + /** + * theme configuration object + * @name $.jstree.defaults.core.themes + */ + themes : { + /** + * the name of the theme to use (if left as `false` the default theme is used) + * @name $.jstree.defaults.core.themes.name + */ + name : false, + /** + * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme. + * @name $.jstree.defaults.core.themes.url + */ + url : false, + /** + * the location of all jstree themes - only used if `url` is set to `true` + * @name $.jstree.defaults.core.themes.dir + */ + dir : false, + /** + * a boolean indicating if connecting dots are shown + * @name $.jstree.defaults.core.themes.dots + */ + dots : true, + /** + * a boolean indicating if node icons are shown + * @name $.jstree.defaults.core.themes.icons + */ + icons : true, + /** + * a boolean indicating if the tree background is striped + * @name $.jstree.defaults.core.themes.stripes + */ + stripes : false, + /** + * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants) + * @name $.jstree.defaults.core.themes.variant + */ + variant : false, + /** + * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `true`. + * @name $.jstree.defaults.core.themes.responsive + */ + responsive : true + }, + /** + * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user) + * @name $.jstree.defaults.core.expand_selected_onload + */ + expand_selected_onload : true + }; + $.jstree.core.prototype = { + /** + * used to decorate an instance with a plugin. Used internally. + * @private + * @name plugin(deco [, opts]) + * @param {String} deco the plugin to decorate with + * @param {Object} opts options for the plugin + * @return {jsTree} + */ + plugin : function (deco, opts) { + var Child = $.jstree.plugins[deco]; + if(Child) { + this._data[deco] = {}; + Child.prototype = this; + return new Child(opts, this); + } + return this; + }, + /** + * used to decorate an instance with a plugin. Used internally. + * @private + * @name init(el, optons) + * @param {DOMElement|jQuery|String} el the element we are transforming + * @param {Object} options options for this instance + * @trigger init.jstree, loading.jstree, loaded.jstree, ready.jstree, changed.jstree + */ + init : function (el, options) { + this._model = { + data : { + '#' : { + id : '#', + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + } + }, + changed : [], + force_full_redraw : false, + redraw_timeout : false, + default_state : { + loaded : true, + opened : false, + selected : false, + disabled : false + } + }; + + this.element = $(el).addClass('jstree jstree-' + this._id); + this.settings = options; + this.element.bind("destroyed", $.proxy(this.teardown, this)); + + this._data.core.ready = false; + this._data.core.loaded = false; + this._data.core.rtl = (this.element.css("direction") === "rtl"); + this.element[this._data.core.rtl ? 'addClass' : 'removeClass']("jstree-rtl"); + this.element.attr('role','tree'); + + this.bind(); + /** + * triggered after all events are bound + * @event + * @name init.jstree + */ + this.trigger("init"); + + this._data.core.original_container_html = this.element.find(" > ul > li").clone(true); + this._data.core.original_container_html + .find("li").addBack() + .contents().filter(function() { + return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue)); + }) + .remove(); + this.element.html("<"+"ul class='jstree-container-ul'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last'><"+"a class='jstree-anchor' href='#'>" + this.get_string("Loading ...") + ""); + this._data.core.li_height = this.get_container_ul().children("li:eq(0)").height() || 18; + /** + * triggered after the loading text is shown and before loading starts + * @event + * @name loading.jstree + */ + this.trigger("loading"); + this.load_node('#'); + }, + /** + * destroy an instance + * @name destroy() + */ + destroy : function () { + this.element.unbind("destroyed", this.teardown); + this.teardown(); + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name teardown() + */ + teardown : function () { + this.unbind(); + this.element + .removeClass('jstree') + .removeData('jstree') + .find("[class^='jstree']") + .addBack() + .attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); }); + this.element = null; + }, + /** + * bind all events. Used internally. + * @private + * @name bind() + */ + bind : function () { + this.element + .on("dblclick.jstree", function () { + if(document.selection && document.selection.empty) { + document.selection.empty(); + } + else { + if(window.getSelection) { + var sel = window.getSelection(); + try { + sel.removeAllRanges(); + sel.collapse(); + } catch (ignore) { } + } + } + }) + .on("click.jstree", ".jstree-ocl", $.proxy(function (e) { + this.toggle_node(e.target); + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + e.preventDefault(); + $(e.currentTarget).focus(); + this.activate_node(e.currentTarget, e); + }, this)) + .on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) { + var o = null; + switch(e.which) { + case 13: + case 32: + e.type = "click"; + $(e.currentTarget).trigger(e); + break; + case 37: + e.preventDefault(); + if(this.is_open(e.currentTarget)) { + this.close_node(e.currentTarget); + } + else { + o = this.get_prev_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + } + break; + case 38: + e.preventDefault(); + o = this.get_prev_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + case 39: + e.preventDefault(); + if(this.is_closed(e.currentTarget)) { + this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); }); + } + else { + o = this.get_next_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + } + break; + case 40: + e.preventDefault(); + o = this.get_next_dom(e.currentTarget); + if(o && o.length) { o.children('.jstree-anchor').focus(); } + break; + // delete + case 46: + e.preventDefault(); + o = this.get_node(e.currentTarget); + if(o && o.id && o.id !== '#') { + o = this.is_selected(o) ? this.get_selected() : o; + // this.delete_node(o); + } + break; + // f2 + case 113: + e.preventDefault(); + o = this.get_node(e.currentTarget); + /*! + if(o && o.id && o.id !== '#') { + // this.edit(o); + } + */ + break; + default: + // console.log(e.which); + break; + } + }, this)) + .on("load_node.jstree", $.proxy(function (e, data) { + if(data.status) { + if(data.node.id === '#' && !this._data.core.loaded) { + this._data.core.loaded = true; + /** + * triggered after the root node is loaded for the first time + * @event + * @name loaded.jstree + */ + this.trigger("loaded"); + } + if(!this._data.core.ready && !this.get_container_ul().find('.jstree-loading:eq(0)').length) { + this._data.core.ready = true; + if(this._data.core.selected.length) { + if(this.settings.core.expand_selected_onload) { + var tmp = [], i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + tmp = tmp.concat(this._model.data[this._data.core.selected[i]].parents); + } + tmp = $.vakata.array_unique(tmp); + for(i = 0, j = tmp.length; i < j; i++) { + this.open_node(tmp[i], false, 0); + } + } + this.trigger('changed', { 'action' : 'ready', 'selected' : this._data.core.selected }); + } + /** + * triggered after all nodes are finished loading + * @event + * @name ready.jstree + */ + setTimeout($.proxy(function () { this.trigger("ready"); }, this), 0); + } + } + }, this)) + // THEME RELATED + .on("init.jstree", $.proxy(function () { + var s = this.settings.core.themes; + this._data.core.themes.dots = s.dots; + this._data.core.themes.stripes = s.stripes; + this._data.core.themes.icons = s.icons; + this.set_theme(s.name || "default", s.url); + this.set_theme_variant(s.variant); + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ](); + this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ](); + this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ](); + }, this)) + .on('focus.jstree', '.jstree-anchor', $.proxy(function (e) { + this.element.find('.jstree-hovered').not(e.currentTarget).mouseleave(); + $(e.currentTarget).mouseenter(); + }, this)) + .on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) { + this.hover_node(e.currentTarget); + }, this)) + .on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }, + /** + * part of the destroying of an instance. Used internally. + * @private + * @name unbind() + */ + unbind : function () { + this.element.off('.jstree'); + $(document).off('.jstree-' + this._id); + }, + /** + * trigger an event. Used internally. + * @private + * @name trigger(ev [, data]) + * @param {String} ev the name of the event to trigger + * @param {Object} data additional data to pass with the event + */ + trigger : function (ev, data) { + if(!data) { + data = {}; + } + data.instance = this; + this.element.triggerHandler(ev.replace('.jstree','') + '.jstree', data); + }, + /** + * returns the jQuery extended instance container + * @name get_container() + * @return {jQuery} + */ + get_container : function () { + return this.element; + }, + /** + * returns the jQuery extended main UL node inside the instance container. Used internally. + * @private + * @name get_container_ul() + * @return {jQuery} + */ + get_container_ul : function () { + return this.element.children("ul:eq(0)"); + }, + /** + * gets string replacements (localization). Used internally. + * @private + * @name get_string(key) + * @param {String} key + * @return {String} + */ + get_string : function (key) { + var a = this.settings.core.strings; + if($.isFunction(a)) { return a.call(this, key); } + if(a && a[key]) { return a[key]; } + return key; + }, + /** + * gets the first child of a DOM node. Used internally. + * @private + * @name _firstChild(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _firstChild : function (dom) { + dom = dom ? dom.firstChild : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the next sibling of a DOM node. Used internally. + * @private + * @name _nextSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _nextSibling : function (dom) { + dom = dom ? dom.nextSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.nextSibling; + } + return dom; + }, + /** + * gets the previous sibling of a DOM node. Used internally. + * @private + * @name _previousSibling(dom) + * @param {DOMElement} dom + * @return {DOMElement} + */ + _previousSibling : function (dom) { + dom = dom ? dom.previousSibling : null; + while(dom !== null && dom.nodeType !== 1) { + dom = dom.previousSibling; + } + return dom; + }, + /** + * get the JSON representation of a node (or the actual jQuery extended DOM node) by using any input (child DOM element, ID string, selector, etc) + * @name get_node(obj [, as_dom]) + * @param {mixed} obj + * @param {Boolean} as_dom + * @return {Object|jQuery} + */ + get_node : function (obj, as_dom) { + if(obj && obj.id) { + obj = obj.id; + } + var dom; + try { + if(this._model.data[obj]) { + obj = this._model.data[obj]; + } + else if(((dom = $(obj, this.element)).length || (dom = $('#' + obj, this.element)).length) && this._model.data[dom.closest('li').attr('id')]) { + obj = this._model.data[dom.closest('li').attr('id')]; + } + else if((dom = $(obj, this.element)).length && dom.hasClass('jstree')) { + obj = this._model.data['#']; + } + else { + return false; + } + + if(as_dom) { + obj = obj.id === '#' ? this.element : $(document.getElementById(obj.id)); + } + return obj; + } catch (ex) { return false; } + }, + /** + * get the path to a node, either consisting of node texts, or of node IDs, optionally glued together (otherwise an array) + * @name get_path(obj [, glue, ids]) + * @param {mixed} obj the node + * @param {String} glue if you want the path as a string - pass the glue here (for example '/'), if a falsy value is supplied here, an array is returned + * @param {Boolean} ids if set to true build the path using ID, otherwise node text is used + * @return {mixed} + */ + get_path : function (obj, glue, ids) { + obj = obj.parents ? obj : this.get_node(obj); + if(!obj || obj.id === '#' || !obj.parents) { + return false; + } + var i, j, p = []; + p.push(ids ? obj.id : obj.text); + for(i = 0, j = obj.parents.length; i < j; i++) { + p.push(ids ? obj.parents[i] : this.get_text(obj.parents[i])); + } + p = p.reverse().slice(1); + return glue ? p.join(glue) : p; + }, + /** + * get the next visible node that is below the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_next_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_next_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this._firstChild(this.get_container_ul()[0]); + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = this._nextSibling(obj[0]); + return tmp ? $(tmp) : false; + } + if(obj.hasClass("jstree-open")) { + tmp = this._firstChild(obj.children('ul')[0]); + return tmp ? $(tmp) : false; + } + if((tmp = this._nextSibling(obj[0])) !== null) { + return $(tmp); + } + return obj.parentsUntil(".jstree","li").next("li").eq(0); + }, + /** + * get the previous visible node that is above the `obj` node. If `strict` is set to `true` only sibling nodes are returned. + * @name get_prev_dom(obj [, strict]) + * @param {mixed} obj + * @param {Boolean} strict + * @return {jQuery} + */ + get_prev_dom : function (obj, strict) { + var tmp; + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + tmp = this.get_container_ul()[0].lastChild; + return tmp ? $(tmp) : false; + } + if(!obj || !obj.length) { + return false; + } + if(strict) { + tmp = this._previousSibling(obj[0]); + return tmp ? $(tmp) : false; + } + if((tmp = this._previousSibling(obj[0])) !== null) { + obj = $(tmp); + while(obj.hasClass("jstree-open")) { + obj = obj.children("ul:eq(0)").children("li:last"); + } + return obj; + } + tmp = obj[0].parentNode.parentNode; + return tmp && tmp.tagName === 'LI' ? $(tmp) : false; + }, + /** + * get the parent ID of a node + * @name get_parent(obj) + * @param {mixed} obj + * @return {String} + */ + get_parent : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + return obj.parent; + }, + /** + * get a jQuery collection of all the children of a node (node must be rendered) + * @name get_children_dom(obj) + * @param {mixed} obj + * @return {jQuery} + */ + get_children_dom : function (obj) { + obj = this.get_node(obj, true); + if(obj[0] === this.element[0]) { + return this.get_container_ul().children("li"); + } + if(!obj || !obj.length) { + return false; + } + return obj.children("ul").children("li"); + }, + /** + * checks if a node has children + * @name is_parent(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_parent : function (obj) { + obj = this.get_node(obj); + return obj && (obj.state.loaded === false || obj.children.length > 0); + }, + /** + * checks if a node is loaded (its children are available) + * @name is_loaded(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loaded : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.loaded; + }, + /** + * check if a node is currently loading (fetching children) + * @name is_loading(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_loading : function (obj) { + obj = this.get_node(obj, true); + return obj && obj.hasClass("jstree-loading"); + }, + /** + * check if a node is opened + * @name is_open(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_open : function (obj) { + obj = this.get_node(obj); + return obj && obj.state.opened; + }, + /** + * check if a node is in a closed state + * @name is_closed(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_closed : function (obj) { + obj = this.get_node(obj); + return obj && this.is_parent(obj) && !obj.state.opened; + }, + /** + * check if a node has no children + * @name is_leaf(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_leaf : function (obj) { + return !this.is_parent(obj); + }, + /** + * loads a node (fetches its children using the `core.data` setting). Multiple nodes can be passed to by using an array. + * @name load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is conplete, the function is executed in the instance's scope and receives two arguments - the node and a boolean status + * @return {Boolean} + * @trigger load_node.jstree + */ + load_node : function (obj, callback) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.load_node(obj[t1], callback); + } + return true; + } + obj = this.get_node(obj); + if(!obj) { + callback.call(this, obj, false); + return false; + } + this.get_node(obj, true).addClass("jstree-loading"); + this._load_node(obj, $.proxy(function (status) { + obj.state.loaded = status; + this.get_node(obj, true).removeClass("jstree-loading"); + /** + * triggered after a node is loaded + * @event + * @name load_node.jstree + * @param {Object} node the node that was loading + * @param {Boolean} status was the node loaded successfully + */ + this.trigger('load_node', { "node" : obj, "status" : status }); + if(callback) { + callback.call(this, obj, status); + } + }, this)); + return true; + }, + /** + * handles the actual loading of a node. Used only internally. + * @private + * @name _load_node(obj [, callback]) + * @param {mixed} obj + * @param {function} callback a function to be executed once loading is conplete, the function is executed in the instance's scope and receives one argument - a boolean status + * @return {Boolean} + */ + _load_node : function (obj, callback) { + var s = this.settings.core.data, t; + // use original HTML + if(!s) { + return callback.call(this, obj.id === '#' ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false); + } + if($.isFunction(s)) { + return s.call(this, obj, $.proxy(function (d) { + return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d)); + }, this)); + } + if(typeof s === 'object') { + if(s.url) { + s = $.extend(true, {}, s); + if($.isFunction(s.url)) { + s.url = s.url.call(this, obj); + } + if($.isFunction(s.data)) { + s.data = s.data.call(this, obj); + } + return $.ajax(s) + .done($.proxy(function (d,t,x) { + var type = x.getResponseHeader('Content-Type'); + if(type.indexOf('json') !== -1) { + return callback.call(this, this._append_json_data(obj, d)); + } + if(type.indexOf('html') !== -1) { + return callback.call(this, this._append_html_data(obj, $(d))); + } + }, this)) + .fail($.proxy(function () { + callback.call(this, false); + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify(s) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)); + } + t = ($.isArray(s) || $.isPlainObject(s)) ? JSON.parse(JSON.stringify(s)) : s; + return callback.call(this, this._append_json_data(obj, t)); + } + if(typeof s === 'string') { + return callback.call(this, this._append_html_data(obj, s)); + } + return callback.call(this, false); + }, + /** + * adds a node to the list of nodes to redraw. Used only internally. + * @private + * @name _node_changed(obj [, callback]) + * @param {mixed} obj + */ + _node_changed : function (obj) { + obj = this.get_node(obj); + if(obj) { + this._model.changed.push(obj.id); + } + }, + /** + * appends HTML content to the tree. Used internally. + * @private + * @name _append_html_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the HTML string to parse and append + * @return {Boolean} + * @trigger model.jstree, changed.jstree + */ + _append_html_data : function (dom, data) { + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + var dat = data.is('ul') ? data.children() : data, + par = dom.id, + chd = [], + dpc = [], + m = this._model.data, + p = m[par], + s = this._data.core.selected.length, + tmp, i, j; + dat.each($.proxy(function (i, v) { + tmp = this._parse_model_from_html($(v), par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + }, this)); + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + /** + * triggered when new data is inserted to the tree model + * @event + * @name model.jstree + * @param {Array} nodes an array of node IDs + * @param {String} parent the parent ID of the nodes + */ + this.trigger('model', { "nodes" : dpc, 'parent' : par }); + if(par !== '#') { + this._node_changed(par); + this.redraw(); + } + else { + this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(this._data.core.selected.length !== s) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + return true; + }, + /** + * appends JSON content to the tree. Used internally. + * @private + * @name _append_json_data(obj, data) + * @param {mixed} obj the node to append to + * @param {String} data the JSON object to parse and append + * @return {Boolean} + */ + _append_json_data : function (dom, data) { + dom = this.get_node(dom); + dom.children = []; + dom.children_d = []; + var dat = data, + par = dom.id, + chd = [], + dpc = [], + m = this._model.data, + p = m[par], + s = this._data.core.selected.length, + tmp, i, j; + // *%$@!!! + if(dat.d) { + dat = dat.d; + if(typeof dat === "string") { + dat = JSON.parse(dat); + } + } + if(!$.isArray(dat)) { dat = [dat]; } + if(dat.length && dat[0].id !== undefined && dat[0].parent !== undefined) { + // Flat JSON support (for easy import from DB): + // 1) convert to object (foreach) + for(i = 0, j = dat.length; i < j; i++) { + if(!dat[i].children) { + dat[i].children = []; + } + m[dat[i].id] = dat[i]; + } + // 2) populate children (foreach) + for(i = 0, j = dat.length; i < j; i++) { + m[dat[i].parent].children.push(dat[i].id); + // populate parent.children_d + p.children_d.push(dat[i].id); + } + // 3) normalize && populate parents and children_d with recursion + for(i = 0, j = p.children.length; i < j; i++) { + tmp = this._parse_model_from_flat_json(m[p.children[i]], par, p.parents.concat()); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + // ?) three_state selection - p.state.selected && t - (if three_state foreach(dat => ch) -> foreach(parents) if(parent.selected) child.selected = true; + } + else { + for(i = 0, j = dat.length; i < j; i++) { + tmp = this._parse_model_from_json(dat[i], par, p.parents.concat()); + if(tmp) { + chd.push(tmp); + dpc.push(tmp); + if(m[tmp].children_d.length) { + dpc = dpc.concat(m[tmp].children_d); + } + } + } + p.children = chd; + p.children_d = dpc; + for(i = 0, j = p.parents.length; i < j; i++) { + m[p.parents[i]].children_d = m[p.parents[i]].children_d.concat(dpc); + } + } + this.trigger('model', { "nodes" : dpc, 'parent' : par }); + + if(par !== '#') { + this._node_changed(par); + this.redraw(); + } + else { + // this.get_container_ul().children('.jstree-initial-node').remove(); + this.redraw(true); + } + if(this._data.core.selected.length !== s) { + this.trigger('changed', { 'action' : 'model', 'selected' : this._data.core.selected }); + } + return true; + }, + /** + * parses a node from a jQuery object and appends them to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_html(d [, p, ps]) + * @param {jQuery} d the jQuery object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_html : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = [].concat(ps); } + if(p) { ps.unshift(p); } + var c, e, m = this._model.data, + data = { + id : false, + text : false, + icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }, i, tmp, tid; + for(i in this._model.default_state) { + if(this._model.default_state.hasOwnProperty(i)) { + data.state[i] = this._model.default_state[i]; + } + } + tmp = $.vakata.attributes(d, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(!v.length) { return true; } + data.li_attr[i] = v; + if(i === 'id') { + data.id = v; + } + }); + tmp = d.children('a').eq(0); + if(tmp.length) { + tmp = $.vakata.attributes(tmp, true); + $.each(tmp, function (i, v) { + v = $.trim(v); + if(v.length) { + data.a_attr[i] = v; + } + }); + } + tmp = d.children("a:eq(0)").length ? d.children("a:eq(0)").clone() : d.clone(); + tmp.children("ins, i, ul").remove(); + tmp = tmp.html(); + tmp = $('').html(tmp); + data.text = tmp.html(); + tmp = d.data(); + data.data = tmp ? $.extend(true, {}, tmp) : null; + data.state.opened = d.hasClass('jstree-open'); + data.state.selected = d.children('a').hasClass('jstree-clicked'); + data.state.disabled = d.children('a').hasClass('jstree-disabled'); + if(data.data && data.data.jstree) { + for(i in data.data.jstree) { + if(data.data.jstree.hasOwnProperty(i)) { + data.state[i] = data.data.jstree[i]; + } + } + } + tmp = d.children("a").children(".jstree-themeicon"); + if(tmp.length) { + data.icon = tmp.hasClass('jstree-themeicon-hidden') ? false : tmp.attr('rel'); + } + if(data.state.icon) { + data.icon = data.state.icon; + } + tmp = d.children("ul").children("li"); + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + data.id = data.li_attr.id || tid; + if(tmp.length) { + tmp.each($.proxy(function (i, v) { + c = this._parse_model_from_html($(v), data.id, ps); + e = this._model.data[c]; + data.children.push(c); + if(e.children_d.length) { + data.children_d = data.children_d.concat(e.children_d); + } + }, this)); + data.children_d = data.children_d.concat(data.children); + } + else { + if(d.hasClass('jstree-closed')) { + data.state.loaded = false; + } + } + if(data.li_attr['class']) { + data.li_attr['class'] = data.li_attr['class'].replace('jstree-closed','').replace('jstree-open',''); + } + if(data.a_attr['class']) { + data.a_attr['class'] = data.a_attr['class'].replace('jstree-clicked','').replace('jstree-disabled',''); + } + m[data.id] = data; + if(data.state.selected) { + this._data.core.selected.push(data.id); + } + return data.id; + }, + /** + * parses a node from a JSON object (used when dealing with flat data, which has no nesting of children, but has id and parent properties) and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_flat_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_flat_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = d.id, + m = this._model.data, + df = this._model.default_state, + i, j, c, e, + tmp = { + id : tid, + text : d.text || '', + icon : d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : d.children || [], + children_d : d.children_d || [], + data : d.data, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tid; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + m[tmp.id] = tmp; + for(i = 0, j = tmp.children.length; i < j; i++) { + c = this._parse_model_from_flat_json(m[tmp.children[i]], tmp.id, ps); + e = m[c]; + tmp.children_d.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + delete d.data; + delete d.children; + m[tmp.id].original = d; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * parses a node from a JSON object and appends it to the in memory tree model. Used internally. + * @private + * @name _parse_model_from_json(d [, p, ps]) + * @param {Object} d the JSON object to parse + * @param {String} p the parent ID + * @param {Array} ps list of all parents + * @return {String} the ID of the object added to the model + */ + _parse_model_from_json : function (d, p, ps) { + if(!ps) { ps = []; } + else { ps = ps.concat(); } + if(p) { ps.unshift(p); } + var tid = false, i, j, c, e, m = this._model.data, df = this._model.default_state, tmp; + do { + tid = 'j' + this._id + '_' + (++this._cnt); + } while(m[tid]); + + tmp = { + id : false, + text : typeof d === 'string' ? d : '', + icon : typeof d === 'object' && d.icon !== undefined ? d.icon : true, + parent : p, + parents : ps, + children : [], + children_d : [], + data : null, + state : { }, + li_attr : { id : false }, + a_attr : { href : '#' }, + original : false + }; + for(i in df) { + if(df.hasOwnProperty(i)) { + tmp.state[i] = df[i]; + } + } + if(d && d.id) { tmp.id = d.id; } + if(d && d.text) { tmp.text = d.text; } + if(d && d.data && d.data.jstree && d.data.jstree.icon) { + tmp.icon = d.data.jstree.icon; + } + if(d && d.data) { + tmp.data = d.data; + if(d.data.jstree) { + for(i in d.data.jstree) { + if(d.data.jstree.hasOwnProperty(i)) { + tmp.state[i] = d.data.jstree[i]; + } + } + } + } + if(d && typeof d.state === 'object') { + for (i in d.state) { + if(d.state.hasOwnProperty(i)) { + tmp.state[i] = d.state[i]; + } + } + } + if(d && typeof d.li_attr === 'object') { + for (i in d.li_attr) { + if(d.li_attr.hasOwnProperty(i)) { + tmp.li_attr[i] = d.li_attr[i]; + } + } + } + if(tmp.li_attr.id && !tmp.id) { + tmp.id = tmp.li_attr.id; + } + if(!tmp.id) { + tmp.id = tid; + } + if(!tmp.li_attr.id) { + tmp.li_attr.id = tmp.id; + } + if(d && typeof d.a_attr === 'object') { + for (i in d.a_attr) { + if(d.a_attr.hasOwnProperty(i)) { + tmp.a_attr[i] = d.a_attr[i]; + } + } + } + if(d && d.children && d.children.length) { + for(i = 0, j = d.children.length; i < j; i++) { + c = this._parse_model_from_json(d.children[i], tmp.id, ps); + e = m[c]; + tmp.children.push(c); + if(e.children_d.length) { + tmp.children_d = tmp.children_d.concat(e.children_d); + } + } + tmp.children_d = tmp.children_d.concat(tmp.children); + } + if(d && d.children && d.children === true) { + tmp.state.loaded = false; + tmp.children = []; + tmp.children_d = []; + } + delete d.data; + delete d.children; + tmp.original = d; + m[tmp.id] = tmp; + if(tmp.state.selected) { + this._data.core.selected.push(tmp.id); + } + return tmp.id; + }, + /** + * redraws all nodes that need to be redrawn. Used internally. + * @private + * @name _redraw() + * @trigger redraw.jstree + */ + _redraw : function () { + var nodes = this._model.force_full_redraw ? this._model.data['#'].children.concat([]) : this._model.changed.concat([]), + f = document.createElement('UL'), tmp, i, j; + for(i = 0, j = nodes.length; i < j; i++) { + tmp = this.redraw_node(nodes[i], true, this._model.force_full_redraw); + if(tmp && this._model.force_full_redraw) { + f.appendChild(tmp); + } + } + if(this._model.force_full_redraw) { + f.className = this.get_container_ul()[0].className; + this.element.empty().append(f); + //this.get_container_ul()[0].appendChild(f); + } + this._model.force_full_redraw = false; + this._model.changed = []; + /** + * triggered after nodes are redrawn + * @event + * @name redraw.jstree + * @param {array} nodes the redrawn nodes + */ + this.trigger('redraw', { "nodes" : nodes }); + }, + /** + * redraws all nodes that need to be redrawn or optionally - the whole tree + * @name redraw([full]) + * @param {Boolean} full if set to `true` all nodes are redrawn. + */ + redraw : function (full) { + if(full) { + this._model.force_full_redraw = true; + } + //if(this._model.redraw_timeout) { + // clearTimeout(this._model.redraw_timeout); + //} + //this._model.redraw_timeout = setTimeout($.proxy(this._redraw, this),0); + this._redraw(); + }, + /** + * redraws a single node. Used internally. + * @private + * @name redraw_node(node, deep, is_callback) + * @param {mixed} node the node to redraw + * @param {Boolean} deep should child nodes be redrawn too + * @param {Boolean} is_callback is this a recursion call + */ + redraw_node : function (node, deep, is_callback) { + var obj = this.get_node(node), + par = false, + ind = false, + old = false, + i = false, + j = false, + k = false, + c = '', + d = document, + m = this._model.data, + f = false, + s = false; + if(!obj) { return false; } + if(obj.id === '#') { return this.redraw(true); } + deep = deep || obj.children.length === 0; + node = d.getElementById(obj.id); //, this.element); + if(!node) { + deep = true; + //node = d.createElement('LI'); + if(!is_callback) { + par = obj.parent !== '#' ? $('#' + obj.parent, this.element)[0] : null; + if(par !== null && (!par || !m[obj.parent].state.opened)) { + return false; + } + ind = $.inArray(obj.id, par === null ? m['#'].children : m[obj.parent].children); + } + } + else { + node = $(node); + if(!is_callback) { + par = node.parent().parent()[0]; + if(par === this.element[0]) { + par = null; + } + ind = node.index(); + } + // m[obj.id].data = node.data(); // use only node's data, no need to touch jquery storage + if(!deep && obj.children.length && !node.children('ul').length) { + deep = true; + } + if(!deep) { + old = node.children('UL')[0]; + } + s = node.attr('aria-selected'); + f = node.children('.jstree-anchor')[0] === document.activeElement; + node.remove(); + //node = d.createElement('LI'); + //node = node[0]; + } + node = _node.cloneNode(true); + // node is DOM, deep is boolean + + c = 'jstree-node '; + for(i in obj.li_attr) { + if(obj.li_attr.hasOwnProperty(i)) { + if(i === 'id') { continue; } + if(i !== 'class') { + node.setAttribute(i, obj.li_attr[i]); + } + else { + c += obj.li_attr[i]; + } + } + } + if(s && s !== "false") { + node.setAttribute('aria-selected', true); + } + if(!obj.children.length && obj.state.loaded) { + c += ' jstree-leaf'; + } + else { + c += obj.state.opened ? ' jstree-open' : ' jstree-closed'; + node.setAttribute('aria-expanded', obj.state.opened); + } + if(obj.parent !== null && m[obj.parent].children[m[obj.parent].children.length - 1] === obj.id) { + c += ' jstree-last'; + } + node.id = obj.id; + node.className = c; + c = ( obj.state.selected ? ' jstree-clicked' : '') + ( obj.state.disabled ? ' jstree-disabled' : ''); + for(j in obj.a_attr) { + if(obj.a_attr.hasOwnProperty(j)) { + if(j === 'href' && obj.a_attr[j] === '#') { continue; } + if(j !== 'class') { + node.childNodes[1].setAttribute(j, obj.a_attr[j]); + } + else { + c += ' ' + obj.a_attr[j]; + } + } + } + if(c.length) { + node.childNodes[1].className = 'jstree-anchor ' + c; + } + if((obj.icon && obj.icon !== true) || obj.icon === false) { + if(obj.icon === false) { + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-hidden'; + } + else if(obj.icon.indexOf('/') === -1 && obj.icon.indexOf('.') === -1) { + node.childNodes[1].childNodes[0].className += ' ' + obj.icon + ' jstree-themeicon-custom'; + } + else { + node.childNodes[1].childNodes[0].style.backgroundImage = 'url('+obj.icon+')'; + node.childNodes[1].childNodes[0].style.backgroundPosition = 'center center'; + node.childNodes[1].childNodes[0].style.backgroundSize = 'auto'; + node.childNodes[1].childNodes[0].className += ' jstree-themeicon-custom'; + } + } + //node.childNodes[1].appendChild(d.createTextNode(obj.text)); + node.childNodes[1].innerHTML += obj.text; + // if(obj.data) { $.data(node, obj.data); } // always work with node's data, no need to touch jquery store + + if(deep && obj.children.length && obj.state.opened) { + k = d.createElement('UL'); + k.setAttribute('role', 'group'); + k.className = 'jstree-children'; + for(i = 0, j = obj.children.length; i < j; i++) { + k.appendChild(this.redraw_node(obj.children[i], deep, true)); + } + node.appendChild(k); + } + if(old) { + node.appendChild(old); + } + if(!is_callback) { + // append back using par / ind + if(!par) { + par = this.element[0]; + } + if(!par.getElementsByTagName('UL').length) { + i = d.createElement('UL'); + i.setAttribute('role', 'group'); + i.className = 'jstree-children'; + par.appendChild(i); + par = i; + } + else { + par = par.getElementsByTagName('UL')[0]; + } + + if(ind < par.childNodes.length) { + par.insertBefore(node, par.childNodes[ind]); + } + else { + par.appendChild(node); + } + if(f) { + node.childNodes[1].focus(); + } + } + return node; + }, + /** + * opens a node, revaling its children. If the node is not loaded it will be loaded and opened once ready. + * @name open_node(obj [, callback, animation]) + * @param {mixed} obj the node to open + * @param {Function} callback a function to execute once the node is opened + * @param {Number} animation the animation duration in milliseconds when opening the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger open_node.jstree, after_open.jstree + */ + open_node : function (obj, callback, animation) { + var t1, t2, d, t; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.open_node(obj[t1], callback, animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + if(!this.is_closed(obj)) { + if(callback) { + callback.call(this, obj, false); + } + return false; + } + if(!this.is_loaded(obj)) { + if(this.is_loading(obj)) { + return setTimeout($.proxy(function () { + this.open_node(obj, callback, animation); + }, this), 500); + } + this.load_node(obj, function (o, ok) { + return ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false); + }); + } + else { + d = this.get_node(obj, true); + t = this; + if(d.length) { + if(obj.children.length && !this._firstChild(d.children('ul')[0])) { + obj.state.opened = true; + this.redraw_node(obj, true); + d = this.get_node(obj, true); + } + if(!animation) { + d[0].className = d[0].className.replace('jstree-closed', 'jstree-open'); + d[0].setAttribute("aria-expanded", true); + } + else { + d + .children("ul").css("display","none").end() + .removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded", true) + .children("ul").stop(true, true) + .slideDown(animation, function () { + this.style.display = ""; + t.trigger("after_open", { "node" : obj }); + }); + } + } + obj.state.opened = true; + if(callback) { + callback.call(this, obj, true); + } + /** + * triggered when a node is opened (if there is an animation it will not be completed yet) + * @event + * @name open_node.jstree + * @param {Object} node the opened node + */ + this.trigger('open_node', { "node" : obj }); + if(!animation || !d.length) { + /** + * triggered when a node is opened and the animation is complete + * @event + * @name after_open.jstree + * @param {Object} node the opened node + */ + this.trigger("after_open", { "node" : obj }); + } + } + }, + /** + * opens every parent of a node (node should be loaded) + * @name _open_to(obj) + * @param {mixed} obj the node to reveal + * @private + */ + _open_to : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + var i, j, p = obj.parents; + for(i = 0, j = p.length; i < j; i+=1) { + if(i !== '#') { + this.open_node(p[i], false, 0); + } + } + return $(document.getElementById(obj.id)); + }, + /** + * closes a node, hiding its children + * @name close_node(obj [, animation]) + * @param {mixed} obj the node to close + * @param {Number} animation the animation duration in milliseconds when closing the node (overrides the `core.animation` setting). Use `false` for no animation. + * @trigger close_node.jstree, after_close.jstree + */ + close_node : function (obj, animation) { + var t1, t2, t, d; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.close_node(obj[t1], animation); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + animation = animation === undefined ? this.settings.core.animation : animation; + t = this; + d = this.get_node(obj, true); + if(d.length) { + if(!animation) { + d[0].className = d[0].className.replace('jstree-open', 'jstree-closed'); + d.attr("aria-expanded", false).children('ul').remove(); + } + else { + d + .children("ul").attr("style","display:block !important").end() + .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false) + .children("ul").stop(true, true).slideUp(animation, function () { + this.style.display = ""; + d.children('ul').remove(); + t.trigger("after_close", { "node" : obj }); + }); + } + } + obj.state.opened = false; + /** + * triggered when a node is closed (if there is an animation it will not be complete yet) + * @event + * @name close_node.jstree + * @param {Object} node the closed node + */ + this.trigger('close_node',{ "node" : obj }); + if(!animation || !d.length) { + /** + * triggered when a node is closed and the animation is complete + * @event + * @name after_close.jstree + * @param {Object} node the closed node + */ + this.trigger("after_close", { "node" : obj }); + } + }, + /** + * toggles a node - closing it if it is open, opening it if it is closed + * @name toggle_node(obj) + * @param {mixed} obj the node to toggle + */ + toggle_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.toggle_node(obj[t1]); + } + return true; + } + if(this.is_closed(obj)) { + return this.open_node(obj); + } + if(this.is_open(obj)) { + return this.close_node(obj); + } + }, + /** + * opens all nodes within a node (or the tree), revaling their children. If the node is not loaded it will be loaded and opened once ready. + * @name open_all([obj, animation, original_obj]) + * @param {mixed} obj the node to open recursively, omit to open all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when opening the nodes, the default is no animation + * @param {jQuery} reference to the node that started the process (internal use) + * @trigger open_all.jstree + */ + open_all : function (obj, animation, original_obj) { + if(!obj) { obj = '#'; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === '#' ? this.get_container_ul() : this.get_node(obj, true), i, j, _this; + if(!dom.length) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + if(this.is_closed(this._model.data[obj.children_d[i]])) { + this._model.data[obj.children_d[i]].state.opened = true; + } + } + return this.trigger('open_all', { "node" : obj }); + } + original_obj = original_obj || dom; + _this = this; + dom = this.is_closed(obj) ? dom.find('li.jstree-closed').addBack() : dom.find('li.jstree-closed'); + dom.each(function () { + _this.open_node( + this, + function(node, status) { if(status && this.is_parent(node)) { this.open_all(node, animation, original_obj); } }, + animation || 0 + ); + }); + if(original_obj.find('li.jstree-closed').length === 0) { + /** + * triggered when an `open_all` call completes + * @event + * @name open_all.jstree + * @param {Object} node the opened node + */ + this.trigger('open_all', { "node" : this.get_node(original_obj) }); + } + }, + /** + * closes all nodes within a node (or the tree), revaling their children + * @name close_all([obj, animation]) + * @param {mixed} obj the node to close recursively, omit to close all nodes in the tree + * @param {Number} animation the animation duration in milliseconds when closing the nodes, the default is no animation + * @trigger close_all.jstree + */ + close_all : function (obj, animation) { + if(!obj) { obj = '#'; } + obj = this.get_node(obj); + if(!obj) { return false; } + var dom = obj.id === '#' ? this.get_container_ul() : this.get_node(obj, true), + _this = this, i, j; + if(!dom.length) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].state.opened = false; + } + return this.trigger('close_all', { "node" : obj }); + } + dom = this.is_open(obj) ? dom.find('li.jstree-open').addBack() : dom.find('li.jstree-open'); + dom.vakata_reverse().each(function () { _this.close_node(this, animation || 0); }); + /** + * triggered when an `close_all` call completes + * @event + * @name close_all.jstree + * @param {Object} node the closed node + */ + this.trigger('close_all', { "node" : obj }); + }, + /** + * checks if a node is disabled (not selectable) + * @name is_disabled(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_disabled : function (obj) { + obj = this.get_node(obj); + return obj && obj.state && obj.state.disabled; + }, + /** + * enables a node - so that it can be selected + * @name enable_node(obj) + * @param {mixed} obj the node to enable + * @trigger enable_node.jstree + */ + enable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.enable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + obj.state.disabled = false; + this.get_node(obj,true).children('.jstree-anchor').removeClass('jstree-disabled'); + /** + * triggered when an node is enabled + * @event + * @name enable_node.jstree + * @param {Object} node the enabled node + */ + this.trigger('enable_node', { 'node' : obj }); + }, + /** + * disables a node - so that it can not be selected + * @name disable_node(obj) + * @param {mixed} obj the node to disable + * @trigger disable_node.jstree + */ + disable_node : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.disable_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + obj.state.disabled = true; + this.get_node(obj,true).children('.jstree-anchor').addClass('jstree-disabled'); + /** + * triggered when an node is disabled + * @event + * @name disable_node.jstree + * @param {Object} node the disabled node + */ + this.trigger('disable_node', { 'node' : obj }); + }, + /** + * called when a node is selected by the user. Used internally. + * @private + * @name activate_node(obj, e) + * @param {mixed} obj the node + * @param {Object} e the related event + * @trigger activate_node.jstree + */ + activate_node : function (obj, e) { + if(this.is_disabled(obj)) { + return false; + } + if(!this.settings.core.multiple || (!e.metaKey && !e.ctrlKey && !e.shiftKey) || (e.shiftKey && (!this._data.core.last_clicked || !this.get_parent(obj) || this.get_parent(obj) !== this._data.core.last_clicked.parent ) )) { + if(!this.settings.core.multiple && (e.metaKey || e.ctrlKey || e.shiftKey) && this.is_selected(obj)) { + this.deselect_node(obj, false, false, e); + } + else { + this.deselect_all(true); + this.select_node(obj, false, false, e); + this._data.core.last_clicked = this.get_node(obj); + } + } + else { + if(e.shiftKey) { + var o = this.get_node(obj).id, + l = this._data.core.last_clicked.id, + p = this.get_node(this._data.core.last_clicked.parent).children, + c = false, + i, j; + for(i = 0, j = p.length; i < j; i += 1) { + // separate IFs work whem o and l are the same + if(p[i] === o) { + c = !c; + } + if(p[i] === l) { + c = !c; + } + if(c || p[i] === o || p[i] === l) { + this.select_node(p[i], false, false, e); + } + else { + this.deselect_node(p[i], false, false, e); + } + } + } + else { + if(!this.is_selected(obj)) { + this.select_node(obj, false, false, e); + } + else { + this.deselect_node(obj, false, false, e); + } + } + } + /** + * triggered when an node is clicked or intercated with by the user + * @event + * @name activate_node.jstree + * @param {Object} node + */ + this.trigger('activate_node', { 'node' : this.get_node(obj) }); + }, + /** + * applies the hover state on a node, called when a node is hovered by the user. Used internally. + * @private + * @name hover_node(obj) + * @param {mixed} obj + * @trigger hover_node.jstree + */ + hover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || obj.children('.jstree-hovered').length) { + return false; + } + var o = this.element.find('.jstree-hovered'), t = this.element; + if(o && o.length) { this.dehover_node(o); } + + obj.children('.jstree-anchor').addClass('jstree-hovered'); + /** + * triggered when an node is hovered + * @event + * @name hover_node.jstree + * @param {Object} node + */ + this.trigger('hover_node', { 'node' : this.get_node(obj) }); + setTimeout(function () { t.attr('aria-activedescendant', obj[0].id); obj.attr('aria-selected', true); }, 0); + }, + /** + * removes the hover state from a nodecalled when a node is no longer hovered by the user. Used internally. + * @private + * @name dehover_node(obj) + * @param {mixed} obj + * @trigger dehover_node.jstree + */ + dehover_node : function (obj) { + obj = this.get_node(obj, true); + if(!obj || !obj.length || !obj.children('.jstree-hovered').length) { + return false; + } + obj.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-hovered'); + /** + * triggered when an node is no longer hovered + * @event + * @name dehover_node.jstree + * @param {Object} node + */ + this.trigger('dehover_node', { 'node' : this.get_node(obj) }); + }, + /** + * select a node + * @name select_node(obj [, supress_event, prevent_open]) + * @param {mixed} obj an array can be used to select multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @param {Boolean} prevent_open if set to `true` parents of the selected node won't be opened + * @trigger select_node.jstree, changed.jstree + */ + select_node : function (obj, supress_event, prevent_open, e) { + var dom, t1, t2, th; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.select_node(obj[t1], supress_event, prevent_open, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + dom = this.get_node(obj, true); + if(!obj.state.selected) { + obj.state.selected = true; + this._data.core.selected.push(obj.id); + if(!prevent_open) { + dom = this._open_to(obj); + } + if(dom && dom.length) { + dom.children('.jstree-anchor').addClass('jstree-clicked'); + } + /** + * triggered when an node is selected + * @event + * @name select_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this select_node + */ + this.trigger('select_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + /** + * triggered when selection changes + * @event + * @name changed.jstree + * @param {Object} node + * @param {Object} action the action that caused the selection to change + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this changed event + */ + this.trigger('changed', { 'action' : 'select_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * deselect a node + * @name deselect_node(obj [, supress_event]) + * @param {mixed} obj an array can be used to deselect multiple nodes + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_node.jstree, changed.jstree + */ + deselect_node : function (obj, supress_event, e) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.deselect_node(obj[t1], supress_event, e); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + dom = this.get_node(obj, true); + if(obj.state.selected) { + obj.state.selected = false; + this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id); + if(dom.length) { + dom.children('.jstree-anchor').removeClass('jstree-clicked'); + } + /** + * triggered when an node is deselected + * @event + * @name deselect_node.jstree + * @param {Object} node + * @param {Array} selected the current selection + * @param {Object} event the event (if any) that triggered this deselect_node + */ + this.trigger('deselect_node', { 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_node', 'node' : obj, 'selected' : this._data.core.selected, 'event' : e }); + } + } + }, + /** + * select all nodes in the tree + * @name select_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger select_all.jstree, changed.jstree + */ + select_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + this._data.core.selected = this._model.data['#'].children_d.concat(); + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = true; + } + } + this.redraw(true); + /** + * triggered when all nodes are selected + * @event + * @name select_all.jstree + * @param {Array} selected the current selection + */ + this.trigger('select_all', { 'selected' : this._data.core.selected }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'select_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * deselect all selected nodes + * @name deselect_all([supress_event]) + * @param {Boolean} supress_event if set to `true` the `changed.jstree` event won't be triggered + * @trigger deselect_all.jstree, changed.jstree + */ + deselect_all : function (supress_event) { + var tmp = this._data.core.selected.concat([]), i, j; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if(this._model.data[this._data.core.selected[i]]) { + this._model.data[this._data.core.selected[i]].state.selected = false; + } + } + this._data.core.selected = []; + this.element.find('.jstree-clicked').removeClass('jstree-clicked'); + /** + * triggered when all nodes are deselected + * @event + * @name deselect_all.jstree + * @param {Object} node the previous selection + * @param {Array} selected the current selection + */ + this.trigger('deselect_all', { 'selected' : this._data.core.selected, 'node' : tmp }); + if(!supress_event) { + this.trigger('changed', { 'action' : 'deselect_all', 'selected' : this._data.core.selected, 'old_selection' : tmp }); + } + }, + /** + * checks if a node is selected + * @name is_selected(obj) + * @param {mixed} obj + * @return {Boolean} + */ + is_selected : function (obj) { + obj = this.get_node(obj); + if(!obj || obj.id === '#') { + return false; + } + return obj.state.selected; + }, + /** + * get an array of all selected node IDs + * @name get_selected([full]) + * @param {mixed} full if set to `true` the returned array will consist of the full node objects, otherwise - only IDs will be returned + * @return {Array} + */ + get_selected : function (full) { + return full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected; + }, + /** + * gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally. + * @name get_state() + * @private + * @return {Object} + */ + get_state : function () { + var state = { + 'core' : { + 'open' : [], + 'scroll' : { + 'left' : this.element.scrollLeft(), + 'top' : this.element.scrollTop() + }, + /*! + 'themes' : { + 'name' : this.get_theme(), + 'icons' : this._data.core.themes.icons, + 'dots' : this._data.core.themes.dots + }, + */ + 'selected' : [] + } + }, i; + for(i in this._model.data) { + if(this._model.data.hasOwnProperty(i)) { + if(i !== '#') { + if(this._model.data[i].state.opened) { + state.core.open.push(i); + } + if(this._model.data[i].state.selected) { + state.core.selected.push(i); + } + } + } + } + return state; + }, + /** + * sets the state of the tree. Used internally. + * @name set_state(state [, callback]) + * @private + * @param {Object} state the state to restore + * @param {Function} callback an optional function to execute once the state is restored. + * @trigger set_state.jstree + */ + set_state : function (state, callback) { + if(state) { + if(state.core) { + var res, n, t, _this; + if(state.core.open) { + if(!$.isArray(state.core.open)) { + delete state.core.open; + this.set_state(state, callback); + return false; + } + res = true; + n = false; + t = this; + $.each(state.core.open.concat([]), function (i, v) { + n = t.get_node(v); + if(n) { + if(t.is_loaded(v)) { + if(t.is_closed(v)) { + t.open_node(v, false, 0); + } + if(state && state.core && state.core.open) { + $.vakata.array_remove_item(state.core.open, v); + } + } + else { + if(!t.is_loading(v)) { + t.open_node(v, $.proxy(function () { this.set_state(state, callback); }, t), 0); + } + // there will be some async activity - so wait for it + res = false; + } + } + }); + if(res) { + delete state.core.open; + this.set_state(state, callback); + } + return false; + } + if(state.core.scroll) { + if(state.core.scroll && state.core.scroll.left !== undefined) { + this.element.scrollLeft(state.core.scroll.left); + } + if(state.core.scroll && state.core.scroll.top !== undefined) { + this.element.scrollTop(state.core.scroll.top); + } + delete state.core.scroll; + this.set_state(state, callback); + return false; + } + /*! + if(state.core.themes) { + if(state.core.themes.name) { + this.set_theme(state.core.themes.name); + } + if(typeof state.core.themes.dots !== 'undefined') { + this[ state.core.themes.dots ? "show_dots" : "hide_dots" ](); + } + if(typeof state.core.themes.icons !== 'undefined') { + this[ state.core.themes.icons ? "show_icons" : "hide_icons" ](); + } + delete state.core.themes; + delete state.core.open; + this.set_state(state, callback); + return false; + } + */ + if(state.core.selected) { + _this = this; + this.deselect_all(); + $.each(state.core.selected, function (i, v) { + _this.select_node(v); + }); + delete state.core.selected; + this.set_state(state, callback); + return false; + } + if($.isEmptyObject(state.core)) { + delete state.core; + this.set_state(state, callback); + return false; + } + } + if($.isEmptyObject(state)) { + state = null; + if(callback) { callback.call(this); } + /** + * triggered when a `set_state` call completes + * @event + * @name set_state.jstree + */ + this.trigger('set_state'); + return false; + } + return true; + } + return false; + }, + /** + * refreshes the tree - all nodes are reloaded with calls to `load_node`. + * @name refresh() + * @param {Boolean} skip_loading an option to skip showing the loading indicator + * @trigger refresh.jstree + */ + refresh : function (skip_loading) { + this._data.core.state = this.get_state(); + this._cnt = 0; + this._model.data = { + '#' : { + id : '#', + parent : null, + parents : [], + children : [], + children_d : [], + state : { loaded : false } + } + }; + var c = this.get_container_ul()[0].className; + if(!skip_loading) { + this.element.html("<"+"ul class='jstree-container-ul'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last'><"+"a class='jstree-anchor' href='#'>" + this.get_string("Loading ...") + ""); + } + this.load_node('#', function (o, s) { + if(s) { + this.get_container_ul()[0].className = c; + this.set_state($.extend(true, {}, this._data.core.state), function () { + /** + * triggered when a `refresh` call completes + * @event + * @name refresh.jstree + */ + this.trigger('refresh'); + }); + } + this._data.core.state = null; + }); + }, + /** + * set (change) the ID of a node + * @name set_id(obj, id) + * @param {mixed} obj the node + * @param {String} id the new ID + * @return {Boolean} + */ + set_id : function (obj, id) { + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + var i, j, m = this._model.data; + // update parents (replace current ID with new one in children and children_d) + m[obj.parent].children[$.inArray(obj.id, m[obj.parent].children)] = id; + for(i = 0, j = obj.parents.length; i < j; i++) { + m[obj.parents[i]].children_d[$.inArray(obj.id, m[obj.parents[i]].children_d)] = id; + } + // update children (replace current ID with new one in parent and parents) + for(i = 0, j = obj.children.length; i < j; i++) { + m[obj.children[i]].parent = id; + } + for(i = 0, j = obj.children_d.length; i < j; i++) { + m[obj.children_d[i]].parents[$.inArray(obj.id, m[obj.children_d[i]].parents)] = id; + } + i = $.inArray(obj.id, this._data.core.selected); + if(i !== -1) { this._data.core.selected[i] = id; } + // update model and obj itself (obj.id, this._model.data[KEY]) + i = this.get_node(obj.id, true); + if(i) { + i.attr('id', id); + } + delete m[obj.id]; + obj.id = id; + m[id] = obj; + return true; + }, + /** + * get the text value of a node + * @name get_text(obj) + * @param {mixed} obj the node + * @return {String} + */ + get_text : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === '#') ? false : obj.text; + }, + /** + * set the text value of a node. Used internally, please use `rename_node(obj, val)`. + * @private + * @name set_text(obj, val) + * @param {mixed} obj the node, you can pass an array to set the text on multiple nodes + * @param {String} val the new text value + * @return {Boolean} + * @trigger set_text.jstree + */ + set_text : function (obj, val) { + var t1, t2, dom, tmp; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_text(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + obj.text = val; + dom = this.get_node(obj, true); + if(dom.length) { + dom = dom.children(".jstree-anchor:eq(0)"); + tmp = dom.children("I").clone(); + dom.html(val).prepend(tmp); + /** + * triggered when a node text value is changed + * @event + * @name set_text.jstree + * @param {Object} obj + * @param {String} text the new value + */ + this.trigger('set_text',{ "obj" : obj, "text" : val }); + } + return true; + }, + /** + * gets a JSON representation of a node (or the whole tree) + * @name get_json([obj, options]) + * @param {mixed} obj + * @param {Object} options + * @param {Boolean} options.no_state do not return state information + * @param {Boolean} options.no_id do not return ID + * @param {Boolean} options.no_children do not include children + * @param {Boolean} options.no_data do not include node data + * @param {Boolean} options.flat return flat JSON instead of nested + * @return {Object} + */ + get_json : function (obj, options, flat) { + obj = this.get_node(obj || '#'); + if(!obj) { return false; } + if(options && options.flat && !flat) { flat = []; } + var tmp = { + 'id' : obj.id, + 'text' : obj.text, + 'icon' : this.get_icon(obj), + 'li_attr' : obj.li_attr, + 'a_attr' : obj.a_attr, + 'state' : {}, + 'data' : options && options.no_data ? false : obj.data + //( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ), + }, i, j; + if(options && options.flat) { + tmp.parent = obj.parent; + } + else { + tmp.children = []; + } + if(!options || !options.no_state) { + for(i in obj.state) { + if(obj.state.hasOwnProperty(i)) { + tmp.state[i] = obj.state[i]; + } + } + } + if(options && options.no_id) { + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + } + if(options && options.flat && obj.id !== '#') { + flat.push(tmp); + } + if(!options || !options.no_children) { + for(i = 0, j = obj.children.length; i < j; i++) { + if(options && options.flat) { + this.get_json(obj.children[i], options, flat); + } + else { + tmp.children.push(this.get_json(obj.children[i], options)); + } + } + } + return options && options.flat ? flat : (obj.id === '#' ? tmp.children : tmp); + }, + /** + * create a new node (do not confuse with load_node) + * @name create_node([obj, node, pos, callback, is_loaded]) + * @param {mixed} par the parent node + * @param {mixed} node the data for the new node (a valid JSON object, or a simple string with the name) + * @param {mixed} pos the index at which to insert the node, "first" and "last" are also supported, default is "last" + * @param {Function} callback a function to be called once the node is created + * @param {Boolean} is_loaded internal argument indicating if the parent node was succesfully loaded + * @return {String} the ID of the newly create node + * @trigger model.jstree, create_node.jstree + */ + create_node : function (par, node, pos, callback, is_loaded) { + par = this.get_node(par); + if(!par) { return false; } + pos = pos === undefined ? "last" : pos; + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.create_node(par, node, pos, callback, true); }); + } + if(!node) { node = { "text" : this.get_string('New node') }; } + if(node.text === undefined) { node.text = this.get_string('New node'); } + var tmp, dpc, i, j; + + if(par.id === '#') { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children); + par = tmp; + break; + case "after" : + tmp = this.get_node(par.parent); + pos = $.inArray(par.id, tmp.children) + 1; + par = tmp; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > par.children.length) { pos = par.children.length; } + if(!node.id) { node.id = true; } + if(!this.check("create_node", node, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, par.id, par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : par.id }); + + par.children_d = par.children_d.concat(dpc); + for(i = 0, j = par.parents.length; i < j; i++) { + this._model.data[par.parents[i]].children_d = this._model.data[par.parents[i]].children_d.concat(dpc); + } + node = tmp; + tmp = []; + for(i = 0, j = par.children.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = par.children[i]; + } + tmp[pos] = node.id; + par.children = tmp; + + this.redraw_node(par, true); + if(callback) { callback.call(this, this.get_node(node)); } + /** + * triggered when a node is created + * @event + * @name create_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the new node among the parent's children + */ + this.trigger('create_node', { "node" : this.get_node(node), "parent" : par.id, "position" : pos }); + return node.id; + }, + /** + * set the text value of a node + * @name rename_node(obj, val) + * @param {mixed} obj the node, you can pass an array to rename multiple nodes to the same name + * @param {String} val the new text value + * @return {Boolean} + * @trigger rename_node.jstree + */ + rename_node : function (obj, val) { + var t1, t2, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.rename_node(obj[t1], val); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + old = obj.text; + if(!this.check("rename_node", obj, this.get_parent(obj), val)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + this.set_text(obj, val); // .apply(this, Array.prototype.slice.call(arguments)) + /** + * triggered when a node is renamed + * @event + * @name rename_node.jstree + * @param {Object} node + * @param {String} text the new value + * @param {String} old the old value + */ + this.trigger('rename_node', { "node" : obj, "text" : val, "old" : old }); + return true; + }, + /** + * remove a node + * @name delete_node(obj) + * @param {mixed} obj the node, you can pass an array to delete multiple nodes + * @return {Boolean} + * @trigger delete_node.jstree, changed.jstree + */ + delete_node : function (obj) { + var t1, t2, par, pos, tmp, i, j, k, l, c; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.delete_node(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + par = this.get_node(obj.parent); + pos = $.inArray(obj.id, par.children); + c = false; + if(!this.check("delete_node", obj, par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(pos !== -1) { + par.children = $.vakata.array_remove(par.children, pos); + } + tmp = obj.children_d.concat([]); + tmp.push(obj.id); + for(k = 0, l = tmp.length; k < l; k++) { + for(i = 0, j = obj.parents.length; i < j; i++) { + pos = $.inArray(tmp[k], this._model.data[obj.parents[i]].children_d); + if(pos !== -1) { + this._model.data[obj.parents[i]].children_d = $.vakata.array_remove(this._model.data[obj.parents[i]].children_d, pos); + } + } + if(this._model.data[tmp[k]].state.selected) { + c = true; + pos = $.inArray(tmp[k], this._data.core.selected); + if(pos !== -1) { + this._data.core.selected = $.vakata.array_remove(this._data.core.selected, pos); + } + } + } + /** + * triggered when a node is deleted + * @event + * @name delete_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + */ + this.trigger('delete_node', { "node" : obj, "parent" : par.id }); + if(c) { + this.trigger('changed', { 'action' : 'delete_node', 'node' : obj, 'selected' : this._data.core.selected, 'parent' : par.id }); + } + for(k = 0, l = tmp.length; k < l; k++) { + delete this._model.data[tmp[k]]; + } + this.redraw_node(par, true); + return true; + }, + /** + * check if an operation is premitted on the tree. Used internally. + * @private + * @name check(chk, obj, par, pos) + * @param {String} chk the operation to check, can be "create_node", "rename_node", "delete_node", "copy_node" or "move_node" + * @param {mixed} obj the node + * @param {mixed} par the parent + * @param {mixed} pos the position to insert at, or if "rename_node" - the new name + * @return {Boolean} + */ + check : function (chk, obj, par, pos) { + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj, + chc = this.settings.core.check_callback; + if(chk === "move_node") { + if(obj.id === par.id || $.inArray(obj.id, par.children) === pos || $.inArray(par.id, obj.children_d) !== -1) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_01', 'reason' : 'Moving parent inside child', 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + } + tmp = this.get_node(tmp, true); + if(tmp.length) { tmp = tmp.data('jstree'); } + if(tmp && tmp.functions && (tmp.functions[chk] === false || tmp.functions[chk] === true)) { + if(tmp.functions[chk] === false) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_02', 'reason' : 'Node data prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return tmp.functions[chk]; + } + if(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos) === false) || (chc && chc[chk] === false)) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + return true; + }, + /** + * get the last error + * @name last_error() + * @return {Object} + */ + last_error : function () { + return this._data.core.last_error; + }, + /** + * move a node to a new parent + * @name move_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to move, pass an array to move multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at ("first" and "last" are supported, as well as "before" and "after"), defaults to `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} internal parameter indicating if the parent node has been loaded + * @trigger move_node.jstree + */ + move_node : function (obj, par, pos, callback, is_loaded) { + var t1, t2, old_par, new_par, old_ins, is_multi, dpc, tmp, i, j, k, l, p; + if($.isArray(obj)) { + obj = obj.reverse().slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.move_node(obj[t1], par, pos, callback, is_loaded); + } + return true; + } + obj = obj && obj.id ? obj : this.get_node(obj); + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + + if(!par || !obj || obj.id === '#') { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.move_node(obj, par, pos, callback, true); }); + } + + old_par = (obj.parent || '#').toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === '#') ? par : this.get_node(par.parent); + old_ins = this._model.data[obj.id] ? this : $.jstree.reference(obj.id); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + if(is_multi) { + if(this.copy_node(obj, par, pos, callback, is_loaded)) { + if(old_ins) { old_ins.delete_node(obj); } + return true; + } + return false; + } + //var m = this._model.data; + if(new_par.id === '#') { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("move_node", obj, new_par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + if(obj.parent === new_par.id) { + dpc = new_par.children.concat(); + tmp = $.inArray(obj.id, dpc); + if(tmp !== -1) { + dpc = $.vakata.array_remove(dpc, tmp); + if(pos > tmp) { pos--; } + } + tmp = []; + for(i = 0, j = dpc.length; i < j; i++) { + tmp[i >= pos ? i+1 : i] = dpc[i]; + } + tmp[pos] = obj.id; + new_par.children = tmp; + this._node_changed(new_par.id); + this.redraw(new_par.id === '#'); + } + else { + // clean old parent and up + tmp = obj.children_d.concat(); + tmp.push(obj.id); + for(i = 0, j = obj.parents.length; i < j; i++) { + dpc = []; + p = old_ins._model.data[obj.parents[i]].children_d; + for(k = 0, l = p.length; k < l; k++) { + if($.inArray(p[k], tmp) === -1) { + dpc.push(p[k]); + } + } + old_ins._model.data[obj.parents[i]].children_d = dpc; + } + old_ins._model.data[old_par].children = $.vakata.array_remove_item(old_ins._model.data[old_par].children, obj.id); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(tmp); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = obj.id; + new_par.children = dpc; + new_par.children_d.push(obj.id); + new_par.children_d = new_par.children_d.concat(obj.children_d); + + // update object + obj.parent = new_par.id; + tmp = new_par.parents.concat(); + tmp.unshift(new_par.id); + p = obj.parents.length; + obj.parents = tmp; + + // update object children + tmp = tmp.concat(); + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].parents = this._model.data[obj.children_d[i]].parents.slice(0,p*-1); + Array.prototype.push.apply(this._model.data[obj.children_d[i]].parents, tmp); + } + + this._node_changed(old_par); + this._node_changed(new_par.id); + this.redraw(old_par === '#' || new_par.id === '#'); + } + if(callback) { callback.call(this, obj, new_par, pos); } + /** + * triggered when a node is moved + * @event + * @name move_node.jstree + * @param {Object} node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('move_node', { "node" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "is_multi" : is_multi, 'old_instance' : old_ins, 'new_instance' : this }); + return true; + }, + /** + * copy a node to a new parent + * @name copy_node(obj, par [, pos, callback, is_loaded]) + * @param {mixed} obj the node to copy, pass an array to copy multiple nodes + * @param {mixed} par the new parent + * @param {mixed} pos the position to insert at ("first" and "last" are supported, as well as "before" and "after"), defaults to `0` + * @param {function} callback a function to call once the move is completed, receives 3 arguments - the node, the new parent and the position + * @param {Boolean} internal parameter indicating if the parent node has been loaded + * @trigger model.jstree copy_node.jstree + */ + copy_node : function (obj, par, pos, callback, is_loaded) { + var t1, t2, dpc, tmp, i, j, node, old_par, new_par, old_ins, is_multi; + if($.isArray(obj)) { + obj = obj.reverse().slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.copy_node(obj[t1], par, pos, callback, is_loaded); + } + return true; + } + obj = obj && obj.id ? obj : this.get_node(obj); + par = this.get_node(par); + pos = pos === undefined ? 0 : pos; + + if(!par || !obj || obj.id === '#') { return false; } + if(!pos.toString().match(/^(before|after)$/) && !is_loaded && !this.is_loaded(par)) { + return this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true); }); + } + + old_par = (obj.parent || '#').toString(); + new_par = (!pos.toString().match(/^(before|after)$/) || par.id === '#') ? par : this.get_node(par.parent); + old_ins = this._model.data[obj.id] ? this : $.jstree.reference(obj.id); + is_multi = !old_ins || !old_ins._id || (this._id !== old_ins._id); + if(new_par.id === '#') { + if(pos === "before") { pos = "first"; } + if(pos === "after") { pos = "last"; } + } + switch(pos) { + case "before": + pos = $.inArray(par.id, new_par.children); + break; + case "after" : + pos = $.inArray(par.id, new_par.children) + 1; + break; + case "inside": + case "first": + pos = 0; + break; + case "last": + pos = new_par.children.length; + break; + default: + if(!pos) { pos = 0; } + break; + } + if(pos > new_par.children.length) { pos = new_par.children.length; } + if(!this.check("copy_node", obj, new_par, pos)) { + this.settings.core.error.call(this, this._data.core.last_error); + return false; + } + node = old_ins ? old_ins.get_json(obj, { no_id : true, no_data : true, no_state : true }) : obj; + if(!node) { return false; } + if(node.id === true) { delete node.id; } + node = this._parse_model_from_json(node, new_par.id, new_par.parents.concat()); + if(!node) { return false; } + tmp = this.get_node(node); + dpc = []; + dpc.push(node); + dpc = dpc.concat(tmp.children_d); + this.trigger('model', { "nodes" : dpc, "parent" : new_par.id }); + + // insert into new parent and up + for(i = 0, j = new_par.parents.length; i < j; i++) { + this._model.data[new_par.parents[i]].children_d = this._model.data[new_par.parents[i]].children_d.concat(dpc); + } + dpc = []; + for(i = 0, j = new_par.children.length; i < j; i++) { + dpc[i >= pos ? i+1 : i] = new_par.children[i]; + } + dpc[pos] = tmp.id; + new_par.children = dpc; + new_par.children_d.push(tmp.id); + new_par.children_d = new_par.children_d.concat(tmp.children_d); + + this._node_changed(new_par.id); + this.redraw(new_par.id === '#'); + if(callback) { callback.call(this, tmp, new_par, pos); } + /** + * triggered when a node is copied + * @event + * @name copy_node.jstree + * @param {Object} node the copied node + * @param {Object} original the original node + * @param {String} parent the parent's ID + * @param {Number} position the position of the node among the parent's children + * @param {String} old_parent the old parent of the node + * @param {Boolean} is_multi do the node and new parent belong to different instances + * @param {jsTree} old_instance the instance the node came from + * @param {jsTree} new_instance the instance of the new parent + */ + this.trigger('copy_node', { "node" : tmp, "original" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "is_multi" : is_multi, 'old_instance' : old_ins, 'new_instance' : this }); + return tmp.id; + }, + /** + * cut a node (a later call to `paste(obj)` would move the node) + * @name cut(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger cut.jstree + */ + cut : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== '#') { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'move_node'; + /** + * triggered when nodes are added to the buffer for moving + * @event + * @name cut.jstree + * @param {Array} node + */ + this.trigger('cut', { "node" : obj }); + }, + /** + * copy a node (a later call to `paste(obj)` would copy the node) + * @name copy(obj) + * @param {mixed} obj multiple objects can be passed using an array + * @trigger copy.jstre + */ + copy : function (obj) { + if(!obj) { obj = this._data.core.selected.concat(); } + if(!$.isArray(obj)) { obj = [obj]; } + if(!obj.length) { return false; } + var tmp = [], o, t1, t2; + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + o = this.get_node(obj[t1]); + if(o && o.id && o.id !== '#') { tmp.push(o); } + } + if(!tmp.length) { return false; } + ccp_node = tmp; + ccp_inst = this; + ccp_mode = 'copy_node'; + /** + * triggered when nodes are added to the buffer for copying + * @event + * @name copy.jstree + * @param {Array} node + */ + this.trigger('copy', { "node" : obj }); + }, + /** + * get the current buffer (any nodes that are waiting for a paste operation) + * @name get_buffer() + * @return {Object} an object consisting of `mode` ("copy_node" or "move_node"), `node` (an array of objects) and `inst` (the instance) + */ + get_buffer : function () { + return { 'mode' : ccp_mode, 'node' : ccp_node, 'inst' : ccp_inst }; + }, + /** + * check if there is something in the buffer to paste + * @name can_paste() + * @return {Boolean} + */ + can_paste : function () { + return ccp_mode !== false && ccp_node !== false; // && ccp_inst._model.data[ccp_node]; + }, + /** + * copy or move the previously cut or copied nodes to a new parent + * @name paste(obj) + * @param {mixed} obj the new parent + * @trigger paste.jstree + */ + paste : function (obj) { + obj = this.get_node(obj); + if(!obj || !ccp_mode || !ccp_mode.match(/^(copy_node|move_node)$/) || !ccp_node) { return false; } + if(this[ccp_mode](ccp_node, obj)) { + /** + * triggered when paste is invoked + * @event + * @name paste.jstree + * @param {String} parent the ID of the receiving node + * @param {Array} node the nodes in the buffer + * @param {String} mode the performed operation - "copy_node" or "move_node" + */ + this.trigger('paste', { "parent" : obj.id, "node" : ccp_node, "mode" : ccp_mode }); + } + ccp_node = false; + ccp_mode = false; + ccp_inst = false; + }, + /** + * put a node in edit mode (input field to rename the node) + * @name edit(obj [, default_text]) + * @param {mixed} obj + * @param {String} default_text the text to populate the input with (if omitted the node text value is used) + */ + edit : function (obj, default_text) { + obj = this._open_to(obj); + if(!obj || !obj.length) { return false; } + var rtl = this._data.core.rtl, + w = this.element.width(), + a = obj.children('.jstree-anchor'), + s = $(''), + /*! + oi = obj.children("i:visible"), + ai = a.children("i:visible"), + w1 = oi.width() * oi.length, + w2 = ai.width() * ai.length, + */ + t = typeof default_text === 'string' ? default_text : this.get_text(obj), + h1 = $("<"+"div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"), + h2 = $("<"+"input />", { + "value" : t, + "class" : "jstree-rename-input", + // "size" : t.length, + "css" : { + "padding" : "0", + "border" : "1px solid silver", + "box-sizing" : "border-box", + "display" : "inline-block", + "height" : (this._data.core.li_height) + "px", + "lineHeight" : (this._data.core.li_height) + "px", + "width" : "150px" // will be set a bit further down + }, + "blur" : $.proxy(function () { + var i = s.children(".jstree-rename-input"), + v = i.val(); + if(v === "") { v = t; } + h1.remove(); + s.replaceWith(a); + s.remove(); + this.set_text(obj, t); + if(this.rename_node(obj, v) === false) { + this.set_text(obj, t); // move this up? and fix #483 + } + }, this), + "keydown" : function (event) { + var key = event.which; + if(key === 27) { + this.value = t; + } + if(key === 27 || key === 13 || key === 37 || key === 38 || key === 39 || key === 40 || key === 32) { + event.stopImmediatePropagation(); + } + if(key === 27 || key === 13) { + event.preventDefault(); + this.blur(); + } + }, + "click" : function (e) { e.stopImmediatePropagation(); }, + "mousedown" : function (e) { e.stopImmediatePropagation(); }, + "keyup" : function (event) { + h2.width(Math.min(h1.text("pW" + this.value).width(),w)); + }, + "keypress" : function(event) { + if(event.which === 13) { return false; } + } + }), + fn = { + fontFamily : a.css('fontFamily') || '', + fontSize : a.css('fontSize') || '', + fontWeight : a.css('fontWeight') || '', + fontStyle : a.css('fontStyle') || '', + fontStretch : a.css('fontStretch') || '', + fontVariant : a.css('fontVariant') || '', + letterSpacing : a.css('letterSpacing') || '', + wordSpacing : a.css('wordSpacing') || '' + }; + this.set_text(obj, ""); + s.attr('class', a.attr('class')).append(a.contents().clone()).append(h2); + a.replaceWith(s); + h1.css(fn); + h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select(); + }, + + + /** + * changes the theme + * @name set_theme(theme_name [, theme_url]) + * @param {String} theme_name the name of the new theme to apply + * @param {mixed} theme_url the location of the CSS file for this theme. Omit or set to `false` if you manually included the file. Set to `true` to autoload from the `core.themes.dir` directory. + * @trigger set_theme.jstree + */ + set_theme : function (theme_name, theme_url) { + if(!theme_name) { return false; } + if(theme_url === true) { + var dir = this.settings.core.themes.dir; + if(!dir) { dir = $.jstree.path + '/themes'; } + theme_url = dir + '/' + theme_name + '/style.css'; + } + if(theme_url && $.inArray(theme_url, themes_loaded) === -1) { + $('head').append('<'+'link rel="stylesheet" href="' + theme_url + '" type="text/css" />'); + themes_loaded.push(theme_url); + } + if(this._data.core.themes.name) { + this.element.removeClass('jstree-' + this._data.core.themes.name); + } + this._data.core.themes.name = theme_name; + this.element.addClass('jstree-' + theme_name); + this.element[this.settings.core.themes.responsive ? 'addClass' : 'removeClass' ]('jstree-' + theme_name + '-responsive'); + /** + * triggered when a theme is set + * @event + * @name set_theme.jstree + * @param {String} theme the new theme + */ + this.trigger('set_theme', { 'theme' : theme_name }); + }, + /** + * gets the name of the currently applied theme name + * @name get_theme() + * @return {String} + */ + get_theme : function () { return this._data.core.themes.name; }, + /** + * changes the theme variant (if the theme has variants) + * @name set_theme_variant(variant_name) + * @param {String|Boolean} variant_name the variant to apply (if `false` is used the current variant is removed) + */ + set_theme_variant : function (variant_name) { + if(this._data.core.themes.variant) { + this.element.removeClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + this._data.core.themes.variant = variant_name; + if(variant_name) { + this.element.addClass('jstree-' + this._data.core.themes.name + '-' + this._data.core.themes.variant); + } + }, + /** + * gets the name of the currently applied theme variant + * @name get_theme() + * @return {String} + */ + get_theme_variant : function () { return this._data.core.themes.variant; }, + /** + * shows a striped background on the container (if the theme supports it) + * @name show_stripes() + */ + show_stripes : function () { this._data.core.themes.stripes = true; this.get_container_ul().addClass("jstree-striped"); }, + /** + * hides the striped background on the container + * @name hide_stripes() + */ + hide_stripes : function () { this._data.core.themes.stripes = false; this.get_container_ul().removeClass("jstree-striped"); }, + /** + * toggles the striped background on the container + * @name toggle_stripes() + */ + toggle_stripes : function () { if(this._data.core.themes.stripes) { this.hide_stripes(); } else { this.show_stripes(); } }, + /** + * shows the connecting dots (if the theme supports it) + * @name show_dots() + */ + show_dots : function () { this._data.core.themes.dots = true; this.get_container_ul().removeClass("jstree-no-dots"); }, + /** + * hides the connecting dots + * @name hide_dots() + */ + hide_dots : function () { this._data.core.themes.dots = false; this.get_container_ul().addClass("jstree-no-dots"); }, + /** + * toggles the connecting dots + * @name toggle_dots() + */ + toggle_dots : function () { if(this._data.core.themes.dots) { this.hide_dots(); } else { this.show_dots(); } }, + /** + * show the node icons + * @name show_icons() + */ + show_icons : function () { this._data.core.themes.icons = true; this.get_container_ul().removeClass("jstree-no-icons"); }, + /** + * hide the node icons + * @name hide_icons() + */ + hide_icons : function () { this._data.core.themes.icons = false; this.get_container_ul().addClass("jstree-no-icons"); }, + /** + * toggle the node icons + * @name toggle_icons() + */ + toggle_icons : function () { if(this._data.core.themes.icons) { this.hide_icons(); } else { this.show_icons(); } }, + /** + * set the node icon for a node + * @name set_icon(obj, icon) + * @param {mixed} obj + * @param {String} icon the new icon - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + */ + set_icon : function (obj, icon) { + var t1, t2, dom, old; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_icon(obj[t1], icon); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + old = obj.icon; + obj.icon = icon; + dom = this.get_node(obj, true).children(".jstree-anchor").children(".jstree-themeicon"); + if(icon === false) { + this.hide_icon(obj); + } + else if(icon === true) { + dom.removeClass('jstree-themeicon-custom ' + old).css("background","").removeAttr("rel"); + } + else if(icon.indexOf("/") === -1 && icon.indexOf(".") === -1) { + dom.removeClass(old).css("background",""); + dom.addClass(icon + ' jstree-themeicon-custom').attr("rel",icon); + } + else { + dom.removeClass(old).css("background",""); + dom.addClass('jstree-themeicon-custom').css("background", "url('" + icon + "') center center no-repeat").attr("rel",icon); + } + return true; + }, + /** + * get the node icon for a node + * @name get_icon(obj) + * @param {mixed} obj + * @return {String} + */ + get_icon : function (obj) { + obj = this.get_node(obj); + return (!obj || obj.id === '#') ? false : obj.icon; + }, + /** + * hide the icon on an individual node + * @name hide_icon(obj) + * @param {mixed} obj + */ + hide_icon : function (obj) { + var t1, t2; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.hide_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === '#') { return false; } + obj.icon = false; + this.get_node(obj, true).children("a").children(".jstree-themeicon").addClass('jstree-themeicon-hidden'); + return true; + }, + /** + * show the icon on an individual node + * @name show_icon(obj) + * @param {mixed} obj + */ + show_icon : function (obj) { + var t1, t2, dom; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.show_icon(obj[t1]); + } + return true; + } + obj = this.get_node(obj); + if(!obj || obj === '#') { return false; } + dom = this.get_node(obj, true); + obj.icon = dom.length ? dom.children("a").children(".jstree-themeicon").attr('rel') : true; + if(!obj.icon) { obj.icon = true; } + dom.children("a").children(".jstree-themeicon").removeClass('jstree-themeicon-hidden'); + return true; + } + }; + + // helpers + $.vakata = {}; + // reverse + $.fn.vakata_reverse = [].reverse; + // collect attributes + $.vakata.attributes = function(node, with_values) { + node = $(node)[0]; + var attr = with_values ? {} : []; + if(node && node.attributes) { + $.each(node.attributes, function (i, v) { + if($.inArray(v.nodeName.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; } + if(v.nodeValue !== null && $.trim(v.nodeValue) !== '') { + if(with_values) { attr[v.nodeName] = v.nodeValue; } + else { attr.push(v.nodeName); } + } + }); + } + return attr; + }; + $.vakata.array_unique = function(array) { + var a = [], i, j, l; + for(i = 0, l = array.length; i < l; i++) { + for(j = 0; j <= i; j++) { + if(array[i] === array[j]) { + break; + } + } + if(j === i) { a.push(array[i]); } + } + return a; + }; + // remove item from array + $.vakata.array_remove = function(array, from, to) { + var rest = array.slice((to || from) + 1 || array.length); + array.length = from < 0 ? array.length + from : from; + array.push.apply(array, rest); + return array; + }; + // remove item from array + $.vakata.array_remove_item = function(array, item) { + var tmp = $.inArray(item, array); + return tmp !== -1 ? $.vakata.array_remove(array, tmp) : array; + }; + // browser sniffing + (function () { + var browser = {}, + b_match = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || + /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + (ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua )) || + []; + return { + browser: match[1] || "", + version: match[2] || "0" + }; + }, + matched = b_match(window.navigator.userAgent); + if(matched.browser) { + browser[ matched.browser ] = true; + browser.version = matched.version; + } + if(browser.chrome) { + browser.webkit = true; + } + else if(browser.webkit) { + browser.safari = true; + } + $.vakata.browser = browser; + }()); + if($.vakata.browser.msie && $.vakata.browser.version < 8) { + $.jstree.defaults.core.animation = 0; + } + +/** + * ### Checkbox plugin + * + * This plugin renders checkbox icons in front of each node, making multiple selection much easier. + * It also supports tri-state behavior, meaning that if a node has a few of its children checked it will be rendered as undetermined, and state will be propagated up. + */ + + var _i = document.createElement('I'); + _i.className = 'jstree-icon jstree-checkbox'; + /** + * stores all defaults for the checkbox plugin + * @name $.jstree.defaults.checkbox + * @plugin checkbox + */ + $.jstree.defaults.checkbox = { + /** + * a boolean indicating if checkboxes should be visible (can be changed at a later time using `show_checkboxes()` and `hide_checkboxes`). Defaults to `true`. + * @name $.jstree.defaults.checkbox.visible + * @plugin checkbox + */ + visible : true, + /** + * a boolean indicating if checkboxes should cascade down and have an undetermined state. Defaults to `true`. + * @name $.jstree.defaults.checkbox.three_state + * @plugin checkbox + */ + three_state : true, + /** + * a boolean indicating if clicking anywhere on the node should act as clicking on the checkbox. Defaults to `true`. + * @name $.jstree.defaults.checkbox.whole_node + * @plugin checkbox + */ + whole_node : true, + /** + * a boolean indicating if the selected style of a node should be kept, or removed. Defaults to `true`. + * @name $.jstree.defaults.checkbox.keep_selected_style + * @plugin checkbox + */ + keep_selected_style : true + }; + $.jstree.plugins.checkbox = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this._data.checkbox.uto = false; + this.element + .on("init.jstree", $.proxy(function () { + this._data.checkbox.visible = this.settings.checkbox.visible; + if(!this.settings.checkbox.keep_selected_style) { + this.element.addClass('jstree-checkbox-no-clicked'); + } + }, this)) + .on("loading.jstree", $.proxy(function () { + this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ](); + }, this)); + if(this.settings.checkbox.three_state) { + this.element + .on('changed.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () { + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + }, this)) + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + p = m[data.parent], + dpc = data.nodes, + chd = [], + c, i, j, k, l, tmp; + + // apply down + if(p.state.selected) { + for(i = 0, j = dpc.length; i < j; i++) { + m[dpc[i]].state.selected = true; + } + this._data.core.selected = this._data.core.selected.concat(dpc); + } + else { + for(i = 0, j = dpc.length; i < j; i++) { + if(m[dpc[i]].state.selected) { + for(k = 0, l = m[dpc[i]].children_d.length; k < l; k++) { + m[m[dpc[i]].children_d[k]].state.selected = true; + } + this._data.core.selected = this._data.core.selected.concat(m[dpc[i]].children_d); + } + } + } + + // apply up + for(i = 0, j = p.children_d.length; i < j; i++) { + if(!m[p.children_d[i]].children.length) { + chd.push(m[p.children_d[i]].parent); + } + } + chd = $.vakata.array_unique(chd); + for(k = 0, l = chd.length; k < l; k++) { + p = m[chd[k]]; + while(p && p.id !== '#') { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state.selected; + } + if(c === j) { + p.state.selected = true; + this._data.core.selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').addClass('jstree-clicked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + this._data.core.selected = $.vakata.array_unique(this._data.core.selected); + }, this)) + .on('select_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + m = this._model.data, + par = this.get_node(obj.parent), + dom = this.get_node(obj, true), + i, j, c, tmp; + this._data.core.selected = $.vakata.array_unique(this._data.core.selected.concat(obj.children_d)); + for(i = 0, j = obj.children_d.length; i < j; i++) { + m[obj.children_d[i]].state.selected = true; + } + while(par && par.id !== '#') { + c = 0; + for(i = 0, j = par.children.length; i < j; i++) { + c += m[par.children[i]].state.selected; + } + if(c === j) { + par.state.selected = true; + this._data.core.selected.push(par.id); + tmp = this.get_node(par, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').addClass('jstree-clicked'); + } + } + else { + break; + } + par = this.get_node(par.parent); + } + if(dom.length) { + dom.find('.jstree-anchor').addClass('jstree-clicked'); + } + }, this)) + .on('deselect_node.jstree', $.proxy(function (e, data) { + var obj = data.node, + dom = this.get_node(obj, true), + i, j, tmp; + for(i = 0, j = obj.children_d.length; i < j; i++) { + this._model.data[obj.children_d[i]].state.selected = false; + } + for(i = 0, j = obj.parents.length; i < j; i++) { + this._model.data[obj.parents[i]].state.selected = false; + tmp = this.get_node(obj.parents[i], true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').removeClass('jstree-clicked'); + } + } + tmp = []; + for(i = 0, j = this._data.core.selected.length; i < j; i++) { + if($.inArray(this._data.core.selected[i], obj.children_d) === -1 && $.inArray(this._data.core.selected[i], obj.parents) === -1) { + tmp.push(this._data.core.selected[i]); + } + } + this._data.core.selected = $.vakata.array_unique(tmp); + if(dom.length) { + dom.find('.jstree-anchor').removeClass('jstree-clicked'); + } + }, this)) + .on('delete_node.jstree', $.proxy(function (e, data) { + var p = this.get_node(data.parent), + m = this._model.data, + i, j, c, tmp; + while(p && p.id !== '#') { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state.selected; + } + if(c === j) { + p.state.selected = true; + this._data.core.selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').addClass('jstree-clicked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + }, this)) + .on('move_node.jstree', $.proxy(function (e, data) { + var is_multi = data.is_multi, + old_par = data.old_parent, + new_par = this.get_node(data.parent), + m = this._model.data, + p, c, i, j, tmp; + if(!is_multi) { + p = this.get_node(old_par); + while(p && p.id !== '#') { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state.selected; + } + if(c === j) { + p.state.selected = true; + this._data.core.selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').addClass('jstree-clicked'); + } + } + else { + break; + } + p = this.get_node(p.parent); + } + } + p = new_par; + while(p && p.id !== '#') { + c = 0; + for(i = 0, j = p.children.length; i < j; i++) { + c += m[p.children[i]].state.selected; + } + if(c === j) { + if(!p.state.selected) { + p.state.selected = true; + this._data.core.selected.push(p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').addClass('jstree-clicked'); + } + } + } + else { + if(p.state.selected) { + p.state.selected = false; + this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, p.id); + tmp = this.get_node(p, true); + if(tmp && tmp.length) { + tmp.children('.jstree-anchor').removeClass('jstree-clicked'); + } + } + else { + break; + } + } + p = this.get_node(p.parent); + } + }, this)); + } + }; + /** + * set the undetermined state where and if necessary. Used internally. + * @private + * @name _undetermined() + * @plugin checkbox + */ + this._undetermined = function () { + var i, j, m = this._model.data, s = this._data.core.selected, p = [], t = this; + for(i = 0, j = s.length; i < j; i++) { + if(m[s[i]] && m[s[i]].parents) { + p = p.concat(m[s[i]].parents); + } + } + // attempt for server side undetermined state + this.element.find('.jstree-closed').not(':has(ul)') + .each(function () { + var tmp = t.get_node(this); + if(!tmp.state.loaded && tmp.original && tmp.original.state && tmp.original.state.undetermined && tmp.original.state.undetermined === true) { + p.push(tmp.id); + p = p.concat(tmp.parents); + } + }); + p = $.vakata.array_unique(p); + i = $.inArray('#', p); + if(i !== -1) { + p = $.vakata.array_remove(p, i); + } + + this.element.find('.jstree-undetermined').removeClass('jstree-undetermined'); + for(i = 0, j = p.length; i < j; i++) { + if(!m[p[i]].state.selected) { + s = this.get_node(p[i], true); + if(s && s.length) { + s.children('a').children('.jstree-checkbox').addClass('jstree-undetermined'); + } + } + } + }; + this.redraw_node = function(obj, deep, is_callback) { + obj = parent.redraw_node.call(this, obj, deep, is_callback); + if(obj) { + var tmp = obj.getElementsByTagName('A')[0]; + tmp.insertBefore(_i.cloneNode(), tmp.childNodes[0]); + } + if(!is_callback && this.settings.checkbox.three_state) { + if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); } + this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50); + } + return obj; + }; + this.activate_node = function (obj, e) { + if(this.settings.checkbox.whole_node || $(e.target).hasClass('jstree-checkbox')) { + e.ctrlKey = true; + } + return parent.activate_node.call(this, obj, e); + }; + /** + * show the node checkbox icons + * @name show_checkboxes() + * @plugin checkbox + */ + this.show_checkboxes = function () { this._data.core.themes.checkboxes = true; this.element.children("ul").removeClass("jstree-no-checkboxes"); }; + /** + * hide the node checkbox icons + * @name hide_checkboxes() + * @plugin checkbox + */ + this.hide_checkboxes = function () { this._data.core.themes.checkboxes = false; this.element.children("ul").addClass("jstree-no-checkboxes"); }; + /** + * toggle the node icons + * @name toggle_checkboxes() + * @plugin checkbox + */ + this.toggle_checkboxes = function () { if(this._data.core.themes.checkboxes) { this.hide_checkboxes(); } else { this.show_checkboxes(); } }; + }; + + // include the checkbox plugin by default + // $.jstree.defaults.plugins.push("checkbox"); + +/** + * ### Contextmenu plugin + * + * Shows a context menu when a node is right-clicked. + */ +// TODO: move logic outside of function + check multiple move + + /** + * stores all defaults for the contextmenu plugin + * @name $.jstree.defaults.contextmenu + * @plugin contextmenu + */ + $.jstree.defaults.contextmenu = { + /** + * a boolean indicating if the node should be selected when the context menu is invoked on it. Defaults to `true`. + * @name $.jstree.defaults.contextmenu.select_node + * @plugin contextmenu + */ + select_node : true, + /** + * a boolean indicating if the menu should be shown aligned with the node. Defaults to `true`, otherwise the mouse coordinates are used. + * @name $.jstree.defaults.contextmenu.show_at_node + * @plugin contextmenu + */ + show_at_node : true, + /** + * an object of actions, or a function that accepts a node and a callback function and calls the callback function with an object of actions available for that node (you can also return the items too). + * + * Each action consists of a key (a unique name) and a value which is an object with the following properties (only label and action are required): + * + * * `separator_before` - a boolean indicating if there should be a separator before this item + * * `separator_after` - a boolean indicating if there should be a separator after this item + * * `_disabled` - a boolean indicating if this action should be disabled + * * `label` - a string - the name of the action + * * `action` - a function to be executed if this item is chosen + * * `icon` - a string, can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class + * * `shortcut` - keyCode which will trigger the action if the menu is open (for example `113` for rename, which equals F2) + * * `shortcut_label` - shortcut label (like for example `F2` for rename) + * + * @name $.jstree.defaults.contextmenu.items + * @plugin contextmenu + */ + items : function (o, cb) { // Could be an object directly + return { + "create" : { + "separator_before" : false, + "separator_after" : true, + "_disabled" : false, //(this.check("create_node", data.reference, {}, "last")), + "label" : "Create", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.create_node(obj, {}, "last", function (new_node) { + setTimeout(function () { inst.edit(new_node); },0); + }); + } + }, + "rename" : { + "separator_before" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("rename_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Rename", + /* + "shortcut" : 113, + "shortcut_label" : 'F2', + "icon" : "glyphicon glyphicon-leaf", + */ + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.edit(obj); + } + }, + "remove" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "_disabled" : false, //(this.check("delete_node", data.reference, this.get_parent(data.reference), "")), + "label" : "Delete", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.delete_node(inst.get_selected()); + } + else { + inst.delete_node(obj); + } + } + }, + "ccp" : { + "separator_before" : true, + "icon" : false, + "separator_after" : false, + "label" : "Edit", + "action" : false, + "submenu" : { + "cut" : { + "separator_before" : false, + "separator_after" : false, + "label" : "Cut", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.cut(inst.get_selected()); + } + else { + inst.cut(obj); + } + } + }, + "copy" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Copy", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + if(inst.is_selected(obj)) { + inst.copy(inst.get_selected()); + } + else { + inst.copy(obj); + } + } + }, + "paste" : { + "separator_before" : false, + "icon" : false, + "_disabled" : function (data) { + return !$.jstree.reference(data.reference).can_paste(); + }, + "separator_after" : false, + "label" : "Paste", + "action" : function (data) { + var inst = $.jstree.reference(data.reference), + obj = inst.get_node(data.reference); + inst.paste(obj); + } + } + } + } + }; + } + }; + + $.jstree.plugins.contextmenu = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this.element + .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e) { + e.preventDefault(); + if(!this.is_loading(e.currentTarget)) { + this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e); + } + }, this)) + .on("click.jstree", ".jstree-anchor", $.proxy(function (e) { + if(this._data.contextmenu.visible) { + $.vakata.context.hide(); + } + }, this)); + /* + if(!('oncontextmenu' in document.body) && ('ontouchstart' in document.body)) { + var el = null, tm = null; + this.element + .on("touchstart", ".jstree-anchor", function (e) { + el = e.currentTarget; + tm = +new Date(); + $(document).one("touchend", function (e) { + e.target = document.elementFromPoint(e.originalEvent.targetTouches[0].pageX - window.pageXOffset, e.originalEvent.targetTouches[0].pageY - window.pageYOffset); + e.currentTarget = e.target; + tm = ((+(new Date())) - tm); + if(e.target === el && tm > 600 && tm < 1000) { + e.preventDefault(); + $(el).trigger('contextmenu', e); + } + el = null; + tm = null; + }); + }); + } + */ + $(document).on("context_hide.vakata", $.proxy(function () { this._data.contextmenu.visible = false; }, this)); + }; + this.teardown = function () { + if(this._data.contextmenu.visible) { + $.vakata.context.hide(); + } + parent.teardown.call(this); + }; + + /** + * prepare and show the context menu for a node + * @name show_contextmenu(obj [, x, y]) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Object} e the event if available that triggered the contextmenu + * @plugin contextmenu + * @trigger show_contextmenu.jstree + */ + this.show_contextmenu = function (obj, x, y, e) { + obj = this.get_node(obj); + if(!obj || obj.id === '#') { return false; } + var s = this.settings.contextmenu, + d = this.get_node(obj, true), + a = d.children(".jstree-anchor"), + o = false, + i = false; + if(s.show_at_node || x === undefined || y === undefined) { + o = a.offset(); + x = o.left; + y = o.top + this._data.core.li_height; + } + if(this.settings.contextmenu.select_node && !this.is_selected(obj)) { + this.deselect_all(); + this.select_node(obj, false, false, e); + } + + i = s.items; + if($.isFunction(i)) { + i = i.call(this, obj, $.proxy(function (i) { + this._show_contextmenu(obj, x, y, i); + }, this)); + } + if($.isPlainObject(i)) { + this._show_contextmenu(obj, x, y, i); + } + }; + /** + * show the prepared context menu for a node + * @name _show_contextmenu(obj, x, y, i) + * @param {mixed} obj the node + * @param {Number} x the x-coordinate relative to the document to show the menu at + * @param {Number} y the y-coordinate relative to the document to show the menu at + * @param {Number} i the object of items to show + * @plugin contextmenu + * @trigger show_contextmenu.jstree + * @private + */ + this._show_contextmenu = function (obj, x, y, i) { + var d = this.get_node(obj, true), + a = d.children(".jstree-anchor"); + $(document).one("context_show.vakata", $.proxy(function (e, data) { + var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu'; + $(data.element).addClass(cls); + }, this)); + this._data.contextmenu.visible = true; + $.vakata.context.show(a, { 'x' : x, 'y' : y }, i); + /** + * triggered when the contextmenu is shown for a node + * @event + * @name show_contextmenu.jstree + * @param {Object} node the node + * @param {Number} x the x-coordinate of the menu relative to the document + * @param {Number} y the y-coordinate of the menu relative to the document + * @plugin contextmenu + */ + this.trigger('show_contextmenu', { "node" : obj, "x" : x, "y" : y }); + }; + }; + + // contextmenu helper + (function ($) { + var right_to_left = false, + vakata_context = { + element : false, + reference : false, + position_x : 0, + position_y : 0, + items : [], + html : "", + is_visible : false + }; + + $.vakata.context = { + settings : { + hide_onmouseleave : 0, + icons : true + }, + _trigger : function (event_name) { + $(document).triggerHandler("context_" + event_name + ".vakata", { + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }); + }, + _execute : function (i) { + i = vakata_context.items[i]; + return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, { + "item" : i, + "reference" : vakata_context.reference, + "element" : vakata_context.element, + "position" : { + "x" : vakata_context.position_x, + "y" : vakata_context.position_y + } + }) : false; + }, + _parse : function (o, is_callback) { + if(!o) { return false; } + if(!is_callback) { + vakata_context.html = ""; + vakata_context.items = []; + } + var str = "", + sep = false, + tmp; + + if(is_callback) { str += "<"+"ul>"; } + $.each(o, function (i, val) { + if(!val) { return true; } + vakata_context.items.push(val); + if(!sep && val.separator_before) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + } + sep = false; + str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">"; + str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "'>"; + if($.vakata.context.settings.icons) { + str += "<"+"i "; + if(val.icon) { + if(val.icon.indexOf("/") !== -1 || val.icon.indexOf(".") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; } + else { str += " class='" + val.icon + "' "; } + } + str += "><"+"/i><"+"span class='vakata-contextmenu-sep'> <"+"/span>"; + } + str += val.label + (val.shortcut?' '+ (val.shortcut_label || '') +'':'') + "<"+"/a>"; + if(val.submenu) { + tmp = $.vakata.context._parse(val.submenu, true); + if(tmp) { str += tmp; } + } + str += "<"+"/li>"; + if(val.separator_after) { + str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>"; + sep = true; + } + }); + str = str.replace(/<\/li\>$/,""); + if(is_callback) { str += ""; } + /** + * triggered on the document when the contextmenu is parsed (HTML is built) + * @event + * @plugin contextmenu + * @name context_parse.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); } + return str.length > 10 ? str : false; + }, + _show_submenu : function (o) { + o = $(o); + if(!o.length || !o.children("ul").length) { return; } + var e = o.children("ul"), + x = o.offset().left + o.outerWidth(), + y = o.offset().top, + w = e.width(), + h = e.height(), + dw = $(window).width() + $(window).scrollLeft(), + dh = $(window).height() + $(window).scrollTop(); + // може да се спести е една проверка - дали няма някой от класовете вече нагоре + if(right_to_left) { + o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left"); + } + else { + o[x + w + 10 > dw ? "addClass" : "removeClass"]("vakata-context-right"); + } + if(y + h + 10 > dh) { + e.css("bottom","-1px"); + } + e.show(); + }, + show : function (reference, position, data) { + var o, e, x, y, w, h, dw, dh, cond = true; + if(vakata_context.element && vakata_context.element.length) { + vakata_context.element.width(''); + } + switch(cond) { + case (!position && !reference): + return false; + case (!!position && !!reference): + vakata_context.reference = reference; + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + case (!position && !!reference): + vakata_context.reference = reference; + o = reference.offset(); + vakata_context.position_x = o.left + reference.outerHeight(); + vakata_context.position_y = o.top; + break; + case (!!position && !reference): + vakata_context.position_x = position.x; + vakata_context.position_y = position.y; + break; + } + if(!!reference && !data && $(reference).data('vakata_contextmenu')) { + data = $(reference).data('vakata_contextmenu'); + } + if($.vakata.context._parse(data)) { + vakata_context.element.html(vakata_context.html); + } + if(vakata_context.items.length) { + e = vakata_context.element; + x = vakata_context.position_x; + y = vakata_context.position_y; + w = e.width(); + h = e.height(); + dw = $(window).width() + $(window).scrollLeft(); + dh = $(window).height() + $(window).scrollTop(); + if(right_to_left) { + x -= e.outerWidth(); + if(x < $(window).scrollLeft() + 20) { + x = $(window).scrollLeft() + 20; + } + } + if(x + w + 20 > dw) { + x = dw - (w + 20); + } + if(y + h + 20 > dh) { + y = dh - (h + 20); + } + + vakata_context.element + .css({ "left" : x, "top" : y }) + .show() + .find('a:eq(0)').focus().parent().addClass("vakata-context-hover"); + vakata_context.is_visible = true; + /** + * triggered on the document when the contextmenu is shown + * @event + * @plugin contextmenu + * @name context_show.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("show"); + } + }, + hide : function () { + if(vakata_context.is_visible) { + vakata_context.element.hide().find("ul").hide().end().find(':focus').blur(); + vakata_context.is_visible = false; + /** + * triggered on the document when the contextmenu is hidden + * @event + * @plugin contextmenu + * @name context_hide.vakata + * @param {jQuery} reference the element that was right clicked + * @param {jQuery} element the DOM element of the menu itself + * @param {Object} position the x & y coordinates of the menu + */ + $.vakata.context._trigger("hide"); + } + } + }; + $(function () { + right_to_left = $("body").css("direction") === "rtl"; + var to = false; + + vakata_context.element = $(""); + vakata_context.element + .on("mouseenter", "li", function (e) { + e.stopImmediatePropagation(); + + if($.contains(this, e.relatedTarget)) { + // премахнато заради delegate mouseleave по-долу + // $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + return; + } + + if(to) { clearTimeout(to); } + vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(); + + $(this) + .siblings().find("ul").hide().end().end() + .parentsUntil(".vakata-context", "li").addBack().addClass("vakata-context-hover"); + $.vakata.context._show_submenu(this); + }) + // тестово - дали не натоварва? + .on("mouseleave", "li", function (e) { + if($.contains(this, e.relatedTarget)) { return; } + $(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover"); + }) + .on("mouseleave", function (e) { + $(this).find(".vakata-context-hover").removeClass("vakata-context-hover"); + if($.vakata.context.settings.hide_onmouseleave) { + to = setTimeout( + (function (t) { + return function () { $.vakata.context.hide(); }; + }(this)), $.vakata.context.settings.hide_onmouseleave); + } + }) + .on("click", "a", function (e) { + e.preventDefault(); + }) + .on("mouseup", "a", function (e) { + if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) { + $.vakata.context.hide(); + } + }) + .on('keydown', 'a', function (e) { + var o = null; + switch(e.which) { + case 13: + case 32: + e.type = "mouseup"; + e.preventDefault(); + $(e.currentTarget).trigger(e); + break; + case 37: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().parents("li:eq(0)").find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 38: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 39: + if(vakata_context.is_visible) { + vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 40: + if(vakata_context.is_visible) { + o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(); + if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); } + o.addClass("vakata-context-hover").children('a').focus(); + e.stopImmediatePropagation(); + e.preventDefault(); + } + break; + case 27: + $.vakata.context.hide(); + e.preventDefault(); + break; + default: + //console.log(e.which); + break; + } + }) + .on('keydown', function (e) { + e.preventDefault(); + var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent(); + if(a.parent().not('.vakata-context-disabled')) { + a.mouseup(); + } + }) + .appendTo("body"); + + $(document) + .on("mousedown", function (e) { + if(vakata_context.is_visible && !$.contains(vakata_context.element[0], e.target)) { $.vakata.context.hide(); } + }) + .on("context_show.vakata", function (e, data) { + vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"); + if(right_to_left) { + vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl"); + } + // also apply a RTL class? + vakata_context.element.find("ul").hide().end(); + }); + }); + }($)); + // $.jstree.defaults.plugins.push("contextmenu"); + +/** + * ### Drag'n'drop plugin + * + * Enables dragging and dropping of nodes in the tree, resulting in a move or copy operations. + */ + + /** + * stores all defaults for the drag'n'drop plugin + * @name $.jstree.defaults.dnd + * @plugin dnd + */ + $.jstree.defaults.dnd = { + /** + * a boolean indicating if a copy should be possible while dragging (by pressint the meta key or Ctrl). Defaults to `true`. + * @name $.jstree.defaults.dnd.copy + * @plugin dnd + */ + copy : true, + /** + * a number indicating how long a node should remain hovered while dragging to be opened. Defaults to `500`. + * @name $.jstree.defaults.dnd.open_timeout + * @plugin dnd + */ + open_timeout : 500, + /** + * a function invoked each time a node is about to be dragged, invoked in the tree's scope and receives the node as an argument - return `false` to prevent dragging + * @name $.jstree.defaults.dnd.is_draggable + * @plugin dnd + */ + is_draggable : true, + /** + * a boolean indicating if checks should constantly be made while the user is dragging the node (as opposed to checking only on drop), default is `true` + * @name $.jstree.defaults.dnd.check_while_dragging + * @plugin dnd + */ + check_while_dragging : true + }; + // TODO: now check works by checking for each node individually, how about max_children, unique, etc? + // TODO: drop somewhere else - maybe demo only? + $.jstree.plugins.dnd = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this.element + .on('mousedown touchstart', '.jstree-anchor', $.proxy(function (e) { + var obj = this.get_node(e.target), + mlt = this.is_selected(obj) ? this.get_selected().length : 1; + if(obj && obj.id && obj.id !== "#" && (e.which === 1 || e.type === "touchstart") && + (this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, obj))) + ) { + this.element.trigger('mousedown.jstree'); + return $.vakata.dnd.start(e, { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_selected() : [obj.id] }, '' + (mlt > 1 ? mlt + ' ' + this.get_string('nodes') : this.get_text(e.currentTarget, true)) + '+'); + } + }, this)); + }; + }; + + $(function() { + // bind only once for all instances + var lastmv = false, + laster = false, + opento = false, + marker = $(' ').hide().appendTo('body'); + + $(document) + .bind('dnd_start.vakata', function (e, data) { + lastmv = false; + }) + .bind('dnd_move.vakata', function (e, data) { + if(opento) { clearTimeout(opento); } + if(!data.data.jstree) { return; } + + // if we are hovering the marker image do nothing (can happen on "inside" drags) + if(data.event.target.id && data.event.target.id === 'jstree-marker') { + return; + } + + var ins = $.jstree.reference(data.event.target), + ref = false, + off = false, + rel = false, + l, t, h, p, i, o, ok, t1, t2, op, ps, pr; + // if we are over an instance + if(ins && ins._data && ins._data.dnd) { + marker.attr('class', 'jstree-' + ins.get_theme()); + data.helper + .children().attr('class', 'jstree-' + ins.get_theme()) + .find('.jstree-copy:eq(0)')[ data.data.origin && data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey) ? 'show' : 'hide' ](); + + + // if are hovering the container itself add a new root node + if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) { + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + ok = ok && ins.check( (data.data.origin && data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), '#', 'last'); + if(!ok) { break; } + } + if(ok) { + lastmv = { 'ins' : ins, 'par' : '#', 'pos' : 'last' }; + marker.hide(); + data.helper.find('.jstree-icon:eq(0)').removeClass('jstree-er').addClass('jstree-ok'); + return; + } + } + else { + // if we are hovering a tree node + ref = $(data.event.target).closest('a'); + if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) { + off = ref.offset(); + rel = data.event.pageY - off.top; + h = ref.height(); + if(rel < h / 3) { + o = ['b', 'i', 'a']; + } + else if(rel > h - h / 3) { + o = ['a', 'i', 'b']; + } + else { + o = rel > h / 2 ? ['i', 'a', 'b'] : ['i', 'b', 'a']; + } + $.each(o, function (j, v) { + switch(v) { + case 'b': + l = off.left - 6; + t = off.top - 5; + p = ins.get_parent(ref); + i = ref.parent().index(); + break; + case 'i': + l = off.left - 2; + t = off.top - 5 + h / 2 + 1; + p = ref.parent(); + i = 0; + break; + case 'a': + l = off.left - 6; + t = off.top - 5 + h; + p = ins.get_parent(ref); + i = ref.parent().index() + 1; + break; + } + /*! + // TODO: moving inside, but the node is not yet loaded? + // the check will work anyway, as when moving the node will be loaded first and checked again + if(v === 'i' && !ins.is_loaded(p)) { } + */ + ok = true; + for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) { + op = data.data.origin && data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey) ? "copy_node" : "move_node"; + ps = i; + if(op === "move_node" && v === 'a' && (data.data.origin && data.data.origin === ins) && p === ins.get_parent(data.data.nodes[t1])) { + pr = ins.get_node(p); + if(ps > $.inArray(data.data.nodes[t1], pr.children)) { + ps -= 1; + } + } + ok = ok && ( (ins && ins.settings && ins.settings.dnd && ins.settings.dnd.check_while_dragging === false) || ins.check(op, (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps) ); + if(!ok) { + if(ins && ins.last_error) { laster = ins.last_error(); } + break; + } + } + if(ok) { + if(v === 'i' && ref.parent().is('.jstree-closed') && ins.settings.dnd.open_timeout) { + opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout); + } + lastmv = { 'ins' : ins, 'par' : p, 'pos' : i }; + marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show(); + data.helper.find('.jstree-icon:eq(0)').removeClass('jstree-er').addClass('jstree-ok'); + laster = {}; + o = true; + return false; + } + }); + if(o === true) { return; } + } + } + } + lastmv = false; + data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er'); + marker.hide(); + }) + .bind('dnd_scroll.vakata', function (e, data) { + if(!data.data.jstree) { return; } + marker.hide(); + lastmv = false; + data.helper.find('.jstree-icon:eq(0)').removeClass('jstree-ok').addClass('jstree-er'); + }) + .bind('dnd_stop.vakata', function (e, data) { + if(opento) { clearTimeout(opento); } + if(!data.data.jstree) { return; } + marker.hide(); + var i, j, nodes = []; + if(lastmv) { + for(i = 0, j = data.data.nodes.length; i < j; i++) { + nodes[i] = data.data.origin ? data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i]; + } + lastmv.ins[ data.data.origin && data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey) ? 'copy_node' : 'move_node' ](nodes, lastmv.par, lastmv.pos); + } + else { + i = $(data.event.target).closest('.jstree'); + if(i.length && laster && laster.error && laster.error === 'check') { + i = i.jstree(true); + if(i) { + i.settings.core.error.call(this, laster); + } + } + } + }) + .bind('keyup keydown', function (e, data) { + data = $.vakata.dnd._get(); + if(data.data && data.data.jstree) { + data.helper.find('.jstree-copy:eq(0)')[ data.data.origin && data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey) ? 'show' : 'hide' ](); + } + }); + }); + + // helpers + (function ($) { + $.fn.vakata_reverse = [].reverse; + // private variable + var vakata_dnd = { + element : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false + }; + $.vakata.dnd = { + settings : { + scroll_speed : 10, + scroll_proximity : 20, + helper_left : 5, + helper_top : 10, + threshold : 5 + }, + _trigger : function (event_name, e) { + var data = $.vakata.dnd._get(); + data.event = e; + $(document).triggerHandler("dnd_" + event_name + ".vakata", data); + }, + _get : function () { + return { + "data" : vakata_dnd.data, + "element" : vakata_dnd.element, + "helper" : vakata_dnd.helper + }; + }, + _clean : function () { + if(vakata_dnd.helper) { vakata_dnd.helper.remove(); } + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + vakata_dnd = { + element : false, + is_down : false, + is_drag : false, + helper : false, + helper_w: 0, + data : false, + init_x : 0, + init_y : 0, + scroll_l: 0, + scroll_t: 0, + scroll_e: false, + scroll_i: false + }; + $(document).off("mousemove touchmove", $.vakata.dnd.drag); + $(document).off("mouseup touchend", $.vakata.dnd.stop); + }, + _scroll : function (init_only) { + if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) { + if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; } + return false; + } + if(!vakata_dnd.scroll_i) { + vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100); + return false; + } + if(init_only === true) { return false; } + + var i = vakata_dnd.scroll_e.scrollTop(), + j = vakata_dnd.scroll_e.scrollLeft(); + vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed); + vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed); + if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) { + /** + * triggered on the document when a drag causes an element to scroll + * @event + * @plugin dnd + * @name dnd_scroll.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {jQuery} event the element that is scrolling + */ + $.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e); + } + }, + start : function (e, data, html) { + if(e.type === "touchstart" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); } + try { + e.currentTarget.unselectable = "on"; + e.currentTarget.onselectstart = function() { return false; }; + if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; } + } catch(ignore) { } + vakata_dnd.init_x = e.pageX; + vakata_dnd.init_y = e.pageY; + vakata_dnd.data = data; + vakata_dnd.is_down = true; + vakata_dnd.element = e.currentTarget; + if(html !== false) { + vakata_dnd.helper = $("").html(html).css({ + "display" : "block", + "margin" : "0", + "padding" : "0", + "position" : "absolute", + "top" : "-2000px", + "lineHeight" : "16px", + "zIndex" : "10000" + }); + } + $(document).bind("mousemove touchmove", $.vakata.dnd.drag); + $(document).bind("mouseup touchend", $.vakata.dnd.stop); + return false; + }, + drag : function (e) { + if(e.type === "touchmove" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(!vakata_dnd.is_down) { return; } + if(!vakata_dnd.is_drag) { + if( + Math.abs(e.pageX - vakata_dnd.init_x) > $.vakata.dnd.settings.threshold || + Math.abs(e.pageY - vakata_dnd.init_y) > $.vakata.dnd.settings.threshold + ) { + if(vakata_dnd.helper) { + vakata_dnd.helper.appendTo("body"); + vakata_dnd.helper_w = vakata_dnd.helper.outerWidth(); + } + vakata_dnd.is_drag = true; + /** + * triggered on the document when a drag starts + * @event + * @plugin dnd + * @name dnd_start.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the start (probably mousemove) + */ + $.vakata.dnd._trigger("start", e); + } + else { return; } + } + + var d = false, w = false, + dh = false, wh = false, + dw = false, ww = false, + dt = false, dl = false, + ht = false, hl = false; + + vakata_dnd.scroll_t = 0; + vakata_dnd.scroll_l = 0; + vakata_dnd.scroll_e = false; + $(e.target) + .parentsUntil("body").addBack().vakata_reverse() + .filter(function () { + return (/^auto|scroll$/).test($(this).css("overflow")) && + (this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth); + }) + .each(function () { + var t = $(this), o = t.offset(); + if(this.scrollHeight > this.offsetHeight) { + if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + } + if(this.scrollWidth > this.offsetWidth) { + if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = $(this); + return false; + } + }); + + if(!vakata_dnd.scroll_e) { + d = $(document); w = $(window); + dh = d.height(); wh = w.height(); + dw = d.width(); ww = w.width(); + dt = d.scrollTop(); dl = d.scrollLeft(); + if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; } + if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; } + if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; } + if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; } + if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) { + vakata_dnd.scroll_e = d; + } + } + if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); } + + if(vakata_dnd.helper) { + ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10); + hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10); + if(dh && ht + 25 > dh) { ht = dh - 50; } + if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); } + vakata_dnd.helper.css({ + left : hl + "px", + top : ht + "px" + }); + } + /** + * triggered on the document when a drag is in progress + * @event + * @plugin dnd + * @name dnd_move.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused this to trigger (most likely mousemove) + */ + $.vakata.dnd._trigger("move", e); + }, + stop : function (e) { + if(e.type === "touchend" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset); + } + if(vakata_dnd.is_drag) { + /** + * triggered on the document when a drag stops (the dragged element is dropped) + * @event + * @plugin dnd + * @name dnd_stop.vakata + * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start + * @param {DOM} element the DOM element being dragged + * @param {jQuery} helper the helper shown next to the mouse + * @param {Object} event the event that caused the stop + */ + $.vakata.dnd._trigger("stop", e); + } + $.vakata.dnd._clean(); + } + }; + }(jQuery)); + + // include the dnd plugin by default + // $.jstree.defaults.plugins.push("dnd"); + + +/** + * ### Search plugin + * + * Adds search functionality to jsTree. + */ + + /** + * stores all defaults for the search plugin + * @name $.jstree.defaults.search + * @plugin search + */ + $.jstree.defaults.search = { + /** + * a jQuery-like AJAX config, which jstree uses if a server should be queried for results. + * + * A `str` (which is the search string) parameter will be added with the request. The expected result is a JSON array with nodes that need to be opened so that matching nodes will be revealed. + * Leave this setting as `false` to not query the server. + * @name $.jstree.defaults.search.ajax + * @plugin search + */ + ajax : false, + /** + * Indicates if the search should be fuzzy or not (should `chnd3` match `child node 3`). Default is `true`. + * @name $.jstree.defaults.search.fuzzy + * @plugin search + */ + fuzzy : true, + /** + * Indicates if the search should be case sensitive. Default is `false`. + * @name $.jstree.defaults.search.case_sensitive + * @plugin search + */ + case_sensitive : false, + /** + * Indicates if the tree should be filtered to show only matching nodes (keep in mind this can be a heavy on large trees in old browsers). Default is `false`. + * @name $.jstree.defaults.search.show_only_matches + * @plugin search + */ + show_only_matches : false, + /** + * Indicates if all nodes opened to reveal the search result, should be closed when the search is cleared or a new search is performed. Default is `true`. + * @name $.jstree.defaults.search.close_opened_onclear + * @plugin search + */ + close_opened_onclear : true + }; + + $.jstree.plugins.search = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this._data.search.str = ""; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.sln = null; + + if(this.settings.search.show_only_matches) { + this.element + .on("search.jstree", function (e, data) { + if(data.nodes.length) { + $(this).find("li").hide().filter('.jstree-last').filter(function() { return this.nextSibling; }).removeClass('jstree-last'); + data.nodes.parentsUntil(".jstree").addBack().show() + .filter("ul").each(function () { $(this).children("li:visible").eq(-1).addClass("jstree-last"); }); + } + }) + .on("clear_search.jstree", function (e, data) { + if(data.nodes.length) { + $(this).find("li").css("display","").filter('.jstree-last').filter(function() { return this.nextSibling; }).removeClass('jstree-last'); + } + }); + } + }; + /** + * used to search the tree nodes for a given string + * @name search(str [, skip_async]) + * @param {String} str the search string + * @param {Boolean} skip_async if set to true server will not be queried even if configured + * @plugin search + * @trigger search.jstree + */ + this.search = function (str, skip_async) { + if(str === false || $.trim(str) === "") { + return this.clear_search(); + } + var s = this.settings.search, + a = s.ajax ? $.extend({}, s.ajax) : false, + f = null, + r = [], + p = [], i, j; + if(this._data.search.res.length) { + this.clear_search(); + } + if(!skip_async && a !== false) { + if(!a.data) { a.data = {}; } + a.data.str = str; + return $.ajax(a) + .fail($.proxy(function () { + this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) }; + this.settings.core.error.call(this, this._data.core.last_error); + }, this)) + .done($.proxy(function (d) { + if(d && d.d) { d = d.d; } + this._data.search.sln = !$.isArray(d) ? [] : d; + this._search_load(str); + }, this)); + } + this._data.search.str = str; + this._data.search.dom = $(); + this._data.search.res = []; + this._data.search.opn = []; + + f = new $.vakata.search(str, true, { caseSensitive : s.case_sensitive, fuzzy : s.fuzzy }); + + $.each(this._model.data, function (i, v) { + if(v.text && f.search(v.text).isMatch) { + r.push(i); + p = p.concat(v.parents); + } + }); + if(r.length) { + p = $.vakata.array_unique(p); + this._search_open(p); + for(i = 0, j = r.length; i < j; i++) { + f = this.get_node(r[i], true); + if(f) { + this._data.search.dom = this._data.search.dom.add(f); + } + } + this._data.search.res = r; + this._data.search.dom.children(".jstree-anchor").addClass('jstree-search'); + } + /** + * triggered after search is complete + * @event + * @name search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes + * @param {String} str the search string + * @param {Array} res a collection of objects represeing the matching nodes + * @plugin search + */ + this.trigger('search', { nodes : this._data.search.dom, str : str, res : this._data.search.res }); + }; + /** + * used to clear the last search (removes classes and shows all nodes if filtering is on) + * @name clear_search() + * @plugin search + * @trigger clear_search.jstree + */ + this.clear_search = function () { + this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search"); + if(this.settings.search.close_opened_onclear) { + this.close_node(this._data.search.opn, 0); + } + /** + * triggered after search is complete + * @event + * @name clear_search.jstree + * @param {jQuery} nodes a jQuery collection of matching nodes (the result from the last search) + * @param {String} str the search string (the last search string) + * @param {Array} res a collection of objects represeing the matching nodes (the result from the last search) + * @plugin search + */ + this.trigger('clear_search', { 'nodes' : this._data.search.dom, str : this._data.search.str, res : this._data.search.res }); + this._data.search.str = ""; + this._data.search.res = []; + this._data.search.opn = []; + this._data.search.dom = $(); + }; + /** + * opens nodes that need to be opened to reveal the search results. Used only internally. + * @private + * @name _search_open(d) + * @param {Array} d an array of node IDs + * @plugin search + */ + this._search_open = function (d) { + var t = this; + $.each(d.concat([]), function (i, v) { + v = document.getElementById(v); + if(v) { + if(t.is_closed(v)) { + t._data.search.opn.push(v.id); + t.open_node(v, function () { t._search_open(d); }, 0); + } + } + }); + }; + /** + * loads nodes that need to be opened to reveal the search results. Used only internally. + * @private + * @name _search_load(d, str) + * @param {String} str the search string + * @plugin search + */ + this._search_load = function (str) { + var res = true, + t = this, + m = t._model.data; + if($.isArray(this._data.search.sln)) { + if(!this._data.search.sln.length) { + this._data.search.sln = null; + this.search(str, true); + } + else { + $.each(this._data.search.sln, function (i, v) { + if(m[v]) { + $.vakata.array_remove_item(t._data.search.sln, v); + if(!m[v].state.loaded) { + t.load_node(v, function (o, s) { if(s) { t._search_load(str); } }); + res = false; + } + } + }); + if(res) { + this._data.search.sln = []; + this._search_load(str); + } + } + } + }; + }; + + // helpers + (function ($) { + // from http://kiro.me/projects/fuse.html + $.vakata.search = function(pattern, txt, options) { + options = options || {}; + if(options.fuzzy !== false) { + options.fuzzy = true; + } + pattern = options.caseSensitive ? pattern : pattern.toLowerCase(); + var MATCH_LOCATION = options.location || 0, + MATCH_DISTANCE = options.distance || 100, + MATCH_THRESHOLD = options.threshold || 0.6, + patternLen = pattern.length, + matchmask, pattern_alphabet, match_bitapScore, search; + if(patternLen > 32) { + options.fuzzy = false; + } + if(options.fuzzy) { + matchmask = 1 << (patternLen - 1); + pattern_alphabet = (function () { + var mask = {}, + i = 0; + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] = 0; + } + for (i = 0; i < patternLen; i++) { + mask[pattern.charAt(i)] |= 1 << (patternLen - i - 1); + } + return mask; + }()); + match_bitapScore = function (e, x) { + var accuracy = e / patternLen, + proximity = Math.abs(MATCH_LOCATION - x); + if(!MATCH_DISTANCE) { + return proximity ? 1.0 : accuracy; + } + return accuracy + (proximity / MATCH_DISTANCE); + }; + } + search = function (text) { + text = options.caseSensitive ? text : text.toLowerCase(); + if(pattern === text || text.indexOf(pattern) !== -1) { + return { + isMatch: true, + score: 0 + }; + } + if(!options.fuzzy) { + return { + isMatch: false, + score: 1 + }; + } + var i, j, + textLen = text.length, + scoreThreshold = MATCH_THRESHOLD, + bestLoc = text.indexOf(pattern, MATCH_LOCATION), + binMin, binMid, + binMax = patternLen + textLen, + lastRd, start, finish, rd, charMatch, + score = 1, + locations = []; + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + bestLoc = text.lastIndexOf(pattern, MATCH_LOCATION + patternLen); + if (bestLoc !== -1) { + scoreThreshold = Math.min(match_bitapScore(0, bestLoc), scoreThreshold); + } + } + bestLoc = -1; + for (i = 0; i < patternLen; i++) { + binMin = 0; + binMid = binMax; + while (binMin < binMid) { + if (match_bitapScore(i, MATCH_LOCATION + binMid) <= scoreThreshold) { + binMin = binMid; + } else { + binMax = binMid; + } + binMid = Math.floor((binMax - binMin) / 2 + binMin); + } + binMax = binMid; + start = Math.max(1, MATCH_LOCATION - binMid + 1); + finish = Math.min(MATCH_LOCATION + binMid, textLen) + patternLen; + rd = new Array(finish + 2); + rd[finish + 1] = (1 << i) - 1; + for (j = finish; j >= start; j--) { + charMatch = pattern_alphabet[text.charAt(j - 1)]; + if (i === 0) { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; + } else { + rd[j] = ((rd[j + 1] << 1) | 1) & charMatch | (((lastRd[j + 1] | lastRd[j]) << 1) | 1) | lastRd[j + 1]; + } + if (rd[j] & matchmask) { + score = match_bitapScore(i, j - 1); + if (score <= scoreThreshold) { + scoreThreshold = score; + bestLoc = j - 1; + locations.push(bestLoc); + if (bestLoc > MATCH_LOCATION) { + start = Math.max(1, 2 * MATCH_LOCATION - bestLoc); + } else { + break; + } + } + } + } + if (match_bitapScore(i + 1, MATCH_LOCATION) > scoreThreshold) { + break; + } + lastRd = rd; + } + return { + isMatch: bestLoc >= 0, + score: score + }; + }; + return txt === true ? { 'search' : search } : search(txt); + }; + }(jQuery)); + + // include the search plugin by default + // $.jstree.defaults.plugins.push("search"); + +/** + * ### Sort plugin + * + * Autmatically sorts all siblings in the tree according to a sorting function. + */ + + /** + * the settings function used to sort the nodes. + * It is executed in the tree's context, accepts two nodes as arguments and should return `1` or `-1`. + * @name $.jstree.defaults.sort + * @plugin sort + */ + $.jstree.defaults.sort = function (a, b) { + //return this.get_type(a) === this.get_type(b) ? (this.get_text(a) > this.get_text(b) ? 1 : -1) : this.get_type(a) >= this.get_type(b); + return this.get_text(a) > this.get_text(b) ? 1 : -1; + }; + $.jstree.plugins.sort = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + this.element + .on("model.jstree", $.proxy(function (e, data) { + this.sort(data.parent, true); + }, this)) + .on("rename_node.jstree create_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent || data.node.parent, false); + this.redraw_node(data.parent || data.node.parent, true); + }, this)) + .on("move_node.jstree copy_node.jstree", $.proxy(function (e, data) { + this.sort(data.parent, false); + this.redraw_node(data.parent, true); + }, this)); + }; + /** + * used to sort a node's children + * @private + * @name sort(obj [, deep]) + * @param {mixed} obj the node + * @param {Boolean} deep if set to `true` nodes are sorted recursively. + * @plugin sort + * @trigger search.jstree + */ + this.sort = function (obj, deep) { + var i, j; + obj = this.get_node(obj); + if(obj && obj.children && obj.children.length) { + obj.children.sort($.proxy(this.settings.sort, this)); + if(deep) { + for(i = 0, j = obj.children_d.length; i < j; i++) { + this.sort(obj.children_d[i], false); + } + } + } + }; + }; + + // include the sort plugin by default + // $.jstree.defaults.plugins.push("sort"); + +/** + * ### State plugin + * + * Saves the state of the tree (selected nodes, opened nodes) on the user's computer using available options (localStorage, cookies, etc) + */ + + var to = false; + /** + * stores all defaults for the state plugin + * @name $.jstree.defaults.state + * @plugin state + */ + $.jstree.defaults.state = { + /** + * A string for the key to use when saving the current tree (change if using multiple trees in your project). Defaults to `jstree`. + * @name $.jstree.defaults.state.key + * @plugin state + */ + key : 'jstree', + /** + * A space separated list of events that trigger a state save. Defaults to `changed.jstree open_node.jstree close_node.jstree`. + * @name $.jstree.defaults.state.events + * @plugin state + */ + events : 'changed.jstree open_node.jstree close_node.jstree', + /** + * Time in milliseconds after which the state will expire. Defaults to 'false' meaning - no expire. + * @name $.jstree.defaults.state.ttl + * @plugin state + */ + ttl : false, + /** + * A function that will be executed prior to restoring state with one argument - the state object. Can be used to clear unwanted parts of the state. + * @name $.jstree.defaults.state.filter + * @plugin state + */ + filter : false + }; + $.jstree.plugins.state = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + var bind = $.proxy(function () { + this.element.on(this.settings.state.events, $.proxy(function () { + if(to) { clearTimeout(to); } + to = setTimeout($.proxy(function () { this.save_state(); }, this), 100); + }, this)); + }, this); + this.element + .on("ready.jstree", $.proxy(function (e, data) { + this.element.one("restore_state.jstree", bind); + if(!this.restore_state()) { bind(); } + }, this)); + }; + /** + * save the state + * @name save_state() + * @plugin state + */ + this.save_state = function () { + var st = { 'state' : this.get_state(), 'ttl' : this.settings.state.ttl, 'sec' : +(new Date()) }; + $.vakata.storage.set(this.settings.state.key, JSON.stringify(st)); + }; + /** + * restore the state from the user's computer + * @name restore_state() + * @plugin state + */ + this.restore_state = function () { + var k = $.vakata.storage.get(this.settings.state.key); + if(!!k) { try { k = JSON.parse(k); } catch(ex) { return false; } } + if(!!k && k.ttl && k.sec && +(new Date()) - k.sec > k.ttl) { return false; } + if(!!k && k.state) { k = k.state; } + if(!!k && $.isFunction(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); } + if(!!k) { + this.element.one("set_state.jstree", function (e, data) { data.instance.trigger('restore_state', { 'state' : $.extend(true, {}, k) }); }); + this.set_state(k); + return true; + } + return false; + }; + /** + * clear the state on the user's computer + * @name clear_state() + * @plugin state + */ + this.clear_state = function () { + return $.vakata.storage.del(this.settings.state.key); + }; + }; + + (function ($, undefined) { + $.vakata.storage = { + // simply specifying the functions in FF throws an error + set : function (key, val) { return window.localStorage.setItem(key, val); }, + get : function (key) { return window.localStorage.getItem(key); }, + del : function (key) { return window.localStorage.removeItem(key); } + }; + }(jQuery)); + + // include the state plugin by default + // $.jstree.defaults.plugins.push("state"); + +/** + * ### Types plugin + * + * Makes it possible to add predefined types for groups of nodes, which make it possible to easily control nesting rules and icon for each group. + */ + + /** + * An object storing all types as key value pairs, where the key is the type name and the value is an object that could contain following keys (all optional). + * + * * `max_children` the maximum number of immediate children this node type can have. Do not specify or set to `-1` for unlimited. + * * `max_depth` the maximum number of nesting this node type can have. A value of `1` would mean that the node can have children, but no grandchildren. Do not specify or set to `-1` for unlimited. + * * `valid_children` an array of node type strings, that nodes of this type can have as children. Do not specify or set to `-1` for no limits. + * * `icon` a string - can be a path to an icon or a className, if using an image that is in the current directory use a `./` prefix, otherwise it will be detected as a class. Omit to use the default icon from your theme. + * + * There are two predefined types: + * + * * `#` represents the root of the tree, for example `max_children` would control the maximum number of root nodes. + * * `default` represents the default node - any settings here will be applied to all nodes that do not have a type specified. + * + * @name $.jstree.defaults.types + * @plugin types + */ + $.jstree.defaults.types = { + '#' : {}, + 'default' : {} + }; + + $.jstree.plugins.types = function (options, parent) { + this.init = function (el, options) { + var i, j; + if(options && options.types && options.types['default']) { + for(i in options.types) { + if(i !== "default" && i !== "#" && options.types.hasOwnProperty(i)) { + for(j in options.types['default']) { + if(options.types['default'].hasOwnProperty(j) && options.types[i][j] === undefined) { + options.types[i][j] = options.types['default'][j]; + } + } + } + } + } + parent.init.call(this, el, options); + this._model.data['#'].type = '#'; + }; + this.bind = function () { + parent.bind.call(this); + this.element + .on('model.jstree', $.proxy(function (e, data) { + var m = this._model.data, + dpc = data.nodes, + t = this.settings.types, + i, j, c = 'default'; + for(i = 0, j = dpc.length; i < j; i++) { + c = 'default'; + if(m[dpc[i]].original && m[dpc[i]].original.type && t[m[dpc[i]].original.type]) { + c = m[dpc[i]].original.type; + } + if(m[dpc[i]].data && m[dpc[i]].data.jstree && m[dpc[i]].data.jstree.type && t[m[dpc[i]].data.jstree.type]) { + c = m[dpc[i]].data.jstree.type; + } + m[dpc[i]].type = c; + if(m[dpc[i]].icon === true && t[c].icon !== undefined) { + m[dpc[i]].icon = t[c].icon; + } + } + }, this)); + }; + this.get_json = function (obj, options, flat) { + var i, j, + m = this._model.data, + opt = options ? $.extend(true, {}, options, {no_id:false}) : {}, + tmp = parent.get_json.call(this, obj, opt, flat); + if(tmp === false) { return false; } + if($.isArray(tmp)) { + for(i = 0, j = tmp.length; i < j; i++) { + tmp[i].type = tmp[i].id && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default"; + if(options && options.no_id) { + delete tmp[i].id; + if(tmp[i].li_attr && tmp[i].li_attr.id) { + delete tmp[i].li_attr.id; + } + } + } + } + else { + tmp.type = tmp.id && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default"; + if(options && options.no_id) { + tmp = this._delete_ids(tmp); + } + } + return tmp; + }; + this._delete_ids = function (tmp) { + if($.isArray(tmp)) { + for(var i = 0, j = tmp.length; i < j; i++) { + tmp[i] = this._delete_ids(tmp[i]); + } + return tmp; + } + delete tmp.id; + if(tmp.li_attr && tmp.li_attr.id) { + delete tmp.li_attr.id; + } + if(tmp.children && $.isArray(tmp.children)) { + tmp.children = this._delete_ids(tmp.children); + } + return tmp; + }; + this.check = function (chk, obj, par, pos) { + if(parent.check.call(this, chk, obj, par, pos) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + var m = obj && obj.id ? $.jstree.reference(obj.id) : null, tmp, d, i, j; + m = m && m._model && m._model.data ? m._model.data : null; + switch(chk) { + case "create_node": + case "move_node": + case "copy_node": + if(chk !== 'move_node' || $.inArray(obj.id, par.children) === -1) { + tmp = this.get_rules(par); + if(tmp.max_children !== undefined && tmp.max_children !== -1 && tmp.max_children === par.children.length) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(tmp.valid_children !== undefined && tmp.valid_children !== -1 && $.inArray(obj.type, tmp.valid_children) === -1) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + if(m && obj.children_d && obj.parents) { + d = 0; + for(i = 0, j = obj.children_d.length; i < j; i++) { + d = Math.max(d, m[obj.children_d[i]].parents.length); + } + d = d - obj.parents.length + 1; + } + if(d <= 0 || d === undefined) { d = 1; } + do { + if(tmp.max_depth !== undefined && tmp.max_depth !== -1 && tmp.max_depth < d) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + return false; + } + par = this.get_node(par.parent); + tmp = this.get_rules(par); + d++; + } while(par); + } + break; + } + return true; + }; + /** + * used to retrieve the type settings object for a node + * @name get_rules(obj) + * @param {mixed} obj the node to find the rules for + * @return {Object} + * @plugin types + */ + this.get_rules = function (obj) { + obj = this.get_node(obj); + if(!obj) { return false; } + var tmp = this.get_type(obj, true); + if(tmp.max_depth === undefined) { tmp.max_depth = -1; } + if(tmp.max_children === undefined) { tmp.max_children = -1; } + if(tmp.valid_children === undefined) { tmp.valid_children = -1; } + return tmp; + }; + /** + * used to retrieve the type string or settings object for a node + * @name get_type(obj [, rules]) + * @param {mixed} obj the node to find the rules for + * @param {Boolean} rules if set to `true` instead of a string the settings object will be returned + * @return {String|Object} + * @plugin types + */ + this.get_type = function (obj, rules) { + obj = this.get_node(obj); + return (!obj) ? false : ( rules ? $.extend({ 'type' : obj.type }, this.settings.types[obj.type]) : obj.type); + }; + /** + * used to change a node's type + * @name set_type(obj, type) + * @param {mixed} obj the node to change + * @param {String} type the new type + * @plugin types + */ + this.set_type = function (obj, type) { + var t, t1, t2, old_type, old_icon; + if($.isArray(obj)) { + obj = obj.slice(); + for(t1 = 0, t2 = obj.length; t1 < t2; t1++) { + this.set_type(obj[t1], type); + } + return true; + } + t = this.settings.types; + obj = this.get_node(obj); + if(!t[type] || !obj) { return false; } + old_type = obj.type; + old_icon = this.get_icon(obj); + obj.type = type; + if(old_icon === true || (t[old_type] && t[old_type].icon && old_icon === t[old_type].icon)) { + this.set_icon(obj, t[type].icon !== undefined ? t[type].icon : true); + } + return true; + }; + }; + // include the types plugin by default + // $.jstree.defaults.plugins.push("types"); + +/** + * ### Unique plugin + * + * Enforces that no nodes with the same name can coexist as siblings. + */ + + $.jstree.plugins.unique = function (options, parent) { + this.check = function (chk, obj, par, pos) { + if(parent.check.call(this, chk, obj, par, pos) === false) { return false; } + obj = obj && obj.id ? obj : this.get_node(obj); + par = par && par.id ? par : this.get_node(par); + if(!par || !par.children) { return true; } + var n = chk === "rename_node" ? pos : obj.text, + c = [], + m = this._model.data, i, j; + for(i = 0, j = par.children.length; i < j; i++) { + c.push(m[par.children[i]].text); + } + switch(chk) { + case "delete_node": + return true; + case "rename_node": + case "copy_node": + i = ($.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + case "move_node": + i = (obj.parent === par.id || $.inArray(n, c) === -1); + if(!i) { + this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) }; + } + return i; + } + return true; + }; + }; + + // include the unique plugin by default + // $.jstree.defaults.plugins.push("unique"); + + +/** + * ### Wholerow plugin + * + * Makes each node appear block level. Making selection easier. May cause slow down for large trees in old browsers. + */ + + var div = document.createElement('DIV'); + div.setAttribute('unselectable','on'); + div.className = 'jstree-wholerow'; + div.innerHTML = ' '; + $.jstree.plugins.wholerow = function (options, parent) { + this.bind = function () { + parent.bind.call(this); + + this.element + .on('loading', $.proxy(function () { + div.style.height = this._data.core.li_height + 'px'; + }, this)) + .on('ready.jstree set_state.jstree', $.proxy(function () { + this.hide_dots(); + }, this)) + .on("ready.jstree", $.proxy(function () { + this.get_container_ul().addClass('jstree-wholerow-ul'); + }, this)) + .on("deselect_all.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + }, this)) + .on("changed.jstree", $.proxy(function (e, data) { + this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked'); + var tmp = false, i, j; + for(i = 0, j = data.selected.length; i < j; i++) { + tmp = this.get_node(data.selected[i], true); + if(tmp && tmp.length) { + tmp.children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + } + } + }, this)) + .on("open_node.jstree", $.proxy(function (e, data) { + this.get_node(data.node, true).find('.jstree-clicked').parent().children('.jstree-wholerow').addClass('jstree-wholerow-clicked'); + }, this)) + .on("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) { + this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered'); + }, this)) + .on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) { + e.preventDefault(); + $(e.currentTarget).closest("li").children("a:eq(0)").trigger('contextmenu',e); + }, this)) + .on("click.jstree", ".jstree-wholerow", function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest("li").children("a:eq(0)").trigger(tmp).focus(); + }) + .on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) { + e.stopImmediatePropagation(); + var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey }); + $(e.currentTarget).closest("li").children("a:eq(0)").trigger(tmp).focus(); + }, this)) + .on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", $.proxy(function (e) { + e.stopImmediatePropagation(); + this.hover_node(e.currentTarget); + return false; + }, this)) + .on("mouseleave.jstree", ".jstree-node", $.proxy(function (e) { + this.dehover_node(e.currentTarget); + }, this)); + }; + this.teardown = function () { + if(this.settings.wholerow) { + this.element.find(".jstree-wholerow").remove(); + } + parent.teardown.call(this); + }; + this.redraw_node = function(obj, deep, callback) { + obj = parent.redraw_node.call(this, obj, deep, callback); + if(obj) { + var tmp = div.cloneNode(true); + //tmp.style.height = this._data.core.li_height + 'px'; + if($.inArray(obj.id, this._data.core.selected) !== -1) { tmp.className += ' jstree-wholerow-clicked'; } + obj.insertBefore(tmp, obj.childNodes[0]); + } + return obj; + }; + }; + // include the wholerow plugin by default + // $.jstree.defaults.plugins.push("wholerow"); + +})); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJqc3RyZWUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLypnbG9iYWxzIGpRdWVyeSwgZGVmaW5lLCBleHBvcnRzLCByZXF1aXJlLCB3aW5kb3csIGRvY3VtZW50ICovXHJcbihmdW5jdGlvbiAoZmFjdG9yeSkge1xyXG5cdFwidXNlIHN0cmljdFwiO1xyXG5cdGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcclxuXHRcdGRlZmluZShbJ2pxdWVyeSddLCBmYWN0b3J5KTtcclxuXHR9XHJcblx0ZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpIHtcclxuXHRcdGZhY3RvcnkocmVxdWlyZSgnanF1ZXJ5JykpO1xyXG5cdH1cclxuXHRlbHNlIHtcclxuXHRcdGZhY3RvcnkoalF1ZXJ5KTtcclxuXHR9XHJcbn0oZnVuY3Rpb24gKCQsIHVuZGVmaW5lZCkge1xyXG5cdFwidXNlIHN0cmljdFwiO1xyXG4vKiFcclxuICoganNUcmVlIDMuMC4wXHJcbiAqIGh0dHA6Ly9qc3RyZWUuY29tL1xyXG4gKlxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTMgSXZhbiBCb3poYW5vdiAoaHR0cDovL3Zha2F0YS5jb20pXHJcbiAqXHJcbiAqIExpY2Vuc2VkIHNhbWUgYXMganF1ZXJ5IC0gdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNSVQgTGljZW5zZVxyXG4gKiAgIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXHJcbiAqL1xyXG4vKiFcclxuICogaWYgdXNpbmcganNsaW50IHBsZWFzZSBhbGxvdyBmb3IgdGhlIGpRdWVyeSBnbG9iYWwgYW5kIHVzZSBmb2xsb3dpbmcgb3B0aW9uczogXHJcbiAqIGpzbGludDogYnJvd3NlcjogdHJ1ZSwgYXNzOiB0cnVlLCBiaXR3aXNlOiB0cnVlLCBjb250aW51ZTogdHJ1ZSwgbm9tZW46IHRydWUsIHBsdXNwbHVzOiB0cnVlLCByZWdleHA6IHRydWUsIHVucGFyYW06IHRydWUsIHRvZG86IHRydWUsIHdoaXRlOiB0cnVlXHJcbiAqL1xyXG5cclxuXHQvLyBwcmV2ZW50IGFub3RoZXIgbG9hZD8gbWF5YmUgdGhlcmUgaXMgYSBiZXR0ZXIgd2F5P1xyXG5cdGlmKCQuanN0cmVlKSB7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiAjIyMganNUcmVlIGNvcmUgZnVuY3Rpb25hbGl0eVxyXG5cdCAqL1xyXG5cclxuXHQvLyBpbnRlcm5hbCB2YXJpYWJsZXNcclxuXHR2YXIgaW5zdGFuY2VfY291bnRlciA9IDAsXHJcblx0XHRjY3Bfbm9kZSA9IGZhbHNlLFxyXG5cdFx0Y2NwX21vZGUgPSBmYWxzZSxcclxuXHRcdGNjcF9pbnN0ID0gZmFsc2UsXHJcblx0XHR0aGVtZXNfbG9hZGVkID0gW10sXHJcblx0XHRzcmMgPSAkKCdzY3JpcHQ6bGFzdCcpLmF0dHIoJ3NyYycpLFxyXG5cdFx0X2QgPSBkb2N1bWVudCwgX25vZGUgPSBfZC5jcmVhdGVFbGVtZW50KCdMSScpLCBfdGVtcDEsIF90ZW1wMjtcclxuXHJcblx0X25vZGUuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3RyZWVpdGVtJyk7XHJcblx0X3RlbXAxID0gX2QuY3JlYXRlRWxlbWVudCgnSScpO1xyXG5cdF90ZW1wMS5jbGFzc05hbWUgPSAnanN0cmVlLWljb24ganN0cmVlLW9jbCc7XHJcblx0X25vZGUuYXBwZW5kQ2hpbGQoX3RlbXAxKTtcclxuXHRfdGVtcDEgPSBfZC5jcmVhdGVFbGVtZW50KCdBJyk7XHJcblx0X3RlbXAxLmNsYXNzTmFtZSA9ICdqc3RyZWUtYW5jaG9yJztcclxuXHRfdGVtcDEuc2V0QXR0cmlidXRlKCdocmVmJywnIycpO1xyXG5cdF90ZW1wMiA9IF9kLmNyZWF0ZUVsZW1lbnQoJ0knKTtcclxuXHRfdGVtcDIuY2xhc3NOYW1lID0gJ2pzdHJlZS1pY29uIGpzdHJlZS10aGVtZWljb24nO1xyXG5cdF90ZW1wMS5hcHBlbmRDaGlsZChfdGVtcDIpO1xyXG5cdF9ub2RlLmFwcGVuZENoaWxkKF90ZW1wMSk7XHJcblx0X3RlbXAxID0gX3RlbXAyID0gbnVsbDtcclxuXHJcblxyXG5cdC8qKlxyXG5cdCAqIGhvbGRzIGFsbCBqc3RyZWUgcmVsYXRlZCBmdW5jdGlvbnMgYW5kIHZhcmlhYmxlcywgaW5jbHVkaW5nIHRoZSBhY3R1YWwgY2xhc3MgYW5kIG1ldGhvZHMgdG8gY3JlYXRlLCBhY2Nlc3MgYW5kIG1hbmlwdWxhdGUgaW5zdGFuY2VzLlxyXG5cdCAqIEBuYW1lICQuanN0cmVlXHJcblx0ICovXHJcblx0JC5qc3RyZWUgPSB7XHJcblx0XHQvKiogXHJcblx0XHQgKiBzcGVjaWZpZXMgdGhlIGpzdHJlZSB2ZXJzaW9uIGluIHVzZVxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUudmVyc2lvblxyXG5cdFx0ICovXHJcblx0XHR2ZXJzaW9uIDogJzMuMC4wLWJldGE5JyxcclxuXHRcdC8qKlxyXG5cdFx0ICogaG9sZHMgYWxsIHRoZSBkZWZhdWx0IG9wdGlvbnMgdXNlZCB3aGVuIGNyZWF0aW5nIG5ldyBpbnN0YW5jZXNcclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzXHJcblx0XHQgKi9cclxuXHRcdGRlZmF1bHRzIDoge1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogY29uZmlndXJlIHdoaWNoIHBsdWdpbnMgd2lsbCBiZSBhY3RpdmUgb24gYW4gaW5zdGFuY2UuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBzdHJpbmdzLCB3aGVyZSBlYWNoIGVsZW1lbnQgaXMgYSBwbHVnaW4gbmFtZS4gVGhlIGRlZmF1bHQgaXMgYFtdYFxyXG5cdFx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5wbHVnaW5zXHJcblx0XHRcdCAqL1xyXG5cdFx0XHRwbHVnaW5zIDogW11cclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHN0b3JlcyBhbGwgbG9hZGVkIGpzdHJlZSBwbHVnaW5zICh1c2VkIGludGVybmFsbHkpXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5wbHVnaW5zXHJcblx0XHQgKi9cclxuXHRcdHBsdWdpbnMgOiB7fSxcclxuXHRcdHBhdGggOiBzcmMgJiYgc3JjLmluZGV4T2YoJy8nKSAhPT0gLTEgPyBzcmMucmVwbGFjZSgvXFwvW15cXC9dKyQvLCcnKSA6ICcnXHJcblx0fTtcclxuXHQvKipcclxuXHQgKiBjcmVhdGVzIGEganN0cmVlIGluc3RhbmNlXHJcblx0ICogQG5hbWUgJC5qc3RyZWUuY3JlYXRlKGVsIFssIG9wdGlvbnNdKVxyXG5cdCAqIEBwYXJhbSB7RE9NRWxlbWVudHxqUXVlcnl8U3RyaW5nfSBlbCB0aGUgZWxlbWVudCB0byBjcmVhdGUgdGhlIGluc3RhbmNlIG9uLCBjYW4gYmUgalF1ZXJ5IGV4dGVuZGVkIG9yIGEgc2VsZWN0b3JcclxuXHQgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyBvcHRpb25zIGZvciB0aGlzIGluc3RhbmNlIChleHRlbmRzIGAkLmpzdHJlZS5kZWZhdWx0c2ApXHJcblx0ICogQHJldHVybiB7anNUcmVlfSB0aGUgbmV3IGluc3RhbmNlXHJcblx0ICovXHJcblx0JC5qc3RyZWUuY3JlYXRlID0gZnVuY3Rpb24gKGVsLCBvcHRpb25zKSB7XHJcblx0XHR2YXIgdG1wID0gbmV3ICQuanN0cmVlLmNvcmUoKytpbnN0YW5jZV9jb3VudGVyKSxcclxuXHRcdFx0b3B0ID0gb3B0aW9ucztcclxuXHRcdG9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgJC5qc3RyZWUuZGVmYXVsdHMsIG9wdGlvbnMpO1xyXG5cdFx0aWYob3B0ICYmIG9wdC5wbHVnaW5zKSB7XHJcblx0XHRcdG9wdGlvbnMucGx1Z2lucyA9IG9wdC5wbHVnaW5zO1xyXG5cdFx0fVxyXG5cdFx0JC5lYWNoKG9wdGlvbnMucGx1Z2lucywgZnVuY3Rpb24gKGksIGspIHtcclxuXHRcdFx0aWYoaSAhPT0gJ2NvcmUnKSB7XHJcblx0XHRcdFx0dG1wID0gdG1wLnBsdWdpbihrLCBvcHRpb25zW2tdKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0XHR0bXAuaW5pdChlbCwgb3B0aW9ucyk7XHJcblx0XHRyZXR1cm4gdG1wO1xyXG5cdH07XHJcblx0LyoqXHJcblx0ICogdGhlIGpzdHJlZSBjbGFzcyBjb25zdHJ1Y3RvciwgdXNlZCBvbmx5IGludGVybmFsbHlcclxuXHQgKiBAcHJpdmF0ZVxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmNvcmUoaWQpXHJcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGlkIHRoaXMgaW5zdGFuY2UncyBpbmRleFxyXG5cdCAqL1xyXG5cdCQuanN0cmVlLmNvcmUgPSBmdW5jdGlvbiAoaWQpIHtcclxuXHRcdHRoaXMuX2lkID0gaWQ7XHJcblx0XHR0aGlzLl9jbnQgPSAwO1xyXG5cdFx0dGhpcy5fZGF0YSA9IHtcclxuXHRcdFx0Y29yZSA6IHtcclxuXHRcdFx0XHR0aGVtZXMgOiB7XHJcblx0XHRcdFx0XHRuYW1lIDogZmFsc2UsXHJcblx0XHRcdFx0XHRkb3RzIDogZmFsc2UsXHJcblx0XHRcdFx0XHRpY29ucyA6IGZhbHNlXHJcblx0XHRcdFx0fSxcclxuXHRcdFx0XHRzZWxlY3RlZCA6IFtdLFxyXG5cdFx0XHRcdGxhc3RfZXJyb3IgOiB7fVxyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdH07XHJcblx0LyoqXHJcblx0ICogZ2V0IGEgcmVmZXJlbmNlIHRvIGFuIGV4aXN0aW5nIGluc3RhbmNlXHJcblx0ICpcclxuXHQgKiBfX0V4YW1wbGVzX19cclxuXHQgKlxyXG5cdCAqXHQvLyBwcm92aWRlZCBhIGNvbnRhaW5lciB3aXRoIGFuIElEIG9mIFwidHJlZVwiLCBhbmQgYSBuZXN0ZWQgbm9kZSB3aXRoIGFuIElEIG9mIFwiYnJhbmNoXCJcclxuXHQgKlx0Ly8gYWxsIG9mIHRoZXJlIHdpbGwgcmV0dXJuIHRoZSBzYW1lIGluc3RhbmNlXHJcblx0ICpcdCQuanN0cmVlLnJlZmVyZW5jZSgndHJlZScpO1xyXG5cdCAqXHQkLmpzdHJlZS5yZWZlcmVuY2UoJyN0cmVlJyk7XHJcblx0ICpcdCQuanN0cmVlLnJlZmVyZW5jZSgkKCcjdHJlZScpKTtcclxuXHQgKlx0JC5qc3RyZWUucmVmZXJlbmNlKGRvY3VtZW50LmdldEVsZW1lbnRCeUlEKCd0cmVlJykpO1xyXG5cdCAqXHQkLmpzdHJlZS5yZWZlcmVuY2UoJ2JyYW5jaCcpO1xyXG5cdCAqXHQkLmpzdHJlZS5yZWZlcmVuY2UoJyNicmFuY2gnKTtcclxuXHQgKlx0JC5qc3RyZWUucmVmZXJlbmNlKCQoJyNicmFuY2gnKSk7XHJcblx0ICpcdCQuanN0cmVlLnJlZmVyZW5jZShkb2N1bWVudC5nZXRFbGVtZW50QnlJRCgnYnJhbmNoJykpO1xyXG5cdCAqXHJcblx0ICogQG5hbWUgJC5qc3RyZWUucmVmZXJlbmNlKG5lZWRsZSlcclxuXHQgKiBAcGFyYW0ge0RPTUVsZW1lbnR8alF1ZXJ5fFN0cmluZ30gbmVlZGxlXHJcblx0ICogQHJldHVybiB7anNUcmVlfG51bGx9IHRoZSBpbnN0YW5jZSBvciBgbnVsbGAgaWYgbm90IGZvdW5kXHJcblx0ICovXHJcblx0JC5qc3RyZWUucmVmZXJlbmNlID0gZnVuY3Rpb24gKG5lZWRsZSkge1xyXG5cdFx0aWYobmVlZGxlICYmICEkKG5lZWRsZSkubGVuZ3RoKSB7XHJcblx0XHRcdGlmKG5lZWRsZS5pZCkge1xyXG5cdFx0XHRcdG5lZWRsZSA9IG5lZWRsZS5pZDtcclxuXHRcdFx0fVxyXG5cdFx0XHR2YXIgdG1wID0gbnVsbDtcclxuXHRcdFx0JCgnLmpzdHJlZScpLmVhY2goZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdHZhciBpbnN0ID0gJCh0aGlzKS5kYXRhKCdqc3RyZWUnKTtcclxuXHRcdFx0XHRpZihpbnN0ICYmIGluc3QuX21vZGVsLmRhdGFbbmVlZGxlXSkge1xyXG5cdFx0XHRcdFx0dG1wID0gaW5zdDtcclxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0XHRyZXR1cm4gdG1wO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuICQobmVlZGxlKS5jbG9zZXN0KCcuanN0cmVlJykuZGF0YSgnanN0cmVlJyk7XHJcblx0fTtcclxuXHQvKipcclxuXHQgKiBDcmVhdGUgYW4gaW5zdGFuY2UsIGdldCBhbiBpbnN0YW5jZSBvciBpbnZva2UgYSBjb21tYW5kIG9uIGEgaW5zdGFuY2UuIFxyXG5cdCAqIFxyXG5cdCAqIElmIHRoZXJlIGlzIG5vIGluc3RhbmNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgY3VycmVudCBub2RlIGEgbmV3IG9uZSBpcyBjcmVhdGVkIGFuZCBgYXJnYCBpcyB1c2VkIHRvIGV4dGVuZCBgJC5qc3RyZWUuZGVmYXVsdHNgIGZvciB0aGlzIG5ldyBpbnN0YW5jZS4gVGhlcmUgd291bGQgYmUgbm8gcmV0dXJuIHZhbHVlIChjaGFpbmluZyBpcyBub3QgYnJva2VuKS5cclxuXHQgKiBcclxuXHQgKiBJZiB0aGVyZSBpcyBhbiBleGlzdGluZyBpbnN0YW5jZSBhbmQgYGFyZ2AgaXMgYSBzdHJpbmcgdGhlIGNvbW1hbmQgc3BlY2lmaWVkIGJ5IGBhcmdgIGlzIGV4ZWN1dGVkIG9uIHRoZSBpbnN0YW5jZSwgd2l0aCBhbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgcGFzc2VkIHRvIHRoZSBmdW5jdGlvbi4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgYSB2YWx1ZSBpdCB3aWxsIGJlIHJldHVybmVkIChjaGFpbmluZyBjb3VsZCBicmVhayBkZXBlbmRpbmcgb24gZnVuY3Rpb24pLlxyXG5cdCAqIFxyXG5cdCAqIElmIHRoZXJlIGlzIGFuIGV4aXN0aW5nIGluc3RhbmNlIGFuZCBgYXJnYCBpcyBub3QgYSBzdHJpbmcgdGhlIGluc3RhbmNlIGl0c2VsZiBpcyByZXR1cm5lZCAoc2ltaWxhciB0byBgJC5qc3RyZWUucmVmZXJlbmNlYCkuXHJcblx0ICogXHJcblx0ICogSW4gYW55IG90aGVyIGNhc2UgLSBub3RoaW5nIGlzIHJldHVybmVkIGFuZCBjaGFpbmluZyBpcyBub3QgYnJva2VuLlxyXG5cdCAqXHJcblx0ICogX19FeGFtcGxlc19fXHJcblx0ICpcclxuXHQgKlx0JCgnI3RyZWUxJykuanN0cmVlKCk7IC8vIGNyZWF0ZXMgYW4gaW5zdGFuY2VcclxuXHQgKlx0JCgnI3RyZWUyJykuanN0cmVlKHsgcGx1Z2lucyA6IFtdIH0pOyAvLyBjcmVhdGUgYW4gaW5zdGFuY2Ugd2l0aCBzb21lIG9wdGlvbnNcclxuXHQgKlx0JCgnI3RyZWUxJykuanN0cmVlKCdvcGVuX25vZGUnLCAnI2JyYW5jaF8xJyk7IC8vIGNhbGwgYSBtZXRob2Qgb24gYW4gZXhpc3RpbmcgaW5zdGFuY2UsIHBhc3NpbmcgYWRkaXRpb25hbCBhcmd1bWVudHNcclxuXHQgKlx0JCgnI3RyZWUyJykuanN0cmVlKCk7IC8vIGdldCBhbiBleGlzdGluZyBpbnN0YW5jZSAob3IgY3JlYXRlIGFuIGluc3RhbmNlKVxyXG5cdCAqXHQkKCcjdHJlZTInKS5qc3RyZWUodHJ1ZSk7IC8vIGdldCBhbiBleGlzdGluZyBpbnN0YW5jZSAod2lsbCBub3QgY3JlYXRlIG5ldyBpbnN0YW5jZSlcclxuXHQgKlx0JCgnI2JyYW5jaF8xJykuanN0cmVlKCkuc2VsZWN0X25vZGUoJyNicmFuY2hfMScpOyAvLyBnZXQgYW4gaW5zdGFuY2UgKHVzaW5nIGEgbmVzdGVkIGVsZW1lbnQgYW5kIGNhbGwgYSBtZXRob2QpXHJcblx0ICpcclxuXHQgKiBAbmFtZSAkKCkuanN0cmVlKFthcmddKVxyXG5cdCAqIEBwYXJhbSB7U3RyaW5nfE9iamVjdH0gYXJnXHJcblx0ICogQHJldHVybiB7TWl4ZWR9XHJcblx0ICovXHJcblx0JC5mbi5qc3RyZWUgPSBmdW5jdGlvbiAoYXJnKSB7XHJcblx0XHQvLyBjaGVjayBmb3Igc3RyaW5nIGFyZ3VtZW50XHJcblx0XHR2YXIgaXNfbWV0aG9kXHQ9ICh0eXBlb2YgYXJnID09PSAnc3RyaW5nJyksXHJcblx0XHRcdGFyZ3NcdFx0PSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG5cdFx0XHRyZXN1bHRcdFx0PSBudWxsO1xyXG5cdFx0dGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0Ly8gZ2V0IHRoZSBpbnN0YW5jZSAoaWYgdGhlcmUgaXMgb25lKSBhbmQgbWV0aG9kIChpZiBpdCBleGlzdHMpXHJcblx0XHRcdHZhciBpbnN0YW5jZSA9ICQuanN0cmVlLnJlZmVyZW5jZSh0aGlzKSxcclxuXHRcdFx0XHRtZXRob2QgPSBpc19tZXRob2QgJiYgaW5zdGFuY2UgPyBpbnN0YW5jZVthcmddIDogbnVsbDtcclxuXHRcdFx0Ly8gaWYgY2FsbGluZyBhIG1ldGhvZCwgYW5kIG1ldGhvZCBpcyBhdmFpbGFibGUgLSBleGVjdXRlIG9uIHRoZSBpbnN0YW5jZVxyXG5cdFx0XHRyZXN1bHQgPSBpc19tZXRob2QgJiYgbWV0aG9kID9cclxuXHRcdFx0XHRtZXRob2QuYXBwbHkoaW5zdGFuY2UsIGFyZ3MpIDpcclxuXHRcdFx0XHRudWxsO1xyXG5cdFx0XHQvLyBpZiB0aGVyZSBpcyBubyBpbnN0YW5jZSBhbmQgbm8gbWV0aG9kIGlzIGJlaW5nIGNhbGxlZCAtIGNyZWF0ZSBvbmVcclxuXHRcdFx0aWYoIWluc3RhbmNlICYmICFpc19tZXRob2QgJiYgKGFyZyA9PT0gdW5kZWZpbmVkIHx8ICQuaXNQbGFpbk9iamVjdChhcmcpKSkge1xyXG5cdFx0XHRcdCQodGhpcykuZGF0YSgnanN0cmVlJywgbmV3ICQuanN0cmVlLmNyZWF0ZSh0aGlzLCBhcmcpKTtcclxuXHRcdFx0fVxyXG5cdFx0XHQvLyBpZiB0aGVyZSBpcyBhbiBpbnN0YW5jZSBhbmQgbm8gbWV0aG9kIGlzIGNhbGxlZCAtIHJldHVybiB0aGUgaW5zdGFuY2VcclxuXHRcdFx0aWYoaW5zdGFuY2UgJiYgIWlzX21ldGhvZCkge1xyXG5cdFx0XHRcdHJlc3VsdCA9IGluc3RhbmNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdC8vIGlmIHRoZXJlIHdhcyBhIG1ldGhvZCBjYWxsIHdoaWNoIHJldHVybmVkIGEgcmVzdWx0IC0gYnJlYWsgYW5kIHJldHVybiB0aGUgdmFsdWVcclxuXHRcdFx0aWYocmVzdWx0ICE9PSBudWxsICYmIHJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHRcdC8vIGlmIHRoZXJlIHdhcyBhIG1ldGhvZCBjYWxsIHdpdGggYSB2YWxpZCByZXR1cm4gdmFsdWUgLSByZXR1cm4gdGhhdCwgb3RoZXJ3aXNlIGNvbnRpbnVlIHRoZSBjaGFpblxyXG5cdFx0cmV0dXJuIHJlc3VsdCAhPT0gbnVsbCAmJiByZXN1bHQgIT09IHVuZGVmaW5lZCA/XHJcblx0XHRcdHJlc3VsdCA6IHRoaXM7XHJcblx0fTtcclxuXHQvKipcclxuXHQgKiB1c2VkIHRvIGZpbmQgZWxlbWVudHMgY29udGFpbmluZyBhbiBpbnN0YW5jZVxyXG5cdCAqXHJcblx0ICogX19FeGFtcGxlc19fXHJcblx0ICpcclxuXHQgKlx0JCgnZGl2OmpzdHJlZScpLmVhY2goZnVuY3Rpb24gKCkge1xyXG5cdCAqXHRcdCQodGhpcykuanN0cmVlKCdkZXN0cm95Jyk7XHJcblx0ICpcdH0pO1xyXG5cdCAqXHJcblx0ICogQG5hbWUgJCgnOmpzdHJlZScpXHJcblx0ICogQHJldHVybiB7alF1ZXJ5fVxyXG5cdCAqL1xyXG5cdCQuZXhwclsnOiddLmpzdHJlZSA9ICQuZXhwci5jcmVhdGVQc2V1ZG8oZnVuY3Rpb24oc2VhcmNoKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24oYSkge1xyXG5cdFx0XHRyZXR1cm4gJChhKS5oYXNDbGFzcygnanN0cmVlJykgJiZcclxuXHRcdFx0XHQkKGEpLmRhdGEoJ2pzdHJlZScpICE9PSB1bmRlZmluZWQ7XHJcblx0XHR9O1xyXG5cdH0pO1xyXG5cclxuXHQvKipcclxuXHQgKiBzdG9yZXMgYWxsIGRlZmF1bHRzIGZvciB0aGUgY29yZVxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmVcclxuXHQgKi9cclxuXHQkLmpzdHJlZS5kZWZhdWx0cy5jb3JlID0ge1xyXG5cdFx0LyoqXHJcblx0XHQgKiBkYXRhIGNvbmZpZ3VyYXRpb25cclxuXHRcdCAqIFxyXG5cdFx0ICogSWYgbGVmdCBhcyBgZmFsc2VgIHRoZSBIVE1MIGluc2lkZSB0aGUganN0cmVlIGNvbnRhaW5lciBlbGVtZW50IGlzIHVzZWQgdG8gcG9wdWxhdGUgdGhlIHRyZWUgKHRoYXQgc2hvdWxkIGJlIGFuIHVub3JkZXJlZCBsaXN0IHdpdGggbGlzdCBpdGVtcykuXHJcblx0XHQgKlxyXG5cdFx0ICogWW91IGNhbiBhbHNvIHBhc3MgaW4gYSBIVE1MIHN0cmluZyBvciBhIEpTT04gYXJyYXkgaGVyZS5cclxuXHRcdCAqIFxyXG5cdFx0ICogSXQgaXMgcG9zc2libGUgdG8gcGFzcyBpbiBhIHN0YW5kYXJkIGpRdWVyeS1saWtlIEFKQVggY29uZmlnIGFuZCBqc3RyZWUgd2lsbCBhdXRvbWF0aWNhbGx5IGRldGVybWluZSBpZiB0aGUgcmVzcG9uc2UgaXMgSlNPTiBvciBIVE1MIGFuZCB1c2UgdGhhdCB0byBwb3B1bGF0ZSB0aGUgdHJlZS4gXHJcblx0XHQgKiBJbiBhZGRpdGlvbiB0byB0aGUgc3RhbmRhcmQgalF1ZXJ5IGFqYXggb3B0aW9ucyBoZXJlIHlvdSBjYW4gc3VwcHkgZnVuY3Rpb25zIGZvciBgZGF0YWAgYW5kIGB1cmxgLCB0aGUgZnVuY3Rpb25zIHdpbGwgYmUgcnVuIGluIHRoZSBjdXJyZW50IGluc3RhbmNlJ3Mgc2NvcGUgYW5kIGEgcGFyYW0gd2lsbCBiZSBwYXNzZWQgaW5kaWNhdGluZyB3aGljaCBub2RlIGlzIGJlaW5nIGxvYWRlZCwgdGhlIHJldHVybiB2YWx1ZSBvZiB0aG9zZSBmdW5jdGlvbnMgd2lsbCBiZSB1c2VkLlxyXG5cdFx0ICogXHJcblx0XHQgKiBUaGUgbGFzdCBvcHRpb24gaXMgdG8gc3BlY2lmeSBhIGZ1bmN0aW9uLCB0aGF0IGZ1bmN0aW9uIHdpbGwgcmVjZWl2ZSB0aGUgbm9kZSBiZWluZyBsb2FkZWQgYXMgYXJndW1lbnQgYW5kIGEgc2Vjb25kIHBhcmFtIHdoaWNoIGlzIGEgZnVuY3Rpb24gd2hpY2ggc2hvdWxkIGJlIGNhbGxlZCB3aXRoIHRoZSByZXN1bHQuXHJcblx0XHQgKlxyXG5cdFx0ICogX19FeGFtcGxlc19fXHJcblx0XHQgKlxyXG5cdFx0ICpcdC8vIEFKQVhcclxuXHRcdCAqXHQkKCcjdHJlZScpLmpzdHJlZSh7XHJcblx0XHQgKlx0XHQnY29yZScgOiB7XHJcblx0XHQgKlx0XHRcdCdkYXRhJyA6IHtcclxuXHRcdCAqXHRcdFx0XHQndXJsJyA6ICcvZ2V0L2NoaWxkcmVuLycsXHJcblx0XHQgKlx0XHRcdFx0J2RhdGEnIDogZnVuY3Rpb24gKG5vZGUpIHtcclxuXHRcdCAqXHRcdFx0XHRcdHJldHVybiB7ICdpZCcgOiBub2RlLmlkIH07XHJcblx0XHQgKlx0XHRcdFx0fVxyXG5cdFx0ICpcdFx0XHR9XHJcblx0XHQgKlx0XHR9KTtcclxuXHRcdCAqXHJcblx0XHQgKlx0Ly8gZGlyZWN0IGRhdGFcclxuXHRcdCAqXHQkKCcjdHJlZScpLmpzdHJlZSh7XHJcblx0XHQgKlx0XHQnY29yZScgOiB7XHJcblx0XHQgKlx0XHRcdCdkYXRhJyA6IFtcclxuXHRcdCAqXHRcdFx0XHQnU2ltcGxlIHJvb3Qgbm9kZScsXHJcblx0XHQgKlx0XHRcdFx0e1xyXG5cdFx0ICpcdFx0XHRcdFx0J2lkJyA6ICdub2RlXzInLFxyXG5cdFx0ICpcdFx0XHRcdFx0J3RleHQnIDogJ1Jvb3Qgbm9kZSB3aXRoIG9wdGlvbnMnLFxyXG5cdFx0ICpcdFx0XHRcdFx0J3N0YXRlJyA6IHsgJ29wZW5lZCcgOiB0cnVlLCAnc2VsZWN0ZWQnIDogdHJ1ZSB9LFxyXG5cdFx0ICpcdFx0XHRcdFx0J2NoaWxkcmVuJyA6IFsgeyAndGV4dCcgOiAnQ2hpbGQgMScgfSwgJ0NoaWxkIDInXVxyXG5cdFx0ICpcdFx0XHRcdH1cclxuXHRcdCAqXHRcdFx0XVxyXG5cdFx0ICpcdFx0fSk7XHJcblx0XHQgKlx0XHJcblx0XHQgKlx0Ly8gZnVuY3Rpb25cclxuXHRcdCAqXHQkKCcjdHJlZScpLmpzdHJlZSh7XHJcblx0XHQgKlx0XHQnY29yZScgOiB7XHJcblx0XHQgKlx0XHRcdCdkYXRhJyA6IGZ1bmN0aW9uIChvYmosIGNhbGxiYWNrKSB7XHJcblx0XHQgKlx0XHRcdFx0Y2FsbGJhY2suY2FsbCh0aGlzLCBbJ1Jvb3QgMScsICdSb290IDInXSk7XHJcblx0XHQgKlx0XHRcdH1cclxuXHRcdCAqXHRcdH0pO1xyXG5cdFx0ICogXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb3JlLmRhdGFcclxuXHRcdCAqL1xyXG5cdFx0ZGF0YVx0XHRcdDogZmFsc2UsXHJcblx0XHQvKipcclxuXHRcdCAqIGNvbmZpZ3VyZSB0aGUgdmFyaW91cyBzdHJpbmdzIHVzZWQgdGhyb3VnaG91dCB0aGUgdHJlZVxyXG5cdFx0ICpcclxuXHRcdCAqIFlvdSBjYW4gdXNlIGFuIG9iamVjdCB3aGVyZSB0aGUga2V5IGlzIHRoZSBzdHJpbmcgeW91IG5lZWQgdG8gcmVwbGFjZSBhbmQgdGhlIHZhbHVlIGlzIHlvdXIgcmVwbGFjZW1lbnQuXHJcblx0XHQgKiBBbm90aGVyIG9wdGlvbiBpcyB0byBzcGVjaWZ5IGEgZnVuY3Rpb24gd2hpY2ggd2lsbCBiZSBjYWxsZWQgd2l0aCBhbiBhcmd1bWVudCBvZiB0aGUgbmVlZGVkIHN0cmluZyBhbmQgc2hvdWxkIHJldHVybiB0aGUgcmVwbGFjZW1lbnQuXHJcblx0XHQgKiBJZiBsZWZ0IGFzIGBmYWxzZWAgbm8gcmVwbGFjZW1lbnQgaXMgbWFkZS5cclxuXHRcdCAqXHJcblx0XHQgKiBfX0V4YW1wbGVzX19cclxuXHRcdCAqXHJcblx0XHQgKlx0JCgnI3RyZWUnKS5qc3RyZWUoe1xyXG5cdFx0ICpcdFx0J2NvcmUnIDoge1xyXG5cdFx0ICpcdFx0XHQnc3RyaW5ncycgOiB7XHJcblx0XHQgKlx0XHRcdFx0J0xvYWRpbmcuLi4nIDogJ1BsZWFzZSB3YWl0IC4uLidcclxuXHRcdCAqXHRcdFx0fVxyXG5cdFx0ICpcdFx0fVxyXG5cdFx0ICpcdH0pO1xyXG5cdFx0ICpcclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmUuc3RyaW5nc1xyXG5cdFx0ICovXHJcblx0XHRzdHJpbmdzXHRcdFx0OiBmYWxzZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZGV0ZXJtaW5lcyB3aGF0IGhhcHBlbnMgd2hlbiBhIHVzZXIgdHJpZXMgdG8gbW9kaWZ5IHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIHRyZWVcclxuXHRcdCAqIElmIGxlZnQgYXMgYGZhbHNlYCBhbGwgb3BlcmF0aW9ucyBsaWtlIGNyZWF0ZSwgcmVuYW1lLCBkZWxldGUsIG1vdmUgb3IgY29weSBhcmUgcHJldmVudGVkLlxyXG5cdFx0ICogWW91IGNhbiBzZXQgdGhpcyB0byBgdHJ1ZWAgdG8gYWxsb3cgYWxsIGludGVyYWN0aW9ucyBvciB1c2UgYSBmdW5jdGlvbiB0byBoYXZlIGJldHRlciBjb250cm9sLlxyXG5cdFx0ICpcclxuXHRcdCAqIF9fRXhhbXBsZXNfX1xyXG5cdFx0ICpcclxuXHRcdCAqXHQkKCcjdHJlZScpLmpzdHJlZSh7XHJcblx0XHQgKlx0XHQnY29yZScgOiB7XHJcblx0XHQgKlx0XHRcdCdjaGVja19jYWxsYmFjaycgOiBmdW5jdGlvbiAob3BlcmF0aW9uLCBub2RlLCBub2RlX3BhcmVudCwgbm9kZV9wb3NpdGlvbikge1xyXG5cdFx0ICpcdFx0XHRcdC8vIG9wZXJhdGlvbiBjYW4gYmUgJ2NyZWF0ZV9ub2RlJywgJ3JlbmFtZV9ub2RlJywgJ2RlbGV0ZV9ub2RlJywgJ21vdmVfbm9kZScgb3IgJ2NvcHlfbm9kZSdcclxuXHRcdCAqXHRcdFx0XHQvLyBpbiBjYXNlIG9mICdyZW5hbWVfbm9kZScgbm9kZV9wb3NpdGlvbiBpcyBmaWxsZWQgd2l0aCB0aGUgbmV3IG5vZGUgbmFtZVxyXG5cdFx0ICpcdFx0XHRcdHJldHVybiBvcGVyYXRpb24gPT09ICdyZW5hbWVfbm9kZScgPyB0cnVlIDogZmFsc2U7XHJcblx0XHQgKlx0XHRcdH1cclxuXHRcdCAqXHRcdH1cclxuXHRcdCAqXHR9KTtcclxuXHRcdCAqIFxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS5jaGVja19jYWxsYmFja1xyXG5cdFx0ICovXHJcblx0XHRjaGVja19jYWxsYmFja1x0OiBmYWxzZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogYSBjYWxsYmFjayBjYWxsZWQgd2l0aCBhIHNpbmdsZSBvYmplY3QgcGFyYW1ldGVyIGluIHRoZSBpbnN0YW5jZSdzIHNjb3BlIHdoZW4gc29tZXRoaW5nIGdvZXMgd3JvbmcgKG9wZXJhdGlvbiBwcmV2ZW50ZWQsIGFqYXggZmFpbGVkLCBldGMpXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb3JlLmVycm9yXHJcblx0XHQgKi9cclxuXHRcdGVycm9yXHRcdFx0OiAkLm5vb3AsXHJcblx0XHQvKipcclxuXHRcdCAqIHRoZSBvcGVuIC8gY2xvc2UgYW5pbWF0aW9uIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcyAtIHNldCB0aGlzIHRvIGBmYWxzZWAgdG8gZGlzYWJsZSB0aGUgYW5pbWF0aW9uIChkZWZhdWx0IGlzIGAyMDBgKVxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS5hbmltYXRpb25cclxuXHRcdCAqL1xyXG5cdFx0YW5pbWF0aW9uXHRcdDogMjAwLFxyXG5cdFx0LyoqXHJcblx0XHQgKiBhIGJvb2xlYW4gaW5kaWNhdGluZyBpZiBtdWx0aXBsZSBub2RlcyBjYW4gYmUgc2VsZWN0ZWRcclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmUubXVsdGlwbGVcclxuXHRcdCAqL1xyXG5cdFx0bXVsdGlwbGVcdFx0OiB0cnVlLFxyXG5cdFx0LyoqXHJcblx0XHQgKiB0aGVtZSBjb25maWd1cmF0aW9uIG9iamVjdFxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS50aGVtZXNcclxuXHRcdCAqL1xyXG5cdFx0dGhlbWVzXHRcdFx0OiB7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0aGUgbmFtZSBvZiB0aGUgdGhlbWUgdG8gdXNlIChpZiBsZWZ0IGFzIGBmYWxzZWAgdGhlIGRlZmF1bHQgdGhlbWUgaXMgdXNlZClcclxuXHRcdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS50aGVtZXMubmFtZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0bmFtZVx0XHRcdDogZmFsc2UsXHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0aGUgVVJMIG9mIHRoZSB0aGVtZSdzIENTUyBmaWxlLCBsZWF2ZSB0aGlzIGFzIGBmYWxzZWAgaWYgeW91IGhhdmUgbWFudWFsbHkgaW5jbHVkZWQgdGhlIHRoZW1lIENTUyAocmVjb21tZW5kZWQpLiBZb3UgY2FuIHNldCB0aGlzIHRvIGB0cnVlYCB0b28gd2hpY2ggd2lsbCB0cnkgdG8gYXV0b2xvYWQgdGhlIHRoZW1lLlxyXG5cdFx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb3JlLnRoZW1lcy51cmxcclxuXHRcdFx0ICovXHJcblx0XHRcdHVybFx0XHRcdFx0OiBmYWxzZSxcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRoZSBsb2NhdGlvbiBvZiBhbGwganN0cmVlIHRoZW1lcyAtIG9ubHkgdXNlZCBpZiBgdXJsYCBpcyBzZXQgdG8gYHRydWVgXHJcblx0XHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmUudGhlbWVzLmRpclxyXG5cdFx0XHQgKi9cclxuXHRcdFx0ZGlyXHRcdFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogYSBib29sZWFuIGluZGljYXRpbmcgaWYgY29ubmVjdGluZyBkb3RzIGFyZSBzaG93blxyXG5cdFx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb3JlLnRoZW1lcy5kb3RzXHJcblx0XHRcdCAqL1xyXG5cdFx0XHRkb3RzXHRcdFx0OiB0cnVlLFxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogYSBib29sZWFuIGluZGljYXRpbmcgaWYgbm9kZSBpY29ucyBhcmUgc2hvd25cclxuXHRcdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS50aGVtZXMuaWNvbnNcclxuXHRcdFx0ICovXHJcblx0XHRcdGljb25zXHRcdFx0OiB0cnVlLFxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogYSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIHRyZWUgYmFja2dyb3VuZCBpcyBzdHJpcGVkXHJcblx0XHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmUudGhlbWVzLnN0cmlwZXNcclxuXHRcdFx0ICovXHJcblx0XHRcdHN0cmlwZXNcdFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogYSBzdHJpbmcgKG9yIGJvb2xlYW4gYGZhbHNlYCkgc3BlY2lmeWluZyB0aGUgdGhlbWUgdmFyaWFudCB0byB1c2UgKGlmIHRoZSB0aGVtZSBzdXBwb3J0cyB2YXJpYW50cylcclxuXHRcdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS50aGVtZXMudmFyaWFudFxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dmFyaWFudFx0XHRcdDogZmFsc2UsXHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiBhIGJvb2xlYW4gc3BlY2lmeWluZyBpZiBhIHJlcG9uc2l2ZSB2ZXJzaW9uIG9mIHRoZSB0aGVtZSBzaG91bGQga2ljayBpbiBvbiBzbWFsbGVyIHNjcmVlbnMgKGlmIHRoZSB0aGVtZSBzdXBwb3J0cyBpdCkuIERlZmF1bHRzIHRvIGB0cnVlYC5cclxuXHRcdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY29yZS50aGVtZXMucmVzcG9uc2l2ZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0cmVzcG9uc2l2ZVx0XHQ6IHRydWVcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGlmIGxlZnQgYXMgYHRydWVgIGFsbCBwYXJlbnRzIG9mIGFsbCBzZWxlY3RlZCBub2RlcyB3aWxsIGJlIG9wZW5lZCBvbmNlIHRoZSB0cmVlIGxvYWRzIChzbyB0aGF0IGFsbCBzZWxlY3RlZCBub2RlcyBhcmUgdmlzaWJsZSB0byB0aGUgdXNlcilcclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvcmUuZXhwYW5kX3NlbGVjdGVkX29ubG9hZFxyXG5cdFx0ICovXHJcblx0XHRleHBhbmRfc2VsZWN0ZWRfb25sb2FkIDogdHJ1ZVxyXG5cdH07XHJcblx0JC5qc3RyZWUuY29yZS5wcm90b3R5cGUgPSB7XHJcblx0XHQvKipcclxuXHRcdCAqIHVzZWQgdG8gZGVjb3JhdGUgYW4gaW5zdGFuY2Ugd2l0aCBhIHBsdWdpbi4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIHBsdWdpbihkZWNvIFssIG9wdHNdKVxyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBkZWNvIHRoZSBwbHVnaW4gdG8gZGVjb3JhdGUgd2l0aFxyXG5cdFx0ICogQHBhcmFtICB7T2JqZWN0fSBvcHRzIG9wdGlvbnMgZm9yIHRoZSBwbHVnaW5cclxuXHRcdCAqIEByZXR1cm4ge2pzVHJlZX1cclxuXHRcdCAqL1xyXG5cdFx0cGx1Z2luIDogZnVuY3Rpb24gKGRlY28sIG9wdHMpIHtcclxuXHRcdFx0dmFyIENoaWxkID0gJC5qc3RyZWUucGx1Z2luc1tkZWNvXTtcclxuXHRcdFx0aWYoQ2hpbGQpIHtcclxuXHRcdFx0XHR0aGlzLl9kYXRhW2RlY29dID0ge307XHJcblx0XHRcdFx0Q2hpbGQucHJvdG90eXBlID0gdGhpcztcclxuXHRcdFx0XHRyZXR1cm4gbmV3IENoaWxkKG9wdHMsIHRoaXMpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogdXNlZCB0byBkZWNvcmF0ZSBhbiBpbnN0YW5jZSB3aXRoIGEgcGx1Z2luLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgaW5pdChlbCwgb3B0b25zKVxyXG5cdFx0ICogQHBhcmFtIHtET01FbGVtZW50fGpRdWVyeXxTdHJpbmd9IGVsIHRoZSBlbGVtZW50IHdlIGFyZSB0cmFuc2Zvcm1pbmdcclxuXHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIG9wdGlvbnMgZm9yIHRoaXMgaW5zdGFuY2VcclxuXHRcdCAqIEB0cmlnZ2VyIGluaXQuanN0cmVlLCBsb2FkaW5nLmpzdHJlZSwgbG9hZGVkLmpzdHJlZSwgcmVhZHkuanN0cmVlLCBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRpbml0IDogZnVuY3Rpb24gKGVsLCBvcHRpb25zKSB7XHJcblx0XHRcdHRoaXMuX21vZGVsID0ge1xyXG5cdFx0XHRcdGRhdGEgOiB7XHJcblx0XHRcdFx0XHQnIycgOiB7XHJcblx0XHRcdFx0XHRcdGlkIDogJyMnLFxyXG5cdFx0XHRcdFx0XHRwYXJlbnQgOiBudWxsLFxyXG5cdFx0XHRcdFx0XHRwYXJlbnRzIDogW10sXHJcblx0XHRcdFx0XHRcdGNoaWxkcmVuIDogW10sXHJcblx0XHRcdFx0XHRcdGNoaWxkcmVuX2QgOiBbXSxcclxuXHRcdFx0XHRcdFx0c3RhdGUgOiB7IGxvYWRlZCA6IGZhbHNlIH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9LFxyXG5cdFx0XHRcdGNoYW5nZWQgOiBbXSxcclxuXHRcdFx0XHRmb3JjZV9mdWxsX3JlZHJhdyA6IGZhbHNlLFxyXG5cdFx0XHRcdHJlZHJhd190aW1lb3V0IDogZmFsc2UsXHJcblx0XHRcdFx0ZGVmYXVsdF9zdGF0ZSA6IHtcclxuXHRcdFx0XHRcdGxvYWRlZCA6IHRydWUsXHJcblx0XHRcdFx0XHRvcGVuZWQgOiBmYWxzZSxcclxuXHRcdFx0XHRcdHNlbGVjdGVkIDogZmFsc2UsXHJcblx0XHRcdFx0XHRkaXNhYmxlZCA6IGZhbHNlXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9O1xyXG5cclxuXHRcdFx0dGhpcy5lbGVtZW50ID0gJChlbCkuYWRkQ2xhc3MoJ2pzdHJlZSBqc3RyZWUtJyArIHRoaXMuX2lkKTtcclxuXHRcdFx0dGhpcy5zZXR0aW5ncyA9IG9wdGlvbnM7XHJcblx0XHRcdHRoaXMuZWxlbWVudC5iaW5kKFwiZGVzdHJveWVkXCIsICQucHJveHkodGhpcy50ZWFyZG93biwgdGhpcykpO1xyXG5cclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLnJlYWR5ID0gZmFsc2U7XHJcblx0XHRcdHRoaXMuX2RhdGEuY29yZS5sb2FkZWQgPSBmYWxzZTtcclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLnJ0bCA9ICh0aGlzLmVsZW1lbnQuY3NzKFwiZGlyZWN0aW9uXCIpID09PSBcInJ0bFwiKTtcclxuXHRcdFx0dGhpcy5lbGVtZW50W3RoaXMuX2RhdGEuY29yZS5ydGwgPyAnYWRkQ2xhc3MnIDogJ3JlbW92ZUNsYXNzJ10oXCJqc3RyZWUtcnRsXCIpO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnQuYXR0cigncm9sZScsJ3RyZWUnKTtcclxuXHJcblx0XHRcdHRoaXMuYmluZCgpO1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIGFsbCBldmVudHMgYXJlIGJvdW5kXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBpbml0LmpzdHJlZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKFwiaW5pdFwiKTtcclxuXHJcblx0XHRcdHRoaXMuX2RhdGEuY29yZS5vcmlnaW5hbF9jb250YWluZXJfaHRtbCA9IHRoaXMuZWxlbWVudC5maW5kKFwiID4gdWwgPiBsaVwiKS5jbG9uZSh0cnVlKTtcclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLm9yaWdpbmFsX2NvbnRhaW5lcl9odG1sXHJcblx0XHRcdFx0LmZpbmQoXCJsaVwiKS5hZGRCYWNrKClcclxuXHRcdFx0XHQuY29udGVudHMoKS5maWx0ZXIoZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5ub2RlVHlwZSA9PT0gMyAmJiAoIXRoaXMubm9kZVZhbHVlIHx8IC9eXFxzKyQvLnRlc3QodGhpcy5ub2RlVmFsdWUpKTtcclxuXHRcdFx0XHR9KVxyXG5cdFx0XHRcdC5yZW1vdmUoKTtcclxuXHRcdFx0dGhpcy5lbGVtZW50Lmh0bWwoXCI8XCIrXCJ1bCBjbGFzcz0nanN0cmVlLWNvbnRhaW5lci11bCc+PFwiK1wibGkgY2xhc3M9J2pzdHJlZS1pbml0aWFsLW5vZGUganN0cmVlLWxvYWRpbmcganN0cmVlLWxlYWYganN0cmVlLWxhc3QnPjxpIGNsYXNzPSdqc3RyZWUtaWNvbiBqc3RyZWUtb2NsJz48L2k+PFwiK1wiYSBjbGFzcz0nanN0cmVlLWFuY2hvcicgaHJlZj0nIyc+PGkgY2xhc3M9J2pzdHJlZS1pY29uIGpzdHJlZS10aGVtZWljb24taGlkZGVuJz48L2k+XCIgKyB0aGlzLmdldF9zdHJpbmcoXCJMb2FkaW5nIC4uLlwiKSArIFwiPC9hPjwvbGk+PC91bD5cIik7XHJcblx0XHRcdHRoaXMuX2RhdGEuY29yZS5saV9oZWlnaHQgPSB0aGlzLmdldF9jb250YWluZXJfdWwoKS5jaGlsZHJlbihcImxpOmVxKDApXCIpLmhlaWdodCgpIHx8IDE4O1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIHRoZSBsb2FkaW5nIHRleHQgaXMgc2hvd24gYW5kIGJlZm9yZSBsb2FkaW5nIHN0YXJ0c1xyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgbG9hZGluZy5qc3RyZWVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcihcImxvYWRpbmdcIik7XHJcblx0XHRcdHRoaXMubG9hZF9ub2RlKCcjJyk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBkZXN0cm95IGFuIGluc3RhbmNlXHJcblx0XHQgKiBAbmFtZSBkZXN0cm95KClcclxuXHRcdCAqL1xyXG5cdFx0ZGVzdHJveSA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0dGhpcy5lbGVtZW50LnVuYmluZChcImRlc3Ryb3llZFwiLCB0aGlzLnRlYXJkb3duKTtcclxuXHRcdFx0dGhpcy50ZWFyZG93bigpO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogcGFydCBvZiB0aGUgZGVzdHJveWluZyBvZiBhbiBpbnN0YW5jZS4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIHRlYXJkb3duKClcclxuXHRcdCAqL1xyXG5cdFx0dGVhcmRvd24gOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXMudW5iaW5kKCk7XHJcblx0XHRcdHRoaXMuZWxlbWVudFxyXG5cdFx0XHRcdC5yZW1vdmVDbGFzcygnanN0cmVlJylcclxuXHRcdFx0XHQucmVtb3ZlRGF0YSgnanN0cmVlJylcclxuXHRcdFx0XHQuZmluZChcIltjbGFzc149J2pzdHJlZSddXCIpXHJcblx0XHRcdFx0XHQuYWRkQmFjaygpXHJcblx0XHRcdFx0XHQuYXR0cihcImNsYXNzXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY2xhc3NOYW1lLnJlcGxhY2UoL2pzdHJlZVteIF0qfCQvaWcsJycpOyB9KTtcclxuXHRcdFx0dGhpcy5lbGVtZW50ID0gbnVsbDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGJpbmQgYWxsIGV2ZW50cy4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIGJpbmQoKVxyXG5cdFx0ICovXHJcblx0XHRiaW5kIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHQub24oXCJkYmxjbGljay5qc3RyZWVcIiwgZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRpZihkb2N1bWVudC5zZWxlY3Rpb24gJiYgZG9jdW1lbnQuc2VsZWN0aW9uLmVtcHR5KSB7XHJcblx0XHRcdFx0XHRcdFx0ZG9jdW1lbnQuc2VsZWN0aW9uLmVtcHR5KCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0aWYod2luZG93LmdldFNlbGVjdGlvbikge1xyXG5cdFx0XHRcdFx0XHRcdFx0dmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcclxuXHRcdFx0XHRcdFx0XHRcdHRyeSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHNlbC5yZW1vdmVBbGxSYW5nZXMoKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0c2VsLmNvbGxhcHNlKCk7XHJcblx0XHRcdFx0XHRcdFx0XHR9IGNhdGNoIChpZ25vcmUpIHsgfVxyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHQub24oXCJjbGljay5qc3RyZWVcIiwgXCIuanN0cmVlLW9jbFwiLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMudG9nZ2xlX25vZGUoZS50YXJnZXQpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwiY2xpY2suanN0cmVlXCIsIFwiLmpzdHJlZS1hbmNob3JcIiwgJC5wcm94eShmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdCQoZS5jdXJyZW50VGFyZ2V0KS5mb2N1cygpO1xyXG5cdFx0XHRcdFx0XHR0aGlzLmFjdGl2YXRlX25vZGUoZS5jdXJyZW50VGFyZ2V0LCBlKTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbigna2V5ZG93bi5qc3RyZWUnLCAnLmpzdHJlZS1hbmNob3InLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdHZhciBvID0gbnVsbDtcclxuXHRcdFx0XHRcdFx0c3dpdGNoKGUud2hpY2gpIHtcclxuXHRcdFx0XHRcdFx0XHRjYXNlIDEzOlxyXG5cdFx0XHRcdFx0XHRcdGNhc2UgMzI6XHJcblx0XHRcdFx0XHRcdFx0XHRlLnR5cGUgPSBcImNsaWNrXCI7XHJcblx0XHRcdFx0XHRcdFx0XHQkKGUuY3VycmVudFRhcmdldCkudHJpZ2dlcihlKTtcclxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdGNhc2UgMzc6XHJcblx0XHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZih0aGlzLmlzX29wZW4oZS5jdXJyZW50VGFyZ2V0KSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLmNsb3NlX25vZGUoZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRvID0gdGhpcy5nZXRfcHJldl9kb20oZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYobyAmJiBvLmxlbmd0aCkgeyBvLmNoaWxkcmVuKCcuanN0cmVlLWFuY2hvcicpLmZvY3VzKCk7IH1cclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdGNhc2UgMzg6XHJcblx0XHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdFx0XHRvID0gdGhpcy5nZXRfcHJldl9kb20oZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdFx0XHRcdGlmKG8gJiYgby5sZW5ndGgpIHsgby5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5mb2N1cygpOyB9XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRjYXNlIDM5OlxyXG5cdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYodGhpcy5pc19jbG9zZWQoZS5jdXJyZW50VGFyZ2V0KSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLm9wZW5fbm9kZShlLmN1cnJlbnRUYXJnZXQsIGZ1bmN0aW9uIChvKSB7IHRoaXMuZ2V0X25vZGUobywgdHJ1ZSkuY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJykuZm9jdXMoKTsgfSk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0byA9IHRoaXMuZ2V0X25leHRfZG9tKGUuY3VycmVudFRhcmdldCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKG8gJiYgby5sZW5ndGgpIHsgby5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5mb2N1cygpOyB9XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRjYXNlIDQwOlxyXG5cdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0byA9IHRoaXMuZ2V0X25leHRfZG9tKGUuY3VycmVudFRhcmdldCk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZihvICYmIG8ubGVuZ3RoKSB7IG8uY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJykuZm9jdXMoKTsgfVxyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0Ly8gZGVsZXRlXHJcblx0XHRcdFx0XHRcdFx0Y2FzZSA0NjpcclxuXHRcdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdFx0XHRcdG8gPSB0aGlzLmdldF9ub2RlKGUuY3VycmVudFRhcmdldCk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZihvICYmIG8uaWQgJiYgby5pZCAhPT0gJyMnKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdG8gPSB0aGlzLmlzX3NlbGVjdGVkKG8pID8gdGhpcy5nZXRfc2VsZWN0ZWQoKSA6IG87XHJcblx0XHRcdFx0XHRcdFx0XHRcdC8vIHRoaXMuZGVsZXRlX25vZGUobyk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHQvLyBmMlxyXG5cdFx0XHRcdFx0XHRcdGNhc2UgMTEzOlxyXG5cdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0byA9IHRoaXMuZ2V0X25vZGUoZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdFx0XHRcdC8qIVxyXG5cdFx0XHRcdFx0XHRcdFx0aWYobyAmJiBvLmlkICYmIG8uaWQgIT09ICcjJykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyB0aGlzLmVkaXQobyk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHQqL1xyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKGUud2hpY2gpO1xyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbihcImxvYWRfbm9kZS5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHRpZihkYXRhLnN0YXR1cykge1xyXG5cdFx0XHRcdFx0XHRcdGlmKGRhdGEubm9kZS5pZCA9PT0gJyMnICYmICF0aGlzLl9kYXRhLmNvcmUubG9hZGVkKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUubG9hZGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0XHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIHRoZSByb290IG5vZGUgaXMgbG9hZGVkIGZvciB0aGUgZmlyc3QgdGltZVxyXG5cdFx0XHRcdFx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0XHRcdFx0XHQgKiBAbmFtZSBsb2FkZWQuanN0cmVlXHJcblx0XHRcdFx0XHRcdFx0XHQgKi9cclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMudHJpZ2dlcihcImxvYWRlZFwiKTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0aWYoIXRoaXMuX2RhdGEuY29yZS5yZWFkeSAmJiAhdGhpcy5nZXRfY29udGFpbmVyX3VsKCkuZmluZCgnLmpzdHJlZS1sb2FkaW5nOmVxKDApJykubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUucmVhZHkgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYodGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZih0aGlzLnNldHRpbmdzLmNvcmUuZXhwYW5kX3NlbGVjdGVkX29ubG9hZCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHZhciB0bXAgPSBbXSwgaSwgajtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAgPSB0bXAuY29uY2F0KHRoaXMuX21vZGVsLmRhdGFbdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkW2ldXS5wYXJlbnRzKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0dG1wID0gJC52YWthdGEuYXJyYXlfdW5pcXVlKHRtcCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gdG1wLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5vcGVuX25vZGUodG1wW2ldLCBmYWxzZSwgMCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMudHJpZ2dlcignY2hhbmdlZCcsIHsgJ2FjdGlvbicgOiAncmVhZHknLCAnc2VsZWN0ZWQnIDogdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkIH0pO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0LyoqXHJcblx0XHRcdFx0XHRcdFx0XHQgKiB0cmlnZ2VyZWQgYWZ0ZXIgYWxsIG5vZGVzIGFyZSBmaW5pc2hlZCBsb2FkaW5nXHJcblx0XHRcdFx0XHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHRcdFx0XHRcdCAqIEBuYW1lIHJlYWR5LmpzdHJlZVxyXG5cdFx0XHRcdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHRcdFx0XHRzZXRUaW1lb3V0KCQucHJveHkoZnVuY3Rpb24gKCkgeyB0aGlzLnRyaWdnZXIoXCJyZWFkeVwiKTsgfSwgdGhpcyksIDApO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Ly8gVEhFTUUgUkVMQVRFRFxyXG5cdFx0XHRcdC5vbihcImluaXQuanN0cmVlXCIsICQucHJveHkoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHR2YXIgcyA9IHRoaXMuc2V0dGluZ3MuY29yZS50aGVtZXM7XHJcblx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS50aGVtZXMuZG90c1x0XHRcdD0gcy5kb3RzO1xyXG5cdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUudGhlbWVzLnN0cmlwZXNcdFx0PSBzLnN0cmlwZXM7XHJcblx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS50aGVtZXMuaWNvbnNcdFx0PSBzLmljb25zO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNldF90aGVtZShzLm5hbWUgfHwgXCJkZWZhdWx0XCIsIHMudXJsKTtcclxuXHRcdFx0XHRcdFx0dGhpcy5zZXRfdGhlbWVfdmFyaWFudChzLnZhcmlhbnQpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwibG9hZGluZy5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdHRoaXNbIHRoaXMuX2RhdGEuY29yZS50aGVtZXMuZG90cyA/IFwic2hvd19kb3RzXCIgOiBcImhpZGVfZG90c1wiIF0oKTtcclxuXHRcdFx0XHRcdFx0dGhpc1sgdGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5pY29ucyA/IFwic2hvd19pY29uc1wiIDogXCJoaWRlX2ljb25zXCIgXSgpO1xyXG5cdFx0XHRcdFx0XHR0aGlzWyB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLnN0cmlwZXMgPyBcInNob3dfc3RyaXBlc1wiIDogXCJoaWRlX3N0cmlwZXNcIiBdKCk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oJ2ZvY3VzLmpzdHJlZScsICcuanN0cmVlLWFuY2hvcicsICQucHJveHkoZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5lbGVtZW50LmZpbmQoJy5qc3RyZWUtaG92ZXJlZCcpLm5vdChlLmN1cnJlbnRUYXJnZXQpLm1vdXNlbGVhdmUoKTtcclxuXHRcdFx0XHRcdFx0JChlLmN1cnJlbnRUYXJnZXQpLm1vdXNlZW50ZXIoKTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbignbW91c2VlbnRlci5qc3RyZWUnLCAnLmpzdHJlZS1hbmNob3InLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuaG92ZXJfbm9kZShlLmN1cnJlbnRUYXJnZXQpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKCdtb3VzZWxlYXZlLmpzdHJlZScsICcuanN0cmVlLWFuY2hvcicsICQucHJveHkoZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5kZWhvdmVyX25vZGUoZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHBhcnQgb2YgdGhlIGRlc3Ryb3lpbmcgb2YgYW4gaW5zdGFuY2UuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSB1bmJpbmQoKVxyXG5cdFx0ICovXHJcblx0XHR1bmJpbmQgOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXMuZWxlbWVudC5vZmYoJy5qc3RyZWUnKTtcclxuXHRcdFx0JChkb2N1bWVudCkub2ZmKCcuanN0cmVlLScgKyB0aGlzLl9pZCk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiB0cmlnZ2VyIGFuIGV2ZW50LiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgdHJpZ2dlcihldiBbLCBkYXRhXSlcclxuXHRcdCAqIEBwYXJhbSAge1N0cmluZ30gZXYgdGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHRyaWdnZXJcclxuXHRcdCAqIEBwYXJhbSAge09iamVjdH0gZGF0YSBhZGRpdGlvbmFsIGRhdGEgdG8gcGFzcyB3aXRoIHRoZSBldmVudFxyXG5cdFx0ICovXHJcblx0XHR0cmlnZ2VyIDogZnVuY3Rpb24gKGV2LCBkYXRhKSB7XHJcblx0XHRcdGlmKCFkYXRhKSB7XHJcblx0XHRcdFx0ZGF0YSA9IHt9O1xyXG5cdFx0XHR9XHJcblx0XHRcdGRhdGEuaW5zdGFuY2UgPSB0aGlzO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnQudHJpZ2dlckhhbmRsZXIoZXYucmVwbGFjZSgnLmpzdHJlZScsJycpICsgJy5qc3RyZWUnLCBkYXRhKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHJldHVybnMgdGhlIGpRdWVyeSBleHRlbmRlZCBpbnN0YW5jZSBjb250YWluZXJcclxuXHRcdCAqIEBuYW1lIGdldF9jb250YWluZXIoKVxyXG5cdFx0ICogQHJldHVybiB7alF1ZXJ5fVxyXG5cdFx0ICovXHJcblx0XHRnZXRfY29udGFpbmVyIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5lbGVtZW50O1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogcmV0dXJucyB0aGUgalF1ZXJ5IGV4dGVuZGVkIG1haW4gVUwgbm9kZSBpbnNpZGUgdGhlIGluc3RhbmNlIGNvbnRhaW5lci4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIGdldF9jb250YWluZXJfdWwoKVxyXG5cdFx0ICogQHJldHVybiB7alF1ZXJ5fVxyXG5cdFx0ICovXHJcblx0XHRnZXRfY29udGFpbmVyX3VsIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5lbGVtZW50LmNoaWxkcmVuKFwidWw6ZXEoMClcIik7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXRzIHN0cmluZyByZXBsYWNlbWVudHMgKGxvY2FsaXphdGlvbikuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBnZXRfc3RyaW5nKGtleSlcclxuXHRcdCAqIEBwYXJhbSAge1N0cmluZ30ga2V5XHJcblx0XHQgKiBAcmV0dXJuIHtTdHJpbmd9XHJcblx0XHQgKi9cclxuXHRcdGdldF9zdHJpbmcgOiBmdW5jdGlvbiAoa2V5KSB7XHJcblx0XHRcdHZhciBhID0gdGhpcy5zZXR0aW5ncy5jb3JlLnN0cmluZ3M7XHJcblx0XHRcdGlmKCQuaXNGdW5jdGlvbihhKSkgeyByZXR1cm4gYS5jYWxsKHRoaXMsIGtleSk7IH1cclxuXHRcdFx0aWYoYSAmJiBhW2tleV0pIHsgcmV0dXJuIGFba2V5XTsgfVxyXG5cdFx0XHRyZXR1cm4ga2V5O1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0cyB0aGUgZmlyc3QgY2hpbGQgb2YgYSBET00gbm9kZS4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIF9maXJzdENoaWxkKGRvbSlcclxuXHRcdCAqIEBwYXJhbSAge0RPTUVsZW1lbnR9IGRvbVxyXG5cdFx0ICogQHJldHVybiB7RE9NRWxlbWVudH1cclxuXHRcdCAqL1xyXG5cdFx0X2ZpcnN0Q2hpbGQgOiBmdW5jdGlvbiAoZG9tKSB7XHJcblx0XHRcdGRvbSA9IGRvbSA/IGRvbS5maXJzdENoaWxkIDogbnVsbDtcclxuXHRcdFx0d2hpbGUoZG9tICE9PSBudWxsICYmIGRvbS5ub2RlVHlwZSAhPT0gMSkge1xyXG5cdFx0XHRcdGRvbSA9IGRvbS5uZXh0U2libGluZztcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gZG9tO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0cyB0aGUgbmV4dCBzaWJsaW5nIG9mIGEgRE9NIG5vZGUuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBfbmV4dFNpYmxpbmcoZG9tKVxyXG5cdFx0ICogQHBhcmFtICB7RE9NRWxlbWVudH0gZG9tXHJcblx0XHQgKiBAcmV0dXJuIHtET01FbGVtZW50fVxyXG5cdFx0ICovXHJcblx0XHRfbmV4dFNpYmxpbmcgOiBmdW5jdGlvbiAoZG9tKSB7XHJcblx0XHRcdGRvbSA9IGRvbSA/IGRvbS5uZXh0U2libGluZyA6IG51bGw7XHJcblx0XHRcdHdoaWxlKGRvbSAhPT0gbnVsbCAmJiBkb20ubm9kZVR5cGUgIT09IDEpIHtcclxuXHRcdFx0XHRkb20gPSBkb20ubmV4dFNpYmxpbmc7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGRvbTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGdldHMgdGhlIHByZXZpb3VzIHNpYmxpbmcgb2YgYSBET00gbm9kZS4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIF9wcmV2aW91c1NpYmxpbmcoZG9tKVxyXG5cdFx0ICogQHBhcmFtICB7RE9NRWxlbWVudH0gZG9tXHJcblx0XHQgKiBAcmV0dXJuIHtET01FbGVtZW50fVxyXG5cdFx0ICovXHJcblx0XHRfcHJldmlvdXNTaWJsaW5nIDogZnVuY3Rpb24gKGRvbSkge1xyXG5cdFx0XHRkb20gPSBkb20gPyBkb20ucHJldmlvdXNTaWJsaW5nIDogbnVsbDtcclxuXHRcdFx0d2hpbGUoZG9tICE9PSBudWxsICYmIGRvbS5ub2RlVHlwZSAhPT0gMSkge1xyXG5cdFx0XHRcdGRvbSA9IGRvbS5wcmV2aW91c1NpYmxpbmc7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGRvbTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGdldCB0aGUgSlNPTiByZXByZXNlbnRhdGlvbiBvZiBhIG5vZGUgKG9yIHRoZSBhY3R1YWwgalF1ZXJ5IGV4dGVuZGVkIERPTSBub2RlKSBieSB1c2luZyBhbnkgaW5wdXQgKGNoaWxkIERPTSBlbGVtZW50LCBJRCBzdHJpbmcsIHNlbGVjdG9yLCBldGMpXHJcblx0XHQgKiBAbmFtZSBnZXRfbm9kZShvYmogWywgYXNfZG9tXSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEBwYXJhbSAge0Jvb2xlYW59IGFzX2RvbVxyXG5cdFx0ICogQHJldHVybiB7T2JqZWN0fGpRdWVyeX1cclxuXHRcdCAqL1xyXG5cdFx0Z2V0X25vZGUgOiBmdW5jdGlvbiAob2JqLCBhc19kb20pIHtcclxuXHRcdFx0aWYob2JqICYmIG9iai5pZCkge1xyXG5cdFx0XHRcdG9iaiA9IG9iai5pZDtcclxuXHRcdFx0fVxyXG5cdFx0XHR2YXIgZG9tO1xyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdGlmKHRoaXMuX21vZGVsLmRhdGFbb2JqXSkge1xyXG5cdFx0XHRcdFx0b2JqID0gdGhpcy5fbW9kZWwuZGF0YVtvYmpdO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIGlmKCgoZG9tID0gJChvYmosIHRoaXMuZWxlbWVudCkpLmxlbmd0aCB8fCAoZG9tID0gJCgnIycgKyBvYmosIHRoaXMuZWxlbWVudCkpLmxlbmd0aCkgJiYgdGhpcy5fbW9kZWwuZGF0YVtkb20uY2xvc2VzdCgnbGknKS5hdHRyKCdpZCcpXSkge1xyXG5cdFx0XHRcdFx0b2JqID0gdGhpcy5fbW9kZWwuZGF0YVtkb20uY2xvc2VzdCgnbGknKS5hdHRyKCdpZCcpXTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSBpZigoZG9tID0gJChvYmosIHRoaXMuZWxlbWVudCkpLmxlbmd0aCAmJiBkb20uaGFzQ2xhc3MoJ2pzdHJlZScpKSB7XHJcblx0XHRcdFx0XHRvYmogPSB0aGlzLl9tb2RlbC5kYXRhWycjJ107XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYoYXNfZG9tKSB7XHJcblx0XHRcdFx0XHRvYmogPSBvYmouaWQgPT09ICcjJyA/IHRoaXMuZWxlbWVudCA6ICQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob2JqLmlkKSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiBvYmo7XHJcblx0XHRcdH0gY2F0Y2ggKGV4KSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0IHRoZSBwYXRoIHRvIGEgbm9kZSwgZWl0aGVyIGNvbnNpc3Rpbmcgb2Ygbm9kZSB0ZXh0cywgb3Igb2Ygbm9kZSBJRHMsIG9wdGlvbmFsbHkgZ2x1ZWQgdG9nZXRoZXIgKG90aGVyd2lzZSBhbiBhcnJheSlcclxuXHRcdCAqIEBuYW1lIGdldF9wYXRoKG9iaiBbLCBnbHVlLCBpZHNdKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiB0aGUgbm9kZVxyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBnbHVlIGlmIHlvdSB3YW50IHRoZSBwYXRoIGFzIGEgc3RyaW5nIC0gcGFzcyB0aGUgZ2x1ZSBoZXJlIChmb3IgZXhhbXBsZSAnLycpLCBpZiBhIGZhbHN5IHZhbHVlIGlzIHN1cHBsaWVkIGhlcmUsIGFuIGFycmF5IGlzIHJldHVybmVkXHJcblx0XHQgKiBAcGFyYW0gIHtCb29sZWFufSBpZHMgaWYgc2V0IHRvIHRydWUgYnVpbGQgdGhlIHBhdGggdXNpbmcgSUQsIG90aGVyd2lzZSBub2RlIHRleHQgaXMgdXNlZFxyXG5cdFx0ICogQHJldHVybiB7bWl4ZWR9XHJcblx0XHQgKi9cclxuXHRcdGdldF9wYXRoIDogZnVuY3Rpb24gKG9iaiwgZ2x1ZSwgaWRzKSB7XHJcblx0XHRcdG9iaiA9IG9iai5wYXJlbnRzID8gb2JqIDogdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnIHx8ICFvYmoucGFyZW50cykge1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHR2YXIgaSwgaiwgcCA9IFtdO1xyXG5cdFx0XHRwLnB1c2goaWRzID8gb2JqLmlkIDogb2JqLnRleHQpO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSBvYmoucGFyZW50cy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRwLnB1c2goaWRzID8gb2JqLnBhcmVudHNbaV0gOiB0aGlzLmdldF90ZXh0KG9iai5wYXJlbnRzW2ldKSk7XHJcblx0XHRcdH1cclxuXHRcdFx0cCA9IHAucmV2ZXJzZSgpLnNsaWNlKDEpO1xyXG5cdFx0XHRyZXR1cm4gZ2x1ZSA/IHAuam9pbihnbHVlKSA6IHA7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXQgdGhlIG5leHQgdmlzaWJsZSBub2RlIHRoYXQgaXMgYmVsb3cgdGhlIGBvYmpgIG5vZGUuIElmIGBzdHJpY3RgIGlzIHNldCB0byBgdHJ1ZWAgb25seSBzaWJsaW5nIG5vZGVzIGFyZSByZXR1cm5lZC5cclxuXHRcdCAqIEBuYW1lIGdldF9uZXh0X2RvbShvYmogWywgc3RyaWN0XSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEBwYXJhbSAge0Jvb2xlYW59IHN0cmljdFxyXG5cdFx0ICogQHJldHVybiB7alF1ZXJ5fVxyXG5cdFx0ICovXHJcblx0XHRnZXRfbmV4dF9kb20gOiBmdW5jdGlvbiAob2JqLCBzdHJpY3QpIHtcclxuXHRcdFx0dmFyIHRtcDtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpO1xyXG5cdFx0XHRpZihvYmpbMF0gPT09IHRoaXMuZWxlbWVudFswXSkge1xyXG5cdFx0XHRcdHRtcCA9IHRoaXMuX2ZpcnN0Q2hpbGQodGhpcy5nZXRfY29udGFpbmVyX3VsKClbMF0pO1xyXG5cdFx0XHRcdHJldHVybiB0bXAgPyAkKHRtcCkgOiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZighb2JqIHx8ICFvYmoubGVuZ3RoKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHN0cmljdCkge1xyXG5cdFx0XHRcdHRtcCA9IHRoaXMuX25leHRTaWJsaW5nKG9ialswXSk7XHJcblx0XHRcdFx0cmV0dXJuIHRtcCA/ICQodG1wKSA6IGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKG9iai5oYXNDbGFzcyhcImpzdHJlZS1vcGVuXCIpKSB7XHJcblx0XHRcdFx0dG1wID0gdGhpcy5fZmlyc3RDaGlsZChvYmouY2hpbGRyZW4oJ3VsJylbMF0pO1xyXG5cdFx0XHRcdHJldHVybiB0bXAgPyAkKHRtcCkgOiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZigodG1wID0gdGhpcy5fbmV4dFNpYmxpbmcob2JqWzBdKSkgIT09IG51bGwpIHtcclxuXHRcdFx0XHRyZXR1cm4gJCh0bXApO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBvYmoucGFyZW50c1VudGlsKFwiLmpzdHJlZVwiLFwibGlcIikubmV4dChcImxpXCIpLmVxKDApO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0IHRoZSBwcmV2aW91cyB2aXNpYmxlIG5vZGUgdGhhdCBpcyBhYm92ZSB0aGUgYG9iamAgbm9kZS4gSWYgYHN0cmljdGAgaXMgc2V0IHRvIGB0cnVlYCBvbmx5IHNpYmxpbmcgbm9kZXMgYXJlIHJldHVybmVkLlxyXG5cdFx0ICogQG5hbWUgZ2V0X3ByZXZfZG9tKG9iaiBbLCBzdHJpY3RdKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHBhcmFtICB7Qm9vbGVhbn0gc3RyaWN0XHJcblx0XHQgKiBAcmV0dXJuIHtqUXVlcnl9XHJcblx0XHQgKi9cclxuXHRcdGdldF9wcmV2X2RvbSA6IGZ1bmN0aW9uIChvYmosIHN0cmljdCkge1xyXG5cdFx0XHR2YXIgdG1wO1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaiwgdHJ1ZSk7XHJcblx0XHRcdGlmKG9ialswXSA9PT0gdGhpcy5lbGVtZW50WzBdKSB7XHJcblx0XHRcdFx0dG1wID0gdGhpcy5nZXRfY29udGFpbmVyX3VsKClbMF0ubGFzdENoaWxkO1xyXG5cdFx0XHRcdHJldHVybiB0bXAgPyAkKHRtcCkgOiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZighb2JqIHx8ICFvYmoubGVuZ3RoKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHN0cmljdCkge1xyXG5cdFx0XHRcdHRtcCA9IHRoaXMuX3ByZXZpb3VzU2libGluZyhvYmpbMF0pO1xyXG5cdFx0XHRcdHJldHVybiB0bXAgPyAkKHRtcCkgOiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZigodG1wID0gdGhpcy5fcHJldmlvdXNTaWJsaW5nKG9ialswXSkpICE9PSBudWxsKSB7XHJcblx0XHRcdFx0b2JqID0gJCh0bXApO1xyXG5cdFx0XHRcdHdoaWxlKG9iai5oYXNDbGFzcyhcImpzdHJlZS1vcGVuXCIpKSB7XHJcblx0XHRcdFx0XHRvYmogPSBvYmouY2hpbGRyZW4oXCJ1bDplcSgwKVwiKS5jaGlsZHJlbihcImxpOmxhc3RcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiBvYmo7XHJcblx0XHRcdH1cclxuXHRcdFx0dG1wID0gb2JqWzBdLnBhcmVudE5vZGUucGFyZW50Tm9kZTtcclxuXHRcdFx0cmV0dXJuIHRtcCAmJiB0bXAudGFnTmFtZSA9PT0gJ0xJJyA/ICQodG1wKSA6IGZhbHNlO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0IHRoZSBwYXJlbnQgSUQgb2YgYSBub2RlXHJcblx0XHQgKiBAbmFtZSBnZXRfcGFyZW50KG9iailcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEByZXR1cm4ge1N0cmluZ31cclxuXHRcdCAqL1xyXG5cdFx0Z2V0X3BhcmVudCA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBvYmoucGFyZW50O1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0IGEgalF1ZXJ5IGNvbGxlY3Rpb24gb2YgYWxsIHRoZSBjaGlsZHJlbiBvZiBhIG5vZGUgKG5vZGUgbXVzdCBiZSByZW5kZXJlZClcclxuXHRcdCAqIEBuYW1lIGdldF9jaGlsZHJlbl9kb20ob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHJldHVybiB7alF1ZXJ5fVxyXG5cdFx0ICovXHJcblx0XHRnZXRfY2hpbGRyZW5fZG9tIDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaiwgdHJ1ZSk7XHJcblx0XHRcdGlmKG9ialswXSA9PT0gdGhpcy5lbGVtZW50WzBdKSB7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMuZ2V0X2NvbnRhaW5lcl91bCgpLmNoaWxkcmVuKFwibGlcIik7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIW9iaiB8fCAhb2JqLmxlbmd0aCkge1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gb2JqLmNoaWxkcmVuKFwidWxcIikuY2hpbGRyZW4oXCJsaVwiKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNoZWNrcyBpZiBhIG5vZGUgaGFzIGNoaWxkcmVuXHJcblx0XHQgKiBAbmFtZSBpc19wYXJlbnQob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHJldHVybiB7Qm9vbGVhbn1cclxuXHRcdCAqL1xyXG5cdFx0aXNfcGFyZW50IDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdHJldHVybiBvYmogJiYgKG9iai5zdGF0ZS5sb2FkZWQgPT09IGZhbHNlIHx8IG9iai5jaGlsZHJlbi5sZW5ndGggPiAwKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNoZWNrcyBpZiBhIG5vZGUgaXMgbG9hZGVkIChpdHMgY2hpbGRyZW4gYXJlIGF2YWlsYWJsZSlcclxuXHRcdCAqIEBuYW1lIGlzX2xvYWRlZChvYmopXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRpc19sb2FkZWQgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0cmV0dXJuIG9iaiAmJiBvYmouc3RhdGUubG9hZGVkO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY2hlY2sgaWYgYSBub2RlIGlzIGN1cnJlbnRseSBsb2FkaW5nIChmZXRjaGluZyBjaGlsZHJlbilcclxuXHRcdCAqIEBuYW1lIGlzX2xvYWRpbmcob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHJldHVybiB7Qm9vbGVhbn1cclxuXHRcdCAqL1xyXG5cdFx0aXNfbG9hZGluZyA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpO1xyXG5cdFx0XHRyZXR1cm4gb2JqICYmIG9iai5oYXNDbGFzcyhcImpzdHJlZS1sb2FkaW5nXCIpO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY2hlY2sgaWYgYSBub2RlIGlzIG9wZW5lZFxyXG5cdFx0ICogQG5hbWUgaXNfb3BlbihvYmopXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRpc19vcGVuIDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdHJldHVybiBvYmogJiYgb2JqLnN0YXRlLm9wZW5lZDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNoZWNrIGlmIGEgbm9kZSBpcyBpbiBhIGNsb3NlZCBzdGF0ZVxyXG5cdFx0ICogQG5hbWUgaXNfY2xvc2VkKG9iailcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEByZXR1cm4ge0Jvb2xlYW59XHJcblx0XHQgKi9cclxuXHRcdGlzX2Nsb3NlZCA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRyZXR1cm4gb2JqICYmIHRoaXMuaXNfcGFyZW50KG9iaikgJiYgIW9iai5zdGF0ZS5vcGVuZWQ7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBjaGVjayBpZiBhIG5vZGUgaGFzIG5vIGNoaWxkcmVuXHJcblx0XHQgKiBAbmFtZSBpc19sZWFmKG9iailcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEByZXR1cm4ge0Jvb2xlYW59XHJcblx0XHQgKi9cclxuXHRcdGlzX2xlYWYgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdHJldHVybiAhdGhpcy5pc19wYXJlbnQob2JqKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGxvYWRzIGEgbm9kZSAoZmV0Y2hlcyBpdHMgY2hpbGRyZW4gdXNpbmcgdGhlIGBjb3JlLmRhdGFgIHNldHRpbmcpLiBNdWx0aXBsZSBub2RlcyBjYW4gYmUgcGFzc2VkIHRvIGJ5IHVzaW5nIGFuIGFycmF5LlxyXG5cdFx0ICogQG5hbWUgbG9hZF9ub2RlKG9iaiBbLCBjYWxsYmFja10pXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAcGFyYW0gIHtmdW5jdGlvbn0gY2FsbGJhY2sgYSBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmNlIGxvYWRpbmcgaXMgY29ucGxldGUsIHRoZSBmdW5jdGlvbiBpcyBleGVjdXRlZCBpbiB0aGUgaW5zdGFuY2UncyBzY29wZSBhbmQgcmVjZWl2ZXMgdHdvIGFyZ3VtZW50cyAtIHRoZSBub2RlIGFuZCBhIGJvb2xlYW4gc3RhdHVzXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICogQHRyaWdnZXIgbG9hZF9ub2RlLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRsb2FkX25vZGUgOiBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaykge1xyXG5cdFx0XHR2YXIgdDEsIHQyO1xyXG5cdFx0XHRpZigkLmlzQXJyYXkob2JqKSkge1xyXG5cdFx0XHRcdG9iaiA9IG9iai5zbGljZSgpO1xyXG5cdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0dGhpcy5sb2FkX25vZGUob2JqW3QxXSwgY2FsbGJhY2spO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmopIHtcclxuXHRcdFx0XHRjYWxsYmFjay5jYWxsKHRoaXMsIG9iaiwgZmFsc2UpO1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHR0aGlzLmdldF9ub2RlKG9iaiwgdHJ1ZSkuYWRkQ2xhc3MoXCJqc3RyZWUtbG9hZGluZ1wiKTtcclxuXHRcdFx0dGhpcy5fbG9hZF9ub2RlKG9iaiwgJC5wcm94eShmdW5jdGlvbiAoc3RhdHVzKSB7XHJcblx0XHRcdFx0b2JqLnN0YXRlLmxvYWRlZCA9IHN0YXR1cztcclxuXHRcdFx0XHR0aGlzLmdldF9ub2RlKG9iaiwgdHJ1ZSkucmVtb3ZlQ2xhc3MoXCJqc3RyZWUtbG9hZGluZ1wiKTtcclxuXHRcdFx0XHQvKipcclxuXHRcdFx0XHQgKiB0cmlnZ2VyZWQgYWZ0ZXIgYSBub2RlIGlzIGxvYWRlZFxyXG5cdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdCAqIEBuYW1lIGxvYWRfbm9kZS5qc3RyZWVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZSB0aGUgbm9kZSB0aGF0IHdhcyBsb2FkaW5nXHJcblx0XHRcdFx0ICogQHBhcmFtIHtCb29sZWFufSBzdGF0dXMgd2FzIHRoZSBub2RlIGxvYWRlZCBzdWNjZXNzZnVsbHlcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoJ2xvYWRfbm9kZScsIHsgXCJub2RlXCIgOiBvYmosIFwic3RhdHVzXCIgOiBzdGF0dXMgfSk7XHJcblx0XHRcdFx0aWYoY2FsbGJhY2spIHtcclxuXHRcdFx0XHRcdGNhbGxiYWNrLmNhbGwodGhpcywgb2JqLCBzdGF0dXMpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGhhbmRsZXMgdGhlIGFjdHVhbCBsb2FkaW5nIG9mIGEgbm9kZS4gVXNlZCBvbmx5IGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgX2xvYWRfbm9kZShvYmogWywgY2FsbGJhY2tdKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHBhcmFtICB7ZnVuY3Rpb259IGNhbGxiYWNrIGEgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgb25jZSBsb2FkaW5nIGlzIGNvbnBsZXRlLCB0aGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgaW4gdGhlIGluc3RhbmNlJ3Mgc2NvcGUgYW5kIHJlY2VpdmVzIG9uZSBhcmd1bWVudCAtIGEgYm9vbGVhbiBzdGF0dXNcclxuXHRcdCAqIEByZXR1cm4ge0Jvb2xlYW59XHJcblx0XHQgKi9cclxuXHRcdF9sb2FkX25vZGUgOiBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaykge1xyXG5cdFx0XHR2YXIgcyA9IHRoaXMuc2V0dGluZ3MuY29yZS5kYXRhLCB0O1xyXG5cdFx0XHQvLyB1c2Ugb3JpZ2luYWwgSFRNTFxyXG5cdFx0XHRpZighcykge1xyXG5cdFx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKHRoaXMsIG9iai5pZCA9PT0gJyMnID8gdGhpcy5fYXBwZW5kX2h0bWxfZGF0YShvYmosIHRoaXMuX2RhdGEuY29yZS5vcmlnaW5hbF9jb250YWluZXJfaHRtbC5jbG9uZSh0cnVlKSkgOiBmYWxzZSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoJC5pc0Z1bmN0aW9uKHMpKSB7XHJcblx0XHRcdFx0cmV0dXJuIHMuY2FsbCh0aGlzLCBvYmosICQucHJveHkoZnVuY3Rpb24gKGQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBkID09PSBmYWxzZSA/IGNhbGxiYWNrLmNhbGwodGhpcywgZmFsc2UpIDogY2FsbGJhY2suY2FsbCh0aGlzLCB0aGlzW3R5cGVvZiBkID09PSAnc3RyaW5nJyA/ICdfYXBwZW5kX2h0bWxfZGF0YScgOiAnX2FwcGVuZF9qc29uX2RhdGEnXShvYmosIHR5cGVvZiBkID09PSAnc3RyaW5nJyA/ICQoZCkgOiBkKSk7XHJcblx0XHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHR5cGVvZiBzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRcdGlmKHMudXJsKSB7XHJcblx0XHRcdFx0XHRzID0gJC5leHRlbmQodHJ1ZSwge30sIHMpO1xyXG5cdFx0XHRcdFx0aWYoJC5pc0Z1bmN0aW9uKHMudXJsKSkge1xyXG5cdFx0XHRcdFx0XHRzLnVybCA9IHMudXJsLmNhbGwodGhpcywgb2JqKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmKCQuaXNGdW5jdGlvbihzLmRhdGEpKSB7XHJcblx0XHRcdFx0XHRcdHMuZGF0YSA9IHMuZGF0YS5jYWxsKHRoaXMsIG9iaik7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRyZXR1cm4gJC5hamF4KHMpXHJcblx0XHRcdFx0XHRcdC5kb25lKCQucHJveHkoZnVuY3Rpb24gKGQsdCx4KSB7XHJcblx0XHRcdFx0XHRcdFx0XHR2YXIgdHlwZSA9IHguZ2V0UmVzcG9uc2VIZWFkZXIoJ0NvbnRlbnQtVHlwZScpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYodHlwZS5pbmRleE9mKCdqc29uJykgIT09IC0xKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKHRoaXMsIHRoaXMuX2FwcGVuZF9qc29uX2RhdGEob2JqLCBkKSk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRpZih0eXBlLmluZGV4T2YoJ2h0bWwnKSAhPT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGNhbGxiYWNrLmNhbGwodGhpcywgdGhpcy5fYXBwZW5kX2h0bWxfZGF0YShvYmosICQoZCkpKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHRcdFx0LmZhaWwoJC5wcm94eShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRjYWxsYmFjay5jYWxsKHRoaXMsIGZhbHNlKTtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yID0geyAnZXJyb3InIDogJ2FqYXgnLCAncGx1Z2luJyA6ICdjb3JlJywgJ2lkJyA6ICdjb3JlXzA0JywgJ3JlYXNvbicgOiAnQ291bGQgbm90IGxvYWQgbm9kZScsICdkYXRhJyA6IEpTT04uc3RyaW5naWZ5KHMpIH07XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLmNvcmUuZXJyb3IuY2FsbCh0aGlzLCB0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvcik7XHJcblx0XHRcdFx0XHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR0ID0gKCQuaXNBcnJheShzKSB8fCAkLmlzUGxhaW5PYmplY3QocykpID8gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShzKSkgOiBzO1xyXG5cdFx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKHRoaXMsIHRoaXMuX2FwcGVuZF9qc29uX2RhdGEob2JqLCB0KSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYodHlwZW9mIHMgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGNhbGxiYWNrLmNhbGwodGhpcywgdGhpcy5fYXBwZW5kX2h0bWxfZGF0YShvYmosIHMpKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gY2FsbGJhY2suY2FsbCh0aGlzLCBmYWxzZSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBhZGRzIGEgbm9kZSB0byB0aGUgbGlzdCBvZiBub2RlcyB0byByZWRyYXcuIFVzZWQgb25seSBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIF9ub2RlX2NoYW5nZWQob2JqIFssIGNhbGxiYWNrXSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqL1xyXG5cdFx0X25vZGVfY2hhbmdlZCA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZihvYmopIHtcclxuXHRcdFx0XHR0aGlzLl9tb2RlbC5jaGFuZ2VkLnB1c2gob2JqLmlkKTtcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogYXBwZW5kcyBIVE1MIGNvbnRlbnQgdG8gdGhlIHRyZWUuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBfYXBwZW5kX2h0bWxfZGF0YShvYmosIGRhdGEpXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIGFwcGVuZCB0b1xyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBkYXRhIHRoZSBIVE1MIHN0cmluZyB0byBwYXJzZSBhbmQgYXBwZW5kXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICogQHRyaWdnZXIgbW9kZWwuanN0cmVlLCBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRfYXBwZW5kX2h0bWxfZGF0YSA6IGZ1bmN0aW9uIChkb20sIGRhdGEpIHtcclxuXHRcdFx0ZG9tID0gdGhpcy5nZXRfbm9kZShkb20pO1xyXG5cdFx0XHRkb20uY2hpbGRyZW4gPSBbXTtcclxuXHRcdFx0ZG9tLmNoaWxkcmVuX2QgPSBbXTtcclxuXHRcdFx0dmFyIGRhdCA9IGRhdGEuaXMoJ3VsJykgPyBkYXRhLmNoaWxkcmVuKCkgOiBkYXRhLFxyXG5cdFx0XHRcdHBhciA9IGRvbS5pZCxcclxuXHRcdFx0XHRjaGQgPSBbXSxcclxuXHRcdFx0XHRkcGMgPSBbXSxcclxuXHRcdFx0XHRtID0gdGhpcy5fbW9kZWwuZGF0YSxcclxuXHRcdFx0XHRwID0gbVtwYXJdLFxyXG5cdFx0XHRcdHMgPSB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQubGVuZ3RoLFxyXG5cdFx0XHRcdHRtcCwgaSwgajtcclxuXHRcdFx0ZGF0LmVhY2goJC5wcm94eShmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdHRtcCA9IHRoaXMuX3BhcnNlX21vZGVsX2Zyb21faHRtbCgkKHYpLCBwYXIsIHAucGFyZW50cy5jb25jYXQoKSk7XHJcblx0XHRcdFx0aWYodG1wKSB7XHJcblx0XHRcdFx0XHRjaGQucHVzaCh0bXApO1xyXG5cdFx0XHRcdFx0ZHBjLnB1c2godG1wKTtcclxuXHRcdFx0XHRcdGlmKG1bdG1wXS5jaGlsZHJlbl9kLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRkcGMgPSBkcGMuY29uY2F0KG1bdG1wXS5jaGlsZHJlbl9kKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdFx0cC5jaGlsZHJlbiA9IGNoZDtcclxuXHRcdFx0cC5jaGlsZHJlbl9kID0gZHBjO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSBwLnBhcmVudHMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0bVtwLnBhcmVudHNbaV1dLmNoaWxkcmVuX2QgPSBtW3AucGFyZW50c1tpXV0uY2hpbGRyZW5fZC5jb25jYXQoZHBjKTtcclxuXHRcdFx0fVxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gbmV3IGRhdGEgaXMgaW5zZXJ0ZWQgdG8gdGhlIHRyZWUgbW9kZWxcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIG1vZGVsLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge0FycmF5fSBub2RlcyBhbiBhcnJheSBvZiBub2RlIElEc1xyXG5cdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gcGFyZW50IHRoZSBwYXJlbnQgSUQgb2YgdGhlIG5vZGVzXHJcblx0XHRcdCAqL1xyXG5cdFx0XHR0aGlzLnRyaWdnZXIoJ21vZGVsJywgeyBcIm5vZGVzXCIgOiBkcGMsICdwYXJlbnQnIDogcGFyIH0pO1xyXG5cdFx0XHRpZihwYXIgIT09ICcjJykge1xyXG5cdFx0XHRcdHRoaXMuX25vZGVfY2hhbmdlZChwYXIpO1xyXG5cdFx0XHRcdHRoaXMucmVkcmF3KCk7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0dGhpcy5nZXRfY29udGFpbmVyX3VsKCkuY2hpbGRyZW4oJy5qc3RyZWUtaW5pdGlhbC1ub2RlJykucmVtb3ZlKCk7XHJcblx0XHRcdFx0dGhpcy5yZWRyYXcodHJ1ZSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYodGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmxlbmd0aCAhPT0gcykge1xyXG5cdFx0XHRcdHRoaXMudHJpZ2dlcignY2hhbmdlZCcsIHsgJ2FjdGlvbicgOiAnbW9kZWwnLCAnc2VsZWN0ZWQnIDogdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkIH0pO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogYXBwZW5kcyBKU09OIGNvbnRlbnQgdG8gdGhlIHRyZWUuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBfYXBwZW5kX2pzb25fZGF0YShvYmosIGRhdGEpXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIGFwcGVuZCB0b1xyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBkYXRhIHRoZSBKU09OIG9iamVjdCB0byBwYXJzZSBhbmQgYXBwZW5kXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRfYXBwZW5kX2pzb25fZGF0YSA6IGZ1bmN0aW9uIChkb20sIGRhdGEpIHtcclxuXHRcdFx0ZG9tID0gdGhpcy5nZXRfbm9kZShkb20pO1xyXG5cdFx0XHRkb20uY2hpbGRyZW4gPSBbXTtcclxuXHRcdFx0ZG9tLmNoaWxkcmVuX2QgPSBbXTtcclxuXHRcdFx0dmFyIGRhdCA9IGRhdGEsXHJcblx0XHRcdFx0cGFyID0gZG9tLmlkLFxyXG5cdFx0XHRcdGNoZCA9IFtdLFxyXG5cdFx0XHRcdGRwYyA9IFtdLFxyXG5cdFx0XHRcdG0gPSB0aGlzLl9tb2RlbC5kYXRhLFxyXG5cdFx0XHRcdHAgPSBtW3Bhcl0sXHJcblx0XHRcdFx0cyA9IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZC5sZW5ndGgsXHJcblx0XHRcdFx0dG1wLCBpLCBqO1xyXG5cdFx0XHQvLyAqJSRAISEhXHJcblx0XHRcdGlmKGRhdC5kKSB7XHJcblx0XHRcdFx0ZGF0ID0gZGF0LmQ7XHJcblx0XHRcdFx0aWYodHlwZW9mIGRhdCA9PT0gXCJzdHJpbmdcIikge1xyXG5cdFx0XHRcdFx0ZGF0ID0gSlNPTi5wYXJzZShkYXQpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZighJC5pc0FycmF5KGRhdCkpIHsgZGF0ID0gW2RhdF07IH1cclxuXHRcdFx0aWYoZGF0Lmxlbmd0aCAmJiBkYXRbMF0uaWQgIT09IHVuZGVmaW5lZCAmJiBkYXRbMF0ucGFyZW50ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHQvLyBGbGF0IEpTT04gc3VwcG9ydCAoZm9yIGVhc3kgaW1wb3J0IGZyb20gREIpOlxyXG5cdFx0XHRcdC8vIDEpIGNvbnZlcnQgdG8gb2JqZWN0IChmb3JlYWNoKVxyXG5cdFx0XHRcdGZvcihpID0gMCwgaiA9IGRhdC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdGlmKCFkYXRbaV0uY2hpbGRyZW4pIHtcclxuXHRcdFx0XHRcdFx0ZGF0W2ldLmNoaWxkcmVuID0gW107XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRtW2RhdFtpXS5pZF0gPSBkYXRbaV07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdC8vIDIpIHBvcHVsYXRlIGNoaWxkcmVuIChmb3JlYWNoKVxyXG5cdFx0XHRcdGZvcihpID0gMCwgaiA9IGRhdC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdG1bZGF0W2ldLnBhcmVudF0uY2hpbGRyZW4ucHVzaChkYXRbaV0uaWQpO1xyXG5cdFx0XHRcdFx0Ly8gcG9wdWxhdGUgcGFyZW50LmNoaWxkcmVuX2RcclxuXHRcdFx0XHRcdHAuY2hpbGRyZW5fZC5wdXNoKGRhdFtpXS5pZCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdC8vIDMpIG5vcm1hbGl6ZSAmJiBwb3B1bGF0ZSBwYXJlbnRzIGFuZCBjaGlsZHJlbl9kIHdpdGggcmVjdXJzaW9uXHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gcC5jaGlsZHJlbi5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdHRtcCA9IHRoaXMuX3BhcnNlX21vZGVsX2Zyb21fZmxhdF9qc29uKG1bcC5jaGlsZHJlbltpXV0sIHBhciwgcC5wYXJlbnRzLmNvbmNhdCgpKTtcclxuXHRcdFx0XHRcdGRwYy5wdXNoKHRtcCk7XHJcblx0XHRcdFx0XHRpZihtW3RtcF0uY2hpbGRyZW5fZC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0ZHBjID0gZHBjLmNvbmNhdChtW3RtcF0uY2hpbGRyZW5fZCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdC8vID8pIHRocmVlX3N0YXRlIHNlbGVjdGlvbiAtIHAuc3RhdGUuc2VsZWN0ZWQgJiYgdCAtIChpZiB0aHJlZV9zdGF0ZSBmb3JlYWNoKGRhdCA9PiBjaCkgLT4gZm9yZWFjaChwYXJlbnRzKSBpZihwYXJlbnQuc2VsZWN0ZWQpIGNoaWxkLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSBkYXQubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHR0bXAgPSB0aGlzLl9wYXJzZV9tb2RlbF9mcm9tX2pzb24oZGF0W2ldLCBwYXIsIHAucGFyZW50cy5jb25jYXQoKSk7XHJcblx0XHRcdFx0XHRpZih0bXApIHtcclxuXHRcdFx0XHRcdFx0Y2hkLnB1c2godG1wKTtcclxuXHRcdFx0XHRcdFx0ZHBjLnB1c2godG1wKTtcclxuXHRcdFx0XHRcdFx0aWYobVt0bXBdLmNoaWxkcmVuX2QubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0ZHBjID0gZHBjLmNvbmNhdChtW3RtcF0uY2hpbGRyZW5fZCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cC5jaGlsZHJlbiA9IGNoZDtcclxuXHRcdFx0XHRwLmNoaWxkcmVuX2QgPSBkcGM7XHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gcC5wYXJlbnRzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0bVtwLnBhcmVudHNbaV1dLmNoaWxkcmVuX2QgPSBtW3AucGFyZW50c1tpXV0uY2hpbGRyZW5fZC5jb25jYXQoZHBjKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdtb2RlbCcsIHsgXCJub2Rlc1wiIDogZHBjLCAncGFyZW50JyA6IHBhciB9KTtcclxuXHJcblx0XHRcdGlmKHBhciAhPT0gJyMnKSB7XHJcblx0XHRcdFx0dGhpcy5fbm9kZV9jaGFuZ2VkKHBhcik7XHJcblx0XHRcdFx0dGhpcy5yZWRyYXcoKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHQvLyB0aGlzLmdldF9jb250YWluZXJfdWwoKS5jaGlsZHJlbignLmpzdHJlZS1pbml0aWFsLW5vZGUnKS5yZW1vdmUoKTtcclxuXHRcdFx0XHR0aGlzLnJlZHJhdyh0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZih0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQubGVuZ3RoICE9PSBzKSB7XHJcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCdjaGFuZ2VkJywgeyAnYWN0aW9uJyA6ICdtb2RlbCcsICdzZWxlY3RlZCcgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQgfSk7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBwYXJzZXMgYSBub2RlIGZyb20gYSBqUXVlcnkgb2JqZWN0IGFuZCBhcHBlbmRzIHRoZW0gdG8gdGhlIGluIG1lbW9yeSB0cmVlIG1vZGVsLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgX3BhcnNlX21vZGVsX2Zyb21faHRtbChkIFssIHAsIHBzXSlcclxuXHRcdCAqIEBwYXJhbSAge2pRdWVyeX0gZCB0aGUgalF1ZXJ5IG9iamVjdCB0byBwYXJzZVxyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBwIHRoZSBwYXJlbnQgSURcclxuXHRcdCAqIEBwYXJhbSAge0FycmF5fSBwcyBsaXN0IG9mIGFsbCBwYXJlbnRzXHJcblx0XHQgKiBAcmV0dXJuIHtTdHJpbmd9IHRoZSBJRCBvZiB0aGUgb2JqZWN0IGFkZGVkIHRvIHRoZSBtb2RlbFxyXG5cdFx0ICovXHJcblx0XHRfcGFyc2VfbW9kZWxfZnJvbV9odG1sIDogZnVuY3Rpb24gKGQsIHAsIHBzKSB7XHJcblx0XHRcdGlmKCFwcykgeyBwcyA9IFtdOyB9XHJcblx0XHRcdGVsc2UgeyBwcyA9IFtdLmNvbmNhdChwcyk7IH1cclxuXHRcdFx0aWYocCkgeyBwcy51bnNoaWZ0KHApOyB9XHJcblx0XHRcdHZhciBjLCBlLCBtID0gdGhpcy5fbW9kZWwuZGF0YSxcclxuXHRcdFx0XHRkYXRhID0ge1xyXG5cdFx0XHRcdFx0aWRcdFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0dGV4dFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0aWNvblx0XHQ6IHRydWUsXHJcblx0XHRcdFx0XHRwYXJlbnRcdFx0OiBwLFxyXG5cdFx0XHRcdFx0cGFyZW50c1x0XHQ6IHBzLFxyXG5cdFx0XHRcdFx0Y2hpbGRyZW5cdDogW10sXHJcblx0XHRcdFx0XHRjaGlsZHJlbl9kXHQ6IFtdLFxyXG5cdFx0XHRcdFx0ZGF0YVx0XHQ6IG51bGwsXHJcblx0XHRcdFx0XHRzdGF0ZVx0XHQ6IHsgfSxcclxuXHRcdFx0XHRcdGxpX2F0dHJcdFx0OiB7IGlkIDogZmFsc2UgfSxcclxuXHRcdFx0XHRcdGFfYXR0clx0XHQ6IHsgaHJlZiA6ICcjJyB9LFxyXG5cdFx0XHRcdFx0b3JpZ2luYWxcdDogZmFsc2VcclxuXHRcdFx0XHR9LCBpLCB0bXAsIHRpZDtcclxuXHRcdFx0Zm9yKGkgaW4gdGhpcy5fbW9kZWwuZGVmYXVsdF9zdGF0ZSkge1xyXG5cdFx0XHRcdGlmKHRoaXMuX21vZGVsLmRlZmF1bHRfc3RhdGUuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuXHRcdFx0XHRcdGRhdGEuc3RhdGVbaV0gPSB0aGlzLl9tb2RlbC5kZWZhdWx0X3N0YXRlW2ldO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHR0bXAgPSAkLnZha2F0YS5hdHRyaWJ1dGVzKGQsIHRydWUpO1xyXG5cdFx0XHQkLmVhY2godG1wLCBmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdHYgPSAkLnRyaW0odik7XHJcblx0XHRcdFx0aWYoIXYubGVuZ3RoKSB7IHJldHVybiB0cnVlOyB9XHJcblx0XHRcdFx0ZGF0YS5saV9hdHRyW2ldID0gdjtcclxuXHRcdFx0XHRpZihpID09PSAnaWQnKSB7XHJcblx0XHRcdFx0XHRkYXRhLmlkID0gdjtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0XHR0bXAgPSBkLmNoaWxkcmVuKCdhJykuZXEoMCk7XHJcblx0XHRcdGlmKHRtcC5sZW5ndGgpIHtcclxuXHRcdFx0XHR0bXAgPSAkLnZha2F0YS5hdHRyaWJ1dGVzKHRtcCwgdHJ1ZSk7XHJcblx0XHRcdFx0JC5lYWNoKHRtcCwgZnVuY3Rpb24gKGksIHYpIHtcclxuXHRcdFx0XHRcdHYgPSAkLnRyaW0odik7XHJcblx0XHRcdFx0XHRpZih2Lmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRkYXRhLmFfYXR0cltpXSA9IHY7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSk7XHJcblx0XHRcdH1cclxuXHRcdFx0dG1wID0gZC5jaGlsZHJlbihcImE6ZXEoMClcIikubGVuZ3RoID8gZC5jaGlsZHJlbihcImE6ZXEoMClcIikuY2xvbmUoKSA6IGQuY2xvbmUoKTtcclxuXHRcdFx0dG1wLmNoaWxkcmVuKFwiaW5zLCBpLCB1bFwiKS5yZW1vdmUoKTtcclxuXHRcdFx0dG1wID0gdG1wLmh0bWwoKTtcclxuXHRcdFx0dG1wID0gJCgnPGRpdiAvPicpLmh0bWwodG1wKTtcclxuXHRcdFx0ZGF0YS50ZXh0ID0gdG1wLmh0bWwoKTtcclxuXHRcdFx0dG1wID0gZC5kYXRhKCk7XHJcblx0XHRcdGRhdGEuZGF0YSA9IHRtcCA/ICQuZXh0ZW5kKHRydWUsIHt9LCB0bXApIDogbnVsbDtcclxuXHRcdFx0ZGF0YS5zdGF0ZS5vcGVuZWQgPSBkLmhhc0NsYXNzKCdqc3RyZWUtb3BlbicpO1xyXG5cdFx0XHRkYXRhLnN0YXRlLnNlbGVjdGVkID0gZC5jaGlsZHJlbignYScpLmhhc0NsYXNzKCdqc3RyZWUtY2xpY2tlZCcpO1xyXG5cdFx0XHRkYXRhLnN0YXRlLmRpc2FibGVkID0gZC5jaGlsZHJlbignYScpLmhhc0NsYXNzKCdqc3RyZWUtZGlzYWJsZWQnKTtcclxuXHRcdFx0aWYoZGF0YS5kYXRhICYmIGRhdGEuZGF0YS5qc3RyZWUpIHtcclxuXHRcdFx0XHRmb3IoaSBpbiBkYXRhLmRhdGEuanN0cmVlKSB7XHJcblx0XHRcdFx0XHRpZihkYXRhLmRhdGEuanN0cmVlLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHRcdGRhdGEuc3RhdGVbaV0gPSBkYXRhLmRhdGEuanN0cmVlW2ldO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHR0bXAgPSBkLmNoaWxkcmVuKFwiYVwiKS5jaGlsZHJlbihcIi5qc3RyZWUtdGhlbWVpY29uXCIpO1xyXG5cdFx0XHRpZih0bXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0ZGF0YS5pY29uID0gdG1wLmhhc0NsYXNzKCdqc3RyZWUtdGhlbWVpY29uLWhpZGRlbicpID8gZmFsc2UgOiB0bXAuYXR0cigncmVsJyk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZGF0YS5zdGF0ZS5pY29uKSB7XHJcblx0XHRcdFx0ZGF0YS5pY29uID0gZGF0YS5zdGF0ZS5pY29uO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRtcCA9IGQuY2hpbGRyZW4oXCJ1bFwiKS5jaGlsZHJlbihcImxpXCIpO1xyXG5cdFx0XHRkbyB7XHJcblx0XHRcdFx0dGlkID0gJ2onICsgdGhpcy5faWQgKyAnXycgKyAoKyt0aGlzLl9jbnQpO1xyXG5cdFx0XHR9IHdoaWxlKG1bdGlkXSk7XHJcblx0XHRcdGRhdGEuaWQgPSBkYXRhLmxpX2F0dHIuaWQgfHwgdGlkO1xyXG5cdFx0XHRpZih0bXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0dG1wLmVhY2goJC5wcm94eShmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdFx0YyA9IHRoaXMuX3BhcnNlX21vZGVsX2Zyb21faHRtbCgkKHYpLCBkYXRhLmlkLCBwcyk7XHJcblx0XHRcdFx0XHRlID0gdGhpcy5fbW9kZWwuZGF0YVtjXTtcclxuXHRcdFx0XHRcdGRhdGEuY2hpbGRyZW4ucHVzaChjKTtcclxuXHRcdFx0XHRcdGlmKGUuY2hpbGRyZW5fZC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0ZGF0YS5jaGlsZHJlbl9kID0gZGF0YS5jaGlsZHJlbl9kLmNvbmNhdChlLmNoaWxkcmVuX2QpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdFx0XHRkYXRhLmNoaWxkcmVuX2QgPSBkYXRhLmNoaWxkcmVuX2QuY29uY2F0KGRhdGEuY2hpbGRyZW4pO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGlmKGQuaGFzQ2xhc3MoJ2pzdHJlZS1jbG9zZWQnKSkge1xyXG5cdFx0XHRcdFx0ZGF0YS5zdGF0ZS5sb2FkZWQgPSBmYWxzZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZGF0YS5saV9hdHRyWydjbGFzcyddKSB7XHJcblx0XHRcdFx0ZGF0YS5saV9hdHRyWydjbGFzcyddID0gZGF0YS5saV9hdHRyWydjbGFzcyddLnJlcGxhY2UoJ2pzdHJlZS1jbG9zZWQnLCcnKS5yZXBsYWNlKCdqc3RyZWUtb3BlbicsJycpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGRhdGEuYV9hdHRyWydjbGFzcyddKSB7XHJcblx0XHRcdFx0ZGF0YS5hX2F0dHJbJ2NsYXNzJ10gPSBkYXRhLmFfYXR0clsnY2xhc3MnXS5yZXBsYWNlKCdqc3RyZWUtY2xpY2tlZCcsJycpLnJlcGxhY2UoJ2pzdHJlZS1kaXNhYmxlZCcsJycpO1xyXG5cdFx0XHR9XHJcblx0XHRcdG1bZGF0YS5pZF0gPSBkYXRhO1xyXG5cdFx0XHRpZihkYXRhLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLnB1c2goZGF0YS5pZCk7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGRhdGEuaWQ7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBwYXJzZXMgYSBub2RlIGZyb20gYSBKU09OIG9iamVjdCAodXNlZCB3aGVuIGRlYWxpbmcgd2l0aCBmbGF0IGRhdGEsIHdoaWNoIGhhcyBubyBuZXN0aW5nIG9mIGNoaWxkcmVuLCBidXQgaGFzIGlkIGFuZCBwYXJlbnQgcHJvcGVydGllcykgYW5kIGFwcGVuZHMgaXQgdG8gdGhlIGluIG1lbW9yeSB0cmVlIG1vZGVsLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgX3BhcnNlX21vZGVsX2Zyb21fZmxhdF9qc29uKGQgWywgcCwgcHNdKVxyXG5cdFx0ICogQHBhcmFtICB7T2JqZWN0fSBkIHRoZSBKU09OIG9iamVjdCB0byBwYXJzZVxyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBwIHRoZSBwYXJlbnQgSURcclxuXHRcdCAqIEBwYXJhbSAge0FycmF5fSBwcyBsaXN0IG9mIGFsbCBwYXJlbnRzXHJcblx0XHQgKiBAcmV0dXJuIHtTdHJpbmd9IHRoZSBJRCBvZiB0aGUgb2JqZWN0IGFkZGVkIHRvIHRoZSBtb2RlbFxyXG5cdFx0ICovXHJcblx0XHRfcGFyc2VfbW9kZWxfZnJvbV9mbGF0X2pzb24gOiBmdW5jdGlvbiAoZCwgcCwgcHMpIHtcclxuXHRcdFx0aWYoIXBzKSB7IHBzID0gW107IH1cclxuXHRcdFx0ZWxzZSB7IHBzID0gcHMuY29uY2F0KCk7IH1cclxuXHRcdFx0aWYocCkgeyBwcy51bnNoaWZ0KHApOyB9XHJcblx0XHRcdHZhciB0aWQgPSBkLmlkLFxyXG5cdFx0XHRcdG0gPSB0aGlzLl9tb2RlbC5kYXRhLFxyXG5cdFx0XHRcdGRmID0gdGhpcy5fbW9kZWwuZGVmYXVsdF9zdGF0ZSxcclxuXHRcdFx0XHRpLCBqLCBjLCBlLFxyXG5cdFx0XHRcdHRtcCA9IHtcclxuXHRcdFx0XHRcdGlkXHRcdFx0OiB0aWQsXHJcblx0XHRcdFx0XHR0ZXh0XHRcdDogZC50ZXh0IHx8ICcnLFxyXG5cdFx0XHRcdFx0aWNvblx0XHQ6IGQuaWNvbiAhPT0gdW5kZWZpbmVkID8gZC5pY29uIDogdHJ1ZSxcclxuXHRcdFx0XHRcdHBhcmVudFx0XHQ6IHAsXHJcblx0XHRcdFx0XHRwYXJlbnRzXHRcdDogcHMsXHJcblx0XHRcdFx0XHRjaGlsZHJlblx0OiBkLmNoaWxkcmVuIHx8IFtdLFxyXG5cdFx0XHRcdFx0Y2hpbGRyZW5fZFx0OiBkLmNoaWxkcmVuX2QgfHwgW10sXHJcblx0XHRcdFx0XHRkYXRhXHRcdDogZC5kYXRhLFxyXG5cdFx0XHRcdFx0c3RhdGVcdFx0OiB7IH0sXHJcblx0XHRcdFx0XHRsaV9hdHRyXHRcdDogeyBpZCA6IGZhbHNlIH0sXHJcblx0XHRcdFx0XHRhX2F0dHJcdFx0OiB7IGhyZWYgOiAnIycgfSxcclxuXHRcdFx0XHRcdG9yaWdpbmFsXHQ6IGZhbHNlXHJcblx0XHRcdFx0fTtcclxuXHRcdFx0Zm9yKGkgaW4gZGYpIHtcclxuXHRcdFx0XHRpZihkZi5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0dG1wLnN0YXRlW2ldID0gZGZbaV07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGQgJiYgZC5kYXRhICYmIGQuZGF0YS5qc3RyZWUgJiYgZC5kYXRhLmpzdHJlZS5pY29uKSB7XHJcblx0XHRcdFx0dG1wLmljb24gPSBkLmRhdGEuanN0cmVlLmljb247XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiBkLmRhdGEpIHtcclxuXHRcdFx0XHR0bXAuZGF0YSA9IGQuZGF0YTtcclxuXHRcdFx0XHRpZihkLmRhdGEuanN0cmVlKSB7XHJcblx0XHRcdFx0XHRmb3IoaSBpbiBkLmRhdGEuanN0cmVlKSB7XHJcblx0XHRcdFx0XHRcdGlmKGQuZGF0YS5qc3RyZWUuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuXHRcdFx0XHRcdFx0XHR0bXAuc3RhdGVbaV0gPSBkLmRhdGEuanN0cmVlW2ldO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGQgJiYgdHlwZW9mIGQuc3RhdGUgPT09ICdvYmplY3QnKSB7XHJcblx0XHRcdFx0Zm9yIChpIGluIGQuc3RhdGUpIHtcclxuXHRcdFx0XHRcdGlmKGQuc3RhdGUuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuXHRcdFx0XHRcdFx0dG1wLnN0YXRlW2ldID0gZC5zdGF0ZVtpXTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiB0eXBlb2YgZC5saV9hdHRyID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRcdGZvciAoaSBpbiBkLmxpX2F0dHIpIHtcclxuXHRcdFx0XHRcdGlmKGQubGlfYXR0ci5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0XHR0bXAubGlfYXR0cltpXSA9IGQubGlfYXR0cltpXTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIXRtcC5saV9hdHRyLmlkKSB7XHJcblx0XHRcdFx0dG1wLmxpX2F0dHIuaWQgPSB0aWQ7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiB0eXBlb2YgZC5hX2F0dHIgPT09ICdvYmplY3QnKSB7XHJcblx0XHRcdFx0Zm9yIChpIGluIGQuYV9hdHRyKSB7XHJcblx0XHRcdFx0XHRpZihkLmFfYXR0ci5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0XHR0bXAuYV9hdHRyW2ldID0gZC5hX2F0dHJbaV07XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGQgJiYgZC5jaGlsZHJlbiAmJiBkLmNoaWxkcmVuID09PSB0cnVlKSB7XHJcblx0XHRcdFx0dG1wLnN0YXRlLmxvYWRlZCA9IGZhbHNlO1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbiA9IFtdO1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbl9kID0gW107XHJcblx0XHRcdH1cclxuXHRcdFx0bVt0bXAuaWRdID0gdG1wO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSB0bXAuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0YyA9IHRoaXMuX3BhcnNlX21vZGVsX2Zyb21fZmxhdF9qc29uKG1bdG1wLmNoaWxkcmVuW2ldXSwgdG1wLmlkLCBwcyk7XHJcblx0XHRcdFx0ZSA9IG1bY107XHJcblx0XHRcdFx0dG1wLmNoaWxkcmVuX2QucHVzaChjKTtcclxuXHRcdFx0XHRpZihlLmNoaWxkcmVuX2QubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHR0bXAuY2hpbGRyZW5fZCA9IHRtcC5jaGlsZHJlbl9kLmNvbmNhdChlLmNoaWxkcmVuX2QpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRkZWxldGUgZC5kYXRhO1xyXG5cdFx0XHRkZWxldGUgZC5jaGlsZHJlbjtcclxuXHRcdFx0bVt0bXAuaWRdLm9yaWdpbmFsID0gZDtcclxuXHRcdFx0aWYodG1wLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLnB1c2godG1wLmlkKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdG1wLmlkO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogcGFyc2VzIGEgbm9kZSBmcm9tIGEgSlNPTiBvYmplY3QgYW5kIGFwcGVuZHMgaXQgdG8gdGhlIGluIG1lbW9yeSB0cmVlIG1vZGVsLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgX3BhcnNlX21vZGVsX2Zyb21fanNvbihkIFssIHAsIHBzXSlcclxuXHRcdCAqIEBwYXJhbSAge09iamVjdH0gZCB0aGUgSlNPTiBvYmplY3QgdG8gcGFyc2VcclxuXHRcdCAqIEBwYXJhbSAge1N0cmluZ30gcCB0aGUgcGFyZW50IElEXHJcblx0XHQgKiBAcGFyYW0gIHtBcnJheX0gcHMgbGlzdCBvZiBhbGwgcGFyZW50c1xyXG5cdFx0ICogQHJldHVybiB7U3RyaW5nfSB0aGUgSUQgb2YgdGhlIG9iamVjdCBhZGRlZCB0byB0aGUgbW9kZWxcclxuXHRcdCAqL1xyXG5cdFx0X3BhcnNlX21vZGVsX2Zyb21fanNvbiA6IGZ1bmN0aW9uIChkLCBwLCBwcykge1xyXG5cdFx0XHRpZighcHMpIHsgcHMgPSBbXTsgfVxyXG5cdFx0XHRlbHNlIHsgcHMgPSBwcy5jb25jYXQoKTsgfVxyXG5cdFx0XHRpZihwKSB7IHBzLnVuc2hpZnQocCk7IH1cclxuXHRcdFx0dmFyIHRpZCA9IGZhbHNlLCBpLCBqLCBjLCBlLCBtID0gdGhpcy5fbW9kZWwuZGF0YSwgZGYgPSB0aGlzLl9tb2RlbC5kZWZhdWx0X3N0YXRlLCB0bXA7XHJcblx0XHRcdGRvIHtcclxuXHRcdFx0XHR0aWQgPSAnaicgKyB0aGlzLl9pZCArICdfJyArICgrK3RoaXMuX2NudCk7XHJcblx0XHRcdH0gd2hpbGUobVt0aWRdKTtcclxuXHJcblx0XHRcdHRtcCA9IHtcclxuXHRcdFx0XHRpZFx0XHRcdDogZmFsc2UsXHJcblx0XHRcdFx0dGV4dFx0XHQ6IHR5cGVvZiBkID09PSAnc3RyaW5nJyA/IGQgOiAnJyxcclxuXHRcdFx0XHRpY29uXHRcdDogdHlwZW9mIGQgPT09ICdvYmplY3QnICYmIGQuaWNvbiAhPT0gdW5kZWZpbmVkID8gZC5pY29uIDogdHJ1ZSxcclxuXHRcdFx0XHRwYXJlbnRcdFx0OiBwLFxyXG5cdFx0XHRcdHBhcmVudHNcdFx0OiBwcyxcclxuXHRcdFx0XHRjaGlsZHJlblx0OiBbXSxcclxuXHRcdFx0XHRjaGlsZHJlbl9kXHQ6IFtdLFxyXG5cdFx0XHRcdGRhdGFcdFx0OiBudWxsLFxyXG5cdFx0XHRcdHN0YXRlXHRcdDogeyB9LFxyXG5cdFx0XHRcdGxpX2F0dHJcdFx0OiB7IGlkIDogZmFsc2UgfSxcclxuXHRcdFx0XHRhX2F0dHJcdFx0OiB7IGhyZWYgOiAnIycgfSxcclxuXHRcdFx0XHRvcmlnaW5hbFx0OiBmYWxzZVxyXG5cdFx0XHR9O1xyXG5cdFx0XHRmb3IoaSBpbiBkZikge1xyXG5cdFx0XHRcdGlmKGRmLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHR0bXAuc3RhdGVbaV0gPSBkZltpXTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiBkLmlkKSB7IHRtcC5pZCA9IGQuaWQ7IH1cclxuXHRcdFx0aWYoZCAmJiBkLnRleHQpIHsgdG1wLnRleHQgPSBkLnRleHQ7IH1cclxuXHRcdFx0aWYoZCAmJiBkLmRhdGEgJiYgZC5kYXRhLmpzdHJlZSAmJiBkLmRhdGEuanN0cmVlLmljb24pIHtcclxuXHRcdFx0XHR0bXAuaWNvbiA9IGQuZGF0YS5qc3RyZWUuaWNvbjtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZihkICYmIGQuZGF0YSkge1xyXG5cdFx0XHRcdHRtcC5kYXRhID0gZC5kYXRhO1xyXG5cdFx0XHRcdGlmKGQuZGF0YS5qc3RyZWUpIHtcclxuXHRcdFx0XHRcdGZvcihpIGluIGQuZGF0YS5qc3RyZWUpIHtcclxuXHRcdFx0XHRcdFx0aWYoZC5kYXRhLmpzdHJlZS5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0XHRcdHRtcC5zdGF0ZVtpXSA9IGQuZGF0YS5qc3RyZWVbaV07XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiB0eXBlb2YgZC5zdGF0ZSA9PT0gJ29iamVjdCcpIHtcclxuXHRcdFx0XHRmb3IgKGkgaW4gZC5zdGF0ZSkge1xyXG5cdFx0XHRcdFx0aWYoZC5zdGF0ZS5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0XHR0bXAuc3RhdGVbaV0gPSBkLnN0YXRlW2ldO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZihkICYmIHR5cGVvZiBkLmxpX2F0dHIgPT09ICdvYmplY3QnKSB7XHJcblx0XHRcdFx0Zm9yIChpIGluIGQubGlfYXR0cikge1xyXG5cdFx0XHRcdFx0aWYoZC5saV9hdHRyLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHRcdHRtcC5saV9hdHRyW2ldID0gZC5saV9hdHRyW2ldO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZih0bXAubGlfYXR0ci5pZCAmJiAhdG1wLmlkKSB7XHJcblx0XHRcdFx0dG1wLmlkID0gdG1wLmxpX2F0dHIuaWQ7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIXRtcC5pZCkge1xyXG5cdFx0XHRcdHRtcC5pZCA9IHRpZDtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZighdG1wLmxpX2F0dHIuaWQpIHtcclxuXHRcdFx0XHR0bXAubGlfYXR0ci5pZCA9IHRtcC5pZDtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZihkICYmIHR5cGVvZiBkLmFfYXR0ciA9PT0gJ29iamVjdCcpIHtcclxuXHRcdFx0XHRmb3IgKGkgaW4gZC5hX2F0dHIpIHtcclxuXHRcdFx0XHRcdGlmKGQuYV9hdHRyLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHRcdHRtcC5hX2F0dHJbaV0gPSBkLmFfYXR0cltpXTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoZCAmJiBkLmNoaWxkcmVuICYmIGQuY2hpbGRyZW4ubGVuZ3RoKSB7XHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gZC5jaGlsZHJlbi5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdGMgPSB0aGlzLl9wYXJzZV9tb2RlbF9mcm9tX2pzb24oZC5jaGlsZHJlbltpXSwgdG1wLmlkLCBwcyk7XHJcblx0XHRcdFx0XHRlID0gbVtjXTtcclxuXHRcdFx0XHRcdHRtcC5jaGlsZHJlbi5wdXNoKGMpO1xyXG5cdFx0XHRcdFx0aWYoZS5jaGlsZHJlbl9kLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHR0bXAuY2hpbGRyZW5fZCA9IHRtcC5jaGlsZHJlbl9kLmNvbmNhdChlLmNoaWxkcmVuX2QpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR0bXAuY2hpbGRyZW5fZCA9IHRtcC5jaGlsZHJlbl9kLmNvbmNhdCh0bXAuY2hpbGRyZW4pO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGQgJiYgZC5jaGlsZHJlbiAmJiBkLmNoaWxkcmVuID09PSB0cnVlKSB7XHJcblx0XHRcdFx0dG1wLnN0YXRlLmxvYWRlZCA9IGZhbHNlO1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbiA9IFtdO1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbl9kID0gW107XHJcblx0XHRcdH1cclxuXHRcdFx0ZGVsZXRlIGQuZGF0YTtcclxuXHRcdFx0ZGVsZXRlIGQuY2hpbGRyZW47XHJcblx0XHRcdHRtcC5vcmlnaW5hbCA9IGQ7XHJcblx0XHRcdG1bdG1wLmlkXSA9IHRtcDtcclxuXHRcdFx0aWYodG1wLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLnB1c2godG1wLmlkKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdG1wLmlkO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogcmVkcmF3cyBhbGwgbm9kZXMgdGhhdCBuZWVkIHRvIGJlIHJlZHJhd24uIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBfcmVkcmF3KClcclxuXHRcdCAqIEB0cmlnZ2VyIHJlZHJhdy5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0X3JlZHJhdyA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0dmFyIG5vZGVzID0gdGhpcy5fbW9kZWwuZm9yY2VfZnVsbF9yZWRyYXcgPyB0aGlzLl9tb2RlbC5kYXRhWycjJ10uY2hpbGRyZW4uY29uY2F0KFtdKSA6IHRoaXMuX21vZGVsLmNoYW5nZWQuY29uY2F0KFtdKSxcclxuXHRcdFx0XHRmID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnVUwnKSwgdG1wLCBpLCBqO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSBub2Rlcy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHR0bXAgPSB0aGlzLnJlZHJhd19ub2RlKG5vZGVzW2ldLCB0cnVlLCB0aGlzLl9tb2RlbC5mb3JjZV9mdWxsX3JlZHJhdyk7XHJcblx0XHRcdFx0aWYodG1wICYmIHRoaXMuX21vZGVsLmZvcmNlX2Z1bGxfcmVkcmF3KSB7XHJcblx0XHRcdFx0XHRmLmFwcGVuZENoaWxkKHRtcCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHRoaXMuX21vZGVsLmZvcmNlX2Z1bGxfcmVkcmF3KSB7XHJcblx0XHRcdFx0Zi5jbGFzc05hbWUgPSB0aGlzLmdldF9jb250YWluZXJfdWwoKVswXS5jbGFzc05hbWU7XHJcblx0XHRcdFx0dGhpcy5lbGVtZW50LmVtcHR5KCkuYXBwZW5kKGYpO1xyXG5cdFx0XHRcdC8vdGhpcy5nZXRfY29udGFpbmVyX3VsKClbMF0uYXBwZW5kQ2hpbGQoZik7XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5fbW9kZWwuZm9yY2VfZnVsbF9yZWRyYXcgPSBmYWxzZTtcclxuXHRcdFx0dGhpcy5fbW9kZWwuY2hhbmdlZCA9IFtdO1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIG5vZGVzIGFyZSByZWRyYXduXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSByZWRyYXcuanN0cmVlXHJcblx0XHRcdCAqIEBwYXJhbSB7YXJyYXl9IG5vZGVzIHRoZSByZWRyYXduIG5vZGVzXHJcblx0XHRcdCAqL1xyXG5cdFx0XHR0aGlzLnRyaWdnZXIoJ3JlZHJhdycsIHsgXCJub2Rlc1wiIDogbm9kZXMgfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiByZWRyYXdzIGFsbCBub2RlcyB0aGF0IG5lZWQgdG8gYmUgcmVkcmF3biBvciBvcHRpb25hbGx5IC0gdGhlIHdob2xlIHRyZWVcclxuXHRcdCAqIEBuYW1lIHJlZHJhdyhbZnVsbF0pXHJcblx0XHQgKiBAcGFyYW0ge0Jvb2xlYW59IGZ1bGwgaWYgc2V0IHRvIGB0cnVlYCBhbGwgbm9kZXMgYXJlIHJlZHJhd24uXHJcblx0XHQgKi9cclxuXHRcdHJlZHJhdyA6IGZ1bmN0aW9uIChmdWxsKSB7XHJcblx0XHRcdGlmKGZ1bGwpIHtcclxuXHRcdFx0XHR0aGlzLl9tb2RlbC5mb3JjZV9mdWxsX3JlZHJhdyA9IHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0Ly9pZih0aGlzLl9tb2RlbC5yZWRyYXdfdGltZW91dCkge1xyXG5cdFx0XHQvL1x0Y2xlYXJUaW1lb3V0KHRoaXMuX21vZGVsLnJlZHJhd190aW1lb3V0KTtcclxuXHRcdFx0Ly99XHJcblx0XHRcdC8vdGhpcy5fbW9kZWwucmVkcmF3X3RpbWVvdXQgPSBzZXRUaW1lb3V0KCQucHJveHkodGhpcy5fcmVkcmF3LCB0aGlzKSwwKTtcclxuXHRcdFx0dGhpcy5fcmVkcmF3KCk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiByZWRyYXdzIGEgc2luZ2xlIG5vZGUuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSByZWRyYXdfbm9kZShub2RlLCBkZWVwLCBpc19jYWxsYmFjaylcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG5vZGUgdGhlIG5vZGUgdG8gcmVkcmF3XHJcblx0XHQgKiBAcGFyYW0ge0Jvb2xlYW59IGRlZXAgc2hvdWxkIGNoaWxkIG5vZGVzIGJlIHJlZHJhd24gdG9vXHJcblx0XHQgKiBAcGFyYW0ge0Jvb2xlYW59IGlzX2NhbGxiYWNrIGlzIHRoaXMgYSByZWN1cnNpb24gY2FsbFxyXG5cdFx0ICovXHJcblx0XHRyZWRyYXdfbm9kZSA6IGZ1bmN0aW9uIChub2RlLCBkZWVwLCBpc19jYWxsYmFjaykge1xyXG5cdFx0XHR2YXIgb2JqID0gdGhpcy5nZXRfbm9kZShub2RlKSxcclxuXHRcdFx0XHRwYXIgPSBmYWxzZSxcclxuXHRcdFx0XHRpbmQgPSBmYWxzZSxcclxuXHRcdFx0XHRvbGQgPSBmYWxzZSxcclxuXHRcdFx0XHRpID0gZmFsc2UsXHJcblx0XHRcdFx0aiA9IGZhbHNlLFxyXG5cdFx0XHRcdGsgPSBmYWxzZSxcclxuXHRcdFx0XHRjID0gJycsXHJcblx0XHRcdFx0ZCA9IGRvY3VtZW50LFxyXG5cdFx0XHRcdG0gPSB0aGlzLl9tb2RlbC5kYXRhLFxyXG5cdFx0XHRcdGYgPSBmYWxzZSxcclxuXHRcdFx0XHRzID0gZmFsc2U7XHJcblx0XHRcdGlmKCFvYmopIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdGlmKG9iai5pZCA9PT0gJyMnKSB7ICByZXR1cm4gdGhpcy5yZWRyYXcodHJ1ZSk7IH1cclxuXHRcdFx0ZGVlcCA9IGRlZXAgfHwgb2JqLmNoaWxkcmVuLmxlbmd0aCA9PT0gMDtcclxuXHRcdFx0bm9kZSA9IGQuZ2V0RWxlbWVudEJ5SWQob2JqLmlkKTsgLy8sIHRoaXMuZWxlbWVudCk7XHJcblx0XHRcdGlmKCFub2RlKSB7XHJcblx0XHRcdFx0ZGVlcCA9IHRydWU7XHJcblx0XHRcdFx0Ly9ub2RlID0gZC5jcmVhdGVFbGVtZW50KCdMSScpO1xyXG5cdFx0XHRcdGlmKCFpc19jYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0cGFyID0gb2JqLnBhcmVudCAhPT0gJyMnID8gJCgnIycgKyBvYmoucGFyZW50LCB0aGlzLmVsZW1lbnQpWzBdIDogbnVsbDtcclxuXHRcdFx0XHRcdGlmKHBhciAhPT0gbnVsbCAmJiAoIXBhciB8fCAhbVtvYmoucGFyZW50XS5zdGF0ZS5vcGVuZWQpKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGluZCA9ICQuaW5BcnJheShvYmouaWQsIHBhciA9PT0gbnVsbCA/IG1bJyMnXS5jaGlsZHJlbiA6IG1bb2JqLnBhcmVudF0uY2hpbGRyZW4pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRub2RlID0gJChub2RlKTtcclxuXHRcdFx0XHRpZighaXNfY2FsbGJhY2spIHtcclxuXHRcdFx0XHRcdHBhciA9IG5vZGUucGFyZW50KCkucGFyZW50KClbMF07XHJcblx0XHRcdFx0XHRpZihwYXIgPT09IHRoaXMuZWxlbWVudFswXSkge1xyXG5cdFx0XHRcdFx0XHRwYXIgPSBudWxsO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aW5kID0gbm9kZS5pbmRleCgpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHQvLyBtW29iai5pZF0uZGF0YSA9IG5vZGUuZGF0YSgpOyAvLyB1c2Ugb25seSBub2RlJ3MgZGF0YSwgbm8gbmVlZCB0byB0b3VjaCBqcXVlcnkgc3RvcmFnZVxyXG5cdFx0XHRcdGlmKCFkZWVwICYmIG9iai5jaGlsZHJlbi5sZW5ndGggJiYgIW5vZGUuY2hpbGRyZW4oJ3VsJykubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRkZWVwID0gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoIWRlZXApIHtcclxuXHRcdFx0XHRcdG9sZCA9IG5vZGUuY2hpbGRyZW4oJ1VMJylbMF07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHMgPSBub2RlLmF0dHIoJ2FyaWEtc2VsZWN0ZWQnKTtcclxuXHRcdFx0XHRmID0gbm9kZS5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKVswXSA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcclxuXHRcdFx0XHRub2RlLnJlbW92ZSgpO1xyXG5cdFx0XHRcdC8vbm9kZSA9IGQuY3JlYXRlRWxlbWVudCgnTEknKTtcclxuXHRcdFx0XHQvL25vZGUgPSBub2RlWzBdO1xyXG5cdFx0XHR9XHJcblx0XHRcdG5vZGUgPSBfbm9kZS5jbG9uZU5vZGUodHJ1ZSk7XHJcblx0XHRcdC8vIG5vZGUgaXMgRE9NLCBkZWVwIGlzIGJvb2xlYW5cclxuXHJcblx0XHRcdGMgPSAnanN0cmVlLW5vZGUgJztcclxuXHRcdFx0Zm9yKGkgaW4gb2JqLmxpX2F0dHIpIHtcclxuXHRcdFx0XHRpZihvYmoubGlfYXR0ci5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG5cdFx0XHRcdFx0aWYoaSA9PT0gJ2lkJykgeyBjb250aW51ZTsgfVxyXG5cdFx0XHRcdFx0aWYoaSAhPT0gJ2NsYXNzJykge1xyXG5cdFx0XHRcdFx0XHRub2RlLnNldEF0dHJpYnV0ZShpLCBvYmoubGlfYXR0cltpXSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0YyArPSBvYmoubGlfYXR0cltpXTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYocyAmJiBzICE9PSBcImZhbHNlXCIpIHtcclxuXHRcdFx0XHRub2RlLnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsIHRydWUpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKCFvYmouY2hpbGRyZW4ubGVuZ3RoICYmIG9iai5zdGF0ZS5sb2FkZWQpIHtcclxuXHRcdFx0XHRjICs9ICcganN0cmVlLWxlYWYnO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGMgKz0gb2JqLnN0YXRlLm9wZW5lZCA/ICcganN0cmVlLW9wZW4nIDogJyBqc3RyZWUtY2xvc2VkJztcclxuXHRcdFx0XHRub2RlLnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIG9iai5zdGF0ZS5vcGVuZWQpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKG9iai5wYXJlbnQgIT09IG51bGwgJiYgbVtvYmoucGFyZW50XS5jaGlsZHJlblttW29iai5wYXJlbnRdLmNoaWxkcmVuLmxlbmd0aCAtIDFdID09PSBvYmouaWQpIHtcclxuXHRcdFx0XHRjICs9ICcganN0cmVlLWxhc3QnO1xyXG5cdFx0XHR9XHJcblx0XHRcdG5vZGUuaWQgPSBvYmouaWQ7XHJcblx0XHRcdG5vZGUuY2xhc3NOYW1lID0gYztcclxuXHRcdFx0YyA9ICggb2JqLnN0YXRlLnNlbGVjdGVkID8gJyBqc3RyZWUtY2xpY2tlZCcgOiAnJykgKyAoIG9iai5zdGF0ZS5kaXNhYmxlZCA/ICcganN0cmVlLWRpc2FibGVkJyA6ICcnKTtcclxuXHRcdFx0Zm9yKGogaW4gb2JqLmFfYXR0cikge1xyXG5cdFx0XHRcdGlmKG9iai5hX2F0dHIuaGFzT3duUHJvcGVydHkoaikpIHtcclxuXHRcdFx0XHRcdGlmKGogPT09ICdocmVmJyAmJiBvYmouYV9hdHRyW2pdID09PSAnIycpIHsgY29udGludWU7IH1cclxuXHRcdFx0XHRcdGlmKGogIT09ICdjbGFzcycpIHtcclxuXHRcdFx0XHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLnNldEF0dHJpYnV0ZShqLCBvYmouYV9hdHRyW2pdKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRjICs9ICcgJyArIG9iai5hX2F0dHJbal07XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGMubGVuZ3RoKSB7XHJcblx0XHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLmNsYXNzTmFtZSA9ICdqc3RyZWUtYW5jaG9yICcgKyBjO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKChvYmouaWNvbiAmJiBvYmouaWNvbiAhPT0gdHJ1ZSkgfHwgb2JqLmljb24gPT09IGZhbHNlKSB7XHJcblx0XHRcdFx0aWYob2JqLmljb24gPT09IGZhbHNlKSB7XHJcblx0XHRcdFx0XHRub2RlLmNoaWxkTm9kZXNbMV0uY2hpbGROb2Rlc1swXS5jbGFzc05hbWUgKz0gJyBqc3RyZWUtdGhlbWVpY29uLWhpZGRlbic7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2UgaWYob2JqLmljb24uaW5kZXhPZignLycpID09PSAtMSAmJiBvYmouaWNvbi5pbmRleE9mKCcuJykgPT09IC0xKSB7XHJcblx0XHRcdFx0XHRub2RlLmNoaWxkTm9kZXNbMV0uY2hpbGROb2Rlc1swXS5jbGFzc05hbWUgKz0gJyAnICsgb2JqLmljb24gKyAnIGpzdHJlZS10aGVtZWljb24tY3VzdG9tJztcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRub2RlLmNoaWxkTm9kZXNbMV0uY2hpbGROb2Rlc1swXS5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSAndXJsKCcrb2JqLmljb24rJyknO1xyXG5cdFx0XHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLmNoaWxkTm9kZXNbMF0uc3R5bGUuYmFja2dyb3VuZFBvc2l0aW9uID0gJ2NlbnRlciBjZW50ZXInO1xyXG5cdFx0XHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLmNoaWxkTm9kZXNbMF0uc3R5bGUuYmFja2dyb3VuZFNpemUgPSAnYXV0byc7XHJcblx0XHRcdFx0XHRub2RlLmNoaWxkTm9kZXNbMV0uY2hpbGROb2Rlc1swXS5jbGFzc05hbWUgKz0gJyBqc3RyZWUtdGhlbWVpY29uLWN1c3RvbSc7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdC8vbm9kZS5jaGlsZE5vZGVzWzFdLmFwcGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUob2JqLnRleHQpKTtcclxuXHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLmlubmVySFRNTCArPSBvYmoudGV4dDtcclxuXHRcdFx0Ly8gaWYob2JqLmRhdGEpIHsgJC5kYXRhKG5vZGUsIG9iai5kYXRhKTsgfSAvLyBhbHdheXMgd29yayB3aXRoIG5vZGUncyBkYXRhLCBubyBuZWVkIHRvIHRvdWNoIGpxdWVyeSBzdG9yZVxyXG5cclxuXHRcdFx0aWYoZGVlcCAmJiBvYmouY2hpbGRyZW4ubGVuZ3RoICYmIG9iai5zdGF0ZS5vcGVuZWQpIHtcclxuXHRcdFx0XHRrID0gZC5jcmVhdGVFbGVtZW50KCdVTCcpO1xyXG5cdFx0XHRcdGsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2dyb3VwJyk7XHJcblx0XHRcdFx0ay5jbGFzc05hbWUgPSAnanN0cmVlLWNoaWxkcmVuJztcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRrLmFwcGVuZENoaWxkKHRoaXMucmVkcmF3X25vZGUob2JqLmNoaWxkcmVuW2ldLCBkZWVwLCB0cnVlKSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdG5vZGUuYXBwZW5kQ2hpbGQoayk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYob2xkKSB7XHJcblx0XHRcdFx0bm9kZS5hcHBlbmRDaGlsZChvbGQpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKCFpc19jYWxsYmFjaykge1xyXG5cdFx0XHRcdC8vIGFwcGVuZCBiYWNrIHVzaW5nIHBhciAvIGluZFxyXG5cdFx0XHRcdGlmKCFwYXIpIHtcclxuXHRcdFx0XHRcdHBhciA9IHRoaXMuZWxlbWVudFswXTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoIXBhci5nZXRFbGVtZW50c0J5VGFnTmFtZSgnVUwnKS5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdGkgPSBkLmNyZWF0ZUVsZW1lbnQoJ1VMJyk7XHJcblx0XHRcdFx0XHRpLnNldEF0dHJpYnV0ZSgncm9sZScsICdncm91cCcpO1xyXG5cdFx0XHRcdFx0aS5jbGFzc05hbWUgPSAnanN0cmVlLWNoaWxkcmVuJztcclxuXHRcdFx0XHRcdHBhci5hcHBlbmRDaGlsZChpKTtcclxuXHRcdFx0XHRcdHBhciA9IGk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0cGFyID0gcGFyLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdVTCcpWzBdO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYoaW5kIDwgcGFyLmNoaWxkTm9kZXMubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRwYXIuaW5zZXJ0QmVmb3JlKG5vZGUsIHBhci5jaGlsZE5vZGVzW2luZF0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdHBhci5hcHBlbmRDaGlsZChub2RlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoZikge1xyXG5cdFx0XHRcdFx0bm9kZS5jaGlsZE5vZGVzWzFdLmZvY3VzKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBub2RlO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogb3BlbnMgYSBub2RlLCByZXZhbGluZyBpdHMgY2hpbGRyZW4uIElmIHRoZSBub2RlIGlzIG5vdCBsb2FkZWQgaXQgd2lsbCBiZSBsb2FkZWQgYW5kIG9wZW5lZCBvbmNlIHJlYWR5LlxyXG5cdFx0ICogQG5hbWUgb3Blbl9ub2RlKG9iaiBbLCBjYWxsYmFjaywgYW5pbWF0aW9uXSlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiB0aGUgbm9kZSB0byBvcGVuXHJcblx0XHQgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBhIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgb25jZSB0aGUgbm9kZSBpcyBvcGVuZWRcclxuXHRcdCAqIEBwYXJhbSB7TnVtYmVyfSBhbmltYXRpb24gdGhlIGFuaW1hdGlvbiBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgd2hlbiBvcGVuaW5nIHRoZSBub2RlIChvdmVycmlkZXMgdGhlIGBjb3JlLmFuaW1hdGlvbmAgc2V0dGluZykuIFVzZSBgZmFsc2VgIGZvciBubyBhbmltYXRpb24uXHJcblx0XHQgKiBAdHJpZ2dlciBvcGVuX25vZGUuanN0cmVlLCBhZnRlcl9vcGVuLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRvcGVuX25vZGUgOiBmdW5jdGlvbiAob2JqLCBjYWxsYmFjaywgYW5pbWF0aW9uKSB7XHJcblx0XHRcdHZhciB0MSwgdDIsIGQsIHQ7XHJcblx0XHRcdGlmKCQuaXNBcnJheShvYmopKSB7XHJcblx0XHRcdFx0b2JqID0gb2JqLnNsaWNlKCk7XHJcblx0XHRcdFx0Zm9yKHQxID0gMCwgdDIgPSBvYmoubGVuZ3RoOyB0MSA8IHQyOyB0MSsrKSB7XHJcblx0XHRcdFx0XHR0aGlzLm9wZW5fbm9kZShvYmpbdDFdLCBjYWxsYmFjaywgYW5pbWF0aW9uKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGFuaW1hdGlvbiA9IGFuaW1hdGlvbiA9PT0gdW5kZWZpbmVkID8gdGhpcy5zZXR0aW5ncy5jb3JlLmFuaW1hdGlvbiA6IGFuaW1hdGlvbjtcclxuXHRcdFx0aWYoIXRoaXMuaXNfY2xvc2VkKG9iaikpIHtcclxuXHRcdFx0XHRpZihjYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0Y2FsbGJhY2suY2FsbCh0aGlzLCBvYmosIGZhbHNlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKCF0aGlzLmlzX2xvYWRlZChvYmopKSB7XHJcblx0XHRcdFx0aWYodGhpcy5pc19sb2FkaW5nKG9iaikpIHtcclxuXHRcdFx0XHRcdHJldHVybiBzZXRUaW1lb3V0KCQucHJveHkoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLm9wZW5fbm9kZShvYmosIGNhbGxiYWNrLCBhbmltYXRpb24pO1xyXG5cdFx0XHRcdFx0fSwgdGhpcyksIDUwMCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHRoaXMubG9hZF9ub2RlKG9iaiwgZnVuY3Rpb24gKG8sIG9rKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gb2sgPyB0aGlzLm9wZW5fbm9kZShvLCBjYWxsYmFjaywgYW5pbWF0aW9uKSA6IChjYWxsYmFjayA/IGNhbGxiYWNrLmNhbGwodGhpcywgbywgZmFsc2UpIDogZmFsc2UpO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdGQgPSB0aGlzLmdldF9ub2RlKG9iaiwgdHJ1ZSk7XHJcblx0XHRcdFx0dCA9IHRoaXM7XHJcblx0XHRcdFx0aWYoZC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdGlmKG9iai5jaGlsZHJlbi5sZW5ndGggJiYgIXRoaXMuX2ZpcnN0Q2hpbGQoZC5jaGlsZHJlbigndWwnKVswXSkpIHtcclxuXHRcdFx0XHRcdFx0b2JqLnN0YXRlLm9wZW5lZCA9IHRydWU7XHJcblx0XHRcdFx0XHRcdHRoaXMucmVkcmF3X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0XHRcdFx0ZCA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmKCFhbmltYXRpb24pIHtcclxuXHRcdFx0XHRcdFx0ZFswXS5jbGFzc05hbWUgPSBkWzBdLmNsYXNzTmFtZS5yZXBsYWNlKCdqc3RyZWUtY2xvc2VkJywgJ2pzdHJlZS1vcGVuJyk7XHJcblx0XHRcdFx0XHRcdGRbMF0uc2V0QXR0cmlidXRlKFwiYXJpYS1leHBhbmRlZFwiLCB0cnVlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRkXHJcblx0XHRcdFx0XHRcdFx0LmNoaWxkcmVuKFwidWxcIikuY3NzKFwiZGlzcGxheVwiLFwibm9uZVwiKS5lbmQoKVxyXG5cdFx0XHRcdFx0XHRcdC5yZW1vdmVDbGFzcyhcImpzdHJlZS1jbG9zZWRcIikuYWRkQ2xhc3MoXCJqc3RyZWUtb3BlblwiKS5hdHRyKFwiYXJpYS1leHBhbmRlZFwiLCB0cnVlKVxyXG5cdFx0XHRcdFx0XHRcdC5jaGlsZHJlbihcInVsXCIpLnN0b3AodHJ1ZSwgdHJ1ZSlcclxuXHRcdFx0XHRcdFx0XHRcdC5zbGlkZURvd24oYW5pbWF0aW9uLCBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuc3R5bGUuZGlzcGxheSA9IFwiXCI7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHQudHJpZ2dlcihcImFmdGVyX29wZW5cIiwgeyBcIm5vZGVcIiA6IG9iaiB9KTtcclxuXHRcdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRvYmouc3RhdGUub3BlbmVkID0gdHJ1ZTtcclxuXHRcdFx0XHRpZihjYWxsYmFjaykge1xyXG5cdFx0XHRcdFx0Y2FsbGJhY2suY2FsbCh0aGlzLCBvYmosIHRydWUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHQvKipcclxuXHRcdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIG5vZGUgaXMgb3BlbmVkIChpZiB0aGVyZSBpcyBhbiBhbmltYXRpb24gaXQgd2lsbCBub3QgYmUgY29tcGxldGVkIHlldClcclxuXHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHQgKiBAbmFtZSBvcGVuX25vZGUuanN0cmVlXHJcblx0XHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGUgdGhlIG9wZW5lZCBub2RlXHJcblx0XHRcdFx0ICovXHJcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCdvcGVuX25vZGUnLCB7IFwibm9kZVwiIDogb2JqIH0pO1xyXG5cdFx0XHRcdGlmKCFhbmltYXRpb24gfHwgIWQubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHQvKipcclxuXHRcdFx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGEgbm9kZSBpcyBvcGVuZWQgYW5kIHRoZSBhbmltYXRpb24gaXMgY29tcGxldGVcclxuXHRcdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdFx0ICogQG5hbWUgYWZ0ZXJfb3Blbi5qc3RyZWVcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBub2RlIHRoZSBvcGVuZWQgbm9kZVxyXG5cdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXIoXCJhZnRlcl9vcGVuXCIsIHsgXCJub2RlXCIgOiBvYmogfSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBvcGVucyBldmVyeSBwYXJlbnQgb2YgYSBub2RlIChub2RlIHNob3VsZCBiZSBsb2FkZWQpXHJcblx0XHQgKiBAbmFtZSBfb3Blbl90byhvYmopXHJcblx0XHQgKiBAcGFyYW0ge21peGVkfSBvYmogdGhlIG5vZGUgdG8gcmV2ZWFsXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICovXHJcblx0XHRfb3Blbl90byA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdHZhciBpLCBqLCBwID0gb2JqLnBhcmVudHM7XHJcblx0XHRcdGZvcihpID0gMCwgaiA9IHAubGVuZ3RoOyBpIDwgajsgaSs9MSkge1xyXG5cdFx0XHRcdGlmKGkgIT09ICcjJykge1xyXG5cdFx0XHRcdFx0dGhpcy5vcGVuX25vZGUocFtpXSwgZmFsc2UsIDApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gJChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChvYmouaWQpKTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNsb3NlcyBhIG5vZGUsIGhpZGluZyBpdHMgY2hpbGRyZW5cclxuXHRcdCAqIEBuYW1lIGNsb3NlX25vZGUob2JqIFssIGFuaW1hdGlvbl0pXHJcblx0XHQgKiBAcGFyYW0ge21peGVkfSBvYmogdGhlIG5vZGUgdG8gY2xvc2VcclxuXHRcdCAqIEBwYXJhbSB7TnVtYmVyfSBhbmltYXRpb24gdGhlIGFuaW1hdGlvbiBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgd2hlbiBjbG9zaW5nIHRoZSBub2RlIChvdmVycmlkZXMgdGhlIGBjb3JlLmFuaW1hdGlvbmAgc2V0dGluZykuIFVzZSBgZmFsc2VgIGZvciBubyBhbmltYXRpb24uXHJcblx0XHQgKiBAdHJpZ2dlciBjbG9zZV9ub2RlLmpzdHJlZSwgYWZ0ZXJfY2xvc2UuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGNsb3NlX25vZGUgOiBmdW5jdGlvbiAob2JqLCBhbmltYXRpb24pIHtcclxuXHRcdFx0dmFyIHQxLCB0MiwgdCwgZDtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuY2xvc2Vfbm9kZShvYmpbdDFdLCBhbmltYXRpb24pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0YW5pbWF0aW9uID0gYW5pbWF0aW9uID09PSB1bmRlZmluZWQgPyB0aGlzLnNldHRpbmdzLmNvcmUuYW5pbWF0aW9uIDogYW5pbWF0aW9uO1xyXG5cdFx0XHR0ID0gdGhpcztcclxuXHRcdFx0ZCA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0aWYoZC5sZW5ndGgpIHtcclxuXHRcdFx0XHRpZighYW5pbWF0aW9uKSB7XHJcblx0XHRcdFx0XHRkWzBdLmNsYXNzTmFtZSA9IGRbMF0uY2xhc3NOYW1lLnJlcGxhY2UoJ2pzdHJlZS1vcGVuJywgJ2pzdHJlZS1jbG9zZWQnKTtcclxuXHRcdFx0XHRcdGQuYXR0cihcImFyaWEtZXhwYW5kZWRcIiwgZmFsc2UpLmNoaWxkcmVuKCd1bCcpLnJlbW92ZSgpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdGRcclxuXHRcdFx0XHRcdFx0LmNoaWxkcmVuKFwidWxcIikuYXR0cihcInN0eWxlXCIsXCJkaXNwbGF5OmJsb2NrICFpbXBvcnRhbnRcIikuZW5kKClcclxuXHRcdFx0XHRcdFx0LnJlbW92ZUNsYXNzKFwianN0cmVlLW9wZW5cIikuYWRkQ2xhc3MoXCJqc3RyZWUtY2xvc2VkXCIpLmF0dHIoXCJhcmlhLWV4cGFuZGVkXCIsIGZhbHNlKVxyXG5cdFx0XHRcdFx0XHQuY2hpbGRyZW4oXCJ1bFwiKS5zdG9wKHRydWUsIHRydWUpLnNsaWRlVXAoYW5pbWF0aW9uLCBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5zdHlsZS5kaXNwbGF5ID0gXCJcIjtcclxuXHRcdFx0XHRcdFx0XHRkLmNoaWxkcmVuKCd1bCcpLnJlbW92ZSgpO1xyXG5cdFx0XHRcdFx0XHRcdHQudHJpZ2dlcihcImFmdGVyX2Nsb3NlXCIsIHsgXCJub2RlXCIgOiBvYmogfSk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRvYmouc3RhdGUub3BlbmVkID0gZmFsc2U7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIG5vZGUgaXMgY2xvc2VkIChpZiB0aGVyZSBpcyBhbiBhbmltYXRpb24gaXQgd2lsbCBub3QgYmUgY29tcGxldGUgeWV0KVxyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgY2xvc2Vfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGUgdGhlIGNsb3NlZCBub2RlXHJcblx0XHRcdCAqL1xyXG5cdFx0XHR0aGlzLnRyaWdnZXIoJ2Nsb3NlX25vZGUnLHsgXCJub2RlXCIgOiBvYmogfSk7XHJcblx0XHRcdGlmKCFhbmltYXRpb24gfHwgIWQubGVuZ3RoKSB7XHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gYSBub2RlIGlzIGNsb3NlZCBhbmQgdGhlIGFuaW1hdGlvbiBpcyBjb21wbGV0ZVxyXG5cdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdCAqIEBuYW1lIGFmdGVyX2Nsb3NlLmpzdHJlZVxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBub2RlIHRoZSBjbG9zZWQgbm9kZVxyXG5cdFx0XHRcdCAqL1xyXG5cdFx0XHRcdHRoaXMudHJpZ2dlcihcImFmdGVyX2Nsb3NlXCIsIHsgXCJub2RlXCIgOiBvYmogfSk7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHRvZ2dsZXMgYSBub2RlIC0gY2xvc2luZyBpdCBpZiBpdCBpcyBvcGVuLCBvcGVuaW5nIGl0IGlmIGl0IGlzIGNsb3NlZFxyXG5cdFx0ICogQG5hbWUgdG9nZ2xlX25vZGUob2JqKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIHRvZ2dsZVxyXG5cdFx0ICovXHJcblx0XHR0b2dnbGVfbm9kZSA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0dmFyIHQxLCB0MjtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMudG9nZ2xlX25vZGUob2JqW3QxXSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHRoaXMuaXNfY2xvc2VkKG9iaikpIHtcclxuXHRcdFx0XHRyZXR1cm4gdGhpcy5vcGVuX25vZGUob2JqKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZih0aGlzLmlzX29wZW4ob2JqKSkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLmNsb3NlX25vZGUob2JqKTtcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogb3BlbnMgYWxsIG5vZGVzIHdpdGhpbiBhIG5vZGUgKG9yIHRoZSB0cmVlKSwgcmV2YWxpbmcgdGhlaXIgY2hpbGRyZW4uIElmIHRoZSBub2RlIGlzIG5vdCBsb2FkZWQgaXQgd2lsbCBiZSBsb2FkZWQgYW5kIG9wZW5lZCBvbmNlIHJlYWR5LlxyXG5cdFx0ICogQG5hbWUgb3Blbl9hbGwoW29iaiwgYW5pbWF0aW9uLCBvcmlnaW5hbF9vYmpdKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIG9wZW4gcmVjdXJzaXZlbHksIG9taXQgdG8gb3BlbiBhbGwgbm9kZXMgaW4gdGhlIHRyZWVcclxuXHRcdCAqIEBwYXJhbSB7TnVtYmVyfSBhbmltYXRpb24gdGhlIGFuaW1hdGlvbiBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgd2hlbiBvcGVuaW5nIHRoZSBub2RlcywgdGhlIGRlZmF1bHQgaXMgbm8gYW5pbWF0aW9uXHJcblx0XHQgKiBAcGFyYW0ge2pRdWVyeX0gcmVmZXJlbmNlIHRvIHRoZSBub2RlIHRoYXQgc3RhcnRlZCB0aGUgcHJvY2VzcyAoaW50ZXJuYWwgdXNlKVxyXG5cdFx0ICogQHRyaWdnZXIgb3Blbl9hbGwuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdG9wZW5fYWxsIDogZnVuY3Rpb24gKG9iaiwgYW5pbWF0aW9uLCBvcmlnaW5hbF9vYmopIHtcclxuXHRcdFx0aWYoIW9iaikgeyBvYmogPSAnIyc7IH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHR2YXIgZG9tID0gb2JqLmlkID09PSAnIycgPyB0aGlzLmdldF9jb250YWluZXJfdWwoKSA6IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKSwgaSwgaiwgX3RoaXM7XHJcblx0XHRcdGlmKCFkb20ubGVuZ3RoKSB7XHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gb2JqLmNoaWxkcmVuX2QubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRpZih0aGlzLmlzX2Nsb3NlZCh0aGlzLl9tb2RlbC5kYXRhW29iai5jaGlsZHJlbl9kW2ldXSkpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVtvYmouY2hpbGRyZW5fZFtpXV0uc3RhdGUub3BlbmVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMudHJpZ2dlcignb3Blbl9hbGwnLCB7IFwibm9kZVwiIDogb2JqIH0pO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9yaWdpbmFsX29iaiA9IG9yaWdpbmFsX29iaiB8fCBkb207XHJcblx0XHRcdF90aGlzID0gdGhpcztcclxuXHRcdFx0ZG9tID0gdGhpcy5pc19jbG9zZWQob2JqKSA/IGRvbS5maW5kKCdsaS5qc3RyZWUtY2xvc2VkJykuYWRkQmFjaygpIDogZG9tLmZpbmQoJ2xpLmpzdHJlZS1jbG9zZWQnKTtcclxuXHRcdFx0ZG9tLmVhY2goZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdF90aGlzLm9wZW5fbm9kZShcclxuXHRcdFx0XHRcdHRoaXMsXHJcblx0XHRcdFx0XHRmdW5jdGlvbihub2RlLCBzdGF0dXMpIHsgaWYoc3RhdHVzICYmIHRoaXMuaXNfcGFyZW50KG5vZGUpKSB7IHRoaXMub3Blbl9hbGwobm9kZSwgYW5pbWF0aW9uLCBvcmlnaW5hbF9vYmopOyB9IH0sXHJcblx0XHRcdFx0XHRhbmltYXRpb24gfHwgMFxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdH0pO1xyXG5cdFx0XHRpZihvcmlnaW5hbF9vYmouZmluZCgnbGkuanN0cmVlLWNsb3NlZCcpLmxlbmd0aCA9PT0gMCkge1xyXG5cdFx0XHRcdC8qKlxyXG5cdFx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGFuIGBvcGVuX2FsbGAgY2FsbCBjb21wbGV0ZXNcclxuXHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHQgKiBAbmFtZSBvcGVuX2FsbC5qc3RyZWVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZSB0aGUgb3BlbmVkIG5vZGVcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoJ29wZW5fYWxsJywgeyBcIm5vZGVcIiA6IHRoaXMuZ2V0X25vZGUob3JpZ2luYWxfb2JqKSB9KTtcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY2xvc2VzIGFsbCBub2RlcyB3aXRoaW4gYSBub2RlIChvciB0aGUgdHJlZSksIHJldmFsaW5nIHRoZWlyIGNoaWxkcmVuXHJcblx0XHQgKiBAbmFtZSBjbG9zZV9hbGwoW29iaiwgYW5pbWF0aW9uXSlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiB0aGUgbm9kZSB0byBjbG9zZSByZWN1cnNpdmVseSwgb21pdCB0byBjbG9zZSBhbGwgbm9kZXMgaW4gdGhlIHRyZWVcclxuXHRcdCAqIEBwYXJhbSB7TnVtYmVyfSBhbmltYXRpb24gdGhlIGFuaW1hdGlvbiBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMgd2hlbiBjbG9zaW5nIHRoZSBub2RlcywgdGhlIGRlZmF1bHQgaXMgbm8gYW5pbWF0aW9uXHJcblx0XHQgKiBAdHJpZ2dlciBjbG9zZV9hbGwuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGNsb3NlX2FsbCA6IGZ1bmN0aW9uIChvYmosIGFuaW1hdGlvbikge1xyXG5cdFx0XHRpZighb2JqKSB7IG9iaiA9ICcjJzsgfVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmopIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdHZhciBkb20gPSBvYmouaWQgPT09ICcjJyA/IHRoaXMuZ2V0X2NvbnRhaW5lcl91bCgpIDogdGhpcy5nZXRfbm9kZShvYmosIHRydWUpLFxyXG5cdFx0XHRcdF90aGlzID0gdGhpcywgaSwgajtcclxuXHRcdFx0aWYoIWRvbS5sZW5ndGgpIHtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW5fZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuX21vZGVsLmRhdGFbb2JqLmNoaWxkcmVuX2RbaV1dLnN0YXRlLm9wZW5lZCA9IGZhbHNlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdGhpcy50cmlnZ2VyKCdjbG9zZV9hbGwnLCB7IFwibm9kZVwiIDogb2JqIH0pO1xyXG5cdFx0XHR9XHJcblx0XHRcdGRvbSA9IHRoaXMuaXNfb3BlbihvYmopID8gZG9tLmZpbmQoJ2xpLmpzdHJlZS1vcGVuJykuYWRkQmFjaygpIDogZG9tLmZpbmQoJ2xpLmpzdHJlZS1vcGVuJyk7XHJcblx0XHRcdGRvbS52YWthdGFfcmV2ZXJzZSgpLmVhY2goZnVuY3Rpb24gKCkgeyBfdGhpcy5jbG9zZV9ub2RlKHRoaXMsIGFuaW1hdGlvbiB8fCAwKTsgfSk7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhbiBgY2xvc2VfYWxsYCBjYWxsIGNvbXBsZXRlc1xyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgY2xvc2VfYWxsLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZSB0aGUgY2xvc2VkIG5vZGVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignY2xvc2VfYWxsJywgeyBcIm5vZGVcIiA6IG9iaiB9KTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNoZWNrcyBpZiBhIG5vZGUgaXMgZGlzYWJsZWQgKG5vdCBzZWxlY3RhYmxlKVxyXG5cdFx0ICogQG5hbWUgaXNfZGlzYWJsZWQob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHJldHVybiB7Qm9vbGVhbn1cclxuXHRcdCAqL1xyXG5cdFx0aXNfZGlzYWJsZWQgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0cmV0dXJuIG9iaiAmJiBvYmouc3RhdGUgJiYgb2JqLnN0YXRlLmRpc2FibGVkO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZW5hYmxlcyBhIG5vZGUgLSBzbyB0aGF0IGl0IGNhbiBiZSBzZWxlY3RlZFxyXG5cdFx0ICogQG5hbWUgZW5hYmxlX25vZGUob2JqKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIGVuYWJsZVxyXG5cdFx0ICogQHRyaWdnZXIgZW5hYmxlX25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGVuYWJsZV9ub2RlIDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0XHR2YXIgdDEsIHQyO1xyXG5cdFx0XHRpZigkLmlzQXJyYXkob2JqKSkge1xyXG5cdFx0XHRcdG9iaiA9IG9iai5zbGljZSgpO1xyXG5cdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0dGhpcy5lbmFibGVfbm9kZShvYmpbdDFdKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iai5zdGF0ZS5kaXNhYmxlZCA9IGZhbHNlO1xyXG5cdFx0XHR0aGlzLmdldF9ub2RlKG9iaix0cnVlKS5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5yZW1vdmVDbGFzcygnanN0cmVlLWRpc2FibGVkJyk7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhbiBub2RlIGlzIGVuYWJsZWRcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGVuYWJsZV9ub2RlLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZSB0aGUgZW5hYmxlZCBub2RlXHJcblx0XHRcdCAqL1xyXG5cdFx0XHR0aGlzLnRyaWdnZXIoJ2VuYWJsZV9ub2RlJywgeyAnbm9kZScgOiBvYmogfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBkaXNhYmxlcyBhIG5vZGUgLSBzbyB0aGF0IGl0IGNhbiBub3QgYmUgc2VsZWN0ZWRcclxuXHRcdCAqIEBuYW1lIGRpc2FibGVfbm9kZShvYmopXHJcblx0XHQgKiBAcGFyYW0ge21peGVkfSBvYmogdGhlIG5vZGUgdG8gZGlzYWJsZVxyXG5cdFx0ICogQHRyaWdnZXIgZGlzYWJsZV9ub2RlLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRkaXNhYmxlX25vZGUgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdHZhciB0MSwgdDI7XHJcblx0XHRcdGlmKCQuaXNBcnJheShvYmopKSB7XHJcblx0XHRcdFx0b2JqID0gb2JqLnNsaWNlKCk7XHJcblx0XHRcdFx0Zm9yKHQxID0gMCwgdDIgPSBvYmoubGVuZ3RoOyB0MSA8IHQyOyB0MSsrKSB7XHJcblx0XHRcdFx0XHR0aGlzLmRpc2FibGVfbm9kZShvYmpbdDFdKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iai5zdGF0ZS5kaXNhYmxlZCA9IHRydWU7XHJcblx0XHRcdHRoaXMuZ2V0X25vZGUob2JqLHRydWUpLmNoaWxkcmVuKCcuanN0cmVlLWFuY2hvcicpLmFkZENsYXNzKCdqc3RyZWUtZGlzYWJsZWQnKTtcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGFuIG5vZGUgaXMgZGlzYWJsZWRcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGRpc2FibGVfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGUgdGhlIGRpc2FibGVkIG5vZGVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignZGlzYWJsZV9ub2RlJywgeyAnbm9kZScgOiBvYmogfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBjYWxsZWQgd2hlbiBhIG5vZGUgaXMgc2VsZWN0ZWQgYnkgdGhlIHVzZXIuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBhY3RpdmF0ZV9ub2RlKG9iaiwgZSlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiB0aGUgbm9kZVxyXG5cdFx0ICogQHBhcmFtIHtPYmplY3R9IGUgdGhlIHJlbGF0ZWQgZXZlbnRcclxuXHRcdCAqIEB0cmlnZ2VyIGFjdGl2YXRlX25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGFjdGl2YXRlX25vZGUgOiBmdW5jdGlvbiAob2JqLCBlKSB7XHJcblx0XHRcdGlmKHRoaXMuaXNfZGlzYWJsZWQob2JqKSkge1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZighdGhpcy5zZXR0aW5ncy5jb3JlLm11bHRpcGxlIHx8ICghZS5tZXRhS2V5ICYmICFlLmN0cmxLZXkgJiYgIWUuc2hpZnRLZXkpIHx8IChlLnNoaWZ0S2V5ICYmICghdGhpcy5fZGF0YS5jb3JlLmxhc3RfY2xpY2tlZCB8fCAhdGhpcy5nZXRfcGFyZW50KG9iaikgfHwgdGhpcy5nZXRfcGFyZW50KG9iaikgIT09IHRoaXMuX2RhdGEuY29yZS5sYXN0X2NsaWNrZWQucGFyZW50ICkgKSkge1xyXG5cdFx0XHRcdGlmKCF0aGlzLnNldHRpbmdzLmNvcmUubXVsdGlwbGUgJiYgKGUubWV0YUtleSB8fCBlLmN0cmxLZXkgfHwgZS5zaGlmdEtleSkgJiYgdGhpcy5pc19zZWxlY3RlZChvYmopKSB7XHJcblx0XHRcdFx0XHR0aGlzLmRlc2VsZWN0X25vZGUob2JqLCBmYWxzZSwgZmFsc2UsIGUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdHRoaXMuZGVzZWxlY3RfYWxsKHRydWUpO1xyXG5cdFx0XHRcdFx0dGhpcy5zZWxlY3Rfbm9kZShvYmosIGZhbHNlLCBmYWxzZSwgZSk7XHJcblx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUubGFzdF9jbGlja2VkID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRpZihlLnNoaWZ0S2V5KSB7XHJcblx0XHRcdFx0XHR2YXIgbyA9IHRoaXMuZ2V0X25vZGUob2JqKS5pZCxcclxuXHRcdFx0XHRcdFx0bCA9IHRoaXMuX2RhdGEuY29yZS5sYXN0X2NsaWNrZWQuaWQsXHJcblx0XHRcdFx0XHRcdHAgPSB0aGlzLmdldF9ub2RlKHRoaXMuX2RhdGEuY29yZS5sYXN0X2NsaWNrZWQucGFyZW50KS5jaGlsZHJlbixcclxuXHRcdFx0XHRcdFx0YyA9IGZhbHNlLFxyXG5cdFx0XHRcdFx0XHRpLCBqO1xyXG5cdFx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gcC5sZW5ndGg7IGkgPCBqOyBpICs9IDEpIHtcclxuXHRcdFx0XHRcdFx0Ly8gc2VwYXJhdGUgSUZzIHdvcmsgd2hlbSBvIGFuZCBsIGFyZSB0aGUgc2FtZVxyXG5cdFx0XHRcdFx0XHRpZihwW2ldID09PSBvKSB7XHJcblx0XHRcdFx0XHRcdFx0YyA9ICFjO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGlmKHBbaV0gPT09IGwpIHtcclxuXHRcdFx0XHRcdFx0XHRjID0gIWM7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYoYyB8fCBwW2ldID09PSBvIHx8IHBbaV0gPT09IGwpIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnNlbGVjdF9ub2RlKHBbaV0sIGZhbHNlLCBmYWxzZSwgZSk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5kZXNlbGVjdF9ub2RlKHBbaV0sIGZhbHNlLCBmYWxzZSwgZSk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRpZighdGhpcy5pc19zZWxlY3RlZChvYmopKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuc2VsZWN0X25vZGUob2JqLCBmYWxzZSwgZmFsc2UsIGUpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuZGVzZWxlY3Rfbm9kZShvYmosIGZhbHNlLCBmYWxzZSwgZSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhbiBub2RlIGlzIGNsaWNrZWQgb3IgaW50ZXJjYXRlZCB3aXRoIGJ5IHRoZSB1c2VyXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBhY3RpdmF0ZV9ub2RlLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdhY3RpdmF0ZV9ub2RlJywgeyAnbm9kZScgOiB0aGlzLmdldF9ub2RlKG9iaikgfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBhcHBsaWVzIHRoZSBob3ZlciBzdGF0ZSBvbiBhIG5vZGUsIGNhbGxlZCB3aGVuIGEgbm9kZSBpcyBob3ZlcmVkIGJ5IHRoZSB1c2VyLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgaG92ZXJfbm9kZShvYmopXHJcblx0XHQgKiBAcGFyYW0ge21peGVkfSBvYmpcclxuXHRcdCAqIEB0cmlnZ2VyIGhvdmVyX25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGhvdmVyX25vZGUgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0aWYoIW9iaiB8fCAhb2JqLmxlbmd0aCB8fCBvYmouY2hpbGRyZW4oJy5qc3RyZWUtaG92ZXJlZCcpLmxlbmd0aCkge1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHR2YXIgbyA9IHRoaXMuZWxlbWVudC5maW5kKCcuanN0cmVlLWhvdmVyZWQnKSwgdCA9IHRoaXMuZWxlbWVudDtcclxuXHRcdFx0aWYobyAmJiBvLmxlbmd0aCkgeyB0aGlzLmRlaG92ZXJfbm9kZShvKTsgfVxyXG5cclxuXHRcdFx0b2JqLmNoaWxkcmVuKCcuanN0cmVlLWFuY2hvcicpLmFkZENsYXNzKCdqc3RyZWUtaG92ZXJlZCcpO1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gYW4gbm9kZSBpcyBob3ZlcmVkXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBob3Zlcl9ub2RlLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdob3Zlcl9ub2RlJywgeyAnbm9kZScgOiB0aGlzLmdldF9ub2RlKG9iaikgfSk7XHJcblx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyB0LmF0dHIoJ2FyaWEtYWN0aXZlZGVzY2VuZGFudCcsIG9ialswXS5pZCk7IG9iai5hdHRyKCdhcmlhLXNlbGVjdGVkJywgdHJ1ZSk7IH0sIDApO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogcmVtb3ZlcyB0aGUgaG92ZXIgc3RhdGUgZnJvbSBhIG5vZGVjYWxsZWQgd2hlbiBhIG5vZGUgaXMgbm8gbG9uZ2VyIGhvdmVyZWQgYnkgdGhlIHVzZXIuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBkZWhvdmVyX25vZGUob2JqKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAdHJpZ2dlciBkZWhvdmVyX25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGRlaG92ZXJfbm9kZSA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpO1xyXG5cdFx0XHRpZighb2JqIHx8ICFvYmoubGVuZ3RoIHx8ICFvYmouY2hpbGRyZW4oJy5qc3RyZWUtaG92ZXJlZCcpLmxlbmd0aCkge1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmouYXR0cignYXJpYS1zZWxlY3RlZCcsIGZhbHNlKS5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5yZW1vdmVDbGFzcygnanN0cmVlLWhvdmVyZWQnKTtcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGFuIG5vZGUgaXMgbm8gbG9uZ2VyIGhvdmVyZWRcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGRlaG92ZXJfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignZGVob3Zlcl9ub2RlJywgeyAnbm9kZScgOiB0aGlzLmdldF9ub2RlKG9iaikgfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBzZWxlY3QgYSBub2RlXHJcblx0XHQgKiBAbmFtZSBzZWxlY3Rfbm9kZShvYmogWywgc3VwcmVzc19ldmVudCwgcHJldmVudF9vcGVuXSlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiBhbiBhcnJheSBjYW4gYmUgdXNlZCB0byBzZWxlY3QgbXVsdGlwbGUgbm9kZXNcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gc3VwcmVzc19ldmVudCBpZiBzZXQgdG8gYHRydWVgIHRoZSBgY2hhbmdlZC5qc3RyZWVgIGV2ZW50IHdvbid0IGJlIHRyaWdnZXJlZFxyXG5cdFx0ICogQHBhcmFtIHtCb29sZWFufSBwcmV2ZW50X29wZW4gaWYgc2V0IHRvIGB0cnVlYCBwYXJlbnRzIG9mIHRoZSBzZWxlY3RlZCBub2RlIHdvbid0IGJlIG9wZW5lZFxyXG5cdFx0ICogQHRyaWdnZXIgc2VsZWN0X25vZGUuanN0cmVlLCBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRzZWxlY3Rfbm9kZSA6IGZ1bmN0aW9uIChvYmosIHN1cHJlc3NfZXZlbnQsIHByZXZlbnRfb3BlbiwgZSkge1xyXG5cdFx0XHR2YXIgZG9tLCB0MSwgdDIsIHRoO1xyXG5cdFx0XHRpZigkLmlzQXJyYXkob2JqKSkge1xyXG5cdFx0XHRcdG9iaiA9IG9iai5zbGljZSgpO1xyXG5cdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0dGhpcy5zZWxlY3Rfbm9kZShvYmpbdDFdLCBzdXByZXNzX2V2ZW50LCBwcmV2ZW50X29wZW4sIGUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0ZG9tID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpO1xyXG5cdFx0XHRpZighb2JqLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0b2JqLnN0YXRlLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQucHVzaChvYmouaWQpO1xyXG5cdFx0XHRcdGlmKCFwcmV2ZW50X29wZW4pIHtcclxuXHRcdFx0XHRcdGRvbSA9IHRoaXMuX29wZW5fdG8ob2JqKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoZG9tICYmIGRvbS5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdGRvbS5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5hZGRDbGFzcygnanN0cmVlLWNsaWNrZWQnKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gYW4gbm9kZSBpcyBzZWxlY3RlZFxyXG5cdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdCAqIEBuYW1lIHNlbGVjdF9ub2RlLmpzdHJlZVxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBub2RlXHJcblx0XHRcdFx0ICogQHBhcmFtIHtBcnJheX0gc2VsZWN0ZWQgdGhlIGN1cnJlbnQgc2VsZWN0aW9uXHJcblx0XHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IHRoZSBldmVudCAoaWYgYW55KSB0aGF0IHRyaWdnZXJlZCB0aGlzIHNlbGVjdF9ub2RlXHJcblx0XHRcdFx0ICovXHJcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCdzZWxlY3Rfbm9kZScsIHsgJ25vZGUnIDogb2JqLCAnc2VsZWN0ZWQnIDogdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLCAnZXZlbnQnIDogZSB9KTtcclxuXHRcdFx0XHRpZighc3VwcmVzc19ldmVudCkge1xyXG5cdFx0XHRcdFx0LyoqXHJcblx0XHRcdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBzZWxlY3Rpb24gY2hhbmdlc1xyXG5cdFx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0XHQgKiBAbmFtZSBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGVcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gdGhlIGFjdGlvbiB0aGF0IGNhdXNlZCB0aGUgc2VsZWN0aW9uIHRvIGNoYW5nZVxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtBcnJheX0gc2VsZWN0ZWQgdGhlIGN1cnJlbnQgc2VsZWN0aW9uXHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgdGhlIGV2ZW50IChpZiBhbnkpIHRoYXQgdHJpZ2dlcmVkIHRoaXMgY2hhbmdlZCBldmVudFxyXG5cdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXIoJ2NoYW5nZWQnLCB7ICdhY3Rpb24nIDogJ3NlbGVjdF9ub2RlJywgJ25vZGUnIDogb2JqLCAnc2VsZWN0ZWQnIDogdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLCAnZXZlbnQnIDogZSB9KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGRlc2VsZWN0IGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgZGVzZWxlY3Rfbm9kZShvYmogWywgc3VwcmVzc19ldmVudF0pXHJcblx0XHQgKiBAcGFyYW0ge21peGVkfSBvYmogYW4gYXJyYXkgY2FuIGJlIHVzZWQgdG8gZGVzZWxlY3QgbXVsdGlwbGUgbm9kZXNcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gc3VwcmVzc19ldmVudCBpZiBzZXQgdG8gYHRydWVgIHRoZSBgY2hhbmdlZC5qc3RyZWVgIGV2ZW50IHdvbid0IGJlIHRyaWdnZXJlZFxyXG5cdFx0ICogQHRyaWdnZXIgZGVzZWxlY3Rfbm9kZS5qc3RyZWUsIGNoYW5nZWQuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGRlc2VsZWN0X25vZGUgOiBmdW5jdGlvbiAob2JqLCBzdXByZXNzX2V2ZW50LCBlKSB7XHJcblx0XHRcdHZhciB0MSwgdDIsIGRvbTtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuZGVzZWxlY3Rfbm9kZShvYmpbdDFdLCBzdXByZXNzX2V2ZW50LCBlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGRvbSA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0aWYob2JqLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0b2JqLnN0YXRlLnNlbGVjdGVkID0gZmFsc2U7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gJC52YWthdGEuYXJyYXlfcmVtb3ZlX2l0ZW0odGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLCBvYmouaWQpO1xyXG5cdFx0XHRcdGlmKGRvbS5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdGRvbS5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5yZW1vdmVDbGFzcygnanN0cmVlLWNsaWNrZWQnKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gYW4gbm9kZSBpcyBkZXNlbGVjdGVkXHJcblx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0ICogQG5hbWUgZGVzZWxlY3Rfbm9kZS5qc3RyZWVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZVxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7QXJyYXl9IHNlbGVjdGVkIHRoZSBjdXJyZW50IHNlbGVjdGlvblxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCB0aGUgZXZlbnQgKGlmIGFueSkgdGhhdCB0cmlnZ2VyZWQgdGhpcyBkZXNlbGVjdF9ub2RlXHJcblx0XHRcdFx0ICovXHJcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCdkZXNlbGVjdF9ub2RlJywgeyAnbm9kZScgOiBvYmosICdzZWxlY3RlZCcgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQsICdldmVudCcgOiBlIH0pO1xyXG5cdFx0XHRcdGlmKCFzdXByZXNzX2V2ZW50KSB7XHJcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXIoJ2NoYW5nZWQnLCB7ICdhY3Rpb24nIDogJ2Rlc2VsZWN0X25vZGUnLCAnbm9kZScgOiBvYmosICdzZWxlY3RlZCcgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQsICdldmVudCcgOiBlIH0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogc2VsZWN0IGFsbCBub2RlcyBpbiB0aGUgdHJlZVxyXG5cdFx0ICogQG5hbWUgc2VsZWN0X2FsbChbc3VwcmVzc19ldmVudF0pXHJcblx0XHQgKiBAcGFyYW0ge0Jvb2xlYW59IHN1cHJlc3NfZXZlbnQgaWYgc2V0IHRvIGB0cnVlYCB0aGUgYGNoYW5nZWQuanN0cmVlYCBldmVudCB3b24ndCBiZSB0cmlnZ2VyZWRcclxuXHRcdCAqIEB0cmlnZ2VyIHNlbGVjdF9hbGwuanN0cmVlLCBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRzZWxlY3RfYWxsIDogZnVuY3Rpb24gKHN1cHJlc3NfZXZlbnQpIHtcclxuXHRcdFx0dmFyIHRtcCA9IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZC5jb25jYXQoW10pLCBpLCBqO1xyXG5cdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQgPSB0aGlzLl9tb2RlbC5kYXRhWycjJ10uY2hpbGRyZW5fZC5jb25jYXQoKTtcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdGlmKHRoaXMuX21vZGVsLmRhdGFbdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkW2ldXSkge1xyXG5cdFx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVt0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWRbaV1dLnN0YXRlLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5yZWRyYXcodHJ1ZSk7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhbGwgbm9kZXMgYXJlIHNlbGVjdGVkXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBzZWxlY3RfYWxsLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge0FycmF5fSBzZWxlY3RlZCB0aGUgY3VycmVudCBzZWxlY3Rpb25cclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignc2VsZWN0X2FsbCcsIHsgJ3NlbGVjdGVkJyA6IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCB9KTtcclxuXHRcdFx0aWYoIXN1cHJlc3NfZXZlbnQpIHtcclxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoJ2NoYW5nZWQnLCB7ICdhY3Rpb24nIDogJ3NlbGVjdF9hbGwnLCAnc2VsZWN0ZWQnIDogdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLCAnb2xkX3NlbGVjdGlvbicgOiB0bXAgfSk7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGRlc2VsZWN0IGFsbCBzZWxlY3RlZCBub2Rlc1xyXG5cdFx0ICogQG5hbWUgZGVzZWxlY3RfYWxsKFtzdXByZXNzX2V2ZW50XSlcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gc3VwcmVzc19ldmVudCBpZiBzZXQgdG8gYHRydWVgIHRoZSBgY2hhbmdlZC5qc3RyZWVgIGV2ZW50IHdvbid0IGJlIHRyaWdnZXJlZFxyXG5cdFx0ICogQHRyaWdnZXIgZGVzZWxlY3RfYWxsLmpzdHJlZSwgY2hhbmdlZC5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0ZGVzZWxlY3RfYWxsIDogZnVuY3Rpb24gKHN1cHJlc3NfZXZlbnQpIHtcclxuXHRcdFx0dmFyIHRtcCA9IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZC5jb25jYXQoW10pLCBpLCBqO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0aWYodGhpcy5fbW9kZWwuZGF0YVt0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWRbaV1dKSB7XHJcblx0XHRcdFx0XHR0aGlzLl9tb2RlbC5kYXRhW3RoaXMuX2RhdGEuY29yZS5zZWxlY3RlZFtpXV0uc3RhdGUuc2VsZWN0ZWQgPSBmYWxzZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gW107XHJcblx0XHRcdHRoaXMuZWxlbWVudC5maW5kKCcuanN0cmVlLWNsaWNrZWQnKS5yZW1vdmVDbGFzcygnanN0cmVlLWNsaWNrZWQnKTtcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGFsbCBub2RlcyBhcmUgZGVzZWxlY3RlZFxyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgZGVzZWxlY3RfYWxsLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZSB0aGUgcHJldmlvdXMgc2VsZWN0aW9uXHJcblx0XHRcdCAqIEBwYXJhbSB7QXJyYXl9IHNlbGVjdGVkIHRoZSBjdXJyZW50IHNlbGVjdGlvblxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdkZXNlbGVjdF9hbGwnLCB7ICdzZWxlY3RlZCcgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQsICdub2RlJyA6IHRtcCB9KTtcclxuXHRcdFx0aWYoIXN1cHJlc3NfZXZlbnQpIHtcclxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoJ2NoYW5nZWQnLCB7ICdhY3Rpb24nIDogJ2Rlc2VsZWN0X2FsbCcsICdzZWxlY3RlZCcgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQsICdvbGRfc2VsZWN0aW9uJyA6IHRtcCB9KTtcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY2hlY2tzIGlmIGEgbm9kZSBpcyBzZWxlY3RlZFxyXG5cdFx0ICogQG5hbWUgaXNfc2VsZWN0ZWQob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9ICBvYmpcclxuXHRcdCAqIEByZXR1cm4ge0Jvb2xlYW59XHJcblx0XHQgKi9cclxuXHRcdGlzX3NlbGVjdGVkIDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIG9iai5zdGF0ZS5zZWxlY3RlZDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGdldCBhbiBhcnJheSBvZiBhbGwgc2VsZWN0ZWQgbm9kZSBJRHNcclxuXHRcdCAqIEBuYW1lIGdldF9zZWxlY3RlZChbZnVsbF0pXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gIGZ1bGwgaWYgc2V0IHRvIGB0cnVlYCB0aGUgcmV0dXJuZWQgYXJyYXkgd2lsbCBjb25zaXN0IG9mIHRoZSBmdWxsIG5vZGUgb2JqZWN0cywgb3RoZXJ3aXNlIC0gb25seSBJRHMgd2lsbCBiZSByZXR1cm5lZFxyXG5cdFx0ICogQHJldHVybiB7QXJyYXl9XHJcblx0XHQgKi9cclxuXHRcdGdldF9zZWxlY3RlZCA6IGZ1bmN0aW9uIChmdWxsKSB7XHJcblx0XHRcdHJldHVybiBmdWxsID8gJC5tYXAodGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLCAkLnByb3h5KGZ1bmN0aW9uIChpKSB7IHJldHVybiB0aGlzLmdldF9ub2RlKGkpOyB9LCB0aGlzKSkgOiB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQ7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXRzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSB0cmVlIHNvIHRoYXQgaXQgY2FuIGJlIHJlc3RvcmVkIGxhdGVyIHdpdGggYHNldF9zdGF0ZShzdGF0ZSlgLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAbmFtZSBnZXRfc3RhdGUoKVxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEByZXR1cm4ge09iamVjdH1cclxuXHRcdCAqL1xyXG5cdFx0Z2V0X3N0YXRlIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR2YXIgc3RhdGVcdD0ge1xyXG5cdFx0XHRcdCdjb3JlJyA6IHtcclxuXHRcdFx0XHRcdCdvcGVuJyA6IFtdLFxyXG5cdFx0XHRcdFx0J3Njcm9sbCcgOiB7XHJcblx0XHRcdFx0XHRcdCdsZWZ0JyA6IHRoaXMuZWxlbWVudC5zY3JvbGxMZWZ0KCksXHJcblx0XHRcdFx0XHRcdCd0b3AnIDogdGhpcy5lbGVtZW50LnNjcm9sbFRvcCgpXHJcblx0XHRcdFx0XHR9LFxyXG5cdFx0XHRcdFx0LyohXHJcblx0XHRcdFx0XHQndGhlbWVzJyA6IHtcclxuXHRcdFx0XHRcdFx0J25hbWUnIDogdGhpcy5nZXRfdGhlbWUoKSxcclxuXHRcdFx0XHRcdFx0J2ljb25zJyA6IHRoaXMuX2RhdGEuY29yZS50aGVtZXMuaWNvbnMsXHJcblx0XHRcdFx0XHRcdCdkb3RzJyA6IHRoaXMuX2RhdGEuY29yZS50aGVtZXMuZG90c1xyXG5cdFx0XHRcdFx0fSxcclxuXHRcdFx0XHRcdCovXHJcblx0XHRcdFx0XHQnc2VsZWN0ZWQnIDogW11cclxuXHRcdFx0XHR9XHJcblx0XHRcdH0sIGk7XHJcblx0XHRcdGZvcihpIGluIHRoaXMuX21vZGVsLmRhdGEpIHtcclxuXHRcdFx0XHRpZih0aGlzLl9tb2RlbC5kYXRhLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHRpZihpICE9PSAnIycpIHtcclxuXHRcdFx0XHRcdFx0aWYodGhpcy5fbW9kZWwuZGF0YVtpXS5zdGF0ZS5vcGVuZWQpIHtcclxuXHRcdFx0XHRcdFx0XHRzdGF0ZS5jb3JlLm9wZW4ucHVzaChpKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZih0aGlzLl9tb2RlbC5kYXRhW2ldLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0XHRcdFx0c3RhdGUuY29yZS5zZWxlY3RlZC5wdXNoKGkpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBzdGF0ZTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHNldHMgdGhlIHN0YXRlIG9mIHRoZSB0cmVlLiBVc2VkIGludGVybmFsbHkuXHJcblx0XHQgKiBAbmFtZSBzZXRfc3RhdGUoc3RhdGUgWywgY2FsbGJhY2tdKVxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSB0aGUgc3RhdGUgdG8gcmVzdG9yZVxyXG5cdFx0ICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYW4gb3B0aW9uYWwgZnVuY3Rpb24gdG8gZXhlY3V0ZSBvbmNlIHRoZSBzdGF0ZSBpcyByZXN0b3JlZC5cclxuXHRcdCAqIEB0cmlnZ2VyIHNldF9zdGF0ZS5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0c2V0X3N0YXRlIDogZnVuY3Rpb24gKHN0YXRlLCBjYWxsYmFjaykge1xyXG5cdFx0XHRpZihzdGF0ZSkge1xyXG5cdFx0XHRcdGlmKHN0YXRlLmNvcmUpIHtcclxuXHRcdFx0XHRcdHZhciByZXMsIG4sIHQsIF90aGlzO1xyXG5cdFx0XHRcdFx0aWYoc3RhdGUuY29yZS5vcGVuKSB7XHJcblx0XHRcdFx0XHRcdGlmKCEkLmlzQXJyYXkoc3RhdGUuY29yZS5vcGVuKSkge1xyXG5cdFx0XHRcdFx0XHRcdGRlbGV0ZSBzdGF0ZS5jb3JlLm9wZW47XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5zZXRfc3RhdGUoc3RhdGUsIGNhbGxiYWNrKTtcclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0cmVzID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0biA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0XHR0ID0gdGhpcztcclxuXHRcdFx0XHRcdFx0JC5lYWNoKHN0YXRlLmNvcmUub3Blbi5jb25jYXQoW10pLCBmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdFx0XHRcdG4gPSB0LmdldF9ub2RlKHYpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKG4pIHtcclxuXHRcdFx0XHRcdFx0XHRcdGlmKHQuaXNfbG9hZGVkKHYpKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKHQuaXNfY2xvc2VkKHYpKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0dC5vcGVuX25vZGUodiwgZmFsc2UsIDApO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKHN0YXRlICYmIHN0YXRlLmNvcmUgJiYgc3RhdGUuY29yZS5vcGVuKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0JC52YWthdGEuYXJyYXlfcmVtb3ZlX2l0ZW0oc3RhdGUuY29yZS5vcGVuLCB2KTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCF0LmlzX2xvYWRpbmcodikpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0Lm9wZW5fbm9kZSh2LCAkLnByb3h5KGZ1bmN0aW9uICgpIHsgdGhpcy5zZXRfc3RhdGUoc3RhdGUsIGNhbGxiYWNrKTsgfSwgdCksIDApO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdC8vIHRoZXJlIHdpbGwgYmUgc29tZSBhc3luYyBhY3Rpdml0eSAtIHNvIHdhaXQgZm9yIGl0XHJcblx0XHRcdFx0XHRcdFx0XHRcdHJlcyA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHRcdGlmKHJlcykge1xyXG5cdFx0XHRcdFx0XHRcdGRlbGV0ZSBzdGF0ZS5jb3JlLm9wZW47XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5zZXRfc3RhdGUoc3RhdGUsIGNhbGxiYWNrKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRpZihzdGF0ZS5jb3JlLnNjcm9sbCkge1xyXG5cdFx0XHRcdFx0XHRpZihzdGF0ZS5jb3JlLnNjcm9sbCAmJiBzdGF0ZS5jb3JlLnNjcm9sbC5sZWZ0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLmVsZW1lbnQuc2Nyb2xsTGVmdChzdGF0ZS5jb3JlLnNjcm9sbC5sZWZ0KTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZihzdGF0ZS5jb3JlLnNjcm9sbCAmJiBzdGF0ZS5jb3JlLnNjcm9sbC50b3AgIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMuZWxlbWVudC5zY3JvbGxUb3Aoc3RhdGUuY29yZS5zY3JvbGwudG9wKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRkZWxldGUgc3RhdGUuY29yZS5zY3JvbGw7XHJcblx0XHRcdFx0XHRcdHRoaXMuc2V0X3N0YXRlKHN0YXRlLCBjYWxsYmFjayk7XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdC8qIVxyXG5cdFx0XHRcdFx0aWYoc3RhdGUuY29yZS50aGVtZXMpIHtcclxuXHRcdFx0XHRcdFx0aWYoc3RhdGUuY29yZS50aGVtZXMubmFtZSkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMuc2V0X3RoZW1lKHN0YXRlLmNvcmUudGhlbWVzLm5hbWUpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGlmKHR5cGVvZiBzdGF0ZS5jb3JlLnRoZW1lcy5kb3RzICE9PSAndW5kZWZpbmVkJykge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXNbIHN0YXRlLmNvcmUudGhlbWVzLmRvdHMgPyBcInNob3dfZG90c1wiIDogXCJoaWRlX2RvdHNcIiBdKCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYodHlwZW9mIHN0YXRlLmNvcmUudGhlbWVzLmljb25zICE9PSAndW5kZWZpbmVkJykge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXNbIHN0YXRlLmNvcmUudGhlbWVzLmljb25zID8gXCJzaG93X2ljb25zXCIgOiBcImhpZGVfaWNvbnNcIiBdKCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0ZGVsZXRlIHN0YXRlLmNvcmUudGhlbWVzO1xyXG5cdFx0XHRcdFx0XHRkZWxldGUgc3RhdGUuY29yZS5vcGVuO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNldF9zdGF0ZShzdGF0ZSwgY2FsbGJhY2spO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHQqL1xyXG5cdFx0XHRcdFx0aWYoc3RhdGUuY29yZS5zZWxlY3RlZCkge1xyXG5cdFx0XHRcdFx0XHRfdGhpcyA9IHRoaXM7XHJcblx0XHRcdFx0XHRcdHRoaXMuZGVzZWxlY3RfYWxsKCk7XHJcblx0XHRcdFx0XHRcdCQuZWFjaChzdGF0ZS5jb3JlLnNlbGVjdGVkLCBmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdFx0XHRcdF90aGlzLnNlbGVjdF9ub2RlKHYpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdFx0ZGVsZXRlIHN0YXRlLmNvcmUuc2VsZWN0ZWQ7XHJcblx0XHRcdFx0XHRcdHRoaXMuc2V0X3N0YXRlKHN0YXRlLCBjYWxsYmFjayk7XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmKCQuaXNFbXB0eU9iamVjdChzdGF0ZS5jb3JlKSkge1xyXG5cdFx0XHRcdFx0XHRkZWxldGUgc3RhdGUuY29yZTtcclxuXHRcdFx0XHRcdFx0dGhpcy5zZXRfc3RhdGUoc3RhdGUsIGNhbGxiYWNrKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZigkLmlzRW1wdHlPYmplY3Qoc3RhdGUpKSB7XHJcblx0XHRcdFx0XHRzdGF0ZSA9IG51bGw7XHJcblx0XHRcdFx0XHRpZihjYWxsYmFjaykgeyBjYWxsYmFjay5jYWxsKHRoaXMpOyB9XHJcblx0XHRcdFx0XHQvKipcclxuXHRcdFx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGEgYHNldF9zdGF0ZWAgY2FsbCBjb21wbGV0ZXNcclxuXHRcdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdFx0ICogQG5hbWUgc2V0X3N0YXRlLmpzdHJlZVxyXG5cdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXIoJ3NldF9zdGF0ZScpO1xyXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiByZWZyZXNoZXMgdGhlIHRyZWUgLSBhbGwgbm9kZXMgYXJlIHJlbG9hZGVkIHdpdGggY2FsbHMgdG8gYGxvYWRfbm9kZWAuXHJcblx0XHQgKiBAbmFtZSByZWZyZXNoKClcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gc2tpcF9sb2FkaW5nIGFuIG9wdGlvbiB0byBza2lwIHNob3dpbmcgdGhlIGxvYWRpbmcgaW5kaWNhdG9yXHJcblx0XHQgKiBAdHJpZ2dlciByZWZyZXNoLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRyZWZyZXNoIDogZnVuY3Rpb24gKHNraXBfbG9hZGluZykge1xyXG5cdFx0XHR0aGlzLl9kYXRhLmNvcmUuc3RhdGUgPSB0aGlzLmdldF9zdGF0ZSgpO1xyXG5cdFx0XHR0aGlzLl9jbnQgPSAwO1xyXG5cdFx0XHR0aGlzLl9tb2RlbC5kYXRhID0ge1xyXG5cdFx0XHRcdCcjJyA6IHtcclxuXHRcdFx0XHRcdGlkIDogJyMnLFxyXG5cdFx0XHRcdFx0cGFyZW50IDogbnVsbCxcclxuXHRcdFx0XHRcdHBhcmVudHMgOiBbXSxcclxuXHRcdFx0XHRcdGNoaWxkcmVuIDogW10sXHJcblx0XHRcdFx0XHRjaGlsZHJlbl9kIDogW10sXHJcblx0XHRcdFx0XHRzdGF0ZSA6IHsgbG9hZGVkIDogZmFsc2UgfVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fTtcclxuXHRcdFx0dmFyIGMgPSB0aGlzLmdldF9jb250YWluZXJfdWwoKVswXS5jbGFzc05hbWU7XHJcblx0XHRcdGlmKCFza2lwX2xvYWRpbmcpIHtcclxuXHRcdFx0XHR0aGlzLmVsZW1lbnQuaHRtbChcIjxcIitcInVsIGNsYXNzPSdqc3RyZWUtY29udGFpbmVyLXVsJz48XCIrXCJsaSBjbGFzcz0nanN0cmVlLWluaXRpYWwtbm9kZSBqc3RyZWUtbG9hZGluZyBqc3RyZWUtbGVhZiBqc3RyZWUtbGFzdCc+PGkgY2xhc3M9J2pzdHJlZS1pY29uIGpzdHJlZS1vY2wnPjwvaT48XCIrXCJhIGNsYXNzPSdqc3RyZWUtYW5jaG9yJyBocmVmPScjJz48aSBjbGFzcz0nanN0cmVlLWljb24ganN0cmVlLXRoZW1laWNvbi1oaWRkZW4nPjwvaT5cIiArIHRoaXMuZ2V0X3N0cmluZyhcIkxvYWRpbmcgLi4uXCIpICsgXCI8L2E+PC9saT48L3VsPlwiKTtcclxuXHRcdFx0fVxyXG5cdFx0XHR0aGlzLmxvYWRfbm9kZSgnIycsIGZ1bmN0aW9uIChvLCBzKSB7XHJcblx0XHRcdFx0aWYocykge1xyXG5cdFx0XHRcdFx0dGhpcy5nZXRfY29udGFpbmVyX3VsKClbMF0uY2xhc3NOYW1lID0gYztcclxuXHRcdFx0XHRcdHRoaXMuc2V0X3N0YXRlKCQuZXh0ZW5kKHRydWUsIHt9LCB0aGlzLl9kYXRhLmNvcmUuc3RhdGUpLCBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIGByZWZyZXNoYCBjYWxsIGNvbXBsZXRlc1xyXG5cdFx0XHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHRcdFx0ICogQG5hbWUgcmVmcmVzaC5qc3RyZWVcclxuXHRcdFx0XHRcdFx0ICovXHJcblx0XHRcdFx0XHRcdHRoaXMudHJpZ2dlcigncmVmcmVzaCcpO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5zdGF0ZSA9IG51bGw7XHJcblx0XHRcdH0pO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogc2V0IChjaGFuZ2UpIHRoZSBJRCBvZiBhIG5vZGVcclxuXHRcdCAqIEBuYW1lIHNldF9pZChvYmosIGlkKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiB0aGUgbm9kZVxyXG5cdFx0ICogQHBhcmFtICB7U3RyaW5nfSBpZCB0aGUgbmV3IElEXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRzZXRfaWQgOiBmdW5jdGlvbiAob2JqLCBpZCkge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdHZhciBpLCBqLCBtID0gdGhpcy5fbW9kZWwuZGF0YTtcclxuXHRcdFx0Ly8gdXBkYXRlIHBhcmVudHMgKHJlcGxhY2UgY3VycmVudCBJRCB3aXRoIG5ldyBvbmUgaW4gY2hpbGRyZW4gYW5kIGNoaWxkcmVuX2QpXHJcblx0XHRcdG1bb2JqLnBhcmVudF0uY2hpbGRyZW5bJC5pbkFycmF5KG9iai5pZCwgbVtvYmoucGFyZW50XS5jaGlsZHJlbildID0gaWQ7XHJcblx0XHRcdGZvcihpID0gMCwgaiA9IG9iai5wYXJlbnRzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdG1bb2JqLnBhcmVudHNbaV1dLmNoaWxkcmVuX2RbJC5pbkFycmF5KG9iai5pZCwgbVtvYmoucGFyZW50c1tpXV0uY2hpbGRyZW5fZCldID0gaWQ7XHJcblx0XHRcdH1cclxuXHRcdFx0Ly8gdXBkYXRlIGNoaWxkcmVuIChyZXBsYWNlIGN1cnJlbnQgSUQgd2l0aCBuZXcgb25lIGluIHBhcmVudCBhbmQgcGFyZW50cylcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gb2JqLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdG1bb2JqLmNoaWxkcmVuW2ldXS5wYXJlbnQgPSBpZDtcclxuXHRcdFx0fVxyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW5fZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRtW29iai5jaGlsZHJlbl9kW2ldXS5wYXJlbnRzWyQuaW5BcnJheShvYmouaWQsIG1bb2JqLmNoaWxkcmVuX2RbaV1dLnBhcmVudHMpXSA9IGlkO1xyXG5cdFx0XHR9XHJcblx0XHRcdGkgPSAkLmluQXJyYXkob2JqLmlkLCB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQpO1xyXG5cdFx0XHRpZihpICE9PSAtMSkgeyB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWRbaV0gPSBpZDsgfVxyXG5cdFx0XHQvLyB1cGRhdGUgbW9kZWwgYW5kIG9iaiBpdHNlbGYgKG9iai5pZCwgdGhpcy5fbW9kZWwuZGF0YVtLRVldKVxyXG5cdFx0XHRpID0gdGhpcy5nZXRfbm9kZShvYmouaWQsIHRydWUpO1xyXG5cdFx0XHRpZihpKSB7XHJcblx0XHRcdFx0aS5hdHRyKCdpZCcsIGlkKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRkZWxldGUgbVtvYmouaWRdO1xyXG5cdFx0XHRvYmouaWQgPSBpZDtcclxuXHRcdFx0bVtpZF0gPSBvYmo7XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0IHRoZSB0ZXh0IHZhbHVlIG9mIGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgZ2V0X3RleHQob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiB0aGUgbm9kZVxyXG5cdFx0ICogQHJldHVybiB7U3RyaW5nfVxyXG5cdFx0ICovXHJcblx0XHRnZXRfdGV4dCA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRyZXR1cm4gKCFvYmogfHwgb2JqLmlkID09PSAnIycpID8gZmFsc2UgOiBvYmoudGV4dDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHNldCB0aGUgdGV4dCB2YWx1ZSBvZiBhIG5vZGUuIFVzZWQgaW50ZXJuYWxseSwgcGxlYXNlIHVzZSBgcmVuYW1lX25vZGUob2JqLCB2YWwpYC5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBzZXRfdGV4dChvYmosIHZhbClcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmogdGhlIG5vZGUsIHlvdSBjYW4gcGFzcyBhbiBhcnJheSB0byBzZXQgdGhlIHRleHQgb24gbXVsdGlwbGUgbm9kZXNcclxuXHRcdCAqIEBwYXJhbSAge1N0cmluZ30gdmFsIHRoZSBuZXcgdGV4dCB2YWx1ZVxyXG5cdFx0ICogQHJldHVybiB7Qm9vbGVhbn1cclxuXHRcdCAqIEB0cmlnZ2VyIHNldF90ZXh0LmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRzZXRfdGV4dCA6IGZ1bmN0aW9uIChvYmosIHZhbCkge1xyXG5cdFx0XHR2YXIgdDEsIHQyLCBkb20sIHRtcDtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuc2V0X3RleHQob2JqW3QxXSwgdmFsKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRvYmoudGV4dCA9IHZhbDtcclxuXHRcdFx0ZG9tID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpO1xyXG5cdFx0XHRpZihkb20ubGVuZ3RoKSB7XHJcblx0XHRcdFx0ZG9tID0gZG9tLmNoaWxkcmVuKFwiLmpzdHJlZS1hbmNob3I6ZXEoMClcIik7XHJcblx0XHRcdFx0dG1wID0gZG9tLmNoaWxkcmVuKFwiSVwiKS5jbG9uZSgpO1xyXG5cdFx0XHRcdGRvbS5odG1sKHZhbCkucHJlcGVuZCh0bXApO1xyXG5cdFx0XHRcdC8qKlxyXG5cdFx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGEgbm9kZSB0ZXh0IHZhbHVlIGlzIGNoYW5nZWRcclxuXHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHQgKiBAbmFtZSBzZXRfdGV4dC5qc3RyZWVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gb2JqXHJcblx0XHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHRleHQgdGhlIG5ldyB2YWx1ZVxyXG5cdFx0XHRcdCAqL1xyXG5cdFx0XHRcdHRoaXMudHJpZ2dlcignc2V0X3RleHQnLHsgXCJvYmpcIiA6IG9iaiwgXCJ0ZXh0XCIgOiB2YWwgfSk7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXRzIGEgSlNPTiByZXByZXNlbnRhdGlvbiBvZiBhIG5vZGUgKG9yIHRoZSB3aG9sZSB0cmVlKVxyXG5cdFx0ICogQG5hbWUgZ2V0X2pzb24oW29iaiwgb3B0aW9uc10pXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAcGFyYW0gIHtPYmplY3R9IG9wdGlvbnNcclxuXHRcdCAqIEBwYXJhbSAge0Jvb2xlYW59IG9wdGlvbnMubm9fc3RhdGUgZG8gbm90IHJldHVybiBzdGF0ZSBpbmZvcm1hdGlvblxyXG5cdFx0ICogQHBhcmFtICB7Qm9vbGVhbn0gb3B0aW9ucy5ub19pZCBkbyBub3QgcmV0dXJuIElEXHJcblx0XHQgKiBAcGFyYW0gIHtCb29sZWFufSBvcHRpb25zLm5vX2NoaWxkcmVuIGRvIG5vdCBpbmNsdWRlIGNoaWxkcmVuXHJcblx0XHQgKiBAcGFyYW0gIHtCb29sZWFufSBvcHRpb25zLm5vX2RhdGEgZG8gbm90IGluY2x1ZGUgbm9kZSBkYXRhXHJcblx0XHQgKiBAcGFyYW0gIHtCb29sZWFufSBvcHRpb25zLmZsYXQgcmV0dXJuIGZsYXQgSlNPTiBpbnN0ZWFkIG9mIG5lc3RlZFxyXG5cdFx0ICogQHJldHVybiB7T2JqZWN0fVxyXG5cdFx0ICovXHJcblx0XHRnZXRfanNvbiA6IGZ1bmN0aW9uIChvYmosIG9wdGlvbnMsIGZsYXQpIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmogfHwgJyMnKTtcclxuXHRcdFx0aWYoIW9iaikgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0aWYob3B0aW9ucyAmJiBvcHRpb25zLmZsYXQgJiYgIWZsYXQpIHsgZmxhdCA9IFtdOyB9XHJcblx0XHRcdHZhciB0bXAgPSB7XHJcblx0XHRcdFx0J2lkJyA6IG9iai5pZCxcclxuXHRcdFx0XHQndGV4dCcgOiBvYmoudGV4dCxcclxuXHRcdFx0XHQnaWNvbicgOiB0aGlzLmdldF9pY29uKG9iaiksXHJcblx0XHRcdFx0J2xpX2F0dHInIDogb2JqLmxpX2F0dHIsXHJcblx0XHRcdFx0J2FfYXR0cicgOiBvYmouYV9hdHRyLFxyXG5cdFx0XHRcdCdzdGF0ZScgOiB7fSxcclxuXHRcdFx0XHQnZGF0YScgOiBvcHRpb25zICYmIG9wdGlvbnMubm9fZGF0YSA/IGZhbHNlIDogb2JqLmRhdGFcclxuXHRcdFx0XHQvLyggdGhpcy5nZXRfbm9kZShvYmosIHRydWUpLmxlbmd0aCA/IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKS5kYXRhKCkgOiBvYmouZGF0YSApLFxyXG5cdFx0XHR9LCBpLCBqO1xyXG5cdFx0XHRpZihvcHRpb25zICYmIG9wdGlvbnMuZmxhdCkge1xyXG5cdFx0XHRcdHRtcC5wYXJlbnQgPSBvYmoucGFyZW50O1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbiA9IFtdO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKCFvcHRpb25zIHx8ICFvcHRpb25zLm5vX3N0YXRlKSB7XHJcblx0XHRcdFx0Zm9yKGkgaW4gb2JqLnN0YXRlKSB7XHJcblx0XHRcdFx0XHRpZihvYmouc3RhdGUuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuXHRcdFx0XHRcdFx0dG1wLnN0YXRlW2ldID0gb2JqLnN0YXRlW2ldO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZihvcHRpb25zICYmIG9wdGlvbnMubm9faWQpIHtcclxuXHRcdFx0XHRkZWxldGUgdG1wLmlkO1xyXG5cdFx0XHRcdGlmKHRtcC5saV9hdHRyICYmIHRtcC5saV9hdHRyLmlkKSB7XHJcblx0XHRcdFx0XHRkZWxldGUgdG1wLmxpX2F0dHIuaWQ7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKG9wdGlvbnMgJiYgb3B0aW9ucy5mbGF0ICYmIG9iai5pZCAhPT0gJyMnKSB7XHJcblx0XHRcdFx0ZmxhdC5wdXNoKHRtcCk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIW9wdGlvbnMgfHwgIW9wdGlvbnMubm9fY2hpbGRyZW4pIHtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRpZihvcHRpb25zICYmIG9wdGlvbnMuZmxhdCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmdldF9qc29uKG9iai5jaGlsZHJlbltpXSwgb3B0aW9ucywgZmxhdCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0dG1wLmNoaWxkcmVuLnB1c2godGhpcy5nZXRfanNvbihvYmouY2hpbGRyZW5baV0sIG9wdGlvbnMpKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIG9wdGlvbnMgJiYgb3B0aW9ucy5mbGF0ID8gZmxhdCA6IChvYmouaWQgPT09ICcjJyA/IHRtcC5jaGlsZHJlbiA6IHRtcCk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBjcmVhdGUgYSBuZXcgbm9kZSAoZG8gbm90IGNvbmZ1c2Ugd2l0aCBsb2FkX25vZGUpXHJcblx0XHQgKiBAbmFtZSBjcmVhdGVfbm9kZShbb2JqLCBub2RlLCBwb3MsIGNhbGxiYWNrLCBpc19sb2FkZWRdKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9ICAgcGFyICAgICAgIHRoZSBwYXJlbnQgbm9kZVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9ICAgbm9kZSAgICAgIHRoZSBkYXRhIGZvciB0aGUgbmV3IG5vZGUgKGEgdmFsaWQgSlNPTiBvYmplY3QsIG9yIGEgc2ltcGxlIHN0cmluZyB3aXRoIHRoZSBuYW1lKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9ICAgcG9zICAgICAgIHRoZSBpbmRleCBhdCB3aGljaCB0byBpbnNlcnQgdGhlIG5vZGUsIFwiZmlyc3RcIiBhbmQgXCJsYXN0XCIgYXJlIGFsc28gc3VwcG9ydGVkLCBkZWZhdWx0IGlzIFwibGFzdFwiXHJcblx0XHQgKiBAcGFyYW0gIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgb25jZSB0aGUgbm9kZSBpcyBjcmVhdGVkXHJcblx0XHQgKiBAcGFyYW0gIHtCb29sZWFufSBpc19sb2FkZWQgaW50ZXJuYWwgYXJndW1lbnQgaW5kaWNhdGluZyBpZiB0aGUgcGFyZW50IG5vZGUgd2FzIHN1Y2Nlc2Z1bGx5IGxvYWRlZFxyXG5cdFx0ICogQHJldHVybiB7U3RyaW5nfSAgICAgICAgICAgIHRoZSBJRCBvZiB0aGUgbmV3bHkgY3JlYXRlIG5vZGVcclxuXHRcdCAqIEB0cmlnZ2VyIG1vZGVsLmpzdHJlZSwgY3JlYXRlX25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGNyZWF0ZV9ub2RlIDogZnVuY3Rpb24gKHBhciwgbm9kZSwgcG9zLCBjYWxsYmFjaywgaXNfbG9hZGVkKSB7XHJcblx0XHRcdHBhciA9IHRoaXMuZ2V0X25vZGUocGFyKTtcclxuXHRcdFx0aWYoIXBhcikgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0cG9zID0gcG9zID09PSB1bmRlZmluZWQgPyBcImxhc3RcIiA6IHBvcztcclxuXHRcdFx0aWYoIXBvcy50b1N0cmluZygpLm1hdGNoKC9eKGJlZm9yZXxhZnRlcikkLykgJiYgIWlzX2xvYWRlZCAmJiAhdGhpcy5pc19sb2FkZWQocGFyKSkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLmxvYWRfbm9kZShwYXIsIGZ1bmN0aW9uICgpIHsgdGhpcy5jcmVhdGVfbm9kZShwYXIsIG5vZGUsIHBvcywgY2FsbGJhY2ssIHRydWUpOyB9KTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZighbm9kZSkgeyBub2RlID0geyBcInRleHRcIiA6IHRoaXMuZ2V0X3N0cmluZygnTmV3IG5vZGUnKSB9OyB9XHJcblx0XHRcdGlmKG5vZGUudGV4dCA9PT0gdW5kZWZpbmVkKSB7IG5vZGUudGV4dCA9IHRoaXMuZ2V0X3N0cmluZygnTmV3IG5vZGUnKTsgfVxyXG5cdFx0XHR2YXIgdG1wLCBkcGMsIGksIGo7XHJcblxyXG5cdFx0XHRpZihwYXIuaWQgPT09ICcjJykge1xyXG5cdFx0XHRcdGlmKHBvcyA9PT0gXCJiZWZvcmVcIikgeyBwb3MgPSBcImZpcnN0XCI7IH1cclxuXHRcdFx0XHRpZihwb3MgPT09IFwiYWZ0ZXJcIikgeyBwb3MgPSBcImxhc3RcIjsgfVxyXG5cdFx0XHR9XHJcblx0XHRcdHN3aXRjaChwb3MpIHtcclxuXHRcdFx0XHRjYXNlIFwiYmVmb3JlXCI6XHJcblx0XHRcdFx0XHR0bXAgPSB0aGlzLmdldF9ub2RlKHBhci5wYXJlbnQpO1xyXG5cdFx0XHRcdFx0cG9zID0gJC5pbkFycmF5KHBhci5pZCwgdG1wLmNoaWxkcmVuKTtcclxuXHRcdFx0XHRcdHBhciA9IHRtcDtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdGNhc2UgXCJhZnRlclwiIDpcclxuXHRcdFx0XHRcdHRtcCA9IHRoaXMuZ2V0X25vZGUocGFyLnBhcmVudCk7XHJcblx0XHRcdFx0XHRwb3MgPSAkLmluQXJyYXkocGFyLmlkLCB0bXAuY2hpbGRyZW4pICsgMTtcclxuXHRcdFx0XHRcdHBhciA9IHRtcDtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdGNhc2UgXCJpbnNpZGVcIjpcclxuXHRcdFx0XHRjYXNlIFwiZmlyc3RcIjpcclxuXHRcdFx0XHRcdHBvcyA9IDA7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRjYXNlIFwibGFzdFwiOlxyXG5cdFx0XHRcdFx0cG9zID0gcGFyLmNoaWxkcmVuLmxlbmd0aDtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdGRlZmF1bHQ6XHJcblx0XHRcdFx0XHRpZighcG9zKSB7IHBvcyA9IDA7IH1cclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHBvcyA+IHBhci5jaGlsZHJlbi5sZW5ndGgpIHsgcG9zID0gcGFyLmNoaWxkcmVuLmxlbmd0aDsgfVxyXG5cdFx0XHRpZighbm9kZS5pZCkgeyBub2RlLmlkID0gdHJ1ZTsgfVxyXG5cdFx0XHRpZighdGhpcy5jaGVjayhcImNyZWF0ZV9ub2RlXCIsIG5vZGUsIHBhciwgcG9zKSkge1xyXG5cdFx0XHRcdHRoaXMuc2V0dGluZ3MuY29yZS5lcnJvci5jYWxsKHRoaXMsIHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yKTtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYobm9kZS5pZCA9PT0gdHJ1ZSkgeyBkZWxldGUgbm9kZS5pZDsgfVxyXG5cdFx0XHRub2RlID0gdGhpcy5fcGFyc2VfbW9kZWxfZnJvbV9qc29uKG5vZGUsIHBhci5pZCwgcGFyLnBhcmVudHMuY29uY2F0KCkpO1xyXG5cdFx0XHRpZighbm9kZSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0dG1wID0gdGhpcy5nZXRfbm9kZShub2RlKTtcclxuXHRcdFx0ZHBjID0gW107XHJcblx0XHRcdGRwYy5wdXNoKG5vZGUpO1xyXG5cdFx0XHRkcGMgPSBkcGMuY29uY2F0KHRtcC5jaGlsZHJlbl9kKTtcclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdtb2RlbCcsIHsgXCJub2Rlc1wiIDogZHBjLCBcInBhcmVudFwiIDogcGFyLmlkIH0pO1xyXG5cclxuXHRcdFx0cGFyLmNoaWxkcmVuX2QgPSBwYXIuY2hpbGRyZW5fZC5jb25jYXQoZHBjKTtcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gcGFyLnBhcmVudHMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVtwYXIucGFyZW50c1tpXV0uY2hpbGRyZW5fZCA9IHRoaXMuX21vZGVsLmRhdGFbcGFyLnBhcmVudHNbaV1dLmNoaWxkcmVuX2QuY29uY2F0KGRwYyk7XHJcblx0XHRcdH1cclxuXHRcdFx0bm9kZSA9IHRtcDtcclxuXHRcdFx0dG1wID0gW107XHJcblx0XHRcdGZvcihpID0gMCwgaiA9IHBhci5jaGlsZHJlbi5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHR0bXBbaSA+PSBwb3MgPyBpKzEgOiBpXSA9IHBhci5jaGlsZHJlbltpXTtcclxuXHRcdFx0fVxyXG5cdFx0XHR0bXBbcG9zXSA9IG5vZGUuaWQ7XHJcblx0XHRcdHBhci5jaGlsZHJlbiA9IHRtcDtcclxuXHJcblx0XHRcdHRoaXMucmVkcmF3X25vZGUocGFyLCB0cnVlKTtcclxuXHRcdFx0aWYoY2FsbGJhY2spIHsgY2FsbGJhY2suY2FsbCh0aGlzLCB0aGlzLmdldF9ub2RlKG5vZGUpKTsgfVxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gYSBub2RlIGlzIGNyZWF0ZWRcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGNyZWF0ZV9ub2RlLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gbm9kZVxyXG5cdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gcGFyZW50IHRoZSBwYXJlbnQncyBJRFxyXG5cdFx0XHQgKiBAcGFyYW0ge051bWJlcn0gcG9zaXRpb24gdGhlIHBvc2l0aW9uIG9mIHRoZSBuZXcgbm9kZSBhbW9uZyB0aGUgcGFyZW50J3MgY2hpbGRyZW5cclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignY3JlYXRlX25vZGUnLCB7IFwibm9kZVwiIDogdGhpcy5nZXRfbm9kZShub2RlKSwgXCJwYXJlbnRcIiA6IHBhci5pZCwgXCJwb3NpdGlvblwiIDogcG9zIH0pO1xyXG5cdFx0XHRyZXR1cm4gbm9kZS5pZDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHNldCB0aGUgdGV4dCB2YWx1ZSBvZiBhIG5vZGVcclxuXHRcdCAqIEBuYW1lIHJlbmFtZV9ub2RlKG9iaiwgdmFsKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiB0aGUgbm9kZSwgeW91IGNhbiBwYXNzIGFuIGFycmF5IHRvIHJlbmFtZSBtdWx0aXBsZSBub2RlcyB0byB0aGUgc2FtZSBuYW1lXHJcblx0XHQgKiBAcGFyYW0gIHtTdHJpbmd9IHZhbCB0aGUgbmV3IHRleHQgdmFsdWVcclxuXHRcdCAqIEByZXR1cm4ge0Jvb2xlYW59XHJcblx0XHQgKiBAdHJpZ2dlciByZW5hbWVfbm9kZS5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0cmVuYW1lX25vZGUgOiBmdW5jdGlvbiAob2JqLCB2YWwpIHtcclxuXHRcdFx0dmFyIHQxLCB0Miwgb2xkO1xyXG5cdFx0XHRpZigkLmlzQXJyYXkob2JqKSkge1xyXG5cdFx0XHRcdG9iaiA9IG9iai5zbGljZSgpO1xyXG5cdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0dGhpcy5yZW5hbWVfbm9kZShvYmpbdDFdLCB2YWwpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdG9sZCA9IG9iai50ZXh0O1xyXG5cdFx0XHRpZighdGhpcy5jaGVjayhcInJlbmFtZV9ub2RlXCIsIG9iaiwgdGhpcy5nZXRfcGFyZW50KG9iaiksIHZhbCkpIHtcclxuXHRcdFx0XHR0aGlzLnNldHRpbmdzLmNvcmUuZXJyb3IuY2FsbCh0aGlzLCB0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvcik7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuc2V0X3RleHQob2JqLCB2YWwpOyAvLyAuYXBwbHkodGhpcywgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSlcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGEgbm9kZSBpcyByZW5hbWVkXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSByZW5hbWVfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHRleHQgdGhlIG5ldyB2YWx1ZVxyXG5cdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gb2xkIHRoZSBvbGQgdmFsdWVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcigncmVuYW1lX25vZGUnLCB7IFwibm9kZVwiIDogb2JqLCBcInRleHRcIiA6IHZhbCwgXCJvbGRcIiA6IG9sZCB9KTtcclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiByZW1vdmUgYSBub2RlXHJcblx0XHQgKiBAbmFtZSBkZWxldGVfbm9kZShvYmopXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqIHRoZSBub2RlLCB5b3UgY2FuIHBhc3MgYW4gYXJyYXkgdG8gZGVsZXRlIG11bHRpcGxlIG5vZGVzXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICogQHRyaWdnZXIgZGVsZXRlX25vZGUuanN0cmVlLCBjaGFuZ2VkLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRkZWxldGVfbm9kZSA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0dmFyIHQxLCB0MiwgcGFyLCBwb3MsIHRtcCwgaSwgaiwgaywgbCwgYztcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuZGVsZXRlX25vZGUob2JqW3QxXSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0aWYoIW9iaiB8fCBvYmouaWQgPT09ICcjJykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0cGFyID0gdGhpcy5nZXRfbm9kZShvYmoucGFyZW50KTtcclxuXHRcdFx0cG9zID0gJC5pbkFycmF5KG9iai5pZCwgcGFyLmNoaWxkcmVuKTtcclxuXHRcdFx0YyA9IGZhbHNlO1xyXG5cdFx0XHRpZighdGhpcy5jaGVjayhcImRlbGV0ZV9ub2RlXCIsIG9iaiwgcGFyLCBwb3MpKSB7XHJcblx0XHRcdFx0dGhpcy5zZXR0aW5ncy5jb3JlLmVycm9yLmNhbGwodGhpcywgdGhpcy5fZGF0YS5jb3JlLmxhc3RfZXJyb3IpO1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZihwb3MgIT09IC0xKSB7XHJcblx0XHRcdFx0cGFyLmNoaWxkcmVuID0gJC52YWthdGEuYXJyYXlfcmVtb3ZlKHBhci5jaGlsZHJlbiwgcG9zKTtcclxuXHRcdFx0fVxyXG5cdFx0XHR0bXAgPSBvYmouY2hpbGRyZW5fZC5jb25jYXQoW10pO1xyXG5cdFx0XHR0bXAucHVzaChvYmouaWQpO1xyXG5cdFx0XHRmb3IoayA9IDAsIGwgPSB0bXAubGVuZ3RoOyBrIDwgbDsgaysrKSB7XHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gb2JqLnBhcmVudHMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRwb3MgPSAkLmluQXJyYXkodG1wW2tdLCB0aGlzLl9tb2RlbC5kYXRhW29iai5wYXJlbnRzW2ldXS5jaGlsZHJlbl9kKTtcclxuXHRcdFx0XHRcdGlmKHBvcyAhPT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVtvYmoucGFyZW50c1tpXV0uY2hpbGRyZW5fZCA9ICQudmFrYXRhLmFycmF5X3JlbW92ZSh0aGlzLl9tb2RlbC5kYXRhW29iai5wYXJlbnRzW2ldXS5jaGlsZHJlbl9kLCBwb3MpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZih0aGlzLl9tb2RlbC5kYXRhW3RtcFtrXV0uc3RhdGUuc2VsZWN0ZWQpIHtcclxuXHRcdFx0XHRcdGMgPSB0cnVlO1xyXG5cdFx0XHRcdFx0cG9zID0gJC5pbkFycmF5KHRtcFtrXSwgdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkKTtcclxuXHRcdFx0XHRcdGlmKHBvcyAhPT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gJC52YWthdGEuYXJyYXlfcmVtb3ZlKHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCwgcG9zKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIGEgbm9kZSBpcyBkZWxldGVkXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBkZWxldGVfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHBhcmVudCB0aGUgcGFyZW50J3MgSURcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignZGVsZXRlX25vZGUnLCB7IFwibm9kZVwiIDogb2JqLCBcInBhcmVudFwiIDogcGFyLmlkIH0pO1xyXG5cdFx0XHRpZihjKSB7XHJcblx0XHRcdFx0dGhpcy50cmlnZ2VyKCdjaGFuZ2VkJywgeyAnYWN0aW9uJyA6ICdkZWxldGVfbm9kZScsICdub2RlJyA6IG9iaiwgJ3NlbGVjdGVkJyA6IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCwgJ3BhcmVudCcgOiBwYXIuaWQgfSk7XHJcblx0XHRcdH1cclxuXHRcdFx0Zm9yKGsgPSAwLCBsID0gdG1wLmxlbmd0aDsgayA8IGw7IGsrKykge1xyXG5cdFx0XHRcdGRlbGV0ZSB0aGlzLl9tb2RlbC5kYXRhW3RtcFtrXV07XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5yZWRyYXdfbm9kZShwYXIsIHRydWUpO1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGNoZWNrIGlmIGFuIG9wZXJhdGlvbiBpcyBwcmVtaXR0ZWQgb24gdGhlIHRyZWUuIFVzZWQgaW50ZXJuYWxseS5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBjaGVjayhjaGssIG9iaiwgcGFyLCBwb3MpXHJcblx0XHQgKiBAcGFyYW0gIHtTdHJpbmd9IGNoayB0aGUgb3BlcmF0aW9uIHRvIGNoZWNrLCBjYW4gYmUgXCJjcmVhdGVfbm9kZVwiLCBcInJlbmFtZV9ub2RlXCIsIFwiZGVsZXRlX25vZGVcIiwgXCJjb3B5X25vZGVcIiBvciBcIm1vdmVfbm9kZVwiXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqIHRoZSBub2RlXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gcGFyIHRoZSBwYXJlbnRcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBwb3MgdGhlIHBvc2l0aW9uIHRvIGluc2VydCBhdCwgb3IgaWYgXCJyZW5hbWVfbm9kZVwiIC0gdGhlIG5ldyBuYW1lXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRjaGVjayA6IGZ1bmN0aW9uIChjaGssIG9iaiwgcGFyLCBwb3MpIHtcclxuXHRcdFx0b2JqID0gb2JqICYmIG9iai5pZCA/IG9iaiA6IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0cGFyID0gcGFyICYmIHBhci5pZCA/IHBhciA6IHRoaXMuZ2V0X25vZGUocGFyKTtcclxuXHRcdFx0dmFyIHRtcCA9IGNoay5tYXRjaCgvXm1vdmVfbm9kZXxjb3B5X25vZGV8Y3JlYXRlX25vZGUkL2kpID8gcGFyIDogb2JqLFxyXG5cdFx0XHRcdGNoYyA9IHRoaXMuc2V0dGluZ3MuY29yZS5jaGVja19jYWxsYmFjaztcclxuXHRcdFx0aWYoY2hrID09PSBcIm1vdmVfbm9kZVwiKSB7XHJcblx0XHRcdFx0aWYob2JqLmlkID09PSBwYXIuaWQgfHwgJC5pbkFycmF5KG9iai5pZCwgcGFyLmNoaWxkcmVuKSA9PT0gcG9zIHx8ICQuaW5BcnJheShwYXIuaWQsIG9iai5jaGlsZHJlbl9kKSAhPT0gLTEpIHtcclxuXHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yID0geyAnZXJyb3InIDogJ2NoZWNrJywgJ3BsdWdpbicgOiAnY29yZScsICdpZCcgOiAnY29yZV8wMScsICdyZWFzb24nIDogJ01vdmluZyBwYXJlbnQgaW5zaWRlIGNoaWxkJywgJ2RhdGEnIDogSlNPTi5zdHJpbmdpZnkoeyAnY2hrJyA6IGNoaywgJ3BvcycgOiBwb3MsICdvYmonIDogb2JqICYmIG9iai5pZCA/IG9iai5pZCA6IGZhbHNlLCAncGFyJyA6IHBhciAmJiBwYXIuaWQgPyBwYXIuaWQgOiBmYWxzZSB9KSB9O1xyXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHR0bXAgPSB0aGlzLmdldF9ub2RlKHRtcCwgdHJ1ZSk7XHJcblx0XHRcdGlmKHRtcC5sZW5ndGgpIHsgdG1wID0gdG1wLmRhdGEoJ2pzdHJlZScpOyB9XHJcblx0XHRcdGlmKHRtcCAmJiB0bXAuZnVuY3Rpb25zICYmICh0bXAuZnVuY3Rpb25zW2Noa10gPT09IGZhbHNlIHx8IHRtcC5mdW5jdGlvbnNbY2hrXSA9PT0gdHJ1ZSkpIHtcclxuXHRcdFx0XHRpZih0bXAuZnVuY3Rpb25zW2Noa10gPT09IGZhbHNlKSB7XHJcblx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvciA9IHsgJ2Vycm9yJyA6ICdjaGVjaycsICdwbHVnaW4nIDogJ2NvcmUnLCAnaWQnIDogJ2NvcmVfMDInLCAncmVhc29uJyA6ICdOb2RlIGRhdGEgcHJldmVudHMgZnVuY3Rpb246ICcgKyBjaGssICdkYXRhJyA6IEpTT04uc3RyaW5naWZ5KHsgJ2NoaycgOiBjaGssICdwb3MnIDogcG9zLCAnb2JqJyA6IG9iaiAmJiBvYmouaWQgPyBvYmouaWQgOiBmYWxzZSwgJ3BhcicgOiBwYXIgJiYgcGFyLmlkID8gcGFyLmlkIDogZmFsc2UgfSkgfTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRtcC5mdW5jdGlvbnNbY2hrXTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZihjaGMgPT09IGZhbHNlIHx8ICgkLmlzRnVuY3Rpb24oY2hjKSAmJiBjaGMuY2FsbCh0aGlzLCBjaGssIG9iaiwgcGFyLCBwb3MpID09PSBmYWxzZSkgfHwgKGNoYyAmJiBjaGNbY2hrXSA9PT0gZmFsc2UpKSB7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLmxhc3RfZXJyb3IgPSB7ICdlcnJvcicgOiAnY2hlY2snLCAncGx1Z2luJyA6ICdjb3JlJywgJ2lkJyA6ICdjb3JlXzAzJywgJ3JlYXNvbicgOiAnVXNlciBjb25maWcgZm9yIGNvcmUuY2hlY2tfY2FsbGJhY2sgcHJldmVudHMgZnVuY3Rpb246ICcgKyBjaGssICdkYXRhJyA6IEpTT04uc3RyaW5naWZ5KHsgJ2NoaycgOiBjaGssICdwb3MnIDogcG9zLCAnb2JqJyA6IG9iaiAmJiBvYmouaWQgPyBvYmouaWQgOiBmYWxzZSwgJ3BhcicgOiBwYXIgJiYgcGFyLmlkID8gcGFyLmlkIDogZmFsc2UgfSkgfTtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXQgdGhlIGxhc3QgZXJyb3JcclxuXHRcdCAqIEBuYW1lIGxhc3RfZXJyb3IoKVxyXG5cdFx0ICogQHJldHVybiB7T2JqZWN0fVxyXG5cdFx0ICovXHJcblx0XHRsYXN0X2Vycm9yIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5fZGF0YS5jb3JlLmxhc3RfZXJyb3I7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBtb3ZlIGEgbm9kZSB0byBhIG5ldyBwYXJlbnRcclxuXHRcdCAqIEBuYW1lIG1vdmVfbm9kZShvYmosIHBhciBbLCBwb3MsIGNhbGxiYWNrLCBpc19sb2FkZWRdKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiB0aGUgbm9kZSB0byBtb3ZlLCBwYXNzIGFuIGFycmF5IHRvIG1vdmUgbXVsdGlwbGUgbm9kZXNcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBwYXIgdGhlIG5ldyBwYXJlbnRcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBwb3MgdGhlIHBvc2l0aW9uIHRvIGluc2VydCBhdCAoXCJmaXJzdFwiIGFuZCBcImxhc3RcIiBhcmUgc3VwcG9ydGVkLCBhcyB3ZWxsIGFzIFwiYmVmb3JlXCIgYW5kIFwiYWZ0ZXJcIiksIGRlZmF1bHRzIHRvIGAwYFxyXG5cdFx0ICogQHBhcmFtICB7ZnVuY3Rpb259IGNhbGxiYWNrIGEgZnVuY3Rpb24gdG8gY2FsbCBvbmNlIHRoZSBtb3ZlIGlzIGNvbXBsZXRlZCwgcmVjZWl2ZXMgMyBhcmd1bWVudHMgLSB0aGUgbm9kZSwgdGhlIG5ldyBwYXJlbnQgYW5kIHRoZSBwb3NpdGlvblxyXG5cdFx0ICogQHBhcmFtICB7Qm9vbGVhbn0gaW50ZXJuYWwgcGFyYW1ldGVyIGluZGljYXRpbmcgaWYgdGhlIHBhcmVudCBub2RlIGhhcyBiZWVuIGxvYWRlZFxyXG5cdFx0ICogQHRyaWdnZXIgbW92ZV9ub2RlLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRtb3ZlX25vZGUgOiBmdW5jdGlvbiAob2JqLCBwYXIsIHBvcywgY2FsbGJhY2ssIGlzX2xvYWRlZCkge1xyXG5cdFx0XHR2YXIgdDEsIHQyLCBvbGRfcGFyLCBuZXdfcGFyLCBvbGRfaW5zLCBpc19tdWx0aSwgZHBjLCB0bXAsIGksIGosIGssIGwsIHA7XHJcblx0XHRcdGlmKCQuaXNBcnJheShvYmopKSB7XHJcblx0XHRcdFx0b2JqID0gb2JqLnJldmVyc2UoKS5zbGljZSgpO1xyXG5cdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0dGhpcy5tb3ZlX25vZGUob2JqW3QxXSwgcGFyLCBwb3MsIGNhbGxiYWNrLCBpc19sb2FkZWQpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSBvYmogJiYgb2JqLmlkID8gb2JqIDogdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRwYXIgPSB0aGlzLmdldF9ub2RlKHBhcik7XHJcblx0XHRcdHBvcyA9IHBvcyA9PT0gdW5kZWZpbmVkID8gMCA6IHBvcztcclxuXHJcblx0XHRcdGlmKCFwYXIgfHwgIW9iaiB8fCBvYmouaWQgPT09ICcjJykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0aWYoIXBvcy50b1N0cmluZygpLm1hdGNoKC9eKGJlZm9yZXxhZnRlcikkLykgJiYgIWlzX2xvYWRlZCAmJiAhdGhpcy5pc19sb2FkZWQocGFyKSkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLmxvYWRfbm9kZShwYXIsIGZ1bmN0aW9uICgpIHsgdGhpcy5tb3ZlX25vZGUob2JqLCBwYXIsIHBvcywgY2FsbGJhY2ssIHRydWUpOyB9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0b2xkX3BhciA9IChvYmoucGFyZW50IHx8ICcjJykudG9TdHJpbmcoKTtcclxuXHRcdFx0bmV3X3BhciA9ICghcG9zLnRvU3RyaW5nKCkubWF0Y2goL14oYmVmb3JlfGFmdGVyKSQvKSB8fCBwYXIuaWQgPT09ICcjJykgPyBwYXIgOiB0aGlzLmdldF9ub2RlKHBhci5wYXJlbnQpO1xyXG5cdFx0XHRvbGRfaW5zID0gdGhpcy5fbW9kZWwuZGF0YVtvYmouaWRdID8gdGhpcyA6ICQuanN0cmVlLnJlZmVyZW5jZShvYmouaWQpO1xyXG5cdFx0XHRpc19tdWx0aSA9ICFvbGRfaW5zIHx8ICFvbGRfaW5zLl9pZCB8fCAodGhpcy5faWQgIT09IG9sZF9pbnMuX2lkKTtcclxuXHRcdFx0aWYoaXNfbXVsdGkpIHtcclxuXHRcdFx0XHRpZih0aGlzLmNvcHlfbm9kZShvYmosIHBhciwgcG9zLCBjYWxsYmFjaywgaXNfbG9hZGVkKSkge1xyXG5cdFx0XHRcdFx0aWYob2xkX2lucykgeyBvbGRfaW5zLmRlbGV0ZV9ub2RlKG9iaik7IH1cclxuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0Ly92YXIgbSA9IHRoaXMuX21vZGVsLmRhdGE7XHJcblx0XHRcdGlmKG5ld19wYXIuaWQgPT09ICcjJykge1xyXG5cdFx0XHRcdGlmKHBvcyA9PT0gXCJiZWZvcmVcIikgeyBwb3MgPSBcImZpcnN0XCI7IH1cclxuXHRcdFx0XHRpZihwb3MgPT09IFwiYWZ0ZXJcIikgeyBwb3MgPSBcImxhc3RcIjsgfVxyXG5cdFx0XHR9XHJcblx0XHRcdHN3aXRjaChwb3MpIHtcclxuXHRcdFx0XHRjYXNlIFwiYmVmb3JlXCI6XHJcblx0XHRcdFx0XHRwb3MgPSAkLmluQXJyYXkocGFyLmlkLCBuZXdfcGFyLmNoaWxkcmVuKTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdGNhc2UgXCJhZnRlclwiIDpcclxuXHRcdFx0XHRcdHBvcyA9ICQuaW5BcnJheShwYXIuaWQsIG5ld19wYXIuY2hpbGRyZW4pICsgMTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdGNhc2UgXCJpbnNpZGVcIjpcclxuXHRcdFx0XHRjYXNlIFwiZmlyc3RcIjpcclxuXHRcdFx0XHRcdHBvcyA9IDA7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRjYXNlIFwibGFzdFwiOlxyXG5cdFx0XHRcdFx0cG9zID0gbmV3X3Bhci5jaGlsZHJlbi5sZW5ndGg7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHRcdFx0aWYoIXBvcykgeyBwb3MgPSAwOyB9XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0fVxyXG5cdFx0XHRpZihwb3MgPiBuZXdfcGFyLmNoaWxkcmVuLmxlbmd0aCkgeyBwb3MgPSBuZXdfcGFyLmNoaWxkcmVuLmxlbmd0aDsgfVxyXG5cdFx0XHRpZighdGhpcy5jaGVjayhcIm1vdmVfbm9kZVwiLCBvYmosIG5ld19wYXIsIHBvcykpIHtcclxuXHRcdFx0XHR0aGlzLnNldHRpbmdzLmNvcmUuZXJyb3IuY2FsbCh0aGlzLCB0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvcik7XHJcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKG9iai5wYXJlbnQgPT09IG5ld19wYXIuaWQpIHtcclxuXHRcdFx0XHRkcGMgPSBuZXdfcGFyLmNoaWxkcmVuLmNvbmNhdCgpO1xyXG5cdFx0XHRcdHRtcCA9ICQuaW5BcnJheShvYmouaWQsIGRwYyk7XHJcblx0XHRcdFx0aWYodG1wICE9PSAtMSkge1xyXG5cdFx0XHRcdFx0ZHBjID0gJC52YWthdGEuYXJyYXlfcmVtb3ZlKGRwYywgdG1wKTtcclxuXHRcdFx0XHRcdGlmKHBvcyA+IHRtcCkgeyBwb3MtLTsgfVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR0bXAgPSBbXTtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSBkcGMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHR0bXBbaSA+PSBwb3MgPyBpKzEgOiBpXSA9IGRwY1tpXTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0dG1wW3Bvc10gPSBvYmouaWQ7XHJcblx0XHRcdFx0bmV3X3Bhci5jaGlsZHJlbiA9IHRtcDtcclxuXHRcdFx0XHR0aGlzLl9ub2RlX2NoYW5nZWQobmV3X3Bhci5pZCk7XHJcblx0XHRcdFx0dGhpcy5yZWRyYXcobmV3X3Bhci5pZCA9PT0gJyMnKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHQvLyBjbGVhbiBvbGQgcGFyZW50IGFuZCB1cFxyXG5cdFx0XHRcdHRtcCA9IG9iai5jaGlsZHJlbl9kLmNvbmNhdCgpO1xyXG5cdFx0XHRcdHRtcC5wdXNoKG9iai5pZCk7XHJcblx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gb2JqLnBhcmVudHMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRkcGMgPSBbXTtcclxuXHRcdFx0XHRcdHAgPSBvbGRfaW5zLl9tb2RlbC5kYXRhW29iai5wYXJlbnRzW2ldXS5jaGlsZHJlbl9kO1xyXG5cdFx0XHRcdFx0Zm9yKGsgPSAwLCBsID0gcC5sZW5ndGg7IGsgPCBsOyBrKyspIHtcclxuXHRcdFx0XHRcdFx0aWYoJC5pbkFycmF5KHBba10sIHRtcCkgPT09IC0xKSB7XHJcblx0XHRcdFx0XHRcdFx0ZHBjLnB1c2gocFtrXSk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdG9sZF9pbnMuX21vZGVsLmRhdGFbb2JqLnBhcmVudHNbaV1dLmNoaWxkcmVuX2QgPSBkcGM7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdG9sZF9pbnMuX21vZGVsLmRhdGFbb2xkX3Bhcl0uY2hpbGRyZW4gPSAkLnZha2F0YS5hcnJheV9yZW1vdmVfaXRlbShvbGRfaW5zLl9tb2RlbC5kYXRhW29sZF9wYXJdLmNoaWxkcmVuLCBvYmouaWQpO1xyXG5cclxuXHRcdFx0XHQvLyBpbnNlcnQgaW50byBuZXcgcGFyZW50IGFuZCB1cFxyXG5cdFx0XHRcdGZvcihpID0gMCwgaiA9IG5ld19wYXIucGFyZW50cy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuX21vZGVsLmRhdGFbbmV3X3Bhci5wYXJlbnRzW2ldXS5jaGlsZHJlbl9kID0gdGhpcy5fbW9kZWwuZGF0YVtuZXdfcGFyLnBhcmVudHNbaV1dLmNoaWxkcmVuX2QuY29uY2F0KHRtcCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGRwYyA9IFtdO1xyXG5cdFx0XHRcdGZvcihpID0gMCwgaiA9IG5ld19wYXIuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRkcGNbaSA+PSBwb3MgPyBpKzEgOiBpXSA9IG5ld19wYXIuY2hpbGRyZW5baV07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGRwY1twb3NdID0gb2JqLmlkO1xyXG5cdFx0XHRcdG5ld19wYXIuY2hpbGRyZW4gPSBkcGM7XHJcblx0XHRcdFx0bmV3X3Bhci5jaGlsZHJlbl9kLnB1c2gob2JqLmlkKTtcclxuXHRcdFx0XHRuZXdfcGFyLmNoaWxkcmVuX2QgPSBuZXdfcGFyLmNoaWxkcmVuX2QuY29uY2F0KG9iai5jaGlsZHJlbl9kKTtcclxuXHJcblx0XHRcdFx0Ly8gdXBkYXRlIG9iamVjdFxyXG5cdFx0XHRcdG9iai5wYXJlbnQgPSBuZXdfcGFyLmlkO1xyXG5cdFx0XHRcdHRtcCA9IG5ld19wYXIucGFyZW50cy5jb25jYXQoKTtcclxuXHRcdFx0XHR0bXAudW5zaGlmdChuZXdfcGFyLmlkKTtcclxuXHRcdFx0XHRwID0gb2JqLnBhcmVudHMubGVuZ3RoO1xyXG5cdFx0XHRcdG9iai5wYXJlbnRzID0gdG1wO1xyXG5cclxuXHRcdFx0XHQvLyB1cGRhdGUgb2JqZWN0IGNoaWxkcmVuXHJcblx0XHRcdFx0dG1wID0gdG1wLmNvbmNhdCgpO1xyXG5cdFx0XHRcdGZvcihpID0gMCwgaiA9IG9iai5jaGlsZHJlbl9kLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVtvYmouY2hpbGRyZW5fZFtpXV0ucGFyZW50cyA9IHRoaXMuX21vZGVsLmRhdGFbb2JqLmNoaWxkcmVuX2RbaV1dLnBhcmVudHMuc2xpY2UoMCxwKi0xKTtcclxuXHRcdFx0XHRcdEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHRoaXMuX21vZGVsLmRhdGFbb2JqLmNoaWxkcmVuX2RbaV1dLnBhcmVudHMsIHRtcCk7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHR0aGlzLl9ub2RlX2NoYW5nZWQob2xkX3Bhcik7XHJcblx0XHRcdFx0dGhpcy5fbm9kZV9jaGFuZ2VkKG5ld19wYXIuaWQpO1xyXG5cdFx0XHRcdHRoaXMucmVkcmF3KG9sZF9wYXIgPT09ICcjJyB8fCBuZXdfcGFyLmlkID09PSAnIycpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKGNhbGxiYWNrKSB7IGNhbGxiYWNrLmNhbGwodGhpcywgb2JqLCBuZXdfcGFyLCBwb3MpOyB9XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIG5vZGUgaXMgbW92ZWRcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIG1vdmVfbm9kZS5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHBhcmVudCB0aGUgcGFyZW50J3MgSURcclxuXHRcdFx0ICogQHBhcmFtIHtOdW1iZXJ9IHBvc2l0aW9uIHRoZSBwb3NpdGlvbiBvZiB0aGUgbm9kZSBhbW9uZyB0aGUgcGFyZW50J3MgY2hpbGRyZW5cclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IG9sZF9wYXJlbnQgdGhlIG9sZCBwYXJlbnQgb2YgdGhlIG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtCb29sZWFufSBpc19tdWx0aSBkbyB0aGUgbm9kZSBhbmQgbmV3IHBhcmVudCBiZWxvbmcgdG8gZGlmZmVyZW50IGluc3RhbmNlc1xyXG5cdFx0XHQgKiBAcGFyYW0ge2pzVHJlZX0gb2xkX2luc3RhbmNlIHRoZSBpbnN0YW5jZSB0aGUgbm9kZSBjYW1lIGZyb21cclxuXHRcdFx0ICogQHBhcmFtIHtqc1RyZWV9IG5ld19pbnN0YW5jZSB0aGUgaW5zdGFuY2Ugb2YgdGhlIG5ldyBwYXJlbnRcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignbW92ZV9ub2RlJywgeyBcIm5vZGVcIiA6IG9iaiwgXCJwYXJlbnRcIiA6IG5ld19wYXIuaWQsIFwicG9zaXRpb25cIiA6IHBvcywgXCJvbGRfcGFyZW50XCIgOiBvbGRfcGFyLCBcImlzX211bHRpXCIgOiBpc19tdWx0aSwgJ29sZF9pbnN0YW5jZScgOiBvbGRfaW5zLCAnbmV3X2luc3RhbmNlJyA6IHRoaXMgfSk7XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY29weSBhIG5vZGUgdG8gYSBuZXcgcGFyZW50XHJcblx0XHQgKiBAbmFtZSBjb3B5X25vZGUob2JqLCBwYXIgWywgcG9zLCBjYWxsYmFjaywgaXNfbG9hZGVkXSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmogdGhlIG5vZGUgdG8gY29weSwgcGFzcyBhbiBhcnJheSB0byBjb3B5IG11bHRpcGxlIG5vZGVzXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gcGFyIHRoZSBuZXcgcGFyZW50XHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gcG9zIHRoZSBwb3NpdGlvbiB0byBpbnNlcnQgYXQgKFwiZmlyc3RcIiBhbmQgXCJsYXN0XCIgYXJlIHN1cHBvcnRlZCwgYXMgd2VsbCBhcyBcImJlZm9yZVwiIGFuZCBcImFmdGVyXCIpLCBkZWZhdWx0cyB0byBgMGBcclxuXHRcdCAqIEBwYXJhbSAge2Z1bmN0aW9ufSBjYWxsYmFjayBhIGZ1bmN0aW9uIHRvIGNhbGwgb25jZSB0aGUgbW92ZSBpcyBjb21wbGV0ZWQsIHJlY2VpdmVzIDMgYXJndW1lbnRzIC0gdGhlIG5vZGUsIHRoZSBuZXcgcGFyZW50IGFuZCB0aGUgcG9zaXRpb25cclxuXHRcdCAqIEBwYXJhbSAge0Jvb2xlYW59IGludGVybmFsIHBhcmFtZXRlciBpbmRpY2F0aW5nIGlmIHRoZSBwYXJlbnQgbm9kZSBoYXMgYmVlbiBsb2FkZWRcclxuXHRcdCAqIEB0cmlnZ2VyIG1vZGVsLmpzdHJlZSBjb3B5X25vZGUuanN0cmVlXHJcblx0XHQgKi9cclxuXHRcdGNvcHlfbm9kZSA6IGZ1bmN0aW9uIChvYmosIHBhciwgcG9zLCBjYWxsYmFjaywgaXNfbG9hZGVkKSB7XHJcblx0XHRcdHZhciB0MSwgdDIsIGRwYywgdG1wLCBpLCBqLCBub2RlLCBvbGRfcGFyLCBuZXdfcGFyLCBvbGRfaW5zLCBpc19tdWx0aTtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmoucmV2ZXJzZSgpLnNsaWNlKCk7XHJcblx0XHRcdFx0Zm9yKHQxID0gMCwgdDIgPSBvYmoubGVuZ3RoOyB0MSA8IHQyOyB0MSsrKSB7XHJcblx0XHRcdFx0XHR0aGlzLmNvcHlfbm9kZShvYmpbdDFdLCBwYXIsIHBvcywgY2FsbGJhY2ssIGlzX2xvYWRlZCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iaiA9IG9iaiAmJiBvYmouaWQgPyBvYmogOiB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdHBhciA9IHRoaXMuZ2V0X25vZGUocGFyKTtcclxuXHRcdFx0cG9zID0gcG9zID09PSB1bmRlZmluZWQgPyAwIDogcG9zO1xyXG5cclxuXHRcdFx0aWYoIXBhciB8fCAhb2JqIHx8IG9iai5pZCA9PT0gJyMnKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRpZighcG9zLnRvU3RyaW5nKCkubWF0Y2goL14oYmVmb3JlfGFmdGVyKSQvKSAmJiAhaXNfbG9hZGVkICYmICF0aGlzLmlzX2xvYWRlZChwYXIpKSB7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMubG9hZF9ub2RlKHBhciwgZnVuY3Rpb24gKCkgeyB0aGlzLmNvcHlfbm9kZShvYmosIHBhciwgcG9zLCBjYWxsYmFjaywgdHJ1ZSk7IH0pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRvbGRfcGFyID0gKG9iai5wYXJlbnQgfHwgJyMnKS50b1N0cmluZygpO1xyXG5cdFx0XHRuZXdfcGFyID0gKCFwb3MudG9TdHJpbmcoKS5tYXRjaCgvXihiZWZvcmV8YWZ0ZXIpJC8pIHx8IHBhci5pZCA9PT0gJyMnKSA/IHBhciA6IHRoaXMuZ2V0X25vZGUocGFyLnBhcmVudCk7XHJcblx0XHRcdG9sZF9pbnMgPSB0aGlzLl9tb2RlbC5kYXRhW29iai5pZF0gPyB0aGlzIDogJC5qc3RyZWUucmVmZXJlbmNlKG9iai5pZCk7XHJcblx0XHRcdGlzX211bHRpID0gIW9sZF9pbnMgfHwgIW9sZF9pbnMuX2lkIHx8ICh0aGlzLl9pZCAhPT0gb2xkX2lucy5faWQpO1xyXG5cdFx0XHRpZihuZXdfcGFyLmlkID09PSAnIycpIHtcclxuXHRcdFx0XHRpZihwb3MgPT09IFwiYmVmb3JlXCIpIHsgcG9zID0gXCJmaXJzdFwiOyB9XHJcblx0XHRcdFx0aWYocG9zID09PSBcImFmdGVyXCIpIHsgcG9zID0gXCJsYXN0XCI7IH1cclxuXHRcdFx0fVxyXG5cdFx0XHRzd2l0Y2gocG9zKSB7XHJcblx0XHRcdFx0Y2FzZSBcImJlZm9yZVwiOlxyXG5cdFx0XHRcdFx0cG9zID0gJC5pbkFycmF5KHBhci5pZCwgbmV3X3Bhci5jaGlsZHJlbik7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRjYXNlIFwiYWZ0ZXJcIiA6XHJcblx0XHRcdFx0XHRwb3MgPSAkLmluQXJyYXkocGFyLmlkLCBuZXdfcGFyLmNoaWxkcmVuKSArIDE7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRjYXNlIFwiaW5zaWRlXCI6XHJcblx0XHRcdFx0Y2FzZSBcImZpcnN0XCI6XHJcblx0XHRcdFx0XHRwb3MgPSAwO1xyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0Y2FzZSBcImxhc3RcIjpcclxuXHRcdFx0XHRcdHBvcyA9IG5ld19wYXIuY2hpbGRyZW4ubGVuZ3RoO1xyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRcdGlmKCFwb3MpIHsgcG9zID0gMDsgfVxyXG5cdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYocG9zID4gbmV3X3Bhci5jaGlsZHJlbi5sZW5ndGgpIHsgcG9zID0gbmV3X3Bhci5jaGlsZHJlbi5sZW5ndGg7IH1cclxuXHRcdFx0aWYoIXRoaXMuY2hlY2soXCJjb3B5X25vZGVcIiwgb2JqLCBuZXdfcGFyLCBwb3MpKSB7XHJcblx0XHRcdFx0dGhpcy5zZXR0aW5ncy5jb3JlLmVycm9yLmNhbGwodGhpcywgdGhpcy5fZGF0YS5jb3JlLmxhc3RfZXJyb3IpO1xyXG5cdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRub2RlID0gb2xkX2lucyA/IG9sZF9pbnMuZ2V0X2pzb24ob2JqLCB7IG5vX2lkIDogdHJ1ZSwgbm9fZGF0YSA6IHRydWUsIG5vX3N0YXRlIDogdHJ1ZSB9KSA6IG9iajtcclxuXHRcdFx0aWYoIW5vZGUpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdGlmKG5vZGUuaWQgPT09IHRydWUpIHsgZGVsZXRlIG5vZGUuaWQ7IH1cclxuXHRcdFx0bm9kZSA9IHRoaXMuX3BhcnNlX21vZGVsX2Zyb21fanNvbihub2RlLCBuZXdfcGFyLmlkLCBuZXdfcGFyLnBhcmVudHMuY29uY2F0KCkpO1xyXG5cdFx0XHRpZighbm9kZSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0dG1wID0gdGhpcy5nZXRfbm9kZShub2RlKTtcclxuXHRcdFx0ZHBjID0gW107XHJcblx0XHRcdGRwYy5wdXNoKG5vZGUpO1xyXG5cdFx0XHRkcGMgPSBkcGMuY29uY2F0KHRtcC5jaGlsZHJlbl9kKTtcclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdtb2RlbCcsIHsgXCJub2Rlc1wiIDogZHBjLCBcInBhcmVudFwiIDogbmV3X3Bhci5pZCB9KTtcclxuXHJcblx0XHRcdC8vIGluc2VydCBpbnRvIG5ldyBwYXJlbnQgYW5kIHVwXHJcblx0XHRcdGZvcihpID0gMCwgaiA9IG5ld19wYXIucGFyZW50cy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHR0aGlzLl9tb2RlbC5kYXRhW25ld19wYXIucGFyZW50c1tpXV0uY2hpbGRyZW5fZCA9IHRoaXMuX21vZGVsLmRhdGFbbmV3X3Bhci5wYXJlbnRzW2ldXS5jaGlsZHJlbl9kLmNvbmNhdChkcGMpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGRwYyA9IFtdO1xyXG5cdFx0XHRmb3IoaSA9IDAsIGogPSBuZXdfcGFyLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdGRwY1tpID49IHBvcyA/IGkrMSA6IGldID0gbmV3X3Bhci5jaGlsZHJlbltpXTtcclxuXHRcdFx0fVxyXG5cdFx0XHRkcGNbcG9zXSA9IHRtcC5pZDtcclxuXHRcdFx0bmV3X3Bhci5jaGlsZHJlbiA9IGRwYztcclxuXHRcdFx0bmV3X3Bhci5jaGlsZHJlbl9kLnB1c2godG1wLmlkKTtcclxuXHRcdFx0bmV3X3Bhci5jaGlsZHJlbl9kID0gbmV3X3Bhci5jaGlsZHJlbl9kLmNvbmNhdCh0bXAuY2hpbGRyZW5fZCk7XHJcblxyXG5cdFx0XHR0aGlzLl9ub2RlX2NoYW5nZWQobmV3X3Bhci5pZCk7XHJcblx0XHRcdHRoaXMucmVkcmF3KG5ld19wYXIuaWQgPT09ICcjJyk7XHJcblx0XHRcdGlmKGNhbGxiYWNrKSB7IGNhbGxiYWNrLmNhbGwodGhpcywgdG1wLCBuZXdfcGFyLCBwb3MpOyB9XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIG5vZGUgaXMgY29waWVkXHJcblx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHQgKiBAbmFtZSBjb3B5X25vZGUuanN0cmVlXHJcblx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBub2RlIHRoZSBjb3BpZWQgbm9kZVxyXG5cdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gb3JpZ2luYWwgdGhlIG9yaWdpbmFsIG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHBhcmVudCB0aGUgcGFyZW50J3MgSURcclxuXHRcdFx0ICogQHBhcmFtIHtOdW1iZXJ9IHBvc2l0aW9uIHRoZSBwb3NpdGlvbiBvZiB0aGUgbm9kZSBhbW9uZyB0aGUgcGFyZW50J3MgY2hpbGRyZW5cclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IG9sZF9wYXJlbnQgdGhlIG9sZCBwYXJlbnQgb2YgdGhlIG5vZGVcclxuXHRcdFx0ICogQHBhcmFtIHtCb29sZWFufSBpc19tdWx0aSBkbyB0aGUgbm9kZSBhbmQgbmV3IHBhcmVudCBiZWxvbmcgdG8gZGlmZmVyZW50IGluc3RhbmNlc1xyXG5cdFx0XHQgKiBAcGFyYW0ge2pzVHJlZX0gb2xkX2luc3RhbmNlIHRoZSBpbnN0YW5jZSB0aGUgbm9kZSBjYW1lIGZyb21cclxuXHRcdFx0ICogQHBhcmFtIHtqc1RyZWV9IG5ld19pbnN0YW5jZSB0aGUgaW5zdGFuY2Ugb2YgdGhlIG5ldyBwYXJlbnRcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignY29weV9ub2RlJywgeyBcIm5vZGVcIiA6IHRtcCwgXCJvcmlnaW5hbFwiIDogb2JqLCBcInBhcmVudFwiIDogbmV3X3Bhci5pZCwgXCJwb3NpdGlvblwiIDogcG9zLCBcIm9sZF9wYXJlbnRcIiA6IG9sZF9wYXIsIFwiaXNfbXVsdGlcIiA6IGlzX211bHRpLCAnb2xkX2luc3RhbmNlJyA6IG9sZF9pbnMsICduZXdfaW5zdGFuY2UnIDogdGhpcyB9KTtcclxuXHRcdFx0cmV0dXJuIHRtcC5pZDtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGN1dCBhIG5vZGUgKGEgbGF0ZXIgY2FsbCB0byBgcGFzdGUob2JqKWAgd291bGQgbW92ZSB0aGUgbm9kZSlcclxuXHRcdCAqIEBuYW1lIGN1dChvYmopXHJcblx0XHQgKiBAcGFyYW0gIHttaXhlZH0gb2JqIG11bHRpcGxlIG9iamVjdHMgY2FuIGJlIHBhc3NlZCB1c2luZyBhbiBhcnJheVxyXG5cdFx0ICogQHRyaWdnZXIgY3V0LmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRjdXQgOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdGlmKCFvYmopIHsgb2JqID0gdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmNvbmNhdCgpOyB9XHJcblx0XHRcdGlmKCEkLmlzQXJyYXkob2JqKSkgeyBvYmogPSBbb2JqXTsgfVxyXG5cdFx0XHRpZighb2JqLmxlbmd0aCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0dmFyIHRtcCA9IFtdLCBvLCB0MSwgdDI7XHJcblx0XHRcdGZvcih0MSA9IDAsIHQyID0gb2JqLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdG8gPSB0aGlzLmdldF9ub2RlKG9ialt0MV0pO1xyXG5cdFx0XHRcdGlmKG8gJiYgby5pZCAmJiBvLmlkICE9PSAnIycpIHsgdG1wLnB1c2gobyk7IH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZighdG1wLmxlbmd0aCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0Y2NwX25vZGUgPSB0bXA7XHJcblx0XHRcdGNjcF9pbnN0ID0gdGhpcztcclxuXHRcdFx0Y2NwX21vZGUgPSAnbW92ZV9ub2RlJztcclxuXHRcdFx0LyoqXHJcblx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIG5vZGVzIGFyZSBhZGRlZCB0byB0aGUgYnVmZmVyIGZvciBtb3ZpbmdcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGN1dC5qc3RyZWVcclxuXHRcdFx0ICogQHBhcmFtIHtBcnJheX0gbm9kZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdjdXQnLCB7IFwibm9kZVwiIDogb2JqIH0pO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY29weSBhIG5vZGUgKGEgbGF0ZXIgY2FsbCB0byBgcGFzdGUob2JqKWAgd291bGQgY29weSB0aGUgbm9kZSlcclxuXHRcdCAqIEBuYW1lIGNvcHkob2JqKVxyXG5cdFx0ICogQHBhcmFtICB7bWl4ZWR9IG9iaiBtdWx0aXBsZSBvYmplY3RzIGNhbiBiZSBwYXNzZWQgdXNpbmcgYW4gYXJyYXlcclxuXHRcdCAqIEB0cmlnZ2VyIGNvcHkuanN0cmVcclxuXHRcdCAqL1xyXG5cdFx0Y29weSA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0aWYoIW9iaikgeyBvYmogPSB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQuY29uY2F0KCk7IH1cclxuXHRcdFx0aWYoISQuaXNBcnJheShvYmopKSB7IG9iaiA9IFtvYmpdOyB9XHJcblx0XHRcdGlmKCFvYmoubGVuZ3RoKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHR2YXIgdG1wID0gW10sIG8sIHQxLCB0MjtcclxuXHRcdFx0Zm9yKHQxID0gMCwgdDIgPSBvYmoubGVuZ3RoOyB0MSA8IHQyOyB0MSsrKSB7XHJcblx0XHRcdFx0byA9IHRoaXMuZ2V0X25vZGUob2JqW3QxXSk7XHJcblx0XHRcdFx0aWYobyAmJiBvLmlkICYmIG8uaWQgIT09ICcjJykgeyB0bXAucHVzaChvKTsgfVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmKCF0bXAubGVuZ3RoKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRjY3Bfbm9kZSA9IHRtcDtcclxuXHRcdFx0Y2NwX2luc3QgPSB0aGlzO1xyXG5cdFx0XHRjY3BfbW9kZSA9ICdjb3B5X25vZGUnO1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gbm9kZXMgYXJlIGFkZGVkIHRvIHRoZSBidWZmZXIgZm9yIGNvcHlpbmdcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIGNvcHkuanN0cmVlXHJcblx0XHRcdCAqIEBwYXJhbSB7QXJyYXl9IG5vZGVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignY29weScsIHsgXCJub2RlXCIgOiBvYmogfSk7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBnZXQgdGhlIGN1cnJlbnQgYnVmZmVyIChhbnkgbm9kZXMgdGhhdCBhcmUgd2FpdGluZyBmb3IgYSBwYXN0ZSBvcGVyYXRpb24pXHJcblx0XHQgKiBAbmFtZSBnZXRfYnVmZmVyKClcclxuXHRcdCAqIEByZXR1cm4ge09iamVjdH0gYW4gb2JqZWN0IGNvbnNpc3Rpbmcgb2YgYG1vZGVgIChcImNvcHlfbm9kZVwiIG9yIFwibW92ZV9ub2RlXCIpLCBgbm9kZWAgKGFuIGFycmF5IG9mIG9iamVjdHMpIGFuZCBgaW5zdGAgKHRoZSBpbnN0YW5jZSlcclxuXHRcdCAqL1xyXG5cdFx0Z2V0X2J1ZmZlciA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0cmV0dXJuIHsgJ21vZGUnIDogY2NwX21vZGUsICdub2RlJyA6IGNjcF9ub2RlLCAnaW5zdCcgOiBjY3BfaW5zdCB9O1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogY2hlY2sgaWYgdGhlcmUgaXMgc29tZXRoaW5nIGluIHRoZSBidWZmZXIgdG8gcGFzdGVcclxuXHRcdCAqIEBuYW1lIGNhbl9wYXN0ZSgpXHJcblx0XHQgKiBAcmV0dXJuIHtCb29sZWFufVxyXG5cdFx0ICovXHJcblx0XHRjYW5fcGFzdGUgOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHJldHVybiBjY3BfbW9kZSAhPT0gZmFsc2UgJiYgY2NwX25vZGUgIT09IGZhbHNlOyAvLyAmJiBjY3BfaW5zdC5fbW9kZWwuZGF0YVtjY3Bfbm9kZV07XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBjb3B5IG9yIG1vdmUgdGhlIHByZXZpb3VzbHkgY3V0IG9yIGNvcGllZCBub2RlcyB0byBhIG5ldyBwYXJlbnRcclxuXHRcdCAqIEBuYW1lIHBhc3RlKG9iailcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmogdGhlIG5ldyBwYXJlbnRcclxuXHRcdCAqIEB0cmlnZ2VyIHBhc3RlLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRwYXN0ZSA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZighb2JqIHx8ICFjY3BfbW9kZSB8fCAhY2NwX21vZGUubWF0Y2goL14oY29weV9ub2RlfG1vdmVfbm9kZSkkLykgfHwgIWNjcF9ub2RlKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRpZih0aGlzW2NjcF9tb2RlXShjY3Bfbm9kZSwgb2JqKSkge1xyXG5cdFx0XHRcdC8qKlxyXG5cdFx0XHRcdCAqIHRyaWdnZXJlZCB3aGVuIHBhc3RlIGlzIGludm9rZWRcclxuXHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHQgKiBAbmFtZSBwYXN0ZS5qc3RyZWVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gcGFyZW50IHRoZSBJRCBvZiB0aGUgcmVjZWl2aW5nIG5vZGVcclxuXHRcdFx0XHQgKiBAcGFyYW0ge0FycmF5fSBub2RlIHRoZSBub2RlcyBpbiB0aGUgYnVmZmVyXHJcblx0XHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IG1vZGUgdGhlIHBlcmZvcm1lZCBvcGVyYXRpb24gLSBcImNvcHlfbm9kZVwiIG9yIFwibW92ZV9ub2RlXCJcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHR0aGlzLnRyaWdnZXIoJ3Bhc3RlJywgeyBcInBhcmVudFwiIDogb2JqLmlkLCBcIm5vZGVcIiA6IGNjcF9ub2RlLCBcIm1vZGVcIiA6IGNjcF9tb2RlIH0pO1xyXG5cdFx0XHR9XHJcblx0XHRcdGNjcF9ub2RlID0gZmFsc2U7XHJcblx0XHRcdGNjcF9tb2RlID0gZmFsc2U7XHJcblx0XHRcdGNjcF9pbnN0ID0gZmFsc2U7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBwdXQgYSBub2RlIGluIGVkaXQgbW9kZSAoaW5wdXQgZmllbGQgdG8gcmVuYW1lIHRoZSBub2RlKVxyXG5cdFx0ICogQG5hbWUgZWRpdChvYmogWywgZGVmYXVsdF90ZXh0XSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmpcclxuXHRcdCAqIEBwYXJhbSAge1N0cmluZ30gZGVmYXVsdF90ZXh0IHRoZSB0ZXh0IHRvIHBvcHVsYXRlIHRoZSBpbnB1dCB3aXRoIChpZiBvbWl0dGVkIHRoZSBub2RlIHRleHQgdmFsdWUgaXMgdXNlZClcclxuXHRcdCAqL1xyXG5cdFx0ZWRpdCA6IGZ1bmN0aW9uIChvYmosIGRlZmF1bHRfdGV4dCkge1xyXG5cdFx0XHRvYmogPSB0aGlzLl9vcGVuX3RvKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgIW9iai5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdHZhciBydGwgPSB0aGlzLl9kYXRhLmNvcmUucnRsLFxyXG5cdFx0XHRcdHcgID0gdGhpcy5lbGVtZW50LndpZHRoKCksXHJcblx0XHRcdFx0YSAgPSBvYmouY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJyksXHJcblx0XHRcdFx0cyAgPSAkKCc8c3Bhbj4nKSxcclxuXHRcdFx0XHQvKiFcclxuXHRcdFx0XHRvaSA9IG9iai5jaGlsZHJlbihcImk6dmlzaWJsZVwiKSxcclxuXHRcdFx0XHRhaSA9IGEuY2hpbGRyZW4oXCJpOnZpc2libGVcIiksXHJcblx0XHRcdFx0dzEgPSBvaS53aWR0aCgpICogb2kubGVuZ3RoLFxyXG5cdFx0XHRcdHcyID0gYWkud2lkdGgoKSAqIGFpLmxlbmd0aCxcclxuXHRcdFx0XHQqL1xyXG5cdFx0XHRcdHQgID0gdHlwZW9mIGRlZmF1bHRfdGV4dCA9PT0gJ3N0cmluZycgPyBkZWZhdWx0X3RleHQgOiB0aGlzLmdldF90ZXh0KG9iaiksXHJcblx0XHRcdFx0aDEgPSAkKFwiPFwiK1wiZGl2IC8+XCIsIHsgY3NzIDogeyBcInBvc2l0aW9uXCIgOiBcImFic29sdXRlXCIsIFwidG9wXCIgOiBcIi0yMDBweFwiLCBcImxlZnRcIiA6IChydGwgPyBcIjBweFwiIDogXCItMTAwMHB4XCIpLCBcInZpc2liaWxpdHlcIiA6IFwiaGlkZGVuXCIgfSB9KS5hcHBlbmRUbyhcImJvZHlcIiksXHJcblx0XHRcdFx0aDIgPSAkKFwiPFwiK1wiaW5wdXQgLz5cIiwge1xyXG5cdFx0XHRcdFx0XHRcInZhbHVlXCIgOiB0LFxyXG5cdFx0XHRcdFx0XHRcImNsYXNzXCIgOiBcImpzdHJlZS1yZW5hbWUtaW5wdXRcIixcclxuXHRcdFx0XHRcdFx0Ly8gXCJzaXplXCIgOiB0Lmxlbmd0aCxcclxuXHRcdFx0XHRcdFx0XCJjc3NcIiA6IHtcclxuXHRcdFx0XHRcdFx0XHRcInBhZGRpbmdcIiA6IFwiMFwiLFxyXG5cdFx0XHRcdFx0XHRcdFwiYm9yZGVyXCIgOiBcIjFweCBzb2xpZCBzaWx2ZXJcIixcclxuXHRcdFx0XHRcdFx0XHRcImJveC1zaXppbmdcIiA6IFwiYm9yZGVyLWJveFwiLFxyXG5cdFx0XHRcdFx0XHRcdFwiZGlzcGxheVwiIDogXCJpbmxpbmUtYmxvY2tcIixcclxuXHRcdFx0XHRcdFx0XHRcImhlaWdodFwiIDogKHRoaXMuX2RhdGEuY29yZS5saV9oZWlnaHQpICsgXCJweFwiLFxyXG5cdFx0XHRcdFx0XHRcdFwibGluZUhlaWdodFwiIDogKHRoaXMuX2RhdGEuY29yZS5saV9oZWlnaHQpICsgXCJweFwiLFxyXG5cdFx0XHRcdFx0XHRcdFwid2lkdGhcIiA6IFwiMTUwcHhcIiAvLyB3aWxsIGJlIHNldCBhIGJpdCBmdXJ0aGVyIGRvd25cclxuXHRcdFx0XHRcdFx0fSxcclxuXHRcdFx0XHRcdFx0XCJibHVyXCIgOiAkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0XHR2YXIgaSA9IHMuY2hpbGRyZW4oXCIuanN0cmVlLXJlbmFtZS1pbnB1dFwiKSxcclxuXHRcdFx0XHRcdFx0XHRcdHYgPSBpLnZhbCgpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKHYgPT09IFwiXCIpIHsgdiA9IHQ7IH1cclxuXHRcdFx0XHRcdFx0XHRoMS5yZW1vdmUoKTtcclxuXHRcdFx0XHRcdFx0XHRzLnJlcGxhY2VXaXRoKGEpO1xyXG5cdFx0XHRcdFx0XHRcdHMucmVtb3ZlKCk7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5zZXRfdGV4dChvYmosIHQpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKHRoaXMucmVuYW1lX25vZGUob2JqLCB2KSA9PT0gZmFsc2UpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuc2V0X3RleHQob2JqLCB0KTsgLy8gbW92ZSB0aGlzIHVwPyBhbmQgZml4ICM0ODNcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0sIHRoaXMpLFxyXG5cdFx0XHRcdFx0XHRcImtleWRvd25cIiA6IGZ1bmN0aW9uIChldmVudCkge1xyXG5cdFx0XHRcdFx0XHRcdHZhciBrZXkgPSBldmVudC53aGljaDtcclxuXHRcdFx0XHRcdFx0XHRpZihrZXkgPT09IDI3KSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnZhbHVlID0gdDtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0aWYoa2V5ID09PSAyNyB8fCBrZXkgPT09IDEzIHx8IGtleSA9PT0gMzcgfHwga2V5ID09PSAzOCB8fCBrZXkgPT09IDM5IHx8IGtleSA9PT0gNDAgfHwga2V5ID09PSAzMikge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdGlmKGtleSA9PT0gMjcgfHwga2V5ID09PSAxMykge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuYmx1cigpO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSxcclxuXHRcdFx0XHRcdFx0XCJjbGlja1wiIDogZnVuY3Rpb24gKGUpIHsgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTsgfSxcclxuXHRcdFx0XHRcdFx0XCJtb3VzZWRvd25cIiA6IGZ1bmN0aW9uIChlKSB7IGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7IH0sXHJcblx0XHRcdFx0XHRcdFwia2V5dXBcIiA6IGZ1bmN0aW9uIChldmVudCkge1xyXG5cdFx0XHRcdFx0XHRcdGgyLndpZHRoKE1hdGgubWluKGgxLnRleHQoXCJwV1wiICsgdGhpcy52YWx1ZSkud2lkdGgoKSx3KSk7XHJcblx0XHRcdFx0XHRcdH0sXHJcblx0XHRcdFx0XHRcdFwia2V5cHJlc3NcIiA6IGZ1bmN0aW9uKGV2ZW50KSB7XHJcblx0XHRcdFx0XHRcdFx0aWYoZXZlbnQud2hpY2ggPT09IDEzKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9KSxcclxuXHRcdFx0XHRmbiA9IHtcclxuXHRcdFx0XHRcdFx0Zm9udEZhbWlseVx0XHQ6IGEuY3NzKCdmb250RmFtaWx5JylcdFx0fHwgJycsXHJcblx0XHRcdFx0XHRcdGZvbnRTaXplXHRcdDogYS5jc3MoJ2ZvbnRTaXplJylcdFx0XHR8fCAnJyxcclxuXHRcdFx0XHRcdFx0Zm9udFdlaWdodFx0XHQ6IGEuY3NzKCdmb250V2VpZ2h0JylcdFx0fHwgJycsXHJcblx0XHRcdFx0XHRcdGZvbnRTdHlsZVx0XHQ6IGEuY3NzKCdmb250U3R5bGUnKVx0XHR8fCAnJyxcclxuXHRcdFx0XHRcdFx0Zm9udFN0cmV0Y2hcdFx0OiBhLmNzcygnZm9udFN0cmV0Y2gnKVx0XHR8fCAnJyxcclxuXHRcdFx0XHRcdFx0Zm9udFZhcmlhbnRcdFx0OiBhLmNzcygnZm9udFZhcmlhbnQnKVx0XHR8fCAnJyxcclxuXHRcdFx0XHRcdFx0bGV0dGVyU3BhY2luZ1x0OiBhLmNzcygnbGV0dGVyU3BhY2luZycpXHR8fCAnJyxcclxuXHRcdFx0XHRcdFx0d29yZFNwYWNpbmdcdFx0OiBhLmNzcygnd29yZFNwYWNpbmcnKVx0XHR8fCAnJ1xyXG5cdFx0XHRcdH07XHJcblx0XHRcdHRoaXMuc2V0X3RleHQob2JqLCBcIlwiKTtcclxuXHRcdFx0cy5hdHRyKCdjbGFzcycsIGEuYXR0cignY2xhc3MnKSkuYXBwZW5kKGEuY29udGVudHMoKS5jbG9uZSgpKS5hcHBlbmQoaDIpO1xyXG5cdFx0XHRhLnJlcGxhY2VXaXRoKHMpO1xyXG5cdFx0XHRoMS5jc3MoZm4pO1xyXG5cdFx0XHRoMi5jc3MoZm4pLndpZHRoKE1hdGgubWluKGgxLnRleHQoXCJwV1wiICsgaDJbMF0udmFsdWUpLndpZHRoKCksdykpWzBdLnNlbGVjdCgpO1xyXG5cdFx0fSxcclxuXHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBjaGFuZ2VzIHRoZSB0aGVtZVxyXG5cdFx0ICogQG5hbWUgc2V0X3RoZW1lKHRoZW1lX25hbWUgWywgdGhlbWVfdXJsXSlcclxuXHRcdCAqIEBwYXJhbSB7U3RyaW5nfSB0aGVtZV9uYW1lIHRoZSBuYW1lIG9mIHRoZSBuZXcgdGhlbWUgdG8gYXBwbHlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IHRoZW1lX3VybCAgdGhlIGxvY2F0aW9uIG9mIHRoZSBDU1MgZmlsZSBmb3IgdGhpcyB0aGVtZS4gT21pdCBvciBzZXQgdG8gYGZhbHNlYCBpZiB5b3UgbWFudWFsbHkgaW5jbHVkZWQgdGhlIGZpbGUuIFNldCB0byBgdHJ1ZWAgdG8gYXV0b2xvYWQgZnJvbSB0aGUgYGNvcmUudGhlbWVzLmRpcmAgZGlyZWN0b3J5LlxyXG5cdFx0ICogQHRyaWdnZXIgc2V0X3RoZW1lLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHRzZXRfdGhlbWUgOiBmdW5jdGlvbiAodGhlbWVfbmFtZSwgdGhlbWVfdXJsKSB7XHJcblx0XHRcdGlmKCF0aGVtZV9uYW1lKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRpZih0aGVtZV91cmwgPT09IHRydWUpIHtcclxuXHRcdFx0XHR2YXIgZGlyID0gdGhpcy5zZXR0aW5ncy5jb3JlLnRoZW1lcy5kaXI7XHJcblx0XHRcdFx0aWYoIWRpcikgeyBkaXIgPSAkLmpzdHJlZS5wYXRoICsgJy90aGVtZXMnOyB9XHJcblx0XHRcdFx0dGhlbWVfdXJsID0gZGlyICsgJy8nICsgdGhlbWVfbmFtZSArICcvc3R5bGUuY3NzJztcclxuXHRcdFx0fVxyXG5cdFx0XHRpZih0aGVtZV91cmwgJiYgJC5pbkFycmF5KHRoZW1lX3VybCwgdGhlbWVzX2xvYWRlZCkgPT09IC0xKSB7XHJcblx0XHRcdFx0JCgnaGVhZCcpLmFwcGVuZCgnPCcrJ2xpbmsgcmVsPVwic3R5bGVzaGVldFwiIGhyZWY9XCInICsgdGhlbWVfdXJsICsgJ1wiIHR5cGU9XCJ0ZXh0L2Nzc1wiIC8+Jyk7XHJcblx0XHRcdFx0dGhlbWVzX2xvYWRlZC5wdXNoKHRoZW1lX3VybCk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYodGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5uYW1lKSB7XHJcblx0XHRcdFx0dGhpcy5lbGVtZW50LnJlbW92ZUNsYXNzKCdqc3RyZWUtJyArIHRoaXMuX2RhdGEuY29yZS50aGVtZXMubmFtZSk7XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5uYW1lID0gdGhlbWVfbmFtZTtcclxuXHRcdFx0dGhpcy5lbGVtZW50LmFkZENsYXNzKCdqc3RyZWUtJyArIHRoZW1lX25hbWUpO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnRbdGhpcy5zZXR0aW5ncy5jb3JlLnRoZW1lcy5yZXNwb25zaXZlID8gJ2FkZENsYXNzJyA6ICdyZW1vdmVDbGFzcycgXSgnanN0cmVlLScgKyB0aGVtZV9uYW1lICsgJy1yZXNwb25zaXZlJyk7XHJcblx0XHRcdC8qKlxyXG5cdFx0XHQgKiB0cmlnZ2VyZWQgd2hlbiBhIHRoZW1lIGlzIHNldFxyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgc2V0X3RoZW1lLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gdGhlbWUgdGhlIG5ldyB0aGVtZVxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdzZXRfdGhlbWUnLCB7ICd0aGVtZScgOiB0aGVtZV9uYW1lIH0pO1xyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0cyB0aGUgbmFtZSBvZiB0aGUgY3VycmVudGx5IGFwcGxpZWQgdGhlbWUgbmFtZVxyXG5cdFx0ICogQG5hbWUgZ2V0X3RoZW1lKClcclxuXHRcdCAqIEByZXR1cm4ge1N0cmluZ31cclxuXHRcdCAqL1xyXG5cdFx0Z2V0X3RoZW1lIDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5uYW1lOyB9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBjaGFuZ2VzIHRoZSB0aGVtZSB2YXJpYW50IChpZiB0aGUgdGhlbWUgaGFzIHZhcmlhbnRzKVxyXG5cdFx0ICogQG5hbWUgc2V0X3RoZW1lX3ZhcmlhbnQodmFyaWFudF9uYW1lKVxyXG5cdFx0ICogQHBhcmFtIHtTdHJpbmd8Qm9vbGVhbn0gdmFyaWFudF9uYW1lIHRoZSB2YXJpYW50IHRvIGFwcGx5IChpZiBgZmFsc2VgIGlzIHVzZWQgdGhlIGN1cnJlbnQgdmFyaWFudCBpcyByZW1vdmVkKVxyXG5cdFx0ICovXHJcblx0XHRzZXRfdGhlbWVfdmFyaWFudCA6IGZ1bmN0aW9uICh2YXJpYW50X25hbWUpIHtcclxuXHRcdFx0aWYodGhpcy5fZGF0YS5jb3JlLnRoZW1lcy52YXJpYW50KSB7XHJcblx0XHRcdFx0dGhpcy5lbGVtZW50LnJlbW92ZUNsYXNzKCdqc3RyZWUtJyArIHRoaXMuX2RhdGEuY29yZS50aGVtZXMubmFtZSArICctJyArIHRoaXMuX2RhdGEuY29yZS50aGVtZXMudmFyaWFudCk7XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5fZGF0YS5jb3JlLnRoZW1lcy52YXJpYW50ID0gdmFyaWFudF9uYW1lO1xyXG5cdFx0XHRpZih2YXJpYW50X25hbWUpIHtcclxuXHRcdFx0XHR0aGlzLmVsZW1lbnQuYWRkQ2xhc3MoJ2pzdHJlZS0nICsgdGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5uYW1lICsgJy0nICsgdGhpcy5fZGF0YS5jb3JlLnRoZW1lcy52YXJpYW50KTtcclxuXHRcdFx0fVxyXG5cdFx0fSxcclxuXHRcdC8qKlxyXG5cdFx0ICogZ2V0cyB0aGUgbmFtZSBvZiB0aGUgY3VycmVudGx5IGFwcGxpZWQgdGhlbWUgdmFyaWFudFxyXG5cdFx0ICogQG5hbWUgZ2V0X3RoZW1lKClcclxuXHRcdCAqIEByZXR1cm4ge1N0cmluZ31cclxuXHRcdCAqL1xyXG5cdFx0Z2V0X3RoZW1lX3ZhcmlhbnQgOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLnZhcmlhbnQ7IH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHNob3dzIGEgc3RyaXBlZCBiYWNrZ3JvdW5kIG9uIHRoZSBjb250YWluZXIgKGlmIHRoZSB0aGVtZSBzdXBwb3J0cyBpdClcclxuXHRcdCAqIEBuYW1lIHNob3dfc3RyaXBlcygpXHJcblx0XHQgKi9cclxuXHRcdHNob3dfc3RyaXBlcyA6IGZ1bmN0aW9uICgpIHsgdGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5zdHJpcGVzID0gdHJ1ZTsgdGhpcy5nZXRfY29udGFpbmVyX3VsKCkuYWRkQ2xhc3MoXCJqc3RyZWUtc3RyaXBlZFwiKTsgfSxcclxuXHRcdC8qKlxyXG5cdFx0ICogaGlkZXMgdGhlIHN0cmlwZWQgYmFja2dyb3VuZCBvbiB0aGUgY29udGFpbmVyXHJcblx0XHQgKiBAbmFtZSBoaWRlX3N0cmlwZXMoKVxyXG5cdFx0ICovXHJcblx0XHRoaWRlX3N0cmlwZXMgOiBmdW5jdGlvbiAoKSB7IHRoaXMuX2RhdGEuY29yZS50aGVtZXMuc3RyaXBlcyA9IGZhbHNlOyB0aGlzLmdldF9jb250YWluZXJfdWwoKS5yZW1vdmVDbGFzcyhcImpzdHJlZS1zdHJpcGVkXCIpOyB9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiB0b2dnbGVzIHRoZSBzdHJpcGVkIGJhY2tncm91bmQgb24gdGhlIGNvbnRhaW5lclxyXG5cdFx0ICogQG5hbWUgdG9nZ2xlX3N0cmlwZXMoKVxyXG5cdFx0ICovXHJcblx0XHR0b2dnbGVfc3RyaXBlcyA6IGZ1bmN0aW9uICgpIHsgaWYodGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5zdHJpcGVzKSB7IHRoaXMuaGlkZV9zdHJpcGVzKCk7IH0gZWxzZSB7IHRoaXMuc2hvd19zdHJpcGVzKCk7IH0gfSxcclxuXHRcdC8qKlxyXG5cdFx0ICogc2hvd3MgdGhlIGNvbm5lY3RpbmcgZG90cyAoaWYgdGhlIHRoZW1lIHN1cHBvcnRzIGl0KVxyXG5cdFx0ICogQG5hbWUgc2hvd19kb3RzKClcclxuXHRcdCAqL1xyXG5cdFx0c2hvd19kb3RzIDogZnVuY3Rpb24gKCkgeyB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLmRvdHMgPSB0cnVlOyB0aGlzLmdldF9jb250YWluZXJfdWwoKS5yZW1vdmVDbGFzcyhcImpzdHJlZS1uby1kb3RzXCIpOyB9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBoaWRlcyB0aGUgY29ubmVjdGluZyBkb3RzXHJcblx0XHQgKiBAbmFtZSBoaWRlX2RvdHMoKVxyXG5cdFx0ICovXHJcblx0XHRoaWRlX2RvdHMgOiBmdW5jdGlvbiAoKSB7IHRoaXMuX2RhdGEuY29yZS50aGVtZXMuZG90cyA9IGZhbHNlOyB0aGlzLmdldF9jb250YWluZXJfdWwoKS5hZGRDbGFzcyhcImpzdHJlZS1uby1kb3RzXCIpOyB9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiB0b2dnbGVzIHRoZSBjb25uZWN0aW5nIGRvdHNcclxuXHRcdCAqIEBuYW1lIHRvZ2dsZV9kb3RzKClcclxuXHRcdCAqL1xyXG5cdFx0dG9nZ2xlX2RvdHMgOiBmdW5jdGlvbiAoKSB7IGlmKHRoaXMuX2RhdGEuY29yZS50aGVtZXMuZG90cykgeyB0aGlzLmhpZGVfZG90cygpOyB9IGVsc2UgeyB0aGlzLnNob3dfZG90cygpOyB9IH0sXHJcblx0XHQvKipcclxuXHRcdCAqIHNob3cgdGhlIG5vZGUgaWNvbnNcclxuXHRcdCAqIEBuYW1lIHNob3dfaWNvbnMoKVxyXG5cdFx0ICovXHJcblx0XHRzaG93X2ljb25zIDogZnVuY3Rpb24gKCkgeyB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLmljb25zID0gdHJ1ZTsgdGhpcy5nZXRfY29udGFpbmVyX3VsKCkucmVtb3ZlQ2xhc3MoXCJqc3RyZWUtbm8taWNvbnNcIik7IH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGhpZGUgdGhlIG5vZGUgaWNvbnNcclxuXHRcdCAqIEBuYW1lIGhpZGVfaWNvbnMoKVxyXG5cdFx0ICovXHJcblx0XHRoaWRlX2ljb25zIDogZnVuY3Rpb24gKCkgeyB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLmljb25zID0gZmFsc2U7IHRoaXMuZ2V0X2NvbnRhaW5lcl91bCgpLmFkZENsYXNzKFwianN0cmVlLW5vLWljb25zXCIpOyB9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiB0b2dnbGUgdGhlIG5vZGUgaWNvbnNcclxuXHRcdCAqIEBuYW1lIHRvZ2dsZV9pY29ucygpXHJcblx0XHQgKi9cclxuXHRcdHRvZ2dsZV9pY29ucyA6IGZ1bmN0aW9uICgpIHsgaWYodGhpcy5fZGF0YS5jb3JlLnRoZW1lcy5pY29ucykgeyB0aGlzLmhpZGVfaWNvbnMoKTsgfSBlbHNlIHsgdGhpcy5zaG93X2ljb25zKCk7IH0gfSxcclxuXHRcdC8qKlxyXG5cdFx0ICogc2V0IHRoZSBub2RlIGljb24gZm9yIGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgc2V0X2ljb24ob2JqLCBpY29uKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqXHJcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30gaWNvbiB0aGUgbmV3IGljb24gLSBjYW4gYmUgYSBwYXRoIHRvIGFuIGljb24gb3IgYSBjbGFzc05hbWUsIGlmIHVzaW5nIGFuIGltYWdlIHRoYXQgaXMgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5IHVzZSBhIGAuL2AgcHJlZml4LCBvdGhlcndpc2UgaXQgd2lsbCBiZSBkZXRlY3RlZCBhcyBhIGNsYXNzXHJcblx0XHQgKi9cclxuXHRcdHNldF9pY29uIDogZnVuY3Rpb24gKG9iaiwgaWNvbikge1xyXG5cdFx0XHR2YXIgdDEsIHQyLCBkb20sIG9sZDtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuc2V0X2ljb24ob2JqW3QxXSwgaWNvbik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0aWYoIW9iaiB8fCBvYmouaWQgPT09ICcjJykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0b2xkID0gb2JqLmljb247XHJcblx0XHRcdG9iai5pY29uID0gaWNvbjtcclxuXHRcdFx0ZG9tID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpLmNoaWxkcmVuKFwiLmpzdHJlZS1hbmNob3JcIikuY2hpbGRyZW4oXCIuanN0cmVlLXRoZW1laWNvblwiKTtcclxuXHRcdFx0aWYoaWNvbiA9PT0gZmFsc2UpIHtcclxuXHRcdFx0XHR0aGlzLmhpZGVfaWNvbihvYmopO1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYoaWNvbiA9PT0gdHJ1ZSkge1xyXG5cdFx0XHRcdGRvbS5yZW1vdmVDbGFzcygnanN0cmVlLXRoZW1laWNvbi1jdXN0b20gJyArIG9sZCkuY3NzKFwiYmFja2dyb3VuZFwiLFwiXCIpLnJlbW92ZUF0dHIoXCJyZWxcIik7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSBpZihpY29uLmluZGV4T2YoXCIvXCIpID09PSAtMSAmJiBpY29uLmluZGV4T2YoXCIuXCIpID09PSAtMSkge1xyXG5cdFx0XHRcdGRvbS5yZW1vdmVDbGFzcyhvbGQpLmNzcyhcImJhY2tncm91bmRcIixcIlwiKTtcclxuXHRcdFx0XHRkb20uYWRkQ2xhc3MoaWNvbiArICcganN0cmVlLXRoZW1laWNvbi1jdXN0b20nKS5hdHRyKFwicmVsXCIsaWNvbik7XHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0ZG9tLnJlbW92ZUNsYXNzKG9sZCkuY3NzKFwiYmFja2dyb3VuZFwiLFwiXCIpO1xyXG5cdFx0XHRcdGRvbS5hZGRDbGFzcygnanN0cmVlLXRoZW1laWNvbi1jdXN0b20nKS5jc3MoXCJiYWNrZ3JvdW5kXCIsIFwidXJsKCdcIiArIGljb24gKyBcIicpIGNlbnRlciBjZW50ZXIgbm8tcmVwZWF0XCIpLmF0dHIoXCJyZWxcIixpY29uKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGdldCB0aGUgbm9kZSBpY29uIGZvciBhIG5vZGVcclxuXHRcdCAqIEBuYW1lIGdldF9pY29uKG9iailcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9ialxyXG5cdFx0ICogQHJldHVybiB7U3RyaW5nfVxyXG5cdFx0ICovXHJcblx0XHRnZXRfaWNvbiA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRyZXR1cm4gKCFvYmogfHwgb2JqLmlkID09PSAnIycpID8gZmFsc2UgOiBvYmouaWNvbjtcclxuXHRcdH0sXHJcblx0XHQvKipcclxuXHRcdCAqIGhpZGUgdGhlIGljb24gb24gYW4gaW5kaXZpZHVhbCBub2RlXHJcblx0XHQgKiBAbmFtZSBoaWRlX2ljb24ob2JqKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqXHJcblx0XHQgKi9cclxuXHRcdGhpZGVfaWNvbiA6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdFx0dmFyIHQxLCB0MjtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuaGlkZV9pY29uKG9ialt0MV0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqID09PSAnIycpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdG9iai5pY29uID0gZmFsc2U7XHJcblx0XHRcdHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKS5jaGlsZHJlbihcImFcIikuY2hpbGRyZW4oXCIuanN0cmVlLXRoZW1laWNvblwiKS5hZGRDbGFzcygnanN0cmVlLXRoZW1laWNvbi1oaWRkZW4nKTtcclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9LFxyXG5cdFx0LyoqXHJcblx0XHQgKiBzaG93IHRoZSBpY29uIG9uIGFuIGluZGl2aWR1YWwgbm9kZVxyXG5cdFx0ICogQG5hbWUgc2hvd19pY29uKG9iailcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9ialxyXG5cdFx0ICovXHJcblx0XHRzaG93X2ljb24gOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdHZhciB0MSwgdDIsIGRvbTtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuc2hvd19pY29uKG9ialt0MV0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqID09PSAnIycpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdGRvbSA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKTtcclxuXHRcdFx0b2JqLmljb24gPSBkb20ubGVuZ3RoID8gZG9tLmNoaWxkcmVuKFwiYVwiKS5jaGlsZHJlbihcIi5qc3RyZWUtdGhlbWVpY29uXCIpLmF0dHIoJ3JlbCcpIDogdHJ1ZTtcclxuXHRcdFx0aWYoIW9iai5pY29uKSB7IG9iai5pY29uID0gdHJ1ZTsgfVxyXG5cdFx0XHRkb20uY2hpbGRyZW4oXCJhXCIpLmNoaWxkcmVuKFwiLmpzdHJlZS10aGVtZWljb25cIikucmVtb3ZlQ2xhc3MoJ2pzdHJlZS10aGVtZWljb24taGlkZGVuJyk7XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdC8vIGhlbHBlcnNcclxuXHQkLnZha2F0YSA9IHt9O1xyXG5cdC8vIHJldmVyc2VcclxuXHQkLmZuLnZha2F0YV9yZXZlcnNlID0gW10ucmV2ZXJzZTtcclxuXHQvLyBjb2xsZWN0IGF0dHJpYnV0ZXNcclxuXHQkLnZha2F0YS5hdHRyaWJ1dGVzID0gZnVuY3Rpb24obm9kZSwgd2l0aF92YWx1ZXMpIHtcclxuXHRcdG5vZGUgPSAkKG5vZGUpWzBdO1xyXG5cdFx0dmFyIGF0dHIgPSB3aXRoX3ZhbHVlcyA/IHt9IDogW107XHJcblx0XHRpZihub2RlICYmIG5vZGUuYXR0cmlidXRlcykge1xyXG5cdFx0XHQkLmVhY2gobm9kZS5hdHRyaWJ1dGVzLCBmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdGlmKCQuaW5BcnJheSh2Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksWydzdHlsZScsJ2NvbnRlbnRlZGl0YWJsZScsJ2hhc2ZvY3VzJywndGFiaW5kZXgnXSkgIT09IC0xKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdGlmKHYubm9kZVZhbHVlICE9PSBudWxsICYmICQudHJpbSh2Lm5vZGVWYWx1ZSkgIT09ICcnKSB7XHJcblx0XHRcdFx0XHRpZih3aXRoX3ZhbHVlcykgeyBhdHRyW3Yubm9kZU5hbWVdID0gdi5ub2RlVmFsdWU7IH1cclxuXHRcdFx0XHRcdGVsc2UgeyBhdHRyLnB1c2godi5ub2RlTmFtZSk7IH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGF0dHI7XHJcblx0fTtcclxuXHQkLnZha2F0YS5hcnJheV91bmlxdWUgPSBmdW5jdGlvbihhcnJheSkge1xyXG5cdFx0dmFyIGEgPSBbXSwgaSwgaiwgbDtcclxuXHRcdGZvcihpID0gMCwgbCA9IGFycmF5Lmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG5cdFx0XHRmb3IoaiA9IDA7IGogPD0gaTsgaisrKSB7XHJcblx0XHRcdFx0aWYoYXJyYXlbaV0gPT09IGFycmF5W2pdKSB7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoaiA9PT0gaSkgeyBhLnB1c2goYXJyYXlbaV0pOyB9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9O1xyXG5cdC8vIHJlbW92ZSBpdGVtIGZyb20gYXJyYXlcclxuXHQkLnZha2F0YS5hcnJheV9yZW1vdmUgPSBmdW5jdGlvbihhcnJheSwgZnJvbSwgdG8pIHtcclxuXHRcdHZhciByZXN0ID0gYXJyYXkuc2xpY2UoKHRvIHx8IGZyb20pICsgMSB8fCBhcnJheS5sZW5ndGgpO1xyXG5cdFx0YXJyYXkubGVuZ3RoID0gZnJvbSA8IDAgPyBhcnJheS5sZW5ndGggKyBmcm9tIDogZnJvbTtcclxuXHRcdGFycmF5LnB1c2guYXBwbHkoYXJyYXksIHJlc3QpO1xyXG5cdFx0cmV0dXJuIGFycmF5O1xyXG5cdH07XHJcblx0Ly8gcmVtb3ZlIGl0ZW0gZnJvbSBhcnJheVxyXG5cdCQudmFrYXRhLmFycmF5X3JlbW92ZV9pdGVtID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0pIHtcclxuXHRcdHZhciB0bXAgPSAkLmluQXJyYXkoaXRlbSwgYXJyYXkpO1xyXG5cdFx0cmV0dXJuIHRtcCAhPT0gLTEgPyAkLnZha2F0YS5hcnJheV9yZW1vdmUoYXJyYXksIHRtcCkgOiBhcnJheTtcclxuXHR9O1xyXG5cdC8vIGJyb3dzZXIgc25pZmZpbmdcclxuXHQoZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGJyb3dzZXIgPSB7fSxcclxuXHRcdFx0Yl9tYXRjaCA9IGZ1bmN0aW9uKHVhKSB7XHJcblx0XHRcdHVhID0gdWEudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0XHRcdHZhciBtYXRjaCA9XHQvKGNocm9tZSlbIFxcL10oW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcclxuXHRcdFx0XHRcdFx0Lyh3ZWJraXQpWyBcXC9dKFtcXHcuXSspLy5leGVjKCB1YSApIHx8XHJcblx0XHRcdFx0XHRcdC8ob3BlcmEpKD86Lip2ZXJzaW9ufClbIFxcL10oW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcclxuXHRcdFx0XHRcdFx0Lyhtc2llKSAoW1xcdy5dKykvLmV4ZWMoIHVhICkgfHxcclxuXHRcdFx0XHRcdFx0KHVhLmluZGV4T2YoXCJjb21wYXRpYmxlXCIpIDwgMCAmJiAvKG1vemlsbGEpKD86Lio/IHJ2OihbXFx3Ll0rKXwpLy5leGVjKCB1YSApKSB8fFxyXG5cdFx0XHRcdFx0XHRbXTtcclxuXHRcdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdFx0YnJvd3NlcjogbWF0Y2hbMV0gfHwgXCJcIixcclxuXHRcdFx0XHRcdHZlcnNpb246IG1hdGNoWzJdIHx8IFwiMFwiXHJcblx0XHRcdFx0fTtcclxuXHRcdFx0fSxcclxuXHRcdFx0bWF0Y2hlZCA9IGJfbWF0Y2god2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQpO1xyXG5cdFx0aWYobWF0Y2hlZC5icm93c2VyKSB7XHJcblx0XHRcdGJyb3dzZXJbIG1hdGNoZWQuYnJvd3NlciBdID0gdHJ1ZTtcclxuXHRcdFx0YnJvd3Nlci52ZXJzaW9uID0gbWF0Y2hlZC52ZXJzaW9uO1xyXG5cdFx0fVxyXG5cdFx0aWYoYnJvd3Nlci5jaHJvbWUpIHtcclxuXHRcdFx0YnJvd3Nlci53ZWJraXQgPSB0cnVlO1xyXG5cdFx0fVxyXG5cdFx0ZWxzZSBpZihicm93c2VyLndlYmtpdCkge1xyXG5cdFx0XHRicm93c2VyLnNhZmFyaSA9IHRydWU7XHJcblx0XHR9XHJcblx0XHQkLnZha2F0YS5icm93c2VyID0gYnJvd3NlcjtcclxuXHR9KCkpO1xyXG5cdGlmKCQudmFrYXRhLmJyb3dzZXIubXNpZSAmJiAkLnZha2F0YS5icm93c2VyLnZlcnNpb24gPCA4KSB7XHJcblx0XHQkLmpzdHJlZS5kZWZhdWx0cy5jb3JlLmFuaW1hdGlvbiA9IDA7XHJcblx0fVxyXG5cclxuLyoqXHJcbiAqICMjIyBDaGVja2JveCBwbHVnaW5cclxuICpcclxuICogVGhpcyBwbHVnaW4gcmVuZGVycyBjaGVja2JveCBpY29ucyBpbiBmcm9udCBvZiBlYWNoIG5vZGUsIG1ha2luZyBtdWx0aXBsZSBzZWxlY3Rpb24gbXVjaCBlYXNpZXIuIFxyXG4gKiBJdCBhbHNvIHN1cHBvcnRzIHRyaS1zdGF0ZSBiZWhhdmlvciwgbWVhbmluZyB0aGF0IGlmIGEgbm9kZSBoYXMgYSBmZXcgb2YgaXRzIGNoaWxkcmVuIGNoZWNrZWQgaXQgd2lsbCBiZSByZW5kZXJlZCBhcyB1bmRldGVybWluZWQsIGFuZCBzdGF0ZSB3aWxsIGJlIHByb3BhZ2F0ZWQgdXAuXHJcbiAqL1xyXG5cclxuXHR2YXIgX2kgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdJJyk7XHJcblx0X2kuY2xhc3NOYW1lID0gJ2pzdHJlZS1pY29uIGpzdHJlZS1jaGVja2JveCc7XHJcblx0LyoqXHJcblx0ICogc3RvcmVzIGFsbCBkZWZhdWx0cyBmb3IgdGhlIGNoZWNrYm94IHBsdWdpblxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNoZWNrYm94XHJcblx0ICogQHBsdWdpbiBjaGVja2JveFxyXG5cdCAqL1xyXG5cdCQuanN0cmVlLmRlZmF1bHRzLmNoZWNrYm94ID0ge1xyXG5cdFx0LyoqXHJcblx0XHQgKiBhIGJvb2xlYW4gaW5kaWNhdGluZyBpZiBjaGVja2JveGVzIHNob3VsZCBiZSB2aXNpYmxlIChjYW4gYmUgY2hhbmdlZCBhdCBhIGxhdGVyIHRpbWUgdXNpbmcgYHNob3dfY2hlY2tib3hlcygpYCBhbmQgYGhpZGVfY2hlY2tib3hlc2ApLiBEZWZhdWx0cyB0byBgdHJ1ZWAuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jaGVja2JveC52aXNpYmxlXHJcblx0XHQgKiBAcGx1Z2luIGNoZWNrYm94XHJcblx0XHQgKi9cclxuXHRcdHZpc2libGVcdFx0XHRcdDogdHJ1ZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogYSBib29sZWFuIGluZGljYXRpbmcgaWYgY2hlY2tib3hlcyBzaG91bGQgY2FzY2FkZSBkb3duIGFuZCBoYXZlIGFuIHVuZGV0ZXJtaW5lZCBzdGF0ZS4gRGVmYXVsdHMgdG8gYHRydWVgLlxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuY2hlY2tib3gudGhyZWVfc3RhdGVcclxuXHRcdCAqIEBwbHVnaW4gY2hlY2tib3hcclxuXHRcdCAqL1xyXG5cdFx0dGhyZWVfc3RhdGVcdFx0XHQ6IHRydWUsXHJcblx0XHQvKipcclxuXHRcdCAqIGEgYm9vbGVhbiBpbmRpY2F0aW5nIGlmIGNsaWNraW5nIGFueXdoZXJlIG9uIHRoZSBub2RlIHNob3VsZCBhY3QgYXMgY2xpY2tpbmcgb24gdGhlIGNoZWNrYm94LiBEZWZhdWx0cyB0byBgdHJ1ZWAuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jaGVja2JveC53aG9sZV9ub2RlXHJcblx0XHQgKiBAcGx1Z2luIGNoZWNrYm94XHJcblx0XHQgKi9cclxuXHRcdHdob2xlX25vZGVcdFx0XHQ6IHRydWUsXHJcblx0XHQvKipcclxuXHRcdCAqIGEgYm9vbGVhbiBpbmRpY2F0aW5nIGlmIHRoZSBzZWxlY3RlZCBzdHlsZSBvZiBhIG5vZGUgc2hvdWxkIGJlIGtlcHQsIG9yIHJlbW92ZWQuIERlZmF1bHRzIHRvIGB0cnVlYC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNoZWNrYm94LmtlZXBfc2VsZWN0ZWRfc3R5bGVcclxuXHRcdCAqIEBwbHVnaW4gY2hlY2tib3hcclxuXHRcdCAqL1xyXG5cdFx0a2VlcF9zZWxlY3RlZF9zdHlsZVx0OiB0cnVlXHJcblx0fTtcclxuXHQkLmpzdHJlZS5wbHVnaW5zLmNoZWNrYm94ID0gZnVuY3Rpb24gKG9wdGlvbnMsIHBhcmVudCkge1xyXG5cdFx0dGhpcy5iaW5kID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRwYXJlbnQuYmluZC5jYWxsKHRoaXMpO1xyXG5cdFx0XHR0aGlzLl9kYXRhLmNoZWNrYm94LnV0byA9IGZhbHNlO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHQub24oXCJpbml0LmpzdHJlZVwiLCAkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jaGVja2JveC52aXNpYmxlID0gdGhpcy5zZXR0aW5ncy5jaGVja2JveC52aXNpYmxlO1xyXG5cdFx0XHRcdFx0XHRpZighdGhpcy5zZXR0aW5ncy5jaGVja2JveC5rZWVwX3NlbGVjdGVkX3N0eWxlKSB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5lbGVtZW50LmFkZENsYXNzKCdqc3RyZWUtY2hlY2tib3gtbm8tY2xpY2tlZCcpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oXCJsb2FkaW5nLmpzdHJlZVwiLCAkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0dGhpc1sgdGhpcy5fZGF0YS5jaGVja2JveC52aXNpYmxlID8gJ3Nob3dfY2hlY2tib3hlcycgOiAnaGlkZV9jaGVja2JveGVzJyBdKCk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSk7XHJcblx0XHRcdGlmKHRoaXMuc2V0dGluZ3MuY2hlY2tib3gudGhyZWVfc3RhdGUpIHtcclxuXHRcdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHRcdC5vbignY2hhbmdlZC5qc3RyZWUgbW92ZV9ub2RlLmpzdHJlZSBjb3B5X25vZGUuanN0cmVlIHJlZHJhdy5qc3RyZWUgb3Blbl9ub2RlLmpzdHJlZScsICQucHJveHkoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRcdGlmKHRoaXMuX2RhdGEuY2hlY2tib3gudXRvKSB7IGNsZWFyVGltZW91dCh0aGlzLl9kYXRhLmNoZWNrYm94LnV0byk7IH1cclxuXHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNoZWNrYm94LnV0byA9IHNldFRpbWVvdXQoJC5wcm94eSh0aGlzLl91bmRldGVybWluZWQsIHRoaXMpLCA1MCk7XHJcblx0XHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdFx0Lm9uKCdtb2RlbC5qc3RyZWUnLCAkLnByb3h5KGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdFx0dmFyIG0gPSB0aGlzLl9tb2RlbC5kYXRhLFxyXG5cdFx0XHRcdFx0XHRcdFx0cCA9IG1bZGF0YS5wYXJlbnRdLFxyXG5cdFx0XHRcdFx0XHRcdFx0ZHBjID0gZGF0YS5ub2RlcyxcclxuXHRcdFx0XHRcdFx0XHRcdGNoZCA9IFtdLFxyXG5cdFx0XHRcdFx0XHRcdFx0YywgaSwgaiwgaywgbCwgdG1wO1xyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBhcHBseSBkb3duXHJcblx0XHRcdFx0XHRcdFx0aWYocC5zdGF0ZS5zZWxlY3RlZCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gZHBjLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRtW2RwY1tpXV0uc3RhdGUuc2VsZWN0ZWQgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gdGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmNvbmNhdChkcGMpO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IGRwYy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYobVtkcGNbaV1dLnN0YXRlLnNlbGVjdGVkKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm9yKGsgPSAwLCBsID0gbVtkcGNbaV1dLmNoaWxkcmVuX2QubGVuZ3RoOyBrIDwgbDsgaysrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtW21bZHBjW2ldXS5jaGlsZHJlbl9kW2tdXS5zdGF0ZS5zZWxlY3RlZCA9IHRydWU7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCA9IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZC5jb25jYXQobVtkcGNbaV1dLmNoaWxkcmVuX2QpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBhcHBseSB1cFxyXG5cdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IHAuY2hpbGRyZW5fZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHRcdGlmKCFtW3AuY2hpbGRyZW5fZFtpXV0uY2hpbGRyZW4ubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGNoZC5wdXNoKG1bcC5jaGlsZHJlbl9kW2ldXS5wYXJlbnQpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRjaGQgPSAkLnZha2F0YS5hcnJheV91bmlxdWUoY2hkKTtcclxuXHRcdFx0XHRcdFx0XHRmb3IoayA9IDAsIGwgPSBjaGQubGVuZ3RoOyBrIDwgbDsgaysrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRwID0gbVtjaGRba11dO1xyXG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUocCAmJiBwLmlkICE9PSAnIycpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0YyA9IDA7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IHAuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0YyArPSBtW3AuY2hpbGRyZW5baV1dLnN0YXRlLnNlbGVjdGVkO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKGMgPT09IGopIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRwLnN0YXRlLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQucHVzaChwLmlkKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAgPSB0aGlzLmdldF9ub2RlKHAsIHRydWUpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKHRtcCAmJiB0bXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAuY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJykuYWRkQ2xhc3MoJ2pzdHJlZS1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdHAgPSB0aGlzLmdldF9ub2RlKHAucGFyZW50KTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gJC52YWthdGEuYXJyYXlfdW5pcXVlKHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCk7XHJcblx0XHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdFx0Lm9uKCdzZWxlY3Rfbm9kZS5qc3RyZWUnLCAkLnByb3h5KGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdFx0dmFyIG9iaiA9IGRhdGEubm9kZSxcclxuXHRcdFx0XHRcdFx0XHRcdG0gPSB0aGlzLl9tb2RlbC5kYXRhLFxyXG5cdFx0XHRcdFx0XHRcdFx0cGFyID0gdGhpcy5nZXRfbm9kZShvYmoucGFyZW50KSxcclxuXHRcdFx0XHRcdFx0XHRcdGRvbSA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKSxcclxuXHRcdFx0XHRcdFx0XHRcdGksIGosIGMsIHRtcDtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQgPSAkLnZha2F0YS5hcnJheV91bmlxdWUodGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLmNvbmNhdChvYmouY2hpbGRyZW5fZCkpO1xyXG5cdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IG9iai5jaGlsZHJlbl9kLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0bVtvYmouY2hpbGRyZW5fZFtpXV0uc3RhdGUuc2VsZWN0ZWQgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR3aGlsZShwYXIgJiYgcGFyLmlkICE9PSAnIycpIHtcclxuXHRcdFx0XHRcdFx0XHRcdGMgPSAwO1xyXG5cdFx0XHRcdFx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gcGFyLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjICs9IG1bcGFyLmNoaWxkcmVuW2ldXS5zdGF0ZS5zZWxlY3RlZDtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGlmKGMgPT09IGopIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0cGFyLnN0YXRlLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLnB1c2gocGFyLmlkKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dG1wID0gdGhpcy5nZXRfbm9kZShwYXIsIHRydWUpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZih0bXAgJiYgdG1wLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRtcC5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5hZGRDbGFzcygnanN0cmVlLWNsaWNrZWQnKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0cGFyID0gdGhpcy5nZXRfbm9kZShwYXIucGFyZW50KTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0aWYoZG9tLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZG9tLmZpbmQoJy5qc3RyZWUtYW5jaG9yJykuYWRkQ2xhc3MoJ2pzdHJlZS1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHRcdC5vbignZGVzZWxlY3Rfbm9kZS5qc3RyZWUnLCAkLnByb3h5KGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdFx0dmFyIG9iaiA9IGRhdGEubm9kZSxcclxuXHRcdFx0XHRcdFx0XHRcdGRvbSA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKSxcclxuXHRcdFx0XHRcdFx0XHRcdGksIGosIHRtcDtcclxuXHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW5fZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX21vZGVsLmRhdGFbb2JqLmNoaWxkcmVuX2RbaV1dLnN0YXRlLnNlbGVjdGVkID0gZmFsc2U7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IG9iai5wYXJlbnRzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5fbW9kZWwuZGF0YVtvYmoucGFyZW50c1tpXV0uc3RhdGUuc2VsZWN0ZWQgPSBmYWxzZTtcclxuXHRcdFx0XHRcdFx0XHRcdHRtcCA9IHRoaXMuZ2V0X25vZGUob2JqLnBhcmVudHNbaV0sIHRydWUpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYodG1wICYmIHRtcC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dG1wLmNoaWxkcmVuKCcuanN0cmVlLWFuY2hvcicpLnJlbW92ZUNsYXNzKCdqc3RyZWUtY2xpY2tlZCcpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR0bXAgPSBbXTtcclxuXHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRpZigkLmluQXJyYXkodGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkW2ldLCBvYmouY2hpbGRyZW5fZCkgPT09IC0xICYmICQuaW5BcnJheSh0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWRbaV0sIG9iai5wYXJlbnRzKSA9PT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dG1wLnB1c2godGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkW2ldKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkID0gJC52YWthdGEuYXJyYXlfdW5pcXVlKHRtcCk7XHJcblx0XHRcdFx0XHRcdFx0aWYoZG9tLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZG9tLmZpbmQoJy5qc3RyZWUtYW5jaG9yJykucmVtb3ZlQ2xhc3MoJ2pzdHJlZS1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHRcdC5vbignZGVsZXRlX25vZGUuanN0cmVlJywgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHRcdHZhciBwID0gdGhpcy5nZXRfbm9kZShkYXRhLnBhcmVudCksXHJcblx0XHRcdFx0XHRcdFx0XHRtID0gdGhpcy5fbW9kZWwuZGF0YSxcclxuXHRcdFx0XHRcdFx0XHRcdGksIGosIGMsIHRtcDtcclxuXHRcdFx0XHRcdFx0XHR3aGlsZShwICYmIHAuaWQgIT09ICcjJykge1xyXG5cdFx0XHRcdFx0XHRcdFx0YyA9IDA7XHJcblx0XHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBwLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjICs9IG1bcC5jaGlsZHJlbltpXV0uc3RhdGUuc2VsZWN0ZWQ7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRpZihjID09PSBqKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHAuc3RhdGUuc2VsZWN0ZWQgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQucHVzaChwLmlkKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dG1wID0gdGhpcy5nZXRfbm9kZShwLCB0cnVlKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYodG1wICYmIHRtcC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAuY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJykuYWRkQ2xhc3MoJ2pzdHJlZS1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdHAgPSB0aGlzLmdldF9ub2RlKHAucGFyZW50KTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdFx0Lm9uKCdtb3ZlX25vZGUuanN0cmVlJywgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHRcdHZhciBpc19tdWx0aSA9IGRhdGEuaXNfbXVsdGksXHJcblx0XHRcdFx0XHRcdFx0XHRvbGRfcGFyID0gZGF0YS5vbGRfcGFyZW50LFxyXG5cdFx0XHRcdFx0XHRcdFx0bmV3X3BhciA9IHRoaXMuZ2V0X25vZGUoZGF0YS5wYXJlbnQpLFxyXG5cdFx0XHRcdFx0XHRcdFx0bSA9IHRoaXMuX21vZGVsLmRhdGEsXHJcblx0XHRcdFx0XHRcdFx0XHRwLCBjLCBpLCBqLCB0bXA7XHJcblx0XHRcdFx0XHRcdFx0aWYoIWlzX211bHRpKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRwID0gdGhpcy5nZXRfbm9kZShvbGRfcGFyKTtcclxuXHRcdFx0XHRcdFx0XHRcdHdoaWxlKHAgJiYgcC5pZCAhPT0gJyMnKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGMgPSAwO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBwLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGMgKz0gbVtwLmNoaWxkcmVuW2ldXS5zdGF0ZS5zZWxlY3RlZDtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZihjID09PSBqKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0cC5zdGF0ZS5zZWxlY3RlZCA9IHRydWU7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLnNlbGVjdGVkLnB1c2gocC5pZCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0dG1wID0gdGhpcy5nZXRfbm9kZShwLCB0cnVlKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZih0bXAgJiYgdG1wLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dG1wLmNoaWxkcmVuKCcuanN0cmVlLWFuY2hvcicpLmFkZENsYXNzKCdqc3RyZWUtY2xpY2tlZCcpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRwID0gdGhpcy5nZXRfbm9kZShwLnBhcmVudCk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdHAgPSBuZXdfcGFyO1xyXG5cdFx0XHRcdFx0XHRcdHdoaWxlKHAgJiYgcC5pZCAhPT0gJyMnKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRjID0gMDtcclxuXHRcdFx0XHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IHAuY2hpbGRyZW4ubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGMgKz0gbVtwLmNoaWxkcmVuW2ldXS5zdGF0ZS5zZWxlY3RlZDtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGlmKGMgPT09IGopIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIXAuc3RhdGUuc2VsZWN0ZWQpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRwLnN0YXRlLnNlbGVjdGVkID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQucHVzaChwLmlkKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAgPSB0aGlzLmdldF9ub2RlKHAsIHRydWUpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKHRtcCAmJiB0bXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0bXAuY2hpbGRyZW4oJy5qc3RyZWUtYW5jaG9yJykuYWRkQ2xhc3MoJ2pzdHJlZS1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYocC5zdGF0ZS5zZWxlY3RlZCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHAuc3RhdGUuc2VsZWN0ZWQgPSBmYWxzZTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQgPSAkLnZha2F0YS5hcnJheV9yZW1vdmVfaXRlbSh0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQsIHAuaWQpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRtcCA9IHRoaXMuZ2V0X25vZGUocCwgdHJ1ZSk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYodG1wICYmIHRtcC5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHRtcC5jaGlsZHJlbignLmpzdHJlZS1hbmNob3InKS5yZW1vdmVDbGFzcygnanN0cmVlLWNsaWNrZWQnKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdHAgPSB0aGlzLmdldF9ub2RlKHAucGFyZW50KTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdFx0fVxyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogc2V0IHRoZSB1bmRldGVybWluZWQgc3RhdGUgd2hlcmUgYW5kIGlmIG5lY2Vzc2FyeS4gVXNlZCBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIF91bmRldGVybWluZWQoKVxyXG5cdFx0ICogQHBsdWdpbiBjaGVja2JveFxyXG5cdFx0ICovXHJcblx0XHR0aGlzLl91bmRldGVybWluZWQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHZhciBpLCBqLCBtID0gdGhpcy5fbW9kZWwuZGF0YSwgcyA9IHRoaXMuX2RhdGEuY29yZS5zZWxlY3RlZCwgcCA9IFtdLCB0ID0gdGhpcztcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gcy5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRpZihtW3NbaV1dICYmIG1bc1tpXV0ucGFyZW50cykge1xyXG5cdFx0XHRcdFx0cCA9IHAuY29uY2F0KG1bc1tpXV0ucGFyZW50cyk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdC8vIGF0dGVtcHQgZm9yIHNlcnZlciBzaWRlIHVuZGV0ZXJtaW5lZCBzdGF0ZVxyXG5cdFx0XHR0aGlzLmVsZW1lbnQuZmluZCgnLmpzdHJlZS1jbG9zZWQnKS5ub3QoJzpoYXModWwpJylcclxuXHRcdFx0XHQuZWFjaChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHR2YXIgdG1wID0gdC5nZXRfbm9kZSh0aGlzKTtcclxuXHRcdFx0XHRcdGlmKCF0bXAuc3RhdGUubG9hZGVkICYmIHRtcC5vcmlnaW5hbCAmJiB0bXAub3JpZ2luYWwuc3RhdGUgJiYgdG1wLm9yaWdpbmFsLnN0YXRlLnVuZGV0ZXJtaW5lZCAmJiB0bXAub3JpZ2luYWwuc3RhdGUudW5kZXRlcm1pbmVkID09PSB0cnVlKSB7XHJcblx0XHRcdFx0XHRcdHAucHVzaCh0bXAuaWQpO1xyXG5cdFx0XHRcdFx0XHRwID0gcC5jb25jYXQodG1wLnBhcmVudHMpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHRwID0gJC52YWthdGEuYXJyYXlfdW5pcXVlKHApO1xyXG5cdFx0XHRpID0gJC5pbkFycmF5KCcjJywgcCk7XHJcblx0XHRcdGlmKGkgIT09IC0xKSB7XHJcblx0XHRcdFx0cCA9ICQudmFrYXRhLmFycmF5X3JlbW92ZShwLCBpKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0dGhpcy5lbGVtZW50LmZpbmQoJy5qc3RyZWUtdW5kZXRlcm1pbmVkJykucmVtb3ZlQ2xhc3MoJ2pzdHJlZS11bmRldGVybWluZWQnKTtcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gcC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRpZighbVtwW2ldXS5zdGF0ZS5zZWxlY3RlZCkge1xyXG5cdFx0XHRcdFx0cyA9IHRoaXMuZ2V0X25vZGUocFtpXSwgdHJ1ZSk7XHJcblx0XHRcdFx0XHRpZihzICYmIHMubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdHMuY2hpbGRyZW4oJ2EnKS5jaGlsZHJlbignLmpzdHJlZS1jaGVja2JveCcpLmFkZENsYXNzKCdqc3RyZWUtdW5kZXRlcm1pbmVkJyk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdFx0dGhpcy5yZWRyYXdfbm9kZSA9IGZ1bmN0aW9uKG9iaiwgZGVlcCwgaXNfY2FsbGJhY2spIHtcclxuXHRcdFx0b2JqID0gcGFyZW50LnJlZHJhd19ub2RlLmNhbGwodGhpcywgb2JqLCBkZWVwLCBpc19jYWxsYmFjayk7XHJcblx0XHRcdGlmKG9iaikge1xyXG5cdFx0XHRcdHZhciB0bXAgPSBvYmouZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ0EnKVswXTtcclxuXHRcdFx0XHR0bXAuaW5zZXJ0QmVmb3JlKF9pLmNsb25lTm9kZSgpLCB0bXAuY2hpbGROb2Rlc1swXSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIWlzX2NhbGxiYWNrICYmIHRoaXMuc2V0dGluZ3MuY2hlY2tib3gudGhyZWVfc3RhdGUpIHtcclxuXHRcdFx0XHRpZih0aGlzLl9kYXRhLmNoZWNrYm94LnV0bykgeyBjbGVhclRpbWVvdXQodGhpcy5fZGF0YS5jaGVja2JveC51dG8pOyB9XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5jaGVja2JveC51dG8gPSBzZXRUaW1lb3V0KCQucHJveHkodGhpcy5fdW5kZXRlcm1pbmVkLCB0aGlzKSwgNTApO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBvYmo7XHJcblx0XHR9O1xyXG5cdFx0dGhpcy5hY3RpdmF0ZV9ub2RlID0gZnVuY3Rpb24gKG9iaiwgZSkge1xyXG5cdFx0XHRpZih0aGlzLnNldHRpbmdzLmNoZWNrYm94Lndob2xlX25vZGUgfHwgJChlLnRhcmdldCkuaGFzQ2xhc3MoJ2pzdHJlZS1jaGVja2JveCcpKSB7XHJcblx0XHRcdFx0ZS5jdHJsS2V5ID0gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gcGFyZW50LmFjdGl2YXRlX25vZGUuY2FsbCh0aGlzLCBvYmosIGUpO1xyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogc2hvdyB0aGUgbm9kZSBjaGVja2JveCBpY29uc1xyXG5cdFx0ICogQG5hbWUgc2hvd19jaGVja2JveGVzKClcclxuXHRcdCAqIEBwbHVnaW4gY2hlY2tib3hcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5zaG93X2NoZWNrYm94ZXMgPSBmdW5jdGlvbiAoKSB7IHRoaXMuX2RhdGEuY29yZS50aGVtZXMuY2hlY2tib3hlcyA9IHRydWU7IHRoaXMuZWxlbWVudC5jaGlsZHJlbihcInVsXCIpLnJlbW92ZUNsYXNzKFwianN0cmVlLW5vLWNoZWNrYm94ZXNcIik7IH07XHJcblx0XHQvKipcclxuXHRcdCAqIGhpZGUgdGhlIG5vZGUgY2hlY2tib3ggaWNvbnNcclxuXHRcdCAqIEBuYW1lIGhpZGVfY2hlY2tib3hlcygpXHJcblx0XHQgKiBAcGx1Z2luIGNoZWNrYm94XHJcblx0XHQgKi9cclxuXHRcdHRoaXMuaGlkZV9jaGVja2JveGVzID0gZnVuY3Rpb24gKCkgeyB0aGlzLl9kYXRhLmNvcmUudGhlbWVzLmNoZWNrYm94ZXMgPSBmYWxzZTsgdGhpcy5lbGVtZW50LmNoaWxkcmVuKFwidWxcIikuYWRkQ2xhc3MoXCJqc3RyZWUtbm8tY2hlY2tib3hlc1wiKTsgfTtcclxuXHRcdC8qKlxyXG5cdFx0ICogdG9nZ2xlIHRoZSBub2RlIGljb25zXHJcblx0XHQgKiBAbmFtZSB0b2dnbGVfY2hlY2tib3hlcygpXHJcblx0XHQgKiBAcGx1Z2luIGNoZWNrYm94XHJcblx0XHQgKi9cclxuXHRcdHRoaXMudG9nZ2xlX2NoZWNrYm94ZXMgPSBmdW5jdGlvbiAoKSB7IGlmKHRoaXMuX2RhdGEuY29yZS50aGVtZXMuY2hlY2tib3hlcykgeyB0aGlzLmhpZGVfY2hlY2tib3hlcygpOyB9IGVsc2UgeyB0aGlzLnNob3dfY2hlY2tib3hlcygpOyB9IH07XHJcblx0fTtcclxuXHJcblx0Ly8gaW5jbHVkZSB0aGUgY2hlY2tib3ggcGx1Z2luIGJ5IGRlZmF1bHRcclxuXHQvLyAkLmpzdHJlZS5kZWZhdWx0cy5wbHVnaW5zLnB1c2goXCJjaGVja2JveFwiKTtcclxuXHJcbi8qKlxyXG4gKiAjIyMgQ29udGV4dG1lbnUgcGx1Z2luXHJcbiAqXHJcbiAqIFNob3dzIGEgY29udGV4dCBtZW51IHdoZW4gYSBub2RlIGlzIHJpZ2h0LWNsaWNrZWQuXHJcbiAqL1xyXG4vLyBUT0RPOiBtb3ZlIGxvZ2ljIG91dHNpZGUgb2YgZnVuY3Rpb24gKyBjaGVjayBtdWx0aXBsZSBtb3ZlXHJcblxyXG5cdC8qKlxyXG5cdCAqIHN0b3JlcyBhbGwgZGVmYXVsdHMgZm9yIHRoZSBjb250ZXh0bWVudSBwbHVnaW5cclxuXHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb250ZXh0bWVudVxyXG5cdCAqIEBwbHVnaW4gY29udGV4dG1lbnVcclxuXHQgKi9cclxuXHQkLmpzdHJlZS5kZWZhdWx0cy5jb250ZXh0bWVudSA9IHtcclxuXHRcdC8qKlxyXG5cdFx0ICogYSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlIG5vZGUgc2hvdWxkIGJlIHNlbGVjdGVkIHdoZW4gdGhlIGNvbnRleHQgbWVudSBpcyBpbnZva2VkIG9uIGl0LiBEZWZhdWx0cyB0byBgdHJ1ZWAuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb250ZXh0bWVudS5zZWxlY3Rfbm9kZVxyXG5cdFx0ICogQHBsdWdpbiBjb250ZXh0bWVudVxyXG5cdFx0ICovXHJcblx0XHRzZWxlY3Rfbm9kZSA6IHRydWUsXHJcblx0XHQvKipcclxuXHRcdCAqIGEgYm9vbGVhbiBpbmRpY2F0aW5nIGlmIHRoZSBtZW51IHNob3VsZCBiZSBzaG93biBhbGlnbmVkIHdpdGggdGhlIG5vZGUuIERlZmF1bHRzIHRvIGB0cnVlYCwgb3RoZXJ3aXNlIHRoZSBtb3VzZSBjb29yZGluYXRlcyBhcmUgdXNlZC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmNvbnRleHRtZW51LnNob3dfYXRfbm9kZVxyXG5cdFx0ICogQHBsdWdpbiBjb250ZXh0bWVudVxyXG5cdFx0ICovXHJcblx0XHRzaG93X2F0X25vZGUgOiB0cnVlLFxyXG5cdFx0LyoqXHJcblx0XHQgKiBhbiBvYmplY3Qgb2YgYWN0aW9ucywgb3IgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgYSBub2RlIGFuZCBhIGNhbGxiYWNrIGZ1bmN0aW9uIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gd2l0aCBhbiBvYmplY3Qgb2YgYWN0aW9ucyBhdmFpbGFibGUgZm9yIHRoYXQgbm9kZSAoeW91IGNhbiBhbHNvIHJldHVybiB0aGUgaXRlbXMgdG9vKS5cclxuXHRcdCAqIFxyXG5cdFx0ICogRWFjaCBhY3Rpb24gY29uc2lzdHMgb2YgYSBrZXkgKGEgdW5pcXVlIG5hbWUpIGFuZCBhIHZhbHVlIHdoaWNoIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyAob25seSBsYWJlbCBhbmQgYWN0aW9uIGFyZSByZXF1aXJlZCk6XHJcblx0XHQgKiBcclxuXHRcdCAqICogYHNlcGFyYXRvcl9iZWZvcmVgIC0gYSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhlcmUgc2hvdWxkIGJlIGEgc2VwYXJhdG9yIGJlZm9yZSB0aGlzIGl0ZW1cclxuXHRcdCAqICogYHNlcGFyYXRvcl9hZnRlcmAgLSBhIGJvb2xlYW4gaW5kaWNhdGluZyBpZiB0aGVyZSBzaG91bGQgYmUgYSBzZXBhcmF0b3IgYWZ0ZXIgdGhpcyBpdGVtXHJcblx0XHQgKiAqIGBfZGlzYWJsZWRgIC0gYSBib29sZWFuIGluZGljYXRpbmcgaWYgdGhpcyBhY3Rpb24gc2hvdWxkIGJlIGRpc2FibGVkXHJcblx0XHQgKiAqIGBsYWJlbGAgLSBhIHN0cmluZyAtIHRoZSBuYW1lIG9mIHRoZSBhY3Rpb25cclxuXHRcdCAqICogYGFjdGlvbmAgLSBhIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGlmIHRoaXMgaXRlbSBpcyBjaG9zZW5cclxuXHRcdCAqICogYGljb25gIC0gYSBzdHJpbmcsIGNhbiBiZSBhIHBhdGggdG8gYW4gaWNvbiBvciBhIGNsYXNzTmFtZSwgaWYgdXNpbmcgYW4gaW1hZ2UgdGhhdCBpcyBpbiB0aGUgY3VycmVudCBkaXJlY3RvcnkgdXNlIGEgYC4vYCBwcmVmaXgsIG90aGVyd2lzZSBpdCB3aWxsIGJlIGRldGVjdGVkIGFzIGEgY2xhc3NcclxuXHRcdCAqICogYHNob3J0Y3V0YCAtIGtleUNvZGUgd2hpY2ggd2lsbCB0cmlnZ2VyIHRoZSBhY3Rpb24gaWYgdGhlIG1lbnUgaXMgb3BlbiAoZm9yIGV4YW1wbGUgYDExM2AgZm9yIHJlbmFtZSwgd2hpY2ggZXF1YWxzIEYyKVxyXG5cdFx0ICogKiBgc2hvcnRjdXRfbGFiZWxgIC0gc2hvcnRjdXQgbGFiZWwgKGxpa2UgZm9yIGV4YW1wbGUgYEYyYCBmb3IgcmVuYW1lKVxyXG5cdFx0ICogXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5jb250ZXh0bWVudS5pdGVtc1xyXG5cdFx0ICogQHBsdWdpbiBjb250ZXh0bWVudVxyXG5cdFx0ICovXHJcblx0XHRpdGVtcyA6IGZ1bmN0aW9uIChvLCBjYikgeyAvLyBDb3VsZCBiZSBhbiBvYmplY3QgZGlyZWN0bHlcclxuXHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcImNyZWF0ZVwiIDoge1xyXG5cdFx0XHRcdFx0XCJzZXBhcmF0b3JfYmVmb3JlXCJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRcInNlcGFyYXRvcl9hZnRlclwiXHQ6IHRydWUsXHJcblx0XHRcdFx0XHRcIl9kaXNhYmxlZFwiXHRcdFx0OiBmYWxzZSwgLy8odGhpcy5jaGVjayhcImNyZWF0ZV9ub2RlXCIsIGRhdGEucmVmZXJlbmNlLCB7fSwgXCJsYXN0XCIpKSxcclxuXHRcdFx0XHRcdFwibGFiZWxcIlx0XHRcdFx0OiBcIkNyZWF0ZVwiLFxyXG5cdFx0XHRcdFx0XCJhY3Rpb25cIlx0XHRcdDogZnVuY3Rpb24gKGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0dmFyIGluc3QgPSAkLmpzdHJlZS5yZWZlcmVuY2UoZGF0YS5yZWZlcmVuY2UpLFxyXG5cdFx0XHRcdFx0XHRcdG9iaiA9IGluc3QuZ2V0X25vZGUoZGF0YS5yZWZlcmVuY2UpO1xyXG5cdFx0XHRcdFx0XHRpbnN0LmNyZWF0ZV9ub2RlKG9iaiwge30sIFwibGFzdFwiLCBmdW5jdGlvbiAobmV3X25vZGUpIHtcclxuXHRcdFx0XHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgaW5zdC5lZGl0KG5ld19ub2RlKTsgfSwwKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSxcclxuXHRcdFx0XHRcInJlbmFtZVwiIDoge1xyXG5cdFx0XHRcdFx0XCJzZXBhcmF0b3JfYmVmb3JlXCJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRcInNlcGFyYXRvcl9hZnRlclwiXHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0XCJfZGlzYWJsZWRcIlx0XHRcdDogZmFsc2UsIC8vKHRoaXMuY2hlY2soXCJyZW5hbWVfbm9kZVwiLCBkYXRhLnJlZmVyZW5jZSwgdGhpcy5nZXRfcGFyZW50KGRhdGEucmVmZXJlbmNlKSwgXCJcIikpLFxyXG5cdFx0XHRcdFx0XCJsYWJlbFwiXHRcdFx0XHQ6IFwiUmVuYW1lXCIsXHJcblx0XHRcdFx0XHQvKlxyXG5cdFx0XHRcdFx0XCJzaG9ydGN1dFwiXHRcdFx0OiAxMTMsXHJcblx0XHRcdFx0XHRcInNob3J0Y3V0X2xhYmVsXCJcdDogJ0YyJyxcclxuXHRcdFx0XHRcdFwiaWNvblwiXHRcdFx0XHQ6IFwiZ2x5cGhpY29uIGdseXBoaWNvbi1sZWFmXCIsXHJcblx0XHRcdFx0XHQqL1xyXG5cdFx0XHRcdFx0XCJhY3Rpb25cIlx0XHRcdDogZnVuY3Rpb24gKGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0dmFyIGluc3QgPSAkLmpzdHJlZS5yZWZlcmVuY2UoZGF0YS5yZWZlcmVuY2UpLFxyXG5cdFx0XHRcdFx0XHRcdG9iaiA9IGluc3QuZ2V0X25vZGUoZGF0YS5yZWZlcmVuY2UpO1xyXG5cdFx0XHRcdFx0XHRpbnN0LmVkaXQob2JqKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9LFxyXG5cdFx0XHRcdFwicmVtb3ZlXCIgOiB7XHJcblx0XHRcdFx0XHRcInNlcGFyYXRvcl9iZWZvcmVcIlx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFwiaWNvblwiXHRcdFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0XCJzZXBhcmF0b3JfYWZ0ZXJcIlx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFwiX2Rpc2FibGVkXCJcdFx0XHQ6IGZhbHNlLCAvLyh0aGlzLmNoZWNrKFwiZGVsZXRlX25vZGVcIiwgZGF0YS5yZWZlcmVuY2UsIHRoaXMuZ2V0X3BhcmVudChkYXRhLnJlZmVyZW5jZSksIFwiXCIpKSxcclxuXHRcdFx0XHRcdFwibGFiZWxcIlx0XHRcdFx0OiBcIkRlbGV0ZVwiLFxyXG5cdFx0XHRcdFx0XCJhY3Rpb25cIlx0XHRcdDogZnVuY3Rpb24gKGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0dmFyIGluc3QgPSAkLmpzdHJlZS5yZWZlcmVuY2UoZGF0YS5yZWZlcmVuY2UpLFxyXG5cdFx0XHRcdFx0XHRcdG9iaiA9IGluc3QuZ2V0X25vZGUoZGF0YS5yZWZlcmVuY2UpO1xyXG5cdFx0XHRcdFx0XHRpZihpbnN0LmlzX3NlbGVjdGVkKG9iaikpIHtcclxuXHRcdFx0XHRcdFx0XHRpbnN0LmRlbGV0ZV9ub2RlKGluc3QuZ2V0X3NlbGVjdGVkKCkpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdGluc3QuZGVsZXRlX25vZGUob2JqKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0sXHJcblx0XHRcdFx0XCJjY3BcIiA6IHtcclxuXHRcdFx0XHRcdFwic2VwYXJhdG9yX2JlZm9yZVwiXHQ6IHRydWUsXHJcblx0XHRcdFx0XHRcImljb25cIlx0XHRcdFx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFwic2VwYXJhdG9yX2FmdGVyXCJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRcImxhYmVsXCJcdFx0XHRcdDogXCJFZGl0XCIsXHJcblx0XHRcdFx0XHRcImFjdGlvblwiXHRcdFx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFwic3VibWVudVwiIDoge1xyXG5cdFx0XHRcdFx0XHRcImN1dFwiIDoge1xyXG5cdFx0XHRcdFx0XHRcdFwic2VwYXJhdG9yX2JlZm9yZVwiXHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0XHRcdFwic2VwYXJhdG9yX2FmdGVyXCJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRcdFx0XCJsYWJlbFwiXHRcdFx0XHQ6IFwiQ3V0XCIsXHJcblx0XHRcdFx0XHRcdFx0XCJhY3Rpb25cIlx0XHRcdDogZnVuY3Rpb24gKGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHZhciBpbnN0ID0gJC5qc3RyZWUucmVmZXJlbmNlKGRhdGEucmVmZXJlbmNlKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0b2JqID0gaW5zdC5nZXRfbm9kZShkYXRhLnJlZmVyZW5jZSk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZihpbnN0LmlzX3NlbGVjdGVkKG9iaikpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aW5zdC5jdXQoaW5zdC5nZXRfc2VsZWN0ZWQoKSk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aW5zdC5jdXQob2JqKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0sXHJcblx0XHRcdFx0XHRcdFwiY29weVwiIDoge1xyXG5cdFx0XHRcdFx0XHRcdFwic2VwYXJhdG9yX2JlZm9yZVwiXHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0XHRcdFwiaWNvblwiXHRcdFx0XHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0XHRcdFwic2VwYXJhdG9yX2FmdGVyXCJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRcdFx0XCJsYWJlbFwiXHRcdFx0XHQ6IFwiQ29weVwiLFxyXG5cdFx0XHRcdFx0XHRcdFwiYWN0aW9uXCJcdFx0XHQ6IGZ1bmN0aW9uIChkYXRhKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR2YXIgaW5zdCA9ICQuanN0cmVlLnJlZmVyZW5jZShkYXRhLnJlZmVyZW5jZSksXHJcblx0XHRcdFx0XHRcdFx0XHRcdG9iaiA9IGluc3QuZ2V0X25vZGUoZGF0YS5yZWZlcmVuY2UpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYoaW5zdC5pc19zZWxlY3RlZChvYmopKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGluc3QuY29weShpbnN0LmdldF9zZWxlY3RlZCgpKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpbnN0LmNvcHkob2JqKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0sXHJcblx0XHRcdFx0XHRcdFwicGFzdGVcIiA6IHtcclxuXHRcdFx0XHRcdFx0XHRcInNlcGFyYXRvcl9iZWZvcmVcIlx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0XHRcImljb25cIlx0XHRcdFx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0XHRcIl9kaXNhYmxlZFwiXHRcdFx0OiBmdW5jdGlvbiAoZGF0YSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuICEkLmpzdHJlZS5yZWZlcmVuY2UoZGF0YS5yZWZlcmVuY2UpLmNhbl9wYXN0ZSgpO1xyXG5cdFx0XHRcdFx0XHRcdH0sXHJcblx0XHRcdFx0XHRcdFx0XCJzZXBhcmF0b3JfYWZ0ZXJcIlx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0XHRcImxhYmVsXCJcdFx0XHRcdDogXCJQYXN0ZVwiLFxyXG5cdFx0XHRcdFx0XHRcdFwiYWN0aW9uXCJcdFx0XHQ6IGZ1bmN0aW9uIChkYXRhKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR2YXIgaW5zdCA9ICQuanN0cmVlLnJlZmVyZW5jZShkYXRhLnJlZmVyZW5jZSksXHJcblx0XHRcdFx0XHRcdFx0XHRcdG9iaiA9IGluc3QuZ2V0X25vZGUoZGF0YS5yZWZlcmVuY2UpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aW5zdC5wYXN0ZShvYmopO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHQkLmpzdHJlZS5wbHVnaW5zLmNvbnRleHRtZW51ID0gZnVuY3Rpb24gKG9wdGlvbnMsIHBhcmVudCkge1xyXG5cdFx0dGhpcy5iaW5kID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRwYXJlbnQuYmluZC5jYWxsKHRoaXMpO1xyXG5cclxuXHRcdFx0dGhpcy5lbGVtZW50XHJcblx0XHRcdFx0Lm9uKFwiY29udGV4dG1lbnUuanN0cmVlXCIsIFwiLmpzdHJlZS1hbmNob3JcIiwgJC5wcm94eShmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdGlmKCF0aGlzLmlzX2xvYWRpbmcoZS5jdXJyZW50VGFyZ2V0KSkge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMuc2hvd19jb250ZXh0bWVudShlLmN1cnJlbnRUYXJnZXQsIGUucGFnZVgsIGUucGFnZVksIGUpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oXCJjbGljay5qc3RyZWVcIiwgXCIuanN0cmVlLWFuY2hvclwiLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdGlmKHRoaXMuX2RhdGEuY29udGV4dG1lbnUudmlzaWJsZSkge1xyXG5cdFx0XHRcdFx0XHRcdCQudmFrYXRhLmNvbnRleHQuaGlkZSgpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9LCB0aGlzKSk7XHJcblx0XHRcdC8qXHJcblx0XHRcdGlmKCEoJ29uY29udGV4dG1lbnUnIGluIGRvY3VtZW50LmJvZHkpICYmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5ib2R5KSkge1xyXG5cdFx0XHRcdHZhciBlbCA9IG51bGwsIHRtID0gbnVsbDtcclxuXHRcdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHRcdC5vbihcInRvdWNoc3RhcnRcIiwgXCIuanN0cmVlLWFuY2hvclwiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0XHRlbCA9IGUuY3VycmVudFRhcmdldDtcclxuXHRcdFx0XHRcdFx0dG0gPSArbmV3IERhdGUoKTtcclxuXHRcdFx0XHRcdFx0JChkb2N1bWVudCkub25lKFwidG91Y2hlbmRcIiwgZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdFx0XHRlLnRhcmdldCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZS5vcmlnaW5hbEV2ZW50LnRhcmdldFRvdWNoZXNbMF0ucGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQsIGUub3JpZ2luYWxFdmVudC50YXJnZXRUb3VjaGVzWzBdLnBhZ2VZIC0gd2luZG93LnBhZ2VZT2Zmc2V0KTtcclxuXHRcdFx0XHRcdFx0XHRlLmN1cnJlbnRUYXJnZXQgPSBlLnRhcmdldDtcclxuXHRcdFx0XHRcdFx0XHR0bSA9ICgoKyhuZXcgRGF0ZSgpKSkgLSB0bSk7XHJcblx0XHRcdFx0XHRcdFx0aWYoZS50YXJnZXQgPT09IGVsICYmIHRtID4gNjAwICYmIHRtIDwgMTAwMCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0JChlbCkudHJpZ2dlcignY29udGV4dG1lbnUnLCBlKTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0ZWwgPSBudWxsO1xyXG5cdFx0XHRcdFx0XHRcdHRtID0gbnVsbDtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0XHQqL1xyXG5cdFx0XHQkKGRvY3VtZW50KS5vbihcImNvbnRleHRfaGlkZS52YWthdGFcIiwgJC5wcm94eShmdW5jdGlvbiAoKSB7IHRoaXMuX2RhdGEuY29udGV4dG1lbnUudmlzaWJsZSA9IGZhbHNlOyB9LCB0aGlzKSk7XHJcblx0XHR9O1xyXG5cdFx0dGhpcy50ZWFyZG93biA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0aWYodGhpcy5fZGF0YS5jb250ZXh0bWVudS52aXNpYmxlKSB7XHJcblx0XHRcdFx0JC52YWthdGEuY29udGV4dC5oaWRlKCk7XHJcblx0XHRcdH1cclxuXHRcdFx0cGFyZW50LnRlYXJkb3duLmNhbGwodGhpcyk7XHJcblx0XHR9O1xyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogcHJlcGFyZSBhbmQgc2hvdyB0aGUgY29udGV4dCBtZW51IGZvciBhIG5vZGVcclxuXHRcdCAqIEBuYW1lIHNob3dfY29udGV4dG1lbnUob2JqIFssIHgsIHldKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlXHJcblx0XHQgKiBAcGFyYW0ge051bWJlcn0geCB0aGUgeC1jb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0byBzaG93IHRoZSBtZW51IGF0XHJcblx0XHQgKiBAcGFyYW0ge051bWJlcn0geSB0aGUgeS1jb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0byBzaG93IHRoZSBtZW51IGF0XHJcblx0XHQgKiBAcGFyYW0ge09iamVjdH0gZSB0aGUgZXZlbnQgaWYgYXZhaWxhYmxlIHRoYXQgdHJpZ2dlcmVkIHRoZSBjb250ZXh0bWVudVxyXG5cdFx0ICogQHBsdWdpbiBjb250ZXh0bWVudVxyXG5cdFx0ICogQHRyaWdnZXIgc2hvd19jb250ZXh0bWVudS5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5zaG93X2NvbnRleHRtZW51ID0gZnVuY3Rpb24gKG9iaiwgeCwgeSwgZSkge1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCFvYmogfHwgb2JqLmlkID09PSAnIycpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdHZhciBzID0gdGhpcy5zZXR0aW5ncy5jb250ZXh0bWVudSxcclxuXHRcdFx0XHRkID0gdGhpcy5nZXRfbm9kZShvYmosIHRydWUpLFxyXG5cdFx0XHRcdGEgPSBkLmNoaWxkcmVuKFwiLmpzdHJlZS1hbmNob3JcIiksXHJcblx0XHRcdFx0byA9IGZhbHNlLFxyXG5cdFx0XHRcdGkgPSBmYWxzZTtcclxuXHRcdFx0aWYocy5zaG93X2F0X25vZGUgfHwgeCA9PT0gdW5kZWZpbmVkIHx8IHkgPT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHRcdG8gPSBhLm9mZnNldCgpO1xyXG5cdFx0XHRcdHggPSBvLmxlZnQ7XHJcblx0XHRcdFx0eSA9IG8udG9wICsgdGhpcy5fZGF0YS5jb3JlLmxpX2hlaWdodDtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZih0aGlzLnNldHRpbmdzLmNvbnRleHRtZW51LnNlbGVjdF9ub2RlICYmICF0aGlzLmlzX3NlbGVjdGVkKG9iaikpIHtcclxuXHRcdFx0XHR0aGlzLmRlc2VsZWN0X2FsbCgpO1xyXG5cdFx0XHRcdHRoaXMuc2VsZWN0X25vZGUob2JqLCBmYWxzZSwgZmFsc2UsIGUpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpID0gcy5pdGVtcztcclxuXHRcdFx0aWYoJC5pc0Z1bmN0aW9uKGkpKSB7XHJcblx0XHRcdFx0aSA9IGkuY2FsbCh0aGlzLCBvYmosICQucHJveHkoZnVuY3Rpb24gKGkpIHtcclxuXHRcdFx0XHRcdHRoaXMuX3Nob3dfY29udGV4dG1lbnUob2JqLCB4LCB5LCBpKTtcclxuXHRcdFx0XHR9LCB0aGlzKSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoJC5pc1BsYWluT2JqZWN0KGkpKSB7XHJcblx0XHRcdFx0dGhpcy5fc2hvd19jb250ZXh0bWVudShvYmosIHgsIHksIGkpO1xyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdFx0LyoqXHJcblx0XHQgKiBzaG93IHRoZSBwcmVwYXJlZCBjb250ZXh0IG1lbnUgZm9yIGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgX3Nob3dfY29udGV4dG1lbnUob2JqLCB4LCB5LCBpKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlXHJcblx0XHQgKiBAcGFyYW0ge051bWJlcn0geCB0aGUgeC1jb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0byBzaG93IHRoZSBtZW51IGF0XHJcblx0XHQgKiBAcGFyYW0ge051bWJlcn0geSB0aGUgeS1jb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCB0byBzaG93IHRoZSBtZW51IGF0XHJcblx0XHQgKiBAcGFyYW0ge051bWJlcn0gaSB0aGUgb2JqZWN0IG9mIGl0ZW1zIHRvIHNob3dcclxuXHRcdCAqIEBwbHVnaW4gY29udGV4dG1lbnVcclxuXHRcdCAqIEB0cmlnZ2VyIHNob3dfY29udGV4dG1lbnUuanN0cmVlXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICovXHJcblx0XHR0aGlzLl9zaG93X2NvbnRleHRtZW51ID0gZnVuY3Rpb24gKG9iaiwgeCwgeSwgaSkge1xyXG5cdFx0XHR2YXIgZCA9IHRoaXMuZ2V0X25vZGUob2JqLCB0cnVlKSxcclxuXHRcdFx0XHRhID0gZC5jaGlsZHJlbihcIi5qc3RyZWUtYW5jaG9yXCIpO1xyXG5cdFx0XHQkKGRvY3VtZW50KS5vbmUoXCJjb250ZXh0X3Nob3cudmFrYXRhXCIsICQucHJveHkoZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuXHRcdFx0XHR2YXIgY2xzID0gJ2pzdHJlZS1jb250ZXh0bWVudSBqc3RyZWUtJyArIHRoaXMuZ2V0X3RoZW1lKCkgKyAnLWNvbnRleHRtZW51JztcclxuXHRcdFx0XHQkKGRhdGEuZWxlbWVudCkuYWRkQ2xhc3MoY2xzKTtcclxuXHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0XHR0aGlzLl9kYXRhLmNvbnRleHRtZW51LnZpc2libGUgPSB0cnVlO1xyXG5cdFx0XHQkLnZha2F0YS5jb250ZXh0LnNob3coYSwgeyAneCcgOiB4LCAneScgOiB5IH0sIGkpO1xyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIHdoZW4gdGhlIGNvbnRleHRtZW51IGlzIHNob3duIGZvciBhIG5vZGVcclxuXHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdCAqIEBuYW1lIHNob3dfY29udGV4dG1lbnUuanN0cmVlXHJcblx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBub2RlIHRoZSBub2RlXHJcblx0XHRcdCAqIEBwYXJhbSB7TnVtYmVyfSB4IHRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIG1lbnUgcmVsYXRpdmUgdG8gdGhlIGRvY3VtZW50XHJcblx0XHRcdCAqIEBwYXJhbSB7TnVtYmVyfSB5IHRoZSB5LWNvb3JkaW5hdGUgb2YgdGhlIG1lbnUgcmVsYXRpdmUgdG8gdGhlIGRvY3VtZW50XHJcblx0XHRcdCAqIEBwbHVnaW4gY29udGV4dG1lbnVcclxuXHRcdFx0ICovXHJcblx0XHRcdHRoaXMudHJpZ2dlcignc2hvd19jb250ZXh0bWVudScsIHsgXCJub2RlXCIgOiBvYmosIFwieFwiIDogeCwgXCJ5XCIgOiB5IH0pO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cclxuXHQvLyBjb250ZXh0bWVudSBoZWxwZXJcclxuXHQoZnVuY3Rpb24gKCQpIHtcclxuXHRcdHZhciByaWdodF90b19sZWZ0ID0gZmFsc2UsXHJcblx0XHRcdHZha2F0YV9jb250ZXh0ID0ge1xyXG5cdFx0XHRcdGVsZW1lbnRcdFx0OiBmYWxzZSxcclxuXHRcdFx0XHRyZWZlcmVuY2VcdDogZmFsc2UsXHJcblx0XHRcdFx0cG9zaXRpb25feFx0OiAwLFxyXG5cdFx0XHRcdHBvc2l0aW9uX3lcdDogMCxcclxuXHRcdFx0XHRpdGVtc1x0XHQ6IFtdLFxyXG5cdFx0XHRcdGh0bWxcdFx0OiBcIlwiLFxyXG5cdFx0XHRcdGlzX3Zpc2libGVcdDogZmFsc2VcclxuXHRcdFx0fTtcclxuXHJcblx0XHQkLnZha2F0YS5jb250ZXh0ID0ge1xyXG5cdFx0XHRzZXR0aW5ncyA6IHtcclxuXHRcdFx0XHRoaWRlX29ubW91c2VsZWF2ZVx0OiAwLFxyXG5cdFx0XHRcdGljb25zXHRcdFx0XHQ6IHRydWVcclxuXHRcdFx0fSxcclxuXHRcdFx0X3RyaWdnZXIgOiBmdW5jdGlvbiAoZXZlbnRfbmFtZSkge1xyXG5cdFx0XHRcdCQoZG9jdW1lbnQpLnRyaWdnZXJIYW5kbGVyKFwiY29udGV4dF9cIiArIGV2ZW50X25hbWUgKyBcIi52YWthdGFcIiwge1xyXG5cdFx0XHRcdFx0XCJyZWZlcmVuY2VcIlx0OiB2YWthdGFfY29udGV4dC5yZWZlcmVuY2UsXHJcblx0XHRcdFx0XHRcImVsZW1lbnRcIlx0OiB2YWthdGFfY29udGV4dC5lbGVtZW50LFxyXG5cdFx0XHRcdFx0XCJwb3NpdGlvblwiXHQ6IHtcclxuXHRcdFx0XHRcdFx0XCJ4XCIgOiB2YWthdGFfY29udGV4dC5wb3NpdGlvbl94LFxyXG5cdFx0XHRcdFx0XHRcInlcIiA6IHZha2F0YV9jb250ZXh0LnBvc2l0aW9uX3lcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fSxcclxuXHRcdFx0X2V4ZWN1dGUgOiBmdW5jdGlvbiAoaSkge1xyXG5cdFx0XHRcdGkgPSB2YWthdGFfY29udGV4dC5pdGVtc1tpXTtcclxuXHRcdFx0XHRyZXR1cm4gaSAmJiAoIWkuX2Rpc2FibGVkIHx8ICgkLmlzRnVuY3Rpb24oaS5fZGlzYWJsZWQpICYmICFpLl9kaXNhYmxlZCh7IFwiaXRlbVwiIDogaSwgXCJyZWZlcmVuY2VcIiA6IHZha2F0YV9jb250ZXh0LnJlZmVyZW5jZSwgXCJlbGVtZW50XCIgOiB2YWthdGFfY29udGV4dC5lbGVtZW50IH0pKSkgJiYgaS5hY3Rpb24gPyBpLmFjdGlvbi5jYWxsKG51bGwsIHtcclxuXHRcdFx0XHRcdFx0XHRcIml0ZW1cIlx0XHQ6IGksXHJcblx0XHRcdFx0XHRcdFx0XCJyZWZlcmVuY2VcIlx0OiB2YWthdGFfY29udGV4dC5yZWZlcmVuY2UsXHJcblx0XHRcdFx0XHRcdFx0XCJlbGVtZW50XCJcdDogdmFrYXRhX2NvbnRleHQuZWxlbWVudCxcclxuXHRcdFx0XHRcdFx0XHRcInBvc2l0aW9uXCJcdDoge1xyXG5cdFx0XHRcdFx0XHRcdFx0XCJ4XCIgOiB2YWthdGFfY29udGV4dC5wb3NpdGlvbl94LFxyXG5cdFx0XHRcdFx0XHRcdFx0XCJ5XCIgOiB2YWthdGFfY29udGV4dC5wb3NpdGlvbl95XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9KSA6IGZhbHNlO1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRfcGFyc2UgOiBmdW5jdGlvbiAobywgaXNfY2FsbGJhY2spIHtcclxuXHRcdFx0XHRpZighbykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0XHRpZighaXNfY2FsbGJhY2spIHtcclxuXHRcdFx0XHRcdHZha2F0YV9jb250ZXh0Lmh0bWxcdFx0PSBcIlwiO1xyXG5cdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQuaXRlbXNcdD0gW107XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHZhciBzdHIgPSBcIlwiLFxyXG5cdFx0XHRcdFx0c2VwID0gZmFsc2UsXHJcblx0XHRcdFx0XHR0bXA7XHJcblxyXG5cdFx0XHRcdGlmKGlzX2NhbGxiYWNrKSB7IHN0ciArPSBcIjxcIitcInVsPlwiOyB9XHJcblx0XHRcdFx0JC5lYWNoKG8sIGZ1bmN0aW9uIChpLCB2YWwpIHtcclxuXHRcdFx0XHRcdGlmKCF2YWwpIHsgcmV0dXJuIHRydWU7IH1cclxuXHRcdFx0XHRcdHZha2F0YV9jb250ZXh0Lml0ZW1zLnB1c2godmFsKTtcclxuXHRcdFx0XHRcdGlmKCFzZXAgJiYgdmFsLnNlcGFyYXRvcl9iZWZvcmUpIHtcclxuXHRcdFx0XHRcdFx0c3RyICs9IFwiPFwiK1wibGkgY2xhc3M9J3Zha2F0YS1jb250ZXh0LXNlcGFyYXRvcic+PFwiK1wiYSBocmVmPScjJyBcIiArICgkLnZha2F0YS5jb250ZXh0LnNldHRpbmdzLmljb25zID8gJycgOiAnc3R5bGU9XCJtYXJnaW4tbGVmdDowcHg7XCInKSArIFwiPiYjMTYwOzxcIitcIi9hPjxcIitcIi9saT5cIjtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHNlcCA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0c3RyICs9IFwiPFwiK1wibGkgY2xhc3M9J1wiICsgKHZhbC5fY2xhc3MgfHwgXCJcIikgKyAodmFsLl9kaXNhYmxlZCA9PT0gdHJ1ZSB8fCAoJC5pc0Z1bmN0aW9uKHZhbC5fZGlzYWJsZWQpICYmIHZhbC5fZGlzYWJsZWQoeyBcIml0ZW1cIiA6IHZhbCwgXCJyZWZlcmVuY2VcIiA6IHZha2F0YV9jb250ZXh0LnJlZmVyZW5jZSwgXCJlbGVtZW50XCIgOiB2YWthdGFfY29udGV4dC5lbGVtZW50IH0pKSA/IFwiIHZha2F0YS1jb250ZXh0bWVudS1kaXNhYmxlZCBcIiA6IFwiXCIpICsgXCInIFwiKyh2YWwuc2hvcnRjdXQ/XCIgZGF0YS1zaG9ydGN1dD0nXCIrdmFsLnNob3J0Y3V0K1wiJyBcIjonJykrXCI+XCI7XHJcblx0XHRcdFx0XHRzdHIgKz0gXCI8XCIrXCJhIGhyZWY9JyMnIHJlbD0nXCIgKyAodmFrYXRhX2NvbnRleHQuaXRlbXMubGVuZ3RoIC0gMSkgKyBcIic+XCI7XHJcblx0XHRcdFx0XHRpZigkLnZha2F0YS5jb250ZXh0LnNldHRpbmdzLmljb25zKSB7XHJcblx0XHRcdFx0XHRcdHN0ciArPSBcIjxcIitcImkgXCI7XHJcblx0XHRcdFx0XHRcdGlmKHZhbC5pY29uKSB7XHJcblx0XHRcdFx0XHRcdFx0aWYodmFsLmljb24uaW5kZXhPZihcIi9cIikgIT09IC0xIHx8IHZhbC5pY29uLmluZGV4T2YoXCIuXCIpICE9PSAtMSkgeyBzdHIgKz0gXCIgc3R5bGU9J2JhY2tncm91bmQ6dXJsKFxcXCJcIiArIHZhbC5pY29uICsgXCJcXFwiKSBjZW50ZXIgY2VudGVyIG5vLXJlcGVhdCcgXCI7IH1cclxuXHRcdFx0XHRcdFx0XHRlbHNlIHsgc3RyICs9IFwiIGNsYXNzPSdcIiArIHZhbC5pY29uICsgXCInIFwiOyB9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0c3RyICs9IFwiPjxcIitcIi9pPjxcIitcInNwYW4gY2xhc3M9J3Zha2F0YS1jb250ZXh0bWVudS1zZXAnPiYjMTYwOzxcIitcIi9zcGFuPlwiO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0c3RyICs9IHZhbC5sYWJlbCArICh2YWwuc2hvcnRjdXQ/JyA8c3BhbiBjbGFzcz1cInZha2F0YS1jb250ZXh0bWVudS1zaG9ydGN1dCB2YWthdGEtY29udGV4dG1lbnUtc2hvcnRjdXQtJyt2YWwuc2hvcnRjdXQrJ1wiPicrICh2YWwuc2hvcnRjdXRfbGFiZWwgfHwgJycpICsnPC9zcGFuPic6JycpICsgXCI8XCIrXCIvYT5cIjtcclxuXHRcdFx0XHRcdGlmKHZhbC5zdWJtZW51KSB7XHJcblx0XHRcdFx0XHRcdHRtcCA9ICQudmFrYXRhLmNvbnRleHQuX3BhcnNlKHZhbC5zdWJtZW51LCB0cnVlKTtcclxuXHRcdFx0XHRcdFx0aWYodG1wKSB7IHN0ciArPSB0bXA7IH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHN0ciArPSBcIjxcIitcIi9saT5cIjtcclxuXHRcdFx0XHRcdGlmKHZhbC5zZXBhcmF0b3JfYWZ0ZXIpIHtcclxuXHRcdFx0XHRcdFx0c3RyICs9IFwiPFwiK1wibGkgY2xhc3M9J3Zha2F0YS1jb250ZXh0LXNlcGFyYXRvcic+PFwiK1wiYSBocmVmPScjJyBcIiArICgkLnZha2F0YS5jb250ZXh0LnNldHRpbmdzLmljb25zID8gJycgOiAnc3R5bGU9XCJtYXJnaW4tbGVmdDowcHg7XCInKSArIFwiPiYjMTYwOzxcIitcIi9hPjxcIitcIi9saT5cIjtcclxuXHRcdFx0XHRcdFx0c2VwID0gdHJ1ZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0XHRzdHIgID0gc3RyLnJlcGxhY2UoLzxsaSBjbGFzc1xcPSd2YWthdGEtY29udGV4dC1zZXBhcmF0b3InXFw+PFxcL2xpXFw+JC8sXCJcIik7XHJcblx0XHRcdFx0aWYoaXNfY2FsbGJhY2spIHsgc3RyICs9IFwiPC91bD5cIjsgfVxyXG5cdFx0XHRcdC8qKlxyXG5cdFx0XHRcdCAqIHRyaWdnZXJlZCBvbiB0aGUgZG9jdW1lbnQgd2hlbiB0aGUgY29udGV4dG1lbnUgaXMgcGFyc2VkIChIVE1MIGlzIGJ1aWx0KVxyXG5cdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdCAqIEBwbHVnaW4gY29udGV4dG1lbnVcclxuXHRcdFx0XHQgKiBAbmFtZSBjb250ZXh0X3BhcnNlLnZha2F0YVxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7alF1ZXJ5fSByZWZlcmVuY2UgdGhlIGVsZW1lbnQgdGhhdCB3YXMgcmlnaHQgY2xpY2tlZFxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7alF1ZXJ5fSBlbGVtZW50IHRoZSBET00gZWxlbWVudCBvZiB0aGUgbWVudSBpdHNlbGZcclxuXHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gcG9zaXRpb24gdGhlIHggJiB5IGNvb3JkaW5hdGVzIG9mIHRoZSBtZW51XHJcblx0XHRcdFx0ICovXHJcblx0XHRcdFx0aWYoIWlzX2NhbGxiYWNrKSB7IHZha2F0YV9jb250ZXh0Lmh0bWwgPSBzdHI7ICQudmFrYXRhLmNvbnRleHQuX3RyaWdnZXIoXCJwYXJzZVwiKTsgfVxyXG5cdFx0XHRcdHJldHVybiBzdHIubGVuZ3RoID4gMTAgPyBzdHIgOiBmYWxzZTtcclxuXHRcdFx0fSxcclxuXHRcdFx0X3Nob3dfc3VibWVudSA6IGZ1bmN0aW9uIChvKSB7XHJcblx0XHRcdFx0byA9ICQobyk7XHJcblx0XHRcdFx0aWYoIW8ubGVuZ3RoIHx8ICFvLmNoaWxkcmVuKFwidWxcIikubGVuZ3RoKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdHZhciBlID0gby5jaGlsZHJlbihcInVsXCIpLFxyXG5cdFx0XHRcdFx0eCA9IG8ub2Zmc2V0KCkubGVmdCArIG8ub3V0ZXJXaWR0aCgpLFxyXG5cdFx0XHRcdFx0eSA9IG8ub2Zmc2V0KCkudG9wLFxyXG5cdFx0XHRcdFx0dyA9IGUud2lkdGgoKSxcclxuXHRcdFx0XHRcdGggPSBlLmhlaWdodCgpLFxyXG5cdFx0XHRcdFx0ZHcgPSAkKHdpbmRvdykud2lkdGgoKSArICQod2luZG93KS5zY3JvbGxMZWZ0KCksXHJcblx0XHRcdFx0XHRkaCA9ICQod2luZG93KS5oZWlnaHQoKSArICQod2luZG93KS5zY3JvbGxUb3AoKTtcclxuXHRcdFx0XHQvLyDQvNC+0LbQtSDQtNCwINGB0LUg0YHQv9C10YHRgtC4INC1INC10LTQvdCwINC/0YDQvtCy0LXRgNC60LAgLSDQtNCw0LvQuCDQvdGP0LzQsCDQvdGP0LrQvtC5INC+0YIg0LrQu9Cw0YHQvtCy0LXRgtC1INCy0LXRh9C1INC90LDQs9C+0YDQtVxyXG5cdFx0XHRcdGlmKHJpZ2h0X3RvX2xlZnQpIHtcclxuXHRcdFx0XHRcdG9beCAtICh3ICsgMTAgKyBvLm91dGVyV2lkdGgoKSkgPCAwID8gXCJhZGRDbGFzc1wiIDogXCJyZW1vdmVDbGFzc1wiXShcInZha2F0YS1jb250ZXh0LWxlZnRcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0b1t4ICsgdyArIDEwID4gZHcgPyBcImFkZENsYXNzXCIgOiBcInJlbW92ZUNsYXNzXCJdKFwidmFrYXRhLWNvbnRleHQtcmlnaHRcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmKHkgKyBoICsgMTAgPiBkaCkge1xyXG5cdFx0XHRcdFx0ZS5jc3MoXCJib3R0b21cIixcIi0xcHhcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGUuc2hvdygpO1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRzaG93IDogZnVuY3Rpb24gKHJlZmVyZW5jZSwgcG9zaXRpb24sIGRhdGEpIHtcclxuXHRcdFx0XHR2YXIgbywgZSwgeCwgeSwgdywgaCwgZHcsIGRoLCBjb25kID0gdHJ1ZTtcclxuXHRcdFx0XHRpZih2YWthdGFfY29udGV4dC5lbGVtZW50ICYmIHZha2F0YV9jb250ZXh0LmVsZW1lbnQubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHR2YWthdGFfY29udGV4dC5lbGVtZW50LndpZHRoKCcnKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0c3dpdGNoKGNvbmQpIHtcclxuXHRcdFx0XHRcdGNhc2UgKCFwb3NpdGlvbiAmJiAhcmVmZXJlbmNlKTpcclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0Y2FzZSAoISFwb3NpdGlvbiAmJiAhIXJlZmVyZW5jZSk6XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LnJlZmVyZW5jZVx0PSByZWZlcmVuY2U7XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LnBvc2l0aW9uX3hcdD0gcG9zaXRpb24ueDtcclxuXHRcdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQucG9zaXRpb25feVx0PSBwb3NpdGlvbi55O1xyXG5cdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdGNhc2UgKCFwb3NpdGlvbiAmJiAhIXJlZmVyZW5jZSk6XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LnJlZmVyZW5jZVx0PSByZWZlcmVuY2U7XHJcblx0XHRcdFx0XHRcdG8gPSByZWZlcmVuY2Uub2Zmc2V0KCk7XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LnBvc2l0aW9uX3hcdD0gby5sZWZ0ICsgcmVmZXJlbmNlLm91dGVySGVpZ2h0KCk7XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LnBvc2l0aW9uX3lcdD0gby50b3A7XHJcblx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0Y2FzZSAoISFwb3NpdGlvbiAmJiAhcmVmZXJlbmNlKTpcclxuXHRcdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQucG9zaXRpb25feFx0PSBwb3NpdGlvbi54O1xyXG5cdFx0XHRcdFx0XHR2YWthdGFfY29udGV4dC5wb3NpdGlvbl95XHQ9IHBvc2l0aW9uLnk7XHJcblx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZighIXJlZmVyZW5jZSAmJiAhZGF0YSAmJiAkKHJlZmVyZW5jZSkuZGF0YSgndmFrYXRhX2NvbnRleHRtZW51JykpIHtcclxuXHRcdFx0XHRcdGRhdGEgPSAkKHJlZmVyZW5jZSkuZGF0YSgndmFrYXRhX2NvbnRleHRtZW51Jyk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmKCQudmFrYXRhLmNvbnRleHQuX3BhcnNlKGRhdGEpKSB7XHJcblx0XHRcdFx0XHR2YWthdGFfY29udGV4dC5lbGVtZW50Lmh0bWwodmFrYXRhX2NvbnRleHQuaHRtbCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmKHZha2F0YV9jb250ZXh0Lml0ZW1zLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0ZSA9IHZha2F0YV9jb250ZXh0LmVsZW1lbnQ7XHJcblx0XHRcdFx0XHR4ID0gdmFrYXRhX2NvbnRleHQucG9zaXRpb25feDtcclxuXHRcdFx0XHRcdHkgPSB2YWthdGFfY29udGV4dC5wb3NpdGlvbl95O1xyXG5cdFx0XHRcdFx0dyA9IGUud2lkdGgoKTtcclxuXHRcdFx0XHRcdGggPSBlLmhlaWdodCgpO1xyXG5cdFx0XHRcdFx0ZHcgPSAkKHdpbmRvdykud2lkdGgoKSArICQod2luZG93KS5zY3JvbGxMZWZ0KCk7XHJcblx0XHRcdFx0XHRkaCA9ICQod2luZG93KS5oZWlnaHQoKSArICQod2luZG93KS5zY3JvbGxUb3AoKTtcclxuXHRcdFx0XHRcdGlmKHJpZ2h0X3RvX2xlZnQpIHtcclxuXHRcdFx0XHRcdFx0eCAtPSBlLm91dGVyV2lkdGgoKTtcclxuXHRcdFx0XHRcdFx0aWYoeCA8ICQod2luZG93KS5zY3JvbGxMZWZ0KCkgKyAyMCkge1xyXG5cdFx0XHRcdFx0XHRcdHggPSAkKHdpbmRvdykuc2Nyb2xsTGVmdCgpICsgMjA7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmKHggKyB3ICsgMjAgPiBkdykge1xyXG5cdFx0XHRcdFx0XHR4ID0gZHcgLSAodyArIDIwKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmKHkgKyBoICsgMjAgPiBkaCkge1xyXG5cdFx0XHRcdFx0XHR5ID0gZGggLSAoaCArIDIwKTtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHR2YWthdGFfY29udGV4dC5lbGVtZW50XHJcblx0XHRcdFx0XHRcdC5jc3MoeyBcImxlZnRcIiA6IHgsIFwidG9wXCIgOiB5IH0pXHJcblx0XHRcdFx0XHRcdC5zaG93KClcclxuXHRcdFx0XHRcdFx0LmZpbmQoJ2E6ZXEoMCknKS5mb2N1cygpLnBhcmVudCgpLmFkZENsYXNzKFwidmFrYXRhLWNvbnRleHQtaG92ZXJcIik7XHJcblx0XHRcdFx0XHR2YWthdGFfY29udGV4dC5pc192aXNpYmxlID0gdHJ1ZTtcclxuXHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0ICogdHJpZ2dlcmVkIG9uIHRoZSBkb2N1bWVudCB3aGVuIHRoZSBjb250ZXh0bWVudSBpcyBzaG93blxyXG5cdFx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0XHQgKiBAcGx1Z2luIGNvbnRleHRtZW51XHJcblx0XHRcdFx0XHQgKiBAbmFtZSBjb250ZXh0X3Nob3cudmFrYXRhXHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge2pRdWVyeX0gcmVmZXJlbmNlIHRoZSBlbGVtZW50IHRoYXQgd2FzIHJpZ2h0IGNsaWNrZWRcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7alF1ZXJ5fSBlbGVtZW50IHRoZSBET00gZWxlbWVudCBvZiB0aGUgbWVudSBpdHNlbGZcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBwb3NpdGlvbiB0aGUgeCAmIHkgY29vcmRpbmF0ZXMgb2YgdGhlIG1lbnVcclxuXHRcdFx0XHRcdCAqL1xyXG5cdFx0XHRcdFx0JC52YWthdGEuY29udGV4dC5fdHJpZ2dlcihcInNob3dcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9LFxyXG5cdFx0XHRoaWRlIDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdGlmKHZha2F0YV9jb250ZXh0LmlzX3Zpc2libGUpIHtcclxuXHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LmVsZW1lbnQuaGlkZSgpLmZpbmQoXCJ1bFwiKS5oaWRlKCkuZW5kKCkuZmluZCgnOmZvY3VzJykuYmx1cigpO1xyXG5cdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQuaXNfdmlzaWJsZSA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0LyoqXHJcblx0XHRcdFx0XHQgKiB0cmlnZ2VyZWQgb24gdGhlIGRvY3VtZW50IHdoZW4gdGhlIGNvbnRleHRtZW51IGlzIGhpZGRlblxyXG5cdFx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0XHQgKiBAcGx1Z2luIGNvbnRleHRtZW51XHJcblx0XHRcdFx0XHQgKiBAbmFtZSBjb250ZXh0X2hpZGUudmFrYXRhXHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge2pRdWVyeX0gcmVmZXJlbmNlIHRoZSBlbGVtZW50IHRoYXQgd2FzIHJpZ2h0IGNsaWNrZWRcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7alF1ZXJ5fSBlbGVtZW50IHRoZSBET00gZWxlbWVudCBvZiB0aGUgbWVudSBpdHNlbGZcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBwb3NpdGlvbiB0aGUgeCAmIHkgY29vcmRpbmF0ZXMgb2YgdGhlIG1lbnVcclxuXHRcdFx0XHRcdCAqL1xyXG5cdFx0XHRcdFx0JC52YWthdGEuY29udGV4dC5fdHJpZ2dlcihcImhpZGVcIik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdFx0JChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHJpZ2h0X3RvX2xlZnQgPSAkKFwiYm9keVwiKS5jc3MoXCJkaXJlY3Rpb25cIikgPT09IFwicnRsXCI7XHJcblx0XHRcdHZhciB0byA9IGZhbHNlO1xyXG5cclxuXHRcdFx0dmFrYXRhX2NvbnRleHQuZWxlbWVudCA9ICQoXCI8dWwgY2xhc3M9J3Zha2F0YS1jb250ZXh0Jz48L3VsPlwiKTtcclxuXHRcdFx0dmFrYXRhX2NvbnRleHQuZWxlbWVudFxyXG5cdFx0XHRcdC5vbihcIm1vdXNlZW50ZXJcIiwgXCJsaVwiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcclxuXHJcblx0XHRcdFx0XHRpZigkLmNvbnRhaW5zKHRoaXMsIGUucmVsYXRlZFRhcmdldCkpIHtcclxuXHRcdFx0XHRcdFx0Ly8g0L/RgNC10LzQsNGF0L3QsNGC0L4g0LfQsNGA0LDQtNC4IGRlbGVnYXRlIG1vdXNlbGVhdmUg0L/Qvi3QtNC+0LvRg1xyXG5cdFx0XHRcdFx0XHQvLyAkKHRoaXMpLmZpbmQoXCIudmFrYXRhLWNvbnRleHQtaG92ZXJcIikucmVtb3ZlQ2xhc3MoXCJ2YWthdGEtY29udGV4dC1ob3ZlclwiKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdGlmKHRvKSB7IGNsZWFyVGltZW91dCh0byk7IH1cclxuXHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LmVsZW1lbnQuZmluZChcIi52YWthdGEtY29udGV4dC1ob3ZlclwiKS5yZW1vdmVDbGFzcyhcInZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmVuZCgpO1xyXG5cclxuXHRcdFx0XHRcdCQodGhpcylcclxuXHRcdFx0XHRcdFx0LnNpYmxpbmdzKCkuZmluZChcInVsXCIpLmhpZGUoKS5lbmQoKS5lbmQoKVxyXG5cdFx0XHRcdFx0XHQucGFyZW50c1VudGlsKFwiLnZha2F0YS1jb250ZXh0XCIsIFwibGlcIikuYWRkQmFjaygpLmFkZENsYXNzKFwidmFrYXRhLWNvbnRleHQtaG92ZXJcIik7XHJcblx0XHRcdFx0XHQkLnZha2F0YS5jb250ZXh0Ll9zaG93X3N1Ym1lbnUodGhpcyk7XHJcblx0XHRcdFx0fSlcclxuXHRcdFx0XHQvLyDRgtC10YHRgtC+0LLQviAtINC00LDQu9C4INC90LUg0L3QsNGC0L7QstCw0YDQstCwP1xyXG5cdFx0XHRcdC5vbihcIm1vdXNlbGVhdmVcIiwgXCJsaVwiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0aWYoJC5jb250YWlucyh0aGlzLCBlLnJlbGF0ZWRUYXJnZXQpKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdFx0JCh0aGlzKS5maW5kKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmFkZEJhY2soKS5yZW1vdmVDbGFzcyhcInZha2F0YS1jb250ZXh0LWhvdmVyXCIpO1xyXG5cdFx0XHRcdH0pXHJcblx0XHRcdFx0Lm9uKFwibW91c2VsZWF2ZVwiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0JCh0aGlzKS5maW5kKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLnJlbW92ZUNsYXNzKFwidmFrYXRhLWNvbnRleHQtaG92ZXJcIik7XHJcblx0XHRcdFx0XHRpZigkLnZha2F0YS5jb250ZXh0LnNldHRpbmdzLmhpZGVfb25tb3VzZWxlYXZlKSB7XHJcblx0XHRcdFx0XHRcdHRvID0gc2V0VGltZW91dChcclxuXHRcdFx0XHRcdFx0XHQoZnVuY3Rpb24gKHQpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7ICQudmFrYXRhLmNvbnRleHQuaGlkZSgpOyB9O1xyXG5cdFx0XHRcdFx0XHRcdH0odGhpcykpLCAkLnZha2F0YS5jb250ZXh0LnNldHRpbmdzLmhpZGVfb25tb3VzZWxlYXZlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KVxyXG5cdFx0XHRcdC5vbihcImNsaWNrXCIsIFwiYVwiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdH0pXHJcblx0XHRcdFx0Lm9uKFwibW91c2V1cFwiLCBcImFcIiwgZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdGlmKCEkKHRoaXMpLmJsdXIoKS5wYXJlbnQoKS5oYXNDbGFzcyhcInZha2F0YS1jb250ZXh0LWRpc2FibGVkXCIpICYmICQudmFrYXRhLmNvbnRleHQuX2V4ZWN1dGUoJCh0aGlzKS5hdHRyKFwicmVsXCIpKSAhPT0gZmFsc2UpIHtcclxuXHRcdFx0XHRcdFx0JC52YWthdGEuY29udGV4dC5oaWRlKCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSlcclxuXHRcdFx0XHQub24oJ2tleWRvd24nLCAnYScsIGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdHZhciBvID0gbnVsbDtcclxuXHRcdFx0XHRcdFx0c3dpdGNoKGUud2hpY2gpIHtcclxuXHRcdFx0XHRcdFx0XHRjYXNlIDEzOlxyXG5cdFx0XHRcdFx0XHRcdGNhc2UgMzI6XHJcblx0XHRcdFx0XHRcdFx0XHRlLnR5cGUgPSBcIm1vdXNldXBcIjtcclxuXHRcdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdFx0XHRcdCQoZS5jdXJyZW50VGFyZ2V0KS50cmlnZ2VyKGUpO1xyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0Y2FzZSAzNzpcclxuXHRcdFx0XHRcdFx0XHRcdGlmKHZha2F0YV9jb250ZXh0LmlzX3Zpc2libGUpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQuZWxlbWVudC5maW5kKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmxhc3QoKS5wYXJlbnRzKFwibGk6ZXEoMClcIikuZmluZChcInVsXCIpLmhpZGUoKS5maW5kKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLnJlbW92ZUNsYXNzKFwidmFrYXRhLWNvbnRleHQtaG92ZXJcIikuZW5kKCkuZW5kKCkuY2hpbGRyZW4oJ2EnKS5mb2N1cygpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRjYXNlIDM4OlxyXG5cdFx0XHRcdFx0XHRcdFx0aWYodmFrYXRhX2NvbnRleHQuaXNfdmlzaWJsZSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRvID0gdmFrYXRhX2NvbnRleHQuZWxlbWVudC5maW5kKFwidWw6dmlzaWJsZVwiKS5hZGRCYWNrKCkubGFzdCgpLmNoaWxkcmVuKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLnJlbW92ZUNsYXNzKFwidmFrYXRhLWNvbnRleHQtaG92ZXJcIikucHJldkFsbChcImxpOm5vdCgudmFrYXRhLWNvbnRleHQtc2VwYXJhdG9yKVwiKS5maXJzdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZighby5sZW5ndGgpIHsgbyA9IHZha2F0YV9jb250ZXh0LmVsZW1lbnQuZmluZChcInVsOnZpc2libGVcIikuYWRkQmFjaygpLmxhc3QoKS5jaGlsZHJlbihcImxpOm5vdCgudmFrYXRhLWNvbnRleHQtc2VwYXJhdG9yKVwiKS5sYXN0KCk7IH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0by5hZGRDbGFzcyhcInZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmNoaWxkcmVuKCdhJykuZm9jdXMoKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0Y2FzZSAzOTpcclxuXHRcdFx0XHRcdFx0XHRcdGlmKHZha2F0YV9jb250ZXh0LmlzX3Zpc2libGUpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQuZWxlbWVudC5maW5kKFwiLnZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmxhc3QoKS5jaGlsZHJlbihcInVsXCIpLnNob3coKS5jaGlsZHJlbihcImxpOm5vdCgudmFrYXRhLWNvbnRleHQtc2VwYXJhdG9yKVwiKS5yZW1vdmVDbGFzcyhcInZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmZpcnN0KCkuYWRkQ2xhc3MoXCJ2YWthdGEtY29udGV4dC1ob3ZlclwiKS5jaGlsZHJlbignYScpLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdGNhc2UgNDA6XHJcblx0XHRcdFx0XHRcdFx0XHRpZih2YWthdGFfY29udGV4dC5pc192aXNpYmxlKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdG8gPSB2YWthdGFfY29udGV4dC5lbGVtZW50LmZpbmQoXCJ1bDp2aXNpYmxlXCIpLmFkZEJhY2soKS5sYXN0KCkuY2hpbGRyZW4oXCIudmFrYXRhLWNvbnRleHQtaG92ZXJcIikucmVtb3ZlQ2xhc3MoXCJ2YWthdGEtY29udGV4dC1ob3ZlclwiKS5uZXh0QWxsKFwibGk6bm90KC52YWthdGEtY29udGV4dC1zZXBhcmF0b3IpXCIpLmZpcnN0KCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmKCFvLmxlbmd0aCkgeyBvID0gdmFrYXRhX2NvbnRleHQuZWxlbWVudC5maW5kKFwidWw6dmlzaWJsZVwiKS5hZGRCYWNrKCkubGFzdCgpLmNoaWxkcmVuKFwibGk6bm90KC52YWthdGEtY29udGV4dC1zZXBhcmF0b3IpXCIpLmZpcnN0KCk7IH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0by5hZGRDbGFzcyhcInZha2F0YS1jb250ZXh0LWhvdmVyXCIpLmNoaWxkcmVuKCdhJykuZm9jdXMoKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0Y2FzZSAyNzpcclxuXHRcdFx0XHRcdFx0XHRcdCQudmFrYXRhLmNvbnRleHQuaGlkZSgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRcdFx0XHRcdC8vY29uc29sZS5sb2coZS53aGljaCk7XHJcblx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHQub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0dmFyIGEgPSB2YWthdGFfY29udGV4dC5lbGVtZW50LmZpbmQoJy52YWthdGEtY29udGV4dG1lbnUtc2hvcnRjdXQtJyArIGUud2hpY2gpLnBhcmVudCgpO1xyXG5cdFx0XHRcdFx0aWYoYS5wYXJlbnQoKS5ub3QoJy52YWthdGEtY29udGV4dC1kaXNhYmxlZCcpKSB7XHJcblx0XHRcdFx0XHRcdGEubW91c2V1cCgpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pXHJcblx0XHRcdFx0LmFwcGVuZFRvKFwiYm9keVwiKTtcclxuXHJcblx0XHRcdCQoZG9jdW1lbnQpXHJcblx0XHRcdFx0Lm9uKFwibW91c2Vkb3duXCIsIGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRpZih2YWthdGFfY29udGV4dC5pc192aXNpYmxlICYmICEkLmNvbnRhaW5zKHZha2F0YV9jb250ZXh0LmVsZW1lbnRbMF0sIGUudGFyZ2V0KSkgeyAkLnZha2F0YS5jb250ZXh0LmhpZGUoKTsgfVxyXG5cdFx0XHRcdH0pXHJcblx0XHRcdFx0Lm9uKFwiY29udGV4dF9zaG93LnZha2F0YVwiLCBmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0dmFrYXRhX2NvbnRleHQuZWxlbWVudC5maW5kKFwibGk6aGFzKHVsKVwiKS5jaGlsZHJlbihcImFcIikuYWRkQ2xhc3MoXCJ2YWthdGEtY29udGV4dC1wYXJlbnRcIik7XHJcblx0XHRcdFx0XHRpZihyaWdodF90b19sZWZ0KSB7XHJcblx0XHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LmVsZW1lbnQuYWRkQ2xhc3MoXCJ2YWthdGEtY29udGV4dC1ydGxcIikuY3NzKFwiZGlyZWN0aW9uXCIsIFwicnRsXCIpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Ly8gYWxzbyBhcHBseSBhIFJUTCBjbGFzcz9cclxuXHRcdFx0XHRcdHZha2F0YV9jb250ZXh0LmVsZW1lbnQuZmluZChcInVsXCIpLmhpZGUoKS5lbmQoKTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH0oJCkpO1xyXG5cdC8vICQuanN0cmVlLmRlZmF1bHRzLnBsdWdpbnMucHVzaChcImNvbnRleHRtZW51XCIpO1xyXG5cclxuLyoqXHJcbiAqICMjIyBEcmFnJ24nZHJvcCBwbHVnaW5cclxuICpcclxuICogRW5hYmxlcyBkcmFnZ2luZyBhbmQgZHJvcHBpbmcgb2Ygbm9kZXMgaW4gdGhlIHRyZWUsIHJlc3VsdGluZyBpbiBhIG1vdmUgb3IgY29weSBvcGVyYXRpb25zLlxyXG4gKi9cclxuXHJcblx0LyoqXHJcblx0ICogc3RvcmVzIGFsbCBkZWZhdWx0cyBmb3IgdGhlIGRyYWcnbidkcm9wIHBsdWdpblxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmRuZFxyXG5cdCAqIEBwbHVnaW4gZG5kXHJcblx0ICovXHJcblx0JC5qc3RyZWUuZGVmYXVsdHMuZG5kID0ge1xyXG5cdFx0LyoqXHJcblx0XHQgKiBhIGJvb2xlYW4gaW5kaWNhdGluZyBpZiBhIGNvcHkgc2hvdWxkIGJlIHBvc3NpYmxlIHdoaWxlIGRyYWdnaW5nIChieSBwcmVzc2ludCB0aGUgbWV0YSBrZXkgb3IgQ3RybCkuIERlZmF1bHRzIHRvIGB0cnVlYC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLmRuZC5jb3B5XHJcblx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0ICovXHJcblx0XHRjb3B5IDogdHJ1ZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogYSBudW1iZXIgaW5kaWNhdGluZyBob3cgbG9uZyBhIG5vZGUgc2hvdWxkIHJlbWFpbiBob3ZlcmVkIHdoaWxlIGRyYWdnaW5nIHRvIGJlIG9wZW5lZC4gRGVmYXVsdHMgdG8gYDUwMGAuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5kbmQub3Blbl90aW1lb3V0XHJcblx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0ICovXHJcblx0XHRvcGVuX3RpbWVvdXQgOiA1MDAsXHJcblx0XHQvKipcclxuXHRcdCAqIGEgZnVuY3Rpb24gaW52b2tlZCBlYWNoIHRpbWUgYSBub2RlIGlzIGFib3V0IHRvIGJlIGRyYWdnZWQsIGludm9rZWQgaW4gdGhlIHRyZWUncyBzY29wZSBhbmQgcmVjZWl2ZXMgdGhlIG5vZGUgYXMgYW4gYXJndW1lbnQgLSByZXR1cm4gYGZhbHNlYCB0byBwcmV2ZW50IGRyYWdnaW5nXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5kbmQuaXNfZHJhZ2dhYmxlXHJcblx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0ICovXHJcblx0XHRpc19kcmFnZ2FibGUgOiB0cnVlLFxyXG5cdFx0LyoqXHJcblx0XHQgKiBhIGJvb2xlYW4gaW5kaWNhdGluZyBpZiBjaGVja3Mgc2hvdWxkIGNvbnN0YW50bHkgYmUgbWFkZSB3aGlsZSB0aGUgdXNlciBpcyBkcmFnZ2luZyB0aGUgbm9kZSAoYXMgb3Bwb3NlZCB0byBjaGVja2luZyBvbmx5IG9uIGRyb3ApLCBkZWZhdWx0IGlzIGB0cnVlYFxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuZG5kLmNoZWNrX3doaWxlX2RyYWdnaW5nXHJcblx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0ICovXHJcblx0XHRjaGVja193aGlsZV9kcmFnZ2luZyA6IHRydWVcclxuXHR9O1xyXG5cdC8vIFRPRE86IG5vdyBjaGVjayB3b3JrcyBieSBjaGVja2luZyBmb3IgZWFjaCBub2RlIGluZGl2aWR1YWxseSwgaG93IGFib3V0IG1heF9jaGlsZHJlbiwgdW5pcXVlLCBldGM/XHJcblx0Ly8gVE9ETzogZHJvcCBzb21ld2hlcmUgZWxzZSAtIG1heWJlIGRlbW8gb25seT9cclxuXHQkLmpzdHJlZS5wbHVnaW5zLmRuZCA9IGZ1bmN0aW9uIChvcHRpb25zLCBwYXJlbnQpIHtcclxuXHRcdHRoaXMuYmluZCA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0cGFyZW50LmJpbmQuY2FsbCh0aGlzKTtcclxuXHJcblx0XHRcdHRoaXMuZWxlbWVudFxyXG5cdFx0XHRcdC5vbignbW91c2Vkb3duIHRvdWNoc3RhcnQnLCAnLmpzdHJlZS1hbmNob3InLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHR2YXIgb2JqID0gdGhpcy5nZXRfbm9kZShlLnRhcmdldCksXHJcblx0XHRcdFx0XHRcdG1sdCA9IHRoaXMuaXNfc2VsZWN0ZWQob2JqKSA/IHRoaXMuZ2V0X3NlbGVjdGVkKCkubGVuZ3RoIDogMTtcclxuXHRcdFx0XHRcdGlmKG9iaiAmJiBvYmouaWQgJiYgb2JqLmlkICE9PSBcIiNcIiAmJiAoZS53aGljaCA9PT0gMSB8fCBlLnR5cGUgPT09IFwidG91Y2hzdGFydFwiKSAmJlxyXG5cdFx0XHRcdFx0XHQodGhpcy5zZXR0aW5ncy5kbmQuaXNfZHJhZ2dhYmxlID09PSB0cnVlIHx8ICgkLmlzRnVuY3Rpb24odGhpcy5zZXR0aW5ncy5kbmQuaXNfZHJhZ2dhYmxlKSAmJiB0aGlzLnNldHRpbmdzLmRuZC5pc19kcmFnZ2FibGUuY2FsbCh0aGlzLCBvYmopKSlcclxuXHRcdFx0XHRcdCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmVsZW1lbnQudHJpZ2dlcignbW91c2Vkb3duLmpzdHJlZScpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gJC52YWthdGEuZG5kLnN0YXJ0KGUsIHsgJ2pzdHJlZScgOiB0cnVlLCAnb3JpZ2luJyA6IHRoaXMsICdvYmonIDogdGhpcy5nZXRfbm9kZShvYmosdHJ1ZSksICdub2RlcycgOiBtbHQgPiAxID8gdGhpcy5nZXRfc2VsZWN0ZWQoKSA6IFtvYmouaWRdIH0sICc8ZGl2IGlkPVwianN0cmVlLWRuZFwiIGNsYXNzPVwianN0cmVlLScgKyB0aGlzLmdldF90aGVtZSgpICsgJ1wiPjxpIGNsYXNzPVwianN0cmVlLWljb24ganN0cmVlLWVyXCI+PC9pPicgKyAobWx0ID4gMSA/IG1sdCArICcgJyArIHRoaXMuZ2V0X3N0cmluZygnbm9kZXMnKSA6IHRoaXMuZ2V0X3RleHQoZS5jdXJyZW50VGFyZ2V0LCB0cnVlKSkgKyAnPGlucyBjbGFzcz1cImpzdHJlZS1jb3B5XCIgc3R5bGU9XCJkaXNwbGF5Om5vbmU7XCI+KzwvaW5zPjwvZGl2PicpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdH07XHJcblx0fTtcclxuXHJcblx0JChmdW5jdGlvbigpIHtcclxuXHRcdC8vIGJpbmQgb25seSBvbmNlIGZvciBhbGwgaW5zdGFuY2VzXHJcblx0XHR2YXIgbGFzdG12ID0gZmFsc2UsXHJcblx0XHRcdGxhc3RlciA9IGZhbHNlLFxyXG5cdFx0XHRvcGVudG8gPSBmYWxzZSxcclxuXHRcdFx0bWFya2VyID0gJCgnPGRpdiBpZD1cImpzdHJlZS1tYXJrZXJcIj4mIzE2MDs8L2Rpdj4nKS5oaWRlKCkuYXBwZW5kVG8oJ2JvZHknKTtcclxuXHJcblx0XHQkKGRvY3VtZW50KVxyXG5cdFx0XHQuYmluZCgnZG5kX3N0YXJ0LnZha2F0YScsIGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0bGFzdG12ID0gZmFsc2U7XHJcblx0XHRcdH0pXHJcblx0XHRcdC5iaW5kKCdkbmRfbW92ZS52YWthdGEnLCBmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdGlmKG9wZW50bykgeyBjbGVhclRpbWVvdXQob3BlbnRvKTsgfVxyXG5cdFx0XHRcdGlmKCFkYXRhLmRhdGEuanN0cmVlKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdFx0XHQvLyBpZiB3ZSBhcmUgaG92ZXJpbmcgdGhlIG1hcmtlciBpbWFnZSBkbyBub3RoaW5nIChjYW4gaGFwcGVuIG9uIFwiaW5zaWRlXCIgZHJhZ3MpXHJcblx0XHRcdFx0aWYoZGF0YS5ldmVudC50YXJnZXQuaWQgJiYgZGF0YS5ldmVudC50YXJnZXQuaWQgPT09ICdqc3RyZWUtbWFya2VyJykge1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0dmFyIGlucyA9ICQuanN0cmVlLnJlZmVyZW5jZShkYXRhLmV2ZW50LnRhcmdldCksXHJcblx0XHRcdFx0XHRyZWYgPSBmYWxzZSxcclxuXHRcdFx0XHRcdG9mZiA9IGZhbHNlLFxyXG5cdFx0XHRcdFx0cmVsID0gZmFsc2UsXHJcblx0XHRcdFx0XHRsLCB0LCBoLCBwLCBpLCBvLCBvaywgdDEsIHQyLCBvcCwgcHMsIHByO1xyXG5cdFx0XHRcdC8vIGlmIHdlIGFyZSBvdmVyIGFuIGluc3RhbmNlXHJcblx0XHRcdFx0aWYoaW5zICYmIGlucy5fZGF0YSAmJiBpbnMuX2RhdGEuZG5kKSB7XHJcblx0XHRcdFx0XHRtYXJrZXIuYXR0cignY2xhc3MnLCAnanN0cmVlLScgKyBpbnMuZ2V0X3RoZW1lKCkpO1xyXG5cdFx0XHRcdFx0ZGF0YS5oZWxwZXJcclxuXHRcdFx0XHRcdFx0LmNoaWxkcmVuKCkuYXR0cignY2xhc3MnLCAnanN0cmVlLScgKyBpbnMuZ2V0X3RoZW1lKCkpXHJcblx0XHRcdFx0XHRcdC5maW5kKCcuanN0cmVlLWNvcHk6ZXEoMCknKVsgZGF0YS5kYXRhLm9yaWdpbiAmJiBkYXRhLmRhdGEub3JpZ2luLnNldHRpbmdzLmRuZC5jb3B5ICYmIChkYXRhLmV2ZW50Lm1ldGFLZXkgfHwgZGF0YS5ldmVudC5jdHJsS2V5KSA/ICdzaG93JyA6ICdoaWRlJyBdKCk7XHJcblxyXG5cclxuXHRcdFx0XHRcdC8vIGlmIGFyZSBob3ZlcmluZyB0aGUgY29udGFpbmVyIGl0c2VsZiBhZGQgYSBuZXcgcm9vdCBub2RlXHJcblx0XHRcdFx0XHRpZiggKGRhdGEuZXZlbnQudGFyZ2V0ID09PSBpbnMuZWxlbWVudFswXSB8fCBkYXRhLmV2ZW50LnRhcmdldCA9PT0gaW5zLmdldF9jb250YWluZXJfdWwoKVswXSkgJiYgaW5zLmdldF9jb250YWluZXJfdWwoKS5jaGlsZHJlbigpLmxlbmd0aCA9PT0gMCkge1xyXG5cdFx0XHRcdFx0XHRvayA9IHRydWU7XHJcblx0XHRcdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gZGF0YS5kYXRhLm5vZGVzLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0XHRcdG9rID0gb2sgJiYgaW5zLmNoZWNrKCAoZGF0YS5kYXRhLm9yaWdpbiAmJiBkYXRhLmRhdGEub3JpZ2luLnNldHRpbmdzLmRuZC5jb3B5ICYmIChkYXRhLmV2ZW50Lm1ldGFLZXkgfHwgZGF0YS5ldmVudC5jdHJsS2V5KSA/IFwiY29weV9ub2RlXCIgOiBcIm1vdmVfbm9kZVwiKSwgKGRhdGEuZGF0YS5vcmlnaW4gJiYgZGF0YS5kYXRhLm9yaWdpbiAhPT0gaW5zID8gZGF0YS5kYXRhLm9yaWdpbi5nZXRfbm9kZShkYXRhLmRhdGEubm9kZXNbdDFdKSA6IGRhdGEuZGF0YS5ub2Rlc1t0MV0pLCAnIycsICdsYXN0Jyk7XHJcblx0XHRcdFx0XHRcdFx0aWYoIW9rKSB7IGJyZWFrOyB9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYob2spIHtcclxuXHRcdFx0XHRcdFx0XHRsYXN0bXYgPSB7ICdpbnMnIDogaW5zLCAncGFyJyA6ICcjJywgJ3BvcycgOiAnbGFzdCcgfTtcclxuXHRcdFx0XHRcdFx0XHRtYXJrZXIuaGlkZSgpO1xyXG5cdFx0XHRcdFx0XHRcdGRhdGEuaGVscGVyLmZpbmQoJy5qc3RyZWUtaWNvbjplcSgwKScpLnJlbW92ZUNsYXNzKCdqc3RyZWUtZXInKS5hZGRDbGFzcygnanN0cmVlLW9rJyk7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0Ly8gaWYgd2UgYXJlIGhvdmVyaW5nIGEgdHJlZSBub2RlXHJcblx0XHRcdFx0XHRcdHJlZiA9ICQoZGF0YS5ldmVudC50YXJnZXQpLmNsb3Nlc3QoJ2EnKTtcclxuXHRcdFx0XHRcdFx0aWYocmVmICYmIHJlZi5sZW5ndGggJiYgcmVmLnBhcmVudCgpLmlzKCcuanN0cmVlLWNsb3NlZCwgLmpzdHJlZS1vcGVuLCAuanN0cmVlLWxlYWYnKSkge1xyXG5cdFx0XHRcdFx0XHRcdG9mZiA9IHJlZi5vZmZzZXQoKTtcclxuXHRcdFx0XHRcdFx0XHRyZWwgPSBkYXRhLmV2ZW50LnBhZ2VZIC0gb2ZmLnRvcDtcclxuXHRcdFx0XHRcdFx0XHRoID0gcmVmLmhlaWdodCgpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKHJlbCA8IGggLyAzKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRvID0gWydiJywgJ2knLCAnYSddO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRlbHNlIGlmKHJlbCA+IGggLSBoIC8gMykge1xyXG5cdFx0XHRcdFx0XHRcdFx0byA9IFsnYScsICdpJywgJ2InXTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHRvID0gcmVsID4gaCAvIDIgPyBbJ2knLCAnYScsICdiJ10gOiBbJ2knLCAnYicsICdhJ107XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdCQuZWFjaChvLCBmdW5jdGlvbiAoaiwgdikge1xyXG5cdFx0XHRcdFx0XHRcdFx0c3dpdGNoKHYpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0Y2FzZSAnYic6XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0bCA9IG9mZi5sZWZ0IC0gNjtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0ID0gb2ZmLnRvcCAtIDU7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0cCA9IGlucy5nZXRfcGFyZW50KHJlZik7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aSA9IHJlZi5wYXJlbnQoKS5pbmRleCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdpJzpcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRsID0gb2ZmLmxlZnQgLSAyO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHQgPSBvZmYudG9wIC0gNSArIGggLyAyICsgMTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRwID0gcmVmLnBhcmVudCgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGkgPSAwO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjYXNlICdhJzpcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRsID0gb2ZmLmxlZnQgLSA2O1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHQgPSBvZmYudG9wIC0gNSArIGg7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0cCA9IGlucy5nZXRfcGFyZW50KHJlZik7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aSA9IHJlZi5wYXJlbnQoKS5pbmRleCgpICsgMTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdC8qIVxyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gVE9ETzogbW92aW5nIGluc2lkZSwgYnV0IHRoZSBub2RlIGlzIG5vdCB5ZXQgbG9hZGVkP1xyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gdGhlIGNoZWNrIHdpbGwgd29yayBhbnl3YXksIGFzIHdoZW4gbW92aW5nIHRoZSBub2RlIHdpbGwgYmUgbG9hZGVkIGZpcnN0IGFuZCBjaGVja2VkIGFnYWluXHJcblx0XHRcdFx0XHRcdFx0XHRpZih2ID09PSAnaScgJiYgIWlucy5pc19sb2FkZWQocCkpIHsgfVxyXG5cdFx0XHRcdFx0XHRcdFx0Ki9cclxuXHRcdFx0XHRcdFx0XHRcdG9rID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGZvcih0MSA9IDAsIHQyID0gZGF0YS5kYXRhLm5vZGVzLmxlbmd0aDsgdDEgPCB0MjsgdDErKykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRvcCA9IGRhdGEuZGF0YS5vcmlnaW4gJiYgZGF0YS5kYXRhLm9yaWdpbi5zZXR0aW5ncy5kbmQuY29weSAmJiAoZGF0YS5ldmVudC5tZXRhS2V5IHx8IGRhdGEuZXZlbnQuY3RybEtleSkgPyBcImNvcHlfbm9kZVwiIDogXCJtb3ZlX25vZGVcIjtcclxuXHRcdFx0XHRcdFx0XHRcdFx0cHMgPSBpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZihvcCA9PT0gXCJtb3ZlX25vZGVcIiAmJiB2ID09PSAnYScgJiYgKGRhdGEuZGF0YS5vcmlnaW4gJiYgZGF0YS5kYXRhLm9yaWdpbiA9PT0gaW5zKSAmJiBwID09PSBpbnMuZ2V0X3BhcmVudChkYXRhLmRhdGEubm9kZXNbdDFdKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHByID0gaW5zLmdldF9ub2RlKHApO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmKHBzID4gJC5pbkFycmF5KGRhdGEuZGF0YS5ub2Rlc1t0MV0sIHByLmNoaWxkcmVuKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0cHMgLT0gMTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0b2sgPSBvayAmJiAoIChpbnMgJiYgaW5zLnNldHRpbmdzICYmIGlucy5zZXR0aW5ncy5kbmQgJiYgaW5zLnNldHRpbmdzLmRuZC5jaGVja193aGlsZV9kcmFnZ2luZyA9PT0gZmFsc2UpIHx8IGlucy5jaGVjayhvcCwgKGRhdGEuZGF0YS5vcmlnaW4gJiYgZGF0YS5kYXRhLm9yaWdpbiAhPT0gaW5zID8gZGF0YS5kYXRhLm9yaWdpbi5nZXRfbm9kZShkYXRhLmRhdGEubm9kZXNbdDFdKSA6IGRhdGEuZGF0YS5ub2Rlc1t0MV0pLCBwLCBwcykgKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYoIW9rKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYoaW5zICYmIGlucy5sYXN0X2Vycm9yKSB7IGxhc3RlciA9IGlucy5sYXN0X2Vycm9yKCk7IH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0aWYob2spIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYodiA9PT0gJ2knICYmIHJlZi5wYXJlbnQoKS5pcygnLmpzdHJlZS1jbG9zZWQnKSAmJiBpbnMuc2V0dGluZ3MuZG5kLm9wZW5fdGltZW91dCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdG9wZW50byA9IHNldFRpbWVvdXQoKGZ1bmN0aW9uICh4LCB6KSB7IHJldHVybiBmdW5jdGlvbiAoKSB7IHgub3Blbl9ub2RlKHopOyB9OyB9KGlucywgcmVmKSksIGlucy5zZXR0aW5ncy5kbmQub3Blbl90aW1lb3V0KTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRsYXN0bXYgPSB7ICdpbnMnIDogaW5zLCAncGFyJyA6IHAsICdwb3MnIDogaSB9O1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRtYXJrZXIuY3NzKHsgJ2xlZnQnIDogbCArICdweCcsICd0b3AnIDogdCArICdweCcgfSkuc2hvdygpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRkYXRhLmhlbHBlci5maW5kKCcuanN0cmVlLWljb246ZXEoMCknKS5yZW1vdmVDbGFzcygnanN0cmVlLWVyJykuYWRkQ2xhc3MoJ2pzdHJlZS1vaycpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRsYXN0ZXIgPSB7fTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0byA9IHRydWU7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdFx0XHRpZihvID09PSB0cnVlKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGxhc3RtdiA9IGZhbHNlO1xyXG5cdFx0XHRcdGRhdGEuaGVscGVyLmZpbmQoJy5qc3RyZWUtaWNvbicpLnJlbW92ZUNsYXNzKCdqc3RyZWUtb2snKS5hZGRDbGFzcygnanN0cmVlLWVyJyk7XHJcblx0XHRcdFx0bWFya2VyLmhpZGUoKTtcclxuXHRcdFx0fSlcclxuXHRcdFx0LmJpbmQoJ2RuZF9zY3JvbGwudmFrYXRhJywgZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuXHRcdFx0XHRpZighZGF0YS5kYXRhLmpzdHJlZSkgeyByZXR1cm47IH1cclxuXHRcdFx0XHRtYXJrZXIuaGlkZSgpO1xyXG5cdFx0XHRcdGxhc3RtdiA9IGZhbHNlO1xyXG5cdFx0XHRcdGRhdGEuaGVscGVyLmZpbmQoJy5qc3RyZWUtaWNvbjplcSgwKScpLnJlbW92ZUNsYXNzKCdqc3RyZWUtb2snKS5hZGRDbGFzcygnanN0cmVlLWVyJyk7XHJcblx0XHRcdH0pXHJcblx0XHRcdC5iaW5kKCdkbmRfc3RvcC52YWthdGEnLCBmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdGlmKG9wZW50bykgeyBjbGVhclRpbWVvdXQob3BlbnRvKTsgfVxyXG5cdFx0XHRcdGlmKCFkYXRhLmRhdGEuanN0cmVlKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdG1hcmtlci5oaWRlKCk7XHJcblx0XHRcdFx0dmFyIGksIGosIG5vZGVzID0gW107XHJcblx0XHRcdFx0aWYobGFzdG12KSB7XHJcblx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBkYXRhLmRhdGEubm9kZXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdG5vZGVzW2ldID0gZGF0YS5kYXRhLm9yaWdpbiA/IGRhdGEuZGF0YS5vcmlnaW4uZ2V0X25vZGUoZGF0YS5kYXRhLm5vZGVzW2ldKSA6IGRhdGEuZGF0YS5ub2Rlc1tpXTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGxhc3Rtdi5pbnNbIGRhdGEuZGF0YS5vcmlnaW4gJiYgZGF0YS5kYXRhLm9yaWdpbi5zZXR0aW5ncy5kbmQuY29weSAmJiAoZGF0YS5ldmVudC5tZXRhS2V5IHx8IGRhdGEuZXZlbnQuY3RybEtleSkgPyAnY29weV9ub2RlJyA6ICdtb3ZlX25vZGUnIF0obm9kZXMsIGxhc3Rtdi5wYXIsIGxhc3Rtdi5wb3MpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdGkgPSAkKGRhdGEuZXZlbnQudGFyZ2V0KS5jbG9zZXN0KCcuanN0cmVlJyk7XHJcblx0XHRcdFx0XHRpZihpLmxlbmd0aCAmJiBsYXN0ZXIgJiYgbGFzdGVyLmVycm9yICYmIGxhc3Rlci5lcnJvciA9PT0gJ2NoZWNrJykge1xyXG5cdFx0XHRcdFx0XHRpID0gaS5qc3RyZWUodHJ1ZSk7XHJcblx0XHRcdFx0XHRcdGlmKGkpIHtcclxuXHRcdFx0XHRcdFx0XHRpLnNldHRpbmdzLmNvcmUuZXJyb3IuY2FsbCh0aGlzLCBsYXN0ZXIpO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9KVxyXG5cdFx0XHQuYmluZCgna2V5dXAga2V5ZG93bicsIGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0ZGF0YSA9ICQudmFrYXRhLmRuZC5fZ2V0KCk7XHJcblx0XHRcdFx0aWYoZGF0YS5kYXRhICYmIGRhdGEuZGF0YS5qc3RyZWUpIHtcclxuXHRcdFx0XHRcdGRhdGEuaGVscGVyLmZpbmQoJy5qc3RyZWUtY29weTplcSgwKScpWyBkYXRhLmRhdGEub3JpZ2luICYmIGRhdGEuZGF0YS5vcmlnaW4uc2V0dGluZ3MuZG5kLmNvcHkgJiYgKGUubWV0YUtleSB8fCBlLmN0cmxLZXkpID8gJ3Nob3cnIDogJ2hpZGUnIF0oKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdH0pO1xyXG5cclxuXHQvLyBoZWxwZXJzXHJcblx0KGZ1bmN0aW9uICgkKSB7XHJcblx0XHQkLmZuLnZha2F0YV9yZXZlcnNlID0gW10ucmV2ZXJzZTtcclxuXHRcdC8vIHByaXZhdGUgdmFyaWFibGVcclxuXHRcdHZhciB2YWthdGFfZG5kID0ge1xyXG5cdFx0XHRlbGVtZW50XHQ6IGZhbHNlLFxyXG5cdFx0XHRpc19kb3duXHQ6IGZhbHNlLFxyXG5cdFx0XHRpc19kcmFnXHQ6IGZhbHNlLFxyXG5cdFx0XHRoZWxwZXJcdDogZmFsc2UsXHJcblx0XHRcdGhlbHBlcl93OiAwLFxyXG5cdFx0XHRkYXRhXHQ6IGZhbHNlLFxyXG5cdFx0XHRpbml0X3hcdDogMCxcclxuXHRcdFx0aW5pdF95XHQ6IDAsXHJcblx0XHRcdHNjcm9sbF9sOiAwLFxyXG5cdFx0XHRzY3JvbGxfdDogMCxcclxuXHRcdFx0c2Nyb2xsX2U6IGZhbHNlLFxyXG5cdFx0XHRzY3JvbGxfaTogZmFsc2VcclxuXHRcdH07XHJcblx0XHQkLnZha2F0YS5kbmQgPSB7XHJcblx0XHRcdHNldHRpbmdzIDoge1xyXG5cdFx0XHRcdHNjcm9sbF9zcGVlZFx0XHQ6IDEwLFxyXG5cdFx0XHRcdHNjcm9sbF9wcm94aW1pdHlcdDogMjAsXHJcblx0XHRcdFx0aGVscGVyX2xlZnRcdFx0XHQ6IDUsXHJcblx0XHRcdFx0aGVscGVyX3RvcFx0XHRcdDogMTAsXHJcblx0XHRcdFx0dGhyZXNob2xkXHRcdFx0OiA1XHJcblx0XHRcdH0sXHJcblx0XHRcdF90cmlnZ2VyIDogZnVuY3Rpb24gKGV2ZW50X25hbWUsIGUpIHtcclxuXHRcdFx0XHR2YXIgZGF0YSA9ICQudmFrYXRhLmRuZC5fZ2V0KCk7XHJcblx0XHRcdFx0ZGF0YS5ldmVudCA9IGU7XHJcblx0XHRcdFx0JChkb2N1bWVudCkudHJpZ2dlckhhbmRsZXIoXCJkbmRfXCIgKyBldmVudF9uYW1lICsgXCIudmFrYXRhXCIsIGRhdGEpO1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRfZ2V0IDogZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdHJldHVybiB7XHJcblx0XHRcdFx0XHRcImRhdGFcIlx0XHQ6IHZha2F0YV9kbmQuZGF0YSxcclxuXHRcdFx0XHRcdFwiZWxlbWVudFwiXHQ6IHZha2F0YV9kbmQuZWxlbWVudCxcclxuXHRcdFx0XHRcdFwiaGVscGVyXCJcdDogdmFrYXRhX2RuZC5oZWxwZXJcclxuXHRcdFx0XHR9O1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRfY2xlYW4gOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0aWYodmFrYXRhX2RuZC5oZWxwZXIpIHsgdmFrYXRhX2RuZC5oZWxwZXIucmVtb3ZlKCk7IH1cclxuXHRcdFx0XHRpZih2YWthdGFfZG5kLnNjcm9sbF9pKSB7IGNsZWFySW50ZXJ2YWwodmFrYXRhX2RuZC5zY3JvbGxfaSk7IHZha2F0YV9kbmQuc2Nyb2xsX2kgPSBmYWxzZTsgfVxyXG5cdFx0XHRcdHZha2F0YV9kbmQgPSB7XHJcblx0XHRcdFx0XHRlbGVtZW50XHQ6IGZhbHNlLFxyXG5cdFx0XHRcdFx0aXNfZG93blx0OiBmYWxzZSxcclxuXHRcdFx0XHRcdGlzX2RyYWdcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRoZWxwZXJcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRoZWxwZXJfdzogMCxcclxuXHRcdFx0XHRcdGRhdGFcdDogZmFsc2UsXHJcblx0XHRcdFx0XHRpbml0X3hcdDogMCxcclxuXHRcdFx0XHRcdGluaXRfeVx0OiAwLFxyXG5cdFx0XHRcdFx0c2Nyb2xsX2w6IDAsXHJcblx0XHRcdFx0XHRzY3JvbGxfdDogMCxcclxuXHRcdFx0XHRcdHNjcm9sbF9lOiBmYWxzZSxcclxuXHRcdFx0XHRcdHNjcm9sbF9pOiBmYWxzZVxyXG5cdFx0XHRcdH07XHJcblx0XHRcdFx0JChkb2N1bWVudCkub2ZmKFwibW91c2Vtb3ZlIHRvdWNobW92ZVwiLCAkLnZha2F0YS5kbmQuZHJhZyk7XHJcblx0XHRcdFx0JChkb2N1bWVudCkub2ZmKFwibW91c2V1cCB0b3VjaGVuZFwiLCAkLnZha2F0YS5kbmQuc3RvcCk7XHJcblx0XHRcdH0sXHJcblx0XHRcdF9zY3JvbGwgOiBmdW5jdGlvbiAoaW5pdF9vbmx5KSB7XHJcblx0XHRcdFx0aWYoIXZha2F0YV9kbmQuc2Nyb2xsX2UgfHwgKCF2YWthdGFfZG5kLnNjcm9sbF9sICYmICF2YWthdGFfZG5kLnNjcm9sbF90KSkge1xyXG5cdFx0XHRcdFx0aWYodmFrYXRhX2RuZC5zY3JvbGxfaSkgeyBjbGVhckludGVydmFsKHZha2F0YV9kbmQuc2Nyb2xsX2kpOyB2YWthdGFfZG5kLnNjcm9sbF9pID0gZmFsc2U7IH1cclxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoIXZha2F0YV9kbmQuc2Nyb2xsX2kpIHtcclxuXHRcdFx0XHRcdHZha2F0YV9kbmQuc2Nyb2xsX2kgPSBzZXRJbnRlcnZhbCgkLnZha2F0YS5kbmQuX3Njcm9sbCwgMTAwKTtcclxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYoaW5pdF9vbmx5ID09PSB0cnVlKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuXHRcdFx0XHR2YXIgaSA9IHZha2F0YV9kbmQuc2Nyb2xsX2Uuc2Nyb2xsVG9wKCksXHJcblx0XHRcdFx0XHRqID0gdmFrYXRhX2RuZC5zY3JvbGxfZS5zY3JvbGxMZWZ0KCk7XHJcblx0XHRcdFx0dmFrYXRhX2RuZC5zY3JvbGxfZS5zY3JvbGxUb3AoaSArIHZha2F0YV9kbmQuc2Nyb2xsX3QgKiAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3NwZWVkKTtcclxuXHRcdFx0XHR2YWthdGFfZG5kLnNjcm9sbF9lLnNjcm9sbExlZnQoaiArIHZha2F0YV9kbmQuc2Nyb2xsX2wgKiAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3NwZWVkKTtcclxuXHRcdFx0XHRpZihpICE9PSB2YWthdGFfZG5kLnNjcm9sbF9lLnNjcm9sbFRvcCgpIHx8IGogIT09IHZha2F0YV9kbmQuc2Nyb2xsX2Uuc2Nyb2xsTGVmdCgpKSB7XHJcblx0XHRcdFx0XHQvKipcclxuXHRcdFx0XHRcdCAqIHRyaWdnZXJlZCBvbiB0aGUgZG9jdW1lbnQgd2hlbiBhIGRyYWcgY2F1c2VzIGFuIGVsZW1lbnQgdG8gc2Nyb2xsXHJcblx0XHRcdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0XHRcdCAqIEBwbHVnaW4gZG5kXHJcblx0XHRcdFx0XHQgKiBAbmFtZSBkbmRfc2Nyb2xsLnZha2F0YVxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtNaXhlZH0gZGF0YSBhbnkgZGF0YSBzdXBwbGllZCB3aXRoIHRoZSBjYWxsIHRvICQudmFrYXRhLmRuZC5zdGFydFxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtET019IGVsZW1lbnQgdGhlIERPTSBlbGVtZW50IGJlaW5nIGRyYWdnZWRcclxuXHRcdFx0XHRcdCAqIEBwYXJhbSB7alF1ZXJ5fSBoZWxwZXIgdGhlIGhlbHBlciBzaG93biBuZXh0IHRvIHRoZSBtb3VzZVxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtqUXVlcnl9IGV2ZW50IHRoZSBlbGVtZW50IHRoYXQgaXMgc2Nyb2xsaW5nXHJcblx0XHRcdFx0XHQgKi9cclxuXHRcdFx0XHRcdCQudmFrYXRhLmRuZC5fdHJpZ2dlcihcInNjcm9sbFwiLCB2YWthdGFfZG5kLnNjcm9sbF9lKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0sXHJcblx0XHRcdHN0YXJ0IDogZnVuY3Rpb24gKGUsIGRhdGEsIGh0bWwpIHtcclxuXHRcdFx0XHRpZihlLnR5cGUgPT09IFwidG91Y2hzdGFydFwiICYmIGUub3JpZ2luYWxFdmVudCAmJiBlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXMgJiYgZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdKSB7XHJcblx0XHRcdFx0XHRlLnBhZ2VYID0gZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYO1xyXG5cdFx0XHRcdFx0ZS5wYWdlWSA9IGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXS5wYWdlWTtcclxuXHRcdFx0XHRcdGUudGFyZ2V0ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVggLSB3aW5kb3cucGFnZVhPZmZzZXQsIGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXS5wYWdlWSAtIHdpbmRvdy5wYWdlWU9mZnNldCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmKHZha2F0YV9kbmQuaXNfZHJhZykgeyAkLnZha2F0YS5kbmQuc3RvcCh7fSk7IH1cclxuXHRcdFx0XHR0cnkge1xyXG5cdFx0XHRcdFx0ZS5jdXJyZW50VGFyZ2V0LnVuc2VsZWN0YWJsZSA9IFwib25cIjtcclxuXHRcdFx0XHRcdGUuY3VycmVudFRhcmdldC5vbnNlbGVjdHN0YXJ0ID0gZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZTsgfTtcclxuXHRcdFx0XHRcdGlmKGUuY3VycmVudFRhcmdldC5zdHlsZSkgeyBlLmN1cnJlbnRUYXJnZXQuc3R5bGUuTW96VXNlclNlbGVjdCA9IFwibm9uZVwiOyB9XHJcblx0XHRcdFx0fSBjYXRjaChpZ25vcmUpIHsgfVxyXG5cdFx0XHRcdHZha2F0YV9kbmQuaW5pdF94XHQ9IGUucGFnZVg7XHJcblx0XHRcdFx0dmFrYXRhX2RuZC5pbml0X3lcdD0gZS5wYWdlWTtcclxuXHRcdFx0XHR2YWthdGFfZG5kLmRhdGFcdFx0PSBkYXRhO1xyXG5cdFx0XHRcdHZha2F0YV9kbmQuaXNfZG93blx0PSB0cnVlO1xyXG5cdFx0XHRcdHZha2F0YV9kbmQuZWxlbWVudFx0PSBlLmN1cnJlbnRUYXJnZXQ7XHJcblx0XHRcdFx0aWYoaHRtbCAhPT0gZmFsc2UpIHtcclxuXHRcdFx0XHRcdHZha2F0YV9kbmQuaGVscGVyID0gJChcIjxkaXYgaWQ9J3Zha2F0YS1kbmQnPjwvZGl2PlwiKS5odG1sKGh0bWwpLmNzcyh7XHJcblx0XHRcdFx0XHRcdFwiZGlzcGxheVwiXHRcdDogXCJibG9ja1wiLFxyXG5cdFx0XHRcdFx0XHRcIm1hcmdpblwiXHRcdDogXCIwXCIsXHJcblx0XHRcdFx0XHRcdFwicGFkZGluZ1wiXHRcdDogXCIwXCIsXHJcblx0XHRcdFx0XHRcdFwicG9zaXRpb25cIlx0XHQ6IFwiYWJzb2x1dGVcIixcclxuXHRcdFx0XHRcdFx0XCJ0b3BcIlx0XHRcdDogXCItMjAwMHB4XCIsXHJcblx0XHRcdFx0XHRcdFwibGluZUhlaWdodFwiXHQ6IFwiMTZweFwiLFxyXG5cdFx0XHRcdFx0XHRcInpJbmRleFwiXHRcdDogXCIxMDAwMFwiXHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0JChkb2N1bWVudCkuYmluZChcIm1vdXNlbW92ZSB0b3VjaG1vdmVcIiwgJC52YWthdGEuZG5kLmRyYWcpO1xyXG5cdFx0XHRcdCQoZG9jdW1lbnQpLmJpbmQoXCJtb3VzZXVwIHRvdWNoZW5kXCIsICQudmFrYXRhLmRuZC5zdG9wKTtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH0sXHJcblx0XHRcdGRyYWcgOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdGlmKGUudHlwZSA9PT0gXCJ0b3VjaG1vdmVcIiAmJiBlLm9yaWdpbmFsRXZlbnQgJiYgZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzICYmIGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXSkge1xyXG5cdFx0XHRcdFx0ZS5wYWdlWCA9IGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXS5wYWdlWDtcclxuXHRcdFx0XHRcdGUucGFnZVkgPSBlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVk7XHJcblx0XHRcdFx0XHRlLnRhcmdldCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYIC0gd2luZG93LnBhZ2VYT2Zmc2V0LCBlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZighdmFrYXRhX2RuZC5pc19kb3duKSB7IHJldHVybjsgfVxyXG5cdFx0XHRcdGlmKCF2YWthdGFfZG5kLmlzX2RyYWcpIHtcclxuXHRcdFx0XHRcdGlmKFxyXG5cdFx0XHRcdFx0XHRNYXRoLmFicyhlLnBhZ2VYIC0gdmFrYXRhX2RuZC5pbml0X3gpID4gJC52YWthdGEuZG5kLnNldHRpbmdzLnRocmVzaG9sZCB8fFxyXG5cdFx0XHRcdFx0XHRNYXRoLmFicyhlLnBhZ2VZIC0gdmFrYXRhX2RuZC5pbml0X3kpID4gJC52YWthdGEuZG5kLnNldHRpbmdzLnRocmVzaG9sZFxyXG5cdFx0XHRcdFx0KSB7XHJcblx0XHRcdFx0XHRcdGlmKHZha2F0YV9kbmQuaGVscGVyKSB7XHJcblx0XHRcdFx0XHRcdFx0dmFrYXRhX2RuZC5oZWxwZXIuYXBwZW5kVG8oXCJib2R5XCIpO1xyXG5cdFx0XHRcdFx0XHRcdHZha2F0YV9kbmQuaGVscGVyX3cgPSB2YWthdGFfZG5kLmhlbHBlci5vdXRlcldpZHRoKCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0dmFrYXRhX2RuZC5pc19kcmFnID0gdHJ1ZTtcclxuXHRcdFx0XHRcdFx0LyoqXHJcblx0XHRcdFx0XHRcdCAqIHRyaWdnZXJlZCBvbiB0aGUgZG9jdW1lbnQgd2hlbiBhIGRyYWcgc3RhcnRzXHJcblx0XHRcdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdFx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0XHRcdFx0XHQgKiBAbmFtZSBkbmRfc3RhcnQudmFrYXRhXHJcblx0XHRcdFx0XHRcdCAqIEBwYXJhbSB7TWl4ZWR9IGRhdGEgYW55IGRhdGEgc3VwcGxpZWQgd2l0aCB0aGUgY2FsbCB0byAkLnZha2F0YS5kbmQuc3RhcnRcclxuXHRcdFx0XHRcdFx0ICogQHBhcmFtIHtET019IGVsZW1lbnQgdGhlIERPTSBlbGVtZW50IGJlaW5nIGRyYWdnZWRcclxuXHRcdFx0XHRcdFx0ICogQHBhcmFtIHtqUXVlcnl9IGhlbHBlciB0aGUgaGVscGVyIHNob3duIG5leHQgdG8gdGhlIG1vdXNlXHJcblx0XHRcdFx0XHRcdCAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCB0aGUgZXZlbnQgdGhhdCBjYXVzZWQgdGhlIHN0YXJ0IChwcm9iYWJseSBtb3VzZW1vdmUpXHJcblx0XHRcdFx0XHRcdCAqL1xyXG5cdFx0XHRcdFx0XHQkLnZha2F0YS5kbmQuX3RyaWdnZXIoXCJzdGFydFwiLCBlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2UgeyByZXR1cm47IH1cclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdHZhciBkICA9IGZhbHNlLCB3ICA9IGZhbHNlLFxyXG5cdFx0XHRcdFx0ZGggPSBmYWxzZSwgd2ggPSBmYWxzZSxcclxuXHRcdFx0XHRcdGR3ID0gZmFsc2UsIHd3ID0gZmFsc2UsXHJcblx0XHRcdFx0XHRkdCA9IGZhbHNlLCBkbCA9IGZhbHNlLFxyXG5cdFx0XHRcdFx0aHQgPSBmYWxzZSwgaGwgPSBmYWxzZTtcclxuXHJcblx0XHRcdFx0dmFrYXRhX2RuZC5zY3JvbGxfdCA9IDA7XHJcblx0XHRcdFx0dmFrYXRhX2RuZC5zY3JvbGxfbCA9IDA7XHJcblx0XHRcdFx0dmFrYXRhX2RuZC5zY3JvbGxfZSA9IGZhbHNlO1xyXG5cdFx0XHRcdCQoZS50YXJnZXQpXHJcblx0XHRcdFx0XHQucGFyZW50c1VudGlsKFwiYm9keVwiKS5hZGRCYWNrKCkudmFrYXRhX3JldmVyc2UoKVxyXG5cdFx0XHRcdFx0LmZpbHRlcihmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdHJldHVyblx0KC9eYXV0b3xzY3JvbGwkLykudGVzdCgkKHRoaXMpLmNzcyhcIm92ZXJmbG93XCIpKSAmJlxyXG5cdFx0XHRcdFx0XHRcdFx0KHRoaXMuc2Nyb2xsSGVpZ2h0ID4gdGhpcy5vZmZzZXRIZWlnaHQgfHwgdGhpcy5zY3JvbGxXaWR0aCA+IHRoaXMub2Zmc2V0V2lkdGgpO1xyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHRcdC5lYWNoKGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0dmFyIHQgPSAkKHRoaXMpLCBvID0gdC5vZmZzZXQoKTtcclxuXHRcdFx0XHRcdFx0aWYodGhpcy5zY3JvbGxIZWlnaHQgPiB0aGlzLm9mZnNldEhlaWdodCkge1xyXG5cdFx0XHRcdFx0XHRcdGlmKG8udG9wICsgdC5oZWlnaHQoKSAtIGUucGFnZVkgPCAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3Byb3hpbWl0eSlcdHsgdmFrYXRhX2RuZC5zY3JvbGxfdCA9IDE7IH1cclxuXHRcdFx0XHRcdFx0XHRpZihlLnBhZ2VZIC0gby50b3AgPCAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3Byb3hpbWl0eSlcdFx0XHRcdHsgdmFrYXRhX2RuZC5zY3JvbGxfdCA9IC0xOyB9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYodGhpcy5zY3JvbGxXaWR0aCA+IHRoaXMub2Zmc2V0V2lkdGgpIHtcclxuXHRcdFx0XHRcdFx0XHRpZihvLmxlZnQgKyB0LndpZHRoKCkgLSBlLnBhZ2VYIDwgJC52YWthdGEuZG5kLnNldHRpbmdzLnNjcm9sbF9wcm94aW1pdHkpXHR7IHZha2F0YV9kbmQuc2Nyb2xsX2wgPSAxOyB9XHJcblx0XHRcdFx0XHRcdFx0aWYoZS5wYWdlWCAtIG8ubGVmdCA8ICQudmFrYXRhLmRuZC5zZXR0aW5ncy5zY3JvbGxfcHJveGltaXR5KVx0XHRcdFx0eyB2YWthdGFfZG5kLnNjcm9sbF9sID0gLTE7IH1cclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZih2YWthdGFfZG5kLnNjcm9sbF90IHx8IHZha2F0YV9kbmQuc2Nyb2xsX2wpIHtcclxuXHRcdFx0XHRcdFx0XHR2YWthdGFfZG5kLnNjcm9sbF9lID0gJCh0aGlzKTtcclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0pO1xyXG5cclxuXHRcdFx0XHRpZighdmFrYXRhX2RuZC5zY3JvbGxfZSkge1xyXG5cdFx0XHRcdFx0ZCAgPSAkKGRvY3VtZW50KTsgdyA9ICQod2luZG93KTtcclxuXHRcdFx0XHRcdGRoID0gZC5oZWlnaHQoKTsgd2ggPSB3LmhlaWdodCgpO1xyXG5cdFx0XHRcdFx0ZHcgPSBkLndpZHRoKCk7IHd3ID0gdy53aWR0aCgpO1xyXG5cdFx0XHRcdFx0ZHQgPSBkLnNjcm9sbFRvcCgpOyBkbCA9IGQuc2Nyb2xsTGVmdCgpO1xyXG5cdFx0XHRcdFx0aWYoZGggPiB3aCAmJiBlLnBhZ2VZIC0gZHQgPCAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3Byb3hpbWl0eSlcdFx0eyB2YWthdGFfZG5kLnNjcm9sbF90ID0gLTE7ICB9XHJcblx0XHRcdFx0XHRpZihkaCA+IHdoICYmIHdoIC0gKGUucGFnZVkgLSBkdCkgPCAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3Byb3hpbWl0eSlcdHsgdmFrYXRhX2RuZC5zY3JvbGxfdCA9IDE7IH1cclxuXHRcdFx0XHRcdGlmKGR3ID4gd3cgJiYgZS5wYWdlWCAtIGRsIDwgJC52YWthdGEuZG5kLnNldHRpbmdzLnNjcm9sbF9wcm94aW1pdHkpXHRcdHsgdmFrYXRhX2RuZC5zY3JvbGxfbCA9IC0xOyB9XHJcblx0XHRcdFx0XHRpZihkdyA+IHd3ICYmIHd3IC0gKGUucGFnZVggLSBkbCkgPCAkLnZha2F0YS5kbmQuc2V0dGluZ3Muc2Nyb2xsX3Byb3hpbWl0eSlcdHsgdmFrYXRhX2RuZC5zY3JvbGxfbCA9IDE7IH1cclxuXHRcdFx0XHRcdGlmKHZha2F0YV9kbmQuc2Nyb2xsX3QgfHwgdmFrYXRhX2RuZC5zY3JvbGxfbCkge1xyXG5cdFx0XHRcdFx0XHR2YWthdGFfZG5kLnNjcm9sbF9lID0gZDtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYodmFrYXRhX2RuZC5zY3JvbGxfZSkgeyAkLnZha2F0YS5kbmQuX3Njcm9sbCh0cnVlKTsgfVxyXG5cclxuXHRcdFx0XHRpZih2YWthdGFfZG5kLmhlbHBlcikge1xyXG5cdFx0XHRcdFx0aHQgPSBwYXJzZUludChlLnBhZ2VZICsgJC52YWthdGEuZG5kLnNldHRpbmdzLmhlbHBlcl90b3AsIDEwKTtcclxuXHRcdFx0XHRcdGhsID0gcGFyc2VJbnQoZS5wYWdlWCArICQudmFrYXRhLmRuZC5zZXR0aW5ncy5oZWxwZXJfbGVmdCwgMTApO1xyXG5cdFx0XHRcdFx0aWYoZGggJiYgaHQgKyAyNSA+IGRoKSB7IGh0ID0gZGggLSA1MDsgfVxyXG5cdFx0XHRcdFx0aWYoZHcgJiYgaGwgKyB2YWthdGFfZG5kLmhlbHBlcl93ID4gZHcpIHsgaGwgPSBkdyAtICh2YWthdGFfZG5kLmhlbHBlcl93ICsgMik7IH1cclxuXHRcdFx0XHRcdHZha2F0YV9kbmQuaGVscGVyLmNzcyh7XHJcblx0XHRcdFx0XHRcdGxlZnRcdDogaGwgKyBcInB4XCIsXHJcblx0XHRcdFx0XHRcdHRvcFx0XHQ6IGh0ICsgXCJweFwiXHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogdHJpZ2dlcmVkIG9uIHRoZSBkb2N1bWVudCB3aGVuIGEgZHJhZyBpcyBpbiBwcm9ncmVzc1xyXG5cdFx0XHRcdCAqIEBldmVudFxyXG5cdFx0XHRcdCAqIEBwbHVnaW4gZG5kXHJcblx0XHRcdFx0ICogQG5hbWUgZG5kX21vdmUudmFrYXRhXHJcblx0XHRcdFx0ICogQHBhcmFtIHtNaXhlZH0gZGF0YSBhbnkgZGF0YSBzdXBwbGllZCB3aXRoIHRoZSBjYWxsIHRvICQudmFrYXRhLmRuZC5zdGFydFxyXG5cdFx0XHRcdCAqIEBwYXJhbSB7RE9NfSBlbGVtZW50IHRoZSBET00gZWxlbWVudCBiZWluZyBkcmFnZ2VkXHJcblx0XHRcdFx0ICogQHBhcmFtIHtqUXVlcnl9IGhlbHBlciB0aGUgaGVscGVyIHNob3duIG5leHQgdG8gdGhlIG1vdXNlXHJcblx0XHRcdFx0ICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IHRoZSBldmVudCB0aGF0IGNhdXNlZCB0aGlzIHRvIHRyaWdnZXIgKG1vc3QgbGlrZWx5IG1vdXNlbW92ZSlcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHQkLnZha2F0YS5kbmQuX3RyaWdnZXIoXCJtb3ZlXCIsIGUpO1xyXG5cdFx0XHR9LFxyXG5cdFx0XHRzdG9wIDogZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRpZihlLnR5cGUgPT09IFwidG91Y2hlbmRcIiAmJiBlLm9yaWdpbmFsRXZlbnQgJiYgZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzICYmIGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXSkge1xyXG5cdFx0XHRcdFx0ZS5wYWdlWCA9IGUub3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlc1swXS5wYWdlWDtcclxuXHRcdFx0XHRcdGUucGFnZVkgPSBlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVk7XHJcblx0XHRcdFx0XHRlLnRhcmdldCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZS5vcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLnBhZ2VYIC0gd2luZG93LnBhZ2VYT2Zmc2V0LCBlLm9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0ucGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZih2YWthdGFfZG5kLmlzX2RyYWcpIHtcclxuXHRcdFx0XHRcdC8qKlxyXG5cdFx0XHRcdFx0ICogdHJpZ2dlcmVkIG9uIHRoZSBkb2N1bWVudCB3aGVuIGEgZHJhZyBzdG9wcyAodGhlIGRyYWdnZWQgZWxlbWVudCBpcyBkcm9wcGVkKVxyXG5cdFx0XHRcdFx0ICogQGV2ZW50XHJcblx0XHRcdFx0XHQgKiBAcGx1Z2luIGRuZFxyXG5cdFx0XHRcdFx0ICogQG5hbWUgZG5kX3N0b3AudmFrYXRhXHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge01peGVkfSBkYXRhIGFueSBkYXRhIHN1cHBsaWVkIHdpdGggdGhlIGNhbGwgdG8gJC52YWthdGEuZG5kLnN0YXJ0XHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge0RPTX0gZWxlbWVudCB0aGUgRE9NIGVsZW1lbnQgYmVpbmcgZHJhZ2dlZFxyXG5cdFx0XHRcdFx0ICogQHBhcmFtIHtqUXVlcnl9IGhlbHBlciB0aGUgaGVscGVyIHNob3duIG5leHQgdG8gdGhlIG1vdXNlXHJcblx0XHRcdFx0XHQgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgdGhlIGV2ZW50IHRoYXQgY2F1c2VkIHRoZSBzdG9wXHJcblx0XHRcdFx0XHQgKi9cclxuXHRcdFx0XHRcdCQudmFrYXRhLmRuZC5fdHJpZ2dlcihcInN0b3BcIiwgZSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdCQudmFrYXRhLmRuZC5fY2xlYW4oKTtcclxuXHRcdFx0fVxyXG5cdFx0fTtcclxuXHR9KGpRdWVyeSkpO1xyXG5cclxuXHQvLyBpbmNsdWRlIHRoZSBkbmQgcGx1Z2luIGJ5IGRlZmF1bHRcclxuXHQvLyAkLmpzdHJlZS5kZWZhdWx0cy5wbHVnaW5zLnB1c2goXCJkbmRcIik7XHJcblxyXG5cclxuLyoqXHJcbiAqICMjIyBTZWFyY2ggcGx1Z2luXHJcbiAqXHJcbiAqIEFkZHMgc2VhcmNoIGZ1bmN0aW9uYWxpdHkgdG8ganNUcmVlLlxyXG4gKi9cclxuXHJcblx0LyoqXHJcblx0ICogc3RvcmVzIGFsbCBkZWZhdWx0cyBmb3IgdGhlIHNlYXJjaCBwbHVnaW5cclxuXHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5zZWFyY2hcclxuXHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdCAqL1xyXG5cdCQuanN0cmVlLmRlZmF1bHRzLnNlYXJjaCA9IHtcclxuXHRcdC8qKlxyXG5cdFx0ICogYSBqUXVlcnktbGlrZSBBSkFYIGNvbmZpZywgd2hpY2gganN0cmVlIHVzZXMgaWYgYSBzZXJ2ZXIgc2hvdWxkIGJlIHF1ZXJpZWQgZm9yIHJlc3VsdHMuIFxyXG5cdFx0ICogXHJcblx0XHQgKiBBIGBzdHJgICh3aGljaCBpcyB0aGUgc2VhcmNoIHN0cmluZykgcGFyYW1ldGVyIHdpbGwgYmUgYWRkZWQgd2l0aCB0aGUgcmVxdWVzdC4gVGhlIGV4cGVjdGVkIHJlc3VsdCBpcyBhIEpTT04gYXJyYXkgd2l0aCBub2RlcyB0aGF0IG5lZWQgdG8gYmUgb3BlbmVkIHNvIHRoYXQgbWF0Y2hpbmcgbm9kZXMgd2lsbCBiZSByZXZlYWxlZC5cclxuXHRcdCAqIExlYXZlIHRoaXMgc2V0dGluZyBhcyBgZmFsc2VgIHRvIG5vdCBxdWVyeSB0aGUgc2VydmVyLlxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuc2VhcmNoLmFqYXhcclxuXHRcdCAqIEBwbHVnaW4gc2VhcmNoXHJcblx0XHQgKi9cclxuXHRcdGFqYXggOiBmYWxzZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogSW5kaWNhdGVzIGlmIHRoZSBzZWFyY2ggc2hvdWxkIGJlIGZ1enp5IG9yIG5vdCAoc2hvdWxkIGBjaG5kM2AgbWF0Y2ggYGNoaWxkIG5vZGUgM2ApLiBEZWZhdWx0IGlzIGB0cnVlYC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnNlYXJjaC5mdXp6eVxyXG5cdFx0ICogQHBsdWdpbiBzZWFyY2hcclxuXHRcdCAqL1xyXG5cdFx0ZnV6enkgOiB0cnVlLFxyXG5cdFx0LyoqXHJcblx0XHQgKiBJbmRpY2F0ZXMgaWYgdGhlIHNlYXJjaCBzaG91bGQgYmUgY2FzZSBzZW5zaXRpdmUuIERlZmF1bHQgaXMgYGZhbHNlYC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnNlYXJjaC5jYXNlX3NlbnNpdGl2ZVxyXG5cdFx0ICogQHBsdWdpbiBzZWFyY2hcclxuXHRcdCAqL1xyXG5cdFx0Y2FzZV9zZW5zaXRpdmUgOiBmYWxzZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogSW5kaWNhdGVzIGlmIHRoZSB0cmVlIHNob3VsZCBiZSBmaWx0ZXJlZCB0byBzaG93IG9ubHkgbWF0Y2hpbmcgbm9kZXMgKGtlZXAgaW4gbWluZCB0aGlzIGNhbiBiZSBhIGhlYXZ5IG9uIGxhcmdlIHRyZWVzIGluIG9sZCBicm93c2VycykuIERlZmF1bHQgaXMgYGZhbHNlYC5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnNlYXJjaC5zaG93X29ubHlfbWF0Y2hlc1xyXG5cdFx0ICogQHBsdWdpbiBzZWFyY2hcclxuXHRcdCAqL1xyXG5cdFx0c2hvd19vbmx5X21hdGNoZXMgOiBmYWxzZSxcclxuXHRcdC8qKlxyXG5cdFx0ICogSW5kaWNhdGVzIGlmIGFsbCBub2RlcyBvcGVuZWQgdG8gcmV2ZWFsIHRoZSBzZWFyY2ggcmVzdWx0LCBzaG91bGQgYmUgY2xvc2VkIHdoZW4gdGhlIHNlYXJjaCBpcyBjbGVhcmVkIG9yIGEgbmV3IHNlYXJjaCBpcyBwZXJmb3JtZWQuIERlZmF1bHQgaXMgYHRydWVgLlxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuc2VhcmNoLmNsb3NlX29wZW5lZF9vbmNsZWFyXHJcblx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0ICovXHJcblx0XHRjbG9zZV9vcGVuZWRfb25jbGVhciA6IHRydWVcclxuXHR9O1xyXG5cclxuXHQkLmpzdHJlZS5wbHVnaW5zLnNlYXJjaCA9IGZ1bmN0aW9uIChvcHRpb25zLCBwYXJlbnQpIHtcclxuXHRcdHRoaXMuYmluZCA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0cGFyZW50LmJpbmQuY2FsbCh0aGlzKTtcclxuXHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLnN0ciA9IFwiXCI7XHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLmRvbSA9ICQoKTtcclxuXHRcdFx0dGhpcy5fZGF0YS5zZWFyY2gucmVzID0gW107XHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLm9wbiA9IFtdO1xyXG5cdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5zbG4gPSBudWxsO1xyXG5cclxuXHRcdFx0aWYodGhpcy5zZXR0aW5ncy5zZWFyY2guc2hvd19vbmx5X21hdGNoZXMpIHtcclxuXHRcdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHRcdC5vbihcInNlYXJjaC5qc3RyZWVcIiwgZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0aWYoZGF0YS5ub2Rlcy5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0XHQkKHRoaXMpLmZpbmQoXCJsaVwiKS5oaWRlKCkuZmlsdGVyKCcuanN0cmVlLWxhc3QnKS5maWx0ZXIoZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzLm5leHRTaWJsaW5nOyB9KS5yZW1vdmVDbGFzcygnanN0cmVlLWxhc3QnKTtcclxuXHRcdFx0XHRcdFx0XHRkYXRhLm5vZGVzLnBhcmVudHNVbnRpbChcIi5qc3RyZWVcIikuYWRkQmFjaygpLnNob3coKVxyXG5cdFx0XHRcdFx0XHRcdFx0LmZpbHRlcihcInVsXCIpLmVhY2goZnVuY3Rpb24gKCkgeyAkKHRoaXMpLmNoaWxkcmVuKFwibGk6dmlzaWJsZVwiKS5lcSgtMSkuYWRkQ2xhc3MoXCJqc3RyZWUtbGFzdFwiKTsgfSk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0pXHJcblx0XHRcdFx0XHQub24oXCJjbGVhcl9zZWFyY2guanN0cmVlXCIsIGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdGlmKGRhdGEubm9kZXMubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0JCh0aGlzKS5maW5kKFwibGlcIikuY3NzKFwiZGlzcGxheVwiLFwiXCIpLmZpbHRlcignLmpzdHJlZS1sYXN0JykuZmlsdGVyKGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpcy5uZXh0U2libGluZzsgfSkucmVtb3ZlQ2xhc3MoJ2pzdHJlZS1sYXN0Jyk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0pO1xyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdFx0LyoqXHJcblx0XHQgKiB1c2VkIHRvIHNlYXJjaCB0aGUgdHJlZSBub2RlcyBmb3IgYSBnaXZlbiBzdHJpbmdcclxuXHRcdCAqIEBuYW1lIHNlYXJjaChzdHIgWywgc2tpcF9hc3luY10pXHJcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyIHRoZSBzZWFyY2ggc3RyaW5nXHJcblx0XHQgKiBAcGFyYW0ge0Jvb2xlYW59IHNraXBfYXN5bmMgaWYgc2V0IHRvIHRydWUgc2VydmVyIHdpbGwgbm90IGJlIHF1ZXJpZWQgZXZlbiBpZiBjb25maWd1cmVkXHJcblx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0ICogQHRyaWdnZXIgc2VhcmNoLmpzdHJlZVxyXG5cdFx0ICovXHJcblx0XHR0aGlzLnNlYXJjaCA9IGZ1bmN0aW9uIChzdHIsIHNraXBfYXN5bmMpIHtcclxuXHRcdFx0aWYoc3RyID09PSBmYWxzZSB8fCAkLnRyaW0oc3RyKSA9PT0gXCJcIikge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLmNsZWFyX3NlYXJjaCgpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHZhciBzID0gdGhpcy5zZXR0aW5ncy5zZWFyY2gsXHJcblx0XHRcdFx0YSA9IHMuYWpheCA/ICQuZXh0ZW5kKHt9LCBzLmFqYXgpIDogZmFsc2UsXHJcblx0XHRcdFx0ZiA9IG51bGwsXHJcblx0XHRcdFx0ciA9IFtdLFxyXG5cdFx0XHRcdHAgPSBbXSwgaSwgajtcclxuXHRcdFx0aWYodGhpcy5fZGF0YS5zZWFyY2gucmVzLmxlbmd0aCkge1xyXG5cdFx0XHRcdHRoaXMuY2xlYXJfc2VhcmNoKCk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYoIXNraXBfYXN5bmMgJiYgYSAhPT0gZmFsc2UpIHtcclxuXHRcdFx0XHRpZighYS5kYXRhKSB7IGEuZGF0YSA9IHt9OyB9XHJcblx0XHRcdFx0YS5kYXRhLnN0ciA9IHN0cjtcclxuXHRcdFx0XHRyZXR1cm4gJC5hamF4KGEpXHJcblx0XHRcdFx0XHQuZmFpbCgkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5fZGF0YS5jb3JlLmxhc3RfZXJyb3IgPSB7ICdlcnJvcicgOiAnYWpheCcsICdwbHVnaW4nIDogJ3NlYXJjaCcsICdpZCcgOiAnc2VhcmNoXzAxJywgJ3JlYXNvbicgOiAnQ291bGQgbm90IGxvYWQgc2VhcmNoIHBhcmVudHMnLCAnZGF0YScgOiBKU09OLnN0cmluZ2lmeShhKSB9O1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLmNvcmUuZXJyb3IuY2FsbCh0aGlzLCB0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvcik7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHRcdC5kb25lKCQucHJveHkoZnVuY3Rpb24gKGQpIHtcclxuXHRcdFx0XHRcdFx0aWYoZCAmJiBkLmQpIHsgZCA9IGQuZDsgfVxyXG5cdFx0XHRcdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5zbG4gPSAhJC5pc0FycmF5KGQpID8gW10gOiBkO1xyXG5cdFx0XHRcdFx0XHR0aGlzLl9zZWFyY2hfbG9hZChzdHIpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLnN0ciA9IHN0cjtcclxuXHRcdFx0dGhpcy5fZGF0YS5zZWFyY2guZG9tID0gJCgpO1xyXG5cdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5yZXMgPSBbXTtcclxuXHRcdFx0dGhpcy5fZGF0YS5zZWFyY2gub3BuID0gW107XHJcblxyXG5cdFx0XHRmID0gbmV3ICQudmFrYXRhLnNlYXJjaChzdHIsIHRydWUsIHsgY2FzZVNlbnNpdGl2ZSA6IHMuY2FzZV9zZW5zaXRpdmUsIGZ1enp5IDogcy5mdXp6eSB9KTtcclxuXHJcblx0XHRcdCQuZWFjaCh0aGlzLl9tb2RlbC5kYXRhLCBmdW5jdGlvbiAoaSwgdikge1xyXG5cdFx0XHRcdGlmKHYudGV4dCAmJiBmLnNlYXJjaCh2LnRleHQpLmlzTWF0Y2gpIHtcclxuXHRcdFx0XHRcdHIucHVzaChpKTtcclxuXHRcdFx0XHRcdHAgPSBwLmNvbmNhdCh2LnBhcmVudHMpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0XHRcdGlmKHIubGVuZ3RoKSB7XHJcblx0XHRcdFx0cCA9ICQudmFrYXRhLmFycmF5X3VuaXF1ZShwKTtcclxuXHRcdFx0XHR0aGlzLl9zZWFyY2hfb3BlbihwKTtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSByLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0ZiA9IHRoaXMuZ2V0X25vZGUocltpXSwgdHJ1ZSk7XHJcblx0XHRcdFx0XHRpZihmKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLmRvbSA9IHRoaXMuX2RhdGEuc2VhcmNoLmRvbS5hZGQoZik7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLnJlcyA9IHI7XHJcblx0XHRcdFx0dGhpcy5fZGF0YS5zZWFyY2guZG9tLmNoaWxkcmVuKFwiLmpzdHJlZS1hbmNob3JcIikuYWRkQ2xhc3MoJ2pzdHJlZS1zZWFyY2gnKTtcclxuXHRcdFx0fVxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIHNlYXJjaCBpcyBjb21wbGV0ZVxyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgc2VhcmNoLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge2pRdWVyeX0gbm9kZXMgYSBqUXVlcnkgY29sbGVjdGlvbiBvZiBtYXRjaGluZyBub2Rlc1xyXG5cdFx0XHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyIHRoZSBzZWFyY2ggc3RyaW5nXHJcblx0XHRcdCAqIEBwYXJhbSB7QXJyYXl9IHJlcyBhIGNvbGxlY3Rpb24gb2Ygb2JqZWN0cyByZXByZXNlaW5nIHRoZSBtYXRjaGluZyBub2Rlc1xyXG5cdFx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdzZWFyY2gnLCB7IG5vZGVzIDogdGhpcy5fZGF0YS5zZWFyY2guZG9tLCBzdHIgOiBzdHIsIHJlcyA6IHRoaXMuX2RhdGEuc2VhcmNoLnJlcyB9KTtcclxuXHRcdH07XHJcblx0XHQvKipcclxuXHRcdCAqIHVzZWQgdG8gY2xlYXIgdGhlIGxhc3Qgc2VhcmNoIChyZW1vdmVzIGNsYXNzZXMgYW5kIHNob3dzIGFsbCBub2RlcyBpZiBmaWx0ZXJpbmcgaXMgb24pXHJcblx0XHQgKiBAbmFtZSBjbGVhcl9zZWFyY2goKVxyXG5cdFx0ICogQHBsdWdpbiBzZWFyY2hcclxuXHRcdCAqIEB0cmlnZ2VyIGNsZWFyX3NlYXJjaC5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5jbGVhcl9zZWFyY2ggPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLmRvbS5jaGlsZHJlbihcIi5qc3RyZWUtYW5jaG9yXCIpLnJlbW92ZUNsYXNzKFwianN0cmVlLXNlYXJjaFwiKTtcclxuXHRcdFx0aWYodGhpcy5zZXR0aW5ncy5zZWFyY2guY2xvc2Vfb3BlbmVkX29uY2xlYXIpIHtcclxuXHRcdFx0XHR0aGlzLmNsb3NlX25vZGUodGhpcy5fZGF0YS5zZWFyY2gub3BuLCAwKTtcclxuXHRcdFx0fVxyXG5cdFx0XHQvKipcclxuXHRcdFx0ICogdHJpZ2dlcmVkIGFmdGVyIHNlYXJjaCBpcyBjb21wbGV0ZVxyXG5cdFx0XHQgKiBAZXZlbnRcclxuXHRcdFx0ICogQG5hbWUgY2xlYXJfc2VhcmNoLmpzdHJlZVxyXG5cdFx0XHQgKiBAcGFyYW0ge2pRdWVyeX0gbm9kZXMgYSBqUXVlcnkgY29sbGVjdGlvbiBvZiBtYXRjaGluZyBub2RlcyAodGhlIHJlc3VsdCBmcm9tIHRoZSBsYXN0IHNlYXJjaClcclxuXHRcdFx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciB0aGUgc2VhcmNoIHN0cmluZyAodGhlIGxhc3Qgc2VhcmNoIHN0cmluZylcclxuXHRcdFx0ICogQHBhcmFtIHtBcnJheX0gcmVzIGEgY29sbGVjdGlvbiBvZiBvYmplY3RzIHJlcHJlc2VpbmcgdGhlIG1hdGNoaW5nIG5vZGVzICh0aGUgcmVzdWx0IGZyb20gdGhlIGxhc3Qgc2VhcmNoKVxyXG5cdFx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0XHQgKi9cclxuXHRcdFx0dGhpcy50cmlnZ2VyKCdjbGVhcl9zZWFyY2gnLCB7ICdub2RlcycgOiB0aGlzLl9kYXRhLnNlYXJjaC5kb20sIHN0ciA6IHRoaXMuX2RhdGEuc2VhcmNoLnN0ciwgcmVzIDogdGhpcy5fZGF0YS5zZWFyY2gucmVzIH0pO1xyXG5cdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5zdHIgPSBcIlwiO1xyXG5cdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5yZXMgPSBbXTtcclxuXHRcdFx0dGhpcy5fZGF0YS5zZWFyY2gub3BuID0gW107XHJcblx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLmRvbSA9ICQoKTtcclxuXHRcdH07XHJcblx0XHQvKipcclxuXHRcdCAqIG9wZW5zIG5vZGVzIHRoYXQgbmVlZCB0byBiZSBvcGVuZWQgdG8gcmV2ZWFsIHRoZSBzZWFyY2ggcmVzdWx0cy4gVXNlZCBvbmx5IGludGVybmFsbHkuXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQG5hbWUgX3NlYXJjaF9vcGVuKGQpXHJcblx0XHQgKiBAcGFyYW0ge0FycmF5fSBkIGFuIGFycmF5IG9mIG5vZGUgSURzXHJcblx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0ICovXHJcblx0XHR0aGlzLl9zZWFyY2hfb3BlbiA9IGZ1bmN0aW9uIChkKSB7XHJcblx0XHRcdHZhciB0ID0gdGhpcztcclxuXHRcdFx0JC5lYWNoKGQuY29uY2F0KFtdKSwgZnVuY3Rpb24gKGksIHYpIHtcclxuXHRcdFx0XHR2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodik7XHJcblx0XHRcdFx0aWYodikge1xyXG5cdFx0XHRcdFx0aWYodC5pc19jbG9zZWQodikpIHtcclxuXHRcdFx0XHRcdFx0dC5fZGF0YS5zZWFyY2gub3BuLnB1c2godi5pZCk7XHJcblx0XHRcdFx0XHRcdHQub3Blbl9ub2RlKHYsIGZ1bmN0aW9uICgpIHsgdC5fc2VhcmNoX29wZW4oZCk7IH0sIDApO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSk7XHJcblx0XHR9O1xyXG5cdFx0LyoqXHJcblx0XHQgKiBsb2FkcyBub2RlcyB0aGF0IG5lZWQgdG8gYmUgb3BlbmVkIHRvIHJldmVhbCB0aGUgc2VhcmNoIHJlc3VsdHMuIFVzZWQgb25seSBpbnRlcm5hbGx5LlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEBuYW1lIF9zZWFyY2hfbG9hZChkLCBzdHIpXHJcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyIHRoZSBzZWFyY2ggc3RyaW5nXHJcblx0XHQgKiBAcGx1Z2luIHNlYXJjaFxyXG5cdFx0ICovXHJcblx0XHR0aGlzLl9zZWFyY2hfbG9hZCA9IGZ1bmN0aW9uIChzdHIpIHtcclxuXHRcdFx0dmFyIHJlcyA9IHRydWUsXHJcblx0XHRcdFx0dCA9IHRoaXMsXHJcblx0XHRcdFx0bSA9IHQuX21vZGVsLmRhdGE7XHJcblx0XHRcdGlmKCQuaXNBcnJheSh0aGlzLl9kYXRhLnNlYXJjaC5zbG4pKSB7XHJcblx0XHRcdFx0aWYoIXRoaXMuX2RhdGEuc2VhcmNoLnNsbi5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdHRoaXMuX2RhdGEuc2VhcmNoLnNsbiA9IG51bGw7XHJcblx0XHRcdFx0XHR0aGlzLnNlYXJjaChzdHIsIHRydWUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdCQuZWFjaCh0aGlzLl9kYXRhLnNlYXJjaC5zbG4sIGZ1bmN0aW9uIChpLCB2KSB7XHJcblx0XHRcdFx0XHRcdGlmKG1bdl0pIHtcclxuXHRcdFx0XHRcdFx0XHQkLnZha2F0YS5hcnJheV9yZW1vdmVfaXRlbSh0Ll9kYXRhLnNlYXJjaC5zbG4sIHYpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKCFtW3ZdLnN0YXRlLmxvYWRlZCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0dC5sb2FkX25vZGUodiwgZnVuY3Rpb24gKG8sIHMpIHsgaWYocykgeyB0Ll9zZWFyY2hfbG9hZChzdHIpOyB9IH0pO1xyXG5cdFx0XHRcdFx0XHRcdFx0cmVzID0gZmFsc2U7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdGlmKHJlcykge1xyXG5cdFx0XHRcdFx0XHR0aGlzLl9kYXRhLnNlYXJjaC5zbG4gPSBbXTtcclxuXHRcdFx0XHRcdFx0dGhpcy5fc2VhcmNoX2xvYWQoc3RyKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH07XHJcblx0fTtcclxuXHJcblx0Ly8gaGVscGVyc1xyXG5cdChmdW5jdGlvbiAoJCkge1xyXG5cdFx0Ly8gZnJvbSBodHRwOi8va2lyby5tZS9wcm9qZWN0cy9mdXNlLmh0bWxcclxuXHRcdCQudmFrYXRhLnNlYXJjaCA9IGZ1bmN0aW9uKHBhdHRlcm4sIHR4dCwgb3B0aW9ucykge1xyXG5cdFx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHRcdFx0aWYob3B0aW9ucy5mdXp6eSAhPT0gZmFsc2UpIHtcclxuXHRcdFx0XHRvcHRpb25zLmZ1enp5ID0gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRwYXR0ZXJuID0gb3B0aW9ucy5jYXNlU2Vuc2l0aXZlID8gcGF0dGVybiA6IHBhdHRlcm4udG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0dmFyIE1BVENIX0xPQ0FUSU9OXHQ9IG9wdGlvbnMubG9jYXRpb24gfHwgMCxcclxuXHRcdFx0XHRNQVRDSF9ESVNUQU5DRVx0PSBvcHRpb25zLmRpc3RhbmNlIHx8IDEwMCxcclxuXHRcdFx0XHRNQVRDSF9USFJFU0hPTERcdD0gb3B0aW9ucy50aHJlc2hvbGQgfHwgMC42LFxyXG5cdFx0XHRcdHBhdHRlcm5MZW4gPSBwYXR0ZXJuLmxlbmd0aCxcclxuXHRcdFx0XHRtYXRjaG1hc2ssIHBhdHRlcm5fYWxwaGFiZXQsIG1hdGNoX2JpdGFwU2NvcmUsIHNlYXJjaDtcclxuXHRcdFx0aWYocGF0dGVybkxlbiA+IDMyKSB7XHJcblx0XHRcdFx0b3B0aW9ucy5mdXp6eSA9IGZhbHNlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKG9wdGlvbnMuZnV6enkpIHtcclxuXHRcdFx0XHRtYXRjaG1hc2sgPSAxIDw8IChwYXR0ZXJuTGVuIC0gMSk7XHJcblx0XHRcdFx0cGF0dGVybl9hbHBoYWJldCA9IChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHR2YXIgbWFzayA9IHt9LFxyXG5cdFx0XHRcdFx0XHRpID0gMDtcclxuXHRcdFx0XHRcdGZvciAoaSA9IDA7IGkgPCBwYXR0ZXJuTGVuOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0bWFza1twYXR0ZXJuLmNoYXJBdChpKV0gPSAwO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Zm9yIChpID0gMDsgaSA8IHBhdHRlcm5MZW47IGkrKykge1xyXG5cdFx0XHRcdFx0XHRtYXNrW3BhdHRlcm4uY2hhckF0KGkpXSB8PSAxIDw8IChwYXR0ZXJuTGVuIC0gaSAtIDEpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0cmV0dXJuIG1hc2s7XHJcblx0XHRcdFx0fSgpKTtcclxuXHRcdFx0XHRtYXRjaF9iaXRhcFNjb3JlID0gZnVuY3Rpb24gKGUsIHgpIHtcclxuXHRcdFx0XHRcdHZhciBhY2N1cmFjeSA9IGUgLyBwYXR0ZXJuTGVuLFxyXG5cdFx0XHRcdFx0XHRwcm94aW1pdHkgPSBNYXRoLmFicyhNQVRDSF9MT0NBVElPTiAtIHgpO1xyXG5cdFx0XHRcdFx0aWYoIU1BVENIX0RJU1RBTkNFKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiBwcm94aW1pdHkgPyAxLjAgOiBhY2N1cmFjeTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHJldHVybiBhY2N1cmFjeSArIChwcm94aW1pdHkgLyBNQVRDSF9ESVNUQU5DRSk7XHJcblx0XHRcdFx0fTtcclxuXHRcdFx0fVxyXG5cdFx0XHRzZWFyY2ggPSBmdW5jdGlvbiAodGV4dCkge1xyXG5cdFx0XHRcdHRleHQgPSBvcHRpb25zLmNhc2VTZW5zaXRpdmUgPyB0ZXh0IDogdGV4dC50b0xvd2VyQ2FzZSgpO1xyXG5cdFx0XHRcdGlmKHBhdHRlcm4gPT09IHRleHQgfHwgdGV4dC5pbmRleE9mKHBhdHRlcm4pICE9PSAtMSkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcdFx0aXNNYXRjaDogdHJ1ZSxcclxuXHRcdFx0XHRcdFx0c2NvcmU6IDBcclxuXHRcdFx0XHRcdH07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmKCFvcHRpb25zLmZ1enp5KSB7XHJcblx0XHRcdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdFx0XHRpc01hdGNoOiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0c2NvcmU6IDFcclxuXHRcdFx0XHRcdH07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHZhciBpLCBqLFxyXG5cdFx0XHRcdFx0dGV4dExlbiA9IHRleHQubGVuZ3RoLFxyXG5cdFx0XHRcdFx0c2NvcmVUaHJlc2hvbGQgPSBNQVRDSF9USFJFU0hPTEQsXHJcblx0XHRcdFx0XHRiZXN0TG9jID0gdGV4dC5pbmRleE9mKHBhdHRlcm4sIE1BVENIX0xPQ0FUSU9OKSxcclxuXHRcdFx0XHRcdGJpbk1pbiwgYmluTWlkLFxyXG5cdFx0XHRcdFx0YmluTWF4ID0gcGF0dGVybkxlbiArIHRleHRMZW4sXHJcblx0XHRcdFx0XHRsYXN0UmQsIHN0YXJ0LCBmaW5pc2gsIHJkLCBjaGFyTWF0Y2gsXHJcblx0XHRcdFx0XHRzY29yZSA9IDEsXHJcblx0XHRcdFx0XHRsb2NhdGlvbnMgPSBbXTtcclxuXHRcdFx0XHRpZiAoYmVzdExvYyAhPT0gLTEpIHtcclxuXHRcdFx0XHRcdHNjb3JlVGhyZXNob2xkID0gTWF0aC5taW4obWF0Y2hfYml0YXBTY29yZSgwLCBiZXN0TG9jKSwgc2NvcmVUaHJlc2hvbGQpO1xyXG5cdFx0XHRcdFx0YmVzdExvYyA9IHRleHQubGFzdEluZGV4T2YocGF0dGVybiwgTUFUQ0hfTE9DQVRJT04gKyBwYXR0ZXJuTGVuKTtcclxuXHRcdFx0XHRcdGlmIChiZXN0TG9jICE9PSAtMSkge1xyXG5cdFx0XHRcdFx0XHRzY29yZVRocmVzaG9sZCA9IE1hdGgubWluKG1hdGNoX2JpdGFwU2NvcmUoMCwgYmVzdExvYyksIHNjb3JlVGhyZXNob2xkKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YmVzdExvYyA9IC0xO1xyXG5cdFx0XHRcdGZvciAoaSA9IDA7IGkgPCBwYXR0ZXJuTGVuOyBpKyspIHtcclxuXHRcdFx0XHRcdGJpbk1pbiA9IDA7XHJcblx0XHRcdFx0XHRiaW5NaWQgPSBiaW5NYXg7XHJcblx0XHRcdFx0XHR3aGlsZSAoYmluTWluIDwgYmluTWlkKSB7XHJcblx0XHRcdFx0XHRcdGlmIChtYXRjaF9iaXRhcFNjb3JlKGksIE1BVENIX0xPQ0FUSU9OICsgYmluTWlkKSA8PSBzY29yZVRocmVzaG9sZCkge1xyXG5cdFx0XHRcdFx0XHRcdGJpbk1pbiA9IGJpbk1pZDtcclxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRiaW5NYXggPSBiaW5NaWQ7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0YmluTWlkID0gTWF0aC5mbG9vcigoYmluTWF4IC0gYmluTWluKSAvIDIgKyBiaW5NaW4pO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0YmluTWF4ID0gYmluTWlkO1xyXG5cdFx0XHRcdFx0c3RhcnQgPSBNYXRoLm1heCgxLCBNQVRDSF9MT0NBVElPTiAtIGJpbk1pZCArIDEpO1xyXG5cdFx0XHRcdFx0ZmluaXNoID0gTWF0aC5taW4oTUFUQ0hfTE9DQVRJT04gKyBiaW5NaWQsIHRleHRMZW4pICsgcGF0dGVybkxlbjtcclxuXHRcdFx0XHRcdHJkID0gbmV3IEFycmF5KGZpbmlzaCArIDIpO1xyXG5cdFx0XHRcdFx0cmRbZmluaXNoICsgMV0gPSAoMSA8PCBpKSAtIDE7XHJcblx0XHRcdFx0XHRmb3IgKGogPSBmaW5pc2g7IGogPj0gc3RhcnQ7IGotLSkge1xyXG5cdFx0XHRcdFx0XHRjaGFyTWF0Y2ggPSBwYXR0ZXJuX2FscGhhYmV0W3RleHQuY2hhckF0KGogLSAxKV07XHJcblx0XHRcdFx0XHRcdGlmIChpID09PSAwKSB7XHJcblx0XHRcdFx0XHRcdFx0cmRbal0gPSAoKHJkW2ogKyAxXSA8PCAxKSB8IDEpICYgY2hhck1hdGNoO1xyXG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdHJkW2pdID0gKChyZFtqICsgMV0gPDwgMSkgfCAxKSAmIGNoYXJNYXRjaCB8ICgoKGxhc3RSZFtqICsgMV0gfCBsYXN0UmRbal0pIDw8IDEpIHwgMSkgfCBsYXN0UmRbaiArIDFdO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGlmIChyZFtqXSAmIG1hdGNobWFzaykge1xyXG5cdFx0XHRcdFx0XHRcdHNjb3JlID0gbWF0Y2hfYml0YXBTY29yZShpLCBqIC0gMSk7XHJcblx0XHRcdFx0XHRcdFx0aWYgKHNjb3JlIDw9IHNjb3JlVGhyZXNob2xkKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRzY29yZVRocmVzaG9sZCA9IHNjb3JlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YmVzdExvYyA9IGogLSAxO1xyXG5cdFx0XHRcdFx0XHRcdFx0bG9jYXRpb25zLnB1c2goYmVzdExvYyk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZiAoYmVzdExvYyA+IE1BVENIX0xPQ0FUSU9OKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHN0YXJ0ID0gTWF0aC5tYXgoMSwgMiAqIE1BVENIX0xPQ0FUSU9OIC0gYmVzdExvYyk7XHJcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGlmIChtYXRjaF9iaXRhcFNjb3JlKGkgKyAxLCBNQVRDSF9MT0NBVElPTikgPiBzY29yZVRocmVzaG9sZCkge1xyXG5cdFx0XHRcdFx0XHRicmVhaztcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGxhc3RSZCA9IHJkO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdFx0aXNNYXRjaDogYmVzdExvYyA+PSAwLFxyXG5cdFx0XHRcdFx0c2NvcmU6IHNjb3JlXHJcblx0XHRcdFx0fTtcclxuXHRcdFx0fTtcclxuXHRcdFx0cmV0dXJuIHR4dCA9PT0gdHJ1ZSA/IHsgJ3NlYXJjaCcgOiBzZWFyY2ggfSA6IHNlYXJjaCh0eHQpO1xyXG5cdFx0fTtcclxuXHR9KGpRdWVyeSkpO1xyXG5cclxuXHQvLyBpbmNsdWRlIHRoZSBzZWFyY2ggcGx1Z2luIGJ5IGRlZmF1bHRcclxuXHQvLyAkLmpzdHJlZS5kZWZhdWx0cy5wbHVnaW5zLnB1c2goXCJzZWFyY2hcIik7XHJcblxyXG4vKipcclxuICogIyMjIFNvcnQgcGx1Z2luXHJcbiAqXHJcbiAqIEF1dG1hdGljYWxseSBzb3J0cyBhbGwgc2libGluZ3MgaW4gdGhlIHRyZWUgYWNjb3JkaW5nIHRvIGEgc29ydGluZyBmdW5jdGlvbi5cclxuICovXHJcblxyXG5cdC8qKlxyXG5cdCAqIHRoZSBzZXR0aW5ncyBmdW5jdGlvbiB1c2VkIHRvIHNvcnQgdGhlIG5vZGVzLlxyXG5cdCAqIEl0IGlzIGV4ZWN1dGVkIGluIHRoZSB0cmVlJ3MgY29udGV4dCwgYWNjZXB0cyB0d28gbm9kZXMgYXMgYXJndW1lbnRzIGFuZCBzaG91bGQgcmV0dXJuIGAxYCBvciBgLTFgLlxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnNvcnRcclxuXHQgKiBAcGx1Z2luIHNvcnRcclxuXHQgKi9cclxuXHQkLmpzdHJlZS5kZWZhdWx0cy5zb3J0ID0gZnVuY3Rpb24gKGEsIGIpIHtcclxuXHRcdC8vcmV0dXJuIHRoaXMuZ2V0X3R5cGUoYSkgPT09IHRoaXMuZ2V0X3R5cGUoYikgPyAodGhpcy5nZXRfdGV4dChhKSA+IHRoaXMuZ2V0X3RleHQoYikgPyAxIDogLTEpIDogdGhpcy5nZXRfdHlwZShhKSA+PSB0aGlzLmdldF90eXBlKGIpO1xyXG5cdFx0cmV0dXJuIHRoaXMuZ2V0X3RleHQoYSkgPiB0aGlzLmdldF90ZXh0KGIpID8gMSA6IC0xO1xyXG5cdH07XHJcblx0JC5qc3RyZWUucGx1Z2lucy5zb3J0ID0gZnVuY3Rpb24gKG9wdGlvbnMsIHBhcmVudCkge1xyXG5cdFx0dGhpcy5iaW5kID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRwYXJlbnQuYmluZC5jYWxsKHRoaXMpO1xyXG5cdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHQub24oXCJtb2RlbC5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNvcnQoZGF0YS5wYXJlbnQsIHRydWUpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwicmVuYW1lX25vZGUuanN0cmVlIGNyZWF0ZV9ub2RlLmpzdHJlZVwiLCAkLnByb3h5KGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuc29ydChkYXRhLnBhcmVudCB8fCBkYXRhLm5vZGUucGFyZW50LCBmYWxzZSk7XHJcblx0XHRcdFx0XHRcdHRoaXMucmVkcmF3X25vZGUoZGF0YS5wYXJlbnQgfHwgZGF0YS5ub2RlLnBhcmVudCwgdHJ1ZSk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oXCJtb3ZlX25vZGUuanN0cmVlIGNvcHlfbm9kZS5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNvcnQoZGF0YS5wYXJlbnQsIGZhbHNlKTtcclxuXHRcdFx0XHRcdFx0dGhpcy5yZWRyYXdfbm9kZShkYXRhLnBhcmVudCwgdHJ1ZSk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSk7XHJcblx0XHR9O1xyXG5cdFx0LyoqXHJcblx0XHQgKiB1c2VkIHRvIHNvcnQgYSBub2RlJ3MgY2hpbGRyZW5cclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAbmFtZSBzb3J0KG9iaiBbLCBkZWVwXSlcclxuXHRcdCAqIEBwYXJhbSAge21peGVkfSBvYmogdGhlIG5vZGVcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gZGVlcCBpZiBzZXQgdG8gYHRydWVgIG5vZGVzIGFyZSBzb3J0ZWQgcmVjdXJzaXZlbHkuXHJcblx0XHQgKiBAcGx1Z2luIHNvcnRcclxuXHRcdCAqIEB0cmlnZ2VyIHNlYXJjaC5qc3RyZWVcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5zb3J0ID0gZnVuY3Rpb24gKG9iaiwgZGVlcCkge1xyXG5cdFx0XHR2YXIgaSwgajtcclxuXHRcdFx0b2JqID0gdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRpZihvYmogJiYgb2JqLmNoaWxkcmVuICYmIG9iai5jaGlsZHJlbi5sZW5ndGgpIHtcclxuXHRcdFx0XHRvYmouY2hpbGRyZW4uc29ydCgkLnByb3h5KHRoaXMuc2V0dGluZ3Muc29ydCwgdGhpcykpO1xyXG5cdFx0XHRcdGlmKGRlZXApIHtcclxuXHRcdFx0XHRcdGZvcihpID0gMCwgaiA9IG9iai5jaGlsZHJlbl9kLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0XHR0aGlzLnNvcnQob2JqLmNoaWxkcmVuX2RbaV0sIGZhbHNlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH07XHJcblx0fTtcclxuXHJcblx0Ly8gaW5jbHVkZSB0aGUgc29ydCBwbHVnaW4gYnkgZGVmYXVsdFxyXG5cdC8vICQuanN0cmVlLmRlZmF1bHRzLnBsdWdpbnMucHVzaChcInNvcnRcIik7XHJcblxyXG4vKipcclxuICogIyMjIFN0YXRlIHBsdWdpblxyXG4gKlxyXG4gKiBTYXZlcyB0aGUgc3RhdGUgb2YgdGhlIHRyZWUgKHNlbGVjdGVkIG5vZGVzLCBvcGVuZWQgbm9kZXMpIG9uIHRoZSB1c2VyJ3MgY29tcHV0ZXIgdXNpbmcgYXZhaWxhYmxlIG9wdGlvbnMgKGxvY2FsU3RvcmFnZSwgY29va2llcywgZXRjKVxyXG4gKi9cclxuXHJcblx0dmFyIHRvID0gZmFsc2U7XHJcblx0LyoqXHJcblx0ICogc3RvcmVzIGFsbCBkZWZhdWx0cyBmb3IgdGhlIHN0YXRlIHBsdWdpblxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnN0YXRlXHJcblx0ICogQHBsdWdpbiBzdGF0ZVxyXG5cdCAqL1xyXG5cdCQuanN0cmVlLmRlZmF1bHRzLnN0YXRlID0ge1xyXG5cdFx0LyoqXHJcblx0XHQgKiBBIHN0cmluZyBmb3IgdGhlIGtleSB0byB1c2Ugd2hlbiBzYXZpbmcgdGhlIGN1cnJlbnQgdHJlZSAoY2hhbmdlIGlmIHVzaW5nIG11bHRpcGxlIHRyZWVzIGluIHlvdXIgcHJvamVjdCkuIERlZmF1bHRzIHRvIGBqc3RyZWVgLlxyXG5cdFx0ICogQG5hbWUgJC5qc3RyZWUuZGVmYXVsdHMuc3RhdGUua2V5XHJcblx0XHQgKiBAcGx1Z2luIHN0YXRlXHJcblx0XHQgKi9cclxuXHRcdGtleVx0XHQ6ICdqc3RyZWUnLFxyXG5cdFx0LyoqXHJcblx0XHQgKiBBIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGV2ZW50cyB0aGF0IHRyaWdnZXIgYSBzdGF0ZSBzYXZlLiBEZWZhdWx0cyB0byBgY2hhbmdlZC5qc3RyZWUgb3Blbl9ub2RlLmpzdHJlZSBjbG9zZV9ub2RlLmpzdHJlZWAuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5zdGF0ZS5ldmVudHNcclxuXHRcdCAqIEBwbHVnaW4gc3RhdGVcclxuXHRcdCAqL1xyXG5cdFx0ZXZlbnRzXHQ6ICdjaGFuZ2VkLmpzdHJlZSBvcGVuX25vZGUuanN0cmVlIGNsb3NlX25vZGUuanN0cmVlJyxcclxuXHRcdC8qKlxyXG5cdFx0ICogVGltZSBpbiBtaWxsaXNlY29uZHMgYWZ0ZXIgd2hpY2ggdGhlIHN0YXRlIHdpbGwgZXhwaXJlLiBEZWZhdWx0cyB0byAnZmFsc2UnIG1lYW5pbmcgLSBubyBleHBpcmUuXHJcblx0XHQgKiBAbmFtZSAkLmpzdHJlZS5kZWZhdWx0cy5zdGF0ZS50dGxcclxuXHRcdCAqIEBwbHVnaW4gc3RhdGVcclxuXHRcdCAqL1xyXG5cdFx0dHRsXHRcdDogZmFsc2UsXHJcblx0XHQvKipcclxuXHRcdCAqIEEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIHByaW9yIHRvIHJlc3RvcmluZyBzdGF0ZSB3aXRoIG9uZSBhcmd1bWVudCAtIHRoZSBzdGF0ZSBvYmplY3QuIENhbiBiZSB1c2VkIHRvIGNsZWFyIHVud2FudGVkIHBhcnRzIG9mIHRoZSBzdGF0ZS5cclxuXHRcdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnN0YXRlLmZpbHRlclxyXG5cdFx0ICogQHBsdWdpbiBzdGF0ZVxyXG5cdFx0ICovXHJcblx0XHRmaWx0ZXJcdDogZmFsc2VcclxuXHR9O1xyXG5cdCQuanN0cmVlLnBsdWdpbnMuc3RhdGUgPSBmdW5jdGlvbiAob3B0aW9ucywgcGFyZW50KSB7XHJcblx0XHR0aGlzLmJpbmQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHBhcmVudC5iaW5kLmNhbGwodGhpcyk7XHJcblx0XHRcdHZhciBiaW5kID0gJC5wcm94eShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0dGhpcy5lbGVtZW50Lm9uKHRoaXMuc2V0dGluZ3Muc3RhdGUuZXZlbnRzLCAkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdGlmKHRvKSB7IGNsZWFyVGltZW91dCh0byk7IH1cclxuXHRcdFx0XHRcdHRvID0gc2V0VGltZW91dCgkLnByb3h5KGZ1bmN0aW9uICgpIHsgdGhpcy5zYXZlX3N0YXRlKCk7IH0sIHRoaXMpLCAxMDApO1xyXG5cdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdFx0fSwgdGhpcyk7XHJcblx0XHRcdHRoaXMuZWxlbWVudFxyXG5cdFx0XHRcdC5vbihcInJlYWR5LmpzdHJlZVwiLCAkLnByb3h5KGZ1bmN0aW9uIChlLCBkYXRhKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuZWxlbWVudC5vbmUoXCJyZXN0b3JlX3N0YXRlLmpzdHJlZVwiLCBiaW5kKTtcclxuXHRcdFx0XHRcdFx0aWYoIXRoaXMucmVzdG9yZV9zdGF0ZSgpKSB7IGJpbmQoKTsgfVxyXG5cdFx0XHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogc2F2ZSB0aGUgc3RhdGVcclxuXHRcdCAqIEBuYW1lIHNhdmVfc3RhdGUoKVxyXG5cdFx0ICogQHBsdWdpbiBzdGF0ZVxyXG5cdFx0ICovXHJcblx0XHR0aGlzLnNhdmVfc3RhdGUgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHZhciBzdCA9IHsgJ3N0YXRlJyA6IHRoaXMuZ2V0X3N0YXRlKCksICd0dGwnIDogdGhpcy5zZXR0aW5ncy5zdGF0ZS50dGwsICdzZWMnIDogKyhuZXcgRGF0ZSgpKSB9O1xyXG5cdFx0XHQkLnZha2F0YS5zdG9yYWdlLnNldCh0aGlzLnNldHRpbmdzLnN0YXRlLmtleSwgSlNPTi5zdHJpbmdpZnkoc3QpKTtcclxuXHRcdH07XHJcblx0XHQvKipcclxuXHRcdCAqIHJlc3RvcmUgdGhlIHN0YXRlIGZyb20gdGhlIHVzZXIncyBjb21wdXRlclxyXG5cdFx0ICogQG5hbWUgcmVzdG9yZV9zdGF0ZSgpXHJcblx0XHQgKiBAcGx1Z2luIHN0YXRlXHJcblx0XHQgKi9cclxuXHRcdHRoaXMucmVzdG9yZV9zdGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0dmFyIGsgPSAkLnZha2F0YS5zdG9yYWdlLmdldCh0aGlzLnNldHRpbmdzLnN0YXRlLmtleSk7XHJcblx0XHRcdGlmKCEhaykgeyB0cnkgeyBrID0gSlNPTi5wYXJzZShrKTsgfSBjYXRjaChleCkgeyByZXR1cm4gZmFsc2U7IH0gfVxyXG5cdFx0XHRpZighIWsgJiYgay50dGwgJiYgay5zZWMgJiYgKyhuZXcgRGF0ZSgpKSAtIGsuc2VjID4gay50dGwpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdGlmKCEhayAmJiBrLnN0YXRlKSB7IGsgPSBrLnN0YXRlOyB9XHJcblx0XHRcdGlmKCEhayAmJiAkLmlzRnVuY3Rpb24odGhpcy5zZXR0aW5ncy5zdGF0ZS5maWx0ZXIpKSB7IGsgPSB0aGlzLnNldHRpbmdzLnN0YXRlLmZpbHRlci5jYWxsKHRoaXMsIGspOyB9XHJcblx0XHRcdGlmKCEhaykge1xyXG5cdFx0XHRcdHRoaXMuZWxlbWVudC5vbmUoXCJzZXRfc3RhdGUuanN0cmVlXCIsIGZ1bmN0aW9uIChlLCBkYXRhKSB7IGRhdGEuaW5zdGFuY2UudHJpZ2dlcigncmVzdG9yZV9zdGF0ZScsIHsgJ3N0YXRlJyA6ICQuZXh0ZW5kKHRydWUsIHt9LCBrKSB9KTsgfSk7XHJcblx0XHRcdFx0dGhpcy5zZXRfc3RhdGUoayk7XHJcblx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogY2xlYXIgdGhlIHN0YXRlIG9uIHRoZSB1c2VyJ3MgY29tcHV0ZXJcclxuXHRcdCAqIEBuYW1lIGNsZWFyX3N0YXRlKClcclxuXHRcdCAqIEBwbHVnaW4gc3RhdGVcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5jbGVhcl9zdGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0cmV0dXJuICQudmFrYXRhLnN0b3JhZ2UuZGVsKHRoaXMuc2V0dGluZ3Muc3RhdGUua2V5KTtcclxuXHRcdH07XHJcblx0fTtcclxuXHJcblx0KGZ1bmN0aW9uICgkLCB1bmRlZmluZWQpIHtcclxuXHRcdCQudmFrYXRhLnN0b3JhZ2UgPSB7XHJcblx0XHRcdC8vIHNpbXBseSBzcGVjaWZ5aW5nIHRoZSBmdW5jdGlvbnMgaW4gRkYgdGhyb3dzIGFuIGVycm9yXHJcblx0XHRcdHNldCA6IGZ1bmN0aW9uIChrZXksIHZhbCkgeyByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKGtleSwgdmFsKTsgfSxcclxuXHRcdFx0Z2V0IDogZnVuY3Rpb24gKGtleSkgeyByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKGtleSk7IH0sXHJcblx0XHRcdGRlbCA6IGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuIHdpbmRvdy5sb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpOyB9XHJcblx0XHR9O1xyXG5cdH0oalF1ZXJ5KSk7XHJcblxyXG5cdC8vIGluY2x1ZGUgdGhlIHN0YXRlIHBsdWdpbiBieSBkZWZhdWx0XHJcblx0Ly8gJC5qc3RyZWUuZGVmYXVsdHMucGx1Z2lucy5wdXNoKFwic3RhdGVcIik7XHJcblxyXG4vKipcclxuICogIyMjIFR5cGVzIHBsdWdpblxyXG4gKlxyXG4gKiBNYWtlcyBpdCBwb3NzaWJsZSB0byBhZGQgcHJlZGVmaW5lZCB0eXBlcyBmb3IgZ3JvdXBzIG9mIG5vZGVzLCB3aGljaCBtYWtlIGl0IHBvc3NpYmxlIHRvIGVhc2lseSBjb250cm9sIG5lc3RpbmcgcnVsZXMgYW5kIGljb24gZm9yIGVhY2ggZ3JvdXAuXHJcbiAqL1xyXG5cclxuXHQvKipcclxuXHQgKiBBbiBvYmplY3Qgc3RvcmluZyBhbGwgdHlwZXMgYXMga2V5IHZhbHVlIHBhaXJzLCB3aGVyZSB0aGUga2V5IGlzIHRoZSB0eXBlIG5hbWUgYW5kIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3QgdGhhdCBjb3VsZCBjb250YWluIGZvbGxvd2luZyBrZXlzIChhbGwgb3B0aW9uYWwpLlxyXG5cdCAqIFxyXG5cdCAqICogYG1heF9jaGlsZHJlbmAgdGhlIG1heGltdW0gbnVtYmVyIG9mIGltbWVkaWF0ZSBjaGlsZHJlbiB0aGlzIG5vZGUgdHlwZSBjYW4gaGF2ZS4gRG8gbm90IHNwZWNpZnkgb3Igc2V0IHRvIGAtMWAgZm9yIHVubGltaXRlZC5cclxuXHQgKiAqIGBtYXhfZGVwdGhgIHRoZSBtYXhpbXVtIG51bWJlciBvZiBuZXN0aW5nIHRoaXMgbm9kZSB0eXBlIGNhbiBoYXZlLiBBIHZhbHVlIG9mIGAxYCB3b3VsZCBtZWFuIHRoYXQgdGhlIG5vZGUgY2FuIGhhdmUgY2hpbGRyZW4sIGJ1dCBubyBncmFuZGNoaWxkcmVuLiBEbyBub3Qgc3BlY2lmeSBvciBzZXQgdG8gYC0xYCBmb3IgdW5saW1pdGVkLlxyXG5cdCAqICogYHZhbGlkX2NoaWxkcmVuYCBhbiBhcnJheSBvZiBub2RlIHR5cGUgc3RyaW5ncywgdGhhdCBub2RlcyBvZiB0aGlzIHR5cGUgY2FuIGhhdmUgYXMgY2hpbGRyZW4uIERvIG5vdCBzcGVjaWZ5IG9yIHNldCB0byBgLTFgIGZvciBubyBsaW1pdHMuXHJcblx0ICogKiBgaWNvbmAgYSBzdHJpbmcgLSBjYW4gYmUgYSBwYXRoIHRvIGFuIGljb24gb3IgYSBjbGFzc05hbWUsIGlmIHVzaW5nIGFuIGltYWdlIHRoYXQgaXMgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5IHVzZSBhIGAuL2AgcHJlZml4LCBvdGhlcndpc2UgaXQgd2lsbCBiZSBkZXRlY3RlZCBhcyBhIGNsYXNzLiBPbWl0IHRvIHVzZSB0aGUgZGVmYXVsdCBpY29uIGZyb20geW91ciB0aGVtZS5cclxuXHQgKlxyXG5cdCAqIFRoZXJlIGFyZSB0d28gcHJlZGVmaW5lZCB0eXBlczpcclxuXHQgKiBcclxuXHQgKiAqIGAjYCByZXByZXNlbnRzIHRoZSByb290IG9mIHRoZSB0cmVlLCBmb3IgZXhhbXBsZSBgbWF4X2NoaWxkcmVuYCB3b3VsZCBjb250cm9sIHRoZSBtYXhpbXVtIG51bWJlciBvZiByb290IG5vZGVzLlxyXG5cdCAqICogYGRlZmF1bHRgIHJlcHJlc2VudHMgdGhlIGRlZmF1bHQgbm9kZSAtIGFueSBzZXR0aW5ncyBoZXJlIHdpbGwgYmUgYXBwbGllZCB0byBhbGwgbm9kZXMgdGhhdCBkbyBub3QgaGF2ZSBhIHR5cGUgc3BlY2lmaWVkLlxyXG5cdCAqIFxyXG5cdCAqIEBuYW1lICQuanN0cmVlLmRlZmF1bHRzLnR5cGVzXHJcblx0ICogQHBsdWdpbiB0eXBlc1xyXG5cdCAqL1xyXG5cdCQuanN0cmVlLmRlZmF1bHRzLnR5cGVzID0ge1xyXG5cdFx0JyMnIDoge30sXHJcblx0XHQnZGVmYXVsdCcgOiB7fVxyXG5cdH07XHJcblxyXG5cdCQuanN0cmVlLnBsdWdpbnMudHlwZXMgPSBmdW5jdGlvbiAob3B0aW9ucywgcGFyZW50KSB7XHJcblx0XHR0aGlzLmluaXQgPSBmdW5jdGlvbiAoZWwsIG9wdGlvbnMpIHtcclxuXHRcdFx0dmFyIGksIGo7XHJcblx0XHRcdGlmKG9wdGlvbnMgJiYgb3B0aW9ucy50eXBlcyAmJiBvcHRpb25zLnR5cGVzWydkZWZhdWx0J10pIHtcclxuXHRcdFx0XHRmb3IoaSBpbiBvcHRpb25zLnR5cGVzKSB7XHJcblx0XHRcdFx0XHRpZihpICE9PSBcImRlZmF1bHRcIiAmJiBpICE9PSBcIiNcIiAmJiBvcHRpb25zLnR5cGVzLmhhc093blByb3BlcnR5KGkpKSB7XHJcblx0XHRcdFx0XHRcdGZvcihqIGluIG9wdGlvbnMudHlwZXNbJ2RlZmF1bHQnXSkge1xyXG5cdFx0XHRcdFx0XHRcdGlmKG9wdGlvbnMudHlwZXNbJ2RlZmF1bHQnXS5oYXNPd25Qcm9wZXJ0eShqKSAmJiBvcHRpb25zLnR5cGVzW2ldW2pdID09PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHRcdFx0XHRcdG9wdGlvbnMudHlwZXNbaV1bal0gPSBvcHRpb25zLnR5cGVzWydkZWZhdWx0J11bal07XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHBhcmVudC5pbml0LmNhbGwodGhpcywgZWwsIG9wdGlvbnMpO1xyXG5cdFx0XHR0aGlzLl9tb2RlbC5kYXRhWycjJ10udHlwZSA9ICcjJztcclxuXHRcdH07XHJcblx0XHR0aGlzLmJpbmQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHBhcmVudC5iaW5kLmNhbGwodGhpcyk7XHJcblx0XHRcdHRoaXMuZWxlbWVudFxyXG5cdFx0XHRcdC5vbignbW9kZWwuanN0cmVlJywgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR2YXIgbSA9IHRoaXMuX21vZGVsLmRhdGEsXHJcblx0XHRcdFx0XHRcdFx0ZHBjID0gZGF0YS5ub2RlcyxcclxuXHRcdFx0XHRcdFx0XHR0ID0gdGhpcy5zZXR0aW5ncy50eXBlcyxcclxuXHRcdFx0XHRcdFx0XHRpLCBqLCBjID0gJ2RlZmF1bHQnO1xyXG5cdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBkcGMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdFx0YyA9ICdkZWZhdWx0JztcclxuXHRcdFx0XHRcdFx0XHRpZihtW2RwY1tpXV0ub3JpZ2luYWwgJiYgbVtkcGNbaV1dLm9yaWdpbmFsLnR5cGUgJiYgdFttW2RwY1tpXV0ub3JpZ2luYWwudHlwZV0pIHtcclxuXHRcdFx0XHRcdFx0XHRcdGMgPSBtW2RwY1tpXV0ub3JpZ2luYWwudHlwZTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0aWYobVtkcGNbaV1dLmRhdGEgJiYgbVtkcGNbaV1dLmRhdGEuanN0cmVlICYmIG1bZHBjW2ldXS5kYXRhLmpzdHJlZS50eXBlICYmIHRbbVtkcGNbaV1dLmRhdGEuanN0cmVlLnR5cGVdKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRjID0gbVtkcGNbaV1dLmRhdGEuanN0cmVlLnR5cGU7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdG1bZHBjW2ldXS50eXBlID0gYztcclxuXHRcdFx0XHRcdFx0XHRpZihtW2RwY1tpXV0uaWNvbiA9PT0gdHJ1ZSAmJiB0W2NdLmljb24gIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0bVtkcGNbaV1dLmljb24gPSB0W2NdLmljb247XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9LCB0aGlzKSk7XHJcblx0XHR9O1xyXG5cdFx0dGhpcy5nZXRfanNvbiA9IGZ1bmN0aW9uIChvYmosIG9wdGlvbnMsIGZsYXQpIHtcclxuXHRcdFx0dmFyIGksIGosXHJcblx0XHRcdFx0bSA9IHRoaXMuX21vZGVsLmRhdGEsXHJcblx0XHRcdFx0b3B0ID0gb3B0aW9ucyA/ICQuZXh0ZW5kKHRydWUsIHt9LCBvcHRpb25zLCB7bm9faWQ6ZmFsc2V9KSA6IHt9LFxyXG5cdFx0XHRcdHRtcCA9IHBhcmVudC5nZXRfanNvbi5jYWxsKHRoaXMsIG9iaiwgb3B0LCBmbGF0KTtcclxuXHRcdFx0aWYodG1wID09PSBmYWxzZSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0aWYoJC5pc0FycmF5KHRtcCkpIHtcclxuXHRcdFx0XHRmb3IoaSA9IDAsIGogPSB0bXAubGVuZ3RoOyBpIDwgajsgaSsrKSB7XHJcblx0XHRcdFx0XHR0bXBbaV0udHlwZSA9IHRtcFtpXS5pZCAmJiBtW3RtcFtpXS5pZF0gJiYgbVt0bXBbaV0uaWRdLnR5cGUgPyBtW3RtcFtpXS5pZF0udHlwZSA6IFwiZGVmYXVsdFwiO1xyXG5cdFx0XHRcdFx0aWYob3B0aW9ucyAmJiBvcHRpb25zLm5vX2lkKSB7XHJcblx0XHRcdFx0XHRcdGRlbGV0ZSB0bXBbaV0uaWQ7XHJcblx0XHRcdFx0XHRcdGlmKHRtcFtpXS5saV9hdHRyICYmIHRtcFtpXS5saV9hdHRyLmlkKSB7XHJcblx0XHRcdFx0XHRcdFx0ZGVsZXRlIHRtcFtpXS5saV9hdHRyLmlkO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdHRtcC50eXBlID0gdG1wLmlkICYmIG1bdG1wLmlkXSAmJiBtW3RtcC5pZF0udHlwZSA/IG1bdG1wLmlkXS50eXBlIDogXCJkZWZhdWx0XCI7XHJcblx0XHRcdFx0aWYob3B0aW9ucyAmJiBvcHRpb25zLm5vX2lkKSB7XHJcblx0XHRcdFx0XHR0bXAgPSB0aGlzLl9kZWxldGVfaWRzKHRtcCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0bXA7XHJcblx0XHR9O1xyXG5cdFx0dGhpcy5fZGVsZXRlX2lkcyA9IGZ1bmN0aW9uICh0bXApIHtcclxuXHRcdFx0aWYoJC5pc0FycmF5KHRtcCkpIHtcclxuXHRcdFx0XHRmb3IodmFyIGkgPSAwLCBqID0gdG1wLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdFx0dG1wW2ldID0gdGhpcy5fZGVsZXRlX2lkcyh0bXBbaV0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gdG1wO1xyXG5cdFx0XHR9XHJcblx0XHRcdGRlbGV0ZSB0bXAuaWQ7XHJcblx0XHRcdGlmKHRtcC5saV9hdHRyICYmIHRtcC5saV9hdHRyLmlkKSB7XHJcblx0XHRcdFx0ZGVsZXRlIHRtcC5saV9hdHRyLmlkO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmKHRtcC5jaGlsZHJlbiAmJiAkLmlzQXJyYXkodG1wLmNoaWxkcmVuKSkge1xyXG5cdFx0XHRcdHRtcC5jaGlsZHJlbiA9IHRoaXMuX2RlbGV0ZV9pZHModG1wLmNoaWxkcmVuKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdG1wO1xyXG5cdFx0fTtcclxuXHRcdHRoaXMuY2hlY2sgPSBmdW5jdGlvbiAoY2hrLCBvYmosIHBhciwgcG9zKSB7XHJcblx0XHRcdGlmKHBhcmVudC5jaGVjay5jYWxsKHRoaXMsIGNoaywgb2JqLCBwYXIsIHBvcykgPT09IGZhbHNlKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRvYmogPSBvYmogJiYgb2JqLmlkID8gb2JqIDogdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRwYXIgPSBwYXIgJiYgcGFyLmlkID8gcGFyIDogdGhpcy5nZXRfbm9kZShwYXIpO1xyXG5cdFx0XHR2YXIgbSA9IG9iaiAmJiBvYmouaWQgPyAkLmpzdHJlZS5yZWZlcmVuY2Uob2JqLmlkKSA6IG51bGwsIHRtcCwgZCwgaSwgajtcclxuXHRcdFx0bSA9IG0gJiYgbS5fbW9kZWwgJiYgbS5fbW9kZWwuZGF0YSA/IG0uX21vZGVsLmRhdGEgOiBudWxsO1xyXG5cdFx0XHRzd2l0Y2goY2hrKSB7XHJcblx0XHRcdFx0Y2FzZSBcImNyZWF0ZV9ub2RlXCI6XHJcblx0XHRcdFx0Y2FzZSBcIm1vdmVfbm9kZVwiOlxyXG5cdFx0XHRcdGNhc2UgXCJjb3B5X25vZGVcIjpcclxuXHRcdFx0XHRcdGlmKGNoayAhPT0gJ21vdmVfbm9kZScgfHwgJC5pbkFycmF5KG9iai5pZCwgcGFyLmNoaWxkcmVuKSA9PT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0dG1wID0gdGhpcy5nZXRfcnVsZXMocGFyKTtcclxuXHRcdFx0XHRcdFx0aWYodG1wLm1heF9jaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIHRtcC5tYXhfY2hpbGRyZW4gIT09IC0xICYmIHRtcC5tYXhfY2hpbGRyZW4gPT09IHBhci5jaGlsZHJlbi5sZW5ndGgpIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvciA9IHsgJ2Vycm9yJyA6ICdjaGVjaycsICdwbHVnaW4nIDogJ3R5cGVzJywgJ2lkJyA6ICd0eXBlc18wMScsICdyZWFzb24nIDogJ21heF9jaGlsZHJlbiBwcmV2ZW50cyBmdW5jdGlvbjogJyArIGNoaywgJ2RhdGEnIDogSlNPTi5zdHJpbmdpZnkoeyAnY2hrJyA6IGNoaywgJ3BvcycgOiBwb3MsICdvYmonIDogb2JqICYmIG9iai5pZCA/IG9iai5pZCA6IGZhbHNlLCAncGFyJyA6IHBhciAmJiBwYXIuaWQgPyBwYXIuaWQgOiBmYWxzZSB9KSB9O1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZih0bXAudmFsaWRfY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiB0bXAudmFsaWRfY2hpbGRyZW4gIT09IC0xICYmICQuaW5BcnJheShvYmoudHlwZSwgdG1wLnZhbGlkX2NoaWxkcmVuKSA9PT0gLTEpIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLl9kYXRhLmNvcmUubGFzdF9lcnJvciA9IHsgJ2Vycm9yJyA6ICdjaGVjaycsICdwbHVnaW4nIDogJ3R5cGVzJywgJ2lkJyA6ICd0eXBlc18wMicsICdyZWFzb24nIDogJ3ZhbGlkX2NoaWxkcmVuIHByZXZlbnRzIGZ1bmN0aW9uOiAnICsgY2hrLCAnZGF0YScgOiBKU09OLnN0cmluZ2lmeSh7ICdjaGsnIDogY2hrLCAncG9zJyA6IHBvcywgJ29iaicgOiBvYmogJiYgb2JqLmlkID8gb2JqLmlkIDogZmFsc2UsICdwYXInIDogcGFyICYmIHBhci5pZCA/IHBhci5pZCA6IGZhbHNlIH0pIH07XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGlmKG0gJiYgb2JqLmNoaWxkcmVuX2QgJiYgb2JqLnBhcmVudHMpIHtcclxuXHRcdFx0XHRcdFx0XHRkID0gMDtcclxuXHRcdFx0XHRcdFx0XHRmb3IoaSA9IDAsIGogPSBvYmouY2hpbGRyZW5fZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHRcdGQgPSBNYXRoLm1heChkLCBtW29iai5jaGlsZHJlbl9kW2ldXS5wYXJlbnRzLmxlbmd0aCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdGQgPSBkIC0gb2JqLnBhcmVudHMubGVuZ3RoICsgMTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZihkIDw9IDAgfHwgZCA9PT0gdW5kZWZpbmVkKSB7IGQgPSAxOyB9XHJcblx0XHRcdFx0XHRcdGRvIHtcclxuXHRcdFx0XHRcdFx0XHRpZih0bXAubWF4X2RlcHRoICE9PSB1bmRlZmluZWQgJiYgdG1wLm1heF9kZXB0aCAhPT0gLTEgJiYgdG1wLm1heF9kZXB0aCA8IGQpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yID0geyAnZXJyb3InIDogJ2NoZWNrJywgJ3BsdWdpbicgOiAndHlwZXMnLCAnaWQnIDogJ3R5cGVzXzAzJywgJ3JlYXNvbicgOiAnbWF4X2RlcHRoIHByZXZlbnRzIGZ1bmN0aW9uOiAnICsgY2hrLCAnZGF0YScgOiBKU09OLnN0cmluZ2lmeSh7ICdjaGsnIDogY2hrLCAncG9zJyA6IHBvcywgJ29iaicgOiBvYmogJiYgb2JqLmlkID8gb2JqLmlkIDogZmFsc2UsICdwYXInIDogcGFyICYmIHBhci5pZCA/IHBhci5pZCA6IGZhbHNlIH0pIH07XHJcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdHBhciA9IHRoaXMuZ2V0X25vZGUocGFyLnBhcmVudCk7XHJcblx0XHRcdFx0XHRcdFx0dG1wID0gdGhpcy5nZXRfcnVsZXMocGFyKTtcclxuXHRcdFx0XHRcdFx0XHRkKys7XHJcblx0XHRcdFx0XHRcdH0gd2hpbGUocGFyKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogdXNlZCB0byByZXRyaWV2ZSB0aGUgdHlwZSBzZXR0aW5ncyBvYmplY3QgZm9yIGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgZ2V0X3J1bGVzKG9iailcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiB0aGUgbm9kZSB0byBmaW5kIHRoZSBydWxlcyBmb3JcclxuXHRcdCAqIEByZXR1cm4ge09iamVjdH1cclxuXHRcdCAqIEBwbHVnaW4gdHlwZXNcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5nZXRfcnVsZXMgPSBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0aWYoIW9iaikgeyByZXR1cm4gZmFsc2U7IH1cclxuXHRcdFx0dmFyIHRtcCA9IHRoaXMuZ2V0X3R5cGUob2JqLCB0cnVlKTtcclxuXHRcdFx0aWYodG1wLm1heF9kZXB0aCA9PT0gdW5kZWZpbmVkKSB7IHRtcC5tYXhfZGVwdGggPSAtMTsgfVxyXG5cdFx0XHRpZih0bXAubWF4X2NoaWxkcmVuID09PSB1bmRlZmluZWQpIHsgdG1wLm1heF9jaGlsZHJlbiA9IC0xOyB9XHJcblx0XHRcdGlmKHRtcC52YWxpZF9jaGlsZHJlbiA9PT0gdW5kZWZpbmVkKSB7IHRtcC52YWxpZF9jaGlsZHJlbiA9IC0xOyB9XHJcblx0XHRcdHJldHVybiB0bXA7XHJcblx0XHR9O1xyXG5cdFx0LyoqXHJcblx0XHQgKiB1c2VkIHRvIHJldHJpZXZlIHRoZSB0eXBlIHN0cmluZyBvciBzZXR0aW5ncyBvYmplY3QgZm9yIGEgbm9kZVxyXG5cdFx0ICogQG5hbWUgZ2V0X3R5cGUob2JqIFssIHJ1bGVzXSlcclxuXHRcdCAqIEBwYXJhbSB7bWl4ZWR9IG9iaiB0aGUgbm9kZSB0byBmaW5kIHRoZSBydWxlcyBmb3JcclxuXHRcdCAqIEBwYXJhbSB7Qm9vbGVhbn0gcnVsZXMgaWYgc2V0IHRvIGB0cnVlYCBpbnN0ZWFkIG9mIGEgc3RyaW5nIHRoZSBzZXR0aW5ncyBvYmplY3Qgd2lsbCBiZSByZXR1cm5lZFxyXG5cdFx0ICogQHJldHVybiB7U3RyaW5nfE9iamVjdH1cclxuXHRcdCAqIEBwbHVnaW4gdHlwZXNcclxuXHRcdCAqL1xyXG5cdFx0dGhpcy5nZXRfdHlwZSA9IGZ1bmN0aW9uIChvYmosIHJ1bGVzKSB7XHJcblx0XHRcdG9iaiA9IHRoaXMuZ2V0X25vZGUob2JqKTtcclxuXHRcdFx0cmV0dXJuICghb2JqKSA/IGZhbHNlIDogKCBydWxlcyA/ICQuZXh0ZW5kKHsgJ3R5cGUnIDogb2JqLnR5cGUgfSwgdGhpcy5zZXR0aW5ncy50eXBlc1tvYmoudHlwZV0pIDogb2JqLnR5cGUpO1xyXG5cdFx0fTtcclxuXHRcdC8qKlxyXG5cdFx0ICogdXNlZCB0byBjaGFuZ2UgYSBub2RlJ3MgdHlwZVxyXG5cdFx0ICogQG5hbWUgc2V0X3R5cGUob2JqLCB0eXBlKVxyXG5cdFx0ICogQHBhcmFtIHttaXhlZH0gb2JqIHRoZSBub2RlIHRvIGNoYW5nZVxyXG5cdFx0ICogQHBhcmFtIHtTdHJpbmd9IHR5cGUgdGhlIG5ldyB0eXBlXHJcblx0XHQgKiBAcGx1Z2luIHR5cGVzXHJcblx0XHQgKi9cclxuXHRcdHRoaXMuc2V0X3R5cGUgPSBmdW5jdGlvbiAob2JqLCB0eXBlKSB7XHJcblx0XHRcdHZhciB0LCB0MSwgdDIsIG9sZF90eXBlLCBvbGRfaWNvbjtcclxuXHRcdFx0aWYoJC5pc0FycmF5KG9iaikpIHtcclxuXHRcdFx0XHRvYmogPSBvYmouc2xpY2UoKTtcclxuXHRcdFx0XHRmb3IodDEgPSAwLCB0MiA9IG9iai5sZW5ndGg7IHQxIDwgdDI7IHQxKyspIHtcclxuXHRcdFx0XHRcdHRoaXMuc2V0X3R5cGUob2JqW3QxXSwgdHlwZSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdHQgPSB0aGlzLnNldHRpbmdzLnR5cGVzO1xyXG5cdFx0XHRvYmogPSB0aGlzLmdldF9ub2RlKG9iaik7XHJcblx0XHRcdGlmKCF0W3R5cGVdIHx8ICFvYmopIHsgcmV0dXJuIGZhbHNlOyB9XHJcblx0XHRcdG9sZF90eXBlID0gb2JqLnR5cGU7XHJcblx0XHRcdG9sZF9pY29uID0gdGhpcy5nZXRfaWNvbihvYmopO1xyXG5cdFx0XHRvYmoudHlwZSA9IHR5cGU7XHJcblx0XHRcdGlmKG9sZF9pY29uID09PSB0cnVlIHx8ICh0W29sZF90eXBlXSAmJiB0W29sZF90eXBlXS5pY29uICYmIG9sZF9pY29uID09PSB0W29sZF90eXBlXS5pY29uKSkge1xyXG5cdFx0XHRcdHRoaXMuc2V0X2ljb24ob2JqLCB0W3R5cGVdLmljb24gIT09IHVuZGVmaW5lZCA/IHRbdHlwZV0uaWNvbiA6IHRydWUpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdC8vIGluY2x1ZGUgdGhlIHR5cGVzIHBsdWdpbiBieSBkZWZhdWx0XHJcblx0Ly8gJC5qc3RyZWUuZGVmYXVsdHMucGx1Z2lucy5wdXNoKFwidHlwZXNcIik7XHJcblxyXG4vKipcclxuICogIyMjIFVuaXF1ZSBwbHVnaW5cclxuICpcclxuICogRW5mb3JjZXMgdGhhdCBubyBub2RlcyB3aXRoIHRoZSBzYW1lIG5hbWUgY2FuIGNvZXhpc3QgYXMgc2libGluZ3MuXHJcbiAqL1xyXG5cclxuXHQkLmpzdHJlZS5wbHVnaW5zLnVuaXF1ZSA9IGZ1bmN0aW9uIChvcHRpb25zLCBwYXJlbnQpIHtcclxuXHRcdHRoaXMuY2hlY2sgPSBmdW5jdGlvbiAoY2hrLCBvYmosIHBhciwgcG9zKSB7XHJcblx0XHRcdGlmKHBhcmVudC5jaGVjay5jYWxsKHRoaXMsIGNoaywgb2JqLCBwYXIsIHBvcykgPT09IGZhbHNlKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cdFx0XHRvYmogPSBvYmogJiYgb2JqLmlkID8gb2JqIDogdGhpcy5nZXRfbm9kZShvYmopO1xyXG5cdFx0XHRwYXIgPSBwYXIgJiYgcGFyLmlkID8gcGFyIDogdGhpcy5nZXRfbm9kZShwYXIpO1xyXG5cdFx0XHRpZighcGFyIHx8ICFwYXIuY2hpbGRyZW4pIHsgcmV0dXJuIHRydWU7IH1cclxuXHRcdFx0dmFyIG4gPSBjaGsgPT09IFwicmVuYW1lX25vZGVcIiA/IHBvcyA6IG9iai50ZXh0LFxyXG5cdFx0XHRcdGMgPSBbXSxcclxuXHRcdFx0XHRtID0gdGhpcy5fbW9kZWwuZGF0YSwgaSwgajtcclxuXHRcdFx0Zm9yKGkgPSAwLCBqID0gcGFyLmNoaWxkcmVuLmxlbmd0aDsgaSA8IGo7IGkrKykge1xyXG5cdFx0XHRcdGMucHVzaChtW3Bhci5jaGlsZHJlbltpXV0udGV4dCk7XHJcblx0XHRcdH1cclxuXHRcdFx0c3dpdGNoKGNoaykge1xyXG5cdFx0XHRcdGNhc2UgXCJkZWxldGVfbm9kZVwiOlxyXG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdFx0Y2FzZSBcInJlbmFtZV9ub2RlXCI6XHJcblx0XHRcdFx0Y2FzZSBcImNvcHlfbm9kZVwiOlxyXG5cdFx0XHRcdFx0aSA9ICgkLmluQXJyYXkobiwgYykgPT09IC0xKTtcclxuXHRcdFx0XHRcdGlmKCFpKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yID0geyAnZXJyb3InIDogJ2NoZWNrJywgJ3BsdWdpbicgOiAndW5pcXVlJywgJ2lkJyA6ICd1bmlxdWVfMDEnLCAncmVhc29uJyA6ICdDaGlsZCB3aXRoIG5hbWUgJyArIG4gKyAnIGFscmVhZHkgZXhpc3RzLiBQcmV2ZW50aW5nOiAnICsgY2hrLCAnZGF0YScgOiBKU09OLnN0cmluZ2lmeSh7ICdjaGsnIDogY2hrLCAncG9zJyA6IHBvcywgJ29iaicgOiBvYmogJiYgb2JqLmlkID8gb2JqLmlkIDogZmFsc2UsICdwYXInIDogcGFyICYmIHBhci5pZCA/IHBhci5pZCA6IGZhbHNlIH0pIH07XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRyZXR1cm4gaTtcclxuXHRcdFx0XHRjYXNlIFwibW92ZV9ub2RlXCI6XHJcblx0XHRcdFx0XHRpID0gKG9iai5wYXJlbnQgPT09IHBhci5pZCB8fCAkLmluQXJyYXkobiwgYykgPT09IC0xKTtcclxuXHRcdFx0XHRcdGlmKCFpKSB7XHJcblx0XHRcdFx0XHRcdHRoaXMuX2RhdGEuY29yZS5sYXN0X2Vycm9yID0geyAnZXJyb3InIDogJ2NoZWNrJywgJ3BsdWdpbicgOiAndW5pcXVlJywgJ2lkJyA6ICd1bmlxdWVfMDEnLCAncmVhc29uJyA6ICdDaGlsZCB3aXRoIG5hbWUgJyArIG4gKyAnIGFscmVhZHkgZXhpc3RzLiBQcmV2ZW50aW5nOiAnICsgY2hrLCAnZGF0YScgOiBKU09OLnN0cmluZ2lmeSh7ICdjaGsnIDogY2hrLCAncG9zJyA6IHBvcywgJ29iaicgOiBvYmogJiYgb2JqLmlkID8gb2JqLmlkIDogZmFsc2UsICdwYXInIDogcGFyICYmIHBhci5pZCA/IHBhci5pZCA6IGZhbHNlIH0pIH07XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRyZXR1cm4gaTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH07XHJcblx0fTtcclxuXHJcblx0Ly8gaW5jbHVkZSB0aGUgdW5pcXVlIHBsdWdpbiBieSBkZWZhdWx0XHJcblx0Ly8gJC5qc3RyZWUuZGVmYXVsdHMucGx1Z2lucy5wdXNoKFwidW5pcXVlXCIpO1xyXG5cclxuXHJcbi8qKlxyXG4gKiAjIyMgV2hvbGVyb3cgcGx1Z2luXHJcbiAqXHJcbiAqIE1ha2VzIGVhY2ggbm9kZSBhcHBlYXIgYmxvY2sgbGV2ZWwuIE1ha2luZyBzZWxlY3Rpb24gZWFzaWVyLiBNYXkgY2F1c2Ugc2xvdyBkb3duIGZvciBsYXJnZSB0cmVlcyBpbiBvbGQgYnJvd3NlcnMuXHJcbiAqL1xyXG5cclxuXHR2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnRElWJyk7XHJcblx0ZGl2LnNldEF0dHJpYnV0ZSgndW5zZWxlY3RhYmxlJywnb24nKTtcclxuXHRkaXYuY2xhc3NOYW1lID0gJ2pzdHJlZS13aG9sZXJvdyc7XHJcblx0ZGl2LmlubmVySFRNTCA9ICcmIzE2MDsnO1xyXG5cdCQuanN0cmVlLnBsdWdpbnMud2hvbGVyb3cgPSBmdW5jdGlvbiAob3B0aW9ucywgcGFyZW50KSB7XHJcblx0XHR0aGlzLmJpbmQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHBhcmVudC5iaW5kLmNhbGwodGhpcyk7XHJcblxyXG5cdFx0XHR0aGlzLmVsZW1lbnRcclxuXHRcdFx0XHQub24oJ2xvYWRpbmcnLCAkLnByb3h5KGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0ZGl2LnN0eWxlLmhlaWdodCA9IHRoaXMuX2RhdGEuY29yZS5saV9oZWlnaHQgKyAncHgnO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKCdyZWFkeS5qc3RyZWUgc2V0X3N0YXRlLmpzdHJlZScsICQucHJveHkoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmhpZGVfZG90cygpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwicmVhZHkuanN0cmVlXCIsICQucHJveHkoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmdldF9jb250YWluZXJfdWwoKS5hZGRDbGFzcygnanN0cmVlLXdob2xlcm93LXVsJyk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oXCJkZXNlbGVjdF9hbGwuanN0cmVlXCIsICQucHJveHkoZnVuY3Rpb24gKGUsIGRhdGEpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5lbGVtZW50LmZpbmQoJy5qc3RyZWUtd2hvbGVyb3ctY2xpY2tlZCcpLnJlbW92ZUNsYXNzKCdqc3RyZWUtd2hvbGVyb3ctY2xpY2tlZCcpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwiY2hhbmdlZC5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmVsZW1lbnQuZmluZCgnLmpzdHJlZS13aG9sZXJvdy1jbGlja2VkJykucmVtb3ZlQ2xhc3MoJ2pzdHJlZS13aG9sZXJvdy1jbGlja2VkJyk7XHJcblx0XHRcdFx0XHRcdHZhciB0bXAgPSBmYWxzZSwgaSwgajtcclxuXHRcdFx0XHRcdFx0Zm9yKGkgPSAwLCBqID0gZGF0YS5zZWxlY3RlZC5sZW5ndGg7IGkgPCBqOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHR0bXAgPSB0aGlzLmdldF9ub2RlKGRhdGEuc2VsZWN0ZWRbaV0sIHRydWUpO1xyXG5cdFx0XHRcdFx0XHRcdGlmKHRtcCAmJiB0bXAubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0bXAuY2hpbGRyZW4oJy5qc3RyZWUtd2hvbGVyb3cnKS5hZGRDbGFzcygnanN0cmVlLXdob2xlcm93LWNsaWNrZWQnKTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbihcIm9wZW5fbm9kZS5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmdldF9ub2RlKGRhdGEubm9kZSwgdHJ1ZSkuZmluZCgnLmpzdHJlZS1jbGlja2VkJykucGFyZW50KCkuY2hpbGRyZW4oJy5qc3RyZWUtd2hvbGVyb3cnKS5hZGRDbGFzcygnanN0cmVlLXdob2xlcm93LWNsaWNrZWQnKTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbihcImhvdmVyX25vZGUuanN0cmVlIGRlaG92ZXJfbm9kZS5qc3RyZWVcIiwgJC5wcm94eShmdW5jdGlvbiAoZSwgZGF0YSkge1xyXG5cdFx0XHRcdFx0XHR0aGlzLmdldF9ub2RlKGRhdGEubm9kZSwgdHJ1ZSkuY2hpbGRyZW4oJy5qc3RyZWUtd2hvbGVyb3cnKVtlLnR5cGUgPT09IFwiaG92ZXJfbm9kZVwiP1wiYWRkQ2xhc3NcIjpcInJlbW92ZUNsYXNzXCJdKCdqc3RyZWUtd2hvbGVyb3ctaG92ZXJlZCcpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwiY29udGV4dG1lbnUuanN0cmVlXCIsIFwiLmpzdHJlZS13aG9sZXJvd1wiLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRcdFx0JChlLmN1cnJlbnRUYXJnZXQpLmNsb3Nlc3QoXCJsaVwiKS5jaGlsZHJlbihcImE6ZXEoMClcIikudHJpZ2dlcignY29udGV4dG1lbnUnLGUpO1xyXG5cdFx0XHRcdFx0fSwgdGhpcykpXHJcblx0XHRcdFx0Lm9uKFwiY2xpY2suanN0cmVlXCIsIFwiLmpzdHJlZS13aG9sZXJvd1wiLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xyXG5cdFx0XHRcdFx0XHR2YXIgdG1wID0gJC5FdmVudCgnY2xpY2snLCB7IG1ldGFLZXkgOiBlLm1ldGFLZXksIGN0cmxLZXkgOiBlLmN0cmxLZXksIGFsdEtleSA6IGUuYWx0S2V5LCBzaGlmdEtleSA6IGUuc2hpZnRLZXkgfSk7XHJcblx0XHRcdFx0XHRcdCQoZS5jdXJyZW50VGFyZ2V0KS5jbG9zZXN0KFwibGlcIikuY2hpbGRyZW4oXCJhOmVxKDApXCIpLnRyaWdnZXIodG1wKS5mb2N1cygpO1xyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHQub24oXCJjbGljay5qc3RyZWVcIiwgXCIuanN0cmVlLWxlYWYgPiAuanN0cmVlLW9jbFwiLCAkLnByb3h5KGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRcdGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XHJcblx0XHRcdFx0XHRcdHZhciB0bXAgPSAkLkV2ZW50KCdjbGljaycsIHsgbWV0YUtleSA6IGUubWV0YUtleSwgY3RybEtleSA6IGUuY3RybEtleSwgYWx0S2V5IDogZS5hbHRLZXksIHNoaWZ0S2V5IDogZS5zaGlmdEtleSB9KTtcclxuXHRcdFx0XHRcdFx0JChlLmN1cnJlbnRUYXJnZXQpLmNsb3Nlc3QoXCJsaVwiKS5jaGlsZHJlbihcImE6ZXEoMClcIikudHJpZ2dlcih0bXApLmZvY3VzKCk7XHJcblx0XHRcdFx0XHR9LCB0aGlzKSlcclxuXHRcdFx0XHQub24oXCJtb3VzZW92ZXIuanN0cmVlXCIsIFwiLmpzdHJlZS13aG9sZXJvdywgLmpzdHJlZS1pY29uXCIsICQucHJveHkoZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcclxuXHRcdFx0XHRcdFx0dGhpcy5ob3Zlcl9ub2RlKGUuY3VycmVudFRhcmdldCk7XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKVxyXG5cdFx0XHRcdC5vbihcIm1vdXNlbGVhdmUuanN0cmVlXCIsIFwiLmpzdHJlZS1ub2RlXCIsICQucHJveHkoZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRcdFx0dGhpcy5kZWhvdmVyX25vZGUoZS5jdXJyZW50VGFyZ2V0KTtcclxuXHRcdFx0XHRcdH0sIHRoaXMpKTtcclxuXHRcdH07XHJcblx0XHR0aGlzLnRlYXJkb3duID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRpZih0aGlzLnNldHRpbmdzLndob2xlcm93KSB7XHJcblx0XHRcdFx0dGhpcy5lbGVtZW50LmZpbmQoXCIuanN0cmVlLXdob2xlcm93XCIpLnJlbW92ZSgpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHBhcmVudC50ZWFyZG93bi5jYWxsKHRoaXMpO1xyXG5cdFx0fTtcclxuXHRcdHRoaXMucmVkcmF3X25vZGUgPSBmdW5jdGlvbihvYmosIGRlZXAsIGNhbGxiYWNrKSB7XHJcblx0XHRcdG9iaiA9IHBhcmVudC5yZWRyYXdfbm9kZS5jYWxsKHRoaXMsIG9iaiwgZGVlcCwgY2FsbGJhY2spO1xyXG5cdFx0XHRpZihvYmopIHtcclxuXHRcdFx0XHR2YXIgdG1wID0gZGl2LmNsb25lTm9kZSh0cnVlKTtcclxuXHRcdFx0XHQvL3RtcC5zdHlsZS5oZWlnaHQgPSB0aGlzLl9kYXRhLmNvcmUubGlfaGVpZ2h0ICsgJ3B4JztcclxuXHRcdFx0XHRpZigkLmluQXJyYXkob2JqLmlkLCB0aGlzLl9kYXRhLmNvcmUuc2VsZWN0ZWQpICE9PSAtMSkgeyB0bXAuY2xhc3NOYW1lICs9ICcganN0cmVlLXdob2xlcm93LWNsaWNrZWQnOyB9XHJcblx0XHRcdFx0b2JqLmluc2VydEJlZm9yZSh0bXAsIG9iai5jaGlsZE5vZGVzWzBdKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gb2JqO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdC8vIGluY2x1ZGUgdGhlIHdob2xlcm93IHBsdWdpbiBieSBkZWZhdWx0XHJcblx0Ly8gJC5qc3RyZWUuZGVmYXVsdHMucGx1Z2lucy5wdXNoKFwid2hvbGVyb3dcIik7XHJcblxyXG59KSk7Il0sImZpbGUiOiJqc3RyZWUuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.min.js new file mode 100644 index 000000000..a2e4228f6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/jstree.min.js @@ -0,0 +1,3 @@ +!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):e("object"==typeof exports?require("jquery"):jQuery)}(function(e,t){"use strict";if(!e.jstree){var i,n,r=0,s=!1,a=!1,o=!1,d=[],l=e("script:last").attr("src"),c=document,h=c.createElement("LI");h.setAttribute("role","treeitem"),i=c.createElement("I"),i.className="jstree-icon jstree-ocl",h.appendChild(i),i=c.createElement("A"),i.className="jstree-anchor",i.setAttribute("href","#"),n=c.createElement("I"),n.className="jstree-icon jstree-themeicon",i.appendChild(n),h.appendChild(i),i=n=null,e.jstree={version:"3.0.0-beta9",defaults:{plugins:[]},plugins:{},path:l&&-1!==l.indexOf("/")?l.replace(/\/[^\/]+$/,""):""},e.jstree.create=function(t,i){var n=new e.jstree.core(++r),s=i;return i=e.extend(!0,{},e.jstree.defaults,i),s&&s.plugins&&(i.plugins=s.plugins),e.each(i.plugins,function(e,t){"core"!==e&&(n=n.plugin(t,i[t]))}),n.init(t,i),n},e.jstree.core=function(e){this._id=e,this._cnt=0,this._data={core:{themes:{name:!1,dots:!1,icons:!1},selected:[],last_error:{}}}},e.jstree.reference=function(t){if(t&&!e(t).length){t.id&&(t=t.id);var i=null;return e(".jstree").each(function(){var n=e(this).data("jstree");return n&&n._model.data[t]?(i=n,!1):void 0}),i}return e(t).closest(".jstree").data("jstree")},e.fn.jstree=function(i){var n="string"==typeof i,r=Array.prototype.slice.call(arguments,1),s=null;return this.each(function(){var a=e.jstree.reference(this),o=n&&a?a[i]:null;return s=n&&o?o.apply(a,r):null,a||n||i!==t&&!e.isPlainObject(i)||e(this).data("jstree",new e.jstree.create(this,i)),a&&!n&&(s=a),null!==s&&s!==t?!1:void 0}),null!==s&&s!==t?s:this},e.expr[":"].jstree=e.expr.createPseudo(function(i){return function(i){return e(i).hasClass("jstree")&&e(i).data("jstree")!==t}}),e.jstree.defaults.core={data:!1,strings:!1,check_callback:!1,error:e.noop,animation:200,multiple:!0,themes:{name:!1,url:!1,dir:!1,dots:!0,icons:!0,stripes:!1,variant:!1,responsive:!0},expand_selected_onload:!0},e.jstree.core.prototype={plugin:function(t,i){var n=e.jstree.plugins[t];return n?(this._data[t]={},n.prototype=this,new n(i,this)):this},init:function(t,i){this._model={data:{"#":{id:"#",parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}}},changed:[],force_full_redraw:!1,redraw_timeout:!1,default_state:{loaded:!0,opened:!1,selected:!1,disabled:!1}},this.element=e(t).addClass("jstree jstree-"+this._id),this.settings=i,this.element.bind("destroyed",e.proxy(this.teardown,this)),this._data.core.ready=!1,this._data.core.loaded=!1,this._data.core.rtl="rtl"===this.element.css("direction"),this.element[this._data.core.rtl?"addClass":"removeClass"]("jstree-rtl"),this.element.attr("role","tree"),this.bind(),this.trigger("init"),this._data.core.original_container_html=this.element.find(" > ul > li").clone(!0),this._data.core.original_container_html.find("li").addBack().contents().filter(function(){return 3===this.nodeType&&(!this.nodeValue||/^\s+$/.test(this.nodeValue))}).remove(),this.element.html(""+this.get_string("Loading ...")+""),this._data.core.li_height=this.get_container_ul().children("li:eq(0)").height()||18,this.trigger("loading"),this.load_node("#")},destroy:function(){this.element.unbind("destroyed",this.teardown),this.teardown()},teardown:function(){this.unbind(),this.element.removeClass("jstree").removeData("jstree").find("[class^='jstree']").addBack().attr("class",function(){return this.className.replace(/jstree[^ ]*|$/gi,"")}),this.element=null},bind:function(){this.element.on("dblclick.jstree",function(){if(document.selection&&document.selection.empty)document.selection.empty();else if(window.getSelection){var e=window.getSelection();try{e.removeAllRanges(),e.collapse()}catch(t){}}}).on("click.jstree",".jstree-ocl",e.proxy(function(e){this.toggle_node(e.target)},this)).on("click.jstree",".jstree-anchor",e.proxy(function(t){t.preventDefault(),e(t.currentTarget).focus(),this.activate_node(t.currentTarget,t)},this)).on("keydown.jstree",".jstree-anchor",e.proxy(function(t){var i=null;switch(t.which){case 13:case 32:t.type="click",e(t.currentTarget).trigger(t);break;case 37:t.preventDefault(),this.is_open(t.currentTarget)?this.close_node(t.currentTarget):(i=this.get_prev_dom(t.currentTarget),i&&i.length&&i.children(".jstree-anchor").focus());break;case 38:t.preventDefault(),i=this.get_prev_dom(t.currentTarget),i&&i.length&&i.children(".jstree-anchor").focus();break;case 39:t.preventDefault(),this.is_closed(t.currentTarget)?this.open_node(t.currentTarget,function(e){this.get_node(e,!0).children(".jstree-anchor").focus()}):(i=this.get_next_dom(t.currentTarget),i&&i.length&&i.children(".jstree-anchor").focus());break;case 40:t.preventDefault(),i=this.get_next_dom(t.currentTarget),i&&i.length&&i.children(".jstree-anchor").focus();break;case 46:t.preventDefault(),i=this.get_node(t.currentTarget),i&&i.id&&"#"!==i.id&&(i=this.is_selected(i)?this.get_selected():i);break;case 113:t.preventDefault(),i=this.get_node(t.currentTarget)}},this)).on("load_node.jstree",e.proxy(function(t,i){if(i.status&&("#"!==i.node.id||this._data.core.loaded||(this._data.core.loaded=!0,this.trigger("loaded")),!this._data.core.ready&&!this.get_container_ul().find(".jstree-loading:eq(0)").length)){if(this._data.core.ready=!0,this._data.core.selected.length){if(this.settings.core.expand_selected_onload){var n,r,s=[];for(n=0,r=this._data.core.selected.length;r>n;n++)s=s.concat(this._model.data[this._data.core.selected[n]].parents);for(s=e.vakata.array_unique(s),n=0,r=s.length;r>n;n++)this.open_node(s[n],!1,0)}this.trigger("changed",{action:"ready",selected:this._data.core.selected})}setTimeout(e.proxy(function(){this.trigger("ready")},this),0)}},this)).on("init.jstree",e.proxy(function(){var e=this.settings.core.themes;this._data.core.themes.dots=e.dots,this._data.core.themes.stripes=e.stripes,this._data.core.themes.icons=e.icons,this.set_theme(e.name||"default",e.url),this.set_theme_variant(e.variant)},this)).on("loading.jstree",e.proxy(function(){this[this._data.core.themes.dots?"show_dots":"hide_dots"](),this[this._data.core.themes.icons?"show_icons":"hide_icons"](),this[this._data.core.themes.stripes?"show_stripes":"hide_stripes"]()},this)).on("focus.jstree",".jstree-anchor",e.proxy(function(t){this.element.find(".jstree-hovered").not(t.currentTarget).mouseleave(),e(t.currentTarget).mouseenter()},this)).on("mouseenter.jstree",".jstree-anchor",e.proxy(function(e){this.hover_node(e.currentTarget)},this)).on("mouseleave.jstree",".jstree-anchor",e.proxy(function(e){this.dehover_node(e.currentTarget)},this))},unbind:function(){this.element.off(".jstree"),e(document).off(".jstree-"+this._id)},trigger:function(e,t){t||(t={}),t.instance=this,this.element.triggerHandler(e.replace(".jstree","")+".jstree",t)},get_container:function(){return this.element},get_container_ul:function(){return this.element.children("ul:eq(0)")},get_string:function(t){var i=this.settings.core.strings;return e.isFunction(i)?i.call(this,t):i&&i[t]?i[t]:t},_firstChild:function(e){for(e=e?e.firstChild:null;null!==e&&1!==e.nodeType;)e=e.nextSibling;return e},_nextSibling:function(e){for(e=e?e.nextSibling:null;null!==e&&1!==e.nodeType;)e=e.nextSibling;return e},_previousSibling:function(e){for(e=e?e.previousSibling:null;null!==e&&1!==e.nodeType;)e=e.previousSibling;return e},get_node:function(t,i){t&&t.id&&(t=t.id);var n;try{if(this._model.data[t])t=this._model.data[t];else if(((n=e(t,this.element)).length||(n=e("#"+t,this.element)).length)&&this._model.data[n.closest("li").attr("id")])t=this._model.data[n.closest("li").attr("id")];else{if(!(n=e(t,this.element)).length||!n.hasClass("jstree"))return!1;t=this._model.data["#"]}return i&&(t="#"===t.id?this.element:e(document.getElementById(t.id))),t}catch(r){return!1}},get_path:function(e,t,i){if(e=e.parents?e:this.get_node(e),!e||"#"===e.id||!e.parents)return!1;var n,r,s=[];for(s.push(i?e.id:e.text),n=0,r=e.parents.length;r>n;n++)s.push(i?e.parents[n]:this.get_text(e.parents[n]));return s=s.reverse().slice(1),t?s.join(t):s},get_next_dom:function(t,i){var n;return t=this.get_node(t,!0),t[0]===this.element[0]?(n=this._firstChild(this.get_container_ul()[0]),n?e(n):!1):t&&t.length?i?(n=this._nextSibling(t[0]),n?e(n):!1):t.hasClass("jstree-open")?(n=this._firstChild(t.children("ul")[0]),n?e(n):!1):null!==(n=this._nextSibling(t[0]))?e(n):t.parentsUntil(".jstree","li").next("li").eq(0):!1},get_prev_dom:function(t,i){var n;if(t=this.get_node(t,!0),t[0]===this.element[0])return n=this.get_container_ul()[0].lastChild,n?e(n):!1;if(!t||!t.length)return!1;if(i)return n=this._previousSibling(t[0]),n?e(n):!1;if(null!==(n=this._previousSibling(t[0]))){for(t=e(n);t.hasClass("jstree-open");)t=t.children("ul:eq(0)").children("li:last");return t}return n=t[0].parentNode.parentNode,n&&"LI"===n.tagName?e(n):!1},get_parent:function(e){return e=this.get_node(e),e&&"#"!==e.id?e.parent:!1},get_children_dom:function(e){return e=this.get_node(e,!0),e[0]===this.element[0]?this.get_container_ul().children("li"):e&&e.length?e.children("ul").children("li"):!1},is_parent:function(e){return e=this.get_node(e),e&&(e.state.loaded===!1||e.children.length>0)},is_loaded:function(e){return e=this.get_node(e),e&&e.state.loaded},is_loading:function(e){return e=this.get_node(e,!0),e&&e.hasClass("jstree-loading")},is_open:function(e){return e=this.get_node(e),e&&e.state.opened},is_closed:function(e){return e=this.get_node(e),e&&this.is_parent(e)&&!e.state.opened},is_leaf:function(e){return!this.is_parent(e)},load_node:function(t,i){var n,r;if(e.isArray(t)){for(t=t.slice(),n=0,r=t.length;r>n;n++)this.load_node(t[n],i);return!0}return(t=this.get_node(t))?(this.get_node(t,!0).addClass("jstree-loading"),this._load_node(t,e.proxy(function(e){t.state.loaded=e,this.get_node(t,!0).removeClass("jstree-loading"),this.trigger("load_node",{node:t,status:e}),i&&i.call(this,t,e)},this)),!0):(i.call(this,t,!1),!1)},_load_node:function(t,i){var n,r=this.settings.core.data;return r?e.isFunction(r)?r.call(this,t,e.proxy(function(n){return n===!1?i.call(this,!1):i.call(this,this["string"==typeof n?"_append_html_data":"_append_json_data"](t,"string"==typeof n?e(n):n))},this)):"object"==typeof r?r.url?(r=e.extend(!0,{},r),e.isFunction(r.url)&&(r.url=r.url.call(this,t)),e.isFunction(r.data)&&(r.data=r.data.call(this,t)),e.ajax(r).done(e.proxy(function(n,r,s){var a=s.getResponseHeader("Content-Type");return-1!==a.indexOf("json")?i.call(this,this._append_json_data(t,n)):-1!==a.indexOf("html")?i.call(this,this._append_html_data(t,e(n))):void 0},this)).fail(e.proxy(function(){i.call(this,!1),this._data.core.last_error={error:"ajax",plugin:"core",id:"core_04",reason:"Could not load node",data:JSON.stringify(r)},this.settings.core.error.call(this,this._data.core.last_error)},this))):(n=e.isArray(r)||e.isPlainObject(r)?JSON.parse(JSON.stringify(r)):r,i.call(this,this._append_json_data(t,n))):"string"==typeof r?i.call(this,this._append_html_data(t,r)):i.call(this,!1):i.call(this,"#"===t.id?this._append_html_data(t,this._data.core.original_container_html.clone(!0)):!1)},_node_changed:function(e){e=this.get_node(e),e&&this._model.changed.push(e.id)},_append_html_data:function(t,i){t=this.get_node(t),t.children=[],t.children_d=[];var n,r,s,a=i.is("ul")?i.children():i,o=t.id,d=[],l=[],c=this._model.data,h=c[o],_=this._data.core.selected.length;for(a.each(e.proxy(function(t,i){n=this._parse_model_from_html(e(i),o,h.parents.concat()),n&&(d.push(n),l.push(n),c[n].children_d.length&&(l=l.concat(c[n].children_d)))},this)),h.children=d,h.children_d=l,r=0,s=h.parents.length;s>r;r++)c[h.parents[r]].children_d=c[h.parents[r]].children_d.concat(l);return this.trigger("model",{nodes:l,parent:o}),"#"!==o?(this._node_changed(o),this.redraw()):(this.get_container_ul().children(".jstree-initial-node").remove(),this.redraw(!0)),this._data.core.selected.length!==_&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),!0},_append_json_data:function(i,n){i=this.get_node(i),i.children=[],i.children_d=[];var r,s,a,o=n,d=i.id,l=[],c=[],h=this._model.data,_=h[d],u=this._data.core.selected.length;if(o.d&&(o=o.d,"string"==typeof o&&(o=JSON.parse(o))),e.isArray(o)||(o=[o]),o.length&&o[0].id!==t&&o[0].parent!==t){for(s=0,a=o.length;a>s;s++)o[s].children||(o[s].children=[]),h[o[s].id]=o[s];for(s=0,a=o.length;a>s;s++)h[o[s].parent].children.push(o[s].id),_.children_d.push(o[s].id);for(s=0,a=_.children.length;a>s;s++)r=this._parse_model_from_flat_json(h[_.children[s]],d,_.parents.concat()),c.push(r),h[r].children_d.length&&(c=c.concat(h[r].children_d))}else{for(s=0,a=o.length;a>s;s++)r=this._parse_model_from_json(o[s],d,_.parents.concat()),r&&(l.push(r),c.push(r),h[r].children_d.length&&(c=c.concat(h[r].children_d)));for(_.children=l,_.children_d=c,s=0,a=_.parents.length;a>s;s++)h[_.parents[s]].children_d=h[_.parents[s]].children_d.concat(c)}return this.trigger("model",{nodes:c,parent:d}),"#"!==d?(this._node_changed(d),this.redraw()):this.redraw(!0),this._data.core.selected.length!==u&&this.trigger("changed",{action:"model",selected:this._data.core.selected}),!0},_parse_model_from_html:function(t,i,n){n=n?[].concat(n):[],i&&n.unshift(i);var r,s,a,o,d,l=this._model.data,c={id:!1,text:!1,icon:!0,parent:i,parents:n,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(a in this._model.default_state)this._model.default_state.hasOwnProperty(a)&&(c.state[a]=this._model.default_state[a]);if(o=e.vakata.attributes(t,!0),e.each(o,function(t,i){return i=e.trim(i),i.length?(c.li_attr[t]=i,void("id"===t&&(c.id=i))):!0}),o=t.children("a").eq(0),o.length&&(o=e.vakata.attributes(o,!0),e.each(o,function(t,i){i=e.trim(i),i.length&&(c.a_attr[t]=i)})),o=t.children("a:eq(0)").length?t.children("a:eq(0)").clone():t.clone(),o.children("ins, i, ul").remove(),o=o.html(),o=e("").html(o),c.text=o.html(),o=t.data(),c.data=o?e.extend(!0,{},o):null,c.state.opened=t.hasClass("jstree-open"),c.state.selected=t.children("a").hasClass("jstree-clicked"),c.state.disabled=t.children("a").hasClass("jstree-disabled"),c.data&&c.data.jstree)for(a in c.data.jstree)c.data.jstree.hasOwnProperty(a)&&(c.state[a]=c.data.jstree[a]);o=t.children("a").children(".jstree-themeicon"),o.length&&(c.icon=o.hasClass("jstree-themeicon-hidden")?!1:o.attr("rel")),c.state.icon&&(c.icon=c.state.icon),o=t.children("ul").children("li");do d="j"+this._id+"_"+ ++this._cnt;while(l[d]);return c.id=c.li_attr.id||d,o.length?(o.each(e.proxy(function(t,i){r=this._parse_model_from_html(e(i),c.id,n),s=this._model.data[r],c.children.push(r),s.children_d.length&&(c.children_d=c.children_d.concat(s.children_d))},this)),c.children_d=c.children_d.concat(c.children)):t.hasClass("jstree-closed")&&(c.state.loaded=!1),c.li_attr["class"]&&(c.li_attr["class"]=c.li_attr["class"].replace("jstree-closed","").replace("jstree-open","")),c.a_attr["class"]&&(c.a_attr["class"]=c.a_attr["class"].replace("jstree-clicked","").replace("jstree-disabled","")),l[c.id]=c,c.state.selected&&this._data.core.selected.push(c.id),c.id},_parse_model_from_flat_json:function(e,i,n){n=n?n.concat():[],i&&n.unshift(i);var r,s,a,o,d=e.id,l=this._model.data,c=this._model.default_state,h={id:d,text:e.text||"",icon:e.icon!==t?e.icon:!0,parent:i,parents:n,children:e.children||[],children_d:e.children_d||[],data:e.data,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(r in c)c.hasOwnProperty(r)&&(h.state[r]=c[r]);if(e&&e.data&&e.data.jstree&&e.data.jstree.icon&&(h.icon=e.data.jstree.icon),e&&e.data&&(h.data=e.data,e.data.jstree))for(r in e.data.jstree)e.data.jstree.hasOwnProperty(r)&&(h.state[r]=e.data.jstree[r]);if(e&&"object"==typeof e.state)for(r in e.state)e.state.hasOwnProperty(r)&&(h.state[r]=e.state[r]);if(e&&"object"==typeof e.li_attr)for(r in e.li_attr)e.li_attr.hasOwnProperty(r)&&(h.li_attr[r]=e.li_attr[r]);if(h.li_attr.id||(h.li_attr.id=d),e&&"object"==typeof e.a_attr)for(r in e.a_attr)e.a_attr.hasOwnProperty(r)&&(h.a_attr[r]=e.a_attr[r]);for(e&&e.children&&e.children===!0&&(h.state.loaded=!1,h.children=[],h.children_d=[]),l[h.id]=h,r=0,s=h.children.length;s>r;r++)a=this._parse_model_from_flat_json(l[h.children[r]],h.id,n),o=l[a],h.children_d.push(a),o.children_d.length&&(h.children_d=h.children_d.concat(o.children_d));return delete e.data,delete e.children,l[h.id].original=e,h.state.selected&&this._data.core.selected.push(h.id),h.id},_parse_model_from_json:function(e,i,n){n=n?n.concat():[],i&&n.unshift(i);var r,s,a,o,d,l=!1,c=this._model.data,h=this._model.default_state;do l="j"+this._id+"_"+ ++this._cnt;while(c[l]);d={id:!1,text:"string"==typeof e?e:"",icon:"object"==typeof e&&e.icon!==t?e.icon:!0,parent:i,parents:n,children:[],children_d:[],data:null,state:{},li_attr:{id:!1},a_attr:{href:"#"},original:!1};for(r in h)h.hasOwnProperty(r)&&(d.state[r]=h[r]);if(e&&e.id&&(d.id=e.id),e&&e.text&&(d.text=e.text),e&&e.data&&e.data.jstree&&e.data.jstree.icon&&(d.icon=e.data.jstree.icon),e&&e.data&&(d.data=e.data,e.data.jstree))for(r in e.data.jstree)e.data.jstree.hasOwnProperty(r)&&(d.state[r]=e.data.jstree[r]);if(e&&"object"==typeof e.state)for(r in e.state)e.state.hasOwnProperty(r)&&(d.state[r]=e.state[r]);if(e&&"object"==typeof e.li_attr)for(r in e.li_attr)e.li_attr.hasOwnProperty(r)&&(d.li_attr[r]=e.li_attr[r]);if(d.li_attr.id&&!d.id&&(d.id=d.li_attr.id),d.id||(d.id=l),d.li_attr.id||(d.li_attr.id=d.id),e&&"object"==typeof e.a_attr)for(r in e.a_attr)e.a_attr.hasOwnProperty(r)&&(d.a_attr[r]=e.a_attr[r]);if(e&&e.children&&e.children.length){for(r=0,s=e.children.length;s>r;r++)a=this._parse_model_from_json(e.children[r],d.id,n),o=c[a],d.children.push(a),o.children_d.length&&(d.children_d=d.children_d.concat(o.children_d));d.children_d=d.children_d.concat(d.children)}return e&&e.children&&e.children===!0&&(d.state.loaded=!1,d.children=[],d.children_d=[]),delete e.data,delete e.children,d.original=e,c[d.id]=d,d.state.selected&&this._data.core.selected.push(d.id),d.id},_redraw:function(){var e,t,i,n=this._model.force_full_redraw?this._model.data["#"].children.concat([]):this._model.changed.concat([]),r=document.createElement("UL");for(t=0,i=n.length;i>t;t++)e=this.redraw_node(n[t],!0,this._model.force_full_redraw),e&&this._model.force_full_redraw&&r.appendChild(e);this._model.force_full_redraw&&(r.className=this.get_container_ul()[0].className,this.element.empty().append(r)),this._model.force_full_redraw=!1,this._model.changed=[],this.trigger("redraw",{nodes:n})},redraw:function(e){e&&(this._model.force_full_redraw=!0),this._redraw()},redraw_node:function(t,i,n){var r=this.get_node(t),s=!1,a=!1,o=!1,d=!1,l=!1,c=!1,_="",u=document,g=this._model.data,f=!1,p=!1;if(!r)return!1;if("#"===r.id)return this.redraw(!0);if(i=i||0===r.children.length,t=u.getElementById(r.id))t=e(t),n||(s=t.parent().parent()[0],s===this.element[0]&&(s=null),a=t.index()),i||!r.children.length||t.children("ul").length||(i=!0),i||(o=t.children("UL")[0]),p=t.attr("aria-selected"),f=t.children(".jstree-anchor")[0]===document.activeElement,t.remove();else if(i=!0,!n){if(s="#"!==r.parent?e("#"+r.parent,this.element)[0]:null,!(null===s||s&&g[r.parent].state.opened))return!1;a=e.inArray(r.id,null===s?g["#"].children:g[r.parent].children)}t=h.cloneNode(!0),_="jstree-node ";for(d in r.li_attr)if(r.li_attr.hasOwnProperty(d)){if("id"===d)continue;"class"!==d?t.setAttribute(d,r.li_attr[d]):_+=r.li_attr[d]}p&&"false"!==p&&t.setAttribute("aria-selected",!0),!r.children.length&&r.state.loaded?_+=" jstree-leaf":(_+=r.state.opened?" jstree-open":" jstree-closed",t.setAttribute("aria-expanded",r.state.opened)),null!==r.parent&&g[r.parent].children[g[r.parent].children.length-1]===r.id&&(_+=" jstree-last"),t.id=r.id,t.className=_,_=(r.state.selected?" jstree-clicked":"")+(r.state.disabled?" jstree-disabled":"");for(l in r.a_attr)if(r.a_attr.hasOwnProperty(l)){if("href"===l&&"#"===r.a_attr[l])continue;"class"!==l?t.childNodes[1].setAttribute(l,r.a_attr[l]):_+=" "+r.a_attr[l]}if(_.length&&(t.childNodes[1].className="jstree-anchor "+_),(r.icon&&r.icon!==!0||r.icon===!1)&&(r.icon===!1?t.childNodes[1].childNodes[0].className+=" jstree-themeicon-hidden":-1===r.icon.indexOf("/")&&-1===r.icon.indexOf(".")?t.childNodes[1].childNodes[0].className+=" "+r.icon+" jstree-themeicon-custom":(t.childNodes[1].childNodes[0].style.backgroundImage="url("+r.icon+")",t.childNodes[1].childNodes[0].style.backgroundPosition="center center",t.childNodes[1].childNodes[0].style.backgroundSize="auto",t.childNodes[1].childNodes[0].className+=" jstree-themeicon-custom")),t.childNodes[1].innerHTML+=r.text,i&&r.children.length&&r.state.opened){for(c=u.createElement("UL"),c.setAttribute("role","group"),c.className="jstree-children",d=0,l=r.children.length;l>d;d++)c.appendChild(this.redraw_node(r.children[d],i,!0));t.appendChild(c)}return o&&t.appendChild(o),n||(s||(s=this.element[0]),s.getElementsByTagName("UL").length?s=s.getElementsByTagName("UL")[0]:(d=u.createElement("UL"),d.setAttribute("role","group"),d.className="jstree-children",s.appendChild(d),s=d),as;s++)this.open_node(i[s],n,r);return!0}if(i=this.get_node(i),!i||"#"===i.id)return!1;if(r=r===t?this.settings.core.animation:r,!this.is_closed(i))return n&&n.call(this,i,!1),!1;if(this.is_loaded(i))o=this.get_node(i,!0),d=this,o.length&&(i.children.length&&!this._firstChild(o.children("ul")[0])&&(i.state.opened=!0,this.redraw_node(i,!0),o=this.get_node(i,!0)),r?o.children("ul").css("display","none").end().removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded",!0).children("ul").stop(!0,!0).slideDown(r,function(){this.style.display="",d.trigger("after_open",{node:i})}):(o[0].className=o[0].className.replace("jstree-closed","jstree-open"),o[0].setAttribute("aria-expanded",!0))),i.state.opened=!0,n&&n.call(this,i,!0),this.trigger("open_node",{node:i}),r&&o.length||this.trigger("after_open",{node:i});else{if(this.is_loading(i))return setTimeout(e.proxy(function(){this.open_node(i,n,r)},this),500);this.load_node(i,function(e,t){return t?this.open_node(e,n,r):n?n.call(this,e,!1):!1})}},_open_to:function(t){if(t=this.get_node(t),!t||"#"===t.id)return!1;var i,n,r=t.parents;for(i=0,n=r.length;n>i;i+=1)"#"!==i&&this.open_node(r[i],!1,0);return e(document.getElementById(t.id))},close_node:function(i,n){var r,s,a,o;if(e.isArray(i)){for(i=i.slice(),r=0,s=i.length;s>r;r++)this.close_node(i[r],n);return!0}return i=this.get_node(i),i&&"#"!==i.id?(n=n===t?this.settings.core.animation:n,a=this,o=this.get_node(i,!0),o.length&&(n?o.children("ul").attr("style","display:block !important").end().removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded",!1).children("ul").stop(!0,!0).slideUp(n,function(){this.style.display="",o.children("ul").remove(),a.trigger("after_close",{node:i})}):(o[0].className=o[0].className.replace("jstree-open","jstree-closed"),o.attr("aria-expanded",!1).children("ul").remove())),i.state.opened=!1,this.trigger("close_node",{node:i}),void(n&&o.length||this.trigger("after_close",{node:i}))):!1},toggle_node:function(t){var i,n;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.toggle_node(t[i]);return!0}return this.is_closed(t)?this.open_node(t):this.is_open(t)?this.close_node(t):void 0},open_all:function(e,t,i){if(e||(e="#"),e=this.get_node(e),!e)return!1;var n,r,s,a="#"===e.id?this.get_container_ul():this.get_node(e,!0);if(!a.length){for(n=0,r=e.children_d.length;r>n;n++)this.is_closed(this._model.data[e.children_d[n]])&&(this._model.data[e.children_d[n]].state.opened=!0);return this.trigger("open_all",{node:e})}i=i||a,s=this,a=this.is_closed(e)?a.find("li.jstree-closed").addBack():a.find("li.jstree-closed"),a.each(function(){s.open_node(this,function(e,n){n&&this.is_parent(e)&&this.open_all(e,t,i)},t||0)}),0===i.find("li.jstree-closed").length&&this.trigger("open_all",{node:this.get_node(i)})},close_all:function(e,t){if(e||(e="#"),e=this.get_node(e),!e)return!1;var i,n,r="#"===e.id?this.get_container_ul():this.get_node(e,!0),s=this;if(!r.length){for(i=0,n=e.children_d.length;n>i;i++)this._model.data[e.children_d[i]].state.opened=!1;return this.trigger("close_all",{node:e})}r=this.is_open(e)?r.find("li.jstree-open").addBack():r.find("li.jstree-open"),r.vakata_reverse().each(function(){s.close_node(this,t||0)}),this.trigger("close_all",{node:e})},is_disabled:function(e){return e=this.get_node(e),e&&e.state&&e.state.disabled},enable_node:function(t){var i,n;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.enable_node(t[i]);return!0}return t=this.get_node(t),t&&"#"!==t.id?(t.state.disabled=!1,this.get_node(t,!0).children(".jstree-anchor").removeClass("jstree-disabled"),void this.trigger("enable_node",{node:t})):!1},disable_node:function(t){var i,n;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.disable_node(t[i]);return!0}return t=this.get_node(t),t&&"#"!==t.id?(t.state.disabled=!0,this.get_node(t,!0).children(".jstree-anchor").addClass("jstree-disabled"),void this.trigger("disable_node",{node:t})):!1},activate_node:function(e,t){if(this.is_disabled(e))return!1;if(this.settings.core.multiple&&(t.metaKey||t.ctrlKey||t.shiftKey)&&(!t.shiftKey||this._data.core.last_clicked&&this.get_parent(e)&&this.get_parent(e)===this._data.core.last_clicked.parent))if(t.shiftKey){var i,n,r=this.get_node(e).id,s=this._data.core.last_clicked.id,a=this.get_node(this._data.core.last_clicked.parent).children,o=!1;for(i=0,n=a.length;n>i;i+=1)a[i]===r&&(o=!o),a[i]===s&&(o=!o),o||a[i]===r||a[i]===s?this.select_node(a[i],!1,!1,t):this.deselect_node(a[i],!1,!1,t)}else this.is_selected(e)?this.deselect_node(e,!1,!1,t):this.select_node(e,!1,!1,t);else!this.settings.core.multiple&&(t.metaKey||t.ctrlKey||t.shiftKey)&&this.is_selected(e)?this.deselect_node(e,!1,!1,t):(this.deselect_all(!0),this.select_node(e,!1,!1,t),this._data.core.last_clicked=this.get_node(e));this.trigger("activate_node",{node:this.get_node(e)})},hover_node:function(e){if(e=this.get_node(e,!0),!e||!e.length||e.children(".jstree-hovered").length)return!1;var t=this.element.find(".jstree-hovered"),i=this.element;t&&t.length&&this.dehover_node(t),e.children(".jstree-anchor").addClass("jstree-hovered"),this.trigger("hover_node",{node:this.get_node(e)}),setTimeout(function(){i.attr("aria-activedescendant",e[0].id),e.attr("aria-selected",!0)},0)},dehover_node:function(e){return e=this.get_node(e,!0),e&&e.length&&e.children(".jstree-hovered").length?(e.attr("aria-selected",!1).children(".jstree-anchor").removeClass("jstree-hovered"),void this.trigger("dehover_node",{node:this.get_node(e)})):!1},select_node:function(t,i,n,r){var s,a,o;if(e.isArray(t)){for(t=t.slice(),a=0,o=t.length;o>a;a++)this.select_node(t[a],i,n,r);return!0}return t=this.get_node(t),t&&"#"!==t.id?(s=this.get_node(t,!0),void(t.state.selected||(t.state.selected=!0,this._data.core.selected.push(t.id),n||(s=this._open_to(t)),s&&s.length&&s.children(".jstree-anchor").addClass("jstree-clicked"),this.trigger("select_node",{node:t,selected:this._data.core.selected,event:r}),i||this.trigger("changed",{action:"select_node",node:t,selected:this._data.core.selected,event:r})))):!1},deselect_node:function(t,i,n){var r,s,a;if(e.isArray(t)){for(t=t.slice(),r=0,s=t.length;s>r;r++)this.deselect_node(t[r],i,n);return!0}return t=this.get_node(t),t&&"#"!==t.id?(a=this.get_node(t,!0),void(t.state.selected&&(t.state.selected=!1,this._data.core.selected=e.vakata.array_remove_item(this._data.core.selected,t.id),a.length&&a.children(".jstree-anchor").removeClass("jstree-clicked"),this.trigger("deselect_node",{node:t,selected:this._data.core.selected,event:n}),i||this.trigger("changed",{action:"deselect_node",node:t,selected:this._data.core.selected,event:n})))):!1},select_all:function(e){var t,i,n=this._data.core.selected.concat([]);for(this._data.core.selected=this._model.data["#"].children_d.concat(),t=0,i=this._data.core.selected.length;i>t;t++)this._model.data[this._data.core.selected[t]]&&(this._model.data[this._data.core.selected[t]].state.selected=!0);this.redraw(!0),this.trigger("select_all",{selected:this._data.core.selected}),e||this.trigger("changed",{action:"select_all",selected:this._data.core.selected,old_selection:n})},deselect_all:function(e){var t,i,n=this._data.core.selected.concat([]);for(t=0,i=this._data.core.selected.length;i>t;t++)this._model.data[this._data.core.selected[t]]&&(this._model.data[this._data.core.selected[t]].state.selected=!1);this._data.core.selected=[],this.element.find(".jstree-clicked").removeClass("jstree-clicked"),this.trigger("deselect_all",{selected:this._data.core.selected,node:n}),e||this.trigger("changed",{action:"deselect_all",selected:this._data.core.selected,old_selection:n})},is_selected:function(e){return e=this.get_node(e),e&&"#"!==e.id?e.state.selected:!1},get_selected:function(t){return t?e.map(this._data.core.selected,e.proxy(function(e){return this.get_node(e)},this)):this._data.core.selected},get_state:function(){var e,t={core:{open:[],scroll:{left:this.element.scrollLeft(),top:this.element.scrollTop()},selected:[]}};for(e in this._model.data)this._model.data.hasOwnProperty(e)&&"#"!==e&&(this._model.data[e].state.opened&&t.core.open.push(e),this._model.data[e].state.selected&&t.core.selected.push(e));return t},set_state:function(i,n){if(i){if(i.core){var r,s,a,o;if(i.core.open)return e.isArray(i.core.open)?(r=!0,s=!1,a=this,e.each(i.core.open.concat([]),function(t,o){s=a.get_node(o),s&&(a.is_loaded(o)?(a.is_closed(o)&&a.open_node(o,!1,0),i&&i.core&&i.core.open&&e.vakata.array_remove_item(i.core.open,o)):(a.is_loading(o)||a.open_node(o,e.proxy(function(){this.set_state(i,n)},a),0),r=!1))}),r&&(delete i.core.open,this.set_state(i,n)),!1):(delete i.core.open,this.set_state(i,n),!1);if(i.core.scroll)return i.core.scroll&&i.core.scroll.left!==t&&this.element.scrollLeft(i.core.scroll.left),i.core.scroll&&i.core.scroll.top!==t&&this.element.scrollTop(i.core.scroll.top),delete i.core.scroll,this.set_state(i,n),!1;if(i.core.selected)return o=this,this.deselect_all(),e.each(i.core.selected,function(e,t){o.select_node(t)}),delete i.core.selected,this.set_state(i,n),!1;if(e.isEmptyObject(i.core))return delete i.core,this.set_state(i,n),!1}return e.isEmptyObject(i)?(i=null,n&&n.call(this),this.trigger("set_state"),!1):!0}return!1},refresh:function(t){this._data.core.state=this.get_state(),this._cnt=0,this._model.data={"#":{id:"#",parent:null,parents:[],children:[],children_d:[],state:{loaded:!1}}};var i=this.get_container_ul()[0].className;t||this.element.html(""+this.get_string("Loading ...")+""),this.load_node("#",function(t,n){n&&(this.get_container_ul()[0].className=i,this.set_state(e.extend(!0,{},this._data.core.state),function(){this.trigger("refresh")})),this._data.core.state=null})},set_id:function(t,i){if(t=this.get_node(t),!t||"#"===t.id)return!1;var n,r,s=this._model.data;for(s[t.parent].children[e.inArray(t.id,s[t.parent].children)]=i,n=0,r=t.parents.length;r>n;n++)s[t.parents[n]].children_d[e.inArray(t.id,s[t.parents[n]].children_d)]=i;for(n=0,r=t.children.length;r>n;n++)s[t.children[n]].parent=i;for(n=0,r=t.children_d.length;r>n;n++)s[t.children_d[n]].parents[e.inArray(t.id,s[t.children_d[n]].parents)]=i;return n=e.inArray(t.id,this._data.core.selected),-1!==n&&(this._data.core.selected[n]=i),n=this.get_node(t.id,!0),n&&n.attr("id",i),delete s[t.id],t.id=i,s[i]=t,!0},get_text:function(e){return e=this.get_node(e),e&&"#"!==e.id?e.text:!1},set_text:function(t,i){ +var n,r,s,a;if(e.isArray(t)){for(t=t.slice(),n=0,r=t.length;r>n;n++)this.set_text(t[n],i);return!0}return t=this.get_node(t),t&&"#"!==t.id?(t.text=i,s=this.get_node(t,!0),s.length&&(s=s.children(".jstree-anchor:eq(0)"),a=s.children("I").clone(),s.html(i).prepend(a),this.trigger("set_text",{obj:t,text:i})),!0):!1},get_json:function(e,t,i){if(e=this.get_node(e||"#"),!e)return!1;t&&t.flat&&!i&&(i=[]);var n,r,s={id:e.id,text:e.text,icon:this.get_icon(e),li_attr:e.li_attr,a_attr:e.a_attr,state:{},data:t&&t.no_data?!1:e.data};if(t&&t.flat?s.parent=e.parent:s.children=[],!t||!t.no_state)for(n in e.state)e.state.hasOwnProperty(n)&&(s.state[n]=e.state[n]);if(t&&t.no_id&&(delete s.id,s.li_attr&&s.li_attr.id&&delete s.li_attr.id),t&&t.flat&&"#"!==e.id&&i.push(s),!t||!t.no_children)for(n=0,r=e.children.length;r>n;n++)t&&t.flat?this.get_json(e.children[n],t,i):s.children.push(this.get_json(e.children[n],t));return t&&t.flat?i:"#"===e.id?s.children:s},create_node:function(i,n,r,s,a){if(i=this.get_node(i),!i)return!1;if(r=r===t?"last":r,!r.toString().match(/^(before|after)$/)&&!a&&!this.is_loaded(i))return this.load_node(i,function(){this.create_node(i,n,r,s,!0)});n||(n={text:this.get_string("New node")}),n.text===t&&(n.text=this.get_string("New node"));var o,d,l,c;switch("#"===i.id&&("before"===r&&(r="first"),"after"===r&&(r="last")),r){case"before":o=this.get_node(i.parent),r=e.inArray(i.id,o.children),i=o;break;case"after":o=this.get_node(i.parent),r=e.inArray(i.id,o.children)+1,i=o;break;case"inside":case"first":r=0;break;case"last":r=i.children.length;break;default:r||(r=0)}if(r>i.children.length&&(r=i.children.length),n.id||(n.id=!0),!this.check("create_node",n,i,r))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(n.id===!0&&delete n.id,n=this._parse_model_from_json(n,i.id,i.parents.concat()),!n)return!1;for(o=this.get_node(n),d=[],d.push(n),d=d.concat(o.children_d),this.trigger("model",{nodes:d,parent:i.id}),i.children_d=i.children_d.concat(d),l=0,c=i.parents.length;c>l;l++)this._model.data[i.parents[l]].children_d=this._model.data[i.parents[l]].children_d.concat(d);for(n=o,o=[],l=0,c=i.children.length;c>l;l++)o[l>=r?l+1:l]=i.children[l];return o[r]=n.id,i.children=o,this.redraw_node(i,!0),s&&s.call(this,this.get_node(n)),this.trigger("create_node",{node:this.get_node(n),parent:i.id,position:r}),n.id},rename_node:function(t,i){var n,r,s;if(e.isArray(t)){for(t=t.slice(),n=0,r=t.length;r>n;n++)this.rename_node(t[n],i);return!0}return t=this.get_node(t),t&&"#"!==t.id?(s=t.text,this.check("rename_node",t,this.get_parent(t),i)?(this.set_text(t,i),this.trigger("rename_node",{node:t,text:i,old:s}),!0):(this.settings.core.error.call(this,this._data.core.last_error),!1)):!1},delete_node:function(t){var i,n,r,s,a,o,d,l,c,h;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.delete_node(t[i]);return!0}if(t=this.get_node(t),!t||"#"===t.id)return!1;if(r=this.get_node(t.parent),s=e.inArray(t.id,r.children),h=!1,!this.check("delete_node",t,r,s))return this.settings.core.error.call(this,this._data.core.last_error),!1;for(-1!==s&&(r.children=e.vakata.array_remove(r.children,s)),a=t.children_d.concat([]),a.push(t.id),l=0,c=a.length;c>l;l++){for(o=0,d=t.parents.length;d>o;o++)s=e.inArray(a[l],this._model.data[t.parents[o]].children_d),-1!==s&&(this._model.data[t.parents[o]].children_d=e.vakata.array_remove(this._model.data[t.parents[o]].children_d,s));this._model.data[a[l]].state.selected&&(h=!0,s=e.inArray(a[l],this._data.core.selected),-1!==s&&(this._data.core.selected=e.vakata.array_remove(this._data.core.selected,s)))}for(this.trigger("delete_node",{node:t,parent:r.id}),h&&this.trigger("changed",{action:"delete_node",node:t,selected:this._data.core.selected,parent:r.id}),l=0,c=a.length;c>l;l++)delete this._model.data[a[l]];return this.redraw_node(r,!0),!0},check:function(t,i,n,r){i=i&&i.id?i:this.get_node(i),n=n&&n.id?n:this.get_node(n);var s=t.match(/^move_node|copy_node|create_node$/i)?n:i,a=this.settings.core.check_callback;return"move_node"!==t||i.id!==n.id&&e.inArray(i.id,n.children)!==r&&-1===e.inArray(n.id,i.children_d)?(s=this.get_node(s,!0),s.length&&(s=s.data("jstree")),s&&s.functions&&(s.functions[t]===!1||s.functions[t]===!0)?(s.functions[t]===!1&&(this._data.core.last_error={error:"check",plugin:"core",id:"core_02",reason:"Node data prevents function: "+t,data:JSON.stringify({chk:t,pos:r,obj:i&&i.id?i.id:!1,par:n&&n.id?n.id:!1})}),s.functions[t]):a===!1||e.isFunction(a)&&a.call(this,t,i,n,r)===!1||a&&a[t]===!1?(this._data.core.last_error={error:"check",plugin:"core",id:"core_03",reason:"User config for core.check_callback prevents function: "+t,data:JSON.stringify({chk:t,pos:r,obj:i&&i.id?i.id:!1,par:n&&n.id?n.id:!1})},!1):!0):(this._data.core.last_error={error:"check",plugin:"core",id:"core_01",reason:"Moving parent inside child",data:JSON.stringify({chk:t,pos:r,obj:i&&i.id?i.id:!1,par:n&&n.id?n.id:!1})},!1)},last_error:function(){return this._data.core.last_error},move_node:function(i,n,r,s,a){var o,d,l,c,h,_,u,g,f,p,m,v,y;if(e.isArray(i)){for(i=i.reverse().slice(),o=0,d=i.length;d>o;o++)this.move_node(i[o],n,r,s,a);return!0}if(i=i&&i.id?i:this.get_node(i),n=this.get_node(n),r=r===t?0:r,!n||!i||"#"===i.id)return!1;if(!r.toString().match(/^(before|after)$/)&&!a&&!this.is_loaded(n))return this.load_node(n,function(){this.move_node(i,n,r,s,!0)});if(l=(i.parent||"#").toString(),c=r.toString().match(/^(before|after)$/)&&"#"!==n.id?this.get_node(n.parent):n,h=this._model.data[i.id]?this:e.jstree.reference(i.id),_=!h||!h._id||this._id!==h._id)return this.copy_node(i,n,r,s,a)?(h&&h.delete_node(i),!0):!1;switch("#"===c.id&&("before"===r&&(r="first"),"after"===r&&(r="last")),r){case"before":r=e.inArray(n.id,c.children);break;case"after":r=e.inArray(n.id,c.children)+1;break;case"inside":case"first":r=0;break;case"last":r=c.children.length;break;default:r||(r=0)}if(r>c.children.length&&(r=c.children.length),!this.check("move_node",i,c,r))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(i.parent===c.id){for(u=c.children.concat(),g=e.inArray(i.id,u),-1!==g&&(u=e.vakata.array_remove(u,g),r>g&&r--),g=[],f=0,p=u.length;p>f;f++)g[f>=r?f+1:f]=u[f];g[r]=i.id,c.children=g,this._node_changed(c.id),this.redraw("#"===c.id)}else{for(g=i.children_d.concat(),g.push(i.id),f=0,p=i.parents.length;p>f;f++){for(u=[],y=h._model.data[i.parents[f]].children_d,m=0,v=y.length;v>m;m++)-1===e.inArray(y[m],g)&&u.push(y[m]);h._model.data[i.parents[f]].children_d=u}for(h._model.data[l].children=e.vakata.array_remove_item(h._model.data[l].children,i.id),f=0,p=c.parents.length;p>f;f++)this._model.data[c.parents[f]].children_d=this._model.data[c.parents[f]].children_d.concat(g);for(u=[],f=0,p=c.children.length;p>f;f++)u[f>=r?f+1:f]=c.children[f];for(u[r]=i.id,c.children=u,c.children_d.push(i.id),c.children_d=c.children_d.concat(i.children_d),i.parent=c.id,g=c.parents.concat(),g.unshift(c.id),y=i.parents.length,i.parents=g,g=g.concat(),f=0,p=i.children_d.length;p>f;f++)this._model.data[i.children_d[f]].parents=this._model.data[i.children_d[f]].parents.slice(0,-1*y),Array.prototype.push.apply(this._model.data[i.children_d[f]].parents,g);this._node_changed(l),this._node_changed(c.id),this.redraw("#"===l||"#"===c.id)}return s&&s.call(this,i,c,r),this.trigger("move_node",{node:i,parent:c.id,position:r,old_parent:l,is_multi:_,old_instance:h,new_instance:this}),!0},copy_node:function(i,n,r,s,a){var o,d,l,c,h,_,u,g,f,p,m;if(e.isArray(i)){for(i=i.reverse().slice(),o=0,d=i.length;d>o;o++)this.copy_node(i[o],n,r,s,a);return!0}if(i=i&&i.id?i:this.get_node(i),n=this.get_node(n),r=r===t?0:r,!n||!i||"#"===i.id)return!1;if(!r.toString().match(/^(before|after)$/)&&!a&&!this.is_loaded(n))return this.load_node(n,function(){this.copy_node(i,n,r,s,!0)});switch(g=(i.parent||"#").toString(),f=r.toString().match(/^(before|after)$/)&&"#"!==n.id?this.get_node(n.parent):n,p=this._model.data[i.id]?this:e.jstree.reference(i.id),m=!p||!p._id||this._id!==p._id,"#"===f.id&&("before"===r&&(r="first"),"after"===r&&(r="last")),r){case"before":r=e.inArray(n.id,f.children);break;case"after":r=e.inArray(n.id,f.children)+1;break;case"inside":case"first":r=0;break;case"last":r=f.children.length;break;default:r||(r=0)}if(r>f.children.length&&(r=f.children.length),!this.check("copy_node",i,f,r))return this.settings.core.error.call(this,this._data.core.last_error),!1;if(u=p?p.get_json(i,{no_id:!0,no_data:!0,no_state:!0}):i,!u)return!1;if(u.id===!0&&delete u.id,u=this._parse_model_from_json(u,f.id,f.parents.concat()),!u)return!1;for(c=this.get_node(u),l=[],l.push(u),l=l.concat(c.children_d),this.trigger("model",{nodes:l,parent:f.id}),h=0,_=f.parents.length;_>h;h++)this._model.data[f.parents[h]].children_d=this._model.data[f.parents[h]].children_d.concat(l);for(l=[],h=0,_=f.children.length;_>h;h++)l[h>=r?h+1:h]=f.children[h];return l[r]=c.id,f.children=l,f.children_d.push(c.id),f.children_d=f.children_d.concat(c.children_d),this._node_changed(f.id),this.redraw("#"===f.id),s&&s.call(this,c,f,r),this.trigger("copy_node",{node:c,original:i,parent:f.id,position:r,old_parent:g,is_multi:m,old_instance:p,new_instance:this}),c.id},cut:function(t){if(t||(t=this._data.core.selected.concat()),e.isArray(t)||(t=[t]),!t.length)return!1;var i,n,r,d=[];for(n=0,r=t.length;r>n;n++)i=this.get_node(t[n]),i&&i.id&&"#"!==i.id&&d.push(i);return d.length?(s=d,o=this,a="move_node",void this.trigger("cut",{node:t})):!1},copy:function(t){if(t||(t=this._data.core.selected.concat()),e.isArray(t)||(t=[t]),!t.length)return!1;var i,n,r,d=[];for(n=0,r=t.length;r>n;n++)i=this.get_node(t[n]),i&&i.id&&"#"!==i.id&&d.push(i);return d.length?(s=d,o=this,a="copy_node",void this.trigger("copy",{node:t})):!1},get_buffer:function(){return{mode:a,node:s,inst:o}},can_paste:function(){return a!==!1&&s!==!1},paste:function(e){return e=this.get_node(e),e&&a&&a.match(/^(copy_node|move_node)$/)&&s?(this[a](s,e)&&this.trigger("paste",{parent:e.id,node:s,mode:a}),s=!1,a=!1,void(o=!1)):!1},edit:function(t,i){if(t=this._open_to(t),!t||!t.length)return!1;var n=this._data.core.rtl,r=this.element.width(),s=t.children(".jstree-anchor"),a=e(""),o="string"==typeof i?i:this.get_text(t),d=e("",{css:{position:"absolute",top:"-200px",left:n?"0px":"-1000px",visibility:"hidden"}}).appendTo("body"),l=e("",{value:o,"class":"jstree-rename-input",css:{padding:"0",border:"1px solid silver","box-sizing":"border-box",display:"inline-block",height:this._data.core.li_height+"px",lineHeight:this._data.core.li_height+"px",width:"150px"},blur:e.proxy(function(){var e=a.children(".jstree-rename-input"),i=e.val();""===i&&(i=o),d.remove(),a.replaceWith(s),a.remove(),this.set_text(t,o),this.rename_node(t,i)===!1&&this.set_text(t,o)},this),keydown:function(e){var t=e.which;27===t&&(this.value=o),(27===t||13===t||37===t||38===t||39===t||40===t||32===t)&&e.stopImmediatePropagation(),(27===t||13===t)&&(e.preventDefault(),this.blur())},click:function(e){e.stopImmediatePropagation()},mousedown:function(e){e.stopImmediatePropagation()},keyup:function(e){l.width(Math.min(d.text("pW"+this.value).width(),r))},keypress:function(e){return 13===e.which?!1:void 0}}),c={fontFamily:s.css("fontFamily")||"",fontSize:s.css("fontSize")||"",fontWeight:s.css("fontWeight")||"",fontStyle:s.css("fontStyle")||"",fontStretch:s.css("fontStretch")||"",fontVariant:s.css("fontVariant")||"",letterSpacing:s.css("letterSpacing")||"",wordSpacing:s.css("wordSpacing")||""};this.set_text(t,""),a.attr("class",s.attr("class")).append(s.contents().clone()).append(l),s.replaceWith(a),d.css(c),l.css(c).width(Math.min(d.text("pW"+l[0].value).width(),r))[0].select()},set_theme:function(t,i){if(!t)return!1;if(i===!0){var n=this.settings.core.themes.dir;n||(n=e.jstree.path+"/themes"),i=n+"/"+t+"/style.css"}i&&-1===e.inArray(i,d)&&(e("head").append(''),d.push(i)),this._data.core.themes.name&&this.element.removeClass("jstree-"+this._data.core.themes.name),this._data.core.themes.name=t,this.element.addClass("jstree-"+t),this.element[this.settings.core.themes.responsive?"addClass":"removeClass"]("jstree-"+t+"-responsive"),this.trigger("set_theme",{theme:t})},get_theme:function(){return this._data.core.themes.name},set_theme_variant:function(e){this._data.core.themes.variant&&this.element.removeClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant),this._data.core.themes.variant=e,e&&this.element.addClass("jstree-"+this._data.core.themes.name+"-"+this._data.core.themes.variant)},get_theme_variant:function(){return this._data.core.themes.variant},show_stripes:function(){this._data.core.themes.stripes=!0,this.get_container_ul().addClass("jstree-striped")},hide_stripes:function(){this._data.core.themes.stripes=!1,this.get_container_ul().removeClass("jstree-striped")},toggle_stripes:function(){this._data.core.themes.stripes?this.hide_stripes():this.show_stripes()},show_dots:function(){this._data.core.themes.dots=!0,this.get_container_ul().removeClass("jstree-no-dots")},hide_dots:function(){this._data.core.themes.dots=!1,this.get_container_ul().addClass("jstree-no-dots")},toggle_dots:function(){this._data.core.themes.dots?this.hide_dots():this.show_dots()},show_icons:function(){this._data.core.themes.icons=!0,this.get_container_ul().removeClass("jstree-no-icons")},hide_icons:function(){this._data.core.themes.icons=!1,this.get_container_ul().addClass("jstree-no-icons")},toggle_icons:function(){this._data.core.themes.icons?this.hide_icons():this.show_icons()},set_icon:function(t,i){var n,r,s,a;if(e.isArray(t)){for(t=t.slice(),n=0,r=t.length;r>n;n++)this.set_icon(t[n],i);return!0}return t=this.get_node(t),t&&"#"!==t.id?(a=t.icon,t.icon=i,s=this.get_node(t,!0).children(".jstree-anchor").children(".jstree-themeicon"),i===!1?this.hide_icon(t):i===!0?s.removeClass("jstree-themeicon-custom "+a).css("background","").removeAttr("rel"):-1===i.indexOf("/")&&-1===i.indexOf(".")?(s.removeClass(a).css("background",""),s.addClass(i+" jstree-themeicon-custom").attr("rel",i)):(s.removeClass(a).css("background",""),s.addClass("jstree-themeicon-custom").css("background","url('"+i+"') center center no-repeat").attr("rel",i)),!0):!1},get_icon:function(e){return e=this.get_node(e),e&&"#"!==e.id?e.icon:!1},hide_icon:function(t){var i,n;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.hide_icon(t[i]);return!0}return t=this.get_node(t),t&&"#"!==t?(t.icon=!1,this.get_node(t,!0).children("a").children(".jstree-themeicon").addClass("jstree-themeicon-hidden"),!0):!1},show_icon:function(t){var i,n,r;if(e.isArray(t)){for(t=t.slice(),i=0,n=t.length;n>i;i++)this.show_icon(t[i]);return!0}return t=this.get_node(t),t&&"#"!==t?(r=this.get_node(t,!0),t.icon=r.length?r.children("a").children(".jstree-themeicon").attr("rel"):!0,t.icon||(t.icon=!0),r.children("a").children(".jstree-themeicon").removeClass("jstree-themeicon-hidden"),!0):!1}},e.vakata={},e.fn.vakata_reverse=[].reverse,e.vakata.attributes=function(t,i){t=e(t)[0];var n=i?{}:[];return t&&t.attributes&&e.each(t.attributes,function(t,r){-1===e.inArray(r.nodeName.toLowerCase(),["style","contenteditable","hasfocus","tabindex"])&&null!==r.nodeValue&&""!==e.trim(r.nodeValue)&&(i?n[r.nodeName]=r.nodeValue:n.push(r.nodeName))}),n},e.vakata.array_unique=function(e){var t,i,n,r=[];for(t=0,n=e.length;n>t;t++){for(i=0;t>=i&&e[t]!==e[i];i++);i===t&&r.push(e[t])}return r},e.vakata.array_remove=function(e,t,i){var n=e.slice((i||t)+1||e.length);return e.length=0>t?e.length+t:t,e.push.apply(e,n),e},e.vakata.array_remove_item=function(t,i){var n=e.inArray(i,t);return-1!==n?e.vakata.array_remove(t,n):t},function(){var t={},i=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},n=i(window.navigator.userAgent);n.browser&&(t[n.browser]=!0,t.version=n.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),e.vakata.browser=t}(),e.vakata.browser.msie&&e.vakata.browser.version<8&&(e.jstree.defaults.core.animation=0);var _=document.createElement("I");_.className="jstree-icon jstree-checkbox",e.jstree.defaults.checkbox={visible:!0,three_state:!0,whole_node:!0,keep_selected_style:!0},e.jstree.plugins.checkbox=function(t,i){this.bind=function(){i.bind.call(this),this._data.checkbox.uto=!1,this.element.on("init.jstree",e.proxy(function(){this._data.checkbox.visible=this.settings.checkbox.visible,this.settings.checkbox.keep_selected_style||this.element.addClass("jstree-checkbox-no-clicked")},this)).on("loading.jstree",e.proxy(function(){this[this._data.checkbox.visible?"show_checkboxes":"hide_checkboxes"]()},this)),this.settings.checkbox.three_state&&this.element.on("changed.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree",e.proxy(function(){this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(e.proxy(this._undetermined,this),50)},this)).on("model.jstree",e.proxy(function(t,i){var n,r,s,a,o,d,l=this._model.data,c=l[i.parent],h=i.nodes,_=[];if(c.state.selected){for(r=0,s=h.length;s>r;r++)l[h[r]].state.selected=!0;this._data.core.selected=this._data.core.selected.concat(h)}else for(r=0,s=h.length;s>r;r++)if(l[h[r]].state.selected){for(a=0,o=l[h[r]].children_d.length;o>a;a++)l[l[h[r]].children_d[a]].state.selected=!0;this._data.core.selected=this._data.core.selected.concat(l[h[r]].children_d)}for(r=0,s=c.children_d.length;s>r;r++)l[c.children_d[r]].children.length||_.push(l[c.children_d[r]].parent);for(_=e.vakata.array_unique(_),a=0,o=_.length;o>a;a++)for(c=l[_[a]];c&&"#"!==c.id;){for(n=0,r=0,s=c.children.length;s>r;r++)n+=l[c.children[r]].state.selected;if(n!==s)break;c.state.selected=!0,this._data.core.selected.push(c.id),d=this.get_node(c,!0),d&&d.length&&d.children(".jstree-anchor").addClass("jstree-clicked"),c=this.get_node(c.parent)}this._data.core.selected=e.vakata.array_unique(this._data.core.selected)},this)).on("select_node.jstree",e.proxy(function(t,i){var n,r,s,a,o=i.node,d=this._model.data,l=this.get_node(o.parent),c=this.get_node(o,!0);for(this._data.core.selected=e.vakata.array_unique(this._data.core.selected.concat(o.children_d)),n=0,r=o.children_d.length;r>n;n++)d[o.children_d[n]].state.selected=!0;for(;l&&"#"!==l.id;){for(s=0,n=0,r=l.children.length;r>n;n++)s+=d[l.children[n]].state.selected;if(s!==r)break;l.state.selected=!0,this._data.core.selected.push(l.id),a=this.get_node(l,!0),a&&a.length&&a.children(".jstree-anchor").addClass("jstree-clicked"),l=this.get_node(l.parent)}c.length&&c.find(".jstree-anchor").addClass("jstree-clicked")},this)).on("deselect_node.jstree",e.proxy(function(t,i){var n,r,s,a=i.node,o=this.get_node(a,!0);for(n=0,r=a.children_d.length;r>n;n++)this._model.data[a.children_d[n]].state.selected=!1;for(n=0,r=a.parents.length;r>n;n++)this._model.data[a.parents[n]].state.selected=!1,s=this.get_node(a.parents[n],!0),s&&s.length&&s.children(".jstree-anchor").removeClass("jstree-clicked");for(s=[],n=0,r=this._data.core.selected.length;r>n;n++)-1===e.inArray(this._data.core.selected[n],a.children_d)&&-1===e.inArray(this._data.core.selected[n],a.parents)&&s.push(this._data.core.selected[n]);this._data.core.selected=e.vakata.array_unique(s),o.length&&o.find(".jstree-anchor").removeClass("jstree-clicked")},this)).on("delete_node.jstree",e.proxy(function(e,t){for(var i,n,r,s,a=this.get_node(t.parent),o=this._model.data;a&&"#"!==a.id;){for(r=0,i=0,n=a.children.length;n>i;i++)r+=o[a.children[i]].state.selected;if(r!==n)break;a.state.selected=!0,this._data.core.selected.push(a.id),s=this.get_node(a,!0),s&&s.length&&s.children(".jstree-anchor").addClass("jstree-clicked"),a=this.get_node(a.parent)}},this)).on("move_node.jstree",e.proxy(function(t,i){var n,r,s,a,o,d=i.is_multi,l=i.old_parent,c=this.get_node(i.parent),h=this._model.data;if(!d)for(n=this.get_node(l);n&&"#"!==n.id;){for(r=0,s=0,a=n.children.length;a>s;s++)r+=h[n.children[s]].state.selected;if(r!==a)break;n.state.selected=!0,this._data.core.selected.push(n.id),o=this.get_node(n,!0),o&&o.length&&o.children(".jstree-anchor").addClass("jstree-clicked"),n=this.get_node(n.parent)}for(n=c;n&&"#"!==n.id;){for(r=0,s=0,a=n.children.length;a>s;s++)r+=h[n.children[s]].state.selected;if(r===a)n.state.selected||(n.state.selected=!0,this._data.core.selected.push(n.id),o=this.get_node(n,!0),o&&o.length&&o.children(".jstree-anchor").addClass("jstree-clicked"));else{if(!n.state.selected)break;n.state.selected=!1,this._data.core.selected=e.vakata.array_remove_item(this._data.core.selected,n.id),o=this.get_node(n,!0),o&&o.length&&o.children(".jstree-anchor").removeClass("jstree-clicked")}n=this.get_node(n.parent)}},this))},this._undetermined=function(){var t,i,n=this._model.data,r=this._data.core.selected,s=[],a=this;for(t=0,i=r.length;i>t;t++)n[r[t]]&&n[r[t]].parents&&(s=s.concat(n[r[t]].parents));for(this.element.find(".jstree-closed").not(":has(ul)").each(function(){var e=a.get_node(this);!e.state.loaded&&e.original&&e.original.state&&e.original.state.undetermined&&e.original.state.undetermined===!0&&(s.push(e.id),s=s.concat(e.parents))}),s=e.vakata.array_unique(s),t=e.inArray("#",s),-1!==t&&(s=e.vakata.array_remove(s,t)),this.element.find(".jstree-undetermined").removeClass("jstree-undetermined"),t=0,i=s.length;i>t;t++)n[s[t]].state.selected||(r=this.get_node(s[t],!0),r&&r.length&&r.children("a").children(".jstree-checkbox").addClass("jstree-undetermined"))},this.redraw_node=function(t,n,r){if(t=i.redraw_node.call(this,t,n,r)){var s=t.getElementsByTagName("A")[0];s.insertBefore(_.cloneNode(),s.childNodes[0])}return!r&&this.settings.checkbox.three_state&&(this._data.checkbox.uto&&clearTimeout(this._data.checkbox.uto),this._data.checkbox.uto=setTimeout(e.proxy(this._undetermined,this),50)),t},this.activate_node=function(t,n){return(this.settings.checkbox.whole_node||e(n.target).hasClass("jstree-checkbox"))&&(n.ctrlKey=!0),i.activate_node.call(this,t,n)},this.show_checkboxes=function(){this._data.core.themes.checkboxes=!0,this.element.children("ul").removeClass("jstree-no-checkboxes")},this.hide_checkboxes=function(){this._data.core.themes.checkboxes=!1,this.element.children("ul").addClass("jstree-no-checkboxes")},this.toggle_checkboxes=function(){this._data.core.themes.checkboxes?this.hide_checkboxes():this.show_checkboxes()}},e.jstree.defaults.contextmenu={select_node:!0,show_at_node:!0,items:function(t,i){return{create:{separator_before:!1,separator_after:!0,_disabled:!1,label:"Create",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.create_node(n,{},"last",function(e){setTimeout(function(){i.edit(e)},0)})}},rename:{separator_before:!1,separator_after:!1,_disabled:!1,label:"Rename",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.edit(n)}},remove:{separator_before:!1,icon:!1,separator_after:!1,_disabled:!1,label:"Delete",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.delete_node(i.is_selected(n)?i.get_selected():n)}},ccp:{separator_before:!0,icon:!1,separator_after:!1,label:"Edit",action:!1,submenu:{cut:{separator_before:!1,separator_after:!1,label:"Cut",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.cut(i.is_selected(n)?i.get_selected():n)}},copy:{separator_before:!1,icon:!1,separator_after:!1,label:"Copy",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.copy(i.is_selected(n)?i.get_selected():n)}},paste:{separator_before:!1,icon:!1,_disabled:function(t){return!e.jstree.reference(t.reference).can_paste()},separator_after:!1,label:"Paste",action:function(t){var i=e.jstree.reference(t.reference),n=i.get_node(t.reference);i.paste(n)}}}}}}},e.jstree.plugins.contextmenu=function(i,n){this.bind=function(){n.bind.call(this),this.element.on("contextmenu.jstree",".jstree-anchor",e.proxy(function(e){e.preventDefault(),this.is_loading(e.currentTarget)||this.show_contextmenu(e.currentTarget,e.pageX,e.pageY,e)},this)).on("click.jstree",".jstree-anchor",e.proxy(function(t){this._data.contextmenu.visible&&e.vakata.context.hide()},this)),e(document).on("context_hide.vakata",e.proxy(function(){this._data.contextmenu.visible=!1},this))},this.teardown=function(){this._data.contextmenu.visible&&e.vakata.context.hide(),n.teardown.call(this)},this.show_contextmenu=function(i,n,r,s){if(i=this.get_node(i),!i||"#"===i.id)return!1;var a=this.settings.contextmenu,o=this.get_node(i,!0),d=o.children(".jstree-anchor"),l=!1,c=!1;(a.show_at_node||n===t||r===t)&&(l=d.offset(),n=l.left,r=l.top+this._data.core.li_height),this.settings.contextmenu.select_node&&!this.is_selected(i)&&(this.deselect_all(),this.select_node(i,!1,!1,s)),c=a.items,e.isFunction(c)&&(c=c.call(this,i,e.proxy(function(e){this._show_contextmenu(i,n,r,e)},this))),e.isPlainObject(c)&&this._show_contextmenu(i,n,r,c)},this._show_contextmenu=function(t,i,n,r){var s=this.get_node(t,!0),a=s.children(".jstree-anchor");e(document).one("context_show.vakata",e.proxy(function(t,i){var n="jstree-contextmenu jstree-"+this.get_theme()+"-contextmenu";e(i.element).addClass(n)},this)),this._data.contextmenu.visible=!0,e.vakata.context.show(a,{x:i,y:n},r),this.trigger("show_contextmenu",{node:t,x:i,y:n})}},function(e){var t=!1,i={element:!1,reference:!1,position_x:0,position_y:0,items:[],html:"",is_visible:!1};e.vakata.context={settings:{hide_onmouseleave:0,icons:!0},_trigger:function(t){e(document).triggerHandler("context_"+t+".vakata",{reference:i.reference,element:i.element,position:{x:i.position_x,y:i.position_y}})},_execute:function(t){return t=i.items[t],t&&(!t._disabled||e.isFunction(t._disabled)&&!t._disabled({item:t,reference:i.reference,element:i.element}))&&t.action?t.action.call(null,{item:t,reference:i.reference,element:i.element,position:{x:i.position_x,y:i.position_y}}):!1},_parse:function(t,n){if(!t)return!1;n||(i.html="",i.items=[]);var r,s="",a=!1;return n&&(s+=""),e.each(t,function(t,n){return n?(i.items.push(n),!a&&n.separator_before&&(s+=" "),a=!1,s+="",s+="",e.vakata.context.settings.icons&&(s+=" "),s+=n.label+(n.shortcut?' '+(n.shortcut_label||"")+"":"")+"",n.submenu&&(r=e.vakata.context._parse(n.submenu,!0),r&&(s+=r)),s+="",void(n.separator_after&&(s+=" ",a=!0))):!0}),s=s.replace(/<\/li\>$/,""),n&&(s+=""),n||(i.html=s,e.vakata.context._trigger("parse")),s.length>10?s:!1},_show_submenu:function(i){if(i=e(i),i.length&&i.children("ul").length){var n=i.children("ul"),r=i.offset().left+i.outerWidth(),s=i.offset().top,a=n.width(),o=n.height(),d=e(window).width()+e(window).scrollLeft(),l=e(window).height()+e(window).scrollTop();t?i[r-(a+10+i.outerWidth())<0?"addClass":"removeClass"]("vakata-context-left"):i[r+a+10>d?"addClass":"removeClass"]("vakata-context-right"),s+o+10>l&&n.css("bottom","-1px"),n.show()}},show:function(n,r,s){var a,o,d,l,c,h,_,u,g=!0;switch(i.element&&i.element.length&&i.element.width(""),g){case!r&&!n:return!1;case!!r&&!!n:i.reference=n,i.position_x=r.x,i.position_y=r.y;break;case!r&&!!n:i.reference=n,a=n.offset(),i.position_x=a.left+n.outerHeight(),i.position_y=a.top;break;case!!r&&!n:i.position_x=r.x,i.position_y=r.y}n&&!s&&e(n).data("vakata_contextmenu")&&(s=e(n).data("vakata_contextmenu")),e.vakata.context._parse(s)&&i.element.html(i.html),i.items.length&&(o=i.element,d=i.position_x,l=i.position_y,c=o.width(),h=o.height(),_=e(window).width()+e(window).scrollLeft(),u=e(window).height()+e(window).scrollTop(),t&&(d-=o.outerWidth(),d_&&(d=_-(c+20)),l+h+20>u&&(l=u-(h+20)),i.element.css({left:d,top:l}).show().find("a:eq(0)").focus().parent().addClass("vakata-context-hover"),i.is_visible=!0,e.vakata.context._trigger("show"))},hide:function(){i.is_visible&&(i.element.hide().find("ul").hide().end().find(":focus").blur(),i.is_visible=!1,e.vakata.context._trigger("hide"))}},e(function(){t="rtl"===e("body").css("direction");var n=!1;i.element=e(""),i.element.on("mouseenter","li",function(t){t.stopImmediatePropagation(),e.contains(this,t.relatedTarget)||(n&&clearTimeout(n),i.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end(),e(this).siblings().find("ul").hide().end().end().parentsUntil(".vakata-context","li").addBack().addClass("vakata-context-hover"),e.vakata.context._show_submenu(this))}).on("mouseleave","li",function(t){e.contains(this,t.relatedTarget)||e(this).find(".vakata-context-hover").addBack().removeClass("vakata-context-hover")}).on("mouseleave",function(t){e(this).find(".vakata-context-hover").removeClass("vakata-context-hover"),e.vakata.context.settings.hide_onmouseleave&&(n=setTimeout(function(t){return function(){e.vakata.context.hide()}}(this),e.vakata.context.settings.hide_onmouseleave))}).on("click","a",function(e){e.preventDefault()}).on("mouseup","a",function(t){e(this).blur().parent().hasClass("vakata-context-disabled")||e.vakata.context._execute(e(this).attr("rel"))===!1||e.vakata.context.hide()}).on("keydown","a",function(t){var n=null;switch(t.which){case 13:case 32:t.type="mouseup",t.preventDefault(),e(t.currentTarget).trigger(t);break;case 37:i.is_visible&&(i.element.find(".vakata-context-hover").last().parents("li:eq(0)").find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children("a").focus(),t.stopImmediatePropagation(),t.preventDefault());break;case 38:i.is_visible&&(n=i.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first(),n.length||(n=i.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last()),n.addClass("vakata-context-hover").children("a").focus(),t.stopImmediatePropagation(),t.preventDefault());break;case 39:i.is_visible&&(i.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children("a").focus(),t.stopImmediatePropagation(),t.preventDefault());break;case 40:i.is_visible&&(n=i.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first(),n.length||(n=i.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first()),n.addClass("vakata-context-hover").children("a").focus(),t.stopImmediatePropagation(),t.preventDefault());break;case 27:e.vakata.context.hide(),t.preventDefault()}}).on("keydown",function(e){e.preventDefault();var t=i.element.find(".vakata-contextmenu-shortcut-"+e.which).parent();t.parent().not(".vakata-context-disabled")&&t.mouseup()}).appendTo("body"),e(document).on("mousedown",function(t){i.is_visible&&!e.contains(i.element[0],t.target)&&e.vakata.context.hide()}).on("context_show.vakata",function(e,n){i.element.find("li:has(ul)").children("a").addClass("vakata-context-parent"), +t&&i.element.addClass("vakata-context-rtl").css("direction","rtl"),i.element.find("ul").hide().end()})})}(e),e.jstree.defaults.dnd={copy:!0,open_timeout:500,is_draggable:!0,check_while_dragging:!0},e.jstree.plugins.dnd=function(t,i){this.bind=function(){i.bind.call(this),this.element.on("mousedown touchstart",".jstree-anchor",e.proxy(function(t){var i=this.get_node(t.target),n=this.is_selected(i)?this.get_selected().length:1;return i&&i.id&&"#"!==i.id&&(1===t.which||"touchstart"===t.type)&&(this.settings.dnd.is_draggable===!0||e.isFunction(this.settings.dnd.is_draggable)&&this.settings.dnd.is_draggable.call(this,i))?(this.element.trigger("mousedown.jstree"),e.vakata.dnd.start(t,{jstree:!0,origin:this,obj:this.get_node(i,!0),nodes:n>1?this.get_selected():[i.id]},''+(n>1?n+" "+this.get_string("nodes"):this.get_text(t.currentTarget,!0))+'+')):void 0},this))}},e(function(){var t=!1,i=!1,n=!1,r=e(' ').hide().appendTo("body");e(document).bind("dnd_start.vakata",function(e,i){t=!1}).bind("dnd_move.vakata",function(s,a){if(n&&clearTimeout(n),a.data.jstree&&(!a.event.target.id||"jstree-marker"!==a.event.target.id)){var o,d,l,c,h,_,u,g,f,p,m,v,y=e.jstree.reference(a.event.target),j=!1,x=!1,k=!1;if(y&&y._data&&y._data.dnd)if(r.attr("class","jstree-"+y.get_theme()),a.helper.children().attr("class","jstree-"+y.get_theme()).find(".jstree-copy:eq(0)")[a.data.origin&&a.data.origin.settings.dnd.copy&&(a.event.metaKey||a.event.ctrlKey)?"show":"hide"](),a.event.target!==y.element[0]&&a.event.target!==y.get_container_ul()[0]||0!==y.get_container_ul().children().length){if(j=e(a.event.target).closest("a"),j&&j.length&&j.parent().is(".jstree-closed, .jstree-open, .jstree-leaf")&&(x=j.offset(),k=a.event.pageY-x.top,l=j.height(),_=l/3>k?["b","i","a"]:k>l-l/3?["a","i","b"]:k>l/2?["i","a","b"]:["i","b","a"],e.each(_,function(s,k){switch(k){case"b":o=x.left-6,d=x.top-5,c=y.get_parent(j),h=j.parent().index();break;case"i":o=x.left-2,d=x.top-5+l/2+1,c=j.parent(),h=0;break;case"a":o=x.left-6,d=x.top-5+l,c=y.get_parent(j),h=j.parent().index()+1}for(u=!0,g=0,f=a.data.nodes.length;f>g;g++)if(p=a.data.origin&&a.data.origin.settings.dnd.copy&&(a.event.metaKey||a.event.ctrlKey)?"copy_node":"move_node",m=h,"move_node"===p&&"a"===k&&a.data.origin&&a.data.origin===y&&c===y.get_parent(a.data.nodes[g])&&(v=y.get_node(c),m>e.inArray(a.data.nodes[g],v.children)&&(m-=1)),u=u&&(y&&y.settings&&y.settings.dnd&&y.settings.dnd.check_while_dragging===!1||y.check(p,a.data.origin&&a.data.origin!==y?a.data.origin.get_node(a.data.nodes[g]):a.data.nodes[g],c,m)),!u){y&&y.last_error&&(i=y.last_error());break}return u?("i"===k&&j.parent().is(".jstree-closed")&&y.settings.dnd.open_timeout&&(n=setTimeout(function(e,t){return function(){e.open_node(t)}}(y,j),y.settings.dnd.open_timeout)),t={ins:y,par:c,pos:h},r.css({left:o+"px",top:d+"px"}).show(),a.helper.find(".jstree-icon:eq(0)").removeClass("jstree-er").addClass("jstree-ok"),i={},_=!0,!1):void 0}),_===!0))return}else{for(u=!0,g=0,f=a.data.nodes.length;f>g&&(u=u&&y.check(a.data.origin&&a.data.origin.settings.dnd.copy&&(a.event.metaKey||a.event.ctrlKey)?"copy_node":"move_node",a.data.origin&&a.data.origin!==y?a.data.origin.get_node(a.data.nodes[g]):a.data.nodes[g],"#","last"),u);g++);if(u)return t={ins:y,par:"#",pos:"last"},r.hide(),void a.helper.find(".jstree-icon:eq(0)").removeClass("jstree-er").addClass("jstree-ok")}t=!1,a.helper.find(".jstree-icon").removeClass("jstree-ok").addClass("jstree-er"),r.hide()}}).bind("dnd_scroll.vakata",function(e,i){i.data.jstree&&(r.hide(),t=!1,i.helper.find(".jstree-icon:eq(0)").removeClass("jstree-ok").addClass("jstree-er"))}).bind("dnd_stop.vakata",function(s,a){if(n&&clearTimeout(n),a.data.jstree){r.hide();var o,d,l=[];if(t){for(o=0,d=a.data.nodes.length;d>o;o++)l[o]=a.data.origin?a.data.origin.get_node(a.data.nodes[o]):a.data.nodes[o];t.ins[a.data.origin&&a.data.origin.settings.dnd.copy&&(a.event.metaKey||a.event.ctrlKey)?"copy_node":"move_node"](l,t.par,t.pos)}else o=e(a.event.target).closest(".jstree"),o.length&&i&&i.error&&"check"===i.error&&(o=o.jstree(!0),o&&o.settings.core.error.call(this,i))}}).bind("keyup keydown",function(t,i){i=e.vakata.dnd._get(),i.data&&i.data.jstree&&i.helper.find(".jstree-copy:eq(0)")[i.data.origin&&i.data.origin.settings.dnd.copy&&(t.metaKey||t.ctrlKey)?"show":"hide"]()})}),function(e){e.fn.vakata_reverse=[].reverse;var t={element:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1};e.vakata.dnd={settings:{scroll_speed:10,scroll_proximity:20,helper_left:5,helper_top:10,threshold:5},_trigger:function(t,i){var n=e.vakata.dnd._get();n.event=i,e(document).triggerHandler("dnd_"+t+".vakata",n)},_get:function(){return{data:t.data,element:t.element,helper:t.helper}},_clean:function(){t.helper&&t.helper.remove(),t.scroll_i&&(clearInterval(t.scroll_i),t.scroll_i=!1),t={element:!1,is_down:!1,is_drag:!1,helper:!1,helper_w:0,data:!1,init_x:0,init_y:0,scroll_l:0,scroll_t:0,scroll_e:!1,scroll_i:!1},e(document).off("mousemove touchmove",e.vakata.dnd.drag),e(document).off("mouseup touchend",e.vakata.dnd.stop)},_scroll:function(i){if(!t.scroll_e||!t.scroll_l&&!t.scroll_t)return t.scroll_i&&(clearInterval(t.scroll_i),t.scroll_i=!1),!1;if(!t.scroll_i)return t.scroll_i=setInterval(e.vakata.dnd._scroll,100),!1;if(i===!0)return!1;var n=t.scroll_e.scrollTop(),r=t.scroll_e.scrollLeft();t.scroll_e.scrollTop(n+t.scroll_t*e.vakata.dnd.settings.scroll_speed),t.scroll_e.scrollLeft(r+t.scroll_l*e.vakata.dnd.settings.scroll_speed),(n!==t.scroll_e.scrollTop()||r!==t.scroll_e.scrollLeft())&&e.vakata.dnd._trigger("scroll",t.scroll_e)},start:function(i,n,r){"touchstart"===i.type&&i.originalEvent&&i.originalEvent.changedTouches&&i.originalEvent.changedTouches[0]&&(i.pageX=i.originalEvent.changedTouches[0].pageX,i.pageY=i.originalEvent.changedTouches[0].pageY,i.target=document.elementFromPoint(i.originalEvent.changedTouches[0].pageX-window.pageXOffset,i.originalEvent.changedTouches[0].pageY-window.pageYOffset)),t.is_drag&&e.vakata.dnd.stop({});try{i.currentTarget.unselectable="on",i.currentTarget.onselectstart=function(){return!1},i.currentTarget.style&&(i.currentTarget.style.MozUserSelect="none")}catch(s){}return t.init_x=i.pageX,t.init_y=i.pageY,t.data=n,t.is_down=!0,t.element=i.currentTarget,r!==!1&&(t.helper=e("").html(r).css({display:"block",margin:"0",padding:"0",position:"absolute",top:"-2000px",lineHeight:"16px",zIndex:"10000"})),e(document).bind("mousemove touchmove",e.vakata.dnd.drag),e(document).bind("mouseup touchend",e.vakata.dnd.stop),!1},drag:function(i){if("touchmove"===i.type&&i.originalEvent&&i.originalEvent.changedTouches&&i.originalEvent.changedTouches[0]&&(i.pageX=i.originalEvent.changedTouches[0].pageX,i.pageY=i.originalEvent.changedTouches[0].pageY,i.target=document.elementFromPoint(i.originalEvent.changedTouches[0].pageX-window.pageXOffset,i.originalEvent.changedTouches[0].pageY-window.pageYOffset)),t.is_down){if(!t.is_drag){if(!(Math.abs(i.pageX-t.init_x)>e.vakata.dnd.settings.threshold||Math.abs(i.pageY-t.init_y)>e.vakata.dnd.settings.threshold))return;t.helper&&(t.helper.appendTo("body"),t.helper_w=t.helper.outerWidth()),t.is_drag=!0,e.vakata.dnd._trigger("start",i)}var n=!1,r=!1,s=!1,a=!1,o=!1,d=!1,l=!1,c=!1,h=!1,_=!1;t.scroll_t=0,t.scroll_l=0,t.scroll_e=!1,e(i.target).parentsUntil("body").addBack().vakata_reverse().filter(function(){return/^auto|scroll$/.test(e(this).css("overflow"))&&(this.scrollHeight>this.offsetHeight||this.scrollWidth>this.offsetWidth)}).each(function(){var n=e(this),r=n.offset();return this.scrollHeight>this.offsetHeight&&(r.top+n.height()-i.pageYthis.offsetWidth&&(r.left+n.width()-i.pageXa&&i.pageY-la&&a-(i.pageY-l)d&&i.pageX-cd&&d-(i.pageX-c)s&&(h=s-50),o&&_+t.helper_w>o&&(_=o-(t.helper_w+2)),t.helper.css({left:_+"px",top:h+"px"})),e.vakata.dnd._trigger("move",i)}},stop:function(i){"touchend"===i.type&&i.originalEvent&&i.originalEvent.changedTouches&&i.originalEvent.changedTouches[0]&&(i.pageX=i.originalEvent.changedTouches[0].pageX,i.pageY=i.originalEvent.changedTouches[0].pageY,i.target=document.elementFromPoint(i.originalEvent.changedTouches[0].pageX-window.pageXOffset,i.originalEvent.changedTouches[0].pageY-window.pageYOffset)),t.is_drag&&e.vakata.dnd._trigger("stop",i),e.vakata.dnd._clean()}}}(jQuery),e.jstree.defaults.search={ajax:!1,fuzzy:!0,case_sensitive:!1,show_only_matches:!1,close_opened_onclear:!0},e.jstree.plugins.search=function(t,i){this.bind=function(){i.bind.call(this),this._data.search.str="",this._data.search.dom=e(),this._data.search.res=[],this._data.search.opn=[],this._data.search.sln=null,this.settings.search.show_only_matches&&this.element.on("search.jstree",function(t,i){i.nodes.length&&(e(this).find("li").hide().filter(".jstree-last").filter(function(){return this.nextSibling}).removeClass("jstree-last"),i.nodes.parentsUntil(".jstree").addBack().show().filter("ul").each(function(){e(this).children("li:visible").eq(-1).addClass("jstree-last")}))}).on("clear_search.jstree",function(t,i){i.nodes.length&&e(this).find("li").css("display","").filter(".jstree-last").filter(function(){return this.nextSibling}).removeClass("jstree-last")})},this.search=function(t,i){if(t===!1||""===e.trim(t))return this.clear_search();var n,r,s=this.settings.search,a=s.ajax?e.extend({},s.ajax):!1,o=null,d=[],l=[];if(this._data.search.res.length&&this.clear_search(),!i&&a!==!1)return a.data||(a.data={}),a.data.str=t,e.ajax(a).fail(e.proxy(function(){this._data.core.last_error={error:"ajax",plugin:"search",id:"search_01",reason:"Could not load search parents",data:JSON.stringify(a)},this.settings.core.error.call(this,this._data.core.last_error)},this)).done(e.proxy(function(i){i&&i.d&&(i=i.d),this._data.search.sln=e.isArray(i)?i:[],this._search_load(t)},this));if(this._data.search.str=t,this._data.search.dom=e(),this._data.search.res=[],this._data.search.opn=[],o=new e.vakata.search(t,!0,{caseSensitive:s.case_sensitive,fuzzy:s.fuzzy}),e.each(this._model.data,function(e,t){t.text&&o.search(t.text).isMatch&&(d.push(e),l=l.concat(t.parents))}),d.length){for(l=e.vakata.array_unique(l),this._search_open(l),n=0,r=d.length;r>n;n++)o=this.get_node(d[n],!0),o&&(this._data.search.dom=this._data.search.dom.add(o));this._data.search.res=d,this._data.search.dom.children(".jstree-anchor").addClass("jstree-search")}this.trigger("search",{nodes:this._data.search.dom,str:t,res:this._data.search.res})},this.clear_search=function(){this._data.search.dom.children(".jstree-anchor").removeClass("jstree-search"),this.settings.search.close_opened_onclear&&this.close_node(this._data.search.opn,0),this.trigger("clear_search",{nodes:this._data.search.dom,str:this._data.search.str,res:this._data.search.res}),this._data.search.str="",this._data.search.res=[],this._data.search.opn=[],this._data.search.dom=e()},this._search_open=function(t){var i=this;e.each(t.concat([]),function(e,n){n=document.getElementById(n),n&&i.is_closed(n)&&(i._data.search.opn.push(n.id),i.open_node(n,function(){i._search_open(t)},0))})},this._search_load=function(t){var i=!0,n=this,r=n._model.data;e.isArray(this._data.search.sln)&&(this._data.search.sln.length?(e.each(this._data.search.sln,function(s,a){r[a]&&(e.vakata.array_remove_item(n._data.search.sln,a),r[a].state.loaded||(n.load_node(a,function(e,i){i&&n._search_load(t)}),i=!1))}),i&&(this._data.search.sln=[],this._search_load(t))):(this._data.search.sln=null,this.search(t,!0)))}},function(e){e.vakata.search=function(e,t,i){i=i||{},i.fuzzy!==!1&&(i.fuzzy=!0),e=i.caseSensitive?e:e.toLowerCase();var n,r,s,a,o=i.location||0,d=i.distance||100,l=i.threshold||.6,c=e.length;return c>32&&(i.fuzzy=!1),i.fuzzy&&(n=1<i;i++)t[e.charAt(i)]=0;for(i=0;c>i;i++)t[e.charAt(i)]|=1<a;a++){for(h=0,_=x;_>h;)s(a,o+_)<=y?h=_:x=_,_=Math.floor((x-h)/2+h);for(x=_,g=Math.max(1,o-_+1),f=Math.min(o+_,v)+c,p=new Array(f+2),p[f+1]=(1<=g;d--)if(m=r[t.charAt(d-1)],p[d]=0===a?(p[d+1]<<1|1)&m:(p[d+1]<<1|1)&m|((u[d+1]|u[d])<<1|1)|u[d+1],p[d]&n&&(k=s(a,d-1),y>=k)){if(y=k,j=d-1,b.push(j),!(j>o))break;g=Math.max(1,2*o-j)}if(s(a+1,o)>y)break;u=p}return{isMatch:j>=0,score:k}},t===!0?{search:a}:a(t)}}(jQuery),e.jstree.defaults.sort=function(e,t){return this.get_text(e)>this.get_text(t)?1:-1},e.jstree.plugins.sort=function(t,i){this.bind=function(){i.bind.call(this),this.element.on("model.jstree",e.proxy(function(e,t){this.sort(t.parent,!0)},this)).on("rename_node.jstree create_node.jstree",e.proxy(function(e,t){this.sort(t.parent||t.node.parent,!1),this.redraw_node(t.parent||t.node.parent,!0)},this)).on("move_node.jstree copy_node.jstree",e.proxy(function(e,t){this.sort(t.parent,!1),this.redraw_node(t.parent,!0)},this))},this.sort=function(t,i){var n,r;if(t=this.get_node(t),t&&t.children&&t.children.length&&(t.children.sort(e.proxy(this.settings.sort,this)),i))for(n=0,r=t.children_d.length;r>n;n++)this.sort(t.children_d[n],!1)}};var u=!1;e.jstree.defaults.state={key:"jstree",events:"changed.jstree open_node.jstree close_node.jstree",ttl:!1,filter:!1},e.jstree.plugins.state=function(t,i){this.bind=function(){i.bind.call(this);var t=e.proxy(function(){this.element.on(this.settings.state.events,e.proxy(function(){u&&clearTimeout(u),u=setTimeout(e.proxy(function(){this.save_state()},this),100)},this))},this);this.element.on("ready.jstree",e.proxy(function(e,i){this.element.one("restore_state.jstree",t),this.restore_state()||t()},this))},this.save_state=function(){var t={state:this.get_state(),ttl:this.settings.state.ttl,sec:+new Date};e.vakata.storage.set(this.settings.state.key,JSON.stringify(t))},this.restore_state=function(){var t=e.vakata.storage.get(this.settings.state.key);if(t)try{t=JSON.parse(t)}catch(i){return!1}return t&&t.ttl&&t.sec&&+new Date-t.sec>t.ttl?!1:(t&&t.state&&(t=t.state),t&&e.isFunction(this.settings.state.filter)&&(t=this.settings.state.filter.call(this,t)),t?(this.element.one("set_state.jstree",function(i,n){n.instance.trigger("restore_state",{state:e.extend(!0,{},t)})}),this.set_state(t),!0):!1)},this.clear_state=function(){return e.vakata.storage.del(this.settings.state.key)}},function(e,t){e.vakata.storage={set:function(e,t){return window.localStorage.setItem(e,t)},get:function(e){return window.localStorage.getItem(e)},del:function(e){return window.localStorage.removeItem(e)}}}(jQuery),e.jstree.defaults.types={"#":{},"default":{}},e.jstree.plugins.types=function(i,n){this.init=function(e,i){var r,s;if(i&&i.types&&i.types["default"])for(r in i.types)if("default"!==r&&"#"!==r&&i.types.hasOwnProperty(r))for(s in i.types["default"])i.types["default"].hasOwnProperty(s)&&i.types[r][s]===t&&(i.types[r][s]=i.types["default"][s]);n.init.call(this,e,i),this._model.data["#"].type="#"},this.bind=function(){n.bind.call(this),this.element.on("model.jstree",e.proxy(function(e,i){var n,r,s=this._model.data,a=i.nodes,o=this.settings.types,d="default";for(n=0,r=a.length;r>n;n++)d="default",s[a[n]].original&&s[a[n]].original.type&&o[s[a[n]].original.type]&&(d=s[a[n]].original.type),s[a[n]].data&&s[a[n]].data.jstree&&s[a[n]].data.jstree.type&&o[s[a[n]].data.jstree.type]&&(d=s[a[n]].data.jstree.type),s[a[n]].type=d,s[a[n]].icon===!0&&o[d].icon!==t&&(s[a[n]].icon=o[d].icon)},this))},this.get_json=function(t,i,r){var s,a,o=this._model.data,d=i?e.extend(!0,{},i,{no_id:!1}):{},l=n.get_json.call(this,t,d,r);if(l===!1)return!1;if(e.isArray(l))for(s=0,a=l.length;a>s;s++)l[s].type=l[s].id&&o[l[s].id]&&o[l[s].id].type?o[l[s].id].type:"default",i&&i.no_id&&(delete l[s].id,l[s].li_attr&&l[s].li_attr.id&&delete l[s].li_attr.id);else l.type=l.id&&o[l.id]&&o[l.id].type?o[l.id].type:"default",i&&i.no_id&&(l=this._delete_ids(l));return l},this._delete_ids=function(t){if(e.isArray(t)){for(var i=0,n=t.length;n>i;i++)t[i]=this._delete_ids(t[i]);return t}return delete t.id,t.li_attr&&t.li_attr.id&&delete t.li_attr.id,t.children&&e.isArray(t.children)&&(t.children=this._delete_ids(t.children)),t},this.check=function(i,r,s,a){if(n.check.call(this,i,r,s,a)===!1)return!1;r=r&&r.id?r:this.get_node(r),s=s&&s.id?s:this.get_node(s);var o,d,l,c,h=r&&r.id?e.jstree.reference(r.id):null;switch(h=h&&h._model&&h._model.data?h._model.data:null,i){case"create_node":case"move_node":case"copy_node":if("move_node"!==i||-1===e.inArray(r.id,s.children)){if(o=this.get_rules(s),o.max_children!==t&&-1!==o.max_children&&o.max_children===s.children.length)return this._data.core.last_error={error:"check",plugin:"types",id:"types_01",reason:"max_children prevents function: "+i,data:JSON.stringify({chk:i,pos:a,obj:r&&r.id?r.id:!1,par:s&&s.id?s.id:!1})},!1;if(o.valid_children!==t&&-1!==o.valid_children&&-1===e.inArray(r.type,o.valid_children))return this._data.core.last_error={error:"check",plugin:"types",id:"types_02",reason:"valid_children prevents function: "+i,data:JSON.stringify({chk:i,pos:a,obj:r&&r.id?r.id:!1,par:s&&s.id?s.id:!1})},!1;if(h&&r.children_d&&r.parents){for(d=0,l=0,c=r.children_d.length;c>l;l++)d=Math.max(d,h[r.children_d[l]].parents.length);d=d-r.parents.length+1}(0>=d||d===t)&&(d=1);do{if(o.max_depth!==t&&-1!==o.max_depth&&o.max_depths;s++)this.set_type(i[s],n);return!0}return r=this.settings.types,i=this.get_node(i),r[n]&&i?(o=i.type,d=this.get_icon(i),i.type=n,(d===!0||r[o]&&r[o].icon&&d===r[o].icon)&&this.set_icon(i,r[n].icon!==t?r[n].icon:!0),!0):!1}},e.jstree.plugins.unique=function(t,i){this.check=function(t,n,r,s){if(i.check.call(this,t,n,r,s)===!1)return!1;if(n=n&&n.id?n:this.get_node(n),r=r&&r.id?r:this.get_node(r),!r||!r.children)return!0;var a,o,d="rename_node"===t?s:n.text,l=[],c=this._model.data;for(a=0,o=r.children.length;o>a;a++)l.push(c[r.children[a]].text);switch(t){case"delete_node":return!0;case"rename_node":case"copy_node":return a=-1===e.inArray(d,l),a||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_01",reason:"Child with name "+d+" already exists. Preventing: "+t,data:JSON.stringify({chk:t,pos:s,obj:n&&n.id?n.id:!1,par:r&&r.id?r.id:!1})}),a;case"move_node":return a=n.parent===r.id||-1===e.inArray(d,l),a||(this._data.core.last_error={error:"check",plugin:"unique",id:"unique_01",reason:"Child with name "+d+" already exists. Preventing: "+t,data:JSON.stringify({chk:t,pos:s,obj:n&&n.id?n.id:!1,par:r&&r.id?r.id:!1})}),a}return!0}};var g=document.createElement("DIV");g.setAttribute("unselectable","on"),g.className="jstree-wholerow",g.innerHTML=" ",e.jstree.plugins.wholerow=function(t,i){this.bind=function(){i.bind.call(this),this.element.on("loading",e.proxy(function(){g.style.height=this._data.core.li_height+"px"},this)).on("ready.jstree set_state.jstree",e.proxy(function(){this.hide_dots()},this)).on("ready.jstree",e.proxy(function(){this.get_container_ul().addClass("jstree-wholerow-ul")},this)).on("deselect_all.jstree",e.proxy(function(e,t){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked")},this)).on("changed.jstree",e.proxy(function(e,t){this.element.find(".jstree-wholerow-clicked").removeClass("jstree-wholerow-clicked");var i,n,r=!1;for(i=0,n=t.selected.length;n>i;i++)r=this.get_node(t.selected[i],!0),r&&r.length&&r.children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("open_node.jstree",e.proxy(function(e,t){this.get_node(t.node,!0).find(".jstree-clicked").parent().children(".jstree-wholerow").addClass("jstree-wholerow-clicked")},this)).on("hover_node.jstree dehover_node.jstree",e.proxy(function(e,t){this.get_node(t.node,!0).children(".jstree-wholerow")["hover_node"===e.type?"addClass":"removeClass"]("jstree-wholerow-hovered")},this)).on("contextmenu.jstree",".jstree-wholerow",e.proxy(function(t){t.preventDefault(),e(t.currentTarget).closest("li").children("a:eq(0)").trigger("contextmenu",t)},this)).on("click.jstree",".jstree-wholerow",function(t){t.stopImmediatePropagation();var i=e.Event("click",{metaKey:t.metaKey,ctrlKey:t.ctrlKey,altKey:t.altKey,shiftKey:t.shiftKey});e(t.currentTarget).closest("li").children("a:eq(0)").trigger(i).focus()}).on("click.jstree",".jstree-leaf > .jstree-ocl",e.proxy(function(t){t.stopImmediatePropagation();var i=e.Event("click",{metaKey:t.metaKey,ctrlKey:t.ctrlKey,altKey:t.altKey,shiftKey:t.shiftKey});e(t.currentTarget).closest("li").children("a:eq(0)").trigger(i).focus()},this)).on("mouseover.jstree",".jstree-wholerow, .jstree-icon",e.proxy(function(e){return e.stopImmediatePropagation(),this.hover_node(e.currentTarget),!1},this)).on("mouseleave.jstree",".jstree-node",e.proxy(function(e){this.dehover_node(e.currentTarget)},this))},this.teardown=function(){this.settings.wholerow&&this.element.find(".jstree-wholerow").remove(),i.teardown.call(this)},this.redraw_node=function(t,n,r){if(t=i.redraw_node.call(this,t,n,r)){var s=g.cloneNode(!0);-1!==e.inArray(t.id,this._data.core.selected)&&(s.className+=" jstree-wholerow-clicked"),t.insertBefore(s,t.childNodes[0])}return t}}}}); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.js new file mode 100644 index 000000000..aaab654c6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.js @@ -0,0 +1,2430 @@ +//! moment.js +//! version : 2.5.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +(function (undefined) { + + /************************************ + Constants + ************************************/ + + var moment, + VERSION = "2.5.1", + global = this, + round = Math.round, + i, + + YEAR = 0, + MONTH = 1, + DATE = 2, + HOUR = 3, + MINUTE = 4, + SECOND = 5, + MILLISECOND = 6, + + // internal storage for language config files + languages = {}, + + // moment internal properties + momentProperties = { + _isAMomentObject: null, + _i : null, + _f : null, + _l : null, + _strict : null, + _isUTC : null, + _offset : null, // optional. Combine with _isUTC + _pf : null, + _lang : null // optional + }, + + // check for nodeJS + hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'), + + // ASP.NET json date format regex + aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, + aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, + + // format tokens + formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, + localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, + + // parsing token regexes + parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 + parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 + parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 + parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 + parseTokenDigits = /\d+/, // nonzero number of digits + parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. + parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z + parseTokenT = /T/i, // T (ISO separator) + parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 + parseTokenOrdinal = /\d{1,2}/, + + //strict parsing regexes + parseTokenOneDigit = /\d/, // 0 - 9 + parseTokenTwoDigits = /\d\d/, // 00 - 99 + parseTokenThreeDigits = /\d{3}/, // 000 - 999 + parseTokenFourDigits = /\d{4}/, // 0000 - 9999 + parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 + parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf + + // iso 8601 regex + // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) + isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, + + isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', + + isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ], + + // iso time formats and regexes + isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ], + + // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] + parseTimezoneChunker = /([\+\-]|\d\d)/gi, + + // getter and setter names + proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), + unitMillisecondFactors = { + 'Milliseconds' : 1, + 'Seconds' : 1e3, + 'Minutes' : 6e4, + 'Hours' : 36e5, + 'Days' : 864e5, + 'Months' : 2592e6, + 'Years' : 31536e6 + }, + + unitAliases = { + ms : 'millisecond', + s : 'second', + m : 'minute', + h : 'hour', + d : 'day', + D : 'date', + w : 'week', + W : 'isoWeek', + M : 'month', + y : 'year', + DDD : 'dayOfYear', + e : 'weekday', + E : 'isoWeekday', + gg: 'weekYear', + GG: 'isoWeekYear' + }, + + camelFunctions = { + dayofyear : 'dayOfYear', + isoweekday : 'isoWeekday', + isoweek : 'isoWeek', + weekyear : 'weekYear', + isoweekyear : 'isoWeekYear' + }, + + // format function strings + formatFunctions = {}, + + // tokens to ordinalize and pad + ordinalizeTokens = 'DDD w W M D d'.split(' '), + paddedTokens = 'M D H h m s w W'.split(' '), + + formatTokenFunctions = { + M : function () { + return this.month() + 1; + }, + MMM : function (format) { + return this.lang().monthsShort(this, format); + }, + MMMM : function (format) { + return this.lang().months(this, format); + }, + D : function () { + return this.date(); + }, + DDD : function () { + return this.dayOfYear(); + }, + d : function () { + return this.day(); + }, + dd : function (format) { + return this.lang().weekdaysMin(this, format); + }, + ddd : function (format) { + return this.lang().weekdaysShort(this, format); + }, + dddd : function (format) { + return this.lang().weekdays(this, format); + }, + w : function () { + return this.week(); + }, + W : function () { + return this.isoWeek(); + }, + YY : function () { + return leftZeroFill(this.year() % 100, 2); + }, + YYYY : function () { + return leftZeroFill(this.year(), 4); + }, + YYYYY : function () { + return leftZeroFill(this.year(), 5); + }, + YYYYYY : function () { + var y = this.year(), sign = y >= 0 ? '+' : '-'; + return sign + leftZeroFill(Math.abs(y), 6); + }, + gg : function () { + return leftZeroFill(this.weekYear() % 100, 2); + }, + gggg : function () { + return leftZeroFill(this.weekYear(), 4); + }, + ggggg : function () { + return leftZeroFill(this.weekYear(), 5); + }, + GG : function () { + return leftZeroFill(this.isoWeekYear() % 100, 2); + }, + GGGG : function () { + return leftZeroFill(this.isoWeekYear(), 4); + }, + GGGGG : function () { + return leftZeroFill(this.isoWeekYear(), 5); + }, + e : function () { + return this.weekday(); + }, + E : function () { + return this.isoWeekday(); + }, + a : function () { + return this.lang().meridiem(this.hours(), this.minutes(), true); + }, + A : function () { + return this.lang().meridiem(this.hours(), this.minutes(), false); + }, + H : function () { + return this.hours(); + }, + h : function () { + return this.hours() % 12 || 12; + }, + m : function () { + return this.minutes(); + }, + s : function () { + return this.seconds(); + }, + S : function () { + return toInt(this.milliseconds() / 100); + }, + SS : function () { + return leftZeroFill(toInt(this.milliseconds() / 10), 2); + }, + SSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + SSSS : function () { + return leftZeroFill(this.milliseconds(), 3); + }, + Z : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2); + }, + ZZ : function () { + var a = -this.zone(), + b = "+"; + if (a < 0) { + a = -a; + b = "-"; + } + return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); + }, + z : function () { + return this.zoneAbbr(); + }, + zz : function () { + return this.zoneName(); + }, + X : function () { + return this.unix(); + }, + Q : function () { + return this.quarter(); + } + }, + + lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; + + function defaultParsingFlags() { + // We need to deep clone this object, and es5 standard is not very + // helpful. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso: false + }; + } + + function padToken(func, count) { + return function (a) { + return leftZeroFill(func.call(this, a), count); + }; + } + function ordinalizeToken(func, period) { + return function (a) { + return this.lang().ordinal(func.call(this, a), period); + }; + } + + while (ordinalizeTokens.length) { + i = ordinalizeTokens.pop(); + formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); + } + while (paddedTokens.length) { + i = paddedTokens.pop(); + formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); + } + formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); + + + /************************************ + Constructors + ************************************/ + + function Language() { + + } + + // Moment prototype object + function Moment(config) { + checkOverflow(config); + extend(this, config); + } + + // Duration Constructor + function Duration(duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 0; + + // representation for dateAddRemove + this._milliseconds = +milliseconds + + seconds * 1e3 + // 1000 + minutes * 6e4 + // 1000 * 60 + hours * 36e5; // 1000 * 60 * 60 + // Because of dateAddRemove treats 24 hours as different from a + // day when working around DST, we need to store them separately + this._days = +days + + weeks * 7; + // It is impossible translate months into days without knowing + // which months you are are talking about, so we have to store + // it separately. + this._months = +months + + years * 12; + + this._data = {}; + + this._bubble(); + } + + /************************************ + Helpers + ************************************/ + + + function extend(a, b) { + for (var i in b) { + if (b.hasOwnProperty(i)) { + a[i] = b[i]; + } + } + + if (b.hasOwnProperty("toString")) { + a.toString = b.toString; + } + + if (b.hasOwnProperty("valueOf")) { + a.valueOf = b.valueOf; + } + + return a; + } + + function cloneMoment(m) { + var result = {}, i; + for (i in m) { + if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { + result[i] = m[i]; + } + } + + return result; + } + + function absRound(number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + // left zero fill a number + // see http://jsperf.com/left-zero-filling for performance comparison + function leftZeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } + + // helper function for _.addTime and _.subtractTime + function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months, + minutes, + hours; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + // store the minutes and hours so we can restore them + if (days || months) { + minutes = mom.minute(); + hours = mom.hour(); + } + if (days) { + mom.date(mom.date() + days * isAdding); + } + if (months) { + mom.month(mom.month() + months * isAdding); + } + if (milliseconds && !ignoreUpdateOffset) { + moment.updateOffset(mom, days || months); + } + // restore the minutes and hours after possibly changing dst + if (days || months) { + mom.minute(minutes); + mom.hour(hours); + } + } + + // check if is an array + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return Object.prototype.toString.call(input) === '[object Date]' || + input instanceof Date; + } + + // compare two arrays, return the number of differences + function compareArrays(array1, array2, dontConvert) { + var len = Math.min(array1.length, array2.length), + lengthDiff = Math.abs(array1.length - array2.length), + diffs = 0, + i; + for (i = 0; i < len; i++) { + if ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function normalizeUnits(units) { + if (units) { + var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); + units = unitAliases[units] || camelFunctions[lowered] || lowered; + } + return units; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (inputObject.hasOwnProperty(prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function makeList(field) { + var count, setter; + + if (field.indexOf('week') === 0) { + count = 7; + setter = 'day'; + } + else if (field.indexOf('month') === 0) { + count = 12; + setter = 'month'; + } + else { + return; + } + + moment[field] = function (format, index) { + var i, getter, + method = moment.fn._lang[field], + results = []; + + if (typeof format === 'number') { + index = format; + format = undefined; + } + + getter = function (i) { + var m = moment().utc().set(setter, i); + return method.call(moment.fn._lang, m, format || ''); + }; + + if (index != null) { + return getter(index); + } + else { + for (i = 0; i < count; i++) { + results.push(getter(i)); + } + return results; + } + }; + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; + } + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + function weeksInYear(year, dow, doy) { + return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week; + } + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + function checkOverflow(m) { + var overflow; + if (m._a && m._pf.overflow === -2) { + overflow = + m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : + m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : + m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : + m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : + m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : + m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + m._pf.overflow = overflow; + } + } + + function isValid(m) { + if (m._isValid == null) { + m._isValid = !isNaN(m._d.getTime()) && + m._pf.overflow < 0 && + !m._pf.empty && + !m._pf.invalidMonth && + !m._pf.nullInput && + !m._pf.invalidFormat && + !m._pf.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + m._pf.charsLeftOver === 0 && + m._pf.unusedTokens.length === 0; + } + } + return m._isValid; + } + + function normalizeLanguage(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function makeAs(input, model) { + return model._isUTC ? moment(input).zone(model._offset || 0) : + moment(input).local(); + } + + /************************************ + Languages + ************************************/ + + + extend(Language.prototype, { + + set : function (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + }, + + _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), + months : function (m) { + return this._months[m.month()]; + }, + + _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), + monthsShort : function (m) { + return this._monthsShort[m.month()]; + }, + + monthsParse : function (monthName) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + if (!this._monthsParse[i]) { + mom = moment.utc([2000, i]); + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._monthsParse[i].test(monthName)) { + return i; + } + } + }, + + _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + weekdays : function (m) { + return this._weekdays[m.day()]; + }, + + _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), + weekdaysShort : function (m) { + return this._weekdaysShort[m.day()]; + }, + + _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), + weekdaysMin : function (m) { + return this._weekdaysMin[m.day()]; + }, + + weekdaysParse : function (weekdayName) { + var i, mom, regex; + + if (!this._weekdaysParse) { + this._weekdaysParse = []; + } + + for (i = 0; i < 7; i++) { + // make the regex if we don't have it already + if (!this._weekdaysParse[i]) { + mom = moment([2000, 1]).day(i); + regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); + this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (this._weekdaysParse[i].test(weekdayName)) { + return i; + } + } + }, + + _longDateFormat : { + LT : "h:mm A", + L : "MM/DD/YYYY", + LL : "MMMM D YYYY", + LLL : "MMMM D YYYY LT", + LLLL : "dddd, MMMM D YYYY LT" + }, + longDateFormat : function (key) { + var output = this._longDateFormat[key]; + if (!output && this._longDateFormat[key.toUpperCase()]) { + output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { + return val.slice(1); + }); + this._longDateFormat[key] = output; + } + return output; + }, + + isPM : function (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + }, + + _meridiemParse : /[ap]\.?m?\.?/i, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + }, + + _calendar : { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.apply(mom) : output; + }, + + _relativeTime : { + future : "in %s", + past : "%s ago", + s : "a few seconds", + m : "a minute", + mm : "%d minutes", + h : "an hour", + hh : "%d hours", + d : "a day", + dd : "%d days", + M : "a month", + MM : "%d months", + y : "a year", + yy : "%d years" + }, + relativeTime : function (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + }, + pastFuture : function (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + }, + + ordinal : function (number) { + return this._ordinal.replace("%d", number); + }, + _ordinal : "%d", + + preparse : function (string) { + return string; + }, + + postformat : function (string) { + return string; + }, + + week : function (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + }, + + _week : { + dow : 0, // Sunday is the first day of the week. + doy : 6 // The week that contains Jan 1st is the first week of the year. + }, + + _invalidDate: 'Invalid date', + invalidDate: function () { + return this._invalidDate; + } + }); + + // Loads a language definition into the `languages` cache. The function + // takes a key and optionally values. If not in the browser and no values + // are provided, it will load the language file module. As a convenience, + // this function also returns the language values. + function loadLang(key, values) { + values.abbr = key; + if (!languages[key]) { + languages[key] = new Language(); + } + languages[key].set(values); + return languages[key]; + } + + // Remove a language from the `languages` cache. Mostly useful in tests. + function unloadLang(key) { + delete languages[key]; + } + + // Determines which language definition to use and returns it. + // + // With no parameters, it will return the global language. If you + // pass in a language key, such as 'en', it will return the + // definition for 'en', so long as 'en' has already been loaded using + // moment.lang. + function getLangDefinition(key) { + var i = 0, j, lang, next, split, + get = function (k) { + if (!languages[k] && hasModule) { + try { + require('./lang/' + k); + } catch (e) { } + } + return languages[k]; + }; + + if (!key) { + return moment.fn._lang; + } + + if (!isArray(key)) { + //short-circuit everything else + lang = get(key); + if (lang) { + return lang; + } + key = [key]; + } + + //pick the language from the array + //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + while (i < key.length) { + split = normalizeLanguage(key[i]).split('-'); + j = split.length; + next = normalizeLanguage(key[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + lang = get(split.slice(0, j).join('-')); + if (lang) { + return lang; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return moment.fn._lang; + } + + /************************************ + Formatting + ************************************/ + + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + return input.replace(/^\[|\]$/g, ""); + } + return input.replace(/\\/g, ""); + } + + function makeFormatFunction(format) { + var array = format.match(formattingTokens), i, length; + + for (i = 0, length = array.length; i < length; i++) { + if (formatTokenFunctions[array[i]]) { + array[i] = formatTokenFunctions[array[i]]; + } else { + array[i] = removeFormattingTokens(array[i]); + } + } + + return function (mom) { + var output = ""; + for (i = 0; i < length; i++) { + output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; + } + return output; + }; + } + + // format date using native date object + function formatMoment(m, format) { + + if (!m.isValid()) { + return m.lang().invalidDate(); + } + + format = expandFormat(format, m.lang()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); + } + + function expandFormat(format, lang) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return lang.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + + /************************************ + Parsing + ************************************/ + + + // get the regex to find the next token + function getParseRegexForToken(token, config) { + var a, strict = config._strict; + switch (token) { + case 'DDDD': + return parseTokenThreeDigits; + case 'YYYY': + case 'GGGG': + case 'gggg': + return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; + case 'Y': + case 'G': + case 'g': + return parseTokenSignedNumber; + case 'YYYYYY': + case 'YYYYY': + case 'GGGGG': + case 'ggggg': + return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; + case 'S': + if (strict) { return parseTokenOneDigit; } + /* falls through */ + case 'SS': + if (strict) { return parseTokenTwoDigits; } + /* falls through */ + case 'SSS': + if (strict) { return parseTokenThreeDigits; } + /* falls through */ + case 'DDD': + return parseTokenOneToThreeDigits; + case 'MMM': + case 'MMMM': + case 'dd': + case 'ddd': + case 'dddd': + return parseTokenWord; + case 'a': + case 'A': + return getLangDefinition(config._l)._meridiemParse; + case 'X': + return parseTokenTimestampMs; + case 'Z': + case 'ZZ': + return parseTokenTimezone; + case 'T': + return parseTokenT; + case 'SSSS': + return parseTokenDigits; + case 'MM': + case 'DD': + case 'YY': + case 'GG': + case 'gg': + case 'HH': + case 'hh': + case 'mm': + case 'ss': + case 'ww': + case 'WW': + return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; + case 'M': + case 'D': + case 'd': + case 'H': + case 'h': + case 'm': + case 's': + case 'w': + case 'W': + case 'e': + case 'E': + return parseTokenOneOrTwoDigits; + case 'Do': + return parseTokenOrdinal; + default : + a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i")); + return a; + } + } + + function timezoneMinutesFromString(string) { + string = string || ""; + var possibleTzMatches = (string.match(parseTokenTimezone) || []), + tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], + parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], + minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? -minutes : minutes; + } + + // function to convert string input to date + function addTimeToArrayFromToken(token, input, config) { + var a, datePartArray = config._a; + + switch (token) { + // MONTH + case 'M' : // fall through to MM + case 'MM' : + if (input != null) { + datePartArray[MONTH] = toInt(input) - 1; + } + break; + case 'MMM' : // fall through to MMMM + case 'MMMM' : + a = getLangDefinition(config._l).monthsParse(input); + // if we didn't find a month name, mark the date as invalid. + if (a != null) { + datePartArray[MONTH] = a; + } else { + config._pf.invalidMonth = input; + } + break; + // DAY OF MONTH + case 'D' : // fall through to DD + case 'DD' : + if (input != null) { + datePartArray[DATE] = toInt(input); + } + break; + case 'Do' : + if (input != null) { + datePartArray[DATE] = toInt(parseInt(input, 10)); + } + break; + // DAY OF YEAR + case 'DDD' : // fall through to DDDD + case 'DDDD' : + if (input != null) { + config._dayOfYear = toInt(input); + } + + break; + // YEAR + case 'YY' : + datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + break; + case 'YYYY' : + case 'YYYYY' : + case 'YYYYYY' : + datePartArray[YEAR] = toInt(input); + break; + // AM / PM + case 'a' : // fall through to A + case 'A' : + config._isPm = getLangDefinition(config._l).isPM(input); + break; + // 24 HOUR + case 'H' : // fall through to hh + case 'HH' : // fall through to hh + case 'h' : // fall through to hh + case 'hh' : + datePartArray[HOUR] = toInt(input); + break; + // MINUTE + case 'm' : // fall through to mm + case 'mm' : + datePartArray[MINUTE] = toInt(input); + break; + // SECOND + case 's' : // fall through to ss + case 'ss' : + datePartArray[SECOND] = toInt(input); + break; + // MILLISECOND + case 'S' : + case 'SS' : + case 'SSS' : + case 'SSSS' : + datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); + break; + // UNIX TIMESTAMP WITH MS + case 'X': + config._d = new Date(parseFloat(input) * 1000); + break; + // TIMEZONE + case 'Z' : // fall through to ZZ + case 'ZZ' : + config._useUTC = true; + config._tzm = timezoneMinutesFromString(input); + break; + case 'w': + case 'ww': + case 'W': + case 'WW': + case 'd': + case 'dd': + case 'ddd': + case 'dddd': + case 'e': + case 'E': + token = token.substr(0, 1); + /* falls through */ + case 'gg': + case 'gggg': + case 'GG': + case 'GGGG': + case 'GGGGG': + token = token.substr(0, 2); + if (input) { + config._w = config._w || {}; + config._w[token] = input; + } + break; + } + } + + // convert an array to a date. + // the array should mirror the parameters below + // note: all values past the year are optional and will default to the lowest possible value. + // [year, month, day , hour, minute, second, millisecond] + function dateFromConfig(config) { + var i, date, input = [], currentDate, + yearToUse, fixYear, w, temp, lang, weekday, week; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + fixYear = function (val) { + var int_val = parseInt(val, 10); + return val ? + (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) : + (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]); + }; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1); + } + else { + lang = getLangDefinition(config._l); + weekday = w.d != null ? parseWeekday(w.d, lang) : + (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0); + + week = parseInt(w.w, 10) || 1; + + //if we're parsing 'd', then the low day numbers may be next week + if (w.d != null && weekday < lang._week.dow) { + week++; + } + + temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow); + } + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR]; + + if (config._dayOfYear > daysInYear(yearToUse)) { + config._pf._overflowDayOfYear = true; + } + + date = makeUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // add the offsets to the time to be parsed so that we can have a clean array for checking isValid + input[HOUR] += toInt((config._tzm || 0) / 60); + input[MINUTE] += toInt((config._tzm || 0) % 60); + + config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); + } + + function dateFromObject(config) { + var normalizedInput; + + if (config._d) { + return; + } + + normalizedInput = normalizeObjectUnits(config._i); + config._a = [ + normalizedInput.year, + normalizedInput.month, + normalizedInput.day, + normalizedInput.hour, + normalizedInput.minute, + normalizedInput.second, + normalizedInput.millisecond + ]; + + dateFromConfig(config); + } + + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [ + now.getUTCFullYear(), + now.getUTCMonth(), + now.getUTCDate() + ]; + } else { + return [now.getFullYear(), now.getMonth(), now.getDate()]; + } + } + + // date from string and format string + function makeDateFromStringAndFormat(config) { + + config._a = []; + config._pf.empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var lang = getLangDefinition(config._l), + string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, lang).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + config._pf.unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + config._pf.empty = false; + } + else { + config._pf.unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + config._pf.unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + config._pf.charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + config._pf.unusedInput.push(string); + } + + // handle am pm + if (config._isPm && config._a[HOUR] < 12) { + config._a[HOUR] += 12; + } + // if is 12 am, change hours to 0 + if (config._isPm === false && config._a[HOUR] === 12) { + config._a[HOUR] = 0; + } + + dateFromConfig(config); + checkOverflow(config); + } + + function unescapeFormat(s) { + return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function regexpEscape(s) { + return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + // date from string and array of format strings + function makeDateFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + config._pf.invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = extend({}, config); + tempConfig._pf = defaultParsingFlags(); + tempConfig._f = config._f[i]; + makeDateFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += tempConfig._pf.charsLeftOver; + + //or tokens + currentScore += tempConfig._pf.unusedTokens.length * 10; + + tempConfig._pf.score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + // date from iso format + function makeDateFromString(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); + + if (match) { + config._pf.iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be "T" or undefined + config._f = isoDates[i][0] + (match[6] || " "); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(parseTokenTimezone)) { + config._f += "Z"; + } + makeDateFromStringAndFormat(config); + } + else { + config._d = new Date(string); + } + } + + function makeDateFromInput(config) { + var input = config._i, + matched = aspNetJsonRegex.exec(input); + + if (input === undefined) { + config._d = new Date(); + } else if (matched) { + config._d = new Date(+matched[1]); + } else if (typeof input === 'string') { + makeDateFromString(config); + } else if (isArray(input)) { + config._a = input.slice(0); + dateFromConfig(config); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof(input) === 'object') { + dateFromObject(config); + } else { + config._d = new Date(input); + } + } + + function makeDate(y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } + + function makeUTCDate(y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } + + function parseWeekday(input, language) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = language.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; + } + + /************************************ + Relative Time + ************************************/ + + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { + return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function relativeTime(milliseconds, withoutSuffix, lang) { + var seconds = round(Math.abs(milliseconds) / 1000), + minutes = round(seconds / 60), + hours = round(minutes / 60), + days = round(hours / 24), + years = round(days / 365), + args = seconds < 45 && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < 45 && ['mm', minutes] || + hours === 1 && ['h'] || + hours < 22 && ['hh', hours] || + days === 1 && ['d'] || + days <= 25 && ['dd', days] || + days <= 45 && ['M'] || + days < 345 && ['MM', round(days / 30)] || + years === 1 && ['y'] || ['yy', years]; + args[2] = withoutSuffix; + args[3] = milliseconds > 0; + args[4] = lang; + return substituteTimeAgo.apply({}, args); + } + + + /************************************ + Week of Year + ************************************/ + + + // firstDayOfWeek 0 = sun, 6 = sat + // the day of the week that starts the week + // (usually sunday or monday) + // firstDayOfWeekOfYear 0 = sun, 6 = sat + // the first week is the week that contains the first + // of this day of the week + // (eg. ISO weeks use thursday (4)) + function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { + var end = firstDayOfWeekOfYear - firstDayOfWeek, + daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), + adjustedMoment; + + + if (daysToDayOfWeek > end) { + daysToDayOfWeek -= 7; + } + + if (daysToDayOfWeek < end - 7) { + daysToDayOfWeek += 7; + } + + adjustedMoment = moment(mom).add('d', daysToDayOfWeek); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; + + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year: dayOfYear > 0 ? year : year - 1, + dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } + + /************************************ + Top Level Functions + ************************************/ + + function makeMoment(config) { + var input = config._i, + format = config._f; + + if (input === null) { + return moment.invalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = getLangDefinition().preparse(input); + } + + if (moment.isMoment(input)) { + config = cloneMoment(input); + + config._d = new Date(+input._d); + } else if (format) { + if (isArray(format)) { + makeDateFromStringAndArray(config); + } else { + makeDateFromStringAndFormat(config); + } + } else { + makeDateFromInput(config); + } + + return new Moment(config); + } + + moment = function (input, format, lang, strict) { + var c; + + if (typeof(lang) === "boolean") { + strict = lang; + lang = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._i = input; + c._f = format; + c._l = lang; + c._strict = strict; + c._isUTC = false; + c._pf = defaultParsingFlags(); + + return makeMoment(c); + }; + + // creating with utc + moment.utc = function (input, format, lang, strict) { + var c; + + if (typeof(lang) === "boolean") { + strict = lang; + lang = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c = {}; + c._isAMomentObject = true; + c._useUTC = true; + c._isUTC = true; + c._l = lang; + c._i = input; + c._f = format; + c._strict = strict; + c._pf = defaultParsingFlags(); + + return makeMoment(c).utc(); + }; + + // creating with unix timestamp (in seconds) + moment.unix = function (input) { + return moment(input * 1000); + }; + + // duration + moment.duration = function (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + parseIso; + + if (moment.isDuration(input)) { + duration = { + ms: input._milliseconds, + d: input._days, + M: input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { + sign = (match[1] === "-") ? -1 : 1; + duration = { + y: 0, + d: toInt(match[DATE]) * sign, + h: toInt(match[HOUR]) * sign, + m: toInt(match[MINUTE]) * sign, + s: toInt(match[SECOND]) * sign, + ms: toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoDurationRegex.exec(input))) { + sign = (match[1] === "-") ? -1 : 1; + parseIso = function (inp) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + }; + duration = { + y: parseIso(match[2]), + M: parseIso(match[3]), + d: parseIso(match[4]), + h: parseIso(match[5]), + m: parseIso(match[6]), + s: parseIso(match[7]), + w: parseIso(match[8]) + }; + } + + ret = new Duration(duration); + + if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { + ret._lang = input._lang; + } + + return ret; + }; + + // version number + moment.version = VERSION; + + // default format + moment.defaultFormat = isoFormat; + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + moment.updateOffset = function () {}; + + // This function will load languages and then set the global language. If + // no arguments are passed in, it will simply return the current global + // language key. + moment.lang = function (key, values) { + var r; + if (!key) { + return moment.fn._lang._abbr; + } + if (values) { + loadLang(normalizeLanguage(key), values); + } else if (values === null) { + unloadLang(key); + key = 'en'; + } else if (!languages[key]) { + getLangDefinition(key); + } + r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); + return r._abbr; + }; + + // returns language data + moment.langData = function (key) { + if (key && key._lang && key._lang._abbr) { + key = key._lang._abbr; + } + return getLangDefinition(key); + }; + + // compare moment object + moment.isMoment = function (obj) { + return obj instanceof Moment || + (obj != null && obj.hasOwnProperty('_isAMomentObject')); + }; + + // for typechecking Duration objects + moment.isDuration = function (obj) { + return obj instanceof Duration; + }; + + for (i = lists.length - 1; i >= 0; --i) { + makeList(lists[i]); + } + + moment.normalizeUnits = function (units) { + return normalizeUnits(units); + }; + + moment.invalid = function (flags) { + var m = moment.utc(NaN); + if (flags != null) { + extend(m._pf, flags); + } + else { + m._pf.userInvalidated = true; + } + + return m; + }; + + moment.parseZone = function () { + return moment.apply(null, arguments).parseZone(); + }; + + /************************************ + Moment Prototype + ************************************/ + + + extend(moment.fn = Moment.prototype, { + + clone : function () { + return moment(this); + }, + + valueOf : function () { + return +this._d + ((this._offset || 0) * 60000); + }, + + unix : function () { + return Math.floor(+this / 1000); + }, + + toString : function () { + return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); + }, + + toDate : function () { + return this._offset ? new Date(+this) : this._d; + }, + + toISOString : function () { + var m = moment(this).utc(); + if (0 < m.year() && m.year() <= 9999) { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + }, + + toArray : function () { + var m = this; + return [ + m.year(), + m.month(), + m.date(), + m.hours(), + m.minutes(), + m.seconds(), + m.milliseconds() + ]; + }, + + isValid : function () { + return isValid(this); + }, + + isDSTShifted : function () { + + if (this._a) { + return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; + } + + return false; + }, + + parsingFlags : function () { + return extend({}, this._pf); + }, + + invalidAt: function () { + return this._pf.overflow; + }, + + utc : function () { + return this.zone(0); + }, + + local : function () { + this.zone(0); + this._isUTC = false; + return this; + }, + + format : function (inputString) { + var output = formatMoment(this, inputString || moment.defaultFormat); + return this.lang().postformat(output); + }, + + add : function (input, val) { + var dur; + // switch args to support add('s', 1) and add(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, 1); + return this; + }, + + subtract : function (input, val) { + var dur; + // switch args to support subtract('s', 1) and subtract(1, 's') + if (typeof input === 'string') { + dur = moment.duration(+val, input); + } else { + dur = moment.duration(input, val); + } + addOrSubtractDurationFromMoment(this, dur, -1); + return this; + }, + + diff : function (input, units, asFloat) { + var that = makeAs(input, this), + zoneDiff = (this.zone() - that.zone()) * 6e4, + diff, output; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month') { + // average number of days in the months in the given dates + diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 + // difference in months + output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); + // adjust by taking difference in days, average number of days + // and dst in the given months. + output += ((this - moment(this).startOf('month')) - + (that - moment(that).startOf('month'))) / diff; + // same as above but with zones, to negate all dst + output -= ((this.zone() - moment(this).startOf('month').zone()) - + (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; + if (units === 'year') { + output = output / 12; + } + } else { + diff = (this - that); + output = units === 'second' ? diff / 1e3 : // 1000 + units === 'minute' ? diff / 6e4 : // 1000 * 60 + units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + diff; + } + return asFloat ? output : absRound(output); + }, + + from : function (time, withoutSuffix) { + return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); + }, + + fromNow : function (withoutSuffix) { + return this.from(moment(), withoutSuffix); + }, + + calendar : function () { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're zone'd or not. + var sod = makeAs(moment(), this).startOf('day'), + diff = this.diff(sod, 'days', true), + format = diff < -6 ? 'sameElse' : + diff < -1 ? 'lastWeek' : + diff < 0 ? 'lastDay' : + diff < 1 ? 'sameDay' : + diff < 2 ? 'nextDay' : + diff < 7 ? 'nextWeek' : 'sameElse'; + return this.format(this.lang().calendar(format, this)); + }, + + isLeapYear : function () { + return isLeapYear(this.year()); + }, + + isDST : function () { + return (this.zone() < this.clone().month(0).zone() || + this.zone() < this.clone().month(5).zone()); + }, + + day : function (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.lang()); + return this.add({ d : input - day }); + } else { + return day; + } + }, + + month : function (input) { + var utc = this._isUTC ? 'UTC' : '', + dayOfMonth; + + if (input != null) { + if (typeof input === 'string') { + input = this.lang().monthsParse(input); + if (typeof input !== 'number') { + return this; + } + } + + dayOfMonth = Math.min(this.date(), + daysInMonth(this.year(), input)); + this._d['set' + utc + 'Month'](input, dayOfMonth); + moment.updateOffset(this, true); + return this; + } else { + return this._d['get' + utc + 'Month'](); + } + }, + + startOf: function (units) { + units = normalizeUnits(units); + // the following switch intentionally omits break keywords + // to utilize falling through the cases. + switch (units) { + case 'year': + this.month(0); + /* falls through */ + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + case 'day': + this.hours(0); + /* falls through */ + case 'hour': + this.minutes(0); + /* falls through */ + case 'minute': + this.seconds(0); + /* falls through */ + case 'second': + this.milliseconds(0); + /* falls through */ + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } else if (units === 'isoWeek') { + this.isoWeekday(1); + } + + return this; + }, + + endOf: function (units) { + units = normalizeUnits(units); + return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); + }, + + isAfter: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) > +moment(input).startOf(units); + }, + + isBefore: function (input, units) { + units = typeof units !== 'undefined' ? units : 'millisecond'; + return +this.clone().startOf(units) < +moment(input).startOf(units); + }, + + isSame: function (input, units) { + units = units || 'ms'; + return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); + }, + + min: function (other) { + other = moment.apply(null, arguments); + return other < this ? this : other; + }, + + max: function (other) { + other = moment.apply(null, arguments); + return other > this ? this : other; + }, + + zone : function (input, adjust) { + adjust = (adjust == null ? true : false); + var offset = this._offset || 0; + if (input != null) { + if (typeof input === "string") { + input = timezoneMinutesFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + this._offset = input; + this._isUTC = true; + if (offset !== input && adjust) { + addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true); + } + } else { + return this._isUTC ? offset : this._d.getTimezoneOffset(); + } + return this; + }, + + zoneAbbr : function () { + return this._isUTC ? "UTC" : ""; + }, + + zoneName : function () { + return this._isUTC ? "Coordinated Universal Time" : ""; + }, + + parseZone : function () { + if (this._tzm) { + this.zone(this._tzm); + } else if (typeof this._i === 'string') { + this.zone(this._i); + } + return this; + }, + + hasAlignedHourOffset : function (input) { + if (!input) { + input = 0; + } + else { + input = moment(input).zone(); + } + + return (this.zone() - input) % 60 === 0; + }, + + daysInMonth : function () { + return daysInMonth(this.year(), this.month()); + }, + + dayOfYear : function (input) { + var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); + }, + + quarter : function () { + return Math.ceil((this.month() + 1.0) / 3.0); + }, + + weekYear : function (input) { + var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; + return input == null ? year : this.add("y", (input - year)); + }, + + isoWeekYear : function (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add("y", (input - year)); + }, + + week : function (input) { + var week = this.lang().week(this); + return input == null ? week : this.add("d", (input - week) * 7); + }, + + isoWeek : function (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add("d", (input - week) * 7); + }, + + weekday : function (input) { + var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; + return input == null ? weekday : this.add("d", input - weekday); + }, + + isoWeekday : function (input) { + // behaves the same as moment#day except + // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) + // as a setter, sunday should belong to the previous week. + return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); + }, + + isoWeeksInYear : function () { + return weeksInYear(this.year(), 1, 4); + }, + + weeksInYear : function () { + var weekInfo = this._lang._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units](); + }, + + set : function (units, value) { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + this[units](value); + } + return this; + }, + + // If passed a language key, it will set the language for this + // instance. Otherwise, it will return the language configuration + // variables for this instance. + lang : function (key) { + if (key === undefined) { + return this._lang; + } else { + this._lang = getLangDefinition(key); + return this; + } + } + }); + + // helper for adding shortcuts + function makeGetterAndSetter(name, key) { + // ignoreOffsetTransitions provides a hint to updateOffset to not + // change hours/minutes when crossing a tz boundary. This is frequently + // desirable when modifying part of an existing moment object directly. + var defaultIgnoreOffsetTransitions = key === 'date' || key === 'month' || key === 'year'; + moment.fn[name] = moment.fn[name + 's'] = function (input, ignoreOffsetTransitions) { + var utc = this._isUTC ? 'UTC' : ''; + if (ignoreOffsetTransitions == null) { + ignoreOffsetTransitions = defaultIgnoreOffsetTransitions; + } + if (input != null) { + this._d['set' + utc + key](input); + moment.updateOffset(this, ignoreOffsetTransitions); + return this; + } else { + return this._d['get' + utc + key](); + } + }; + } + + // loop through and add shortcuts (Date, Hours, Minutes, Seconds, Milliseconds) + // Month has a custom getter/setter. + for (i = 0; i < proxyGettersAndSetters.length; i ++) { + makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); + } + + // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') + makeGetterAndSetter('year', 'FullYear'); + + // add plural methods + moment.fn.days = moment.fn.day; + moment.fn.months = moment.fn.month; + moment.fn.weeks = moment.fn.week; + moment.fn.isoWeeks = moment.fn.isoWeek; + + // add aliased format methods + moment.fn.toJSON = moment.fn.toISOString; + + /************************************ + Duration Prototype + ************************************/ + + + extend(moment.duration.fn = Duration.prototype, { + + _bubble : function () { + var milliseconds = this._milliseconds, + days = this._days, + months = this._months, + data = this._data, + seconds, minutes, hours, years; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absRound(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absRound(seconds / 60); + data.minutes = minutes % 60; + + hours = absRound(minutes / 60); + data.hours = hours % 24; + + days += absRound(hours / 24); + data.days = days % 30; + + months += absRound(days / 30); + data.months = months % 12; + + years = absRound(months / 12); + data.years = years; + }, + + weeks : function () { + return absRound(this.days() / 7); + }, + + valueOf : function () { + return this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6; + }, + + humanize : function (withSuffix) { + var difference = +this, + output = relativeTime(difference, !withSuffix, this.lang()); + + if (withSuffix) { + output = this.lang().pastFuture(difference, output); + } + + return this.lang().postformat(output); + }, + + add : function (input, val) { + // supports only 2.0-style add(1, 's') or add(moment) + var dur = moment.duration(input, val); + + this._milliseconds += dur._milliseconds; + this._days += dur._days; + this._months += dur._months; + + this._bubble(); + + return this; + }, + + subtract : function (input, val) { + var dur = moment.duration(input, val); + + this._milliseconds -= dur._milliseconds; + this._days -= dur._days; + this._months -= dur._months; + + this._bubble(); + + return this; + }, + + get : function (units) { + units = normalizeUnits(units); + return this[units.toLowerCase() + 's'](); + }, + + as : function (units) { + units = normalizeUnits(units); + return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); + }, + + lang : moment.fn.lang, + + toIsoString : function () { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var years = Math.abs(this.years()), + months = Math.abs(this.months()), + days = Math.abs(this.days()), + hours = Math.abs(this.hours()), + minutes = Math.abs(this.minutes()), + seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); + + if (!this.asSeconds()) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (this.asSeconds() < 0 ? '-' : '') + + 'P' + + (years ? years + 'Y' : '') + + (months ? months + 'M' : '') + + (days ? days + 'D' : '') + + ((hours || minutes || seconds) ? 'T' : '') + + (hours ? hours + 'H' : '') + + (minutes ? minutes + 'M' : '') + + (seconds ? seconds + 'S' : ''); + } + }); + + function makeDurationGetter(name) { + moment.duration.fn[name] = function () { + return this._data[name]; + }; + } + + function makeDurationAsGetter(name, factor) { + moment.duration.fn['as' + name] = function () { + return +this / factor; + }; + } + + for (i in unitMillisecondFactors) { + if (unitMillisecondFactors.hasOwnProperty(i)) { + makeDurationAsGetter(i, unitMillisecondFactors[i]); + makeDurationGetter(i.toLowerCase()); + } + } + + makeDurationAsGetter('Weeks', 6048e5); + moment.duration.fn.asMonths = function () { + return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; + }; + + + /************************************ + Default Lang + ************************************/ + + + // Set default language, other languages will inherit from English. + moment.lang('en', { + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + /* EMBED_LANGUAGES */ + + /************************************ + Exposing Moment + ************************************/ + + function makeGlobal(deprecate) { + var warned = false, local_moment = moment; + /*global ender:false */ + if (typeof ender !== 'undefined') { + return; + } + // here, `this` means `window` in the browser, or `global` on the server + // add `moment` as a global object via a string identifier, + // for Closure Compiler "advanced" mode + if (deprecate) { + global.moment = function () { + if (!warned && console && console.warn) { + warned = true; + console.warn( + "Accessing Moment through the global scope is " + + "deprecated, and will be removed in an upcoming " + + "release."); + } + return local_moment.apply(null, arguments); + }; + extend(global.moment, local_moment); + } else { + global['moment'] = moment; + } + } + + // CommonJS module is defined + if (hasModule) { + module.exports = moment; + makeGlobal(true); + } else if (typeof define === "function" && define.amd) { + define("moment", function (require, exports, module) { + if (module.config && module.config() && module.config().noGlobal !== true) { + // If user provided noGlobal, he is aware of global + makeGlobal(module.config().noGlobal === undefined); + } + + return moment; + }); + } else { + makeGlobal(); + } +}).call(this); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJtb21lbnQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8hIG1vbWVudC5qc1xyXG4vLyEgdmVyc2lvbiA6IDIuNS4xXHJcbi8vISBhdXRob3JzIDogVGltIFdvb2QsIElza3JlbiBDaGVybmV2LCBNb21lbnQuanMgY29udHJpYnV0b3JzXHJcbi8vISBsaWNlbnNlIDogTUlUXHJcbi8vISBtb21lbnRqcy5jb21cclxuXHJcbihmdW5jdGlvbiAodW5kZWZpbmVkKSB7XHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIENvbnN0YW50c1xyXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xyXG5cclxuICAgIHZhciBtb21lbnQsXHJcbiAgICAgICAgVkVSU0lPTiA9IFwiMi41LjFcIixcclxuICAgICAgICBnbG9iYWwgPSB0aGlzLFxyXG4gICAgICAgIHJvdW5kID0gTWF0aC5yb3VuZCxcclxuICAgICAgICBpLFxyXG5cclxuICAgICAgICBZRUFSID0gMCxcclxuICAgICAgICBNT05USCA9IDEsXHJcbiAgICAgICAgREFURSA9IDIsXHJcbiAgICAgICAgSE9VUiA9IDMsXHJcbiAgICAgICAgTUlOVVRFID0gNCxcclxuICAgICAgICBTRUNPTkQgPSA1LFxyXG4gICAgICAgIE1JTExJU0VDT05EID0gNixcclxuXHJcbiAgICAgICAgLy8gaW50ZXJuYWwgc3RvcmFnZSBmb3IgbGFuZ3VhZ2UgY29uZmlnIGZpbGVzXHJcbiAgICAgICAgbGFuZ3VhZ2VzID0ge30sXHJcblxyXG4gICAgICAgIC8vIG1vbWVudCBpbnRlcm5hbCBwcm9wZXJ0aWVzXHJcbiAgICAgICAgbW9tZW50UHJvcGVydGllcyA9IHtcclxuICAgICAgICAgICAgX2lzQU1vbWVudE9iamVjdDogbnVsbCxcclxuICAgICAgICAgICAgX2kgOiBudWxsLFxyXG4gICAgICAgICAgICBfZiA6IG51bGwsXHJcbiAgICAgICAgICAgIF9sIDogbnVsbCxcclxuICAgICAgICAgICAgX3N0cmljdCA6IG51bGwsXHJcbiAgICAgICAgICAgIF9pc1VUQyA6IG51bGwsXHJcbiAgICAgICAgICAgIF9vZmZzZXQgOiBudWxsLCAgLy8gb3B0aW9uYWwuIENvbWJpbmUgd2l0aCBfaXNVVENcclxuICAgICAgICAgICAgX3BmIDogbnVsbCxcclxuICAgICAgICAgICAgX2xhbmcgOiBudWxsICAvLyBvcHRpb25hbFxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIGNoZWNrIGZvciBub2RlSlNcclxuICAgICAgICBoYXNNb2R1bGUgPSAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgIT09ICd1bmRlZmluZWQnKSxcclxuXHJcbiAgICAgICAgLy8gQVNQLk5FVCBqc29uIGRhdGUgZm9ybWF0IHJlZ2V4XHJcbiAgICAgICAgYXNwTmV0SnNvblJlZ2V4ID0gL15cXC8/RGF0ZVxcKChcXC0/XFxkKykvaSxcclxuICAgICAgICBhc3BOZXRUaW1lU3Bhbkpzb25SZWdleCA9IC8oXFwtKT8oPzooXFxkKilcXC4pPyhcXGQrKVxcOihcXGQrKSg/OlxcOihcXGQrKVxcLj8oXFxkezN9KT8pPy8sXHJcblxyXG4gICAgICAgIC8vIGZyb20gaHR0cDovL2RvY3MuY2xvc3VyZS1saWJyYXJ5Lmdvb2dsZWNvZGUuY29tL2dpdC9jbG9zdXJlX2dvb2dfZGF0ZV9kYXRlLmpzLnNvdXJjZS5odG1sXHJcbiAgICAgICAgLy8gc29tZXdoYXQgbW9yZSBpbiBsaW5lIHdpdGggNC40LjMuMiAyMDA0IHNwZWMsIGJ1dCBhbGxvd3MgZGVjaW1hbCBhbnl3aGVyZVxyXG4gICAgICAgIGlzb0R1cmF0aW9uUmVnZXggPSAvXigtKT9QKD86KD86KFswLTksLl0qKVkpPyg/OihbMC05LC5dKilNKT8oPzooWzAtOSwuXSopRCk/KD86VCg/OihbMC05LC5dKilIKT8oPzooWzAtOSwuXSopTSk/KD86KFswLTksLl0qKVMpPyk/fChbMC05LC5dKilXKSQvLFxyXG5cclxuICAgICAgICAvLyBmb3JtYXQgdG9rZW5zXHJcbiAgICAgICAgZm9ybWF0dGluZ1Rva2VucyA9IC8oXFxbW15cXFtdKlxcXSl8KFxcXFwpPyhNb3xNTT9NP00/fERvfERERG98REQ/RD9EP3xkZGQ/ZD98ZG8/fHdbb3x3XT98V1tvfFddP3xZWVlZWVl8WVlZWVl8WVlZWXxZWXxnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xtbT98c3M/fFN7MSw0fXxYfHp6P3xaWj98LikvZyxcclxuICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMgPSAvKFxcW1teXFxbXSpcXF0pfChcXFxcKT8oTFR8TEw/TD9MP3xsezEsNH0pL2csXHJcblxyXG4gICAgICAgIC8vIHBhcnNpbmcgdG9rZW4gcmVnZXhlc1xyXG4gICAgICAgIHBhcnNlVG9rZW5PbmVPclR3b0RpZ2l0cyA9IC9cXGRcXGQ/LywgLy8gMCAtIDk5XHJcbiAgICAgICAgcGFyc2VUb2tlbk9uZVRvVGhyZWVEaWdpdHMgPSAvXFxkezEsM30vLCAvLyAwIC0gOTk5XHJcbiAgICAgICAgcGFyc2VUb2tlbk9uZVRvRm91ckRpZ2l0cyA9IC9cXGR7MSw0fS8sIC8vIDAgLSA5OTk5XHJcbiAgICAgICAgcGFyc2VUb2tlbk9uZVRvU2l4RGlnaXRzID0gL1srXFwtXT9cXGR7MSw2fS8sIC8vIC05OTksOTk5IC0gOTk5LDk5OVxyXG4gICAgICAgIHBhcnNlVG9rZW5EaWdpdHMgPSAvXFxkKy8sIC8vIG5vbnplcm8gbnVtYmVyIG9mIGRpZ2l0c1xyXG4gICAgICAgIHBhcnNlVG9rZW5Xb3JkID0gL1swLTldKlsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSt8W1xcdTA2MDAtXFx1MDZGRlxcL10rKFxccyo/W1xcdTA2MDAtXFx1MDZGRl0rKXsxLDJ9L2ksIC8vIGFueSB3b3JkIChvciB0d28pIGNoYXJhY3RlcnMgb3IgbnVtYmVycyBpbmNsdWRpbmcgdHdvL3RocmVlIHdvcmQgbW9udGggaW4gYXJhYmljLlxyXG4gICAgICAgIHBhcnNlVG9rZW5UaW1lem9uZSA9IC9afFtcXCtcXC1dXFxkXFxkOj9cXGRcXGQvZ2ksIC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxyXG4gICAgICAgIHBhcnNlVG9rZW5UID0gL1QvaSwgLy8gVCAoSVNPIHNlcGFyYXRvcilcclxuICAgICAgICBwYXJzZVRva2VuVGltZXN0YW1wTXMgPSAvW1xcK1xcLV0/XFxkKyhcXC5cXGR7MSwzfSk/LywgLy8gMTIzNDU2Nzg5IDEyMzQ1Njc4OS4xMjNcclxuICAgICAgICBwYXJzZVRva2VuT3JkaW5hbCA9IC9cXGR7MSwyfS8sXHJcblxyXG4gICAgICAgIC8vc3RyaWN0IHBhcnNpbmcgcmVnZXhlc1xyXG4gICAgICAgIHBhcnNlVG9rZW5PbmVEaWdpdCA9IC9cXGQvLCAvLyAwIC0gOVxyXG4gICAgICAgIHBhcnNlVG9rZW5Ud29EaWdpdHMgPSAvXFxkXFxkLywgLy8gMDAgLSA5OVxyXG4gICAgICAgIHBhcnNlVG9rZW5UaHJlZURpZ2l0cyA9IC9cXGR7M30vLCAvLyAwMDAgLSA5OTlcclxuICAgICAgICBwYXJzZVRva2VuRm91ckRpZ2l0cyA9IC9cXGR7NH0vLCAvLyAwMDAwIC0gOTk5OVxyXG4gICAgICAgIHBhcnNlVG9rZW5TaXhEaWdpdHMgPSAvWystXT9cXGR7Nn0vLCAvLyAtOTk5LDk5OSAtIDk5OSw5OTlcclxuICAgICAgICBwYXJzZVRva2VuU2lnbmVkTnVtYmVyID0gL1srLV0/XFxkKy8sIC8vIC1pbmYgLSBpbmZcclxuXHJcbiAgICAgICAgLy8gaXNvIDg2MDEgcmVnZXhcclxuICAgICAgICAvLyAwMDAwLTAwLTAwIDAwMDAtVzAwIG9yIDAwMDAtVzAwLTAgKyBUICsgMDAgb3IgMDA6MDAgb3IgMDA6MDA6MDAgb3IgMDA6MDA6MDAuMDAwICsgKzAwOjAwIG9yICswMDAwIG9yICswMClcclxuICAgICAgICBpc29SZWdleCA9IC9eXFxzKig/OlsrLV1cXGR7Nn18XFxkezR9KS0oPzooXFxkXFxkLVxcZFxcZCl8KFdcXGRcXGQkKXwoV1xcZFxcZC1cXGQpfChcXGRcXGRcXGQpKSgoVHwgKShcXGRcXGQoOlxcZFxcZCg6XFxkXFxkKFxcLlxcZCspPyk/KT8pPyhbXFwrXFwtXVxcZFxcZCg/Ojo/XFxkXFxkKT98XFxzKlopPyk/JC8sXHJcblxyXG4gICAgICAgIGlzb0Zvcm1hdCA9ICdZWVlZLU1NLUREVEhIOm1tOnNzWicsXHJcblxyXG4gICAgICAgIGlzb0RhdGVzID0gW1xyXG4gICAgICAgICAgICBbJ1lZWVlZWS1NTS1ERCcsIC9bKy1dXFxkezZ9LVxcZHsyfS1cXGR7Mn0vXSxcclxuICAgICAgICAgICAgWydZWVlZLU1NLUREJywgL1xcZHs0fS1cXGR7Mn0tXFxkezJ9L10sXHJcbiAgICAgICAgICAgIFsnR0dHRy1bV11XVy1FJywgL1xcZHs0fS1XXFxkezJ9LVxcZC9dLFxyXG4gICAgICAgICAgICBbJ0dHR0ctW1ddV1cnLCAvXFxkezR9LVdcXGR7Mn0vXSxcclxuICAgICAgICAgICAgWydZWVlZLURERCcsIC9cXGR7NH0tXFxkezN9L11cclxuICAgICAgICBdLFxyXG5cclxuICAgICAgICAvLyBpc28gdGltZSBmb3JtYXRzIGFuZCByZWdleGVzXHJcbiAgICAgICAgaXNvVGltZXMgPSBbXHJcbiAgICAgICAgICAgIFsnSEg6bW06c3MuU1NTUycsIC8oVHwgKVxcZFxcZDpcXGRcXGQ6XFxkXFxkXFwuXFxkezEsM30vXSxcclxuICAgICAgICAgICAgWydISDptbTpzcycsIC8oVHwgKVxcZFxcZDpcXGRcXGQ6XFxkXFxkL10sXHJcbiAgICAgICAgICAgIFsnSEg6bW0nLCAvKFR8IClcXGRcXGQ6XFxkXFxkL10sXHJcbiAgICAgICAgICAgIFsnSEgnLCAvKFR8IClcXGRcXGQvXVxyXG4gICAgICAgIF0sXHJcblxyXG4gICAgICAgIC8vIHRpbWV6b25lIGNodW5rZXIgXCIrMTA6MDBcIiA+IFtcIjEwXCIsIFwiMDBcIl0gb3IgXCItMTUzMFwiID4gW1wiLTE1XCIsIFwiMzBcIl1cclxuICAgICAgICBwYXJzZVRpbWV6b25lQ2h1bmtlciA9IC8oW1xcK1xcLV18XFxkXFxkKS9naSxcclxuXHJcbiAgICAgICAgLy8gZ2V0dGVyIGFuZCBzZXR0ZXIgbmFtZXNcclxuICAgICAgICBwcm94eUdldHRlcnNBbmRTZXR0ZXJzID0gJ0RhdGV8SG91cnN8TWludXRlc3xTZWNvbmRzfE1pbGxpc2Vjb25kcycuc3BsaXQoJ3wnKSxcclxuICAgICAgICB1bml0TWlsbGlzZWNvbmRGYWN0b3JzID0ge1xyXG4gICAgICAgICAgICAnTWlsbGlzZWNvbmRzJyA6IDEsXHJcbiAgICAgICAgICAgICdTZWNvbmRzJyA6IDFlMyxcclxuICAgICAgICAgICAgJ01pbnV0ZXMnIDogNmU0LFxyXG4gICAgICAgICAgICAnSG91cnMnIDogMzZlNSxcclxuICAgICAgICAgICAgJ0RheXMnIDogODY0ZTUsXHJcbiAgICAgICAgICAgICdNb250aHMnIDogMjU5MmU2LFxyXG4gICAgICAgICAgICAnWWVhcnMnIDogMzE1MzZlNlxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHVuaXRBbGlhc2VzID0ge1xyXG4gICAgICAgICAgICBtcyA6ICdtaWxsaXNlY29uZCcsXHJcbiAgICAgICAgICAgIHMgOiAnc2Vjb25kJyxcclxuICAgICAgICAgICAgbSA6ICdtaW51dGUnLFxyXG4gICAgICAgICAgICBoIDogJ2hvdXInLFxyXG4gICAgICAgICAgICBkIDogJ2RheScsXHJcbiAgICAgICAgICAgIEQgOiAnZGF0ZScsXHJcbiAgICAgICAgICAgIHcgOiAnd2VlaycsXHJcbiAgICAgICAgICAgIFcgOiAnaXNvV2VlaycsXHJcbiAgICAgICAgICAgIE0gOiAnbW9udGgnLFxyXG4gICAgICAgICAgICB5IDogJ3llYXInLFxyXG4gICAgICAgICAgICBEREQgOiAnZGF5T2ZZZWFyJyxcclxuICAgICAgICAgICAgZSA6ICd3ZWVrZGF5JyxcclxuICAgICAgICAgICAgRSA6ICdpc29XZWVrZGF5JyxcclxuICAgICAgICAgICAgZ2c6ICd3ZWVrWWVhcicsXHJcbiAgICAgICAgICAgIEdHOiAnaXNvV2Vla1llYXInXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgY2FtZWxGdW5jdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIGRheW9meWVhciA6ICdkYXlPZlllYXInLFxyXG4gICAgICAgICAgICBpc293ZWVrZGF5IDogJ2lzb1dlZWtkYXknLFxyXG4gICAgICAgICAgICBpc293ZWVrIDogJ2lzb1dlZWsnLFxyXG4gICAgICAgICAgICB3ZWVreWVhciA6ICd3ZWVrWWVhcicsXHJcbiAgICAgICAgICAgIGlzb3dlZWt5ZWFyIDogJ2lzb1dlZWtZZWFyJ1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIC8vIGZvcm1hdCBmdW5jdGlvbiBzdHJpbmdzXHJcbiAgICAgICAgZm9ybWF0RnVuY3Rpb25zID0ge30sXHJcblxyXG4gICAgICAgIC8vIHRva2VucyB0byBvcmRpbmFsaXplIGFuZCBwYWRcclxuICAgICAgICBvcmRpbmFsaXplVG9rZW5zID0gJ0RERCB3IFcgTSBEIGQnLnNwbGl0KCcgJyksXHJcbiAgICAgICAgcGFkZGVkVG9rZW5zID0gJ00gRCBIIGggbSBzIHcgVycuc3BsaXQoJyAnKSxcclxuXHJcbiAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIE0gICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tb250aCgpICsgMTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgTU1NICA6IGZ1bmN0aW9uIChmb3JtYXQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS5tb250aHNTaG9ydCh0aGlzLCBmb3JtYXQpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBNTU1NIDogZnVuY3Rpb24gKGZvcm1hdCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLm1vbnRocyh0aGlzLCBmb3JtYXQpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBEICAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBEREQgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5T2ZZZWFyKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGQgICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXkoKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZGQgICA6IGZ1bmN0aW9uIChmb3JtYXQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS53ZWVrZGF5c01pbih0aGlzLCBmb3JtYXQpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBkZGQgIDogZnVuY3Rpb24gKGZvcm1hdCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLndlZWtkYXlzU2hvcnQodGhpcywgZm9ybWF0KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZGRkZCA6IGZ1bmN0aW9uIChmb3JtYXQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS53ZWVrZGF5cyh0aGlzLCBmb3JtYXQpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB3ICAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2VlaygpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBXICAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNvV2VlaygpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBZWSAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLnllYXIoKSAlIDEwMCwgMik7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIFlZWVkgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMueWVhcigpLCA0KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgWVlZWVkgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMueWVhcigpLCA1KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgWVlZWVlZIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHkgPSB0aGlzLnllYXIoKSwgc2lnbiA9IHkgPj0gMCA/ICcrJyA6ICctJztcclxuICAgICAgICAgICAgICAgIHJldHVybiBzaWduICsgbGVmdFplcm9GaWxsKE1hdGguYWJzKHkpLCA2KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZ2cgICA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0WmVyb0ZpbGwodGhpcy53ZWVrWWVhcigpICUgMTAwLCAyKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZ2dnZyA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0WmVyb0ZpbGwodGhpcy53ZWVrWWVhcigpLCA0KTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZ2dnZ2cgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMud2Vla1llYXIoKSwgNSk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIEdHICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMuaXNvV2Vla1llYXIoKSAlIDEwMCwgMik7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIEdHR0cgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMuaXNvV2Vla1llYXIoKSwgNCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIEdHR0dHIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLmlzb1dlZWtZZWFyKCksIDUpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2Vla2RheSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBFIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNvV2Vla2RheSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBhICAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLm1lcmlkaWVtKHRoaXMuaG91cnMoKSwgdGhpcy5taW51dGVzKCksIHRydWUpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBBICAgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLm1lcmlkaWVtKHRoaXMuaG91cnMoKSwgdGhpcy5taW51dGVzKCksIGZhbHNlKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgSCAgICA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmhvdXJzKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGggICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5ob3VycygpICUgMTIgfHwgMTI7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG0gICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5taW51dGVzKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHMgICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZWNvbmRzKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIFMgICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9JbnQodGhpcy5taWxsaXNlY29uZHMoKSAvIDEwMCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIFNTICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRvSW50KHRoaXMubWlsbGlzZWNvbmRzKCkgLyAxMCksIDIpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBTU1MgIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLm1pbGxpc2Vjb25kcygpLCAzKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgU1NTUyA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0WmVyb0ZpbGwodGhpcy5taWxsaXNlY29uZHMoKSwgMyk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIFogICAgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgYSA9IC10aGlzLnpvbmUoKSxcclxuICAgICAgICAgICAgICAgICAgICBiID0gXCIrXCI7XHJcbiAgICAgICAgICAgICAgICBpZiAoYSA8IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBhID0gLWE7XHJcbiAgICAgICAgICAgICAgICAgICAgYiA9IFwiLVwiO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGIgKyBsZWZ0WmVyb0ZpbGwodG9JbnQoYSAvIDYwKSwgMikgKyBcIjpcIiArIGxlZnRaZXJvRmlsbCh0b0ludChhKSAlIDYwLCAyKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgWlogICA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBhID0gLXRoaXMuem9uZSgpLFxyXG4gICAgICAgICAgICAgICAgICAgIGIgPSBcIitcIjtcclxuICAgICAgICAgICAgICAgIGlmIChhIDwgMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGEgPSAtYTtcclxuICAgICAgICAgICAgICAgICAgICBiID0gXCItXCI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gYiArIGxlZnRaZXJvRmlsbCh0b0ludChhIC8gNjApLCAyKSArIGxlZnRaZXJvRmlsbCh0b0ludChhKSAlIDYwLCAyKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgeiA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnpvbmVBYmJyKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHp6IDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuem9uZU5hbWUoKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgWCAgICA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnVuaXgoKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgUSA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnF1YXJ0ZXIoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGxpc3RzID0gWydtb250aHMnLCAnbW9udGhzU2hvcnQnLCAnd2Vla2RheXMnLCAnd2Vla2RheXNTaG9ydCcsICd3ZWVrZGF5c01pbiddO1xyXG5cclxuICAgIGZ1bmN0aW9uIGRlZmF1bHRQYXJzaW5nRmxhZ3MoKSB7XHJcbiAgICAgICAgLy8gV2UgbmVlZCB0byBkZWVwIGNsb25lIHRoaXMgb2JqZWN0LCBhbmQgZXM1IHN0YW5kYXJkIGlzIG5vdCB2ZXJ5XHJcbiAgICAgICAgLy8gaGVscGZ1bC5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBlbXB0eSA6IGZhbHNlLFxyXG4gICAgICAgICAgICB1bnVzZWRUb2tlbnMgOiBbXSxcclxuICAgICAgICAgICAgdW51c2VkSW5wdXQgOiBbXSxcclxuICAgICAgICAgICAgb3ZlcmZsb3cgOiAtMixcclxuICAgICAgICAgICAgY2hhcnNMZWZ0T3ZlciA6IDAsXHJcbiAgICAgICAgICAgIG51bGxJbnB1dCA6IGZhbHNlLFxyXG4gICAgICAgICAgICBpbnZhbGlkTW9udGggOiBudWxsLFxyXG4gICAgICAgICAgICBpbnZhbGlkRm9ybWF0IDogZmFsc2UsXHJcbiAgICAgICAgICAgIHVzZXJJbnZhbGlkYXRlZCA6IGZhbHNlLFxyXG4gICAgICAgICAgICBpc286IGZhbHNlXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBwYWRUb2tlbihmdW5jLCBjb3VudCkge1xyXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoYSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKGZ1bmMuY2FsbCh0aGlzLCBhKSwgY291bnQpO1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBvcmRpbmFsaXplVG9rZW4oZnVuYywgcGVyaW9kKSB7XHJcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS5vcmRpbmFsKGZ1bmMuY2FsbCh0aGlzLCBhKSwgcGVyaW9kKTtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIHdoaWxlIChvcmRpbmFsaXplVG9rZW5zLmxlbmd0aCkge1xyXG4gICAgICAgIGkgPSBvcmRpbmFsaXplVG9rZW5zLnBvcCgpO1xyXG4gICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zW2kgKyAnbyddID0gb3JkaW5hbGl6ZVRva2VuKGZvcm1hdFRva2VuRnVuY3Rpb25zW2ldLCBpKTtcclxuICAgIH1cclxuICAgIHdoaWxlIChwYWRkZWRUb2tlbnMubGVuZ3RoKSB7XHJcbiAgICAgICAgaSA9IHBhZGRlZFRva2Vucy5wb3AoKTtcclxuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1tpICsgaV0gPSBwYWRUb2tlbihmb3JtYXRUb2tlbkZ1bmN0aW9uc1tpXSwgMik7XHJcbiAgICB9XHJcbiAgICBmb3JtYXRUb2tlbkZ1bmN0aW9ucy5EREREID0gcGFkVG9rZW4oZm9ybWF0VG9rZW5GdW5jdGlvbnMuRERELCAzKTtcclxuXHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIENvbnN0cnVjdG9yc1xyXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xyXG5cclxuICAgIGZ1bmN0aW9uIExhbmd1YWdlKCkge1xyXG5cclxuICAgIH1cclxuXHJcbiAgICAvLyBNb21lbnQgcHJvdG90eXBlIG9iamVjdFxyXG4gICAgZnVuY3Rpb24gTW9tZW50KGNvbmZpZykge1xyXG4gICAgICAgIGNoZWNrT3ZlcmZsb3coY29uZmlnKTtcclxuICAgICAgICBleHRlbmQodGhpcywgY29uZmlnKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBEdXJhdGlvbiBDb25zdHJ1Y3RvclxyXG4gICAgZnVuY3Rpb24gRHVyYXRpb24oZHVyYXRpb24pIHtcclxuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0gbm9ybWFsaXplT2JqZWN0VW5pdHMoZHVyYXRpb24pLFxyXG4gICAgICAgICAgICB5ZWFycyA9IG5vcm1hbGl6ZWRJbnB1dC55ZWFyIHx8IDAsXHJcbiAgICAgICAgICAgIG1vbnRocyA9IG5vcm1hbGl6ZWRJbnB1dC5tb250aCB8fCAwLFxyXG4gICAgICAgICAgICB3ZWVrcyA9IG5vcm1hbGl6ZWRJbnB1dC53ZWVrIHx8IDAsXHJcbiAgICAgICAgICAgIGRheXMgPSBub3JtYWxpemVkSW5wdXQuZGF5IHx8IDAsXHJcbiAgICAgICAgICAgIGhvdXJzID0gbm9ybWFsaXplZElucHV0LmhvdXIgfHwgMCxcclxuICAgICAgICAgICAgbWludXRlcyA9IG5vcm1hbGl6ZWRJbnB1dC5taW51dGUgfHwgMCxcclxuICAgICAgICAgICAgc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5zZWNvbmQgfHwgMCxcclxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzID0gbm9ybWFsaXplZElucHV0Lm1pbGxpc2Vjb25kIHx8IDA7XHJcblxyXG4gICAgICAgIC8vIHJlcHJlc2VudGF0aW9uIGZvciBkYXRlQWRkUmVtb3ZlXHJcbiAgICAgICAgdGhpcy5fbWlsbGlzZWNvbmRzID0gK21pbGxpc2Vjb25kcyArXHJcbiAgICAgICAgICAgIHNlY29uZHMgKiAxZTMgKyAvLyAxMDAwXHJcbiAgICAgICAgICAgIG1pbnV0ZXMgKiA2ZTQgKyAvLyAxMDAwICogNjBcclxuICAgICAgICAgICAgaG91cnMgKiAzNmU1OyAvLyAxMDAwICogNjAgKiA2MFxyXG4gICAgICAgIC8vIEJlY2F1c2Ugb2YgZGF0ZUFkZFJlbW92ZSB0cmVhdHMgMjQgaG91cnMgYXMgZGlmZmVyZW50IGZyb20gYVxyXG4gICAgICAgIC8vIGRheSB3aGVuIHdvcmtpbmcgYXJvdW5kIERTVCwgd2UgbmVlZCB0byBzdG9yZSB0aGVtIHNlcGFyYXRlbHlcclxuICAgICAgICB0aGlzLl9kYXlzID0gK2RheXMgK1xyXG4gICAgICAgICAgICB3ZWVrcyAqIDc7XHJcbiAgICAgICAgLy8gSXQgaXMgaW1wb3NzaWJsZSB0cmFuc2xhdGUgbW9udGhzIGludG8gZGF5cyB3aXRob3V0IGtub3dpbmdcclxuICAgICAgICAvLyB3aGljaCBtb250aHMgeW91IGFyZSBhcmUgdGFsa2luZyBhYm91dCwgc28gd2UgaGF2ZSB0byBzdG9yZVxyXG4gICAgICAgIC8vIGl0IHNlcGFyYXRlbHkuXHJcbiAgICAgICAgdGhpcy5fbW9udGhzID0gK21vbnRocyArXHJcbiAgICAgICAgICAgIHllYXJzICogMTI7XHJcblxyXG4gICAgICAgIHRoaXMuX2RhdGEgPSB7fTtcclxuXHJcbiAgICAgICAgdGhpcy5fYnViYmxlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIEhlbHBlcnNcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgZnVuY3Rpb24gZXh0ZW5kKGEsIGIpIHtcclxuICAgICAgICBmb3IgKHZhciBpIGluIGIpIHtcclxuICAgICAgICAgICAgaWYgKGIuaGFzT3duUHJvcGVydHkoaSkpIHtcclxuICAgICAgICAgICAgICAgIGFbaV0gPSBiW2ldO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYi5oYXNPd25Qcm9wZXJ0eShcInRvU3RyaW5nXCIpKSB7XHJcbiAgICAgICAgICAgIGEudG9TdHJpbmcgPSBiLnRvU3RyaW5nO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGIuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZU9mXCIpKSB7XHJcbiAgICAgICAgICAgIGEudmFsdWVPZiA9IGIudmFsdWVPZjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGNsb25lTW9tZW50KG0pIHtcclxuICAgICAgICB2YXIgcmVzdWx0ID0ge30sIGk7XHJcbiAgICAgICAgZm9yIChpIGluIG0pIHtcclxuICAgICAgICAgICAgaWYgKG0uaGFzT3duUHJvcGVydHkoaSkgJiYgbW9tZW50UHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShpKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0W2ldID0gbVtpXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBhYnNSb3VuZChudW1iZXIpIHtcclxuICAgICAgICBpZiAobnVtYmVyIDwgMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKG51bWJlcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtYmVyKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gbGVmdCB6ZXJvIGZpbGwgYSBudW1iZXJcclxuICAgIC8vIHNlZSBodHRwOi8vanNwZXJmLmNvbS9sZWZ0LXplcm8tZmlsbGluZyBmb3IgcGVyZm9ybWFuY2UgY29tcGFyaXNvblxyXG4gICAgZnVuY3Rpb24gbGVmdFplcm9GaWxsKG51bWJlciwgdGFyZ2V0TGVuZ3RoLCBmb3JjZVNpZ24pIHtcclxuICAgICAgICB2YXIgb3V0cHV0ID0gJycgKyBNYXRoLmFicyhudW1iZXIpLFxyXG4gICAgICAgICAgICBzaWduID0gbnVtYmVyID49IDA7XHJcblxyXG4gICAgICAgIHdoaWxlIChvdXRwdXQubGVuZ3RoIDwgdGFyZ2V0TGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIG91dHB1dCA9ICcwJyArIG91dHB1dDtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIChzaWduID8gKGZvcmNlU2lnbiA/ICcrJyA6ICcnKSA6ICctJykgKyBvdXRwdXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gaGVscGVyIGZ1bmN0aW9uIGZvciBfLmFkZFRpbWUgYW5kIF8uc3VidHJhY3RUaW1lXHJcbiAgICBmdW5jdGlvbiBhZGRPclN1YnRyYWN0RHVyYXRpb25Gcm9tTW9tZW50KG1vbSwgZHVyYXRpb24sIGlzQWRkaW5nLCBpZ25vcmVVcGRhdGVPZmZzZXQpIHtcclxuICAgICAgICB2YXIgbWlsbGlzZWNvbmRzID0gZHVyYXRpb24uX21pbGxpc2Vjb25kcyxcclxuICAgICAgICAgICAgZGF5cyA9IGR1cmF0aW9uLl9kYXlzLFxyXG4gICAgICAgICAgICBtb250aHMgPSBkdXJhdGlvbi5fbW9udGhzLFxyXG4gICAgICAgICAgICBtaW51dGVzLFxyXG4gICAgICAgICAgICBob3VycztcclxuXHJcbiAgICAgICAgaWYgKG1pbGxpc2Vjb25kcykge1xyXG4gICAgICAgICAgICBtb20uX2Quc2V0VGltZSgrbW9tLl9kICsgbWlsbGlzZWNvbmRzICogaXNBZGRpbmcpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBzdG9yZSB0aGUgbWludXRlcyBhbmQgaG91cnMgc28gd2UgY2FuIHJlc3RvcmUgdGhlbVxyXG4gICAgICAgIGlmIChkYXlzIHx8IG1vbnRocykge1xyXG4gICAgICAgICAgICBtaW51dGVzID0gbW9tLm1pbnV0ZSgpO1xyXG4gICAgICAgICAgICBob3VycyA9IG1vbS5ob3VyKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChkYXlzKSB7XHJcbiAgICAgICAgICAgIG1vbS5kYXRlKG1vbS5kYXRlKCkgKyBkYXlzICogaXNBZGRpbmcpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAobW9udGhzKSB7XHJcbiAgICAgICAgICAgIG1vbS5tb250aChtb20ubW9udGgoKSArIG1vbnRocyAqIGlzQWRkaW5nKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKG1pbGxpc2Vjb25kcyAmJiAhaWdub3JlVXBkYXRlT2Zmc2V0KSB7XHJcbiAgICAgICAgICAgIG1vbWVudC51cGRhdGVPZmZzZXQobW9tLCBkYXlzIHx8IG1vbnRocyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIHJlc3RvcmUgdGhlIG1pbnV0ZXMgYW5kIGhvdXJzIGFmdGVyIHBvc3NpYmx5IGNoYW5naW5nIGRzdFxyXG4gICAgICAgIGlmIChkYXlzIHx8IG1vbnRocykge1xyXG4gICAgICAgICAgICBtb20ubWludXRlKG1pbnV0ZXMpO1xyXG4gICAgICAgICAgICBtb20uaG91cihob3Vycyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIGNoZWNrIGlmIGlzIGFuIGFycmF5XHJcbiAgICBmdW5jdGlvbiBpc0FycmF5KGlucHV0KSB7XHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IEFycmF5XSc7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gaXNEYXRlKGlucHV0KSB7XHJcbiAgICAgICAgcmV0dXJuICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBEYXRlXScgfHxcclxuICAgICAgICAgICAgICAgIGlucHV0IGluc3RhbmNlb2YgRGF0ZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBjb21wYXJlIHR3byBhcnJheXMsIHJldHVybiB0aGUgbnVtYmVyIG9mIGRpZmZlcmVuY2VzXHJcbiAgICBmdW5jdGlvbiBjb21wYXJlQXJyYXlzKGFycmF5MSwgYXJyYXkyLCBkb250Q29udmVydCkge1xyXG4gICAgICAgIHZhciBsZW4gPSBNYXRoLm1pbihhcnJheTEubGVuZ3RoLCBhcnJheTIubGVuZ3RoKSxcclxuICAgICAgICAgICAgbGVuZ3RoRGlmZiA9IE1hdGguYWJzKGFycmF5MS5sZW5ndGggLSBhcnJheTIubGVuZ3RoKSxcclxuICAgICAgICAgICAgZGlmZnMgPSAwLFxyXG4gICAgICAgICAgICBpO1xyXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoKGRvbnRDb252ZXJ0ICYmIGFycmF5MVtpXSAhPT0gYXJyYXkyW2ldKSB8fFxyXG4gICAgICAgICAgICAgICAgKCFkb250Q29udmVydCAmJiB0b0ludChhcnJheTFbaV0pICE9PSB0b0ludChhcnJheTJbaV0pKSkge1xyXG4gICAgICAgICAgICAgICAgZGlmZnMrKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZGlmZnMgKyBsZW5ndGhEaWZmO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB7XHJcbiAgICAgICAgaWYgKHVuaXRzKSB7XHJcbiAgICAgICAgICAgIHZhciBsb3dlcmVkID0gdW5pdHMudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8oLilzJC8sICckMScpO1xyXG4gICAgICAgICAgICB1bml0cyA9IHVuaXRBbGlhc2VzW3VuaXRzXSB8fCBjYW1lbEZ1bmN0aW9uc1tsb3dlcmVkXSB8fCBsb3dlcmVkO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdW5pdHM7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gbm9ybWFsaXplT2JqZWN0VW5pdHMoaW5wdXRPYmplY3QpIHtcclxuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0ge30sXHJcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRQcm9wLFxyXG4gICAgICAgICAgICBwcm9wO1xyXG5cclxuICAgICAgICBmb3IgKHByb3AgaW4gaW5wdXRPYmplY3QpIHtcclxuICAgICAgICAgICAgaWYgKGlucHV0T2JqZWN0Lmhhc093blByb3BlcnR5KHByb3ApKSB7XHJcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkUHJvcCA9IG5vcm1hbGl6ZVVuaXRzKHByb3ApO1xyXG4gICAgICAgICAgICAgICAgaWYgKG5vcm1hbGl6ZWRQcm9wKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZElucHV0W25vcm1hbGl6ZWRQcm9wXSA9IGlucHV0T2JqZWN0W3Byb3BdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbm9ybWFsaXplZElucHV0O1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIG1ha2VMaXN0KGZpZWxkKSB7XHJcbiAgICAgICAgdmFyIGNvdW50LCBzZXR0ZXI7XHJcblxyXG4gICAgICAgIGlmIChmaWVsZC5pbmRleE9mKCd3ZWVrJykgPT09IDApIHtcclxuICAgICAgICAgICAgY291bnQgPSA3O1xyXG4gICAgICAgICAgICBzZXR0ZXIgPSAnZGF5JztcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoZmllbGQuaW5kZXhPZignbW9udGgnKSA9PT0gMCkge1xyXG4gICAgICAgICAgICBjb3VudCA9IDEyO1xyXG4gICAgICAgICAgICBzZXR0ZXIgPSAnbW9udGgnO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbW9tZW50W2ZpZWxkXSA9IGZ1bmN0aW9uIChmb3JtYXQsIGluZGV4KSB7XHJcbiAgICAgICAgICAgIHZhciBpLCBnZXR0ZXIsXHJcbiAgICAgICAgICAgICAgICBtZXRob2QgPSBtb21lbnQuZm4uX2xhbmdbZmllbGRdLFxyXG4gICAgICAgICAgICAgICAgcmVzdWx0cyA9IFtdO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXQgPT09ICdudW1iZXInKSB7XHJcbiAgICAgICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcclxuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgZ2V0dGVyID0gZnVuY3Rpb24gKGkpIHtcclxuICAgICAgICAgICAgICAgIHZhciBtID0gbW9tZW50KCkudXRjKCkuc2V0KHNldHRlciwgaSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0aG9kLmNhbGwobW9tZW50LmZuLl9sYW5nLCBtLCBmb3JtYXQgfHwgJycpO1xyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgaWYgKGluZGV4ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBnZXR0ZXIoaW5kZXgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goZ2V0dGVyKGkpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHRzO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiB0b0ludChhcmd1bWVudEZvckNvZXJjaW9uKSB7XHJcbiAgICAgICAgdmFyIGNvZXJjZWROdW1iZXIgPSArYXJndW1lbnRGb3JDb2VyY2lvbixcclxuICAgICAgICAgICAgdmFsdWUgPSAwO1xyXG5cclxuICAgICAgICBpZiAoY29lcmNlZE51bWJlciAhPT0gMCAmJiBpc0Zpbml0ZShjb2VyY2VkTnVtYmVyKSkge1xyXG4gICAgICAgICAgICBpZiAoY29lcmNlZE51bWJlciA+PSAwKSB7XHJcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IE1hdGguZmxvb3IoY29lcmNlZE51bWJlcik7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IE1hdGguY2VpbChjb2VyY2VkTnVtYmVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGRheXNJbk1vbnRoKHllYXIsIG1vbnRoKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIG1vbnRoICsgMSwgMCkpLmdldFVUQ0RhdGUoKTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiB3ZWVrc0luWWVhcih5ZWFyLCBkb3csIGRveSkge1xyXG4gICAgICAgIHJldHVybiB3ZWVrT2ZZZWFyKG1vbWVudChbeWVhciwgMTEsIDMxICsgZG93IC0gZG95XSksIGRvdywgZG95KS53ZWVrO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGRheXNJblllYXIoeWVhcikge1xyXG4gICAgICAgIHJldHVybiBpc0xlYXBZZWFyKHllYXIpID8gMzY2IDogMzY1O1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGlzTGVhcFllYXIoeWVhcikge1xyXG4gICAgICAgIHJldHVybiAoeWVhciAlIDQgPT09IDAgJiYgeWVhciAlIDEwMCAhPT0gMCkgfHwgeWVhciAlIDQwMCA9PT0gMDtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBjaGVja092ZXJmbG93KG0pIHtcclxuICAgICAgICB2YXIgb3ZlcmZsb3c7XHJcbiAgICAgICAgaWYgKG0uX2EgJiYgbS5fcGYub3ZlcmZsb3cgPT09IC0yKSB7XHJcbiAgICAgICAgICAgIG92ZXJmbG93ID1cclxuICAgICAgICAgICAgICAgIG0uX2FbTU9OVEhdIDwgMCB8fCBtLl9hW01PTlRIXSA+IDExID8gTU9OVEggOlxyXG4gICAgICAgICAgICAgICAgbS5fYVtEQVRFXSA8IDEgfHwgbS5fYVtEQVRFXSA+IGRheXNJbk1vbnRoKG0uX2FbWUVBUl0sIG0uX2FbTU9OVEhdKSA/IERBVEUgOlxyXG4gICAgICAgICAgICAgICAgbS5fYVtIT1VSXSA8IDAgfHwgbS5fYVtIT1VSXSA+IDIzID8gSE9VUiA6XHJcbiAgICAgICAgICAgICAgICBtLl9hW01JTlVURV0gPCAwIHx8IG0uX2FbTUlOVVRFXSA+IDU5ID8gTUlOVVRFIDpcclxuICAgICAgICAgICAgICAgIG0uX2FbU0VDT05EXSA8IDAgfHwgbS5fYVtTRUNPTkRdID4gNTkgPyBTRUNPTkQgOlxyXG4gICAgICAgICAgICAgICAgbS5fYVtNSUxMSVNFQ09ORF0gPCAwIHx8IG0uX2FbTUlMTElTRUNPTkRdID4gOTk5ID8gTUlMTElTRUNPTkQgOlxyXG4gICAgICAgICAgICAgICAgLTE7XHJcblxyXG4gICAgICAgICAgICBpZiAobS5fcGYuX292ZXJmbG93RGF5T2ZZZWFyICYmIChvdmVyZmxvdyA8IFlFQVIgfHwgb3ZlcmZsb3cgPiBEQVRFKSkge1xyXG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBEQVRFO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBtLl9wZi5vdmVyZmxvdyA9IG92ZXJmbG93O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBpc1ZhbGlkKG0pIHtcclxuICAgICAgICBpZiAobS5faXNWYWxpZCA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIG0uX2lzVmFsaWQgPSAhaXNOYU4obS5fZC5nZXRUaW1lKCkpICYmXHJcbiAgICAgICAgICAgICAgICBtLl9wZi5vdmVyZmxvdyA8IDAgJiZcclxuICAgICAgICAgICAgICAgICFtLl9wZi5lbXB0eSAmJlxyXG4gICAgICAgICAgICAgICAgIW0uX3BmLmludmFsaWRNb250aCAmJlxyXG4gICAgICAgICAgICAgICAgIW0uX3BmLm51bGxJbnB1dCAmJlxyXG4gICAgICAgICAgICAgICAgIW0uX3BmLmludmFsaWRGb3JtYXQgJiZcclxuICAgICAgICAgICAgICAgICFtLl9wZi51c2VySW52YWxpZGF0ZWQ7XHJcblxyXG4gICAgICAgICAgICBpZiAobS5fc3RyaWN0KSB7XHJcbiAgICAgICAgICAgICAgICBtLl9pc1ZhbGlkID0gbS5faXNWYWxpZCAmJlxyXG4gICAgICAgICAgICAgICAgICAgIG0uX3BmLmNoYXJzTGVmdE92ZXIgPT09IDAgJiZcclxuICAgICAgICAgICAgICAgICAgICBtLl9wZi51bnVzZWRUb2tlbnMubGVuZ3RoID09PSAwO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBtLl9pc1ZhbGlkO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUxhbmd1YWdlKGtleSkge1xyXG4gICAgICAgIHJldHVybiBrZXkgPyBrZXkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKCdfJywgJy0nKSA6IGtleTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm4gYSBtb21lbnQgZnJvbSBpbnB1dCwgdGhhdCBpcyBsb2NhbC91dGMvem9uZSBlcXVpdmFsZW50IHRvIG1vZGVsLlxyXG4gICAgZnVuY3Rpb24gbWFrZUFzKGlucHV0LCBtb2RlbCkge1xyXG4gICAgICAgIHJldHVybiBtb2RlbC5faXNVVEMgPyBtb21lbnQoaW5wdXQpLnpvbmUobW9kZWwuX29mZnNldCB8fCAwKSA6XHJcbiAgICAgICAgICAgIG1vbWVudChpbnB1dCkubG9jYWwoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAgICAgICAgTGFuZ3VhZ2VzXHJcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG5cclxuICAgIGV4dGVuZChMYW5ndWFnZS5wcm90b3R5cGUsIHtcclxuXHJcbiAgICAgICAgc2V0IDogZnVuY3Rpb24gKGNvbmZpZykge1xyXG4gICAgICAgICAgICB2YXIgcHJvcCwgaTtcclxuICAgICAgICAgICAgZm9yIChpIGluIGNvbmZpZykge1xyXG4gICAgICAgICAgICAgICAgcHJvcCA9IGNvbmZpZ1tpXTtcclxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXNbaV0gPSBwcm9wO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzWydfJyArIGldID0gcHJvcDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9tb250aHMgOiBcIkphbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXJcIi5zcGxpdChcIl9cIiksXHJcbiAgICAgICAgbW9udGhzIDogZnVuY3Rpb24gKG0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc1ttLm1vbnRoKCldO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9tb250aHNTaG9ydCA6IFwiSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWNcIi5zcGxpdChcIl9cIiksXHJcbiAgICAgICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRbbS5tb250aCgpXTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBtb250aHNQYXJzZSA6IGZ1bmN0aW9uIChtb250aE5hbWUpIHtcclxuICAgICAgICAgICAgdmFyIGksIG1vbSwgcmVnZXg7XHJcblxyXG4gICAgICAgICAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNQYXJzZSA9IFtdO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgLy8gbWFrZSB0aGUgcmVnZXggaWYgd2UgZG9uJ3QgaGF2ZSBpdCBhbHJlYWR5XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlW2ldKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbW9tID0gbW9tZW50LnV0YyhbMjAwMCwgaV0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlZ2V4ID0gJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykgKyAnfF4nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIHRlc3QgdGhlIHJlZ2V4XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fbW9udGhzUGFyc2VbaV0udGVzdChtb250aE5hbWUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfd2Vla2RheXMgOiBcIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5XCIuc3BsaXQoXCJfXCIpLFxyXG4gICAgICAgIHdlZWtkYXlzIDogZnVuY3Rpb24gKG0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzW20uZGF5KCldO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF93ZWVrZGF5c1Nob3J0IDogXCJTdW5fTW9uX1R1ZV9XZWRfVGh1X0ZyaV9TYXRcIi5zcGxpdChcIl9cIiksXHJcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6IGZ1bmN0aW9uIChtKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0W20uZGF5KCldO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF93ZWVrZGF5c01pbiA6IFwiU3VfTW9fVHVfV2VfVGhfRnJfU2FcIi5zcGxpdChcIl9cIiksXHJcbiAgICAgICAgd2Vla2RheXNNaW4gOiBmdW5jdGlvbiAobSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNNaW5bbS5kYXkoKV07XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgd2Vla2RheXNQYXJzZSA6IGZ1bmN0aW9uICh3ZWVrZGF5TmFtZSkge1xyXG4gICAgICAgICAgICB2YXIgaSwgbW9tLCByZWdleDtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZSA9IFtdO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZVtpXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudChbMjAwMCwgMV0pLmRheShpKTtcclxuICAgICAgICAgICAgICAgICAgICByZWdleCA9ICdeJyArIHRoaXMud2Vla2RheXMobW9tLCAnJykgKyAnfF4nICsgdGhpcy53ZWVrZGF5c1Nob3J0KG1vbSwgJycpICsgJ3xeJyArIHRoaXMud2Vla2RheXNNaW4obW9tLCAnJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vIHRlc3QgdGhlIHJlZ2V4XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2xvbmdEYXRlRm9ybWF0IDoge1xyXG4gICAgICAgICAgICBMVCA6IFwiaDptbSBBXCIsXHJcbiAgICAgICAgICAgIEwgOiBcIk1NL0REL1lZWVlcIixcclxuICAgICAgICAgICAgTEwgOiBcIk1NTU0gRCBZWVlZXCIsXHJcbiAgICAgICAgICAgIExMTCA6IFwiTU1NTSBEIFlZWVkgTFRcIixcclxuICAgICAgICAgICAgTExMTCA6IFwiZGRkZCwgTU1NTSBEIFlZWVkgTFRcIlxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgbG9uZ0RhdGVGb3JtYXQgOiBmdW5jdGlvbiAoa2V5KSB7XHJcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldO1xyXG4gICAgICAgICAgICBpZiAoIW91dHB1dCAmJiB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV0pIHtcclxuICAgICAgICAgICAgICAgIG91dHB1dCA9IHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleS50b1VwcGVyQ2FzZSgpXS5yZXBsYWNlKC9NTU1NfE1NfEREfGRkZGQvZywgZnVuY3Rpb24gKHZhbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWwuc2xpY2UoMSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV0gPSBvdXRwdXQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XHJcbiAgICAgICAgICAgIC8vIElFOCBRdWlya3MgTW9kZSAmIElFNyBTdGFuZGFyZHMgTW9kZSBkbyBub3QgYWxsb3cgYWNjZXNzaW5nIHN0cmluZ3MgbGlrZSBhcnJheXNcclxuICAgICAgICAgICAgLy8gVXNpbmcgY2hhckF0IHNob3VsZCBiZSBtb3JlIGNvbXBhdGlibGUuXHJcbiAgICAgICAgICAgIHJldHVybiAoKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKCkuY2hhckF0KDApID09PSAncCcpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9tZXJpZGllbVBhcnNlIDogL1thcF1cXC4/bT9cXC4/L2ksXHJcbiAgICAgICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcclxuICAgICAgICAgICAgaWYgKGhvdXJzID4gMTEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3BtJyA6ICdQTSc7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdhbScgOiAnQU0nO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2NhbGVuZGFyIDoge1xyXG4gICAgICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxyXG4gICAgICAgICAgICBuZXh0RGF5IDogJ1tUb21vcnJvdyBhdF0gTFQnLFxyXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxyXG4gICAgICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcclxuICAgICAgICAgICAgbGFzdFdlZWsgOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXHJcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXHJcbiAgICAgICAgfSxcclxuICAgICAgICBjYWxlbmRhciA6IGZ1bmN0aW9uIChrZXksIG1vbSkge1xyXG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fY2FsZW5kYXJba2V5XTtcclxuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBvdXRwdXQgPT09ICdmdW5jdGlvbicgPyBvdXRwdXQuYXBwbHkobW9tKSA6IG91dHB1dDtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBfcmVsYXRpdmVUaW1lIDoge1xyXG4gICAgICAgICAgICBmdXR1cmUgOiBcImluICVzXCIsXHJcbiAgICAgICAgICAgIHBhc3QgOiBcIiVzIGFnb1wiLFxyXG4gICAgICAgICAgICBzIDogXCJhIGZldyBzZWNvbmRzXCIsXHJcbiAgICAgICAgICAgIG0gOiBcImEgbWludXRlXCIsXHJcbiAgICAgICAgICAgIG1tIDogXCIlZCBtaW51dGVzXCIsXHJcbiAgICAgICAgICAgIGggOiBcImFuIGhvdXJcIixcclxuICAgICAgICAgICAgaGggOiBcIiVkIGhvdXJzXCIsXHJcbiAgICAgICAgICAgIGQgOiBcImEgZGF5XCIsXHJcbiAgICAgICAgICAgIGRkIDogXCIlZCBkYXlzXCIsXHJcbiAgICAgICAgICAgIE0gOiBcImEgbW9udGhcIixcclxuICAgICAgICAgICAgTU0gOiBcIiVkIG1vbnRoc1wiLFxyXG4gICAgICAgICAgICB5IDogXCJhIHllYXJcIixcclxuICAgICAgICAgICAgeXkgOiBcIiVkIHllYXJzXCJcclxuICAgICAgICB9LFxyXG4gICAgICAgIHJlbGF0aXZlVGltZSA6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcclxuICAgICAgICAgICAgdmFyIG91dHB1dCA9IHRoaXMuX3JlbGF0aXZlVGltZVtzdHJpbmddO1xyXG4gICAgICAgICAgICByZXR1cm4gKHR5cGVvZiBvdXRwdXQgPT09ICdmdW5jdGlvbicpID9cclxuICAgICAgICAgICAgICAgIG91dHB1dChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIDpcclxuICAgICAgICAgICAgICAgIG91dHB1dC5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgcGFzdEZ1dHVyZSA6IGZ1bmN0aW9uIChkaWZmLCBvdXRwdXQpIHtcclxuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX3JlbGF0aXZlVGltZVtkaWZmID4gMCA/ICdmdXR1cmUnIDogJ3Bhc3QnXTtcclxuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBmb3JtYXQgPT09ICdmdW5jdGlvbicgPyBmb3JtYXQob3V0cHV0KSA6IGZvcm1hdC5yZXBsYWNlKC8lcy9pLCBvdXRwdXQpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcmRpbmFsLnJlcGxhY2UoXCIlZFwiLCBudW1iZXIpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgX29yZGluYWwgOiBcIiVkXCIsXHJcblxyXG4gICAgICAgIHByZXBhcnNlIDogZnVuY3Rpb24gKHN0cmluZykge1xyXG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHBvc3Rmb3JtYXQgOiBmdW5jdGlvbiAoc3RyaW5nKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmc7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgd2VlayA6IGZ1bmN0aW9uIChtb20pIHtcclxuICAgICAgICAgICAgcmV0dXJuIHdlZWtPZlllYXIobW9tLCB0aGlzLl93ZWVrLmRvdywgdGhpcy5fd2Vlay5kb3kpLndlZWs7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX3dlZWsgOiB7XHJcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxyXG4gICAgICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgX2ludmFsaWREYXRlOiAnSW52YWxpZCBkYXRlJyxcclxuICAgICAgICBpbnZhbGlkRGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faW52YWxpZERhdGU7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gTG9hZHMgYSBsYW5ndWFnZSBkZWZpbml0aW9uIGludG8gdGhlIGBsYW5ndWFnZXNgIGNhY2hlLiAgVGhlIGZ1bmN0aW9uXHJcbiAgICAvLyB0YWtlcyBhIGtleSBhbmQgb3B0aW9uYWxseSB2YWx1ZXMuICBJZiBub3QgaW4gdGhlIGJyb3dzZXIgYW5kIG5vIHZhbHVlc1xyXG4gICAgLy8gYXJlIHByb3ZpZGVkLCBpdCB3aWxsIGxvYWQgdGhlIGxhbmd1YWdlIGZpbGUgbW9kdWxlLiAgQXMgYSBjb252ZW5pZW5jZSxcclxuICAgIC8vIHRoaXMgZnVuY3Rpb24gYWxzbyByZXR1cm5zIHRoZSBsYW5ndWFnZSB2YWx1ZXMuXHJcbiAgICBmdW5jdGlvbiBsb2FkTGFuZyhrZXksIHZhbHVlcykge1xyXG4gICAgICAgIHZhbHVlcy5hYmJyID0ga2V5O1xyXG4gICAgICAgIGlmICghbGFuZ3VhZ2VzW2tleV0pIHtcclxuICAgICAgICAgICAgbGFuZ3VhZ2VzW2tleV0gPSBuZXcgTGFuZ3VhZ2UoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgbGFuZ3VhZ2VzW2tleV0uc2V0KHZhbHVlcyk7XHJcbiAgICAgICAgcmV0dXJuIGxhbmd1YWdlc1trZXldO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlbW92ZSBhIGxhbmd1YWdlIGZyb20gdGhlIGBsYW5ndWFnZXNgIGNhY2hlLiBNb3N0bHkgdXNlZnVsIGluIHRlc3RzLlxyXG4gICAgZnVuY3Rpb24gdW5sb2FkTGFuZyhrZXkpIHtcclxuICAgICAgICBkZWxldGUgbGFuZ3VhZ2VzW2tleV07XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRGV0ZXJtaW5lcyB3aGljaCBsYW5ndWFnZSBkZWZpbml0aW9uIHRvIHVzZSBhbmQgcmV0dXJucyBpdC5cclxuICAgIC8vXHJcbiAgICAvLyBXaXRoIG5vIHBhcmFtZXRlcnMsIGl0IHdpbGwgcmV0dXJuIHRoZSBnbG9iYWwgbGFuZ3VhZ2UuICBJZiB5b3VcclxuICAgIC8vIHBhc3MgaW4gYSBsYW5ndWFnZSBrZXksIHN1Y2ggYXMgJ2VuJywgaXQgd2lsbCByZXR1cm4gdGhlXHJcbiAgICAvLyBkZWZpbml0aW9uIGZvciAnZW4nLCBzbyBsb25nIGFzICdlbicgaGFzIGFscmVhZHkgYmVlbiBsb2FkZWQgdXNpbmdcclxuICAgIC8vIG1vbWVudC5sYW5nLlxyXG4gICAgZnVuY3Rpb24gZ2V0TGFuZ0RlZmluaXRpb24oa2V5KSB7XHJcbiAgICAgICAgdmFyIGkgPSAwLCBqLCBsYW5nLCBuZXh0LCBzcGxpdCxcclxuICAgICAgICAgICAgZ2V0ID0gZnVuY3Rpb24gKGspIHtcclxuICAgICAgICAgICAgICAgIGlmICghbGFuZ3VhZ2VzW2tdICYmIGhhc01vZHVsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmUoJy4vbGFuZy8nICsgayk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgeyB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFuZ3VhZ2VzW2tdO1xyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICBpZiAoIWtleSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LmZuLl9sYW5nO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCFpc0FycmF5KGtleSkpIHtcclxuICAgICAgICAgICAgLy9zaG9ydC1jaXJjdWl0IGV2ZXJ5dGhpbmcgZWxzZVxyXG4gICAgICAgICAgICBsYW5nID0gZ2V0KGtleSk7XHJcbiAgICAgICAgICAgIGlmIChsYW5nKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFuZztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBrZXkgPSBba2V5XTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vcGljayB0aGUgbGFuZ3VhZ2UgZnJvbSB0aGUgYXJyYXlcclxuICAgICAgICAvL3RyeSBbJ2VuLWF1JywgJ2VuLWdiJ10gYXMgJ2VuLWF1JywgJ2VuLWdiJywgJ2VuJywgYXMgaW4gbW92ZSB0aHJvdWdoIHRoZSBsaXN0IHRyeWluZyBlYWNoXHJcbiAgICAgICAgLy9zdWJzdHJpbmcgZnJvbSBtb3N0IHNwZWNpZmljIHRvIGxlYXN0LCBidXQgbW92ZSB0byB0aGUgbmV4dCBhcnJheSBpdGVtIGlmIGl0J3MgYSBtb3JlIHNwZWNpZmljIHZhcmlhbnQgdGhhbiB0aGUgY3VycmVudCByb290XHJcbiAgICAgICAgd2hpbGUgKGkgPCBrZXkubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHNwbGl0ID0gbm9ybWFsaXplTGFuZ3VhZ2Uoa2V5W2ldKS5zcGxpdCgnLScpO1xyXG4gICAgICAgICAgICBqID0gc3BsaXQubGVuZ3RoO1xyXG4gICAgICAgICAgICBuZXh0ID0gbm9ybWFsaXplTGFuZ3VhZ2Uoa2V5W2kgKyAxXSk7XHJcbiAgICAgICAgICAgIG5leHQgPSBuZXh0ID8gbmV4dC5zcGxpdCgnLScpIDogbnVsbDtcclxuICAgICAgICAgICAgd2hpbGUgKGogPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBsYW5nID0gZ2V0KHNwbGl0LnNsaWNlKDAsIGopLmpvaW4oJy0nKSk7XHJcbiAgICAgICAgICAgICAgICBpZiAobGFuZykge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsYW5nO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKG5leHQgJiYgbmV4dC5sZW5ndGggPj0gaiAmJiBjb21wYXJlQXJyYXlzKHNwbGl0LCBuZXh0LCB0cnVlKSA+PSBqIC0gMSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGotLTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpKys7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBtb21lbnQuZm4uX2xhbmc7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIEZvcm1hdHRpbmdcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgZnVuY3Rpb24gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhpbnB1dCkge1xyXG4gICAgICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gaW5wdXQucmVwbGFjZSgvXlxcW3xcXF0kL2csIFwiXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaW5wdXQucmVwbGFjZSgvXFxcXC9nLCBcIlwiKTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBtYWtlRm9ybWF0RnVuY3Rpb24oZm9ybWF0KSB7XHJcbiAgICAgICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLCBpLCBsZW5ndGg7XHJcblxyXG4gICAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChmb3JtYXRUb2tlbkZ1bmN0aW9uc1thcnJheVtpXV0pIHtcclxuICAgICAgICAgICAgICAgIGFycmF5W2ldID0gZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgYXJyYXlbaV0gPSByZW1vdmVGb3JtYXR0aW5nVG9rZW5zKGFycmF5W2ldKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtb20pIHtcclxuICAgICAgICAgICAgdmFyIG91dHB1dCA9IFwiXCI7XHJcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgb3V0cHV0ICs9IGFycmF5W2ldIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBhcnJheVtpXS5jYWxsKG1vbSwgZm9ybWF0KSA6IGFycmF5W2ldO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQ7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBmb3JtYXQgZGF0ZSB1c2luZyBuYXRpdmUgZGF0ZSBvYmplY3RcclxuICAgIGZ1bmN0aW9uIGZvcm1hdE1vbWVudChtLCBmb3JtYXQpIHtcclxuXHJcbiAgICAgICAgaWYgKCFtLmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbS5sYW5nKCkuaW52YWxpZERhdGUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvcm1hdCA9IGV4cGFuZEZvcm1hdChmb3JtYXQsIG0ubGFuZygpKTtcclxuXHJcbiAgICAgICAgaWYgKCFmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XSkge1xyXG4gICAgICAgICAgICBmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XSA9IG1ha2VGb3JtYXRGdW5jdGlvbihmb3JtYXQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdKG0pO1xyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGV4cGFuZEZvcm1hdChmb3JtYXQsIGxhbmcpIHtcclxuICAgICAgICB2YXIgaSA9IDU7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VMb25nRGF0ZUZvcm1hdFRva2VucyhpbnB1dCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbGFuZy5sb25nRGF0ZUZvcm1hdChpbnB1dCkgfHwgaW5wdXQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcclxuICAgICAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcclxuICAgICAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UobG9jYWxGb3JtYXR0aW5nVG9rZW5zLCByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnMpO1xyXG4gICAgICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcclxuICAgICAgICAgICAgaSAtPSAxO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZvcm1hdDtcclxuICAgIH1cclxuXHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIFBhcnNpbmdcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgLy8gZ2V0IHRoZSByZWdleCB0byBmaW5kIHRoZSBuZXh0IHRva2VuXHJcbiAgICBmdW5jdGlvbiBnZXRQYXJzZVJlZ2V4Rm9yVG9rZW4odG9rZW4sIGNvbmZpZykge1xyXG4gICAgICAgIHZhciBhLCBzdHJpY3QgPSBjb25maWcuX3N0cmljdDtcclxuICAgICAgICBzd2l0Y2ggKHRva2VuKSB7XHJcbiAgICAgICAgY2FzZSAnRERERCc6XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVRva2VuVGhyZWVEaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnWVlZWSc6XHJcbiAgICAgICAgY2FzZSAnR0dHRyc6XHJcbiAgICAgICAgY2FzZSAnZ2dnZyc6XHJcbiAgICAgICAgICAgIHJldHVybiBzdHJpY3QgPyBwYXJzZVRva2VuRm91ckRpZ2l0cyA6IHBhcnNlVG9rZW5PbmVUb0ZvdXJEaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnWSc6XHJcbiAgICAgICAgY2FzZSAnRyc6XHJcbiAgICAgICAgY2FzZSAnZyc6XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVRva2VuU2lnbmVkTnVtYmVyO1xyXG4gICAgICAgIGNhc2UgJ1lZWVlZWSc6XHJcbiAgICAgICAgY2FzZSAnWVlZWVknOlxyXG4gICAgICAgIGNhc2UgJ0dHR0dHJzpcclxuICAgICAgICBjYXNlICdnZ2dnZyc6XHJcbiAgICAgICAgICAgIHJldHVybiBzdHJpY3QgPyBwYXJzZVRva2VuU2l4RGlnaXRzIDogcGFyc2VUb2tlbk9uZVRvU2l4RGlnaXRzO1xyXG4gICAgICAgIGNhc2UgJ1MnOlxyXG4gICAgICAgICAgICBpZiAoc3RyaWN0KSB7IHJldHVybiBwYXJzZVRva2VuT25lRGlnaXQ7IH1cclxuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xyXG4gICAgICAgIGNhc2UgJ1NTJzpcclxuICAgICAgICAgICAgaWYgKHN0cmljdCkgeyByZXR1cm4gcGFyc2VUb2tlblR3b0RpZ2l0czsgfVxyXG4gICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXHJcbiAgICAgICAgY2FzZSAnU1NTJzpcclxuICAgICAgICAgICAgaWYgKHN0cmljdCkgeyByZXR1cm4gcGFyc2VUb2tlblRocmVlRGlnaXRzOyB9XHJcbiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cclxuICAgICAgICBjYXNlICdEREQnOlxyXG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlbk9uZVRvVGhyZWVEaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnTU1NJzpcclxuICAgICAgICBjYXNlICdNTU1NJzpcclxuICAgICAgICBjYXNlICdkZCc6XHJcbiAgICAgICAgY2FzZSAnZGRkJzpcclxuICAgICAgICBjYXNlICdkZGRkJzpcclxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5Xb3JkO1xyXG4gICAgICAgIGNhc2UgJ2EnOlxyXG4gICAgICAgIGNhc2UgJ0EnOlxyXG4gICAgICAgICAgICByZXR1cm4gZ2V0TGFuZ0RlZmluaXRpb24oY29uZmlnLl9sKS5fbWVyaWRpZW1QYXJzZTtcclxuICAgICAgICBjYXNlICdYJzpcclxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5UaW1lc3RhbXBNcztcclxuICAgICAgICBjYXNlICdaJzpcclxuICAgICAgICBjYXNlICdaWic6XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVRva2VuVGltZXpvbmU7XHJcbiAgICAgICAgY2FzZSAnVCc6XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVRva2VuVDtcclxuICAgICAgICBjYXNlICdTU1NTJzpcclxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5EaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnTU0nOlxyXG4gICAgICAgIGNhc2UgJ0REJzpcclxuICAgICAgICBjYXNlICdZWSc6XHJcbiAgICAgICAgY2FzZSAnR0cnOlxyXG4gICAgICAgIGNhc2UgJ2dnJzpcclxuICAgICAgICBjYXNlICdISCc6XHJcbiAgICAgICAgY2FzZSAnaGgnOlxyXG4gICAgICAgIGNhc2UgJ21tJzpcclxuICAgICAgICBjYXNlICdzcyc6XHJcbiAgICAgICAgY2FzZSAnd3cnOlxyXG4gICAgICAgIGNhc2UgJ1dXJzpcclxuICAgICAgICAgICAgcmV0dXJuIHN0cmljdCA/IHBhcnNlVG9rZW5Ud29EaWdpdHMgOiBwYXJzZVRva2VuT25lT3JUd29EaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnTSc6XHJcbiAgICAgICAgY2FzZSAnRCc6XHJcbiAgICAgICAgY2FzZSAnZCc6XHJcbiAgICAgICAgY2FzZSAnSCc6XHJcbiAgICAgICAgY2FzZSAnaCc6XHJcbiAgICAgICAgY2FzZSAnbSc6XHJcbiAgICAgICAgY2FzZSAncyc6XHJcbiAgICAgICAgY2FzZSAndyc6XHJcbiAgICAgICAgY2FzZSAnVyc6XHJcbiAgICAgICAgY2FzZSAnZSc6XHJcbiAgICAgICAgY2FzZSAnRSc6XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZVRva2VuT25lT3JUd29EaWdpdHM7XHJcbiAgICAgICAgY2FzZSAnRG8nOlxyXG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlbk9yZGluYWw7XHJcbiAgICAgICAgZGVmYXVsdCA6XHJcbiAgICAgICAgICAgIGEgPSBuZXcgUmVnRXhwKHJlZ2V4cEVzY2FwZSh1bmVzY2FwZUZvcm1hdCh0b2tlbi5yZXBsYWNlKCdcXFxcJywgJycpKSwgXCJpXCIpKTtcclxuICAgICAgICAgICAgcmV0dXJuIGE7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIHRpbWV6b25lTWludXRlc0Zyb21TdHJpbmcoc3RyaW5nKSB7XHJcbiAgICAgICAgc3RyaW5nID0gc3RyaW5nIHx8IFwiXCI7XHJcbiAgICAgICAgdmFyIHBvc3NpYmxlVHpNYXRjaGVzID0gKHN0cmluZy5tYXRjaChwYXJzZVRva2VuVGltZXpvbmUpIHx8IFtdKSxcclxuICAgICAgICAgICAgdHpDaHVuayA9IHBvc3NpYmxlVHpNYXRjaGVzW3Bvc3NpYmxlVHpNYXRjaGVzLmxlbmd0aCAtIDFdIHx8IFtdLFxyXG4gICAgICAgICAgICBwYXJ0cyA9ICh0ekNodW5rICsgJycpLm1hdGNoKHBhcnNlVGltZXpvbmVDaHVua2VyKSB8fCBbJy0nLCAwLCAwXSxcclxuICAgICAgICAgICAgbWludXRlcyA9ICsocGFydHNbMV0gKiA2MCkgKyB0b0ludChwYXJ0c1syXSk7XHJcblxyXG4gICAgICAgIHJldHVybiBwYXJ0c1swXSA9PT0gJysnID8gLW1pbnV0ZXMgOiBtaW51dGVzO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGZ1bmN0aW9uIHRvIGNvbnZlcnQgc3RyaW5nIGlucHV0IHRvIGRhdGVcclxuICAgIGZ1bmN0aW9uIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBpbnB1dCwgY29uZmlnKSB7XHJcbiAgICAgICAgdmFyIGEsIGRhdGVQYXJ0QXJyYXkgPSBjb25maWcuX2E7XHJcblxyXG4gICAgICAgIHN3aXRjaCAodG9rZW4pIHtcclxuICAgICAgICAvLyBNT05USFxyXG4gICAgICAgIGNhc2UgJ00nIDogLy8gZmFsbCB0aHJvdWdoIHRvIE1NXHJcbiAgICAgICAgY2FzZSAnTU0nIDpcclxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGRhdGVQYXJ0QXJyYXlbTU9OVEhdID0gdG9JbnQoaW5wdXQpIC0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICdNTU0nIDogLy8gZmFsbCB0aHJvdWdoIHRvIE1NTU1cclxuICAgICAgICBjYXNlICdNTU1NJyA6XHJcbiAgICAgICAgICAgIGEgPSBnZXRMYW5nRGVmaW5pdGlvbihjb25maWcuX2wpLm1vbnRoc1BhcnNlKGlucHV0KTtcclxuICAgICAgICAgICAgLy8gaWYgd2UgZGlkbid0IGZpbmQgYSBtb250aCBuYW1lLCBtYXJrIHRoZSBkYXRlIGFzIGludmFsaWQuXHJcbiAgICAgICAgICAgIGlmIChhICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGRhdGVQYXJ0QXJyYXlbTU9OVEhdID0gYTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5fcGYuaW52YWxpZE1vbnRoID0gaW5wdXQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgLy8gREFZIE9GIE1PTlRIXHJcbiAgICAgICAgY2FzZSAnRCcgOiAvLyBmYWxsIHRocm91Z2ggdG8gRERcclxuICAgICAgICBjYXNlICdERCcgOlxyXG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtEQVRFXSA9IHRvSW50KGlucHV0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICdEbycgOlxyXG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtEQVRFXSA9IHRvSW50KHBhcnNlSW50KGlucHV0LCAxMCkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIC8vIERBWSBPRiBZRUFSXHJcbiAgICAgICAgY2FzZSAnREREJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBEREREXHJcbiAgICAgICAgY2FzZSAnRERERCcgOlxyXG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uZmlnLl9kYXlPZlllYXIgPSB0b0ludChpbnB1dCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIC8vIFlFQVJcclxuICAgICAgICBjYXNlICdZWScgOlxyXG4gICAgICAgICAgICBkYXRlUGFydEFycmF5W1lFQVJdID0gdG9JbnQoaW5wdXQpICsgKHRvSW50KGlucHV0KSA+IDY4ID8gMTkwMCA6IDIwMDApO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICdZWVlZJyA6XHJcbiAgICAgICAgY2FzZSAnWVlZWVknIDpcclxuICAgICAgICBjYXNlICdZWVlZWVknIDpcclxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtZRUFSXSA9IHRvSW50KGlucHV0KTtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgLy8gQU0gLyBQTVxyXG4gICAgICAgIGNhc2UgJ2EnIDogLy8gZmFsbCB0aHJvdWdoIHRvIEFcclxuICAgICAgICBjYXNlICdBJyA6XHJcbiAgICAgICAgICAgIGNvbmZpZy5faXNQbSA9IGdldExhbmdEZWZpbml0aW9uKGNvbmZpZy5fbCkuaXNQTShpbnB1dCk7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIC8vIDI0IEhPVVJcclxuICAgICAgICBjYXNlICdIJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBoaFxyXG4gICAgICAgIGNhc2UgJ0hIJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBoaFxyXG4gICAgICAgIGNhc2UgJ2gnIDogLy8gZmFsbCB0aHJvdWdoIHRvIGhoXHJcbiAgICAgICAgY2FzZSAnaGgnIDpcclxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtIT1VSXSA9IHRvSW50KGlucHV0KTtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgLy8gTUlOVVRFXHJcbiAgICAgICAgY2FzZSAnbScgOiAvLyBmYWxsIHRocm91Z2ggdG8gbW1cclxuICAgICAgICBjYXNlICdtbScgOlxyXG4gICAgICAgICAgICBkYXRlUGFydEFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dCk7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIC8vIFNFQ09ORFxyXG4gICAgICAgIGNhc2UgJ3MnIDogLy8gZmFsbCB0aHJvdWdoIHRvIHNzXHJcbiAgICAgICAgY2FzZSAnc3MnIDpcclxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtTRUNPTkRdID0gdG9JbnQoaW5wdXQpO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICAvLyBNSUxMSVNFQ09ORFxyXG4gICAgICAgIGNhc2UgJ1MnIDpcclxuICAgICAgICBjYXNlICdTUycgOlxyXG4gICAgICAgIGNhc2UgJ1NTUycgOlxyXG4gICAgICAgIGNhc2UgJ1NTU1MnIDpcclxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtNSUxMSVNFQ09ORF0gPSB0b0ludCgoJzAuJyArIGlucHV0KSAqIDEwMDApO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICAvLyBVTklYIFRJTUVTVEFNUCBXSVRIIE1TXHJcbiAgICAgICAgY2FzZSAnWCc6XHJcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKHBhcnNlRmxvYXQoaW5wdXQpICogMTAwMCk7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIC8vIFRJTUVaT05FXHJcbiAgICAgICAgY2FzZSAnWicgOiAvLyBmYWxsIHRocm91Z2ggdG8gWlpcclxuICAgICAgICBjYXNlICdaWicgOlxyXG4gICAgICAgICAgICBjb25maWcuX3VzZVVUQyA9IHRydWU7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fdHptID0gdGltZXpvbmVNaW51dGVzRnJvbVN0cmluZyhpbnB1dCk7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJ3cnOlxyXG4gICAgICAgIGNhc2UgJ3d3JzpcclxuICAgICAgICBjYXNlICdXJzpcclxuICAgICAgICBjYXNlICdXVyc6XHJcbiAgICAgICAgY2FzZSAnZCc6XHJcbiAgICAgICAgY2FzZSAnZGQnOlxyXG4gICAgICAgIGNhc2UgJ2RkZCc6XHJcbiAgICAgICAgY2FzZSAnZGRkZCc6XHJcbiAgICAgICAgY2FzZSAnZSc6XHJcbiAgICAgICAgY2FzZSAnRSc6XHJcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW4uc3Vic3RyKDAsIDEpO1xyXG4gICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXHJcbiAgICAgICAgY2FzZSAnZ2cnOlxyXG4gICAgICAgIGNhc2UgJ2dnZ2cnOlxyXG4gICAgICAgIGNhc2UgJ0dHJzpcclxuICAgICAgICBjYXNlICdHR0dHJzpcclxuICAgICAgICBjYXNlICdHR0dHRyc6XHJcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW4uc3Vic3RyKDAsIDIpO1xyXG4gICAgICAgICAgICBpZiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5fdyA9IGNvbmZpZy5fdyB8fCB7fTtcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5fd1t0b2tlbl0gPSBpbnB1dDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gY29udmVydCBhbiBhcnJheSB0byBhIGRhdGUuXHJcbiAgICAvLyB0aGUgYXJyYXkgc2hvdWxkIG1pcnJvciB0aGUgcGFyYW1ldGVycyBiZWxvd1xyXG4gICAgLy8gbm90ZTogYWxsIHZhbHVlcyBwYXN0IHRoZSB5ZWFyIGFyZSBvcHRpb25hbCBhbmQgd2lsbCBkZWZhdWx0IHRvIHRoZSBsb3dlc3QgcG9zc2libGUgdmFsdWUuXHJcbiAgICAvLyBbeWVhciwgbW9udGgsIGRheSAsIGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBtaWxsaXNlY29uZF1cclxuICAgIGZ1bmN0aW9uIGRhdGVGcm9tQ29uZmlnKGNvbmZpZykge1xyXG4gICAgICAgIHZhciBpLCBkYXRlLCBpbnB1dCA9IFtdLCBjdXJyZW50RGF0ZSxcclxuICAgICAgICAgICAgeWVhclRvVXNlLCBmaXhZZWFyLCB3LCB0ZW1wLCBsYW5nLCB3ZWVrZGF5LCB3ZWVrO1xyXG5cclxuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGN1cnJlbnREYXRlID0gY3VycmVudERhdGVBcnJheShjb25maWcpO1xyXG5cclxuICAgICAgICAvL2NvbXB1dGUgZGF5IG9mIHRoZSB5ZWFyIGZyb20gd2Vla3MgYW5kIHdlZWtkYXlzXHJcbiAgICAgICAgaWYgKGNvbmZpZy5fdyAmJiBjb25maWcuX2FbREFURV0gPT0gbnVsbCAmJiBjb25maWcuX2FbTU9OVEhdID09IG51bGwpIHtcclxuICAgICAgICAgICAgZml4WWVhciA9IGZ1bmN0aW9uICh2YWwpIHtcclxuICAgICAgICAgICAgICAgIHZhciBpbnRfdmFsID0gcGFyc2VJbnQodmFsLCAxMCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsID9cclxuICAgICAgICAgICAgICAgICAgKHZhbC5sZW5ndGggPCAzID8gKGludF92YWwgPiA2OCA/IDE5MDAgKyBpbnRfdmFsIDogMjAwMCArIGludF92YWwpIDogaW50X3ZhbCkgOlxyXG4gICAgICAgICAgICAgICAgICAoY29uZmlnLl9hW1lFQVJdID09IG51bGwgPyBtb21lbnQoKS53ZWVrWWVhcigpIDogY29uZmlnLl9hW1lFQVJdKTtcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIHcgPSBjb25maWcuX3c7XHJcbiAgICAgICAgICAgIGlmICh3LkdHICE9IG51bGwgfHwgdy5XICE9IG51bGwgfHwgdy5FICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHRlbXAgPSBkYXlPZlllYXJGcm9tV2Vla3MoZml4WWVhcih3LkdHKSwgdy5XIHx8IDEsIHcuRSwgNCwgMSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBsYW5nID0gZ2V0TGFuZ0RlZmluaXRpb24oY29uZmlnLl9sKTtcclxuICAgICAgICAgICAgICAgIHdlZWtkYXkgPSB3LmQgIT0gbnVsbCA/ICBwYXJzZVdlZWtkYXkody5kLCBsYW5nKSA6XHJcbiAgICAgICAgICAgICAgICAgICh3LmUgIT0gbnVsbCA/ICBwYXJzZUludCh3LmUsIDEwKSArIGxhbmcuX3dlZWsuZG93IDogMCk7XHJcblxyXG4gICAgICAgICAgICAgICAgd2VlayA9IHBhcnNlSW50KHcudywgMTApIHx8IDE7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9pZiB3ZSdyZSBwYXJzaW5nICdkJywgdGhlbiB0aGUgbG93IGRheSBudW1iZXJzIG1heSBiZSBuZXh0IHdlZWtcclxuICAgICAgICAgICAgICAgIGlmICh3LmQgIT0gbnVsbCAmJiB3ZWVrZGF5IDwgbGFuZy5fd2Vlay5kb3cpIHtcclxuICAgICAgICAgICAgICAgICAgICB3ZWVrKys7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgdGVtcCA9IGRheU9mWWVhckZyb21XZWVrcyhmaXhZZWFyKHcuZ2cpLCB3ZWVrLCB3ZWVrZGF5LCBsYW5nLl93ZWVrLmRveSwgbGFuZy5fd2Vlay5kb3cpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25maWcuX2FbWUVBUl0gPSB0ZW1wLnllYXI7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdGVtcC5kYXlPZlllYXI7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL2lmIHRoZSBkYXkgb2YgdGhlIHllYXIgaXMgc2V0LCBmaWd1cmUgb3V0IHdoYXQgaXQgaXNcclxuICAgICAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIpIHtcclxuICAgICAgICAgICAgeWVhclRvVXNlID0gY29uZmlnLl9hW1lFQVJdID09IG51bGwgPyBjdXJyZW50RGF0ZVtZRUFSXSA6IGNvbmZpZy5fYVtZRUFSXTtcclxuXHJcbiAgICAgICAgICAgIGlmIChjb25maWcuX2RheU9mWWVhciA+IGRheXNJblllYXIoeWVhclRvVXNlKSkge1xyXG4gICAgICAgICAgICAgICAgY29uZmlnLl9wZi5fb3ZlcmZsb3dEYXlPZlllYXIgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBkYXRlID0gbWFrZVVUQ0RhdGUoeWVhclRvVXNlLCAwLCBjb25maWcuX2RheU9mWWVhcik7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fYVtNT05USF0gPSBkYXRlLmdldFVUQ01vbnRoKCk7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fYVtEQVRFXSA9IGRhdGUuZ2V0VVRDRGF0ZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IGRhdGUuXHJcbiAgICAgICAgLy8gKiBpZiBubyB5ZWFyLCBtb250aCwgZGF5IG9mIG1vbnRoIGFyZSBnaXZlbiwgZGVmYXVsdCB0byB0b2RheVxyXG4gICAgICAgIC8vICogaWYgZGF5IG9mIG1vbnRoIGlzIGdpdmVuLCBkZWZhdWx0IG1vbnRoIGFuZCB5ZWFyXHJcbiAgICAgICAgLy8gKiBpZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBvbmx5IHllYXJcclxuICAgICAgICAvLyAqIGlmIHllYXIgaXMgZ2l2ZW4sIGRvbid0IGRlZmF1bHQgYW55dGhpbmdcclxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMyAmJiBjb25maWcuX2FbaV0gPT0gbnVsbDsgKytpKSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gY3VycmVudERhdGVbaV07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBaZXJvIG91dCB3aGF0ZXZlciB3YXMgbm90IGRlZmF1bHRlZCwgaW5jbHVkaW5nIHRpbWVcclxuICAgICAgICBmb3IgKDsgaSA8IDc7IGkrKykge1xyXG4gICAgICAgICAgICBjb25maWcuX2FbaV0gPSBpbnB1dFtpXSA9IChjb25maWcuX2FbaV0gPT0gbnVsbCkgPyAoaSA9PT0gMiA/IDEgOiAwKSA6IGNvbmZpZy5fYVtpXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIGFkZCB0aGUgb2Zmc2V0cyB0byB0aGUgdGltZSB0byBiZSBwYXJzZWQgc28gdGhhdCB3ZSBjYW4gaGF2ZSBhIGNsZWFuIGFycmF5IGZvciBjaGVja2luZyBpc1ZhbGlkXHJcbiAgICAgICAgaW5wdXRbSE9VUl0gKz0gdG9JbnQoKGNvbmZpZy5fdHptIHx8IDApIC8gNjApO1xyXG4gICAgICAgIGlucHV0W01JTlVURV0gKz0gdG9JbnQoKGNvbmZpZy5fdHptIHx8IDApICUgNjApO1xyXG5cclxuICAgICAgICBjb25maWcuX2QgPSAoY29uZmlnLl91c2VVVEMgPyBtYWtlVVRDRGF0ZSA6IG1ha2VEYXRlKS5hcHBseShudWxsLCBpbnB1dCk7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gZGF0ZUZyb21PYmplY3QoY29uZmlnKSB7XHJcbiAgICAgICAgdmFyIG5vcm1hbGl6ZWRJbnB1dDtcclxuXHJcbiAgICAgICAgaWYgKGNvbmZpZy5fZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhjb25maWcuX2kpO1xyXG4gICAgICAgIGNvbmZpZy5fYSA9IFtcclxuICAgICAgICAgICAgbm9ybWFsaXplZElucHV0LnllYXIsXHJcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5tb250aCxcclxuICAgICAgICAgICAgbm9ybWFsaXplZElucHV0LmRheSxcclxuICAgICAgICAgICAgbm9ybWFsaXplZElucHV0LmhvdXIsXHJcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5taW51dGUsXHJcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5zZWNvbmQsXHJcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5taWxsaXNlY29uZFxyXG4gICAgICAgIF07XHJcblxyXG4gICAgICAgIGRhdGVGcm9tQ29uZmlnKGNvbmZpZyk7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gY3VycmVudERhdGVBcnJheShjb25maWcpIHtcclxuICAgICAgICB2YXIgbm93ID0gbmV3IERhdGUoKTtcclxuICAgICAgICBpZiAoY29uZmlnLl91c2VVVEMpIHtcclxuICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgIG5vdy5nZXRVVENGdWxsWWVhcigpLFxyXG4gICAgICAgICAgICAgICAgbm93LmdldFVUQ01vbnRoKCksXHJcbiAgICAgICAgICAgICAgICBub3cuZ2V0VVRDRGF0ZSgpXHJcbiAgICAgICAgICAgIF07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIFtub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCksIG5vdy5nZXREYXRlKCldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBmb3JtYXQgc3RyaW5nXHJcbiAgICBmdW5jdGlvbiBtYWtlRGF0ZUZyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKSB7XHJcblxyXG4gICAgICAgIGNvbmZpZy5fYSA9IFtdO1xyXG4gICAgICAgIGNvbmZpZy5fcGYuZW1wdHkgPSB0cnVlO1xyXG5cclxuICAgICAgICAvLyBUaGlzIGFycmF5IGlzIHVzZWQgdG8gbWFrZSBhIERhdGUsIGVpdGhlciB3aXRoIGBuZXcgRGF0ZWAgb3IgYERhdGUuVVRDYFxyXG4gICAgICAgIHZhciBsYW5nID0gZ2V0TGFuZ0RlZmluaXRpb24oY29uZmlnLl9sKSxcclxuICAgICAgICAgICAgc3RyaW5nID0gJycgKyBjb25maWcuX2ksXHJcbiAgICAgICAgICAgIGksIHBhcnNlZElucHV0LCB0b2tlbnMsIHRva2VuLCBza2lwcGVkLFxyXG4gICAgICAgICAgICBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoLFxyXG4gICAgICAgICAgICB0b3RhbFBhcnNlZElucHV0TGVuZ3RoID0gMDtcclxuXHJcbiAgICAgICAgdG9rZW5zID0gZXhwYW5kRm9ybWF0KGNvbmZpZy5fZiwgbGFuZykubWF0Y2goZm9ybWF0dGluZ1Rva2VucykgfHwgW107XHJcblxyXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgdG9rZW4gPSB0b2tlbnNbaV07XHJcbiAgICAgICAgICAgIHBhcnNlZElucHV0ID0gKHN0cmluZy5tYXRjaChnZXRQYXJzZVJlZ2V4Rm9yVG9rZW4odG9rZW4sIGNvbmZpZykpIHx8IFtdKVswXTtcclxuICAgICAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XHJcbiAgICAgICAgICAgICAgICBza2lwcGVkID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHNraXBwZWQubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5fcGYudW51c2VkSW5wdXQucHVzaChza2lwcGVkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHN0cmluZyA9IHN0cmluZy5zbGljZShzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkgKyBwYXJzZWRJbnB1dC5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgdG90YWxQYXJzZWRJbnB1dExlbmd0aCArPSBwYXJzZWRJbnB1dC5sZW5ndGg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gZG9uJ3QgcGFyc2UgaWYgaXQncyBub3QgYSBrbm93biB0b2tlblxyXG4gICAgICAgICAgICBpZiAoZm9ybWF0VG9rZW5GdW5jdGlvbnNbdG9rZW5dKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkSW5wdXQpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25maWcuX3BmLmVtcHR5ID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25maWcuX3BmLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBwYXJzZWRJbnB1dCwgY29uZmlnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmIChjb25maWcuX3N0cmljdCAmJiAhcGFyc2VkSW5wdXQpIHtcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5fcGYudW51c2VkVG9rZW5zLnB1c2godG9rZW4pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBhZGQgcmVtYWluaW5nIHVucGFyc2VkIGlucHV0IGxlbmd0aCB0byB0aGUgc3RyaW5nXHJcbiAgICAgICAgY29uZmlnLl9wZi5jaGFyc0xlZnRPdmVyID0gc3RyaW5nTGVuZ3RoIC0gdG90YWxQYXJzZWRJbnB1dExlbmd0aDtcclxuICAgICAgICBpZiAoc3RyaW5nLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgY29uZmlnLl9wZi51bnVzZWRJbnB1dC5wdXNoKHN0cmluZyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBoYW5kbGUgYW0gcG1cclxuICAgICAgICBpZiAoY29uZmlnLl9pc1BtICYmIGNvbmZpZy5fYVtIT1VSXSA8IDEyKSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSArPSAxMjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gaWYgaXMgMTIgYW0sIGNoYW5nZSBob3VycyB0byAwXHJcbiAgICAgICAgaWYgKGNvbmZpZy5faXNQbSA9PT0gZmFsc2UgJiYgY29uZmlnLl9hW0hPVVJdID09PSAxMikge1xyXG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPSAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZGF0ZUZyb21Db25maWcoY29uZmlnKTtcclxuICAgICAgICBjaGVja092ZXJmbG93KGNvbmZpZyk7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gdW5lc2NhcGVGb3JtYXQocykge1xyXG4gICAgICAgIHJldHVybiBzLnJlcGxhY2UoL1xcXFwoXFxbKXxcXFxcKFxcXSl8XFxbKFteXFxdXFxbXSopXFxdfFxcXFwoLikvZywgZnVuY3Rpb24gKG1hdGNoZWQsIHAxLCBwMiwgcDMsIHA0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBwMSB8fCBwMiB8fCBwMyB8fCBwNDtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zNTYxNDkzL2lzLXRoZXJlLWEtcmVnZXhwLWVzY2FwZS1mdW5jdGlvbi1pbi1qYXZhc2NyaXB0XHJcbiAgICBmdW5jdGlvbiByZWdleHBFc2NhcGUocykge1xyXG4gICAgICAgIHJldHVybiBzLnJlcGxhY2UoL1stXFwvXFxcXF4kKis/LigpfFtcXF17fV0vZywgJ1xcXFwkJicpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGRhdGUgZnJvbSBzdHJpbmcgYW5kIGFycmF5IG9mIGZvcm1hdCBzdHJpbmdzXHJcbiAgICBmdW5jdGlvbiBtYWtlRGF0ZUZyb21TdHJpbmdBbmRBcnJheShjb25maWcpIHtcclxuICAgICAgICB2YXIgdGVtcENvbmZpZyxcclxuICAgICAgICAgICAgYmVzdE1vbWVudCxcclxuXHJcbiAgICAgICAgICAgIHNjb3JlVG9CZWF0LFxyXG4gICAgICAgICAgICBpLFxyXG4gICAgICAgICAgICBjdXJyZW50U2NvcmU7XHJcblxyXG4gICAgICAgIGlmIChjb25maWcuX2YubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fcGYuaW52YWxpZEZvcm1hdCA9IHRydWU7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKE5hTik7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb25maWcuX2YubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgY3VycmVudFNjb3JlID0gMDtcclxuICAgICAgICAgICAgdGVtcENvbmZpZyA9IGV4dGVuZCh7fSwgY29uZmlnKTtcclxuICAgICAgICAgICAgdGVtcENvbmZpZy5fcGYgPSBkZWZhdWx0UGFyc2luZ0ZsYWdzKCk7XHJcbiAgICAgICAgICAgIHRlbXBDb25maWcuX2YgPSBjb25maWcuX2ZbaV07XHJcbiAgICAgICAgICAgIG1ha2VEYXRlRnJvbVN0cmluZ0FuZEZvcm1hdCh0ZW1wQ29uZmlnKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghaXNWYWxpZCh0ZW1wQ29uZmlnKSkge1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIGFueSBpbnB1dCB0aGF0IHdhcyBub3QgcGFyc2VkIGFkZCBhIHBlbmFsdHkgZm9yIHRoYXQgZm9ybWF0XHJcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSArPSB0ZW1wQ29uZmlnLl9wZi5jaGFyc0xlZnRPdmVyO1xyXG5cclxuICAgICAgICAgICAgLy9vciB0b2tlbnNcclxuICAgICAgICAgICAgY3VycmVudFNjb3JlICs9IHRlbXBDb25maWcuX3BmLnVudXNlZFRva2Vucy5sZW5ndGggKiAxMDtcclxuXHJcbiAgICAgICAgICAgIHRlbXBDb25maWcuX3BmLnNjb3JlID0gY3VycmVudFNjb3JlO1xyXG5cclxuICAgICAgICAgICAgaWYgKHNjb3JlVG9CZWF0ID09IG51bGwgfHwgY3VycmVudFNjb3JlIDwgc2NvcmVUb0JlYXQpIHtcclxuICAgICAgICAgICAgICAgIHNjb3JlVG9CZWF0ID0gY3VycmVudFNjb3JlO1xyXG4gICAgICAgICAgICAgICAgYmVzdE1vbWVudCA9IHRlbXBDb25maWc7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4dGVuZChjb25maWcsIGJlc3RNb21lbnQgfHwgdGVtcENvbmZpZyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZGF0ZSBmcm9tIGlzbyBmb3JtYXRcclxuICAgIGZ1bmN0aW9uIG1ha2VEYXRlRnJvbVN0cmluZyhjb25maWcpIHtcclxuICAgICAgICB2YXIgaSwgbCxcclxuICAgICAgICAgICAgc3RyaW5nID0gY29uZmlnLl9pLFxyXG4gICAgICAgICAgICBtYXRjaCA9IGlzb1JlZ2V4LmV4ZWMoc3RyaW5nKTtcclxuXHJcbiAgICAgICAgaWYgKG1hdGNoKSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fcGYuaXNvID0gdHJ1ZTtcclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb0RhdGVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGlzb0RhdGVzW2ldWzFdLmV4ZWMoc3RyaW5nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIG1hdGNoWzVdIHNob3VsZCBiZSBcIlRcIiBvciB1bmRlZmluZWRcclxuICAgICAgICAgICAgICAgICAgICBjb25maWcuX2YgPSBpc29EYXRlc1tpXVswXSArIChtYXRjaFs2XSB8fCBcIiBcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb1RpbWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGlzb1RpbWVzW2ldWzFdLmV4ZWMoc3RyaW5nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5fZiArPSBpc29UaW1lc1tpXVswXTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoc3RyaW5nLm1hdGNoKHBhcnNlVG9rZW5UaW1lem9uZSkpIHtcclxuICAgICAgICAgICAgICAgIGNvbmZpZy5fZiArPSBcIlpcIjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBtYWtlRGF0ZUZyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKHN0cmluZyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIG1ha2VEYXRlRnJvbUlucHV0KGNvbmZpZykge1xyXG4gICAgICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faSxcclxuICAgICAgICAgICAgbWF0Y2hlZCA9IGFzcE5ldEpzb25SZWdleC5leGVjKGlucHV0KTtcclxuXHJcbiAgICAgICAgaWYgKGlucHV0ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKG1hdGNoZWQpIHtcclxuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoK21hdGNoZWRbMV0pO1xyXG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBtYWtlRGF0ZUZyb21TdHJpbmcoY29uZmlnKTtcclxuICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoaW5wdXQpKSB7XHJcbiAgICAgICAgICAgIGNvbmZpZy5fYSA9IGlucHV0LnNsaWNlKDApO1xyXG4gICAgICAgICAgICBkYXRlRnJvbUNvbmZpZyhjb25maWcpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xyXG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSgraW5wdXQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mKGlucHV0KSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgICAgICAgZGF0ZUZyb21PYmplY3QoY29uZmlnKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShpbnB1dCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIG1ha2VEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKSB7XHJcbiAgICAgICAgLy9jYW4ndCBqdXN0IGFwcGx5KCkgdG8gY3JlYXRlIGEgZGF0ZTpcclxuICAgICAgICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTgxMzQ4L2luc3RhbnRpYXRpbmctYS1qYXZhc2NyaXB0LW9iamVjdC1ieS1jYWxsaW5nLXByb3RvdHlwZS1jb25zdHJ1Y3Rvci1hcHBseVxyXG4gICAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoeSwgbSwgZCwgaCwgTSwgcywgbXMpO1xyXG5cclxuICAgICAgICAvL3RoZSBkYXRlIGNvbnN0cnVjdG9yIGRvZXNuJ3QgYWNjZXB0IHllYXJzIDwgMTk3MFxyXG4gICAgICAgIGlmICh5IDwgMTk3MCkge1xyXG4gICAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKHkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZGF0ZTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBtYWtlVVRDRGF0ZSh5KSB7XHJcbiAgICAgICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShudWxsLCBhcmd1bWVudHMpKTtcclxuICAgICAgICBpZiAoeSA8IDE5NzApIHtcclxuICAgICAgICAgICAgZGF0ZS5zZXRVVENGdWxsWWVhcih5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGRhdGU7XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gcGFyc2VXZWVrZGF5KGlucHV0LCBsYW5ndWFnZSkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgIGlmICghaXNOYU4oaW5wdXQpKSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dCA9IHBhcnNlSW50KGlucHV0LCAxMCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dCA9IGxhbmd1YWdlLndlZWtkYXlzUGFyc2UoaW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ251bWJlcicpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaW5wdXQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgIFJlbGF0aXZlIFRpbWVcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgLy8gaGVscGVyIGZ1bmN0aW9uIGZvciBtb21lbnQuZm4uZnJvbSwgbW9tZW50LmZuLmZyb21Ob3csIGFuZCBtb21lbnQuZHVyYXRpb24uZm4uaHVtYW5pemVcclxuICAgIGZ1bmN0aW9uIHN1YnN0aXR1dGVUaW1lQWdvKHN0cmluZywgbnVtYmVyLCB3aXRob3V0U3VmZml4LCBpc0Z1dHVyZSwgbGFuZykge1xyXG4gICAgICAgIHJldHVybiBsYW5nLnJlbGF0aXZlVGltZShudW1iZXIgfHwgMSwgISF3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWUobWlsbGlzZWNvbmRzLCB3aXRob3V0U3VmZml4LCBsYW5nKSB7XHJcbiAgICAgICAgdmFyIHNlY29uZHMgPSByb3VuZChNYXRoLmFicyhtaWxsaXNlY29uZHMpIC8gMTAwMCksXHJcbiAgICAgICAgICAgIG1pbnV0ZXMgPSByb3VuZChzZWNvbmRzIC8gNjApLFxyXG4gICAgICAgICAgICBob3VycyA9IHJvdW5kKG1pbnV0ZXMgLyA2MCksXHJcbiAgICAgICAgICAgIGRheXMgPSByb3VuZChob3VycyAvIDI0KSxcclxuICAgICAgICAgICAgeWVhcnMgPSByb3VuZChkYXlzIC8gMzY1KSxcclxuICAgICAgICAgICAgYXJncyA9IHNlY29uZHMgPCA0NSAmJiBbJ3MnLCBzZWNvbmRzXSB8fFxyXG4gICAgICAgICAgICAgICAgbWludXRlcyA9PT0gMSAmJiBbJ20nXSB8fFxyXG4gICAgICAgICAgICAgICAgbWludXRlcyA8IDQ1ICYmIFsnbW0nLCBtaW51dGVzXSB8fFxyXG4gICAgICAgICAgICAgICAgaG91cnMgPT09IDEgJiYgWydoJ10gfHxcclxuICAgICAgICAgICAgICAgIGhvdXJzIDwgMjIgJiYgWydoaCcsIGhvdXJzXSB8fFxyXG4gICAgICAgICAgICAgICAgZGF5cyA9PT0gMSAmJiBbJ2QnXSB8fFxyXG4gICAgICAgICAgICAgICAgZGF5cyA8PSAyNSAmJiBbJ2RkJywgZGF5c10gfHxcclxuICAgICAgICAgICAgICAgIGRheXMgPD0gNDUgJiYgWydNJ10gfHxcclxuICAgICAgICAgICAgICAgIGRheXMgPCAzNDUgJiYgWydNTScsIHJvdW5kKGRheXMgLyAzMCldIHx8XHJcbiAgICAgICAgICAgICAgICB5ZWFycyA9PT0gMSAmJiBbJ3knXSB8fCBbJ3l5JywgeWVhcnNdO1xyXG4gICAgICAgIGFyZ3NbMl0gPSB3aXRob3V0U3VmZml4O1xyXG4gICAgICAgIGFyZ3NbM10gPSBtaWxsaXNlY29uZHMgPiAwO1xyXG4gICAgICAgIGFyZ3NbNF0gPSBsYW5nO1xyXG4gICAgICAgIHJldHVybiBzdWJzdGl0dXRlVGltZUFnby5hcHBseSh7fSwgYXJncyk7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBXZWVrIG9mIFllYXJcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgLy8gZmlyc3REYXlPZldlZWsgICAgICAgMCA9IHN1biwgNiA9IHNhdFxyXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICAgdGhlIGRheSBvZiB0aGUgd2VlayB0aGF0IHN0YXJ0cyB0aGUgd2Vla1xyXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICAgKHVzdWFsbHkgc3VuZGF5IG9yIG1vbmRheSlcclxuICAgIC8vIGZpcnN0RGF5T2ZXZWVrT2ZZZWFyIDAgPSBzdW4sIDYgPSBzYXRcclxuICAgIC8vICAgICAgICAgICAgICAgICAgICAgIHRoZSBmaXJzdCB3ZWVrIGlzIHRoZSB3ZWVrIHRoYXQgY29udGFpbnMgdGhlIGZpcnN0XHJcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGRheSBvZiB0aGUgd2Vla1xyXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICAgKGVnLiBJU08gd2Vla3MgdXNlIHRodXJzZGF5ICg0KSlcclxuICAgIGZ1bmN0aW9uIHdlZWtPZlllYXIobW9tLCBmaXJzdERheU9mV2VlaywgZmlyc3REYXlPZldlZWtPZlllYXIpIHtcclxuICAgICAgICB2YXIgZW5kID0gZmlyc3REYXlPZldlZWtPZlllYXIgLSBmaXJzdERheU9mV2VlayxcclxuICAgICAgICAgICAgZGF5c1RvRGF5T2ZXZWVrID0gZmlyc3REYXlPZldlZWtPZlllYXIgLSBtb20uZGF5KCksXHJcbiAgICAgICAgICAgIGFkanVzdGVkTW9tZW50O1xyXG5cclxuXHJcbiAgICAgICAgaWYgKGRheXNUb0RheU9mV2VlayA+IGVuZCkge1xyXG4gICAgICAgICAgICBkYXlzVG9EYXlPZldlZWsgLT0gNztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChkYXlzVG9EYXlPZldlZWsgPCBlbmQgLSA3KSB7XHJcbiAgICAgICAgICAgIGRheXNUb0RheU9mV2VlayArPSA3O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYWRqdXN0ZWRNb21lbnQgPSBtb21lbnQobW9tKS5hZGQoJ2QnLCBkYXlzVG9EYXlPZldlZWspO1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHdlZWs6IE1hdGguY2VpbChhZGp1c3RlZE1vbWVudC5kYXlPZlllYXIoKSAvIDcpLFxyXG4gICAgICAgICAgICB5ZWFyOiBhZGp1c3RlZE1vbWVudC55ZWFyKClcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8vaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JU09fd2Vla19kYXRlI0NhbGN1bGF0aW5nX2FfZGF0ZV9naXZlbl90aGVfeWVhci4yQ193ZWVrX251bWJlcl9hbmRfd2Vla2RheVxyXG4gICAgZnVuY3Rpb24gZGF5T2ZZZWFyRnJvbVdlZWtzKHllYXIsIHdlZWssIHdlZWtkYXksIGZpcnN0RGF5T2ZXZWVrT2ZZZWFyLCBmaXJzdERheU9mV2Vlaykge1xyXG4gICAgICAgIHZhciBkID0gbWFrZVVUQ0RhdGUoeWVhciwgMCwgMSkuZ2V0VVRDRGF5KCksIGRheXNUb0FkZCwgZGF5T2ZZZWFyO1xyXG5cclxuICAgICAgICB3ZWVrZGF5ID0gd2Vla2RheSAhPSBudWxsID8gd2Vla2RheSA6IGZpcnN0RGF5T2ZXZWVrO1xyXG4gICAgICAgIGRheXNUb0FkZCA9IGZpcnN0RGF5T2ZXZWVrIC0gZCArIChkID4gZmlyc3REYXlPZldlZWtPZlllYXIgPyA3IDogMCkgLSAoZCA8IGZpcnN0RGF5T2ZXZWVrID8gNyA6IDApO1xyXG4gICAgICAgIGRheU9mWWVhciA9IDcgKiAod2VlayAtIDEpICsgKHdlZWtkYXkgLSBmaXJzdERheU9mV2VlaykgKyBkYXlzVG9BZGQgKyAxO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICB5ZWFyOiBkYXlPZlllYXIgPiAwID8geWVhciA6IHllYXIgLSAxLFxyXG4gICAgICAgICAgICBkYXlPZlllYXI6IGRheU9mWWVhciA+IDAgPyAgZGF5T2ZZZWFyIDogZGF5c0luWWVhcih5ZWFyIC0gMSkgKyBkYXlPZlllYXJcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBUb3AgTGV2ZWwgRnVuY3Rpb25zXHJcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG4gICAgZnVuY3Rpb24gbWFrZU1vbWVudChjb25maWcpIHtcclxuICAgICAgICB2YXIgaW5wdXQgPSBjb25maWcuX2ksXHJcbiAgICAgICAgICAgIGZvcm1hdCA9IGNvbmZpZy5fZjtcclxuXHJcbiAgICAgICAgaWYgKGlucHV0ID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBtb21lbnQuaW52YWxpZCh7bnVsbElucHV0OiB0cnVlfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBjb25maWcuX2kgPSBpbnB1dCA9IGdldExhbmdEZWZpbml0aW9uKCkucHJlcGFyc2UoaW5wdXQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG1vbWVudC5pc01vbWVudChpbnB1dCkpIHtcclxuICAgICAgICAgICAgY29uZmlnID0gY2xvbmVNb21lbnQoaW5wdXQpO1xyXG5cclxuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoK2lucHV0Ll9kKTtcclxuICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdCkge1xyXG4gICAgICAgICAgICBpZiAoaXNBcnJheShmb3JtYXQpKSB7XHJcbiAgICAgICAgICAgICAgICBtYWtlRGF0ZUZyb21TdHJpbmdBbmRBcnJheShjb25maWcpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgbWFrZURhdGVGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBtYWtlRGF0ZUZyb21JbnB1dChjb25maWcpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQoY29uZmlnKTtcclxuICAgIH1cclxuXHJcbiAgICBtb21lbnQgPSBmdW5jdGlvbiAoaW5wdXQsIGZvcm1hdCwgbGFuZywgc3RyaWN0KSB7XHJcbiAgICAgICAgdmFyIGM7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YobGFuZykgPT09IFwiYm9vbGVhblwiKSB7XHJcbiAgICAgICAgICAgIHN0cmljdCA9IGxhbmc7XHJcbiAgICAgICAgICAgIGxhbmcgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIG9iamVjdCBjb25zdHJ1Y3Rpb24gbXVzdCBiZSBkb25lIHRoaXMgd2F5LlxyXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8xNDIzXHJcbiAgICAgICAgYyA9IHt9O1xyXG4gICAgICAgIGMuX2lzQU1vbWVudE9iamVjdCA9IHRydWU7XHJcbiAgICAgICAgYy5faSA9IGlucHV0O1xyXG4gICAgICAgIGMuX2YgPSBmb3JtYXQ7XHJcbiAgICAgICAgYy5fbCA9IGxhbmc7XHJcbiAgICAgICAgYy5fc3RyaWN0ID0gc3RyaWN0O1xyXG4gICAgICAgIGMuX2lzVVRDID0gZmFsc2U7XHJcbiAgICAgICAgYy5fcGYgPSBkZWZhdWx0UGFyc2luZ0ZsYWdzKCk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYWtlTW9tZW50KGMpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBjcmVhdGluZyB3aXRoIHV0Y1xyXG4gICAgbW9tZW50LnV0YyA9IGZ1bmN0aW9uIChpbnB1dCwgZm9ybWF0LCBsYW5nLCBzdHJpY3QpIHtcclxuICAgICAgICB2YXIgYztcclxuXHJcbiAgICAgICAgaWYgKHR5cGVvZihsYW5nKSA9PT0gXCJib29sZWFuXCIpIHtcclxuICAgICAgICAgICAgc3RyaWN0ID0gbGFuZztcclxuICAgICAgICAgICAgbGFuZyA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gb2JqZWN0IGNvbnN0cnVjdGlvbiBtdXN0IGJlIGRvbmUgdGhpcyB3YXkuXHJcbiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzE0MjNcclxuICAgICAgICBjID0ge307XHJcbiAgICAgICAgYy5faXNBTW9tZW50T2JqZWN0ID0gdHJ1ZTtcclxuICAgICAgICBjLl91c2VVVEMgPSB0cnVlO1xyXG4gICAgICAgIGMuX2lzVVRDID0gdHJ1ZTtcclxuICAgICAgICBjLl9sID0gbGFuZztcclxuICAgICAgICBjLl9pID0gaW5wdXQ7XHJcbiAgICAgICAgYy5fZiA9IGZvcm1hdDtcclxuICAgICAgICBjLl9zdHJpY3QgPSBzdHJpY3Q7XHJcbiAgICAgICAgYy5fcGYgPSBkZWZhdWx0UGFyc2luZ0ZsYWdzKCk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYWtlTW9tZW50KGMpLnV0YygpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBjcmVhdGluZyB3aXRoIHVuaXggdGltZXN0YW1wIChpbiBzZWNvbmRzKVxyXG4gICAgbW9tZW50LnVuaXggPSBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICByZXR1cm4gbW9tZW50KGlucHV0ICogMTAwMCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIGR1cmF0aW9uXHJcbiAgICBtb21lbnQuZHVyYXRpb24gPSBmdW5jdGlvbiAoaW5wdXQsIGtleSkge1xyXG4gICAgICAgIHZhciBkdXJhdGlvbiA9IGlucHV0LFxyXG4gICAgICAgICAgICAvLyBtYXRjaGluZyBhZ2FpbnN0IHJlZ2V4cCBpcyBleHBlbnNpdmUsIGRvIGl0IG9uIGRlbWFuZFxyXG4gICAgICAgICAgICBtYXRjaCA9IG51bGwsXHJcbiAgICAgICAgICAgIHNpZ24sXHJcbiAgICAgICAgICAgIHJldCxcclxuICAgICAgICAgICAgcGFyc2VJc287XHJcblxyXG4gICAgICAgIGlmIChtb21lbnQuaXNEdXJhdGlvbihpbnB1dCkpIHtcclxuICAgICAgICAgICAgZHVyYXRpb24gPSB7XHJcbiAgICAgICAgICAgICAgICBtczogaW5wdXQuX21pbGxpc2Vjb25kcyxcclxuICAgICAgICAgICAgICAgIGQ6IGlucHV0Ll9kYXlzLFxyXG4gICAgICAgICAgICAgICAgTTogaW5wdXQuX21vbnRoc1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xyXG4gICAgICAgICAgICBkdXJhdGlvbiA9IHt9O1xyXG4gICAgICAgICAgICBpZiAoa2V5KSB7XHJcbiAgICAgICAgICAgICAgICBkdXJhdGlvbltrZXldID0gaW5wdXQ7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBkdXJhdGlvbi5taWxsaXNlY29uZHMgPSBpbnB1dDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAoISEobWF0Y2ggPSBhc3BOZXRUaW1lU3Bhbkpzb25SZWdleC5leGVjKGlucHV0KSkpIHtcclxuICAgICAgICAgICAgc2lnbiA9IChtYXRjaFsxXSA9PT0gXCItXCIpID8gLTEgOiAxO1xyXG4gICAgICAgICAgICBkdXJhdGlvbiA9IHtcclxuICAgICAgICAgICAgICAgIHk6IDAsXHJcbiAgICAgICAgICAgICAgICBkOiB0b0ludChtYXRjaFtEQVRFXSkgKiBzaWduLFxyXG4gICAgICAgICAgICAgICAgaDogdG9JbnQobWF0Y2hbSE9VUl0pICogc2lnbixcclxuICAgICAgICAgICAgICAgIG06IHRvSW50KG1hdGNoW01JTlVURV0pICogc2lnbixcclxuICAgICAgICAgICAgICAgIHM6IHRvSW50KG1hdGNoW1NFQ09ORF0pICogc2lnbixcclxuICAgICAgICAgICAgICAgIG1zOiB0b0ludChtYXRjaFtNSUxMSVNFQ09ORF0pICogc2lnblxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0gZWxzZSBpZiAoISEobWF0Y2ggPSBpc29EdXJhdGlvblJlZ2V4LmV4ZWMoaW5wdXQpKSkge1xyXG4gICAgICAgICAgICBzaWduID0gKG1hdGNoWzFdID09PSBcIi1cIikgPyAtMSA6IDE7XHJcbiAgICAgICAgICAgIHBhcnNlSXNvID0gZnVuY3Rpb24gKGlucCkge1xyXG4gICAgICAgICAgICAgICAgLy8gV2UnZCBub3JtYWxseSB1c2Ugfn5pbnAgZm9yIHRoaXMsIGJ1dCB1bmZvcnR1bmF0ZWx5IGl0IGFsc29cclxuICAgICAgICAgICAgICAgIC8vIGNvbnZlcnRzIGZsb2F0cyB0byBpbnRzLlxyXG4gICAgICAgICAgICAgICAgLy8gaW5wIG1heSBiZSB1bmRlZmluZWQsIHNvIGNhcmVmdWwgY2FsbGluZyByZXBsYWNlIG9uIGl0LlxyXG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IGlucCAmJiBwYXJzZUZsb2F0KGlucC5yZXBsYWNlKCcsJywgJy4nKSk7XHJcbiAgICAgICAgICAgICAgICAvLyBhcHBseSBzaWduIHdoaWxlIHdlJ3JlIGF0IGl0XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKGlzTmFOKHJlcykgPyAwIDogcmVzKSAqIHNpZ247XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGR1cmF0aW9uID0ge1xyXG4gICAgICAgICAgICAgICAgeTogcGFyc2VJc28obWF0Y2hbMl0pLFxyXG4gICAgICAgICAgICAgICAgTTogcGFyc2VJc28obWF0Y2hbM10pLFxyXG4gICAgICAgICAgICAgICAgZDogcGFyc2VJc28obWF0Y2hbNF0pLFxyXG4gICAgICAgICAgICAgICAgaDogcGFyc2VJc28obWF0Y2hbNV0pLFxyXG4gICAgICAgICAgICAgICAgbTogcGFyc2VJc28obWF0Y2hbNl0pLFxyXG4gICAgICAgICAgICAgICAgczogcGFyc2VJc28obWF0Y2hbN10pLFxyXG4gICAgICAgICAgICAgICAgdzogcGFyc2VJc28obWF0Y2hbOF0pXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xyXG5cclxuICAgICAgICBpZiAobW9tZW50LmlzRHVyYXRpb24oaW5wdXQpICYmIGlucHV0Lmhhc093blByb3BlcnR5KCdfbGFuZycpKSB7XHJcbiAgICAgICAgICAgIHJldC5fbGFuZyA9IGlucHV0Ll9sYW5nO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJldDtcclxuICAgIH07XHJcblxyXG4gICAgLy8gdmVyc2lvbiBudW1iZXJcclxuICAgIG1vbWVudC52ZXJzaW9uID0gVkVSU0lPTjtcclxuXHJcbiAgICAvLyBkZWZhdWx0IGZvcm1hdFxyXG4gICAgbW9tZW50LmRlZmF1bHRGb3JtYXQgPSBpc29Gb3JtYXQ7XHJcblxyXG4gICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCB3aGVuZXZlciBhIG1vbWVudCBpcyBtdXRhdGVkLlxyXG4gICAgLy8gSXQgaXMgaW50ZW5kZWQgdG8ga2VlcCB0aGUgb2Zmc2V0IGluIHN5bmMgd2l0aCB0aGUgdGltZXpvbmUuXHJcbiAgICBtb21lbnQudXBkYXRlT2Zmc2V0ID0gZnVuY3Rpb24gKCkge307XHJcblxyXG4gICAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGxvYWQgbGFuZ3VhZ2VzIGFuZCB0aGVuIHNldCB0aGUgZ2xvYmFsIGxhbmd1YWdlLiAgSWZcclxuICAgIC8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXHJcbiAgICAvLyBsYW5ndWFnZSBrZXkuXHJcbiAgICBtb21lbnQubGFuZyA9IGZ1bmN0aW9uIChrZXksIHZhbHVlcykge1xyXG4gICAgICAgIHZhciByO1xyXG4gICAgICAgIGlmICgha2V5KSB7XHJcbiAgICAgICAgICAgIHJldHVybiBtb21lbnQuZm4uX2xhbmcuX2FiYnI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh2YWx1ZXMpIHtcclxuICAgICAgICAgICAgbG9hZExhbmcobm9ybWFsaXplTGFuZ3VhZ2Uoa2V5KSwgdmFsdWVzKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHZhbHVlcyA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICB1bmxvYWRMYW5nKGtleSk7XHJcbiAgICAgICAgICAgIGtleSA9ICdlbic7XHJcbiAgICAgICAgfSBlbHNlIGlmICghbGFuZ3VhZ2VzW2tleV0pIHtcclxuICAgICAgICAgICAgZ2V0TGFuZ0RlZmluaXRpb24oa2V5KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgciA9IG1vbWVudC5kdXJhdGlvbi5mbi5fbGFuZyA9IG1vbWVudC5mbi5fbGFuZyA9IGdldExhbmdEZWZpbml0aW9uKGtleSk7XHJcbiAgICAgICAgcmV0dXJuIHIuX2FiYnI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIHJldHVybnMgbGFuZ3VhZ2UgZGF0YVxyXG4gICAgbW9tZW50LmxhbmdEYXRhID0gZnVuY3Rpb24gKGtleSkge1xyXG4gICAgICAgIGlmIChrZXkgJiYga2V5Ll9sYW5nICYmIGtleS5fbGFuZy5fYWJicikge1xyXG4gICAgICAgICAgICBrZXkgPSBrZXkuX2xhbmcuX2FiYnI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBnZXRMYW5nRGVmaW5pdGlvbihrZXkpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBjb21wYXJlIG1vbWVudCBvYmplY3RcclxuICAgIG1vbWVudC5pc01vbWVudCA9IGZ1bmN0aW9uIChvYmopIHtcclxuICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8XHJcbiAgICAgICAgICAgIChvYmogIT0gbnVsbCAmJiAgb2JqLmhhc093blByb3BlcnR5KCdfaXNBTW9tZW50T2JqZWN0JykpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBmb3IgdHlwZWNoZWNraW5nIER1cmF0aW9uIG9iamVjdHNcclxuICAgIG1vbWVudC5pc0R1cmF0aW9uID0gZnVuY3Rpb24gKG9iaikge1xyXG4gICAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiBEdXJhdGlvbjtcclxuICAgIH07XHJcblxyXG4gICAgZm9yIChpID0gbGlzdHMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcclxuICAgICAgICBtYWtlTGlzdChsaXN0c1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgbW9tZW50Lm5vcm1hbGl6ZVVuaXRzID0gZnVuY3Rpb24gKHVuaXRzKSB7XHJcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcclxuICAgIH07XHJcblxyXG4gICAgbW9tZW50LmludmFsaWQgPSBmdW5jdGlvbiAoZmxhZ3MpIHtcclxuICAgICAgICB2YXIgbSA9IG1vbWVudC51dGMoTmFOKTtcclxuICAgICAgICBpZiAoZmxhZ3MgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBleHRlbmQobS5fcGYsIGZsYWdzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIG0uX3BmLnVzZXJJbnZhbGlkYXRlZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbTtcclxuICAgIH07XHJcblxyXG4gICAgbW9tZW50LnBhcnNlWm9uZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gbW9tZW50LmFwcGx5KG51bGwsIGFyZ3VtZW50cykucGFyc2Vab25lKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBNb21lbnQgUHJvdG90eXBlXHJcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXHJcblxyXG5cclxuICAgIGV4dGVuZChtb21lbnQuZm4gPSBNb21lbnQucHJvdG90eXBlLCB7XHJcblxyXG4gICAgICAgIGNsb25lIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbW9tZW50KHRoaXMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHZhbHVlT2YgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiArdGhpcy5fZCArICgodGhpcy5fb2Zmc2V0IHx8IDApICogNjAwMDApO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHVuaXggOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCt0aGlzIC8gMTAwMCk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgdG9TdHJpbmcgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNsb25lKCkubGFuZygnZW4nKS5mb3JtYXQoXCJkZGQgTU1NIEREIFlZWVkgSEg6bW06c3MgW0dNVF1aWlwiKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB0b0RhdGUgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vZmZzZXQgPyBuZXcgRGF0ZSgrdGhpcykgOiB0aGlzLl9kO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHRvSVNPU3RyaW5nIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgbSA9IG1vbWVudCh0aGlzKS51dGMoKTtcclxuICAgICAgICAgICAgaWYgKDAgPCBtLnllYXIoKSAmJiBtLnllYXIoKSA8PSA5OTk5KSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sICdZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTW1pdJyk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sICdZWVlZWVktTU0tRERbVF1ISDptbTpzcy5TU1NbWl0nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHRvQXJyYXkgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHZhciBtID0gdGhpcztcclxuICAgICAgICAgICAgcmV0dXJuIFtcclxuICAgICAgICAgICAgICAgIG0ueWVhcigpLFxyXG4gICAgICAgICAgICAgICAgbS5tb250aCgpLFxyXG4gICAgICAgICAgICAgICAgbS5kYXRlKCksXHJcbiAgICAgICAgICAgICAgICBtLmhvdXJzKCksXHJcbiAgICAgICAgICAgICAgICBtLm1pbnV0ZXMoKSxcclxuICAgICAgICAgICAgICAgIG0uc2Vjb25kcygpLFxyXG4gICAgICAgICAgICAgICAgbS5taWxsaXNlY29uZHMoKVxyXG4gICAgICAgICAgICBdO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGlzVmFsaWQgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkKHRoaXMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGlzRFNUU2hpZnRlZCA6IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9hKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgJiYgY29tcGFyZUFycmF5cyh0aGlzLl9hLCAodGhpcy5faXNVVEMgPyBtb21lbnQudXRjKHRoaXMuX2EpIDogbW9tZW50KHRoaXMuX2EpKS50b0FycmF5KCkpID4gMDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHBhcnNpbmdGbGFncyA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuZCh7fSwgdGhpcy5fcGYpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGludmFsaWRBdDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcGYub3ZlcmZsb3c7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgdXRjIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy56b25lKDApO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGxvY2FsIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB0aGlzLnpvbmUoMCk7XHJcbiAgICAgICAgICAgIHRoaXMuX2lzVVRDID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGZvcm1hdCA6IGZ1bmN0aW9uIChpbnB1dFN0cmluZykge1xyXG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gZm9ybWF0TW9tZW50KHRoaXMsIGlucHV0U3RyaW5nIHx8IG1vbWVudC5kZWZhdWx0Rm9ybWF0KTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLnBvc3Rmb3JtYXQob3V0cHV0KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBhZGQgOiBmdW5jdGlvbiAoaW5wdXQsIHZhbCkge1xyXG4gICAgICAgICAgICB2YXIgZHVyO1xyXG4gICAgICAgICAgICAvLyBzd2l0Y2ggYXJncyB0byBzdXBwb3J0IGFkZCgncycsIDEpIGFuZCBhZGQoMSwgJ3MnKVxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgZHVyID0gbW9tZW50LmR1cmF0aW9uKCt2YWwsIGlucHV0KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGR1ciA9IG1vbWVudC5kdXJhdGlvbihpbnB1dCwgdmFsKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBhZGRPclN1YnRyYWN0RHVyYXRpb25Gcm9tTW9tZW50KHRoaXMsIGR1ciwgMSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHN1YnRyYWN0IDogZnVuY3Rpb24gKGlucHV0LCB2YWwpIHtcclxuICAgICAgICAgICAgdmFyIGR1cjtcclxuICAgICAgICAgICAgLy8gc3dpdGNoIGFyZ3MgdG8gc3VwcG9ydCBzdWJ0cmFjdCgncycsIDEpIGFuZCBzdWJ0cmFjdCgxLCAncycpXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICBkdXIgPSBtb21lbnQuZHVyYXRpb24oK3ZhbCwgaW5wdXQpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZHVyID0gbW9tZW50LmR1cmF0aW9uKGlucHV0LCB2YWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGFkZE9yU3VidHJhY3REdXJhdGlvbkZyb21Nb21lbnQodGhpcywgZHVyLCAtMSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGRpZmYgOiBmdW5jdGlvbiAoaW5wdXQsIHVuaXRzLCBhc0Zsb2F0KSB7XHJcbiAgICAgICAgICAgIHZhciB0aGF0ID0gbWFrZUFzKGlucHV0LCB0aGlzKSxcclxuICAgICAgICAgICAgICAgIHpvbmVEaWZmID0gKHRoaXMuem9uZSgpIC0gdGhhdC56b25lKCkpICogNmU0LFxyXG4gICAgICAgICAgICAgICAgZGlmZiwgb3V0cHV0O1xyXG5cclxuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XHJcblxyXG4gICAgICAgICAgICBpZiAodW5pdHMgPT09ICd5ZWFyJyB8fCB1bml0cyA9PT0gJ21vbnRoJykge1xyXG4gICAgICAgICAgICAgICAgLy8gYXZlcmFnZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgbW9udGhzIGluIHRoZSBnaXZlbiBkYXRlc1xyXG4gICAgICAgICAgICAgICAgZGlmZiA9ICh0aGlzLmRheXNJbk1vbnRoKCkgKyB0aGF0LmRheXNJbk1vbnRoKCkpICogNDMyZTU7IC8vIDI0ICogNjAgKiA2MCAqIDEwMDAgLyAyXHJcbiAgICAgICAgICAgICAgICAvLyBkaWZmZXJlbmNlIGluIG1vbnRoc1xyXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKCh0aGlzLnllYXIoKSAtIHRoYXQueWVhcigpKSAqIDEyKSArICh0aGlzLm1vbnRoKCkgLSB0aGF0Lm1vbnRoKCkpO1xyXG4gICAgICAgICAgICAgICAgLy8gYWRqdXN0IGJ5IHRha2luZyBkaWZmZXJlbmNlIGluIGRheXMsIGF2ZXJhZ2UgbnVtYmVyIG9mIGRheXNcclxuICAgICAgICAgICAgICAgIC8vIGFuZCBkc3QgaW4gdGhlIGdpdmVuIG1vbnRocy5cclxuICAgICAgICAgICAgICAgIG91dHB1dCArPSAoKHRoaXMgLSBtb21lbnQodGhpcykuc3RhcnRPZignbW9udGgnKSkgLVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAodGhhdCAtIG1vbWVudCh0aGF0KS5zdGFydE9mKCdtb250aCcpKSkgLyBkaWZmO1xyXG4gICAgICAgICAgICAgICAgLy8gc2FtZSBhcyBhYm92ZSBidXQgd2l0aCB6b25lcywgdG8gbmVnYXRlIGFsbCBkc3RcclxuICAgICAgICAgICAgICAgIG91dHB1dCAtPSAoKHRoaXMuem9uZSgpIC0gbW9tZW50KHRoaXMpLnN0YXJ0T2YoJ21vbnRoJykuem9uZSgpKSAtXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGF0LnpvbmUoKSAtIG1vbWVudCh0aGF0KS5zdGFydE9mKCdtb250aCcpLnpvbmUoKSkpICogNmU0IC8gZGlmZjtcclxuICAgICAgICAgICAgICAgIGlmICh1bml0cyA9PT0gJ3llYXInKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gb3V0cHV0IC8gMTI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBkaWZmID0gKHRoaXMgLSB0aGF0KTtcclxuICAgICAgICAgICAgICAgIG91dHB1dCA9IHVuaXRzID09PSAnc2Vjb25kJyA/IGRpZmYgLyAxZTMgOiAvLyAxMDAwXHJcbiAgICAgICAgICAgICAgICAgICAgdW5pdHMgPT09ICdtaW51dGUnID8gZGlmZiAvIDZlNCA6IC8vIDEwMDAgKiA2MFxyXG4gICAgICAgICAgICAgICAgICAgIHVuaXRzID09PSAnaG91cicgPyBkaWZmIC8gMzZlNSA6IC8vIDEwMDAgKiA2MCAqIDYwXHJcbiAgICAgICAgICAgICAgICAgICAgdW5pdHMgPT09ICdkYXknID8gKGRpZmYgLSB6b25lRGlmZikgLyA4NjRlNSA6IC8vIDEwMDAgKiA2MCAqIDYwICogMjQsIG5lZ2F0ZSBkc3RcclxuICAgICAgICAgICAgICAgICAgICB1bml0cyA9PT0gJ3dlZWsnID8gKGRpZmYgLSB6b25lRGlmZikgLyA2MDQ4ZTUgOiAvLyAxMDAwICogNjAgKiA2MCAqIDI0ICogNywgbmVnYXRlIGRzdFxyXG4gICAgICAgICAgICAgICAgICAgIGRpZmY7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIGFzRmxvYXQgPyBvdXRwdXQgOiBhYnNSb3VuZChvdXRwdXQpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGZyb20gOiBmdW5jdGlvbiAodGltZSwgd2l0aG91dFN1ZmZpeCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LmR1cmF0aW9uKHRoaXMuZGlmZih0aW1lKSkubGFuZyh0aGlzLmxhbmcoKS5fYWJicikuaHVtYW5pemUoIXdpdGhvdXRTdWZmaXgpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGZyb21Ob3cgOiBmdW5jdGlvbiAod2l0aG91dFN1ZmZpeCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mcm9tKG1vbWVudCgpLCB3aXRob3V0U3VmZml4KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBjYWxlbmRhciA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgLy8gV2Ugd2FudCB0byBjb21wYXJlIHRoZSBzdGFydCBvZiB0b2RheSwgdnMgdGhpcy5cclxuICAgICAgICAgICAgLy8gR2V0dGluZyBzdGFydC1vZi10b2RheSBkZXBlbmRzIG9uIHdoZXRoZXIgd2UncmUgem9uZSdkIG9yIG5vdC5cclxuICAgICAgICAgICAgdmFyIHNvZCA9IG1ha2VBcyhtb21lbnQoKSwgdGhpcykuc3RhcnRPZignZGF5JyksXHJcbiAgICAgICAgICAgICAgICBkaWZmID0gdGhpcy5kaWZmKHNvZCwgJ2RheXMnLCB0cnVlKSxcclxuICAgICAgICAgICAgICAgIGZvcm1hdCA9IGRpZmYgPCAtNiA/ICdzYW1lRWxzZScgOlxyXG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPCAtMSA/ICdsYXN0V2VlaycgOlxyXG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPCAwID8gJ2xhc3REYXknIDpcclxuICAgICAgICAgICAgICAgICAgICBkaWZmIDwgMSA/ICdzYW1lRGF5JyA6XHJcbiAgICAgICAgICAgICAgICAgICAgZGlmZiA8IDIgPyAnbmV4dERheScgOlxyXG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPCA3ID8gJ25leHRXZWVrJyA6ICdzYW1lRWxzZSc7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZvcm1hdCh0aGlzLmxhbmcoKS5jYWxlbmRhcihmb3JtYXQsIHRoaXMpKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBpc0xlYXBZZWFyIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gaXNMZWFwWWVhcih0aGlzLnllYXIoKSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaXNEU1QgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAodGhpcy56b25lKCkgPCB0aGlzLmNsb25lKCkubW9udGgoMCkuem9uZSgpIHx8XHJcbiAgICAgICAgICAgICAgICB0aGlzLnpvbmUoKSA8IHRoaXMuY2xvbmUoKS5tb250aCg1KS56b25lKCkpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGRheSA6IGZ1bmN0aW9uIChpbnB1dCkge1xyXG4gICAgICAgICAgICB2YXIgZGF5ID0gdGhpcy5faXNVVEMgPyB0aGlzLl9kLmdldFVUQ0RheSgpIDogdGhpcy5fZC5nZXREYXkoKTtcclxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxhbmcoKSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoeyBkIDogaW5wdXQgLSBkYXkgfSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF5O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgbW9udGggOiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgdmFyIHV0YyA9IHRoaXMuX2lzVVRDID8gJ1VUQycgOiAnJyxcclxuICAgICAgICAgICAgICAgIGRheU9mTW9udGg7XHJcblxyXG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgICAgICBpbnB1dCA9IHRoaXMubGFuZygpLm1vbnRoc1BhcnNlKGlucHV0KTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnbnVtYmVyJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgZGF5T2ZNb250aCA9IE1hdGgubWluKHRoaXMuZGF0ZSgpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXlzSW5Nb250aCh0aGlzLnllYXIoKSwgaW5wdXQpKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2RbJ3NldCcgKyB1dGMgKyAnTW9udGgnXShpbnB1dCwgZGF5T2ZNb250aCk7XHJcbiAgICAgICAgICAgICAgICBtb21lbnQudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZFsnZ2V0JyArIHV0YyArICdNb250aCddKCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBzdGFydE9mOiBmdW5jdGlvbiAodW5pdHMpIHtcclxuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XHJcbiAgICAgICAgICAgIC8vIHRoZSBmb2xsb3dpbmcgc3dpdGNoIGludGVudGlvbmFsbHkgb21pdHMgYnJlYWsga2V5d29yZHNcclxuICAgICAgICAgICAgLy8gdG8gdXRpbGl6ZSBmYWxsaW5nIHRocm91Z2ggdGhlIGNhc2VzLlxyXG4gICAgICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XHJcbiAgICAgICAgICAgIGNhc2UgJ3llYXInOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5tb250aCgwKTtcclxuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cclxuICAgICAgICAgICAgY2FzZSAnbW9udGgnOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKDEpO1xyXG4gICAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xyXG4gICAgICAgICAgICBjYXNlICd3ZWVrJzpcclxuICAgICAgICAgICAgY2FzZSAnaXNvV2Vlayc6XHJcbiAgICAgICAgICAgIGNhc2UgJ2RheSc6XHJcbiAgICAgICAgICAgICAgICB0aGlzLmhvdXJzKDApO1xyXG4gICAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xyXG4gICAgICAgICAgICBjYXNlICdob3VyJzpcclxuICAgICAgICAgICAgICAgIHRoaXMubWludXRlcygwKTtcclxuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cclxuICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcclxuICAgICAgICAgICAgICAgIHRoaXMuc2Vjb25kcygwKTtcclxuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cclxuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzpcclxuICAgICAgICAgICAgICAgIHRoaXMubWlsbGlzZWNvbmRzKDApO1xyXG4gICAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyB3ZWVrcyBhcmUgYSBzcGVjaWFsIGNhc2VcclxuICAgICAgICAgICAgaWYgKHVuaXRzID09PSAnd2VlaycpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMud2Vla2RheSgwKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICh1bml0cyA9PT0gJ2lzb1dlZWsnKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmlzb1dlZWtkYXkoMSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGVuZE9mOiBmdW5jdGlvbiAodW5pdHMpIHtcclxuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YodW5pdHMpLmFkZCgodW5pdHMgPT09ICdpc29XZWVrJyA/ICd3ZWVrJyA6IHVuaXRzKSwgMSkuc3VidHJhY3QoJ21zJywgMSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaXNBZnRlcjogZnVuY3Rpb24gKGlucHV0LCB1bml0cykge1xyXG4gICAgICAgICAgICB1bml0cyA9IHR5cGVvZiB1bml0cyAhPT0gJ3VuZGVmaW5lZCcgPyB1bml0cyA6ICdtaWxsaXNlY29uZCc7XHJcbiAgICAgICAgICAgIHJldHVybiArdGhpcy5jbG9uZSgpLnN0YXJ0T2YodW5pdHMpID4gK21vbWVudChpbnB1dCkuc3RhcnRPZih1bml0cyk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaXNCZWZvcmU6IGZ1bmN0aW9uIChpbnB1dCwgdW5pdHMpIHtcclxuICAgICAgICAgICAgdW5pdHMgPSB0eXBlb2YgdW5pdHMgIT09ICd1bmRlZmluZWQnID8gdW5pdHMgOiAnbWlsbGlzZWNvbmQnO1xyXG4gICAgICAgICAgICByZXR1cm4gK3RoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKSA8ICttb21lbnQoaW5wdXQpLnN0YXJ0T2YodW5pdHMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGlzU2FtZTogZnVuY3Rpb24gKGlucHV0LCB1bml0cykge1xyXG4gICAgICAgICAgICB1bml0cyA9IHVuaXRzIHx8ICdtcyc7XHJcbiAgICAgICAgICAgIHJldHVybiArdGhpcy5jbG9uZSgpLnN0YXJ0T2YodW5pdHMpID09PSArbWFrZUFzKGlucHV0LCB0aGlzKS5zdGFydE9mKHVuaXRzKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBtaW46IGZ1bmN0aW9uIChvdGhlcikge1xyXG4gICAgICAgICAgICBvdGhlciA9IG1vbWVudC5hcHBseShudWxsLCBhcmd1bWVudHMpO1xyXG4gICAgICAgICAgICByZXR1cm4gb3RoZXIgPCB0aGlzID8gdGhpcyA6IG90aGVyO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIG1heDogZnVuY3Rpb24gKG90aGVyKSB7XHJcbiAgICAgICAgICAgIG90aGVyID0gbW9tZW50LmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgICAgIHJldHVybiBvdGhlciA+IHRoaXMgPyB0aGlzIDogb3RoZXI7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgem9uZSA6IGZ1bmN0aW9uIChpbnB1dCwgYWRqdXN0KSB7XHJcbiAgICAgICAgICAgIGFkanVzdCA9IChhZGp1c3QgPT0gbnVsbCA/IHRydWUgOiBmYWxzZSk7XHJcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLl9vZmZzZXQgfHwgMDtcclxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBpbnB1dCA9IHRpbWV6b25lTWludXRlc0Zyb21TdHJpbmcoaW5wdXQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKGlucHV0KSA8IDE2KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCAqIDYwO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fb2Zmc2V0ID0gaW5wdXQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9pc1VUQyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBpZiAob2Zmc2V0ICE9PSBpbnB1dCAmJiBhZGp1c3QpIHtcclxuICAgICAgICAgICAgICAgICAgICBhZGRPclN1YnRyYWN0RHVyYXRpb25Gcm9tTW9tZW50KHRoaXMsIG1vbWVudC5kdXJhdGlvbihvZmZzZXQgLSBpbnB1dCwgJ20nKSwgMSwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBvZmZzZXQgOiB0aGlzLl9kLmdldFRpbWV6b25lT2Zmc2V0KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgem9uZUFiYnIgOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/IFwiVVRDXCIgOiBcIlwiO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHpvbmVOYW1lIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBcIkNvb3JkaW5hdGVkIFVuaXZlcnNhbCBUaW1lXCIgOiBcIlwiO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHBhcnNlWm9uZSA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX3R6bSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy56b25lKHRoaXMuX3R6bSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMuX2kgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnpvbmUodGhpcy5faSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaGFzQWxpZ25lZEhvdXJPZmZzZXQgOiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgaWYgKCFpbnB1dCkge1xyXG4gICAgICAgICAgICAgICAgaW5wdXQgPSAwO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaW5wdXQgPSBtb21lbnQoaW5wdXQpLnpvbmUoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuICh0aGlzLnpvbmUoKSAtIGlucHV0KSAlIDYwID09PSAwO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGRheXNJbk1vbnRoIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZGF5c0luTW9udGgodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgZGF5T2ZZZWFyIDogZnVuY3Rpb24gKGlucHV0KSB7XHJcbiAgICAgICAgICAgIHZhciBkYXlPZlllYXIgPSByb3VuZCgobW9tZW50KHRoaXMpLnN0YXJ0T2YoJ2RheScpIC0gbW9tZW50KHRoaXMpLnN0YXJ0T2YoJ3llYXInKSkgLyA4NjRlNSkgKyAxO1xyXG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IGRheU9mWWVhciA6IHRoaXMuYWRkKFwiZFwiLCAoaW5wdXQgLSBkYXlPZlllYXIpKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBxdWFydGVyIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKCh0aGlzLm1vbnRoKCkgKyAxLjApIC8gMy4wKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB3ZWVrWWVhciA6IGZ1bmN0aW9uIChpbnB1dCkge1xyXG4gICAgICAgICAgICB2YXIgeWVhciA9IHdlZWtPZlllYXIodGhpcywgdGhpcy5sYW5nKCkuX3dlZWsuZG93LCB0aGlzLmxhbmcoKS5fd2Vlay5kb3kpLnllYXI7XHJcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8geWVhciA6IHRoaXMuYWRkKFwieVwiLCAoaW5wdXQgLSB5ZWFyKSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaXNvV2Vla1llYXIgOiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgdmFyIHllYXIgPSB3ZWVrT2ZZZWFyKHRoaXMsIDEsIDQpLnllYXI7XHJcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8geWVhciA6IHRoaXMuYWRkKFwieVwiLCAoaW5wdXQgLSB5ZWFyKSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgd2VlayA6IGZ1bmN0aW9uIChpbnB1dCkge1xyXG4gICAgICAgICAgICB2YXIgd2VlayA9IHRoaXMubGFuZygpLndlZWsodGhpcyk7XHJcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKFwiZFwiLCAoaW5wdXQgLSB3ZWVrKSAqIDcpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGlzb1dlZWsgOiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgdmFyIHdlZWsgPSB3ZWVrT2ZZZWFyKHRoaXMsIDEsIDQpLndlZWs7XHJcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKFwiZFwiLCAoaW5wdXQgLSB3ZWVrKSAqIDcpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHdlZWtkYXkgOiBmdW5jdGlvbiAoaW5wdXQpIHtcclxuICAgICAgICAgICAgdmFyIHdlZWtkYXkgPSAodGhpcy5kYXkoKSArIDcgLSB0aGlzLmxhbmcoKS5fd2Vlay5kb3cpICUgNztcclxuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrZGF5IDogdGhpcy5hZGQoXCJkXCIsIGlucHV0IC0gd2Vla2RheSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaXNvV2Vla2RheSA6IGZ1bmN0aW9uIChpbnB1dCkge1xyXG4gICAgICAgICAgICAvLyBiZWhhdmVzIHRoZSBzYW1lIGFzIG1vbWVudCNkYXkgZXhjZXB0XHJcbiAgICAgICAgICAgIC8vIGFzIGEgZ2V0dGVyLCByZXR1cm5zIDcgaW5zdGVhZCBvZiAwICgxLTcgcmFuZ2UgaW5zdGVhZCBvZiAwLTYpXHJcbiAgICAgICAgICAgIC8vIGFzIGEgc2V0dGVyLCBzdW5kYXkgc2hvdWxkIGJlbG9uZyB0byB0aGUgcHJldmlvdXMgd2Vlay5cclxuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB0aGlzLmRheSgpIHx8IDcgOiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IGlucHV0IDogaW5wdXQgLSA3KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBpc29XZWVrc0luWWVhciA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCAxLCA0KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB3ZWVrc0luWWVhciA6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgdmFyIHdlZWtJbmZvID0gdGhpcy5fbGFuZy5fd2VlaztcclxuICAgICAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCB3ZWVrSW5mby5kb3csIHdlZWtJbmZvLmRveSk7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgZ2V0IDogZnVuY3Rpb24gKHVuaXRzKSB7XHJcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpc1t1bml0c10oKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBzZXQgOiBmdW5jdGlvbiAodW5pdHMsIHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXNbdW5pdHNdID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzW3VuaXRzXSh2YWx1ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgLy8gSWYgcGFzc2VkIGEgbGFuZ3VhZ2Uga2V5LCBpdCB3aWxsIHNldCB0aGUgbGFuZ3VhZ2UgZm9yIHRoaXNcclxuICAgICAgICAvLyBpbnN0YW5jZS4gIE90aGVyd2lzZSwgaXQgd2lsbCByZXR1cm4gdGhlIGxhbmd1YWdlIGNvbmZpZ3VyYXRpb25cclxuICAgICAgICAvLyB2YXJpYWJsZXMgZm9yIHRoaXMgaW5zdGFuY2UuXHJcbiAgICAgICAgbGFuZyA6IGZ1bmN0aW9uIChrZXkpIHtcclxuICAgICAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbGFuZztcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xhbmcgPSBnZXRMYW5nRGVmaW5pdGlvbihrZXkpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBoZWxwZXIgZm9yIGFkZGluZyBzaG9ydGN1dHNcclxuICAgIGZ1bmN0aW9uIG1ha2VHZXR0ZXJBbmRTZXR0ZXIobmFtZSwga2V5KSB7XHJcbiAgICAgICAgLy8gaWdub3JlT2Zmc2V0VHJhbnNpdGlvbnMgcHJvdmlkZXMgYSBoaW50IHRvIHVwZGF0ZU9mZnNldCB0byBub3RcclxuICAgICAgICAvLyBjaGFuZ2UgaG91cnMvbWludXRlcyB3aGVuIGNyb3NzaW5nIGEgdHogYm91bmRhcnkuICBUaGlzIGlzIGZyZXF1ZW50bHlcclxuICAgICAgICAvLyBkZXNpcmFibGUgd2hlbiBtb2RpZnlpbmcgcGFydCBvZiBhbiBleGlzdGluZyBtb21lbnQgb2JqZWN0IGRpcmVjdGx5LlxyXG4gICAgICAgIHZhciBkZWZhdWx0SWdub3JlT2Zmc2V0VHJhbnNpdGlvbnMgPSBrZXkgPT09ICdkYXRlJyB8fCBrZXkgPT09ICdtb250aCcgfHwga2V5ID09PSAneWVhcic7XHJcbiAgICAgICAgbW9tZW50LmZuW25hbWVdID0gbW9tZW50LmZuW25hbWUgKyAncyddID0gZnVuY3Rpb24gKGlucHV0LCBpZ25vcmVPZmZzZXRUcmFuc2l0aW9ucykge1xyXG4gICAgICAgICAgICB2YXIgdXRjID0gdGhpcy5faXNVVEMgPyAnVVRDJyA6ICcnO1xyXG4gICAgICAgICAgICBpZiAoaWdub3JlT2Zmc2V0VHJhbnNpdGlvbnMgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgaWdub3JlT2Zmc2V0VHJhbnNpdGlvbnMgPSBkZWZhdWx0SWdub3JlT2Zmc2V0VHJhbnNpdGlvbnM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2RbJ3NldCcgKyB1dGMgKyBrZXldKGlucHV0KTtcclxuICAgICAgICAgICAgICAgIG1vbWVudC51cGRhdGVPZmZzZXQodGhpcywgaWdub3JlT2Zmc2V0VHJhbnNpdGlvbnMpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZFsnZ2V0JyArIHV0YyArIGtleV0oKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLy8gbG9vcCB0aHJvdWdoIGFuZCBhZGQgc2hvcnRjdXRzIChEYXRlLCBIb3VycywgTWludXRlcywgU2Vjb25kcywgTWlsbGlzZWNvbmRzKVxyXG4gICAgLy8gTW9udGggaGFzIGEgY3VzdG9tIGdldHRlci9zZXR0ZXIuXHJcbiAgICBmb3IgKGkgPSAwOyBpIDwgcHJveHlHZXR0ZXJzQW5kU2V0dGVycy5sZW5ndGg7IGkgKyspIHtcclxuICAgICAgICBtYWtlR2V0dGVyQW5kU2V0dGVyKHByb3h5R2V0dGVyc0FuZFNldHRlcnNbaV0udG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9zJC8sICcnKSwgcHJveHlHZXR0ZXJzQW5kU2V0dGVyc1tpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gYWRkIHNob3J0Y3V0IGZvciB5ZWFyICh1c2VzIGRpZmZlcmVudCBzeW50YXggdGhhbiB0aGUgZ2V0dGVyL3NldHRlciAneWVhcicgPT0gJ0Z1bGxZZWFyJylcclxuICAgIG1ha2VHZXR0ZXJBbmRTZXR0ZXIoJ3llYXInLCAnRnVsbFllYXInKTtcclxuXHJcbiAgICAvLyBhZGQgcGx1cmFsIG1ldGhvZHNcclxuICAgIG1vbWVudC5mbi5kYXlzID0gbW9tZW50LmZuLmRheTtcclxuICAgIG1vbWVudC5mbi5tb250aHMgPSBtb21lbnQuZm4ubW9udGg7XHJcbiAgICBtb21lbnQuZm4ud2Vla3MgPSBtb21lbnQuZm4ud2VlaztcclxuICAgIG1vbWVudC5mbi5pc29XZWVrcyA9IG1vbWVudC5mbi5pc29XZWVrO1xyXG5cclxuICAgIC8vIGFkZCBhbGlhc2VkIGZvcm1hdCBtZXRob2RzXHJcbiAgICBtb21lbnQuZm4udG9KU09OID0gbW9tZW50LmZuLnRvSVNPU3RyaW5nO1xyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBEdXJhdGlvbiBQcm90b3R5cGVcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgZXh0ZW5kKG1vbWVudC5kdXJhdGlvbi5mbiA9IER1cmF0aW9uLnByb3RvdHlwZSwge1xyXG5cclxuICAgICAgICBfYnViYmxlIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICB2YXIgbWlsbGlzZWNvbmRzID0gdGhpcy5fbWlsbGlzZWNvbmRzLFxyXG4gICAgICAgICAgICAgICAgZGF5cyA9IHRoaXMuX2RheXMsXHJcbiAgICAgICAgICAgICAgICBtb250aHMgPSB0aGlzLl9tb250aHMsXHJcbiAgICAgICAgICAgICAgICBkYXRhID0gdGhpcy5fZGF0YSxcclxuICAgICAgICAgICAgICAgIHNlY29uZHMsIG1pbnV0ZXMsIGhvdXJzLCB5ZWFycztcclxuXHJcbiAgICAgICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgY29kZSBidWJibGVzIHVwIHZhbHVlcywgc2VlIHRoZSB0ZXN0cyBmb3JcclxuICAgICAgICAgICAgLy8gZXhhbXBsZXMgb2Ygd2hhdCB0aGF0IG1lYW5zLlxyXG4gICAgICAgICAgICBkYXRhLm1pbGxpc2Vjb25kcyA9IG1pbGxpc2Vjb25kcyAlIDEwMDA7XHJcblxyXG4gICAgICAgICAgICBzZWNvbmRzID0gYWJzUm91bmQobWlsbGlzZWNvbmRzIC8gMTAwMCk7XHJcbiAgICAgICAgICAgIGRhdGEuc2Vjb25kcyA9IHNlY29uZHMgJSA2MDtcclxuXHJcbiAgICAgICAgICAgIG1pbnV0ZXMgPSBhYnNSb3VuZChzZWNvbmRzIC8gNjApO1xyXG4gICAgICAgICAgICBkYXRhLm1pbnV0ZXMgPSBtaW51dGVzICUgNjA7XHJcblxyXG4gICAgICAgICAgICBob3VycyA9IGFic1JvdW5kKG1pbnV0ZXMgLyA2MCk7XHJcbiAgICAgICAgICAgIGRhdGEuaG91cnMgPSBob3VycyAlIDI0O1xyXG5cclxuICAgICAgICAgICAgZGF5cyArPSBhYnNSb3VuZChob3VycyAvIDI0KTtcclxuICAgICAgICAgICAgZGF0YS5kYXlzID0gZGF5cyAlIDMwO1xyXG5cclxuICAgICAgICAgICAgbW9udGhzICs9IGFic1JvdW5kKGRheXMgLyAzMCk7XHJcbiAgICAgICAgICAgIGRhdGEubW9udGhzID0gbW9udGhzICUgMTI7XHJcblxyXG4gICAgICAgICAgICB5ZWFycyA9IGFic1JvdW5kKG1vbnRocyAvIDEyKTtcclxuICAgICAgICAgICAgZGF0YS55ZWFycyA9IHllYXJzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHdlZWtzIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gYWJzUm91bmQodGhpcy5kYXlzKCkgLyA3KTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICB2YWx1ZU9mIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbWlsbGlzZWNvbmRzICtcclxuICAgICAgICAgICAgICB0aGlzLl9kYXlzICogODY0ZTUgK1xyXG4gICAgICAgICAgICAgICh0aGlzLl9tb250aHMgJSAxMikgKiAyNTkyZTYgK1xyXG4gICAgICAgICAgICAgIHRvSW50KHRoaXMuX21vbnRocyAvIDEyKSAqIDMxNTM2ZTY7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgaHVtYW5pemUgOiBmdW5jdGlvbiAod2l0aFN1ZmZpeCkge1xyXG4gICAgICAgICAgICB2YXIgZGlmZmVyZW5jZSA9ICt0aGlzLFxyXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gcmVsYXRpdmVUaW1lKGRpZmZlcmVuY2UsICF3aXRoU3VmZml4LCB0aGlzLmxhbmcoKSk7XHJcblxyXG4gICAgICAgICAgICBpZiAod2l0aFN1ZmZpeCkge1xyXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gdGhpcy5sYW5nKCkucGFzdEZ1dHVyZShkaWZmZXJlbmNlLCBvdXRwdXQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sYW5nKCkucG9zdGZvcm1hdChvdXRwdXQpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGFkZCA6IGZ1bmN0aW9uIChpbnB1dCwgdmFsKSB7XHJcbiAgICAgICAgICAgIC8vIHN1cHBvcnRzIG9ubHkgMi4wLXN0eWxlIGFkZCgxLCAncycpIG9yIGFkZChtb21lbnQpXHJcbiAgICAgICAgICAgIHZhciBkdXIgPSBtb21lbnQuZHVyYXRpb24oaW5wdXQsIHZhbCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgKz0gZHVyLl9taWxsaXNlY29uZHM7XHJcbiAgICAgICAgICAgIHRoaXMuX2RheXMgKz0gZHVyLl9kYXlzO1xyXG4gICAgICAgICAgICB0aGlzLl9tb250aHMgKz0gZHVyLl9tb250aHM7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9idWJibGUoKTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHN1YnRyYWN0IDogZnVuY3Rpb24gKGlucHV0LCB2YWwpIHtcclxuICAgICAgICAgICAgdmFyIGR1ciA9IG1vbWVudC5kdXJhdGlvbihpbnB1dCwgdmFsKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyAtPSBkdXIuX21pbGxpc2Vjb25kcztcclxuICAgICAgICAgICAgdGhpcy5fZGF5cyAtPSBkdXIuX2RheXM7XHJcbiAgICAgICAgICAgIHRoaXMuX21vbnRocyAtPSBkdXIuX21vbnRocztcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX2J1YmJsZSgpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfSxcclxuXHJcbiAgICAgICAgZ2V0IDogZnVuY3Rpb24gKHVuaXRzKSB7XHJcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpc1t1bml0cy50b0xvd2VyQ2FzZSgpICsgJ3MnXSgpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIGFzIDogZnVuY3Rpb24gKHVuaXRzKSB7XHJcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpc1snYXMnICsgdW5pdHMuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyB1bml0cy5zbGljZSgxKSArICdzJ10oKTtcclxuICAgICAgICB9LFxyXG5cclxuICAgICAgICBsYW5nIDogbW9tZW50LmZuLmxhbmcsXHJcblxyXG4gICAgICAgIHRvSXNvU3RyaW5nIDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAvLyBpbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vZG9yZGlsbGUvbW9tZW50LWlzb2R1cmF0aW9uL2Jsb2IvbWFzdGVyL21vbWVudC5pc29kdXJhdGlvbi5qc1xyXG4gICAgICAgICAgICB2YXIgeWVhcnMgPSBNYXRoLmFicyh0aGlzLnllYXJzKCkpLFxyXG4gICAgICAgICAgICAgICAgbW9udGhzID0gTWF0aC5hYnModGhpcy5tb250aHMoKSksXHJcbiAgICAgICAgICAgICAgICBkYXlzID0gTWF0aC5hYnModGhpcy5kYXlzKCkpLFxyXG4gICAgICAgICAgICAgICAgaG91cnMgPSBNYXRoLmFicyh0aGlzLmhvdXJzKCkpLFxyXG4gICAgICAgICAgICAgICAgbWludXRlcyA9IE1hdGguYWJzKHRoaXMubWludXRlcygpKSxcclxuICAgICAgICAgICAgICAgIHNlY29uZHMgPSBNYXRoLmFicyh0aGlzLnNlY29uZHMoKSArIHRoaXMubWlsbGlzZWNvbmRzKCkgLyAxMDAwKTtcclxuXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5hc1NlY29uZHMoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgc2FtZSBhcyBDIydzIChOb2RhKSBhbmQgcHl0aG9uIChpc29kYXRlKS4uLlxyXG4gICAgICAgICAgICAgICAgLy8gYnV0IG5vdCBvdGhlciBKUyAoZ29vZy5kYXRlKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdQMEQnO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuYXNTZWNvbmRzKCkgPCAwID8gJy0nIDogJycpICtcclxuICAgICAgICAgICAgICAgICdQJyArXHJcbiAgICAgICAgICAgICAgICAoeWVhcnMgPyB5ZWFycyArICdZJyA6ICcnKSArXHJcbiAgICAgICAgICAgICAgICAobW9udGhzID8gbW9udGhzICsgJ00nIDogJycpICtcclxuICAgICAgICAgICAgICAgIChkYXlzID8gZGF5cyArICdEJyA6ICcnKSArXHJcbiAgICAgICAgICAgICAgICAoKGhvdXJzIHx8IG1pbnV0ZXMgfHwgc2Vjb25kcykgPyAnVCcgOiAnJykgK1xyXG4gICAgICAgICAgICAgICAgKGhvdXJzID8gaG91cnMgKyAnSCcgOiAnJykgK1xyXG4gICAgICAgICAgICAgICAgKG1pbnV0ZXMgPyBtaW51dGVzICsgJ00nIDogJycpICtcclxuICAgICAgICAgICAgICAgIChzZWNvbmRzID8gc2Vjb25kcyArICdTJyA6ICcnKTtcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBmdW5jdGlvbiBtYWtlRHVyYXRpb25HZXR0ZXIobmFtZSkge1xyXG4gICAgICAgIG1vbWVudC5kdXJhdGlvbi5mbltuYW1lXSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGFbbmFtZV07XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBtYWtlRHVyYXRpb25Bc0dldHRlcihuYW1lLCBmYWN0b3IpIHtcclxuICAgICAgICBtb21lbnQuZHVyYXRpb24uZm5bJ2FzJyArIG5hbWVdID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gK3RoaXMgLyBmYWN0b3I7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGkgaW4gdW5pdE1pbGxpc2Vjb25kRmFjdG9ycykge1xyXG4gICAgICAgIGlmICh1bml0TWlsbGlzZWNvbmRGYWN0b3JzLmhhc093blByb3BlcnR5KGkpKSB7XHJcbiAgICAgICAgICAgIG1ha2VEdXJhdGlvbkFzR2V0dGVyKGksIHVuaXRNaWxsaXNlY29uZEZhY3RvcnNbaV0pO1xyXG4gICAgICAgICAgICBtYWtlRHVyYXRpb25HZXR0ZXIoaS50b0xvd2VyQ2FzZSgpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbWFrZUR1cmF0aW9uQXNHZXR0ZXIoJ1dlZWtzJywgNjA0OGU1KTtcclxuICAgIG1vbWVudC5kdXJhdGlvbi5mbi5hc01vbnRocyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gKCt0aGlzIC0gdGhpcy55ZWFycygpICogMzE1MzZlNikgLyAyNTkyZTYgKyB0aGlzLnllYXJzKCkgKiAxMjtcclxuICAgIH07XHJcblxyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBEZWZhdWx0IExhbmdcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcblxyXG4gICAgLy8gU2V0IGRlZmF1bHQgbGFuZ3VhZ2UsIG90aGVyIGxhbmd1YWdlcyB3aWxsIGluaGVyaXQgZnJvbSBFbmdsaXNoLlxyXG4gICAgbW9tZW50LmxhbmcoJ2VuJywge1xyXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XHJcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXHJcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodG9JbnQobnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxyXG4gICAgICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XHJcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcclxuICAgICAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xyXG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8qIEVNQkVEX0xBTkdVQUdFUyAqL1xyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICBFeHBvc2luZyBNb21lbnRcclxuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcbiAgICBmdW5jdGlvbiBtYWtlR2xvYmFsKGRlcHJlY2F0ZSkge1xyXG4gICAgICAgIHZhciB3YXJuZWQgPSBmYWxzZSwgbG9jYWxfbW9tZW50ID0gbW9tZW50O1xyXG4gICAgICAgIC8qZ2xvYmFsIGVuZGVyOmZhbHNlICovXHJcbiAgICAgICAgaWYgKHR5cGVvZiBlbmRlciAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBoZXJlLCBgdGhpc2AgbWVhbnMgYHdpbmRvd2AgaW4gdGhlIGJyb3dzZXIsIG9yIGBnbG9iYWxgIG9uIHRoZSBzZXJ2ZXJcclxuICAgICAgICAvLyBhZGQgYG1vbWVudGAgYXMgYSBnbG9iYWwgb2JqZWN0IHZpYSBhIHN0cmluZyBpZGVudGlmaWVyLFxyXG4gICAgICAgIC8vIGZvciBDbG9zdXJlIENvbXBpbGVyIFwiYWR2YW5jZWRcIiBtb2RlXHJcbiAgICAgICAgaWYgKGRlcHJlY2F0ZSkge1xyXG4gICAgICAgICAgICBnbG9iYWwubW9tZW50ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3YXJuZWQgJiYgY29uc29sZSAmJiBjb25zb2xlLndhcm4pIHtcclxuICAgICAgICAgICAgICAgICAgICB3YXJuZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQWNjZXNzaW5nIE1vbWVudCB0aHJvdWdoIHRoZSBnbG9iYWwgc2NvcGUgaXMgXCIgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJkZXByZWNhdGVkLCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGFuIHVwY29taW5nIFwiICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwicmVsZWFzZS5cIik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxfbW9tZW50LmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGV4dGVuZChnbG9iYWwubW9tZW50LCBsb2NhbF9tb21lbnQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGdsb2JhbFsnbW9tZW50J10gPSBtb21lbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIENvbW1vbkpTIG1vZHVsZSBpcyBkZWZpbmVkXHJcbiAgICBpZiAoaGFzTW9kdWxlKSB7XHJcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtb21lbnQ7XHJcbiAgICAgICAgbWFrZUdsb2JhbCh0cnVlKTtcclxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcclxuICAgICAgICBkZWZpbmUoXCJtb21lbnRcIiwgZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xyXG4gICAgICAgICAgICBpZiAobW9kdWxlLmNvbmZpZyAmJiBtb2R1bGUuY29uZmlnKCkgJiYgbW9kdWxlLmNvbmZpZygpLm5vR2xvYmFsICE9PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBJZiB1c2VyIHByb3ZpZGVkIG5vR2xvYmFsLCBoZSBpcyBhd2FyZSBvZiBnbG9iYWxcclxuICAgICAgICAgICAgICAgIG1ha2VHbG9iYWwobW9kdWxlLmNvbmZpZygpLm5vR2xvYmFsID09PSB1bmRlZmluZWQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gbW9tZW50O1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBtYWtlR2xvYmFsKCk7XHJcbiAgICB9XHJcbn0pLmNhbGwodGhpcyk7XHJcbiJdLCJmaWxlIjoibW9tZW50LmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.min.js new file mode 100644 index 000000000..79b6ccd4e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/moment.min.js @@ -0,0 +1 @@ +(function(t){function e(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function n(t,e){return function(n){return h(t.call(this,n),e)}}function r(t,e){return function(n){return this.lang().ordinal(t.call(this,n),e)}}function s(){}function a(t){v(t),o(this,t)}function i(t){var e=y(t),n=e.year||0,r=e.month||0,s=e.week||0,a=e.day||0,i=e.hour||0,o=e.minute||0,u=e.second||0,d=e.millisecond||0;this._milliseconds=+d+1e3*u+6e4*o+36e5*i,this._days=+a+7*s,this._months=+r+12*n,this._data={},this._bubble()}function o(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return e.hasOwnProperty("toString")&&(t.toString=e.toString),e.hasOwnProperty("valueOf")&&(t.valueOf=e.valueOf),t}function u(t){var e,n={};for(e in t)t.hasOwnProperty(e)&&pt.hasOwnProperty(e)&&(n[e]=t[e]);return n}function d(t){return 0>t?Math.ceil(t):Math.floor(t)}function h(t,e,n){for(var r=""+Math.abs(t),s=t>=0;r.lengthr;r++)(n&&t[r]!==e[r]||!n&&g(t[r])!==g(e[r]))&&i++;return i+a}function m(t){if(t){var e=t.toLowerCase().replace(/(.)s$/,"$1");t=Jt[t]||qt[e]||e}return t}function y(t){var e,n,r={};for(n in t)t.hasOwnProperty(n)&&(e=m(n),e&&(r[e]=t[n]));return r}function p(e){var n,r;if(0===e.indexOf("week"))n=7,r="day";else{if(0!==e.indexOf("month"))return;n=12,r="month"}st[e]=function(s,a){var i,o,u=st.fn._lang[e],d=[];if("number"==typeof s&&(a=s,s=t),o=function(t){var e=st().utc().set(r,t);return u.call(st.fn._lang,e,s||"")},null!=a)return o(a);for(i=0;n>i;i++)d.push(o(i));return d}}function g(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=e>=0?Math.floor(e):Math.ceil(e)),n}function Y(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function w(t,e,n){return B(st([t,11,31+e-n]),e,n).week}function M(t){return D(t)?366:365}function D(t){return t%4===0&&t%100!==0||t%400===0}function v(t){var e;t._a&&-2===t._pf.overflow&&(e=t._a[ht]<0||t._a[ht]>11?ht:t._a[ct]<1||t._a[ct]>Y(t._a[dt],t._a[ht])?ct:t._a[ft]<0||t._a[ft]>23?ft:t._a[lt]<0||t._a[lt]>59?lt:t._a[_t]<0||t._a[_t]>59?_t:t._a[mt]<0||t._a[mt]>999?mt:-1,t._pf._overflowDayOfYear&&(dt>e||e>ct)&&(e=ct),t._pf.overflow=e)}function k(t){return null==t._isValid&&(t._isValid=!isNaN(t._d.getTime())&&t._pf.overflow<0&&!t._pf.empty&&!t._pf.invalidMonth&&!t._pf.nullInput&&!t._pf.invalidFormat&&!t._pf.userInvalidated,t._strict&&(t._isValid=t._isValid&&0===t._pf.charsLeftOver&&0===t._pf.unusedTokens.length)),t._isValid}function b(t){return t?t.toLowerCase().replace("_","-"):t}function S(t,e){return e._isUTC?st(t).zone(e._offset||0):st(t).local()}function T(t,e){return e.abbr=t,yt[t]||(yt[t]=new s),yt[t].set(e),yt[t]}function O(t){delete yt[t]}function G(t){var e,n,r,s,a=0,i=function(t){if(!yt[t]&>)try{require("./lang/"+t)}catch(e){}return yt[t]};if(!t)return st.fn._lang;if(!f(t)){if(n=i(t))return n;t=[t]}for(;a0;){if(n=i(s.slice(0,e).join("-")))return n;if(r&&r.length>=e&&_(s,r,!0)>=e-1)break;e--}a++}return st.fn._lang}function W(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function F(t){var e,n,r=t.match(Dt);for(e=0,n=r.length;n>e;e++)r[e]=Qt[r[e]]?Qt[r[e]]:W(r[e]);return function(s){var a="";for(e=0;n>e;e++)a+=r[e]instanceof Function?r[e].call(s,t):r[e];return a}}function C(t,e){return t.isValid()?(e=z(e,t.lang()),Xt[e]||(Xt[e]=F(e)),Xt[e](t)):t.lang().invalidDate()}function z(t,e){function n(t){return e.longDateFormat(t)||t}var r=5;for(vt.lastIndex=0;r>=0&&vt.test(t);)t=t.replace(vt,n),vt.lastIndex=0,r-=1;return t}function L(t,e){var n,r=e._strict;switch(t){case"DDDD":return Pt;case"YYYY":case"GGGG":case"gggg":return r?Ht:St;case"Y":case"G":case"g":return xt;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return r?At:Tt;case"S":if(r)return Lt;case"SS":if(r)return Ut;case"SSS":if(r)return Pt;case"DDD":return bt;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Gt;case"a":case"A":return G(e._l)._meridiemParse;case"X":return Ct;case"Z":case"ZZ":return Wt;case"T":return Ft;case"SSSS":return Ot;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return r?Ut:kt;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return kt;case"Do":return zt;default:return n=new RegExp(E(Z(t.replace("\\","")),"i"))}}function U(t){t=t||"";var e=t.match(Wt)||[],n=e[e.length-1]||[],r=(n+"").match(jt)||["-",0,0],s=+(60*r[1])+g(r[2]);return"+"===r[0]?-s:s}function P(t,e,n){var r,s=n._a;switch(t){case"M":case"MM":null!=e&&(s[ht]=g(e)-1);break;case"MMM":case"MMMM":r=G(n._l).monthsParse(e),null!=r?s[ht]=r:n._pf.invalidMonth=e;break;case"D":case"DD":null!=e&&(s[ct]=g(e));break;case"Do":null!=e&&(s[ct]=g(parseInt(e,10)));break;case"DDD":case"DDDD":null!=e&&(n._dayOfYear=g(e));break;case"YY":s[dt]=g(e)+(g(e)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":s[dt]=g(e);break;case"a":case"A":n._isPm=G(n._l).isPM(e);break;case"H":case"HH":case"h":case"hh":s[ft]=g(e);break;case"m":case"mm":s[lt]=g(e);break;case"s":case"ss":s[_t]=g(e);break;case"S":case"SS":case"SSS":case"SSSS":s[mt]=g(1e3*("0."+e));break;case"X":n._d=new Date(1e3*parseFloat(e));break;case"Z":case"ZZ":n._useUTC=!0,n._tzm=U(e);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":t=t.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":t=t.substr(0,2),e&&(n._w=n._w||{},n._w[t]=e)}}function H(t){var e,n,r,s,a,i,o,u,d,h,c=[];if(!t._d){for(r=x(t),t._w&&null==t._a[ct]&&null==t._a[ht]&&(a=function(e){var n=parseInt(e,10);return e?e.length<3?n>68?1900+n:2e3+n:n:null==t._a[dt]?st().weekYear():t._a[dt]},i=t._w,null!=i.GG||null!=i.W||null!=i.E?o=Q(a(i.GG),i.W||1,i.E,4,1):(u=G(t._l),d=null!=i.d?q(i.d,u):null!=i.e?parseInt(i.e,10)+u._week.dow:0,h=parseInt(i.w,10)||1,null!=i.d&&dM(s)&&(t._pf._overflowDayOfYear=!0),n=J(s,0,t._dayOfYear),t._a[ht]=n.getUTCMonth(),t._a[ct]=n.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=c[e]=r[e];for(;7>e;e++)t._a[e]=c[e]=null==t._a[e]?2===e?1:0:t._a[e];c[ft]+=g((t._tzm||0)/60),c[lt]+=g((t._tzm||0)%60),t._d=(t._useUTC?J:V).apply(null,c)}}function A(t){var e;t._d||(e=y(t._i),t._a=[e.year,e.month,e.day,e.hour,e.minute,e.second,e.millisecond],H(t))}function x(t){var e=new Date;return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function I(t){t._a=[],t._pf.empty=!0;var e,n,r,s,a,i=G(t._l),o=""+t._i,u=o.length,d=0;for(r=z(t._f,i).match(Dt)||[],e=0;e0&&t._pf.unusedInput.push(a),o=o.slice(o.indexOf(n)+n.length),d+=n.length),Qt[s]?(n?t._pf.empty=!1:t._pf.unusedTokens.push(s),P(s,n,t)):t._strict&&!n&&t._pf.unusedTokens.push(s);t._pf.charsLeftOver=u-d,o.length>0&&t._pf.unusedInput.push(o),t._isPm&&t._a[ft]<12&&(t._a[ft]+=12),t._isPm===!1&&12===t._a[ft]&&(t._a[ft]=0),H(t),v(t)}function Z(t){return t.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,r,s){return e||n||r||s})}function E(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function N(t){var n,r,s,a,i;if(0===t._f.length)return t._pf.invalidFormat=!0,void(t._d=new Date(0/0));for(a=0;ai)&&(s=i,r=n));o(t,r||n)}function j(t){var e,n,r=t._i,s=It.exec(r);if(s){for(t._pf.iso=!0,e=0,n=Et.length;n>e;e++)if(Et[e][1].exec(r)){t._f=Et[e][0]+(s[6]||" ");break}for(e=0,n=Nt.length;n>e;e++)if(Nt[e][1].exec(r)){t._f+=Nt[e][0];break}r.match(Wt)&&(t._f+="Z"),I(t)}else t._d=new Date(r)}function $(e){var n=e._i,r=Yt.exec(n);n===t?e._d=new Date:r?e._d=new Date(+r[1]):"string"==typeof n?j(e):f(n)?(e._a=n.slice(0),H(e)):l(n)?e._d=new Date(+n):"object"==typeof n?A(e):e._d=new Date(n)}function V(t,e,n,r,s,a,i){var o=new Date(t,e,n,r,s,a,i);return 1970>t&&o.setFullYear(t),o}function J(t){var e=new Date(Date.UTC.apply(null,arguments));return 1970>t&&e.setUTCFullYear(t),e}function q(t,e){if("string"==typeof t)if(isNaN(t)){if(t=e.weekdaysParse(t),"number"!=typeof t)return null}else t=parseInt(t,10);return t}function X(t,e,n,r,s){return s.relativeTime(e||1,!!n,t,r)}function R(t,e,n){var r=ut(Math.abs(t)/1e3),s=ut(r/60),a=ut(s/60),i=ut(a/24),o=ut(i/365),u=45>r&&["s",r]||1===s&&["m"]||45>s&&["mm",s]||1===a&&["h"]||22>a&&["hh",a]||1===i&&["d"]||25>=i&&["dd",i]||45>=i&&["M"]||345>i&&["MM",ut(i/30)]||1===o&&["y"]||["yy",o];return u[2]=e,u[3]=t>0,u[4]=n,X.apply({},u)}function B(t,e,n){var r,s=n-e,a=n-t.day();return a>s&&(a-=7),s-7>a&&(a+=7),r=st(t).add("d",a),{week:Math.ceil(r.dayOfYear()/7),year:r.year()}}function Q(t,e,n,r,s){var a,i,o=J(t,0,1).getUTCDay();return n=null!=n?n:s,a=s-o+(o>r?7:0)-(s>o?7:0),i=7*(e-1)+(n-s)+a+1,{year:i>0?t:t-1,dayOfYear:i>0?i:M(t-1)+i}}function K(t){var e=t._i,n=t._f;return null===e?st.invalid({nullInput:!0}):("string"==typeof e&&(t._i=e=G().preparse(e)),st.isMoment(e)?(t=u(e),t._d=new Date(+e._d)):n?f(n)?N(t):I(t):$(t),new a(t))}function tt(t,e){var n="date"===e||"month"===e||"year"===e;st.fn[t]=st.fn[t+"s"]=function(t,r){var s=this._isUTC?"UTC":"";return null==r&&(r=n),null!=t?(this._d["set"+s+e](t),st.updateOffset(this,r),this):this._d["get"+s+e]()}}function et(t){st.duration.fn[t]=function(){return this._data[t]}}function nt(t,e){st.duration.fn["as"+t]=function(){return+this/e}}function rt(t){var e=!1,n=st;"undefined"==typeof ender&&(t?(ot.moment=function(){return!e&&console&&console.warn&&(e=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),n.apply(null,arguments)},o(ot.moment,n)):ot.moment=st)}for(var st,at,it="2.5.1",ot=this,ut=Math.round,dt=0,ht=1,ct=2,ft=3,lt=4,_t=5,mt=6,yt={},pt={_isAMomentObject:null,_i:null,_f:null,_l:null,_strict:null,_isUTC:null,_offset:null,_pf:null,_lang:null},gt="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,Yt=/^\/?Date\((\-?\d+)/i,wt=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,Mt=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,Dt=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,vt=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,kt=/\d\d?/,bt=/\d{1,3}/,St=/\d{1,4}/,Tt=/[+\-]?\d{1,6}/,Ot=/\d+/,Gt=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Wt=/Z|[\+\-]\d\d:?\d\d/gi,Ft=/T/i,Ct=/[\+\-]?\d+(\.\d{1,3})?/,zt=/\d{1,2}/,Lt=/\d/,Ut=/\d\d/,Pt=/\d{3}/,Ht=/\d{4}/,At=/[+-]?\d{6}/,xt=/[+-]?\d+/,It=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Zt="YYYY-MM-DDTHH:mm:ssZ",Et=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],Nt=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],jt=/([\+\-]|\d\d)/gi,$t="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Vt={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Jt={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},qt={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Xt={},Rt="DDD w W M D d".split(" "),Bt="M D H h m s w W".split(" "),Qt={M:function(){return this.month()+1},MMM:function(t){return this.lang().monthsShort(this,t)},MMMM:function(t){return this.lang().months(this,t)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(t){return this.lang().weekdaysMin(this,t)},ddd:function(t){return this.lang().weekdaysShort(this,t)},dddd:function(t){return this.lang().weekdays(this,t)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return h(this.year()%100,2)},YYYY:function(){return h(this.year(),4)},YYYYY:function(){return h(this.year(),5)},YYYYYY:function(){var t=this.year(),e=t>=0?"+":"-";return e+h(Math.abs(t),6)},gg:function(){return h(this.weekYear()%100,2)},gggg:function(){return h(this.weekYear(),4)},ggggg:function(){return h(this.weekYear(),5)},GG:function(){return h(this.isoWeekYear()%100,2)},GGGG:function(){return h(this.isoWeekYear(),4)},GGGGG:function(){return h(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return g(this.milliseconds()/100)},SS:function(){return h(g(this.milliseconds()/10),2)},SSS:function(){return h(this.milliseconds(),3)},SSSS:function(){return h(this.milliseconds(),3)},Z:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+h(g(t/60),2)+":"+h(g(t)%60,2)},ZZ:function(){var t=-this.zone(),e="+";return 0>t&&(t=-t,e="-"),e+h(g(t/60),2)+h(g(t)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Kt=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Rt.length;)at=Rt.pop(),Qt[at+"o"]=r(Qt[at],at);for(;Bt.length;)at=Bt.pop(),Qt[at+at]=n(Qt[at],2);for(Qt.DDDD=n(Qt.DDD,3),o(s.prototype,{set:function(t){var e,n;for(n in t)e=t[n],"function"==typeof e?this[n]=e:this["_"+n]=e},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(t){return this._months[t.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(t){return this._monthsShort[t.month()]},monthsParse:function(t){var e,n,r;for(this._monthsParse||(this._monthsParse=[]),e=0;12>e;e++)if(this._monthsParse[e]||(n=st.utc([2e3,e]),r="^"+this.months(n,"")+"|^"+this.monthsShort(n,""),this._monthsParse[e]=new RegExp(r.replace(".",""),"i")),this._monthsParse[e].test(t))return e},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(t){return this._weekdays[t.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(t){return this._weekdaysShort[t.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(t){return this._weekdaysMin[t.day()]},weekdaysParse:function(t){var e,n,r;for(this._weekdaysParse||(this._weekdaysParse=[]),e=0;7>e;e++)if(this._weekdaysParse[e]||(n=st([2e3,1]).day(e),r="^"+this.weekdays(n,"")+"|^"+this.weekdaysShort(n,"")+"|^"+this.weekdaysMin(n,""),this._weekdaysParse[e]=new RegExp(r.replace(".",""),"i")),this._weekdaysParse[e].test(t))return e},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(t){var e=this._longDateFormat[t];return!e&&this._longDateFormat[t.toUpperCase()]&&(e=this._longDateFormat[t.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t]=e),e},isPM:function(t){return"p"===(t+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(t,e){var n=this._calendar[t];return"function"==typeof n?n.apply(e):n},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(t,e,n,r){var s=this._relativeTime[n];return"function"==typeof s?s(t,e,n,r):s.replace(/%d/i,t)},pastFuture:function(t,e){var n=this._relativeTime[t>0?"future":"past"];return"function"==typeof n?n(e):n.replace(/%s/i,e)},ordinal:function(t){return this._ordinal.replace("%d",t)},_ordinal:"%d",preparse:function(t){return t},postformat:function(t){return t},week:function(t){return B(t,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),st=function(n,r,s,a){var i;return"boolean"==typeof s&&(a=s,s=t),i={},i._isAMomentObject=!0,i._i=n,i._f=r,i._l=s,i._strict=a,i._isUTC=!1,i._pf=e(),K(i)},st.utc=function(n,r,s,a){var i;return"boolean"==typeof s&&(a=s,s=t),i={},i._isAMomentObject=!0,i._useUTC=!0,i._isUTC=!0,i._l=s,i._i=n,i._f=r,i._strict=a,i._pf=e(),K(i).utc()},st.unix=function(t){return st(1e3*t)},st.duration=function(t,e){var n,r,s,a=t,o=null;return st.isDuration(t)?a={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(a={},e?a[e]=t:a.milliseconds=t):(o=wt.exec(t))?(n="-"===o[1]?-1:1,a={y:0,d:g(o[ct])*n,h:g(o[ft])*n,m:g(o[lt])*n,s:g(o[_t])*n,ms:g(o[mt])*n}):(o=Mt.exec(t))&&(n="-"===o[1]?-1:1,s=function(t){var e=t&&parseFloat(t.replace(",","."));return(isNaN(e)?0:e)*n},a={y:s(o[2]),M:s(o[3]),d:s(o[4]),h:s(o[5]),m:s(o[6]),s:s(o[7]),w:s(o[8])}),r=new i(a),st.isDuration(t)&&t.hasOwnProperty("_lang")&&(r._lang=t._lang),r},st.version=it,st.defaultFormat=Zt,st.updateOffset=function(){},st.lang=function(t,e){var n;return t?(e?T(b(t),e):null===e?(O(t),t="en"):yt[t]||G(t),n=st.duration.fn._lang=st.fn._lang=G(t),n._abbr):st.fn._lang._abbr},st.langData=function(t){return t&&t._lang&&t._lang._abbr&&(t=t._lang._abbr),G(t)},st.isMoment=function(t){return t instanceof a||null!=t&&t.hasOwnProperty("_isAMomentObject")},st.isDuration=function(t){return t instanceof i},at=Kt.length-1;at>=0;--at)p(Kt[at]);for(st.normalizeUnits=function(t){return m(t)},st.invalid=function(t){var e=st.utc(0/0);return null!=t?o(e._pf,t):e._pf.userInvalidated=!0,e},st.parseZone=function(){return st.apply(null,arguments).parseZone()},o(st.fn=a.prototype,{clone:function(){return st(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var t=st(this).utc();return 00:!1},parsingFlags:function(){return o({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(t){var e=C(this,t||st.defaultFormat);return this.lang().postformat(e)},add:function(t,e){var n;return n="string"==typeof t?st.duration(+e,t):st.duration(t,e),c(this,n,1),this},subtract:function(t,e){var n;return n="string"==typeof t?st.duration(+e,t):st.duration(t,e),c(this,n,-1),this},diff:function(t,e,n){var r,s,a=S(t,this),i=6e4*(this.zone()-a.zone());return e=m(e),"year"===e||"month"===e?(r=432e5*(this.daysInMonth()+a.daysInMonth()),s=12*(this.year()-a.year())+(this.month()-a.month()),s+=(this-st(this).startOf("month")-(a-st(a).startOf("month")))/r,s-=6e4*(this.zone()-st(this).startOf("month").zone()-(a.zone()-st(a).startOf("month").zone()))/r,"year"===e&&(s/=12)):(r=this-a,s="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-i)/864e5:"week"===e?(r-i)/6048e5:r),n?s:d(s)},from:function(t,e){return st.duration(this.diff(t)).lang(this.lang()._abbr).humanize(!e)},fromNow:function(t){return this.from(st(),t)},calendar:function(){var t=S(st(),this).startOf("day"),e=this.diff(t,"days",!0),n=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(this.lang().calendar(n,this))},isLeapYear:function(){return D(this.year())},isDST:function(){return this.zone()+st(t).startOf(e)},isBefore:function(t,e){return e="undefined"!=typeof e?e:"millisecond",+this.clone().startOf(e)<+st(t).startOf(e)},isSame:function(t,e){return e=e||"ms",+this.clone().startOf(e)===+S(t,this).startOf(e)},min:function(t){return t=st.apply(null,arguments),this>t?this:t},max:function(t){return t=st.apply(null,arguments),t>this?this:t},zone:function(t,e){e=null==e?!0:!1;var n=this._offset||0;return null==t?this._isUTC?n:this._d.getTimezoneOffset():("string"==typeof t&&(t=U(t)),Math.abs(t)<16&&(t=60*t),this._offset=t,this._isUTC=!0,n!==t&&e&&c(this,st.duration(n-t,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(t){return t=t?st(t).zone():0,(this.zone()-t)%60===0},daysInMonth:function(){return Y(this.year(),this.month())},dayOfYear:function(t){var e=ut((st(this).startOf("day")-st(this).startOf("year"))/864e5)+1;return null==t?e:this.add("d",t-e)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(t){var e=B(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==t?e:this.add("y",t-e)},isoWeekYear:function(t){var e=B(this,1,4).year;return null==t?e:this.add("y",t-e)},week:function(t){var e=this.lang().week(this);return null==t?e:this.add("d",7*(t-e))},isoWeek:function(t){var e=B(this,1,4).week;return null==t?e:this.add("d",7*(t-e))},weekday:function(t){var e=(this.day()+7-this.lang()._week.dow)%7;return null==t?e:this.add("d",t-e)},isoWeekday:function(t){return null==t?this.day()||7:this.day(this.day()%7?t:t-7)},isoWeeksInYear:function(){return w(this.year(),1,4)},weeksInYear:function(){var t=this._lang._week;return w(this.year(),t.dow,t.doy)},get:function(t){return t=m(t),this[t]()},set:function(t,e){return t=m(t),"function"==typeof this[t]&&this[t](e),this},lang:function(e){return e===t?this._lang:(this._lang=G(e),this)}}),at=0;at<$t.length;at++)tt($t[at].toLowerCase().replace(/s$/,""),$t[at]);tt("year","FullYear"),st.fn.days=st.fn.day,st.fn.months=st.fn.month,st.fn.weeks=st.fn.week,st.fn.isoWeeks=st.fn.isoWeek,st.fn.toJSON=st.fn.toISOString,o(st.duration.fn=i.prototype,{_bubble:function(){var t,e,n,r,s=this._milliseconds,a=this._days,i=this._months,o=this._data;o.milliseconds=s%1e3,t=d(s/1e3),o.seconds=t%60,e=d(t/60),o.minutes=e%60,n=d(e/60),o.hours=n%24,a+=d(n/24),o.days=a%30,i+=d(a/30),o.months=i%12,r=d(i/12),o.years=r},weeks:function(){return d(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12)},humanize:function(t){var e=+this,n=R(e,!t,this.lang());return t&&(n=this.lang().pastFuture(e,n)),this.lang().postformat(n)},add:function(t,e){var n=st.duration(t,e);return this._milliseconds+=n._milliseconds,this._days+=n._days,this._months+=n._months,this._bubble(),this},subtract:function(t,e){var n=st.duration(t,e);return this._milliseconds-=n._milliseconds,this._days-=n._days,this._months-=n._months,this._bubble(),this},get:function(t){return t=m(t),this[t.toLowerCase()+"s"]()},as:function(t){return t=m(t),this["as"+t.charAt(0).toUpperCase()+t.slice(1)+"s"]()},lang:st.fn.lang,toIsoString:function(){var t=Math.abs(this.years()),e=Math.abs(this.months()),n=Math.abs(this.days()),r=Math.abs(this.hours()),s=Math.abs(this.minutes()),a=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(t?t+"Y":"")+(e?e+"M":"")+(n?n+"D":"")+(r||s||a?"T":"")+(r?r+"H":"")+(s?s+"M":"")+(a?a+"S":""):"P0D"}});for(at in Vt)Vt.hasOwnProperty(at)&&(nt(at,Vt[at]),et(at.toLowerCase()));nt("Weeks",6048e5),st.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},st.lang("en",{ordinal:function(t){var e=t%10,n=1===g(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n}}),gt?(module.exports=st,rt(!0)):"function"==typeof define&&define.amd?define("moment",function(e,n,r){return r.config&&r.config()&&r.config().noGlobal!==!0&&rt(r.config().noGlobal===t),st}):rt()}).call(this); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/swfobject.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/swfobject.js new file mode 100644 index 000000000..ea4a8f7d0 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/swfobject.js @@ -0,0 +1,5 @@ +/* SWFObject v2.2 + is released under the MIT License +*/ +var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;aba;a++)R[a]()}}function t(e){G?e():R[R.length]=e}function n(e){if(typeof x.addEventListener!=L)x.addEventListener("load",e,!1);else if(typeof M.addEventListener!=L)M.addEventListener("load",e,!1);else if(typeof x.attachEvent!=L)m(x,"onload",e);else if("function"==typeof x.onload){var t=x.onload;x.onload=function(){t(),e()}}else x.onload=e}function a(){P?i():r()}function i(){var e=M.getElementsByTagName("body")[0],t=h(k);t.setAttribute("type",O);var n=e.appendChild(t);if(n){var a=0;!function(){if(typeof n.GetVariable!=L){var i=n.GetVariable("$version");i&&(i=i.split(" ")[1].split(","),X.pv=[parseInt(i[0],10),parseInt(i[1],10),parseInt(i[2],10)])}else if(10>a)return a++,void setTimeout(arguments.callee,10);e.removeChild(t),n=null,r()}()}else r()}function r(){var e=D.length;if(e>0)for(var t=0;e>t;t++){var n=D[t].id,a=D[t].callbackFn,i={success:!1,id:n};if(X.pv[0]>0){var r=y(n);if(r)if(!g(D[t].swfVersion)||X.wk&&X.wk<312)if(D[t].expressInstall&&s()){var f={};f.data=D[t].expressInstall,f.width=r.getAttribute("width")||"0",f.height=r.getAttribute("height")||"0",r.getAttribute("class")&&(f.styleclass=r.getAttribute("class")),r.getAttribute("align")&&(f.align=r.getAttribute("align"));for(var d={},u=r.getElementsByTagName("param"),p=u.length,v=0;p>v;v++)"movie"!=u[v].getAttribute("name").toLowerCase()&&(d[u[v].getAttribute("name")]=u[v].getAttribute("value"));l(f,d,n,a)}else c(r),a&&a(i);else b(n,!0),a&&(i.success=!0,i.ref=o(n),a(i))}else if(b(n,!0),a){var h=o(n);h&&typeof h.SetVariable!=L&&(i.success=!0,i.ref=h),a(i)}}}function o(e){var t=null,n=y(e);if(n&&"OBJECT"==n.nodeName)if(typeof n.SetVariable!=L)t=n;else{var a=n.getElementsByTagName(k)[0];a&&(t=a)}return t}function s(){return!J&&g("6.0.65")&&(X.win||X.mac)&&!(X.wk&&X.wk<312)}function l(e,t,n,a){J=!0,A=a||null,N={success:!1,id:n};var i=y(n);if(i){"OBJECT"==i.nodeName?(E=f(i),S=null):(E=i,S=n),e.id=F,(typeof e.width==L||!/%$/.test(e.width)&&parseInt(e.width,10)<310)&&(e.width="310"),(typeof e.height==L||!/%$/.test(e.height)&&parseInt(e.height,10)<137)&&(e.height="137"),M.title=M.title.slice(0,47)+" - Flash Player Installation";var r=X.ie&&X.win?"ActiveX":"PlugIn",o="MMredirectURL="+x.location.toString().replace(/&/g,"%26")+"&MMplayerType="+r+"&MMdoctitle="+M.title;if(typeof t.flashvars!=L?t.flashvars+="&"+o:t.flashvars=o,X.ie&&X.win&&4!=i.readyState){var s=h("div");n+="SWFObjectNew",s.setAttribute("id",n),i.parentNode.insertBefore(s,i),i.style.display="none",function(){4==i.readyState?i.parentNode.removeChild(i):setTimeout(arguments.callee,10)}()}d(e,t,n)}}function c(e){if(X.ie&&X.win&&4!=e.readyState){var t=h("div");e.parentNode.insertBefore(t,e),t.parentNode.replaceChild(f(e),t),e.style.display="none",function(){4==e.readyState?e.parentNode.removeChild(e):setTimeout(arguments.callee,10)}()}else e.parentNode.replaceChild(f(e),e)}function f(e){var t=h("div");if(X.win&&X.ie)t.innerHTML=e.innerHTML;else{var n=e.getElementsByTagName(k)[0];if(n){var a=n.childNodes;if(a)for(var i=a.length,r=0;i>r;r++)1==a[r].nodeType&&"PARAM"==a[r].nodeName||8==a[r].nodeType||t.appendChild(a[r].cloneNode(!0))}}return t}function d(e,t,n){var a,i=y(n);if(X.wk&&X.wk<312)return a;if(i)if(typeof e.id==L&&(e.id=n),X.ie&&X.win){var r="";for(var o in e)e[o]!=Object.prototype[o]&&("data"==o.toLowerCase()?t.movie=e[o]:"styleclass"==o.toLowerCase()?r+=' class="'+e[o]+'"':"classid"!=o.toLowerCase()&&(r+=" "+o+'="'+e[o]+'"'));var s="";for(var l in t)t[l]!=Object.prototype[l]&&(s+='');i.outerHTML='"+s+"",W[W.length]=e.id,a=y(e.id)}else{var c=h(k);c.setAttribute("type",O);for(var f in e)e[f]!=Object.prototype[f]&&("styleclass"==f.toLowerCase()?c.setAttribute("class",e[f]):"classid"!=f.toLowerCase()&&c.setAttribute(f,e[f]));for(var d in t)t[d]!=Object.prototype[d]&&"movie"!=d.toLowerCase()&&u(c,d,t[d]);i.parentNode.replaceChild(c,i),a=c}return a}function u(e,t,n){var a=h("param");a.setAttribute("name",t),a.setAttribute("value",n),e.appendChild(a)}function p(e){var t=y(e);t&&"OBJECT"==t.nodeName&&(X.ie&&X.win?(t.style.display="none",function(){4==t.readyState?v(e):setTimeout(arguments.callee,10)}()):t.parentNode.removeChild(t))}function v(e){var t=y(e);if(t){for(var n in t)"function"==typeof t[n]&&(t[n]=null);t.parentNode.removeChild(t)}}function y(e){var t=null;try{t=M.getElementById(e)}catch(n){}return t}function h(e){return M.createElement(e)}function m(e,t,n){e.attachEvent(t,n),H[H.length]=[e,t,n]}function g(e){var t=X.pv,n=e.split(".");return n[0]=parseInt(n[0],10),n[1]=parseInt(n[1],10)||0,n[2]=parseInt(n[2],10)||0,t[0]>n[0]||t[0]==n[0]&&t[1]>n[1]||t[0]==n[0]&&t[1]==n[1]&&t[2]>=n[2]?!0:!1}function w(e,t,n,a){if(!X.ie||!X.mac){var i=M.getElementsByTagName("head")[0];if(i){var r=n&&"string"==typeof n?n:"screen";if(a&&(T=null,I=null),!T||I!=r){var o=h("style");o.setAttribute("type","text/css"),o.setAttribute("media",r),T=i.appendChild(o),X.ie&&X.win&&typeof M.styleSheets!=L&&M.styleSheets.length>0&&(T=M.styleSheets[M.styleSheets.length-1]),I=r}X.ie&&X.win?T&&typeof T.addRule==k&&T.addRule(e,t):T&&typeof M.createTextNode!=L&&T.appendChild(M.createTextNode(e+" {"+t+"}"))}}}function b(e,t){if(U){var n=t?"visible":"hidden";G&&y(e)?y(e).style.visibility=n:w("#"+e,"visibility:"+n)}}function C(e){var t=/[\\\"<>\.;]/,n=null!=t.exec(e);return n&&typeof encodeURIComponent!=L?encodeURIComponent(e):e}{var E,S,A,N,T,I,L="undefined",k="object",j="Shockwave Flash",B="ShockwaveFlash.ShockwaveFlash",O="application/x-shockwave-flash",F="SWFObjectExprInst",$="onreadystatechange",x=window,M=document,V=navigator,P=!1,R=[a],D=[],W=[],H=[],G=!1,J=!1,U=!0,X=function(){var e=typeof M.getElementById!=L&&typeof M.getElementsByTagName!=L&&typeof M.createElement!=L,t=V.userAgent.toLowerCase(),n=V.platform.toLowerCase(),a=/win/.test(n?n:t),i=/mac/.test(n?n:t),r=/webkit/.test(t)?parseFloat(t.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):!1,o=!1,s=[0,0,0],l=null;if(typeof V.plugins!=L&&typeof V.plugins[j]==k)l=V.plugins[j].description,!l||typeof V.mimeTypes!=L&&V.mimeTypes[O]&&!V.mimeTypes[O].enabledPlugin||(P=!0,o=!1,l=l.replace(/^.*\s+(\S+\s+\S+$)/,"$1"),s[0]=parseInt(l.replace(/^(.*)\..*$/,"$1"),10),s[1]=parseInt(l.replace(/^.*\.(.*)\s.*$/,"$1"),10),s[2]=/[a-zA-Z]/.test(l)?parseInt(l.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0);else if(typeof x.ActiveXObject!=L)try{var c=new ActiveXObject(B);c&&(l=c.GetVariable("$version"),l&&(o=!0,l=l.split(" ")[1].split(","),s=[parseInt(l[0],10),parseInt(l[1],10),parseInt(l[2],10)]))}catch(f){}return{w3:e,pv:s,wk:r,ie:o,win:a,mac:i}}();!function(){X.w3&&((typeof M.readyState!=L&&"complete"==M.readyState||typeof M.readyState==L&&(M.getElementsByTagName("body")[0]||M.body))&&e(),G||(typeof M.addEventListener!=L&&M.addEventListener("DOMContentLoaded",e,!1),X.ie&&X.win&&(M.attachEvent($,function(){"complete"==M.readyState&&(M.detachEvent($,arguments.callee),e())}),x==top&&!function(){if(!G){try{M.documentElement.doScroll("left")}catch(t){return void setTimeout(arguments.callee,0)}e()}}()),X.wk&&!function(){return G?void 0:/loaded|complete/.test(M.readyState)?void e():void setTimeout(arguments.callee,0)}(),n(e)))}(),function(){X.ie&&X.win&&window.attachEvent("onunload",function(){for(var e=H.length,t=0;e>t;t++)H[t][0].detachEvent(H[t][1],H[t][2]);for(var n=W.length,a=0;n>a;a++)p(W[a]);for(var i in X)X[i]=null;X=null;for(var r in swfobject)swfobject[r]=null;swfobject=null})}()}return{registerObject:function(e,t,n,a){if(X.w3&&e&&t){var i={};i.id=e,i.swfVersion=t,i.expressInstall=n,i.callbackFn=a,D[D.length]=i,b(e,!1)}else a&&a({success:!1,id:e})},getObjectById:function(e){return X.w3?o(e):void 0},embedSWF:function(e,n,a,i,r,o,c,f,u,p){var v={success:!1,id:n};X.w3&&!(X.wk&&X.wk<312)&&e&&n&&a&&i&&r?(b(n,!1),t(function(){a+="",i+="";var t={};if(u&&typeof u===k)for(var y in u)t[y]=u[y];t.data=e,t.width=a,t.height=i;var h={};if(f&&typeof f===k)for(var m in f)h[m]=f[m];if(c&&typeof c===k)for(var w in c)typeof h.flashvars!=L?h.flashvars+="&"+w+"="+c[w]:h.flashvars=w+"="+c[w];if(g(r)){var C=d(t,h,n);t.id==n&&b(n,!0),v.success=!0,v.ref=C}else{if(o&&s())return t.data=o,void l(t,h,n,p);b(n,!0)}p&&p(v)})):p&&p(v)},switchOffAutoHideShow:function(){U=!1},ua:X,getFlashPlayerVersion:function(){return{major:X.pv[0],minor:X.pv[1],release:X.pv[2]}},hasFlashPlayerVersion:g,createSWF:function(e,t,n){return X.w3?d(e,t,n):void 0},showExpressInstall:function(e,t,n,a){X.w3&&s()&&l(e,t,n,a)},removeSWF:function(e){X.w3&&p(e)},createCSS:function(e,t,n,a){X.w3&&w(e,t,n,a)},addDomLoadEvent:t,addLoadEvent:n,getQueryParamValue:function(e){var t=M.location.search||M.location.hash;if(t){if(/\?/.test(t)&&(t=t.split("?")[1]),null==e)return C(t);for(var n=t.split("&"),a=0;a 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var result; + any(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); + each(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, function(value, index, list) { + return !predicate.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); + each(obj, function(value, index, list) { + if (!(result = result && predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); + each(obj, function(value, index, list) { + if (result || (result = predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + var result = -Infinity, lastComputed = -Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed > lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + var result = Infinity, lastComputed = Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed < lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Shuffle an array, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + if (value == null) return _.identity; + if (_.isFunction(value)) return value; + return _.property(value); + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + iterator = lookupIterator(iterator); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iterator, context) { + var result = {}; + iterator = lookupIterator(iterator); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, key, value) { + _.has(result, key) ? result[key].push(value) : result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Split an array into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(array, predicate, context) { + predicate = lookupIterator(predicate); + var pass = [], fail = []; + each(array, function(elem) { + (predicate.call(context, elem) ? pass : fail).push(elem); + }); + return [pass, fail]; + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.contains(other, item); + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, 'length').concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error('bindAll must be passed function names'); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor)) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + _.constant = function(value) { + return function () { + return value; + }; + }; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of `key:value` pairs. + _.matches = function(attrs) { + return function(obj) { + if (obj === attrs) return true; //avoid comparing an object to itself. + for (var key in attrs) { + if (attrs[key] !== obj[key]) + return false; + } + return true; + } + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { return new Date().getTime(); }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}).call(this); + +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJ1bmRlcnNjb3JlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vICAgICBVbmRlcnNjb3JlLmpzIDEuNi4wXHJcbi8vICAgICBodHRwOi8vdW5kZXJzY29yZWpzLm9yZ1xyXG4vLyAgICAgKGMpIDIwMDktMjAxNCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xyXG4vLyAgICAgVW5kZXJzY29yZSBtYXkgYmUgZnJlZWx5IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cclxuXHJcbihmdW5jdGlvbigpIHtcclxuXHJcbiAgLy8gQmFzZWxpbmUgc2V0dXBcclxuICAvLyAtLS0tLS0tLS0tLS0tLVxyXG5cclxuICAvLyBFc3RhYmxpc2ggdGhlIHJvb3Qgb2JqZWN0LCBgd2luZG93YCBpbiB0aGUgYnJvd3Nlciwgb3IgYGV4cG9ydHNgIG9uIHRoZSBzZXJ2ZXIuXHJcbiAgdmFyIHJvb3QgPSB0aGlzO1xyXG5cclxuICAvLyBTYXZlIHRoZSBwcmV2aW91cyB2YWx1ZSBvZiB0aGUgYF9gIHZhcmlhYmxlLlxyXG4gIHZhciBwcmV2aW91c1VuZGVyc2NvcmUgPSByb290Ll87XHJcblxyXG4gIC8vIEVzdGFibGlzaCB0aGUgb2JqZWN0IHRoYXQgZ2V0cyByZXR1cm5lZCB0byBicmVhayBvdXQgb2YgYSBsb29wIGl0ZXJhdGlvbi5cclxuICB2YXIgYnJlYWtlciA9IHt9O1xyXG5cclxuICAvLyBTYXZlIGJ5dGVzIGluIHRoZSBtaW5pZmllZCAoYnV0IG5vdCBnemlwcGVkKSB2ZXJzaW9uOlxyXG4gIHZhciBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlLCBPYmpQcm90byA9IE9iamVjdC5wcm90b3R5cGUsIEZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcclxuXHJcbiAgLy8gQ3JlYXRlIHF1aWNrIHJlZmVyZW5jZSB2YXJpYWJsZXMgZm9yIHNwZWVkIGFjY2VzcyB0byBjb3JlIHByb3RvdHlwZXMuXHJcbiAgdmFyXHJcbiAgICBwdXNoICAgICAgICAgICAgID0gQXJyYXlQcm90by5wdXNoLFxyXG4gICAgc2xpY2UgICAgICAgICAgICA9IEFycmF5UHJvdG8uc2xpY2UsXHJcbiAgICBjb25jYXQgICAgICAgICAgID0gQXJyYXlQcm90by5jb25jYXQsXHJcbiAgICB0b1N0cmluZyAgICAgICAgID0gT2JqUHJvdG8udG9TdHJpbmcsXHJcbiAgICBoYXNPd25Qcm9wZXJ0eSAgID0gT2JqUHJvdG8uaGFzT3duUHJvcGVydHk7XHJcblxyXG4gIC8vIEFsbCAqKkVDTUFTY3JpcHQgNSoqIG5hdGl2ZSBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbnMgdGhhdCB3ZSBob3BlIHRvIHVzZVxyXG4gIC8vIGFyZSBkZWNsYXJlZCBoZXJlLlxyXG4gIHZhclxyXG4gICAgbmF0aXZlRm9yRWFjaCAgICAgID0gQXJyYXlQcm90by5mb3JFYWNoLFxyXG4gICAgbmF0aXZlTWFwICAgICAgICAgID0gQXJyYXlQcm90by5tYXAsXHJcbiAgICBuYXRpdmVSZWR1Y2UgICAgICAgPSBBcnJheVByb3RvLnJlZHVjZSxcclxuICAgIG5hdGl2ZVJlZHVjZVJpZ2h0ICA9IEFycmF5UHJvdG8ucmVkdWNlUmlnaHQsXHJcbiAgICBuYXRpdmVGaWx0ZXIgICAgICAgPSBBcnJheVByb3RvLmZpbHRlcixcclxuICAgIG5hdGl2ZUV2ZXJ5ICAgICAgICA9IEFycmF5UHJvdG8uZXZlcnksXHJcbiAgICBuYXRpdmVTb21lICAgICAgICAgPSBBcnJheVByb3RvLnNvbWUsXHJcbiAgICBuYXRpdmVJbmRleE9mICAgICAgPSBBcnJheVByb3RvLmluZGV4T2YsXHJcbiAgICBuYXRpdmVMYXN0SW5kZXhPZiAgPSBBcnJheVByb3RvLmxhc3RJbmRleE9mLFxyXG4gICAgbmF0aXZlSXNBcnJheSAgICAgID0gQXJyYXkuaXNBcnJheSxcclxuICAgIG5hdGl2ZUtleXMgICAgICAgICA9IE9iamVjdC5rZXlzLFxyXG4gICAgbmF0aXZlQmluZCAgICAgICAgID0gRnVuY1Byb3RvLmJpbmQ7XHJcblxyXG4gIC8vIENyZWF0ZSBhIHNhZmUgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgdXNlIGJlbG93LlxyXG4gIHZhciBfID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICBpZiAob2JqIGluc3RhbmNlb2YgXykgcmV0dXJuIG9iajtcclxuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBfKSkgcmV0dXJuIG5ldyBfKG9iaik7XHJcbiAgICB0aGlzLl93cmFwcGVkID0gb2JqO1xyXG4gIH07XHJcblxyXG4gIC8vIEV4cG9ydCB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yICoqTm9kZS5qcyoqLCB3aXRoXHJcbiAgLy8gYmFja3dhcmRzLWNvbXBhdGliaWxpdHkgZm9yIHRoZSBvbGQgYHJlcXVpcmUoKWAgQVBJLiBJZiB3ZSdyZSBpblxyXG4gIC8vIHRoZSBicm93c2VyLCBhZGQgYF9gIGFzIGEgZ2xvYmFsIG9iamVjdCB2aWEgYSBzdHJpbmcgaWRlbnRpZmllcixcclxuICAvLyBmb3IgQ2xvc3VyZSBDb21waWxlciBcImFkdmFuY2VkXCIgbW9kZS5cclxuICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcclxuICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gXztcclxuICAgIH1cclxuICAgIGV4cG9ydHMuXyA9IF87XHJcbiAgfSBlbHNlIHtcclxuICAgIHJvb3QuXyA9IF87XHJcbiAgfVxyXG5cclxuICAvLyBDdXJyZW50IHZlcnNpb24uXHJcbiAgXy5WRVJTSU9OID0gJzEuNi4wJztcclxuXHJcbiAgLy8gQ29sbGVjdGlvbiBGdW5jdGlvbnNcclxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICAvLyBUaGUgY29ybmVyc3RvbmUsIGFuIGBlYWNoYCBpbXBsZW1lbnRhdGlvbiwgYWthIGBmb3JFYWNoYC5cclxuICAvLyBIYW5kbGVzIG9iamVjdHMgd2l0aCB0aGUgYnVpbHQtaW4gYGZvckVhY2hgLCBhcnJheXMsIGFuZCByYXcgb2JqZWN0cy5cclxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgZm9yRWFjaGAgaWYgYXZhaWxhYmxlLlxyXG4gIHZhciBlYWNoID0gXy5lYWNoID0gXy5mb3JFYWNoID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xyXG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gb2JqO1xyXG4gICAgaWYgKG5hdGl2ZUZvckVhY2ggJiYgb2JqLmZvckVhY2ggPT09IG5hdGl2ZUZvckVhY2gpIHtcclxuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xyXG4gICAgfSBlbHNlIGlmIChvYmoubGVuZ3RoID09PSArb2JqLmxlbmd0aCkge1xyXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2ldLCBpLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XHJcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2tleXNbaV1dLCBrZXlzW2ldLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBvYmo7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJuIHRoZSByZXN1bHRzIG9mIGFwcGx5aW5nIHRoZSBpdGVyYXRvciB0byBlYWNoIGVsZW1lbnQuXHJcbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYG1hcGAgaWYgYXZhaWxhYmxlLlxyXG4gIF8ubWFwID0gXy5jb2xsZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xyXG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcclxuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdHM7XHJcbiAgICBpZiAobmF0aXZlTWFwICYmIG9iai5tYXAgPT09IG5hdGl2ZU1hcCkgcmV0dXJuIG9iai5tYXAoaXRlcmF0b3IsIGNvbnRleHQpO1xyXG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xyXG4gICAgICByZXN1bHRzLnB1c2goaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHJlc3VsdHM7XHJcbiAgfTtcclxuXHJcbiAgdmFyIHJlZHVjZUVycm9yID0gJ1JlZHVjZSBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnO1xyXG5cclxuICAvLyAqKlJlZHVjZSoqIGJ1aWxkcyB1cCBhIHNpbmdsZSByZXN1bHQgZnJvbSBhIGxpc3Qgb2YgdmFsdWVzLCBha2EgYGluamVjdGAsXHJcbiAgLy8gb3IgYGZvbGRsYC4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHJlZHVjZWAgaWYgYXZhaWxhYmxlLlxyXG4gIF8ucmVkdWNlID0gXy5mb2xkbCA9IF8uaW5qZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgbWVtbywgY29udGV4dCkge1xyXG4gICAgdmFyIGluaXRpYWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMjtcclxuICAgIGlmIChvYmogPT0gbnVsbCkgb2JqID0gW107XHJcbiAgICBpZiAobmF0aXZlUmVkdWNlICYmIG9iai5yZWR1Y2UgPT09IG5hdGl2ZVJlZHVjZSkge1xyXG4gICAgICBpZiAoY29udGV4dCkgaXRlcmF0b3IgPSBfLmJpbmQoaXRlcmF0b3IsIGNvbnRleHQpO1xyXG4gICAgICByZXR1cm4gaW5pdGlhbCA/IG9iai5yZWR1Y2UoaXRlcmF0b3IsIG1lbW8pIDogb2JqLnJlZHVjZShpdGVyYXRvcik7XHJcbiAgICB9XHJcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XHJcbiAgICAgIGlmICghaW5pdGlhbCkge1xyXG4gICAgICAgIG1lbW8gPSB2YWx1ZTtcclxuICAgICAgICBpbml0aWFsID0gdHJ1ZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBtZW1vID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBtZW1vLCB2YWx1ZSwgaW5kZXgsIGxpc3QpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XHJcbiAgICByZXR1cm4gbWVtbztcclxuICB9O1xyXG5cclxuICAvLyBUaGUgcmlnaHQtYXNzb2NpYXRpdmUgdmVyc2lvbiBvZiByZWR1Y2UsIGFsc28ga25vd24gYXMgYGZvbGRyYC5cclxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgcmVkdWNlUmlnaHRgIGlmIGF2YWlsYWJsZS5cclxuICBfLnJlZHVjZVJpZ2h0ID0gXy5mb2xkciA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIG1lbW8sIGNvbnRleHQpIHtcclxuICAgIHZhciBpbml0aWFsID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBpZiAob2JqID09IG51bGwpIG9iaiA9IFtdO1xyXG4gICAgaWYgKG5hdGl2ZVJlZHVjZVJpZ2h0ICYmIG9iai5yZWR1Y2VSaWdodCA9PT0gbmF0aXZlUmVkdWNlUmlnaHQpIHtcclxuICAgICAgaWYgKGNvbnRleHQpIGl0ZXJhdG9yID0gXy5iaW5kKGl0ZXJhdG9yLCBjb250ZXh0KTtcclxuICAgICAgcmV0dXJuIGluaXRpYWwgPyBvYmoucmVkdWNlUmlnaHQoaXRlcmF0b3IsIG1lbW8pIDogb2JqLnJlZHVjZVJpZ2h0KGl0ZXJhdG9yKTtcclxuICAgIH1cclxuICAgIHZhciBsZW5ndGggPSBvYmoubGVuZ3RoO1xyXG4gICAgaWYgKGxlbmd0aCAhPT0gK2xlbmd0aCkge1xyXG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xyXG4gICAgICBsZW5ndGggPSBrZXlzLmxlbmd0aDtcclxuICAgIH1cclxuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcclxuICAgICAgaW5kZXggPSBrZXlzID8ga2V5c1stLWxlbmd0aF0gOiAtLWxlbmd0aDtcclxuICAgICAgaWYgKCFpbml0aWFsKSB7XHJcbiAgICAgICAgbWVtbyA9IG9ialtpbmRleF07XHJcbiAgICAgICAgaW5pdGlhbCA9IHRydWU7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbWVtbyA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgbWVtbywgb2JqW2luZGV4XSwgaW5kZXgsIGxpc3QpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XHJcbiAgICByZXR1cm4gbWVtbztcclxuICB9O1xyXG5cclxuICAvLyBSZXR1cm4gdGhlIGZpcnN0IHZhbHVlIHdoaWNoIHBhc3NlcyBhIHRydXRoIHRlc3QuIEFsaWFzZWQgYXMgYGRldGVjdGAuXHJcbiAgXy5maW5kID0gXy5kZXRlY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xyXG4gICAgdmFyIHJlc3VsdDtcclxuICAgIGFueShvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xyXG4gICAgICBpZiAocHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkge1xyXG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJuIGFsbCB0aGUgZWxlbWVudHMgdGhhdCBwYXNzIGEgdHJ1dGggdGVzdC5cclxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgZmlsdGVyYCBpZiBhdmFpbGFibGUuXHJcbiAgLy8gQWxpYXNlZCBhcyBgc2VsZWN0YC5cclxuICBfLmZpbHRlciA9IF8uc2VsZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcclxuICAgIHZhciByZXN1bHRzID0gW107XHJcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHRzO1xyXG4gICAgaWYgKG5hdGl2ZUZpbHRlciAmJiBvYmouZmlsdGVyID09PSBuYXRpdmVGaWx0ZXIpIHJldHVybiBvYmouZmlsdGVyKHByZWRpY2F0ZSwgY29udGV4dCk7XHJcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XHJcbiAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSByZXN1bHRzLnB1c2godmFsdWUpO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcmVzdWx0cztcclxuICB9O1xyXG5cclxuICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyBmb3Igd2hpY2ggYSB0cnV0aCB0ZXN0IGZhaWxzLlxyXG4gIF8ucmVqZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcclxuICAgIHJldHVybiBfLmZpbHRlcihvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xyXG4gICAgICByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCk7XHJcbiAgICB9LCBjb250ZXh0KTtcclxuICB9O1xyXG5cclxuICAvLyBEZXRlcm1pbmUgd2hldGhlciBhbGwgb2YgdGhlIGVsZW1lbnRzIG1hdGNoIGEgdHJ1dGggdGVzdC5cclxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgZXZlcnlgIGlmIGF2YWlsYWJsZS5cclxuICAvLyBBbGlhc2VkIGFzIGBhbGxgLlxyXG4gIF8uZXZlcnkgPSBfLmFsbCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XHJcbiAgICBwcmVkaWNhdGUgfHwgKHByZWRpY2F0ZSA9IF8uaWRlbnRpdHkpO1xyXG4gICAgdmFyIHJlc3VsdCA9IHRydWU7XHJcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XHJcbiAgICBpZiAobmF0aXZlRXZlcnkgJiYgb2JqLmV2ZXJ5ID09PSBuYXRpdmVFdmVyeSkgcmV0dXJuIG9iai5ldmVyeShwcmVkaWNhdGUsIGNvbnRleHQpO1xyXG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xyXG4gICAgICBpZiAoIShyZXN1bHQgPSByZXN1bHQgJiYgcHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkpIHJldHVybiBicmVha2VyO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gISFyZXN1bHQ7XHJcbiAgfTtcclxuXHJcbiAgLy8gRGV0ZXJtaW5lIGlmIGF0IGxlYXN0IG9uZSBlbGVtZW50IGluIHRoZSBvYmplY3QgbWF0Y2hlcyBhIHRydXRoIHRlc3QuXHJcbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHNvbWVgIGlmIGF2YWlsYWJsZS5cclxuICAvLyBBbGlhc2VkIGFzIGBhbnlgLlxyXG4gIHZhciBhbnkgPSBfLnNvbWUgPSBfLmFueSA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XHJcbiAgICBwcmVkaWNhdGUgfHwgKHByZWRpY2F0ZSA9IF8uaWRlbnRpdHkpO1xyXG4gICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xyXG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0O1xyXG4gICAgaWYgKG5hdGl2ZVNvbWUgJiYgb2JqLnNvbWUgPT09IG5hdGl2ZVNvbWUpIHJldHVybiBvYmouc29tZShwcmVkaWNhdGUsIGNvbnRleHQpO1xyXG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xyXG4gICAgICBpZiAocmVzdWx0IHx8IChyZXN1bHQgPSBwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSkgcmV0dXJuIGJyZWFrZXI7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiAhIXJlc3VsdDtcclxuICB9O1xyXG5cclxuICAvLyBEZXRlcm1pbmUgaWYgdGhlIGFycmF5IG9yIG9iamVjdCBjb250YWlucyBhIGdpdmVuIHZhbHVlICh1c2luZyBgPT09YCkuXHJcbiAgLy8gQWxpYXNlZCBhcyBgaW5jbHVkZWAuXHJcbiAgXy5jb250YWlucyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgdGFyZ2V0KSB7XHJcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiBmYWxzZTtcclxuICAgIGlmIChuYXRpdmVJbmRleE9mICYmIG9iai5pbmRleE9mID09PSBuYXRpdmVJbmRleE9mKSByZXR1cm4gb2JqLmluZGV4T2YodGFyZ2V0KSAhPSAtMTtcclxuICAgIHJldHVybiBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xyXG4gICAgICByZXR1cm4gdmFsdWUgPT09IHRhcmdldDtcclxuICAgIH0pO1xyXG4gIH07XHJcblxyXG4gIC8vIEludm9rZSBhIG1ldGhvZCAod2l0aCBhcmd1bWVudHMpIG9uIGV2ZXJ5IGl0ZW0gaW4gYSBjb2xsZWN0aW9uLlxyXG4gIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHtcclxuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xyXG4gICAgdmFyIGlzRnVuYyA9IF8uaXNGdW5jdGlvbihtZXRob2QpO1xyXG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcclxuICAgICAgcmV0dXJuIChpc0Z1bmMgPyBtZXRob2QgOiB2YWx1ZVttZXRob2RdKS5hcHBseSh2YWx1ZSwgYXJncyk7XHJcbiAgICB9KTtcclxuICB9O1xyXG5cclxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBtYXBgOiBmZXRjaGluZyBhIHByb3BlcnR5LlxyXG4gIF8ucGx1Y2sgPSBmdW5jdGlvbihvYmosIGtleSkge1xyXG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgXy5wcm9wZXJ0eShrZXkpKTtcclxuICB9O1xyXG5cclxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBmaWx0ZXJgOiBzZWxlY3Rpbmcgb25seSBvYmplY3RzXHJcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cclxuICBfLndoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xyXG4gICAgcmV0dXJuIF8uZmlsdGVyKG9iaiwgXy5tYXRjaGVzKGF0dHJzKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmluZGA6IGdldHRpbmcgdGhlIGZpcnN0IG9iamVjdFxyXG4gIC8vIGNvbnRhaW5pbmcgc3BlY2lmaWMgYGtleTp2YWx1ZWAgcGFpcnMuXHJcbiAgXy5maW5kV2hlcmUgPSBmdW5jdGlvbihvYmosIGF0dHJzKSB7XHJcbiAgICByZXR1cm4gXy5maW5kKG9iaiwgXy5tYXRjaGVzKGF0dHJzKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJuIHRoZSBtYXhpbXVtIGVsZW1lbnQgb3IgKGVsZW1lbnQtYmFzZWQgY29tcHV0YXRpb24pLlxyXG4gIC8vIENhbid0IG9wdGltaXplIGFycmF5cyBvZiBpbnRlZ2VycyBsb25nZXIgdGhhbiA2NSw1MzUgZWxlbWVudHMuXHJcbiAgLy8gU2VlIFtXZWJLaXQgQnVnIDgwNzk3XShodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9ODA3OTcpXHJcbiAgXy5tYXggPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XHJcbiAgICBpZiAoIWl0ZXJhdG9yICYmIF8uaXNBcnJheShvYmopICYmIG9ialswXSA9PT0gK29ialswXSAmJiBvYmoubGVuZ3RoIDwgNjU1MzUpIHtcclxuICAgICAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsIG9iaik7XHJcbiAgICB9XHJcbiAgICB2YXIgcmVzdWx0ID0gLUluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSAtSW5maW5pdHk7XHJcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XHJcbiAgICAgIHZhciBjb21wdXRlZCA9IGl0ZXJhdG9yID8gaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpIDogdmFsdWU7XHJcbiAgICAgIGlmIChjb21wdXRlZCA+IGxhc3RDb21wdXRlZCkge1xyXG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xyXG4gICAgICAgIGxhc3RDb21wdXRlZCA9IGNvbXB1dGVkO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJuIHRoZSBtaW5pbXVtIGVsZW1lbnQgKG9yIGVsZW1lbnQtYmFzZWQgY29tcHV0YXRpb24pLlxyXG4gIF8ubWluID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xyXG4gICAgaWYgKCFpdGVyYXRvciAmJiBfLmlzQXJyYXkob2JqKSAmJiBvYmpbMF0gPT09ICtvYmpbMF0gJiYgb2JqLmxlbmd0aCA8IDY1NTM1KSB7XHJcbiAgICAgIHJldHVybiBNYXRoLm1pbi5hcHBseShNYXRoLCBvYmopO1xyXG4gICAgfVxyXG4gICAgdmFyIHJlc3VsdCA9IEluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSBJbmZpbml0eTtcclxuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcclxuICAgICAgdmFyIGNvbXB1dGVkID0gaXRlcmF0b3IgPyBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkgOiB2YWx1ZTtcclxuICAgICAgaWYgKGNvbXB1dGVkIDwgbGFzdENvbXB1dGVkKSB7XHJcbiAgICAgICAgcmVzdWx0ID0gdmFsdWU7XHJcbiAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9O1xyXG5cclxuICAvLyBTaHVmZmxlIGFuIGFycmF5LCB1c2luZyB0aGUgbW9kZXJuIHZlcnNpb24gb2YgdGhlXHJcbiAgLy8gW0Zpc2hlci1ZYXRlcyBzaHVmZmxlXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlcuKAk1lhdGVzX3NodWZmbGUpLlxyXG4gIF8uc2h1ZmZsZSA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgdmFyIHJhbmQ7XHJcbiAgICB2YXIgaW5kZXggPSAwO1xyXG4gICAgdmFyIHNodWZmbGVkID0gW107XHJcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcclxuICAgICAgcmFuZCA9IF8ucmFuZG9tKGluZGV4KyspO1xyXG4gICAgICBzaHVmZmxlZFtpbmRleCAtIDFdID0gc2h1ZmZsZWRbcmFuZF07XHJcbiAgICAgIHNodWZmbGVkW3JhbmRdID0gdmFsdWU7XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBzaHVmZmxlZDtcclxuICB9O1xyXG5cclxuICAvLyBTYW1wbGUgKipuKiogcmFuZG9tIHZhbHVlcyBmcm9tIGEgY29sbGVjdGlvbi5cclxuICAvLyBJZiAqKm4qKiBpcyBub3Qgc3BlY2lmaWVkLCByZXR1cm5zIGEgc2luZ2xlIHJhbmRvbSBlbGVtZW50LlxyXG4gIC8vIFRoZSBpbnRlcm5hbCBgZ3VhcmRgIGFyZ3VtZW50IGFsbG93cyBpdCB0byB3b3JrIHdpdGggYG1hcGAuXHJcbiAgXy5zYW1wbGUgPSBmdW5jdGlvbihvYmosIG4sIGd1YXJkKSB7XHJcbiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSB7XHJcbiAgICAgIGlmIChvYmoubGVuZ3RoICE9PSArb2JqLmxlbmd0aCkgb2JqID0gXy52YWx1ZXMob2JqKTtcclxuICAgICAgcmV0dXJuIG9ialtfLnJhbmRvbShvYmoubGVuZ3RoIC0gMSldO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTtcclxuICB9O1xyXG5cclxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBsb29rdXAgaXRlcmF0b3JzLlxyXG4gIHZhciBsb29rdXBJdGVyYXRvciA9IGZ1bmN0aW9uKHZhbHVlKSB7XHJcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIF8uaWRlbnRpdHk7XHJcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xyXG4gICAgcmV0dXJuIF8ucHJvcGVydHkodmFsdWUpO1xyXG4gIH07XHJcblxyXG4gIC8vIFNvcnQgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbiBwcm9kdWNlZCBieSBhbiBpdGVyYXRvci5cclxuICBfLnNvcnRCeSA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcclxuICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xyXG4gICAgcmV0dXJuIF8ucGx1Y2soXy5tYXAob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICB2YWx1ZTogdmFsdWUsXHJcbiAgICAgICAgaW5kZXg6IGluZGV4LFxyXG4gICAgICAgIGNyaXRlcmlhOiBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdClcclxuICAgICAgfTtcclxuICAgIH0pLnNvcnQoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcclxuICAgICAgdmFyIGEgPSBsZWZ0LmNyaXRlcmlhO1xyXG4gICAgICB2YXIgYiA9IHJpZ2h0LmNyaXRlcmlhO1xyXG4gICAgICBpZiAoYSAhPT0gYikge1xyXG4gICAgICAgIGlmIChhID4gYiB8fCBhID09PSB2b2lkIDApIHJldHVybiAxO1xyXG4gICAgICAgIGlmIChhIDwgYiB8fCBiID09PSB2b2lkIDApIHJldHVybiAtMTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbGVmdC5pbmRleCAtIHJpZ2h0LmluZGV4O1xyXG4gICAgfSksICd2YWx1ZScpO1xyXG4gIH07XHJcblxyXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIHVzZWQgZm9yIGFnZ3JlZ2F0ZSBcImdyb3VwIGJ5XCIgb3BlcmF0aW9ucy5cclxuICB2YXIgZ3JvdXAgPSBmdW5jdGlvbihiZWhhdmlvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcclxuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgICBpdGVyYXRvciA9IGxvb2t1cEl0ZXJhdG9yKGl0ZXJhdG9yKTtcclxuICAgICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xyXG4gICAgICAgIHZhciBrZXkgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgb2JqKTtcclxuICAgICAgICBiZWhhdmlvcihyZXN1bHQsIGtleSwgdmFsdWUpO1xyXG4gICAgICB9KTtcclxuICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcbiAgfTtcclxuXHJcbiAgLy8gR3JvdXBzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24uIFBhc3MgZWl0aGVyIGEgc3RyaW5nIGF0dHJpYnV0ZVxyXG4gIC8vIHRvIGdyb3VwIGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgY3JpdGVyaW9uLlxyXG4gIF8uZ3JvdXBCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5LCB2YWx1ZSkge1xyXG4gICAgXy5oYXMocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSkgOiByZXN1bHRba2V5XSA9IFt2YWx1ZV07XHJcbiAgfSk7XHJcblxyXG4gIC8vIEluZGV4ZXMgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbiwgc2ltaWxhciB0byBgZ3JvdXBCeWAsIGJ1dCBmb3JcclxuICAvLyB3aGVuIHlvdSBrbm93IHRoYXQgeW91ciBpbmRleCB2YWx1ZXMgd2lsbCBiZSB1bmlxdWUuXHJcbiAgXy5pbmRleEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCBrZXksIHZhbHVlKSB7XHJcbiAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xyXG4gIH0pO1xyXG5cclxuICAvLyBDb3VudHMgaW5zdGFuY2VzIG9mIGFuIG9iamVjdCB0aGF0IGdyb3VwIGJ5IGEgY2VydGFpbiBjcml0ZXJpb24uIFBhc3NcclxuICAvLyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlIHRvIGNvdW50IGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGVcclxuICAvLyBjcml0ZXJpb24uXHJcbiAgXy5jb3VudEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCBrZXkpIHtcclxuICAgIF8uaGFzKHJlc3VsdCwga2V5KSA/IHJlc3VsdFtrZXldKysgOiByZXN1bHRba2V5XSA9IDE7XHJcbiAgfSk7XHJcblxyXG4gIC8vIFVzZSBhIGNvbXBhcmF0b3IgZnVuY3Rpb24gdG8gZmlndXJlIG91dCB0aGUgc21hbGxlc3QgaW5kZXggYXQgd2hpY2hcclxuICAvLyBhbiBvYmplY3Qgc2hvdWxkIGJlIGluc2VydGVkIHNvIGFzIHRvIG1haW50YWluIG9yZGVyLiBVc2VzIGJpbmFyeSBzZWFyY2guXHJcbiAgXy5zb3J0ZWRJbmRleCA9IGZ1bmN0aW9uKGFycmF5LCBvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XHJcbiAgICBpdGVyYXRvciA9IGxvb2t1cEl0ZXJhdG9yKGl0ZXJhdG9yKTtcclxuICAgIHZhciB2YWx1ZSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqKTtcclxuICAgIHZhciBsb3cgPSAwLCBoaWdoID0gYXJyYXkubGVuZ3RoO1xyXG4gICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcclxuICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMTtcclxuICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBhcnJheVttaWRdKSA8IHZhbHVlID8gbG93ID0gbWlkICsgMSA6IGhpZ2ggPSBtaWQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbG93O1xyXG4gIH07XHJcblxyXG4gIC8vIFNhZmVseSBjcmVhdGUgYSByZWFsLCBsaXZlIGFycmF5IGZyb20gYW55dGhpbmcgaXRlcmFibGUuXHJcbiAgXy50b0FycmF5ID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICBpZiAoIW9iaikgcmV0dXJuIFtdO1xyXG4gICAgaWYgKF8uaXNBcnJheShvYmopKSByZXR1cm4gc2xpY2UuY2FsbChvYmopO1xyXG4gICAgaWYgKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSByZXR1cm4gXy5tYXAob2JqLCBfLmlkZW50aXR5KTtcclxuICAgIHJldHVybiBfLnZhbHVlcyhvYmopO1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIGFuIG9iamVjdC5cclxuICBfLnNpemUgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIDA7XHJcbiAgICByZXR1cm4gKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSA/IG9iai5sZW5ndGggOiBfLmtleXMob2JqKS5sZW5ndGg7XHJcbiAgfTtcclxuXHJcbiAgLy8gQXJyYXkgRnVuY3Rpb25zXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIC8vIEdldCB0aGUgZmlyc3QgZWxlbWVudCBvZiBhbiBhcnJheS4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiB0aGUgZmlyc3QgTlxyXG4gIC8vIHZhbHVlcyBpbiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYGhlYWRgIGFuZCBgdGFrZWAuIFRoZSAqKmd1YXJkKiogY2hlY2tcclxuICAvLyBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXHJcbiAgXy5maXJzdCA9IF8uaGVhZCA9IF8udGFrZSA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xyXG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XHJcbiAgICBpZiAoKG4gPT0gbnVsbCkgfHwgZ3VhcmQpIHJldHVybiBhcnJheVswXTtcclxuICAgIGlmIChuIDwgMCkgcmV0dXJuIFtdO1xyXG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIG4pO1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGxhc3QgZW50cnkgb2YgdGhlIGFycmF5LiBFc3BlY2lhbGx5IHVzZWZ1bCBvblxyXG4gIC8vIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIGFsbCB0aGUgdmFsdWVzIGluXHJcbiAgLy8gdGhlIGFycmF5LCBleGNsdWRpbmcgdGhlIGxhc3QgTi4gVGhlICoqZ3VhcmQqKiBjaGVjayBhbGxvd3MgaXQgdG8gd29yayB3aXRoXHJcbiAgLy8gYF8ubWFwYC5cclxuICBfLmluaXRpYWwgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcclxuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAwLCBhcnJheS5sZW5ndGggLSAoKG4gPT0gbnVsbCkgfHwgZ3VhcmQgPyAxIDogbikpO1xyXG4gIH07XHJcblxyXG4gIC8vIEdldCB0aGUgbGFzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBsYXN0IE5cclxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cclxuICBfLmxhc3QgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcclxuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xyXG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbYXJyYXkubGVuZ3RoIC0gMV07XHJcbiAgICByZXR1cm4gc2xpY2UuY2FsbChhcnJheSwgTWF0aC5tYXgoYXJyYXkubGVuZ3RoIC0gbiwgMCkpO1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGZpcnN0IGVudHJ5IG9mIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgdGFpbGAgYW5kIGBkcm9wYC5cclxuICAvLyBFc3BlY2lhbGx5IHVzZWZ1bCBvbiB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyBhbiAqKm4qKiB3aWxsIHJldHVyblxyXG4gIC8vIHRoZSByZXN0IE4gdmFsdWVzIGluIHRoZSBhcnJheS4gVGhlICoqZ3VhcmQqKlxyXG4gIC8vIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cclxuICBfLnJlc3QgPSBfLnRhaWwgPSBfLmRyb3AgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcclxuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKTtcclxuICB9O1xyXG5cclxuICAvLyBUcmltIG91dCBhbGwgZmFsc3kgdmFsdWVzIGZyb20gYW4gYXJyYXkuXHJcbiAgXy5jb21wYWN0ID0gZnVuY3Rpb24oYXJyYXkpIHtcclxuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgXy5pZGVudGl0eSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gSW50ZXJuYWwgaW1wbGVtZW50YXRpb24gb2YgYSByZWN1cnNpdmUgYGZsYXR0ZW5gIGZ1bmN0aW9uLlxyXG4gIHZhciBmbGF0dGVuID0gZnVuY3Rpb24oaW5wdXQsIHNoYWxsb3csIG91dHB1dCkge1xyXG4gICAgaWYgKHNoYWxsb3cgJiYgXy5ldmVyeShpbnB1dCwgXy5pc0FycmF5KSkge1xyXG4gICAgICByZXR1cm4gY29uY2F0LmFwcGx5KG91dHB1dCwgaW5wdXQpO1xyXG4gICAgfVxyXG4gICAgZWFjaChpbnB1dCwgZnVuY3Rpb24odmFsdWUpIHtcclxuICAgICAgaWYgKF8uaXNBcnJheSh2YWx1ZSkgfHwgXy5pc0FyZ3VtZW50cyh2YWx1ZSkpIHtcclxuICAgICAgICBzaGFsbG93ID8gcHVzaC5hcHBseShvdXRwdXQsIHZhbHVlKSA6IGZsYXR0ZW4odmFsdWUsIHNoYWxsb3csIG91dHB1dCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgb3V0cHV0LnB1c2godmFsdWUpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBvdXRwdXQ7XHJcbiAgfTtcclxuXHJcbiAgLy8gRmxhdHRlbiBvdXQgYW4gYXJyYXksIGVpdGhlciByZWN1cnNpdmVseSAoYnkgZGVmYXVsdCksIG9yIGp1c3Qgb25lIGxldmVsLlxyXG4gIF8uZmxhdHRlbiA9IGZ1bmN0aW9uKGFycmF5LCBzaGFsbG93KSB7XHJcbiAgICByZXR1cm4gZmxhdHRlbihhcnJheSwgc2hhbGxvdywgW10pO1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybiBhIHZlcnNpb24gb2YgdGhlIGFycmF5IHRoYXQgZG9lcyBub3QgY29udGFpbiB0aGUgc3BlY2lmaWVkIHZhbHVlKHMpLlxyXG4gIF8ud2l0aG91dCA9IGZ1bmN0aW9uKGFycmF5KSB7XHJcbiAgICByZXR1cm4gXy5kaWZmZXJlbmNlKGFycmF5LCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG4gIH07XHJcblxyXG4gIC8vIFNwbGl0IGFuIGFycmF5IGludG8gdHdvIGFycmF5czogb25lIHdob3NlIGVsZW1lbnRzIGFsbCBzYXRpc2Z5IHRoZSBnaXZlblxyXG4gIC8vIHByZWRpY2F0ZSwgYW5kIG9uZSB3aG9zZSBlbGVtZW50cyBhbGwgZG8gbm90IHNhdGlzZnkgdGhlIHByZWRpY2F0ZS5cclxuICBfLnBhcnRpdGlvbiA9IGZ1bmN0aW9uKGFycmF5LCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcclxuICAgIHByZWRpY2F0ZSA9IGxvb2t1cEl0ZXJhdG9yKHByZWRpY2F0ZSk7XHJcbiAgICB2YXIgcGFzcyA9IFtdLCBmYWlsID0gW107XHJcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbihlbGVtKSB7XHJcbiAgICAgIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCBlbGVtKSA/IHBhc3MgOiBmYWlsKS5wdXNoKGVsZW0pO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gW3Bhc3MsIGZhaWxdO1xyXG4gIH07XHJcblxyXG4gIC8vIFByb2R1Y2UgYSBkdXBsaWNhdGUtZnJlZSB2ZXJzaW9uIG9mIHRoZSBhcnJheS4gSWYgdGhlIGFycmF5IGhhcyBhbHJlYWR5XHJcbiAgLy8gYmVlbiBzb3J0ZWQsIHlvdSBoYXZlIHRoZSBvcHRpb24gb2YgdXNpbmcgYSBmYXN0ZXIgYWxnb3JpdGhtLlxyXG4gIC8vIEFsaWFzZWQgYXMgYHVuaXF1ZWAuXHJcbiAgXy51bmlxID0gXy51bmlxdWUgPSBmdW5jdGlvbihhcnJheSwgaXNTb3J0ZWQsIGl0ZXJhdG9yLCBjb250ZXh0KSB7XHJcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKGlzU29ydGVkKSkge1xyXG4gICAgICBjb250ZXh0ID0gaXRlcmF0b3I7XHJcbiAgICAgIGl0ZXJhdG9yID0gaXNTb3J0ZWQ7XHJcbiAgICAgIGlzU29ydGVkID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgICB2YXIgaW5pdGlhbCA9IGl0ZXJhdG9yID8gXy5tYXAoYXJyYXksIGl0ZXJhdG9yLCBjb250ZXh0KSA6IGFycmF5O1xyXG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcclxuICAgIHZhciBzZWVuID0gW107XHJcbiAgICBlYWNoKGluaXRpYWwsIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xyXG4gICAgICBpZiAoaXNTb3J0ZWQgPyAoIWluZGV4IHx8IHNlZW5bc2Vlbi5sZW5ndGggLSAxXSAhPT0gdmFsdWUpIDogIV8uY29udGFpbnMoc2VlbiwgdmFsdWUpKSB7XHJcbiAgICAgICAgc2Vlbi5wdXNoKHZhbHVlKTtcclxuICAgICAgICByZXN1bHRzLnB1c2goYXJyYXlbaW5kZXhdKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcmVzdWx0cztcclxuICB9O1xyXG5cclxuICAvLyBQcm9kdWNlIGFuIGFycmF5IHRoYXQgY29udGFpbnMgdGhlIHVuaW9uOiBlYWNoIGRpc3RpbmN0IGVsZW1lbnQgZnJvbSBhbGwgb2ZcclxuICAvLyB0aGUgcGFzc2VkLWluIGFycmF5cy5cclxuICBfLnVuaW9uID0gZnVuY3Rpb24oKSB7XHJcbiAgICByZXR1cm4gXy51bmlxKF8uZmxhdHRlbihhcmd1bWVudHMsIHRydWUpKTtcclxuICB9O1xyXG5cclxuICAvLyBQcm9kdWNlIGFuIGFycmF5IHRoYXQgY29udGFpbnMgZXZlcnkgaXRlbSBzaGFyZWQgYmV0d2VlbiBhbGwgdGhlXHJcbiAgLy8gcGFzc2VkLWluIGFycmF5cy5cclxuICBfLmludGVyc2VjdGlvbiA9IGZ1bmN0aW9uKGFycmF5KSB7XHJcbiAgICB2YXIgcmVzdCA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuICAgIHJldHVybiBfLmZpbHRlcihfLnVuaXEoYXJyYXkpLCBmdW5jdGlvbihpdGVtKSB7XHJcbiAgICAgIHJldHVybiBfLmV2ZXJ5KHJlc3QsIGZ1bmN0aW9uKG90aGVyKSB7XHJcbiAgICAgICAgcmV0dXJuIF8uY29udGFpbnMob3RoZXIsIGl0ZW0pO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH07XHJcblxyXG4gIC8vIFRha2UgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBvbmUgYXJyYXkgYW5kIGEgbnVtYmVyIG9mIG90aGVyIGFycmF5cy5cclxuICAvLyBPbmx5IHRoZSBlbGVtZW50cyBwcmVzZW50IGluIGp1c3QgdGhlIGZpcnN0IGFycmF5IHdpbGwgcmVtYWluLlxyXG4gIF8uZGlmZmVyZW5jZSA9IGZ1bmN0aW9uKGFycmF5KSB7XHJcbiAgICB2YXIgcmVzdCA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBmdW5jdGlvbih2YWx1ZSl7IHJldHVybiAhXy5jb250YWlucyhyZXN0LCB2YWx1ZSk7IH0pO1xyXG4gIH07XHJcblxyXG4gIC8vIFppcCB0b2dldGhlciBtdWx0aXBsZSBsaXN0cyBpbnRvIGEgc2luZ2xlIGFycmF5IC0tIGVsZW1lbnRzIHRoYXQgc2hhcmVcclxuICAvLyBhbiBpbmRleCBnbyB0b2dldGhlci5cclxuICBfLnppcCA9IGZ1bmN0aW9uKCkge1xyXG4gICAgdmFyIGxlbmd0aCA9IF8ubWF4KF8ucGx1Y2soYXJndW1lbnRzLCAnbGVuZ3RoJykuY29uY2F0KDApKTtcclxuICAgIHZhciByZXN1bHRzID0gbmV3IEFycmF5KGxlbmd0aCk7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHJlc3VsdHNbaV0gPSBfLnBsdWNrKGFyZ3VtZW50cywgJycgKyBpKTtcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHRzO1xyXG4gIH07XHJcblxyXG4gIC8vIENvbnZlcnRzIGxpc3RzIGludG8gb2JqZWN0cy4gUGFzcyBlaXRoZXIgYSBzaW5nbGUgYXJyYXkgb2YgYFtrZXksIHZhbHVlXWBcclxuICAvLyBwYWlycywgb3IgdHdvIHBhcmFsbGVsIGFycmF5cyBvZiB0aGUgc2FtZSBsZW5ndGggLS0gb25lIG9mIGtleXMsIGFuZCBvbmUgb2ZcclxuICAvLyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuXHJcbiAgXy5vYmplY3QgPSBmdW5jdGlvbihsaXN0LCB2YWx1ZXMpIHtcclxuICAgIGlmIChsaXN0ID09IG51bGwpIHJldHVybiB7fTtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBsaXN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmICh2YWx1ZXMpIHtcclxuICAgICAgICByZXN1bHRbbGlzdFtpXV0gPSB2YWx1ZXNbaV07XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmVzdWx0W2xpc3RbaV1bMF1dID0gbGlzdFtpXVsxXTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9O1xyXG5cclxuICAvLyBJZiB0aGUgYnJvd3NlciBkb2Vzbid0IHN1cHBseSB1cyB3aXRoIGluZGV4T2YgKEknbSBsb29raW5nIGF0IHlvdSwgKipNU0lFKiopLFxyXG4gIC8vIHdlIG5lZWQgdGhpcyBmdW5jdGlvbi4gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhblxyXG4gIC8vIGl0ZW0gaW4gYW4gYXJyYXksIG9yIC0xIGlmIHRoZSBpdGVtIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgYXJyYXkuXHJcbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGluZGV4T2ZgIGlmIGF2YWlsYWJsZS5cclxuICAvLyBJZiB0aGUgYXJyYXkgaXMgbGFyZ2UgYW5kIGFscmVhZHkgaW4gc29ydCBvcmRlciwgcGFzcyBgdHJ1ZWBcclxuICAvLyBmb3IgKippc1NvcnRlZCoqIHRvIHVzZSBiaW5hcnkgc2VhcmNoLlxyXG4gIF8uaW5kZXhPZiA9IGZ1bmN0aW9uKGFycmF5LCBpdGVtLCBpc1NvcnRlZCkge1xyXG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiAtMTtcclxuICAgIHZhciBpID0gMCwgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xyXG4gICAgaWYgKGlzU29ydGVkKSB7XHJcbiAgICAgIGlmICh0eXBlb2YgaXNTb3J0ZWQgPT0gJ251bWJlcicpIHtcclxuICAgICAgICBpID0gKGlzU29ydGVkIDwgMCA/IE1hdGgubWF4KDAsIGxlbmd0aCArIGlzU29ydGVkKSA6IGlzU29ydGVkKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpID0gXy5zb3J0ZWRJbmRleChhcnJheSwgaXRlbSk7XHJcbiAgICAgICAgcmV0dXJuIGFycmF5W2ldID09PSBpdGVtID8gaSA6IC0xO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAobmF0aXZlSW5kZXhPZiAmJiBhcnJheS5pbmRleE9mID09PSBuYXRpdmVJbmRleE9mKSByZXR1cm4gYXJyYXkuaW5kZXhPZihpdGVtLCBpc1NvcnRlZCk7XHJcbiAgICBmb3IgKDsgaSA8IGxlbmd0aDsgaSsrKSBpZiAoYXJyYXlbaV0gPT09IGl0ZW0pIHJldHVybiBpO1xyXG4gICAgcmV0dXJuIC0xO1xyXG4gIH07XHJcblxyXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBsYXN0SW5kZXhPZmAgaWYgYXZhaWxhYmxlLlxyXG4gIF8ubGFzdEluZGV4T2YgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgZnJvbSkge1xyXG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiAtMTtcclxuICAgIHZhciBoYXNJbmRleCA9IGZyb20gIT0gbnVsbDtcclxuICAgIGlmIChuYXRpdmVMYXN0SW5kZXhPZiAmJiBhcnJheS5sYXN0SW5kZXhPZiA9PT0gbmF0aXZlTGFzdEluZGV4T2YpIHtcclxuICAgICAgcmV0dXJuIGhhc0luZGV4ID8gYXJyYXkubGFzdEluZGV4T2YoaXRlbSwgZnJvbSkgOiBhcnJheS5sYXN0SW5kZXhPZihpdGVtKTtcclxuICAgIH1cclxuICAgIHZhciBpID0gKGhhc0luZGV4ID8gZnJvbSA6IGFycmF5Lmxlbmd0aCk7XHJcbiAgICB3aGlsZSAoaS0tKSBpZiAoYXJyYXlbaV0gPT09IGl0ZW0pIHJldHVybiBpO1xyXG4gICAgcmV0dXJuIC0xO1xyXG4gIH07XHJcblxyXG4gIC8vIEdlbmVyYXRlIGFuIGludGVnZXIgQXJyYXkgY29udGFpbmluZyBhbiBhcml0aG1ldGljIHByb2dyZXNzaW9uLiBBIHBvcnQgb2ZcclxuICAvLyB0aGUgbmF0aXZlIFB5dGhvbiBgcmFuZ2UoKWAgZnVuY3Rpb24uIFNlZVxyXG4gIC8vIFt0aGUgUHl0aG9uIGRvY3VtZW50YXRpb25dKGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS9mdW5jdGlvbnMuaHRtbCNyYW5nZSkuXHJcbiAgXy5yYW5nZSA9IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8PSAxKSB7XHJcbiAgICAgIHN0b3AgPSBzdGFydCB8fCAwO1xyXG4gICAgICBzdGFydCA9IDA7XHJcbiAgICB9XHJcbiAgICBzdGVwID0gYXJndW1lbnRzWzJdIHx8IDE7XHJcblxyXG4gICAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KE1hdGguY2VpbCgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXApLCAwKTtcclxuICAgIHZhciBpZHggPSAwO1xyXG4gICAgdmFyIHJhbmdlID0gbmV3IEFycmF5KGxlbmd0aCk7XHJcblxyXG4gICAgd2hpbGUoaWR4IDwgbGVuZ3RoKSB7XHJcbiAgICAgIHJhbmdlW2lkeCsrXSA9IHN0YXJ0O1xyXG4gICAgICBzdGFydCArPSBzdGVwO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByYW5nZTtcclxuICB9O1xyXG5cclxuICAvLyBGdW5jdGlvbiAoYWhlbSkgRnVuY3Rpb25zXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIC8vIFJldXNhYmxlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciBwcm90b3R5cGUgc2V0dGluZy5cclxuICB2YXIgY3RvciA9IGZ1bmN0aW9uKCl7fTtcclxuXHJcbiAgLy8gQ3JlYXRlIGEgZnVuY3Rpb24gYm91bmQgdG8gYSBnaXZlbiBvYmplY3QgKGFzc2lnbmluZyBgdGhpc2AsIGFuZCBhcmd1bWVudHMsXHJcbiAgLy8gb3B0aW9uYWxseSkuIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBGdW5jdGlvbi5iaW5kYCBpZlxyXG4gIC8vIGF2YWlsYWJsZS5cclxuICBfLmJpbmQgPSBmdW5jdGlvbihmdW5jLCBjb250ZXh0KSB7XHJcbiAgICB2YXIgYXJncywgYm91bmQ7XHJcbiAgICBpZiAobmF0aXZlQmluZCAmJiBmdW5jLmJpbmQgPT09IG5hdGl2ZUJpbmQpIHJldHVybiBuYXRpdmVCaW5kLmFwcGx5KGZ1bmMsIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XHJcbiAgICBpZiAoIV8uaXNGdW5jdGlvbihmdW5jKSkgdGhyb3cgbmV3IFR5cGVFcnJvcjtcclxuICAgIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XHJcbiAgICByZXR1cm4gYm91bmQgPSBmdW5jdGlvbigpIHtcclxuICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSkgcmV0dXJuIGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XHJcbiAgICAgIGN0b3IucHJvdG90eXBlID0gZnVuYy5wcm90b3R5cGU7XHJcbiAgICAgIHZhciBzZWxmID0gbmV3IGN0b3I7XHJcbiAgICAgIGN0b3IucHJvdG90eXBlID0gbnVsbDtcclxuICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkoc2VsZiwgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XHJcbiAgICAgIGlmIChPYmplY3QocmVzdWx0KSA9PT0gcmVzdWx0KSByZXR1cm4gcmVzdWx0O1xyXG4gICAgICByZXR1cm4gc2VsZjtcclxuICAgIH07XHJcbiAgfTtcclxuXHJcbiAgLy8gUGFydGlhbGx5IGFwcGx5IGEgZnVuY3Rpb24gYnkgY3JlYXRpbmcgYSB2ZXJzaW9uIHRoYXQgaGFzIGhhZCBzb21lIG9mIGl0c1xyXG4gIC8vIGFyZ3VtZW50cyBwcmUtZmlsbGVkLCB3aXRob3V0IGNoYW5naW5nIGl0cyBkeW5hbWljIGB0aGlzYCBjb250ZXh0LiBfIGFjdHNcclxuICAvLyBhcyBhIHBsYWNlaG9sZGVyLCBhbGxvd2luZyBhbnkgY29tYmluYXRpb24gb2YgYXJndW1lbnRzIHRvIGJlIHByZS1maWxsZWQuXHJcbiAgXy5wYXJ0aWFsID0gZnVuY3Rpb24oZnVuYykge1xyXG4gICAgdmFyIGJvdW5kQXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcclxuICAgICAgdmFyIHBvc2l0aW9uID0gMDtcclxuICAgICAgdmFyIGFyZ3MgPSBib3VuZEFyZ3Muc2xpY2UoKTtcclxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGFyZ3MubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBpZiAoYXJnc1tpXSA9PT0gXykgYXJnc1tpXSA9IGFyZ3VtZW50c1twb3NpdGlvbisrXTtcclxuICAgICAgfVxyXG4gICAgICB3aGlsZSAocG9zaXRpb24gPCBhcmd1bWVudHMubGVuZ3RoKSBhcmdzLnB1c2goYXJndW1lbnRzW3Bvc2l0aW9uKytdKTtcclxuICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIC8vIEJpbmQgYSBudW1iZXIgb2YgYW4gb2JqZWN0J3MgbWV0aG9kcyB0byB0aGF0IG9iamVjdC4gUmVtYWluaW5nIGFyZ3VtZW50c1xyXG4gIC8vIGFyZSB0aGUgbWV0aG9kIG5hbWVzIHRvIGJlIGJvdW5kLiBVc2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgYWxsIGNhbGxiYWNrc1xyXG4gIC8vIGRlZmluZWQgb24gYW4gb2JqZWN0IGJlbG9uZyB0byBpdC5cclxuICBfLmJpbmRBbGwgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHZhciBmdW5jcyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuICAgIGlmIChmdW5jcy5sZW5ndGggPT09IDApIHRocm93IG5ldyBFcnJvcignYmluZEFsbCBtdXN0IGJlIHBhc3NlZCBmdW5jdGlvbiBuYW1lcycpO1xyXG4gICAgZWFjaChmdW5jcywgZnVuY3Rpb24oZikgeyBvYmpbZl0gPSBfLmJpbmQob2JqW2ZdLCBvYmopOyB9KTtcclxuICAgIHJldHVybiBvYmo7XHJcbiAgfTtcclxuXHJcbiAgLy8gTWVtb2l6ZSBhbiBleHBlbnNpdmUgZnVuY3Rpb24gYnkgc3RvcmluZyBpdHMgcmVzdWx0cy5cclxuICBfLm1lbW9pemUgPSBmdW5jdGlvbihmdW5jLCBoYXNoZXIpIHtcclxuICAgIHZhciBtZW1vID0ge307XHJcbiAgICBoYXNoZXIgfHwgKGhhc2hlciA9IF8uaWRlbnRpdHkpO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xyXG4gICAgICB2YXIga2V5ID0gaGFzaGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgIHJldHVybiBfLmhhcyhtZW1vLCBrZXkpID8gbWVtb1trZXldIDogKG1lbW9ba2V5XSA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIC8vIERlbGF5cyBhIGZ1bmN0aW9uIGZvciB0aGUgZ2l2ZW4gbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgYW5kIHRoZW4gY2FsbHNcclxuICAvLyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgc3VwcGxpZWQuXHJcbiAgXy5kZWxheSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQpIHtcclxuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xyXG4gICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgYXJncyk7IH0sIHdhaXQpO1xyXG4gIH07XHJcblxyXG4gIC8vIERlZmVycyBhIGZ1bmN0aW9uLCBzY2hlZHVsaW5nIGl0IHRvIHJ1biBhZnRlciB0aGUgY3VycmVudCBjYWxsIHN0YWNrIGhhc1xyXG4gIC8vIGNsZWFyZWQuXHJcbiAgXy5kZWZlciA9IGZ1bmN0aW9uKGZ1bmMpIHtcclxuICAgIHJldHVybiBfLmRlbGF5LmFwcGx5KF8sIFtmdW5jLCAxXS5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCB3aGVuIGludm9rZWQsIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgYXQgbW9zdCBvbmNlXHJcbiAgLy8gZHVyaW5nIGEgZ2l2ZW4gd2luZG93IG9mIHRpbWUuIE5vcm1hbGx5LCB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHdpbGwgcnVuXHJcbiAgLy8gYXMgbXVjaCBhcyBpdCBjYW4sIHdpdGhvdXQgZXZlciBnb2luZyBtb3JlIHRoYW4gb25jZSBwZXIgYHdhaXRgIGR1cmF0aW9uO1xyXG4gIC8vIGJ1dCBpZiB5b3UnZCBsaWtlIHRvIGRpc2FibGUgdGhlIGV4ZWN1dGlvbiBvbiB0aGUgbGVhZGluZyBlZGdlLCBwYXNzXHJcbiAgLy8gYHtsZWFkaW5nOiBmYWxzZX1gLiBUbyBkaXNhYmxlIGV4ZWN1dGlvbiBvbiB0aGUgdHJhaWxpbmcgZWRnZSwgZGl0dG8uXHJcbiAgXy50aHJvdHRsZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcclxuICAgIHZhciBjb250ZXh0LCBhcmdzLCByZXN1bHQ7XHJcbiAgICB2YXIgdGltZW91dCA9IG51bGw7XHJcbiAgICB2YXIgcHJldmlvdXMgPSAwO1xyXG4gICAgb3B0aW9ucyB8fCAob3B0aW9ucyA9IHt9KTtcclxuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICBwcmV2aW91cyA9IG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UgPyAwIDogXy5ub3coKTtcclxuICAgICAgdGltZW91dCA9IG51bGw7XHJcbiAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XHJcbiAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcclxuICAgIH07XHJcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XHJcbiAgICAgIHZhciBub3cgPSBfLm5vdygpO1xyXG4gICAgICBpZiAoIXByZXZpb3VzICYmIG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UpIHByZXZpb3VzID0gbm93O1xyXG4gICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XHJcbiAgICAgIGNvbnRleHQgPSB0aGlzO1xyXG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xyXG4gICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcclxuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XHJcbiAgICAgICAgdGltZW91dCA9IG51bGw7XHJcbiAgICAgICAgcHJldmlvdXMgPSBub3c7XHJcbiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XHJcbiAgICAgIH0gZWxzZSBpZiAoIXRpbWVvdXQgJiYgb3B0aW9ucy50cmFpbGluZyAhPT0gZmFsc2UpIHtcclxuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfTtcclxuICB9O1xyXG5cclxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XHJcbiAgLy8gYmUgdHJpZ2dlcmVkLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgaXQgc3RvcHMgYmVpbmcgY2FsbGVkIGZvclxyXG4gIC8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxyXG4gIC8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuXHJcbiAgXy5kZWJvdW5jZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGltbWVkaWF0ZSkge1xyXG4gICAgdmFyIHRpbWVvdXQsIGFyZ3MsIGNvbnRleHQsIHRpbWVzdGFtcCwgcmVzdWx0O1xyXG5cclxuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICB2YXIgbGFzdCA9IF8ubm93KCkgLSB0aW1lc3RhbXA7XHJcbiAgICAgIGlmIChsYXN0IDwgd2FpdCkge1xyXG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0IC0gbGFzdCk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGltZW91dCA9IG51bGw7XHJcbiAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcclxuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XHJcbiAgICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcclxuICAgICAgY29udGV4dCA9IHRoaXM7XHJcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XHJcbiAgICAgIHRpbWVzdGFtcCA9IF8ubm93KCk7XHJcbiAgICAgIHZhciBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xyXG4gICAgICBpZiAoIXRpbWVvdXQpIHtcclxuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGNhbGxOb3cpIHtcclxuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xyXG4gICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH07XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhdCBtb3N0IG9uZSB0aW1lLCBubyBtYXR0ZXIgaG93XHJcbiAgLy8gb2Z0ZW4geW91IGNhbGwgaXQuIFVzZWZ1bCBmb3IgbGF6eSBpbml0aWFsaXphdGlvbi5cclxuICBfLm9uY2UgPSBmdW5jdGlvbihmdW5jKSB7XHJcbiAgICB2YXIgcmFuID0gZmFsc2UsIG1lbW87XHJcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XHJcbiAgICAgIGlmIChyYW4pIHJldHVybiBtZW1vO1xyXG4gICAgICByYW4gPSB0cnVlO1xyXG4gICAgICBtZW1vID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gICAgICBmdW5jID0gbnVsbDtcclxuICAgICAgcmV0dXJuIG1lbW87XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLFxyXG4gIC8vIGFsbG93aW5nIHlvdSB0byBhZGp1c3QgYXJndW1lbnRzLCBydW4gY29kZSBiZWZvcmUgYW5kIGFmdGVyLCBhbmRcclxuICAvLyBjb25kaXRpb25hbGx5IGV4ZWN1dGUgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLlxyXG4gIF8ud3JhcCA9IGZ1bmN0aW9uKGZ1bmMsIHdyYXBwZXIpIHtcclxuICAgIHJldHVybiBfLnBhcnRpYWwod3JhcHBlciwgZnVuYyk7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgaXMgdGhlIGNvbXBvc2l0aW9uIG9mIGEgbGlzdCBvZiBmdW5jdGlvbnMsIGVhY2hcclxuICAvLyBjb25zdW1pbmcgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZnVuY3Rpb24gdGhhdCBmb2xsb3dzLlxyXG4gIF8uY29tcG9zZSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgdmFyIGZ1bmNzID0gYXJndW1lbnRzO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xyXG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcclxuICAgICAgZm9yICh2YXIgaSA9IGZ1bmNzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgYXJncyA9IFtmdW5jc1tpXS5hcHBseSh0aGlzLCBhcmdzKV07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGFyZ3NbMF07XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgb25seSBiZSBleGVjdXRlZCBhZnRlciBiZWluZyBjYWxsZWQgTiB0aW1lcy5cclxuICBfLmFmdGVyID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcclxuICAgICAgaWYgKC0tdGltZXMgPCAxKSB7XHJcbiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuICB9O1xyXG5cclxuICAvLyBPYmplY3QgRnVuY3Rpb25zXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuICAvLyBSZXRyaWV2ZSB0aGUgbmFtZXMgb2YgYW4gb2JqZWN0J3MgcHJvcGVydGllcy5cclxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgT2JqZWN0LmtleXNgXHJcbiAgXy5rZXlzID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIFtdO1xyXG4gICAgaWYgKG5hdGl2ZUtleXMpIHJldHVybiBuYXRpdmVLZXlzKG9iaik7XHJcbiAgICB2YXIga2V5cyA9IFtdO1xyXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkga2V5cy5wdXNoKGtleSk7XHJcbiAgICByZXR1cm4ga2V5cztcclxuICB9O1xyXG5cclxuICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWVzIG9mIGFuIG9iamVjdCdzIHByb3BlcnRpZXMuXHJcbiAgXy52YWx1ZXMgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XHJcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XHJcbiAgICB2YXIgdmFsdWVzID0gbmV3IEFycmF5KGxlbmd0aCk7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHZhbHVlc1tpXSA9IG9ialtrZXlzW2ldXTtcclxuICAgIH1cclxuICAgIHJldHVybiB2YWx1ZXM7XHJcbiAgfTtcclxuXHJcbiAgLy8gQ29udmVydCBhbiBvYmplY3QgaW50byBhIGxpc3Qgb2YgYFtrZXksIHZhbHVlXWAgcGFpcnMuXHJcbiAgXy5wYWlycyA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcclxuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcclxuICAgIHZhciBwYWlycyA9IG5ldyBBcnJheShsZW5ndGgpO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xyXG4gICAgICBwYWlyc1tpXSA9IFtrZXlzW2ldLCBvYmpba2V5c1tpXV1dO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHBhaXJzO1xyXG4gIH07XHJcblxyXG4gIC8vIEludmVydCB0aGUga2V5cyBhbmQgdmFsdWVzIG9mIGFuIG9iamVjdC4gVGhlIHZhbHVlcyBtdXN0IGJlIHNlcmlhbGl6YWJsZS5cclxuICBfLmludmVydCA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcclxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIHJlc3VsdFtvYmpba2V5c1tpXV1dID0ga2V5c1tpXTtcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfTtcclxuXHJcbiAgLy8gUmV0dXJuIGEgc29ydGVkIGxpc3Qgb2YgdGhlIGZ1bmN0aW9uIG5hbWVzIGF2YWlsYWJsZSBvbiB0aGUgb2JqZWN0LlxyXG4gIC8vIEFsaWFzZWQgYXMgYG1ldGhvZHNgXHJcbiAgXy5mdW5jdGlvbnMgPSBfLm1ldGhvZHMgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHZhciBuYW1lcyA9IFtdO1xyXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xyXG4gICAgICBpZiAoXy5pc0Z1bmN0aW9uKG9ialtrZXldKSkgbmFtZXMucHVzaChrZXkpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG5hbWVzLnNvcnQoKTtcclxuICB9O1xyXG5cclxuICAvLyBFeHRlbmQgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgaW4gcGFzc2VkLWluIG9iamVjdChzKS5cclxuICBfLmV4dGVuZCA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgZWFjaChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSksIGZ1bmN0aW9uKHNvdXJjZSkge1xyXG4gICAgICBpZiAoc291cmNlKSB7XHJcbiAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBzb3VyY2UpIHtcclxuICAgICAgICAgIG9ialtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG9iajtcclxuICB9O1xyXG5cclxuICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgb25seSBjb250YWluaW5nIHRoZSB3aGl0ZWxpc3RlZCBwcm9wZXJ0aWVzLlxyXG4gIF8ucGljayA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgdmFyIGNvcHkgPSB7fTtcclxuICAgIHZhciBrZXlzID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XHJcbiAgICBlYWNoKGtleXMsIGZ1bmN0aW9uKGtleSkge1xyXG4gICAgICBpZiAoa2V5IGluIG9iaikgY29weVtrZXldID0gb2JqW2tleV07XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBjb3B5O1xyXG4gIH07XHJcblxyXG4gICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgd2l0aG91dCB0aGUgYmxhY2tsaXN0ZWQgcHJvcGVydGllcy5cclxuICBfLm9taXQgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHZhciBjb3B5ID0ge307XHJcbiAgICB2YXIga2V5cyA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xyXG4gICAgICBpZiAoIV8uY29udGFpbnMoa2V5cywga2V5KSkgY29weVtrZXldID0gb2JqW2tleV07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gY29weTtcclxuICB9O1xyXG5cclxuICAvLyBGaWxsIGluIGEgZ2l2ZW4gb2JqZWN0IHdpdGggZGVmYXVsdCBwcm9wZXJ0aWVzLlxyXG4gIF8uZGVmYXVsdHMgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIGVhY2goc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLCBmdW5jdGlvbihzb3VyY2UpIHtcclxuICAgICAgaWYgKHNvdXJjZSkge1xyXG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XHJcbiAgICAgICAgICBpZiAob2JqW3Byb3BdID09PSB2b2lkIDApIG9ialtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIG9iajtcclxuICB9O1xyXG5cclxuICAvLyBDcmVhdGUgYSAoc2hhbGxvdy1jbG9uZWQpIGR1cGxpY2F0ZSBvZiBhbiBvYmplY3QuXHJcbiAgXy5jbG9uZSA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgaWYgKCFfLmlzT2JqZWN0KG9iaikpIHJldHVybiBvYmo7XHJcbiAgICByZXR1cm4gXy5pc0FycmF5KG9iaikgPyBvYmouc2xpY2UoKSA6IF8uZXh0ZW5kKHt9LCBvYmopO1xyXG4gIH07XHJcblxyXG4gIC8vIEludm9rZXMgaW50ZXJjZXB0b3Igd2l0aCB0aGUgb2JqLCBhbmQgdGhlbiByZXR1cm5zIG9iai5cclxuICAvLyBUaGUgcHJpbWFyeSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiwgaW5cclxuICAvLyBvcmRlciB0byBwZXJmb3JtIG9wZXJhdGlvbnMgb24gaW50ZXJtZWRpYXRlIHJlc3VsdHMgd2l0aGluIHRoZSBjaGFpbi5cclxuICBfLnRhcCA9IGZ1bmN0aW9uKG9iaiwgaW50ZXJjZXB0b3IpIHtcclxuICAgIGludGVyY2VwdG9yKG9iaik7XHJcbiAgICByZXR1cm4gb2JqO1xyXG4gIH07XHJcblxyXG4gIC8vIEludGVybmFsIHJlY3Vyc2l2ZSBjb21wYXJpc29uIGZ1bmN0aW9uIGZvciBgaXNFcXVhbGAuXHJcbiAgdmFyIGVxID0gZnVuY3Rpb24oYSwgYiwgYVN0YWNrLCBiU3RhY2spIHtcclxuICAgIC8vIElkZW50aWNhbCBvYmplY3RzIGFyZSBlcXVhbC4gYDAgPT09IC0wYCwgYnV0IHRoZXkgYXJlbid0IGlkZW50aWNhbC5cclxuICAgIC8vIFNlZSB0aGUgW0hhcm1vbnkgYGVnYWxgIHByb3Bvc2FsXShodHRwOi8vd2lraS5lY21hc2NyaXB0Lm9yZy9kb2t1LnBocD9pZD1oYXJtb255OmVnYWwpLlxyXG4gICAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09IDEgLyBiO1xyXG4gICAgLy8gQSBzdHJpY3QgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkgYmVjYXVzZSBgbnVsbCA9PSB1bmRlZmluZWRgLlxyXG4gICAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBhID09PSBiO1xyXG4gICAgLy8gVW53cmFwIGFueSB3cmFwcGVkIG9iamVjdHMuXHJcbiAgICBpZiAoYSBpbnN0YW5jZW9mIF8pIGEgPSBhLl93cmFwcGVkO1xyXG4gICAgaWYgKGIgaW5zdGFuY2VvZiBfKSBiID0gYi5fd3JhcHBlZDtcclxuICAgIC8vIENvbXBhcmUgYFtbQ2xhc3NdXWAgbmFtZXMuXHJcbiAgICB2YXIgY2xhc3NOYW1lID0gdG9TdHJpbmcuY2FsbChhKTtcclxuICAgIGlmIChjbGFzc05hbWUgIT0gdG9TdHJpbmcuY2FsbChiKSkgcmV0dXJuIGZhbHNlO1xyXG4gICAgc3dpdGNoIChjbGFzc05hbWUpIHtcclxuICAgICAgLy8gU3RyaW5ncywgbnVtYmVycywgZGF0ZXMsIGFuZCBib29sZWFucyBhcmUgY29tcGFyZWQgYnkgdmFsdWUuXHJcbiAgICAgIGNhc2UgJ1tvYmplY3QgU3RyaW5nXSc6XHJcbiAgICAgICAgLy8gUHJpbWl0aXZlcyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBvYmplY3Qgd3JhcHBlcnMgYXJlIGVxdWl2YWxlbnQ7IHRodXMsIGBcIjVcImAgaXNcclxuICAgICAgICAvLyBlcXVpdmFsZW50IHRvIGBuZXcgU3RyaW5nKFwiNVwiKWAuXHJcbiAgICAgICAgcmV0dXJuIGEgPT0gU3RyaW5nKGIpO1xyXG4gICAgICBjYXNlICdbb2JqZWN0IE51bWJlcl0nOlxyXG4gICAgICAgIC8vIGBOYU5gcyBhcmUgZXF1aXZhbGVudCwgYnV0IG5vbi1yZWZsZXhpdmUuIEFuIGBlZ2FsYCBjb21wYXJpc29uIGlzIHBlcmZvcm1lZCBmb3JcclxuICAgICAgICAvLyBvdGhlciBudW1lcmljIHZhbHVlcy5cclxuICAgICAgICByZXR1cm4gYSAhPSArYSA/IGIgIT0gK2IgOiAoYSA9PSAwID8gMSAvIGEgPT0gMSAvIGIgOiBhID09ICtiKTtcclxuICAgICAgY2FzZSAnW29iamVjdCBEYXRlXSc6XHJcbiAgICAgIGNhc2UgJ1tvYmplY3QgQm9vbGVhbl0nOlxyXG4gICAgICAgIC8vIENvZXJjZSBkYXRlcyBhbmQgYm9vbGVhbnMgdG8gbnVtZXJpYyBwcmltaXRpdmUgdmFsdWVzLiBEYXRlcyBhcmUgY29tcGFyZWQgYnkgdGhlaXJcclxuICAgICAgICAvLyBtaWxsaXNlY29uZCByZXByZXNlbnRhdGlvbnMuIE5vdGUgdGhhdCBpbnZhbGlkIGRhdGVzIHdpdGggbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zXHJcbiAgICAgICAgLy8gb2YgYE5hTmAgYXJlIG5vdCBlcXVpdmFsZW50LlxyXG4gICAgICAgIHJldHVybiArYSA9PSArYjtcclxuICAgICAgLy8gUmVnRXhwcyBhcmUgY29tcGFyZWQgYnkgdGhlaXIgc291cmNlIHBhdHRlcm5zIGFuZCBmbGFncy5cclxuICAgICAgY2FzZSAnW29iamVjdCBSZWdFeHBdJzpcclxuICAgICAgICByZXR1cm4gYS5zb3VyY2UgPT0gYi5zb3VyY2UgJiZcclxuICAgICAgICAgICAgICAgYS5nbG9iYWwgPT0gYi5nbG9iYWwgJiZcclxuICAgICAgICAgICAgICAgYS5tdWx0aWxpbmUgPT0gYi5tdWx0aWxpbmUgJiZcclxuICAgICAgICAgICAgICAgYS5pZ25vcmVDYXNlID09IGIuaWdub3JlQ2FzZTtcclxuICAgIH1cclxuICAgIGlmICh0eXBlb2YgYSAhPSAnb2JqZWN0JyB8fCB0eXBlb2YgYiAhPSAnb2JqZWN0JykgcmV0dXJuIGZhbHNlO1xyXG4gICAgLy8gQXNzdW1lIGVxdWFsaXR5IGZvciBjeWNsaWMgc3RydWN0dXJlcy4gVGhlIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGN5Y2xpY1xyXG4gICAgLy8gc3RydWN0dXJlcyBpcyBhZGFwdGVkIGZyb20gRVMgNS4xIHNlY3Rpb24gMTUuMTIuMywgYWJzdHJhY3Qgb3BlcmF0aW9uIGBKT2AuXHJcbiAgICB2YXIgbGVuZ3RoID0gYVN0YWNrLmxlbmd0aDtcclxuICAgIHdoaWxlIChsZW5ndGgtLSkge1xyXG4gICAgICAvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2ZcclxuICAgICAgLy8gdW5pcXVlIG5lc3RlZCBzdHJ1Y3R1cmVzLlxyXG4gICAgICBpZiAoYVN0YWNrW2xlbmd0aF0gPT0gYSkgcmV0dXJuIGJTdGFja1tsZW5ndGhdID09IGI7XHJcbiAgICB9XHJcbiAgICAvLyBPYmplY3RzIHdpdGggZGlmZmVyZW50IGNvbnN0cnVjdG9ycyBhcmUgbm90IGVxdWl2YWxlbnQsIGJ1dCBgT2JqZWN0YHNcclxuICAgIC8vIGZyb20gZGlmZmVyZW50IGZyYW1lcyBhcmUuXHJcbiAgICB2YXIgYUN0b3IgPSBhLmNvbnN0cnVjdG9yLCBiQ3RvciA9IGIuY29uc3RydWN0b3I7XHJcbiAgICBpZiAoYUN0b3IgIT09IGJDdG9yICYmICEoXy5pc0Z1bmN0aW9uKGFDdG9yKSAmJiAoYUN0b3IgaW5zdGFuY2VvZiBhQ3RvcikgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfLmlzRnVuY3Rpb24oYkN0b3IpICYmIChiQ3RvciBpbnN0YW5jZW9mIGJDdG9yKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgJiYgKCdjb25zdHJ1Y3RvcicgaW4gYSAmJiAnY29uc3RydWN0b3InIGluIGIpKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIC8vIEFkZCB0aGUgZmlyc3Qgb2JqZWN0IHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cclxuICAgIGFTdGFjay5wdXNoKGEpO1xyXG4gICAgYlN0YWNrLnB1c2goYik7XHJcbiAgICB2YXIgc2l6ZSA9IDAsIHJlc3VsdCA9IHRydWU7XHJcbiAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgYW5kIGFycmF5cy5cclxuICAgIGlmIChjbGFzc05hbWUgPT0gJ1tvYmplY3QgQXJyYXldJykge1xyXG4gICAgICAvLyBDb21wYXJlIGFycmF5IGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeS5cclxuICAgICAgc2l6ZSA9IGEubGVuZ3RoO1xyXG4gICAgICByZXN1bHQgPSBzaXplID09IGIubGVuZ3RoO1xyXG4gICAgICBpZiAocmVzdWx0KSB7XHJcbiAgICAgICAgLy8gRGVlcCBjb21wYXJlIHRoZSBjb250ZW50cywgaWdub3Jpbmcgbm9uLW51bWVyaWMgcHJvcGVydGllcy5cclxuICAgICAgICB3aGlsZSAoc2l6ZS0tKSB7XHJcbiAgICAgICAgICBpZiAoIShyZXN1bHQgPSBlcShhW3NpemVdLCBiW3NpemVdLCBhU3RhY2ssIGJTdGFjaykpKSBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIERlZXAgY29tcGFyZSBvYmplY3RzLlxyXG4gICAgICBmb3IgKHZhciBrZXkgaW4gYSkge1xyXG4gICAgICAgIGlmIChfLmhhcyhhLCBrZXkpKSB7XHJcbiAgICAgICAgICAvLyBDb3VudCB0aGUgZXhwZWN0ZWQgbnVtYmVyIG9mIHByb3BlcnRpZXMuXHJcbiAgICAgICAgICBzaXplKys7XHJcbiAgICAgICAgICAvLyBEZWVwIGNvbXBhcmUgZWFjaCBtZW1iZXIuXHJcbiAgICAgICAgICBpZiAoIShyZXN1bHQgPSBfLmhhcyhiLCBrZXkpICYmIGVxKGFba2V5XSwgYltrZXldLCBhU3RhY2ssIGJTdGFjaykpKSBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gRW5zdXJlIHRoYXQgYm90aCBvYmplY3RzIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIHByb3BlcnRpZXMuXHJcbiAgICAgIGlmIChyZXN1bHQpIHtcclxuICAgICAgICBmb3IgKGtleSBpbiBiKSB7XHJcbiAgICAgICAgICBpZiAoXy5oYXMoYiwga2V5KSAmJiAhKHNpemUtLSkpIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXN1bHQgPSAhc2l6ZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gUmVtb3ZlIHRoZSBmaXJzdCBvYmplY3QgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXHJcbiAgICBhU3RhY2sucG9wKCk7XHJcbiAgICBiU3RhY2sucG9wKCk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG4gIH07XHJcblxyXG4gIC8vIFBlcmZvcm0gYSBkZWVwIGNvbXBhcmlzb24gdG8gY2hlY2sgaWYgdHdvIG9iamVjdHMgYXJlIGVxdWFsLlxyXG4gIF8uaXNFcXVhbCA9IGZ1bmN0aW9uKGEsIGIpIHtcclxuICAgIHJldHVybiBlcShhLCBiLCBbXSwgW10pO1xyXG4gIH07XHJcblxyXG4gIC8vIElzIGEgZ2l2ZW4gYXJyYXksIHN0cmluZywgb3Igb2JqZWN0IGVtcHR5P1xyXG4gIC8vIEFuIFwiZW1wdHlcIiBvYmplY3QgaGFzIG5vIGVudW1lcmFibGUgb3duLXByb3BlcnRpZXMuXHJcbiAgXy5pc0VtcHR5ID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKF8uaXNBcnJheShvYmopIHx8IF8uaXNTdHJpbmcob2JqKSkgcmV0dXJuIG9iai5sZW5ndGggPT09IDA7XHJcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSByZXR1cm4gZmFsc2U7XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9O1xyXG5cclxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgRE9NIGVsZW1lbnQ/XHJcbiAgXy5pc0VsZW1lbnQgPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHJldHVybiAhIShvYmogJiYgb2JqLm5vZGVUeXBlID09PSAxKTtcclxuICB9O1xyXG5cclxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGFuIGFycmF5P1xyXG4gIC8vIERlbGVnYXRlcyB0byBFQ01BNSdzIG5hdGl2ZSBBcnJheS5pc0FycmF5XHJcbiAgXy5pc0FycmF5ID0gbmF0aXZlSXNBcnJheSB8fCBmdW5jdGlvbihvYmopIHtcclxuICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgQXJyYXldJztcclxuICB9O1xyXG5cclxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIGFuIG9iamVjdD9cclxuICBfLmlzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICByZXR1cm4gb2JqID09PSBPYmplY3Qob2JqKTtcclxuICB9O1xyXG5cclxuICAvLyBBZGQgc29tZSBpc1R5cGUgbWV0aG9kczogaXNBcmd1bWVudHMsIGlzRnVuY3Rpb24sIGlzU3RyaW5nLCBpc051bWJlciwgaXNEYXRlLCBpc1JlZ0V4cC5cclxuICBlYWNoKFsnQXJndW1lbnRzJywgJ0Z1bmN0aW9uJywgJ1N0cmluZycsICdOdW1iZXInLCAnRGF0ZScsICdSZWdFeHAnXSwgZnVuY3Rpb24obmFtZSkge1xyXG4gICAgX1snaXMnICsgbmFtZV0gPSBmdW5jdGlvbihvYmopIHtcclxuICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PSAnW29iamVjdCAnICsgbmFtZSArICddJztcclxuICAgIH07XHJcbiAgfSk7XHJcblxyXG4gIC8vIERlZmluZSBhIGZhbGxiYWNrIHZlcnNpb24gb2YgdGhlIG1ldGhvZCBpbiBicm93c2VycyAoYWhlbSwgSUUpLCB3aGVyZVxyXG4gIC8vIHRoZXJlIGlzbid0IGFueSBpbnNwZWN0YWJsZSBcIkFyZ3VtZW50c1wiIHR5cGUuXHJcbiAgaWYgKCFfLmlzQXJndW1lbnRzKGFyZ3VtZW50cykpIHtcclxuICAgIF8uaXNBcmd1bWVudHMgPSBmdW5jdGlvbihvYmopIHtcclxuICAgICAgcmV0dXJuICEhKG9iaiAmJiBfLmhhcyhvYmosICdjYWxsZWUnKSk7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLy8gT3B0aW1pemUgYGlzRnVuY3Rpb25gIGlmIGFwcHJvcHJpYXRlLlxyXG4gIGlmICh0eXBlb2YgKC8uLykgIT09ICdmdW5jdGlvbicpIHtcclxuICAgIF8uaXNGdW5jdGlvbiA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJztcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyBJcyBhIGdpdmVuIG9iamVjdCBhIGZpbml0ZSBudW1iZXI/XHJcbiAgXy5pc0Zpbml0ZSA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgcmV0dXJuIGlzRmluaXRlKG9iaikgJiYgIWlzTmFOKHBhcnNlRmxvYXQob2JqKSk7XHJcbiAgfTtcclxuXHJcbiAgLy8gSXMgdGhlIGdpdmVuIHZhbHVlIGBOYU5gPyAoTmFOIGlzIHRoZSBvbmx5IG51bWJlciB3aGljaCBkb2VzIG5vdCBlcXVhbCBpdHNlbGYpLlxyXG4gIF8uaXNOYU4gPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHJldHVybiBfLmlzTnVtYmVyKG9iaikgJiYgb2JqICE9ICtvYmo7XHJcbiAgfTtcclxuXHJcbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIGJvb2xlYW4/XHJcbiAgXy5pc0Jvb2xlYW4gPSBmdW5jdGlvbihvYmopIHtcclxuICAgIHJldHVybiBvYmogPT09IHRydWUgfHwgb2JqID09PSBmYWxzZSB8fCB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgQm9vbGVhbl0nO1xyXG4gIH07XHJcblxyXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgZXF1YWwgdG8gbnVsbD9cclxuICBfLmlzTnVsbCA9IGZ1bmN0aW9uKG9iaikge1xyXG4gICAgcmV0dXJuIG9iaiA9PT0gbnVsbDtcclxuICB9O1xyXG5cclxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIHVuZGVmaW5lZD9cclxuICBfLmlzVW5kZWZpbmVkID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICByZXR1cm4gb2JqID09PSB2b2lkIDA7XHJcbiAgfTtcclxuXHJcbiAgLy8gU2hvcnRjdXQgZnVuY3Rpb24gZm9yIGNoZWNraW5nIGlmIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBwcm9wZXJ0eSBkaXJlY3RseVxyXG4gIC8vIG9uIGl0c2VsZiAoaW4gb3RoZXIgd29yZHMsIG5vdCBvbiBhIHByb3RvdHlwZSkuXHJcbiAgXy5oYXMgPSBmdW5jdGlvbihvYmosIGtleSkge1xyXG4gICAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpO1xyXG4gIH07XHJcblxyXG4gIC8vIFV0aWxpdHkgRnVuY3Rpb25zXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS1cclxuXHJcbiAgLy8gUnVuIFVuZGVyc2NvcmUuanMgaW4gKm5vQ29uZmxpY3QqIG1vZGUsIHJldHVybmluZyB0aGUgYF9gIHZhcmlhYmxlIHRvIGl0c1xyXG4gIC8vIHByZXZpb3VzIG93bmVyLiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cclxuICBfLm5vQ29uZmxpY3QgPSBmdW5jdGlvbigpIHtcclxuICAgIHJvb3QuXyA9IHByZXZpb3VzVW5kZXJzY29yZTtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH07XHJcblxyXG4gIC8vIEtlZXAgdGhlIGlkZW50aXR5IGZ1bmN0aW9uIGFyb3VuZCBmb3IgZGVmYXVsdCBpdGVyYXRvcnMuXHJcbiAgXy5pZGVudGl0eSA9IGZ1bmN0aW9uKHZhbHVlKSB7XHJcbiAgICByZXR1cm4gdmFsdWU7XHJcbiAgfTtcclxuXHJcbiAgXy5jb25zdGFudCA9IGZ1bmN0aW9uKHZhbHVlKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xyXG4gICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG4gIH07XHJcblxyXG4gIF8ucHJvcGVydHkgPSBmdW5jdGlvbihrZXkpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcclxuICAgICAgcmV0dXJuIG9ialtrZXldO1xyXG4gICAgfTtcclxuICB9O1xyXG5cclxuICAvLyBSZXR1cm5zIGEgcHJlZGljYXRlIGZvciBjaGVja2luZyB3aGV0aGVyIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBzZXQgb2YgYGtleTp2YWx1ZWAgcGFpcnMuXHJcbiAgXy5tYXRjaGVzID0gZnVuY3Rpb24oYXR0cnMpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcclxuICAgICAgaWYgKG9iaiA9PT0gYXR0cnMpIHJldHVybiB0cnVlOyAvL2F2b2lkIGNvbXBhcmluZyBhbiBvYmplY3QgdG8gaXRzZWxmLlxyXG4gICAgICBmb3IgKHZhciBrZXkgaW4gYXR0cnMpIHtcclxuICAgICAgICBpZiAoYXR0cnNba2V5XSAhPT0gb2JqW2tleV0pXHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcbiAgfTtcclxuXHJcbiAgLy8gUnVuIGEgZnVuY3Rpb24gKipuKiogdGltZXMuXHJcbiAgXy50aW1lcyA9IGZ1bmN0aW9uKG4sIGl0ZXJhdG9yLCBjb250ZXh0KSB7XHJcbiAgICB2YXIgYWNjdW0gPSBBcnJheShNYXRoLm1heCgwLCBuKSk7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykgYWNjdW1baV0gPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIGkpO1xyXG4gICAgcmV0dXJuIGFjY3VtO1xyXG4gIH07XHJcblxyXG4gIC8vIFJldHVybiBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIGFuZCBtYXggKGluY2x1c2l2ZSkuXHJcbiAgXy5yYW5kb20gPSBmdW5jdGlvbihtaW4sIG1heCkge1xyXG4gICAgaWYgKG1heCA9PSBudWxsKSB7XHJcbiAgICAgIG1heCA9IG1pbjtcclxuICAgICAgbWluID0gMDtcclxuICAgIH1cclxuICAgIHJldHVybiBtaW4gKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpO1xyXG4gIH07XHJcblxyXG4gIC8vIEEgKHBvc3NpYmx5IGZhc3Rlcikgd2F5IHRvIGdldCB0aGUgY3VycmVudCB0aW1lc3RhbXAgYXMgYW4gaW50ZWdlci5cclxuICBfLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7IH07XHJcblxyXG4gIC8vIExpc3Qgb2YgSFRNTCBlbnRpdGllcyBmb3IgZXNjYXBpbmcuXHJcbiAgdmFyIGVudGl0eU1hcCA9IHtcclxuICAgIGVzY2FwZToge1xyXG4gICAgICAnJic6ICcmYW1wOycsXHJcbiAgICAgICc8JzogJyZsdDsnLFxyXG4gICAgICAnPic6ICcmZ3Q7JyxcclxuICAgICAgJ1wiJzogJyZxdW90OycsXHJcbiAgICAgIFwiJ1wiOiAnJiN4Mjc7J1xyXG4gICAgfVxyXG4gIH07XHJcbiAgZW50aXR5TWFwLnVuZXNjYXBlID0gXy5pbnZlcnQoZW50aXR5TWFwLmVzY2FwZSk7XHJcblxyXG4gIC8vIFJlZ2V4ZXMgY29udGFpbmluZyB0aGUga2V5cyBhbmQgdmFsdWVzIGxpc3RlZCBpbW1lZGlhdGVseSBhYm92ZS5cclxuICB2YXIgZW50aXR5UmVnZXhlcyA9IHtcclxuICAgIGVzY2FwZTogICBuZXcgUmVnRXhwKCdbJyArIF8ua2V5cyhlbnRpdHlNYXAuZXNjYXBlKS5qb2luKCcnKSArICddJywgJ2cnKSxcclxuICAgIHVuZXNjYXBlOiBuZXcgUmVnRXhwKCcoJyArIF8ua2V5cyhlbnRpdHlNYXAudW5lc2NhcGUpLmpvaW4oJ3wnKSArICcpJywgJ2cnKVxyXG4gIH07XHJcblxyXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cclxuICBfLmVhY2goWydlc2NhcGUnLCAndW5lc2NhcGUnXSwgZnVuY3Rpb24obWV0aG9kKSB7XHJcbiAgICBfW21ldGhvZF0gPSBmdW5jdGlvbihzdHJpbmcpIHtcclxuICAgICAgaWYgKHN0cmluZyA9PSBudWxsKSByZXR1cm4gJyc7XHJcbiAgICAgIHJldHVybiAoJycgKyBzdHJpbmcpLnJlcGxhY2UoZW50aXR5UmVnZXhlc1ttZXRob2RdLCBmdW5jdGlvbihtYXRjaCkge1xyXG4gICAgICAgIHJldHVybiBlbnRpdHlNYXBbbWV0aG9kXVttYXRjaF07XHJcbiAgICAgIH0pO1xyXG4gICAgfTtcclxuICB9KTtcclxuXHJcbiAgLy8gSWYgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBgcHJvcGVydHlgIGlzIGEgZnVuY3Rpb24gdGhlbiBpbnZva2UgaXQgd2l0aCB0aGVcclxuICAvLyBgb2JqZWN0YCBhcyBjb250ZXh0OyBvdGhlcndpc2UsIHJldHVybiBpdC5cclxuICBfLnJlc3VsdCA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHtcclxuICAgIGlmIChvYmplY3QgPT0gbnVsbCkgcmV0dXJuIHZvaWQgMDtcclxuICAgIHZhciB2YWx1ZSA9IG9iamVjdFtwcm9wZXJ0eV07XHJcbiAgICByZXR1cm4gXy5pc0Z1bmN0aW9uKHZhbHVlKSA/IHZhbHVlLmNhbGwob2JqZWN0KSA6IHZhbHVlO1xyXG4gIH07XHJcblxyXG4gIC8vIEFkZCB5b3VyIG93biBjdXN0b20gZnVuY3Rpb25zIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cclxuICBfLm1peGluID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICBlYWNoKF8uZnVuY3Rpb25zKG9iaiksIGZ1bmN0aW9uKG5hbWUpIHtcclxuICAgICAgdmFyIGZ1bmMgPSBfW25hbWVdID0gb2JqW25hbWVdO1xyXG4gICAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHZhciBhcmdzID0gW3RoaXMuX3dyYXBwZWRdO1xyXG4gICAgICAgIHB1c2guYXBwbHkoYXJncywgYXJndW1lbnRzKTtcclxuICAgICAgICByZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgZnVuYy5hcHBseShfLCBhcmdzKSk7XHJcbiAgICAgIH07XHJcbiAgICB9KTtcclxuICB9O1xyXG5cclxuICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBpbnRlZ2VyIGlkICh1bmlxdWUgd2l0aGluIHRoZSBlbnRpcmUgY2xpZW50IHNlc3Npb24pLlxyXG4gIC8vIFVzZWZ1bCBmb3IgdGVtcG9yYXJ5IERPTSBpZHMuXHJcbiAgdmFyIGlkQ291bnRlciA9IDA7XHJcbiAgXy51bmlxdWVJZCA9IGZ1bmN0aW9uKHByZWZpeCkge1xyXG4gICAgdmFyIGlkID0gKytpZENvdW50ZXIgKyAnJztcclxuICAgIHJldHVybiBwcmVmaXggPyBwcmVmaXggKyBpZCA6IGlkO1xyXG4gIH07XHJcblxyXG4gIC8vIEJ5IGRlZmF1bHQsIFVuZGVyc2NvcmUgdXNlcyBFUkItc3R5bGUgdGVtcGxhdGUgZGVsaW1pdGVycywgY2hhbmdlIHRoZVxyXG4gIC8vIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cclxuICBfLnRlbXBsYXRlU2V0dGluZ3MgPSB7XHJcbiAgICBldmFsdWF0ZSAgICA6IC88JShbXFxzXFxTXSs/KSU+L2csXHJcbiAgICBpbnRlcnBvbGF0ZSA6IC88JT0oW1xcc1xcU10rPyklPi9nLFxyXG4gICAgZXNjYXBlICAgICAgOiAvPCUtKFtcXHNcXFNdKz8pJT4vZ1xyXG4gIH07XHJcblxyXG4gIC8vIFdoZW4gY3VzdG9taXppbmcgYHRlbXBsYXRlU2V0dGluZ3NgLCBpZiB5b3UgZG9uJ3Qgd2FudCB0byBkZWZpbmUgYW5cclxuICAvLyBpbnRlcnBvbGF0aW9uLCBldmFsdWF0aW9uIG9yIGVzY2FwaW5nIHJlZ2V4LCB3ZSBuZWVkIG9uZSB0aGF0IGlzXHJcbiAgLy8gZ3VhcmFudGVlZCBub3QgdG8gbWF0Y2guXHJcbiAgdmFyIG5vTWF0Y2ggPSAvKC4pXi87XHJcblxyXG4gIC8vIENlcnRhaW4gY2hhcmFjdGVycyBuZWVkIHRvIGJlIGVzY2FwZWQgc28gdGhhdCB0aGV5IGNhbiBiZSBwdXQgaW50byBhXHJcbiAgLy8gc3RyaW5nIGxpdGVyYWwuXHJcbiAgdmFyIGVzY2FwZXMgPSB7XHJcbiAgICBcIidcIjogICAgICBcIidcIixcclxuICAgICdcXFxcJzogICAgICdcXFxcJyxcclxuICAgICdcXHInOiAgICAgJ3InLFxyXG4gICAgJ1xcbic6ICAgICAnbicsXHJcbiAgICAnXFx0JzogICAgICd0JyxcclxuICAgICdcXHUyMDI4JzogJ3UyMDI4JyxcclxuICAgICdcXHUyMDI5JzogJ3UyMDI5J1xyXG4gIH07XHJcblxyXG4gIHZhciBlc2NhcGVyID0gL1xcXFx8J3xcXHJ8XFxufFxcdHxcXHUyMDI4fFxcdTIwMjkvZztcclxuXHJcbiAgLy8gSmF2YVNjcmlwdCBtaWNyby10ZW1wbGF0aW5nLCBzaW1pbGFyIHRvIEpvaG4gUmVzaWcncyBpbXBsZW1lbnRhdGlvbi5cclxuICAvLyBVbmRlcnNjb3JlIHRlbXBsYXRpbmcgaGFuZGxlcyBhcmJpdHJhcnkgZGVsaW1pdGVycywgcHJlc2VydmVzIHdoaXRlc3BhY2UsXHJcbiAgLy8gYW5kIGNvcnJlY3RseSBlc2NhcGVzIHF1b3RlcyB3aXRoaW4gaW50ZXJwb2xhdGVkIGNvZGUuXHJcbiAgXy50ZW1wbGF0ZSA9IGZ1bmN0aW9uKHRleHQsIGRhdGEsIHNldHRpbmdzKSB7XHJcbiAgICB2YXIgcmVuZGVyO1xyXG4gICAgc2V0dGluZ3MgPSBfLmRlZmF1bHRzKHt9LCBzZXR0aW5ncywgXy50ZW1wbGF0ZVNldHRpbmdzKTtcclxuXHJcbiAgICAvLyBDb21iaW5lIGRlbGltaXRlcnMgaW50byBvbmUgcmVndWxhciBleHByZXNzaW9uIHZpYSBhbHRlcm5hdGlvbi5cclxuICAgIHZhciBtYXRjaGVyID0gbmV3IFJlZ0V4cChbXHJcbiAgICAgIChzZXR0aW5ncy5lc2NhcGUgfHwgbm9NYXRjaCkuc291cmNlLFxyXG4gICAgICAoc2V0dGluZ3MuaW50ZXJwb2xhdGUgfHwgbm9NYXRjaCkuc291cmNlLFxyXG4gICAgICAoc2V0dGluZ3MuZXZhbHVhdGUgfHwgbm9NYXRjaCkuc291cmNlXHJcbiAgICBdLmpvaW4oJ3wnKSArICd8JCcsICdnJyk7XHJcblxyXG4gICAgLy8gQ29tcGlsZSB0aGUgdGVtcGxhdGUgc291cmNlLCBlc2NhcGluZyBzdHJpbmcgbGl0ZXJhbHMgYXBwcm9wcmlhdGVseS5cclxuICAgIHZhciBpbmRleCA9IDA7XHJcbiAgICB2YXIgc291cmNlID0gXCJfX3ArPSdcIjtcclxuICAgIHRleHQucmVwbGFjZShtYXRjaGVyLCBmdW5jdGlvbihtYXRjaCwgZXNjYXBlLCBpbnRlcnBvbGF0ZSwgZXZhbHVhdGUsIG9mZnNldCkge1xyXG4gICAgICBzb3VyY2UgKz0gdGV4dC5zbGljZShpbmRleCwgb2Zmc2V0KVxyXG4gICAgICAgIC5yZXBsYWNlKGVzY2FwZXIsIGZ1bmN0aW9uKG1hdGNoKSB7IHJldHVybiAnXFxcXCcgKyBlc2NhcGVzW21hdGNoXTsgfSk7XHJcblxyXG4gICAgICBpZiAoZXNjYXBlKSB7XHJcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBlc2NhcGUgKyBcIikpPT1udWxsPycnOl8uZXNjYXBlKF9fdCkpK1xcbidcIjtcclxuICAgICAgfVxyXG4gICAgICBpZiAoaW50ZXJwb2xhdGUpIHtcclxuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGludGVycG9sYXRlICsgXCIpKT09bnVsbD8nJzpfX3QpK1xcbidcIjtcclxuICAgICAgfVxyXG4gICAgICBpZiAoZXZhbHVhdGUpIHtcclxuICAgICAgICBzb3VyY2UgKz0gXCInO1xcblwiICsgZXZhbHVhdGUgKyBcIlxcbl9fcCs9J1wiO1xyXG4gICAgICB9XHJcbiAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xyXG4gICAgICByZXR1cm4gbWF0Y2g7XHJcbiAgICB9KTtcclxuICAgIHNvdXJjZSArPSBcIic7XFxuXCI7XHJcblxyXG4gICAgLy8gSWYgYSB2YXJpYWJsZSBpcyBub3Qgc3BlY2lmaWVkLCBwbGFjZSBkYXRhIHZhbHVlcyBpbiBsb2NhbCBzY29wZS5cclxuICAgIGlmICghc2V0dGluZ3MudmFyaWFibGUpIHNvdXJjZSA9ICd3aXRoKG9ianx8e30pe1xcbicgKyBzb3VyY2UgKyAnfVxcbic7XHJcblxyXG4gICAgc291cmNlID0gXCJ2YXIgX190LF9fcD0nJyxfX2o9QXJyYXkucHJvdG90eXBlLmpvaW4sXCIgK1xyXG4gICAgICBcInByaW50PWZ1bmN0aW9uKCl7X19wKz1fX2ouY2FsbChhcmd1bWVudHMsJycpO307XFxuXCIgK1xyXG4gICAgICBzb3VyY2UgKyBcInJldHVybiBfX3A7XFxuXCI7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgcmVuZGVyID0gbmV3IEZ1bmN0aW9uKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonLCAnXycsIHNvdXJjZSk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIGUuc291cmNlID0gc291cmNlO1xyXG4gICAgICB0aHJvdyBlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChkYXRhKSByZXR1cm4gcmVuZGVyKGRhdGEsIF8pO1xyXG4gICAgdmFyIHRlbXBsYXRlID0gZnVuY3Rpb24oZGF0YSkge1xyXG4gICAgICByZXR1cm4gcmVuZGVyLmNhbGwodGhpcywgZGF0YSwgXyk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uIHNvdXJjZSBhcyBhIGNvbnZlbmllbmNlIGZvciBwcmVjb21waWxhdGlvbi5cclxuICAgIHRlbXBsYXRlLnNvdXJjZSA9ICdmdW5jdGlvbignICsgKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonKSArICcpe1xcbicgKyBzb3VyY2UgKyAnfSc7XHJcblxyXG4gICAgcmV0dXJuIHRlbXBsYXRlO1xyXG4gIH07XHJcblxyXG4gIC8vIEFkZCBhIFwiY2hhaW5cIiBmdW5jdGlvbiwgd2hpY2ggd2lsbCBkZWxlZ2F0ZSB0byB0aGUgd3JhcHBlci5cclxuICBfLmNoYWluID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICByZXR1cm4gXyhvYmopLmNoYWluKCk7XHJcbiAgfTtcclxuXHJcbiAgLy8gT09QXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXHJcbiAgLy8gSWYgVW5kZXJzY29yZSBpcyBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgaXQgcmV0dXJucyBhIHdyYXBwZWQgb2JqZWN0IHRoYXRcclxuICAvLyBjYW4gYmUgdXNlZCBPTy1zdHlsZS4gVGhpcyB3cmFwcGVyIGhvbGRzIGFsdGVyZWQgdmVyc2lvbnMgb2YgYWxsIHRoZVxyXG4gIC8vIHVuZGVyc2NvcmUgZnVuY3Rpb25zLiBXcmFwcGVkIG9iamVjdHMgbWF5IGJlIGNoYWluZWQuXHJcblxyXG4gIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjb250aW51ZSBjaGFpbmluZyBpbnRlcm1lZGlhdGUgcmVzdWx0cy5cclxuICB2YXIgcmVzdWx0ID0gZnVuY3Rpb24ob2JqKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fY2hhaW4gPyBfKG9iaikuY2hhaW4oKSA6IG9iajtcclxuICB9O1xyXG5cclxuICAvLyBBZGQgYWxsIG9mIHRoZSBVbmRlcnNjb3JlIGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlciBvYmplY3QuXHJcbiAgXy5taXhpbihfKTtcclxuXHJcbiAgLy8gQWRkIGFsbCBtdXRhdG9yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cclxuICBlYWNoKFsncG9wJywgJ3B1c2gnLCAncmV2ZXJzZScsICdzaGlmdCcsICdzb3J0JywgJ3NwbGljZScsICd1bnNoaWZ0J10sIGZ1bmN0aW9uKG5hbWUpIHtcclxuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xyXG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcclxuICAgICAgdmFyIG9iaiA9IHRoaXMuX3dyYXBwZWQ7XHJcbiAgICAgIG1ldGhvZC5hcHBseShvYmosIGFyZ3VtZW50cyk7XHJcbiAgICAgIGlmICgobmFtZSA9PSAnc2hpZnQnIHx8IG5hbWUgPT0gJ3NwbGljZScpICYmIG9iai5sZW5ndGggPT09IDApIGRlbGV0ZSBvYmpbMF07XHJcbiAgICAgIHJldHVybiByZXN1bHQuY2FsbCh0aGlzLCBvYmopO1xyXG4gICAgfTtcclxuICB9KTtcclxuXHJcbiAgLy8gQWRkIGFsbCBhY2Nlc3NvciBBcnJheSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIuXHJcbiAgZWFjaChbJ2NvbmNhdCcsICdqb2luJywgJ3NsaWNlJ10sIGZ1bmN0aW9uKG5hbWUpIHtcclxuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xyXG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcclxuICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIG1ldGhvZC5hcHBseSh0aGlzLl93cmFwcGVkLCBhcmd1bWVudHMpKTtcclxuICAgIH07XHJcbiAgfSk7XHJcblxyXG4gIF8uZXh0ZW5kKF8ucHJvdG90eXBlLCB7XHJcblxyXG4gICAgLy8gU3RhcnQgY2hhaW5pbmcgYSB3cmFwcGVkIFVuZGVyc2NvcmUgb2JqZWN0LlxyXG4gICAgY2hhaW46IGZ1bmN0aW9uKCkge1xyXG4gICAgICB0aGlzLl9jaGFpbiA9IHRydWU7XHJcbiAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfSxcclxuXHJcbiAgICAvLyBFeHRyYWN0cyB0aGUgcmVzdWx0IGZyb20gYSB3cmFwcGVkIGFuZCBjaGFpbmVkIG9iamVjdC5cclxuICAgIHZhbHVlOiBmdW5jdGlvbigpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBwZWQ7XHJcbiAgICB9XHJcblxyXG4gIH0pO1xyXG5cclxuICAvLyBBTUQgcmVnaXN0cmF0aW9uIGhhcHBlbnMgYXQgdGhlIGVuZCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIEFNRCBsb2FkZXJzXHJcbiAgLy8gdGhhdCBtYXkgbm90IGVuZm9yY2UgbmV4dC10dXJuIHNlbWFudGljcyBvbiBtb2R1bGVzLiBFdmVuIHRob3VnaCBnZW5lcmFsXHJcbiAgLy8gcHJhY3RpY2UgZm9yIEFNRCByZWdpc3RyYXRpb24gaXMgdG8gYmUgYW5vbnltb3VzLCB1bmRlcnNjb3JlIHJlZ2lzdGVyc1xyXG4gIC8vIGFzIGEgbmFtZWQgbW9kdWxlIGJlY2F1c2UsIGxpa2UgalF1ZXJ5LCBpdCBpcyBhIGJhc2UgbGlicmFyeSB0aGF0IGlzXHJcbiAgLy8gcG9wdWxhciBlbm91Z2ggdG8gYmUgYnVuZGxlZCBpbiBhIHRoaXJkIHBhcnR5IGxpYiwgYnV0IG5vdCBiZSBwYXJ0IG9mXHJcbiAgLy8gYW4gQU1EIGxvYWQgcmVxdWVzdC4gVGhvc2UgY2FzZXMgY291bGQgZ2VuZXJhdGUgYW4gZXJyb3Igd2hlbiBhblxyXG4gIC8vIGFub255bW91cyBkZWZpbmUoKSBpcyBjYWxsZWQgb3V0c2lkZSBvZiBhIGxvYWRlciByZXF1ZXN0LlxyXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcclxuICAgIGRlZmluZSgndW5kZXJzY29yZScsIFtdLCBmdW5jdGlvbigpIHtcclxuICAgICAgcmV0dXJuIF87XHJcbiAgICB9KTtcclxuICB9XHJcbn0pLmNhbGwodGhpcyk7XHJcbiJdLCJmaWxlIjoidW5kZXJzY29yZS5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/underscore.min.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/underscore.min.js new file mode 100644 index 000000000..123b8d6dd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/underscore.min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-(1/0),u=-(1/0);return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t,r){t=E(t);var e=[],u=[];return A(n,function(n){(t.call(r,n)?e:u).push(n)}),[e,u]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u),e=u=null):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o,c=function(){var l=j.now()-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,a=j.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u),i=u=null),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return j.partial(t,n)},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=function(n){if(!j.isObject(n))return[];if(w)return w(n);var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)void 0===n[r]&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return void 0===n},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.constant=function(n){return function(){return n}},j.property=function(n){return function(t){return t[n]}},j.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},j.now=Date.now||function(){return(new Date).getTime()};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};T.unescape=j.invert(T.escape);var I={escape:new RegExp("["+j.keys(T.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(T.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(I[n],function(t){return T[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return j})}).call(this); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/uri.js b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/uri.js new file mode 100644 index 000000000..097993cc7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Azure.MediaServices/Scripts/Lib/uri.js @@ -0,0 +1,55 @@ +/*! URI.js v1.12.1 http://medialize.github.com/URI.js/ */ +/* build contains: URI.js */ +(function(p,r){"object"===typeof exports?module.exports=r(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"===typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],r):p.URI=r(p.punycode,p.IPv6,p.SecondLevelDomains,p)})(this,function(p,r,v,w){function e(a,b){if(!(this instanceof e))return new e(a,b);void 0===a&&(a="undefined"!==typeof location?location.href+"":"");this.href(a);return void 0!==b?this.absoluteTo(b):this}function s(a){return a.replace(/([.*+?^=!:${}()|[\]\/\\])/g, +"\\$1")}function y(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function l(a){return"Array"===y(a)}function x(a,b){var c,e;if(l(b)){c=0;for(e=b.length;c]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/ig;e.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/};e.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"};e.invalid_hostname_characters= +/[^a-zA-Z0-9\.-]/;e.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"};e.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:e.domAttributes[b]}};e.encode=z;e.decode=decodeURIComponent;e.iso8859=function(){e.encode=escape;e.decode=unescape};e.unicode=function(){e.encode=z;e.decode=decodeURIComponent};e.characters= +{pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/ig,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}};e.encodeQuery= +function(a,b){var c=e.encode(a+"");void 0===b&&(b=e.escapeQuerySpace);return b?c.replace(/%20/g,"+"):c};e.decodeQuery=function(a,b){a+="";void 0===b&&(b=e.escapeQuerySpace);try{return e.decode(b?a.replace(/\+/g,"%20"):a)}catch(c){return a}};e.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;be)return a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"";if("/"!==a.charAt(e)||"/"!==b.charAt(e))e=a.substring(0,e).lastIndexOf("/");return a.substring(0,e+1)};e.withinString=function(a,b,c){c||(c={});var g=c.start||e.findUri.start,d=c.end||e.findUri.end,k=c.trim||e.findUri.trim,h=/[a-z0-9-]=["']?$/i;for(g.lastIndex=0;;){var n=g.exec(a);if(!n)break;n=n.index;if(c.ignoreHtml){var l= +a.slice(Math.max(n-3,0),n);if(l&&h.test(l))continue}var l=n+a.slice(n).search(d),m=a.slice(n,l).replace(k,"");c.ignore&&c.ignore.test(m)||(l=n+m.length,m=b(m,n,l,a),a=a.slice(0,n)+m+a.slice(l),g.lastIndex=n+m.length)}g.lastIndex=0;return a};e.ensureValidHostname=function(a){if(a.match(e.invalid_hostname_characters)){if(!p)throw new TypeError("Hostname '"+a+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(p.toASCII(a).match(e.invalid_hostname_characters))throw new TypeError("Hostname '"+ +a+"' contains characters other than [A-Z0-9.-]");}};e.noConflict=function(a){if(a)return a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),r&&"function"==typeof r.noConflict&&(a.IPv6=r.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a;w.URI===this&&(w.URI=C);return this};d.build=function(a){if(!0===a)this._deferred_build=!0;else if(void 0=== +a||this._deferred_build)this._string=e.build(this._parts),this._deferred_build=!1;return this};d.clone=function(){return new e(this)};d.valueOf=d.toString=function(){return this.build(!1)._string};q={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"};u=function(a){return function(b,c){if(void 0===b)return this._parts[a]||"";this._parts[a]=b||null;this.build(!c);return this}};for(m in q)d[m]=u(q[m]);q={query:"?",fragment:"#"};u=function(a,b){return function(c, +e){if(void 0===c)return this._parts[a]||"";null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1)));this._parts[a]=c;this.build(!e);return this}};for(m in q)d[m]=u(m,q[m]);q={search:["?","query"],hash:["#","fragment"]};u=function(a,b){return function(c,e){var d=this[a](c,e);return"string"===typeof d&&d.length?b+d:d}};for(m in q)d[m]=u(q[m][1],q[m][0]);d.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}this._parts.path=a?e.recodePath(a): +"/";this.build(!b);return this};d.path=d.pathname;d.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="";this._parts=e._parts();var g=a instanceof e,d="object"===typeof a&&(a.hostname||a.path||a.pathname);a.nodeName&&(d=e.getDomAttribute(a),a=a[d]||"",d=!1);!g&&d&&void 0!==a.pathname&&(a=a.toString());if("string"===typeof a)this._parts=e.parse(a,this._parts);else if(g||d)for(c in g=g?a._parts:a,g)t.call(this._parts,c)&&(this._parts[c]=g[c]);else throw new TypeError("invalid input"); +this.build(!b);return this};d.is=function(a){var b=!1,c=!1,d=!1,f=!1,k=!1,h=!1,l=!1,m=!this._parts.urn;this._parts.hostname&&(m=!1,c=e.ip4_expression.test(this._parts.hostname),d=e.ip6_expression.test(this._parts.hostname),b=c||d,k=(f=!b)&&v&&v.has(this._parts.hostname),h=f&&e.idn_expression.test(this._parts.hostname),l=f&&e.punycode_expression.test(this._parts.hostname));switch(a.toLowerCase()){case "relative":return m;case "absolute":return!m;case "domain":case "name":return f;case "sld":return k; +case "ip":return b;case "ip4":case "ipv4":case "inet4":return c;case "ip6":case "ipv6":case "inet6":return d;case "idn":return h;case "url":return!this._parts.urn;case "urn":return!!this._parts.urn;case "punycode":return l}return null};var D=d.protocol,E=d.port,F=d.hostname;d.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\/\/)?$/,""),!a.match(e.protocol_expression)))throw new TypeError("Protocol '"+a+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return D.call(this, +a,b)};d.scheme=d.protocol;d.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port '"+a+"' contains characters other than [0-9]");return E.call(this,a,b)};d.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};e.parseHost(a,c);a=c.hostname}return F.call(this,a,b)};d.host=function(a,b){if(this._parts.urn)return void 0===a?"":this; +if(void 0===a)return this._parts.hostname?e.buildHost(this._parts):"";e.parseHost(a,this._parts);this.build(!b);return this};d.authority=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?e.buildAuthority(this._parts):"";e.parseAuthority(a,this._parts);this.build(!b);return this};d.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=e.buildUserinfo(this._parts);return c.substring(0, +c.length-1)}"@"!==a[a.length-1]&&(a+="@");e.parseUserinfo(a,this._parts);this.build(!b);return this};d.resource=function(a,b){var c;if(void 0===a)return this.path()+this.search()+this.hash();c=e.parse(a);this._parts.path=c.path;this._parts.query=c.query;this._parts.fragment=c.fragment;this.build(!b);return this};d.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length- +1;return this._parts.hostname.substring(0,c)||""}c=this._parts.hostname.length-this.domain().length;c=this._parts.hostname.substring(0,c);c=RegExp("^"+s(c));a&&"."!==a.charAt(a.length-1)&&(a+=".");a&&e.ensureValidHostname(a);this._parts.hostname=this._parts.hostname.replace(c,a);this.build(!b);return this};d.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\./g); +if(c&&2>c.length)return this._parts.hostname;c=this._parts.hostname.length-this.tld(b).length-1;c=this._parts.hostname.lastIndexOf(".",c-1)+1;return this._parts.hostname.substring(c)||""}if(!a)throw new TypeError("cannot set domain empty");e.ensureValidHostname(a);!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(s(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a));this.build(!b);return this};d.tld=function(a,b){if(this._parts.urn)return void 0===a?"": +this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.lastIndexOf("."),c=this._parts.hostname.substring(c+1);return!0!==b&&v&&v.list[c.toLowerCase()]?v.get(this._parts.hostname)||c:c}if(a)if(a.match(/[^a-zA-Z0-9-]/))if(v&&v.is(a))c=RegExp(s(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a);else throw new TypeError("TLD '"+a+"' contains characters other than [A-Z0-9]");else{if(!this._parts.hostname|| +this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");c=RegExp(s(this.tld())+"$");this._parts.hostname=this._parts.hostname.replace(c,a)}else throw new TypeError("cannot set TLD empty");this.build(!b);return this};d.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0, +c)||(this._parts.hostname?"/":"");return a?e.decodePath(c):c}c=this._parts.path.length-this.filename().length;c=this._parts.path.substring(0,c);c=RegExp("^"+s(c));this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a));a&&"/"!==a.charAt(a.length-1)&&(a+="/");a=e.recodePath(a);this._parts.path=this._parts.path.replace(c,a);this.build(!b);return this};d.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return""; +var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?e.decodePathSegment(c):c}c=!1;"/"===a.charAt(0)&&(a=a.substring(1));a.match(/\.?\//)&&(c=!0);var d=RegExp(s(this.filename())+"$");a=e.recodePath(a);this._parts.path=this._parts.path.replace(d,a);c?this.normalizePath(b):this.build(!b);return this};d.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),d=c.lastIndexOf("."); +if(-1===d)return"";c=c.substring(d+1);c=/^[a-z0-9%]+$/i.test(c)?c:"";return a?e.decodePathSegment(c):c}"."===a.charAt(0)&&(a=a.substring(1));if(c=this.suffix())d=a?RegExp(s(c)+"$"):RegExp(s("."+c)+"$");else{if(!a)return this;this._parts.path+="."+e.recodePath(a)}d&&(a=e.recodePath(a),this._parts.path=this._parts.path.replace(d,a));this.build(!b);return this};d.segment=function(a,b,c){var e=this._parts.urn?":":"/",d=this.path(),k="/"===d.substring(0,1),d=d.split(e);void 0!==a&&"number"!==typeof a&& +(c=b,b=a,a=void 0);if(void 0!==a&&"number"!==typeof a)throw Error("Bad segment '"+a+"', must be 0-based integer");k&&d.shift();0>a&&(a=Math.max(d.length+a,0));if(void 0===b)return void 0===a?d:d[a];if(null===a||void 0===d[a])if(l(b)){d=[];a=0;for(var h=b.length;ar;r++)if(!h(t,e[r]))return!1;return!0}var n=a(e);for(r=0,s=t.length;s>r;r++)if("RegExp"===n){if("string"==typeof t[r]&&t[r].match(e))return!0}else if(t[r]===e)return!0;return!1}function u(t,e){if(!o(t)||!o(e)||t.length!==e.length)return!1;t.sort(),e.sort();for(var r=0,s=t.length;s>r;r++)if(t[r]!==e[r])return!1;return!0}function p(t){return escape(t)}function c(t){return encodeURIComponent(t).replace(/[!'()*]/g,p).replace(/\*/g,"%2A")}var l=s&&s.URI;n.version="1.12.1";var d=n.prototype,f=Object.prototype.hasOwnProperty;n._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:n.duplicateQueryParameters,escapeQuerySpace:n.escapeQuerySpace}},n.duplicateQueryParameters=!1,n.escapeQuerySpace=!0,n.protocol_expression=/^[a-z][a-z0-9.+-]*$/i,n.idn_expression=/[^a-z0-9\.-]/i,n.punycode_expression=/(xn--)/i,n.ip4_expression=/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,n.ip6_expression=/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,n.find_uri_expression=/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u2018\u2019]))/gi,n.findUri={start:/\b(?:([a-z][a-z0-9.+-]*:\/\/)|www\.)/gi,end:/[\s\r\n]|$/,trim:/[`!()\[\]{};:'".,<>?\u00ab\u00bb\u201c\u201d\u201e\u2018\u2019]+$/},n.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"},n.invalid_hostname_characters=/[^a-zA-Z0-9\.-]/,n.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"},n.getDomAttribute=function(t){if(t&&t.nodeName){var e=t.nodeName.toLowerCase();return"input"===e&&"image"!==t.type?void 0:n.domAttributes[e]}},n.encode=c,n.decode=decodeURIComponent,n.iso8859=function(){n.encode=escape,n.decode=unescape},n.unicode=function(){n.encode=c,n.decode=decodeURIComponent},n.characters={pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/gi,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\/\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/gi,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}},n.encodeQuery=function(t,e){var r=n.encode(t+"");return void 0===e&&(e=n.escapeQuerySpace),e?r.replace(/%20/g,"+"):r},n.decodeQuery=function(t,e){t+="",void 0===e&&(e=n.escapeQuerySpace);try{return n.decode(e?t.replace(/\+/g,"%20"):t)}catch(r){return t}},n.recodePath=function(t){t=(t+"").split("/");for(var e=0,r=t.length;r>e;e++)t[e]=n.encodePathSegment(n.decode(t[e]));return t.join("/")},n.decodePath=function(t){t=(t+"").split("/");for(var e=0,r=t.length;r>e;e++)t[e]=n.decodePathSegment(t[e]);return t.join("/")};var m,_={encode:"encode",decode:"decode"},g=function(t,e){return function(r){return n[e](r+"").replace(n.characters[t][e].expression,function(r){return n.characters[t][e].map[r]})}};for(m in _)n[m+"PathSegment"]=g("pathname",_[m]);n.encodeReserved=g("reserved","encode"),n.parse=function(t,e){var r;return e||(e={}),r=t.indexOf("#"),r>-1&&(e.fragment=t.substring(r+1)||null,t=t.substring(0,r)),r=t.indexOf("?"),r>-1&&(e.query=t.substring(r+1)||null,t=t.substring(0,r)),"//"===t.substring(0,2)?(e.protocol=null,t=t.substring(2),t=n.parseAuthority(t,e)):(r=t.indexOf(":"),r>-1&&(e.protocol=t.substring(0,r)||null,e.protocol&&!e.protocol.match(n.protocol_expression)?e.protocol=void 0:"file"===e.protocol?t=t.substring(r+3):"//"===t.substring(r+1,r+3)?(t=t.substring(r+3),t=n.parseAuthority(t,e)):(t=t.substring(r+1),e.urn=!0))),e.path=t,e},n.parseHost=function(t,e){var r,s=t.indexOf("/");return-1===s&&(s=t.length),"["===t.charAt(0)?(r=t.indexOf("]"),e.hostname=t.substring(1,r)||null,e.port=t.substring(r+2,s)||null):t.indexOf(":")!==t.lastIndexOf(":")?(e.hostname=t.substring(0,s)||null,e.port=null):(r=t.substring(0,s).split(":"),e.hostname=r[0]||null,e.port=r[1]||null),e.hostname&&"/"!==t.substring(s).charAt(0)&&(s++,t="/"+t),t.substring(s)||"/"},n.parseAuthority=function(t,e){return t=n.parseUserinfo(t,e),n.parseHost(t,e)},n.parseUserinfo=function(t,e){var r=t.indexOf("/"),s=r>-1?t.lastIndexOf("@",r):t.indexOf("@");return s>-1&&(-1===r||r>s)?(r=t.substring(0,s).split(":"),e.username=r[0]?n.decode(r[0]):null,r.shift(),e.password=r[0]?n.decode(r.join(":")):null,t=t.substring(s+1)):(e.username=null,e.password=null),t},n.parseQuery=function(t,e){if(!t)return{};if(t=t.replace(/&+/g,"&").replace(/^\?*&*|&+$/g,""),!t)return{};for(var r,s,i={},a=t.split("&"),o=a.length,h=0;o>h;h++)r=a[h].split("="),s=n.decodeQuery(r.shift(),e),r=r.length?n.decodeQuery(r.join("="),e):null,i[s]?("string"==typeof i[s]&&(i[s]=[i[s]]),i[s].push(r)):i[s]=r;return i},n.build=function(t){var e="";return t.protocol&&(e+=t.protocol+":"),t.urn||!e&&!t.hostname||(e+="//"),e+=n.buildAuthority(t)||"","string"==typeof t.path&&("/"!==t.path.charAt(0)&&"string"==typeof t.hostname&&(e+="/"),e+=t.path),"string"==typeof t.query&&t.query&&(e+="?"+t.query),"string"==typeof t.fragment&&t.fragment&&(e+="#"+t.fragment),e},n.buildHost=function(t){var e="";return t.hostname?(n.ip6_expression.test(t.hostname)?e=t.port?e+("["+t.hostname+"]:"+t.port):e+t.hostname:(e+=t.hostname,t.port&&(e+=":"+t.port)),e):""},n.buildAuthority=function(t){return n.buildUserinfo(t)+n.buildHost(t)},n.buildUserinfo=function(t){var e="";return t.username&&(e+=n.encode(t.username),t.password&&(e+=":"+n.encode(t.password)),e+="@"),e},n.buildQuery=function(t,e,r){var s,i,a,h,u="";for(i in t)if(f.call(t,i)&&i)if(o(t[i]))for(s={},a=0,h=t[i].length;h>a;a++)void 0!==t[i][a]&&void 0===s[t[i][a]+""]&&(u+="&"+n.buildQueryParameter(i,t[i][a],r),!0!==e&&(s[t[i][a]+""]=!0));else void 0!==t[i]&&(u+="&"+n.buildQueryParameter(i,t[i],r));return u.substring(1)},n.buildQueryParameter=function(t,e,r){return n.encodeQuery(t,r)+(null!==e?"="+n.encodeQuery(e,r):"")},n.addQuery=function(t,e,r){if("object"==typeof e)for(var s in e)f.call(e,s)&&n.addQuery(t,s,e[s]);else{if("string"!=typeof e)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");void 0===t[e]?t[e]=r:("string"==typeof t[e]&&(t[e]=[t[e]]),o(r)||(r=[r]),t[e]=t[e].concat(r))}},n.removeQuery=function(t,e,r){var s;if(o(e))for(r=0,s=e.length;s>r;r++)t[e[r]]=void 0;else if("object"==typeof e)for(s in e)f.call(e,s)&&n.removeQuery(t,s,e[s]);else{if("string"!=typeof e)throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");if(void 0!==r){if(t[e]===r)t[e]=void 0;else if(o(t[e])){s=t[e];var i,a,h={};if(o(r))for(i=0,a=r.length;a>i;i++)h[r[i]]=!0;else h[r]=!0;for(i=0,a=s.length;a>i;i++)void 0!==h[s[i]]&&(s.splice(i,1),a--,i--);t[e]=s}}else t[e]=void 0}},n.hasQuery=function(t,e,r,s){if("object"==typeof e){for(var i in e)if(f.call(e,i)&&!n.hasQuery(t,i,e[i]))return!1;return!0}if("string"!=typeof e)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");switch(a(r)){case"Undefined":return e in t;case"Boolean":return t=Boolean(o(t[e])?t[e].length:t[e]),r===t;case"Function":return!!r(t[e],e,t);case"Array":return o(t[e])?(s?h:u)(t[e],r):!1;case"RegExp":return o(t[e])?s?h(t[e],r):!1:Boolean(t[e]&&t[e].match(r));case"Number":r=String(r);case"String":return o(t[e])?s?h(t[e],r):!1:t[e]===r;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter")}},n.commonPath=function(t,e){var r,s=Math.min(t.length,e.length);for(r=0;s>r;r++)if(t.charAt(r)!==e.charAt(r)){r--;break}return 1>r?t.charAt(0)===e.charAt(0)&&"/"===t.charAt(0)?"/":"":(("/"!==t.charAt(r)||"/"!==e.charAt(r))&&(r=t.substring(0,r).lastIndexOf("/")),t.substring(0,r+1))},n.withinString=function(t,e,r){r||(r={});var s=r.start||n.findUri.start,i=r.end||n.findUri.end,a=r.trim||n.findUri.trim,o=/[a-z0-9-]=["']?$/i;for(s.lastIndex=0;;){var h=s.exec(t);if(!h)break;if(h=h.index,r.ignoreHtml){var u=t.slice(Math.max(h-3,0),h);if(u&&o.test(u))continue}var u=h+t.slice(h).search(i),p=t.slice(h,u).replace(a,"");r.ignore&&r.ignore.test(p)||(u=h+p.length,p=e(p,h,u,t),t=t.slice(0,h)+p+t.slice(u),s.lastIndex=h+p.length)}return s.lastIndex=0,t},n.ensureValidHostname=function(e){if(e.match(n.invalid_hostname_characters)){if(!t)throw new TypeError("Hostname '"+e+"' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(t.toASCII(e).match(n.invalid_hostname_characters))throw new TypeError("Hostname '"+e+"' contains characters other than [A-Z0-9.-]")}},n.noConflict=function(t){return t?(t={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(t.URITemplate=URITemplate.noConflict()),e&&"function"==typeof e.noConflict&&(t.IPv6=e.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(t.SecondLevelDomains=SecondLevelDomains.noConflict()),t):(s.URI===this&&(s.URI=l),this)},d.build=function(t){return!0===t?this._deferred_build=!0:(void 0===t||this._deferred_build)&&(this._string=n.build(this._parts),this._deferred_build=!1),this},d.clone=function(){return new n(this)},d.valueOf=d.toString=function(){return this.build(!1)._string},_={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"},g=function(t){return function(e,r){return void 0===e?this._parts[t]||"":(this._parts[t]=e||null,this.build(!r),this)}};for(m in _)d[m]=g(_[m]);_={query:"?",fragment:"#"},g=function(t,e){return function(r,s){return void 0===r?this._parts[t]||"":(null!==r&&(r+="",r.charAt(0)===e&&(r=r.substring(1))),this._parts[t]=r,this.build(!s),this)}};for(m in _)d[m]=g(m,_[m]);_={search:["?","query"],hash:["#","fragment"]},g=function(t,e){return function(r,s){var n=this[t](r,s);return"string"==typeof n&&n.length?e+n:n}};for(m in _)d[m]=g(_[m][1],_[m][0]);d.pathname=function(t,e){if(void 0===t||!0===t){var r=this._parts.path||(this._parts.hostname?"/":"");return t?n.decodePath(r):r}return this._parts.path=t?n.recodePath(t):"/",this.build(!e),this},d.path=d.pathname,d.href=function(t,e){var r;if(void 0===t)return this.toString();this._string="",this._parts=n._parts();var s=t instanceof n,i="object"==typeof t&&(t.hostname||t.path||t.pathname);if(t.nodeName&&(i=n.getDomAttribute(t),t=t[i]||"",i=!1),!s&&i&&void 0!==t.pathname&&(t=t.toString()),"string"==typeof t)this._parts=n.parse(t,this._parts);else{if(!s&&!i)throw new TypeError("invalid input");for(r in s=s?t._parts:t)f.call(this._parts,r)&&(this._parts[r]=s[r])}return this.build(!e),this},d.is=function(t){var e=!1,s=!1,i=!1,a=!1,o=!1,h=!1,u=!1,p=!this._parts.urn;switch(this._parts.hostname&&(p=!1,s=n.ip4_expression.test(this._parts.hostname),i=n.ip6_expression.test(this._parts.hostname),e=s||i,o=(a=!e)&&r&&r.has(this._parts.hostname),h=a&&n.idn_expression.test(this._parts.hostname),u=a&&n.punycode_expression.test(this._parts.hostname)),t.toLowerCase()){case"relative":return p;case"absolute":return!p;case"domain":case"name":return a;case"sld":return o;case"ip":return e;case"ip4":case"ipv4":case"inet4":return s;case"ip6":case"ipv6":case"inet6":return i;case"idn":return h;case"url":return!this._parts.urn;case"urn":return!!this._parts.urn;case"punycode":return u}return null};var y=d.protocol,v=d.port,b=d.hostname;d.protocol=function(t,e){if(void 0!==t&&t&&(t=t.replace(/:(\/\/)?$/,""),!t.match(n.protocol_expression)))throw new TypeError("Protocol '"+t+"' contains characters other than [A-Z0-9.+-] or doesn't start with [A-Z]");return y.call(this,t,e)},d.scheme=d.protocol,d.port=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0!==t&&(0===t&&(t=null),t&&(t+="",":"===t.charAt(0)&&(t=t.substring(1)),t.match(/[^0-9]/))))throw new TypeError("Port '"+t+"' contains characters other than [0-9]");return v.call(this,t,e)},d.hostname=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0!==t){var r={};n.parseHost(t,r),t=r.hostname}return b.call(this,t,e)},d.host=function(t,e){return this._parts.urn?void 0===t?"":this:void 0===t?this._parts.hostname?n.buildHost(this._parts):"":(n.parseHost(t,this._parts),this.build(!e),this)},d.authority=function(t,e){return this._parts.urn?void 0===t?"":this:void 0===t?this._parts.hostname?n.buildAuthority(this._parts):"":(n.parseAuthority(t,this._parts),this.build(!e),this)},d.userinfo=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t){if(!this._parts.username)return"";var r=n.buildUserinfo(this._parts);return r.substring(0,r.length-1)}return"@"!==t[t.length-1]&&(t+="@"),n.parseUserinfo(t,this._parts),this.build(!e),this},d.resource=function(t,e){var r;return void 0===t?this.path()+this.search()+this.hash():(r=n.parse(t),this._parts.path=r.path,this._parts.query=r.query,this._parts.fragment=r.fragment,this.build(!e),this)},d.subdomain=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var r=this._parts.hostname.length-this.domain().length-1;return this._parts.hostname.substring(0,r)||""}return r=this._parts.hostname.length-this.domain().length,r=this._parts.hostname.substring(0,r),r=RegExp("^"+i(r)),t&&"."!==t.charAt(t.length-1)&&(t+="."),t&&n.ensureValidHostname(t),this._parts.hostname=this._parts.hostname.replace(r,t),this.build(!e),this},d.domain=function(t,e){if(this._parts.urn)return void 0===t?"":this;if("boolean"==typeof t&&(e=t,t=void 0),void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var r=this._parts.hostname.match(/\./g);return r&&2>r.length?this._parts.hostname:(r=this._parts.hostname.length-this.tld(e).length-1,r=this._parts.hostname.lastIndexOf(".",r-1)+1,this._parts.hostname.substring(r)||"")}if(!t)throw new TypeError("cannot set domain empty");return n.ensureValidHostname(t),!this._parts.hostname||this.is("IP")?this._parts.hostname=t:(r=RegExp(i(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(r,t)),this.build(!e),this},d.tld=function(t,e){if(this._parts.urn)return void 0===t?"":this;if("boolean"==typeof t&&(e=t,t=void 0),void 0===t){if(!this._parts.hostname||this.is("IP"))return"";var s=this._parts.hostname.lastIndexOf("."),s=this._parts.hostname.substring(s+1);return!0!==e&&r&&r.list[s.toLowerCase()]?r.get(this._parts.hostname)||s:s}if(!t)throw new TypeError("cannot set TLD empty");if(t.match(/[^a-zA-Z0-9-]/)){if(!r||!r.is(t))throw new TypeError("TLD '"+t+"' contains characters other than [A-Z0-9]");s=RegExp(i(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(s,t)}else{if(!this._parts.hostname||this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");s=RegExp(i(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(s,t)}return this.build(!e),this},d.directory=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||!0===t){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var r=this._parts.path.length-this.filename().length-1,r=this._parts.path.substring(0,r)||(this._parts.hostname?"/":"");return t?n.decodePath(r):r}return r=this._parts.path.length-this.filename().length,r=this._parts.path.substring(0,r),r=RegExp("^"+i(r)),this.is("relative")||(t||(t="/"),"/"!==t.charAt(0)&&(t="/"+t)),t&&"/"!==t.charAt(t.length-1)&&(t+="/"),t=n.recodePath(t),this._parts.path=this._parts.path.replace(r,t),this.build(!e),this},d.filename=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||!0===t){if(!this._parts.path||"/"===this._parts.path)return"";var r=this._parts.path.lastIndexOf("/"),r=this._parts.path.substring(r+1);return t?n.decodePathSegment(r):r}r=!1,"/"===t.charAt(0)&&(t=t.substring(1)),t.match(/\.?\//)&&(r=!0);var s=RegExp(i(this.filename())+"$");return t=n.recodePath(t),this._parts.path=this._parts.path.replace(s,t),r?this.normalizePath(e):this.build(!e),this},d.suffix=function(t,e){if(this._parts.urn)return void 0===t?"":this;if(void 0===t||!0===t){if(!this._parts.path||"/"===this._parts.path)return"";var r=this.filename(),s=r.lastIndexOf(".");return-1===s?"":(r=r.substring(s+1),r=/^[a-z0-9%]+$/i.test(r)?r:"",t?n.decodePathSegment(r):r)}if("."===t.charAt(0)&&(t=t.substring(1)),r=this.suffix())s=RegExp(t?i(r)+"$":i("."+r)+"$");else{if(!t)return this;this._parts.path+="."+n.recodePath(t)}return s&&(t=n.recodePath(t),this._parts.path=this._parts.path.replace(s,t)),this.build(!e),this},d.segment=function(t,e,r){var s=this._parts.urn?":":"/",n=this.path(),i="/"===n.substring(0,1),n=n.split(s);if(void 0!==t&&"number"!=typeof t&&(r=e,e=t,t=void 0),void 0!==t&&"number"!=typeof t)throw Error("Bad segment '"+t+"', must be 0-based integer");if(i&&n.shift(),0>t&&(t=Math.max(n.length+t,0)),void 0===e)return void 0===t?n:n[t];if(null===t||void 0===n[t])if(o(e)){n=[],t=0;for(var a=e.length;a>t;t++)(e[t].length||n.length&&n[n.length-1].length)&&(n.length&&!n[n.length-1].length&&n.pop(),n.push(e[t]))}else(e||"string"==typeof e)&&(""===n[n.length-1]?n[n.length-1]=e:n.push(e));else e||"string"==typeof e&&e.length?n[t]=e:n.splice(t,1);return i&&n.unshift(""),this.path(n.join(s),r)},d.segmentCoded=function(t,e,r){var s,i;if("number"!=typeof t&&(r=e,e=t,t=void 0),void 0===e){if(t=this.segment(t,e,r),o(t))for(s=0,i=t.length;i>s;s++)t[s]=n.decode(t[s]);else t=void 0!==t?n.decode(t):void 0;return t}if(o(e))for(s=0,i=e.length;i>s;s++)e[s]=n.decode(e[s]);else e="string"==typeof e?n.encode(e):e;return this.segment(t,e,r)};var Q=d.query;return d.query=function(t,e){if(!0===t)return n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("function"==typeof t){var r=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace),s=t.call(this,r);return this._parts.query=n.buildQuery(s||r,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!e),this}return void 0!==t&&"string"!=typeof t?(this._parts.query=n.buildQuery(t,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!e),this):Q.call(this,t,e)},d.setQuery=function(t,e,r){var s=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);if("object"==typeof t)for(var i in t)f.call(t,i)&&(s[i]=t[i]);else{if("string"!=typeof t)throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");s[t]=void 0!==e?e:null}return this._parts.query=n.buildQuery(s,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(r=e),this.build(!r),this},d.addQuery=function(t,e,r){var s=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.addQuery(s,t,void 0===e?null:e),this._parts.query=n.buildQuery(s,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(r=e),this.build(!r),this},d.removeQuery=function(t,e,r){var s=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.removeQuery(s,t,e),this._parts.query=n.buildQuery(s,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),"string"!=typeof t&&(r=e),this.build(!r),this},d.hasQuery=function(t,e,r){var s=n.parseQuery(this._parts.query,this._parts.escapeQuerySpace);return n.hasQuery(s,t,e,r)},d.setSearch=d.setQuery,d.addSearch=d.addQuery,d.removeSearch=d.removeQuery,d.hasSearch=d.hasQuery,d.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()},d.normalizeProtocol=function(t){return"string"==typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),this.build(!t)),this},d.normalizeHostname=function(r){return this._parts.hostname&&(this.is("IDN")&&t?this._parts.hostname=t.toASCII(this._parts.hostname):this.is("IPv6")&&e&&(this._parts.hostname=e.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!r)),this},d.normalizePort=function(t){return"string"==typeof this._parts.protocol&&this._parts.port===n.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!t)),this},d.normalizePath=function(t){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var e,r,s,i=this._parts.path,a="";for("/"!==i.charAt(0)&&(e=!0,i="/"+i),i=i.replace(/(\/(\.\/)+)|(\/\.$)/g,"/").replace(/\/{2,}/g,"/"),e&&(a=i.substring(1).match(/^(\.\.\/)+/)||"")&&(a=a[0]);r=i.indexOf("/.."),-1!==r;)0!==r?(s=i.substring(0,r).lastIndexOf("/"),-1===s&&(s=r),i=i.substring(0,s)+i.substring(r+3)):i=i.substring(3);return e&&this.is("relative")&&(i=a+i.substring(1)),i=n.recodePath(i),this._parts.path=i,this.build(!t),this},d.normalizePathname=d.normalizePath,d.normalizeQuery=function(t){return"string"==typeof this._parts.query&&(this._parts.query.length?this.query(n.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!t)),this},d.normalizeFragment=function(t){return this._parts.fragment||(this._parts.fragment=null,this.build(!t)),this},d.normalizeSearch=d.normalizeQuery,d.normalizeHash=d.normalizeFragment,d.iso8859=function(){var t=n.encode,e=n.decode;return n.encode=escape,n.decode=decodeURIComponent,this.normalize(),n.encode=t,n.decode=e,this},d.unicode=function(){var t=n.encode,e=n.decode;return n.encode=c,n.decode=unescape,this.normalize(),n.encode=t,n.decode=e,this},d.readable=function(){var e=this.clone();e.username("").password("").normalize();var r="";if(e._parts.protocol&&(r+=e._parts.protocol+"://"),e._parts.hostname&&(e.is("punycode")&&t?(r+=t.toUnicode(e._parts.hostname),e._parts.port&&(r+=":"+e._parts.port)):r+=e.host()),e._parts.hostname&&e._parts.path&&"/"!==e._parts.path.charAt(0)&&(r+="/"),r+=e.path(!0),e._parts.query){for(var s="",i=0,a=e._parts.query.split("&"),o=a.length;o>i;i++){var h=(a[i]||"").split("="),s=s+("&"+n.decodeQuery(h[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==h[1]&&(s+="="+n.decodeQuery(h[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}r+="?"+s.substring(1)}return r+=n.decodeQuery(e.hash(),!0)},d.absoluteTo=function(t){var e,r,s=this.clone(),i=["protocol","username","password","hostname","port"];if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(t instanceof n||(t=new n(t)),s._parts.protocol||(s._parts.protocol=t._parts.protocol),this._parts.hostname)return s;for(e=0;r=i[e];e++)s._parts[r]=t._parts[r];return s._parts.path?".."===s._parts.path.substring(-2)&&(s._parts.path+="/"):(s._parts.path=t._parts.path,s._parts.query||(s._parts.query=t._parts.query)),"/"!==s.path().charAt(0)&&(t=t.directory(),s._parts.path=(t?t+"/":"")+s._parts.path,s.normalizePath()),s.build(),s},d.relativeTo=function(t){var e,r,s,i,a=this.clone().normalize();if(a._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");if(t=new n(t).normalize(),e=a._parts,r=t._parts,s=a.path(),i=t.path(),"/"!==s.charAt(0))throw Error("URI is already relative");if("/"!==i.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");return e.protocol===r.protocol&&(e.protocol=null),e.username!==r.username||e.password!==r.password||null!==e.protocol||null!==e.username||null!==e.password||e.hostname!==r.hostname||e.port!==r.port?a.build():(e.hostname=null,e.port=null,s===i?(e.path="",a.build()):(t=n.commonPath(a.path(),t.path()))?(r=r.path.substring(t.length).replace(/[^\/]*$/,"").replace(/.*?\//g,"../"),e.path=r+e.path.substring(t.length),a.build()):a.build())},d.equals=function(t){var e=this.clone();t=new n(t);var r,s={},i={},a={};if(e.normalize(),t.normalize(),e.toString()===t.toString())return!0;if(s=e.query(),i=t.query(),e.query(""),t.query(""),e.toString()!==t.toString()||s.length!==i.length)return!1;s=n.parseQuery(s,this._parts.escapeQuerySpace),i=n.parseQuery(i,this._parts.escapeQuerySpace);for(r in s)if(f.call(s,r)){if(o(s[r])){if(!u(s[r],i[r]))return!1}else if(s[r]!==i[r])return!1;a[r]=!0}for(r in i)if(f.call(i,r)&&!a[r])return!1;return!0},d.duplicateQueryParameters=function(t){return this._parts.duplicateQueryParameters=!!t,this},d.escapeQuerySpace=function(t){return this._parts.escapeQuerySpace=!!t,this},n}); \ No newline at end of file