From 383fc211066683329e06bb187ee0493f8d242e04 Mon Sep 17 00:00:00 2001 From: Benjamin Matuszewski Date: Wed, 13 Dec 2017 17:43:44 +0100 Subject: [PATCH] added BarChartDisplay sink --- examples/sink-bar-chart-display/.babelrc | 5 + examples/sink-bar-chart-display/.gitignore | 5 + examples/sink-bar-chart-display/README.md | 34 + .../sink-bar-chart-display/assets/favicon.ico | Bin 0 -> 318 bytes .../sink-bar-chart-display/bin/javascripts | 132 + examples/sink-bar-chart-display/bin/log | 81 + examples/sink-bar-chart-display/bin/runner | 188 + examples/sink-bar-chart-display/bin/server | 42 + examples/sink-bar-chart-display/bundle.js | 13694 ++++++++++++++++ .../sink-bar-chart-display/css/styles.css | 20 + examples/sink-bar-chart-display/index.html | 15 + examples/sink-bar-chart-display/package.json | 36 + examples/sink-bar-chart-display/src/index.js | 28 + jsdoc.json | 6 + src/client/sink/BarChartDisplay.js | 126 + src/client/sink/_namespace.js | 2 + src/client/utils/display-utils.js | 3 + 17 files changed, 14417 insertions(+) create mode 100644 examples/sink-bar-chart-display/.babelrc create mode 100644 examples/sink-bar-chart-display/.gitignore create mode 100644 examples/sink-bar-chart-display/README.md create mode 100644 examples/sink-bar-chart-display/assets/favicon.ico create mode 100755 examples/sink-bar-chart-display/bin/javascripts create mode 100755 examples/sink-bar-chart-display/bin/log create mode 100755 examples/sink-bar-chart-display/bin/runner create mode 100755 examples/sink-bar-chart-display/bin/server create mode 100644 examples/sink-bar-chart-display/bundle.js create mode 100644 examples/sink-bar-chart-display/css/styles.css create mode 100644 examples/sink-bar-chart-display/index.html create mode 100644 examples/sink-bar-chart-display/package.json create mode 100644 examples/sink-bar-chart-display/src/index.js create mode 100644 src/client/sink/BarChartDisplay.js diff --git a/examples/sink-bar-chart-display/.babelrc b/examples/sink-bar-chart-display/.babelrc new file mode 100644 index 0000000..dda73e8 --- /dev/null +++ b/examples/sink-bar-chart-display/.babelrc @@ -0,0 +1,5 @@ +{ + "sourceMap": "inline", + "presets": ["latest"], + "plugins": ["transform-runtime", "transform-es2015-modules-commonjs"] +} \ No newline at end of file diff --git a/examples/sink-bar-chart-display/.gitignore b/examples/sink-bar-chart-display/.gitignore new file mode 100644 index 0000000..16e7e87 --- /dev/null +++ b/examples/sink-bar-chart-display/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ + +.DS_Store +npm-debug.log diff --git a/examples/sink-bar-chart-display/README.md b/examples/sink-bar-chart-display/README.md new file mode 100644 index 0000000..3db48bb --- /dev/null +++ b/examples/sink-bar-chart-display/README.md @@ -0,0 +1,34 @@ +ES6 Prototyping Boilerplate +======================================================= + +> A client-side boilerplate for rapid prototyping with latest EcmaScript features (using [babel-latest](https://babeljs.io/docs/plugins/preset-latest/) preset) + +## Available Commands + +``` +npm run [command] +``` + +- `transpile` + * transpile all files from `src` folder to `dist` folder +- `bundle` + * run `transpile` command + * create the browserified bundle +- `watch` + * create a static file server + * transpile files in `src` folder when changed + * rebundle application on page load +- `serve` + * run the static file server only _(presentation mode)_ + +## Usage + +```sh +git clone --depth=1 https://github.com/Ircam-RnD/es6-prototyping-boilerplate.git dest_directory +cd dest_directory +rm -rf .git # remove git history +npm install +``` + +This boilerplate uses [https://babeljs.io/](https://babeljs.io/) and [http://browserify.org/](http://browserify.org/). + diff --git a/examples/sink-bar-chart-display/assets/favicon.ico b/examples/sink-bar-chart-display/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..aad99fba9e97e6ca1e4863f604f4aeaa02b8e711 GIT binary patch literal 318 zcmZQzU<5(|0RbS%!l1#(z#zuJz@P!d0zj+)#2|4HXaJKC0wf0mYCr$LnAD*K1tI3( LqN!sGRZIZ@_WuM2 literal 0 HcmV?d00001 diff --git a/examples/sink-bar-chart-display/bin/javascripts b/examples/sink-bar-chart-display/bin/javascripts new file mode 100755 index 0000000..aae8330 --- /dev/null +++ b/examples/sink-bar-chart-display/bin/javascripts @@ -0,0 +1,132 @@ +#!/usr/bin/env node +var babel = require('babel-core'); +var browserify = require('browserify'); +var fse = require('fs-extra'); +var log = require('./log'); +var path = require('path'); + +'use strict'; + +/** + * Create a transpiler object binded to a `srcDirectory` and a `distDirectory` + */ +function getTranspiler(srcDirectory, distDirectory, isAllowed, babelOptions, browserifyOptions) { + + /** + * Returns the name of the target transpiled file + */ + function getTarget(filename) { + var relFilename = path.relative(srcDirectory, filename); + var outFilename = path.join(distDirectory, relFilename); + return outFilename; + } + + /** + * returns the transpiler to be consumed. + */ + var transpiler = { + /** + * Transpile the given file from es6 to es5. If the given stack is not empty + * call the method recursively till its empty. When the stack is empty, + * execute the callback. + */ + transpile: function(filename, stack, callback) { + /** + * If stack is not empty transpile the next entry, else execute the + * callback if any. + */ + function next() { + if (stack && stack.length > 0) + transpiler.transpile(stack.shift(), stack, callback); + else if (stack.length === 0 && callback) + callback(); + } + + if (filename === undefined || !isAllowed(filename)) + return next(); + + var outFilename = getTarget(filename); + var startTime = new Date().getTime(); + + babel.transformFile(filename, babelOptions, function(err, result) { + if (err) + return log.transpileError(err); + + fse.outputFile(outFilename, result.code, function(err) { + if (err) + return console.error(err.message); + + log.transpileSuccess(filename, outFilename, startTime); + next(); + }); + }); + }, + + /** + * Transform a given file to it's browserified version, client only. + * Only clients have their browserified counterparts, each folder in `src/client` + * is considered has a separate browserified client file. The `index.js` in each + * folder defines the entry point of the particular client. The browserified + * file is name after the name of the folder. + */ + bundle: function(entryPoint, outFilename, callback) { + if (entryPoint === undefined || !isAllowed(entryPoint)) + return; + + var bundler = browserify(entryPoint, browserifyOptions); + var startTime = new Date().getTime(); + + log.bundleStart(outFilename); + fse.ensureFileSync(outFilename); // ensure file exists + + var writeStream = fse.createWriteStream(outFilename); + + bundler + .bundle() + .on('error', function(err) { + log.bundleError(outFilename, err); + }) + .on('end', function() { + log.bundleSuccess(outFilename, startTime); + }) + .pipe(writeStream); + + writeStream.on('finish', function() { + if (callback) + callback(); + }); + }, + + /** + * Delete the transpiled file. + */ + delete: function(filename, callback) { + var outFilename = getTarget(filename); + + fse.stat(outFilename, function(err, stats) { + if (err) + return console.log(err.message); + + if (stats.isFile()) { + fse.remove(outFilename, function(err) { + if (err) + return console.log(err.message); + + log.deleteFile(outFilename); + + if (callback) + callback(); + }); + } else { + callback(); + } + }); + }, + }; + + return transpiler; +} + +module.exports = { + getTranspiler: getTranspiler +}; diff --git a/examples/sink-bar-chart-display/bin/log b/examples/sink-bar-chart-display/bin/log new file mode 100755 index 0000000..0914226 --- /dev/null +++ b/examples/sink-bar-chart-display/bin/log @@ -0,0 +1,81 @@ +#!/usr/bin/env node +var pkg = require('../package.json'); +var colors = require('colors'); +var ora = require('ora'); +var path = require('path'); + +'use strict'; + +var prefix = '[' + pkg.name + ']\t'; +var cwd = process.cwd(); + +function toRel(target) { + return path.relative(cwd, target); +} + +function getDeltaTime(time) { + return new Date().getTime() - time; +} + +var spinners = {}; + +var log = { + bundleStart: function(dest) { + var msg = prefix + (toRel(dest) + ': bundle start').yellow; + var spinner = ora({ color: 'white', text: msg }); + spinner.start(); + + spinners[dest] = spinner; + }, + + bundleSuccess: function(dest, startTime) { + var spinner = spinners[dest]; + var time = getDeltaTime(startTime); + var msg = prefix + '%s: successfully created (%sms)'.green; + + spinner.stop(); + console.log(msg, toRel(dest), time); + }, + + bundleError: function(dest, err) { + var spinner = spinners[dest]; + var msg = prefix + '%s: bundle error'.red; + + spinner.stop(); + console.log(msg, toRel(dest)); + console.log('> ' + err.message); + }, + + transpileSuccess: function(src, dest, startTime) { + var time = getDeltaTime(startTime); + var msg = prefix + '%s: successfully transpiled to "%s" (%sms)'.green; + + console.log(msg, toRel(src), toRel(dest), time); + }, + + transpileError: function(err) { + var parts = err.message.split(':'); + var msg = prefix + '%s'.red; + + console.log(msg, toRel(err.message)); + console.log(err.codeFrame); + }, + + uglifySuccess: function(src, dest, startTime) { + var time = getDeltaTime(startTime); + var msg = prefix + '%s: successfully uglified to "%s" (%sms)'.green; + console.log(msg, toRel(src), toRel(dest), time); + }, + + deleteFile: function(filename) { + var msg = prefix + '%s: successfully removed'.yellow; + console.log(msg, toRel(filename)); + }, + + serverStart: function(port) { + var msg = prefix + 'server listen on http://127.0.0.1:%s'.blue; + console.log(msg, port); + } +}; + +module.exports = log; diff --git a/examples/sink-bar-chart-display/bin/runner b/examples/sink-bar-chart-display/bin/runner new file mode 100755 index 0000000..4e9f202 --- /dev/null +++ b/examples/sink-bar-chart-display/bin/runner @@ -0,0 +1,188 @@ +#!/usr/bin/env node +var fse = require('fs-extra'); +var watch = require('watch'); +var path = require('path'); +var pkg = require('../package.json'); +var util = require('util'); + +var javascripts = require('./javascripts'); +var server = require('./server'); +var cwd = process.cwd(); + +'use strict'; + +/** + * Options for babel transpiling. + */ +var babelrc = fse.readFileSync(path.join(cwd, '.babelrc')); +var babelOptions = JSON.parse(babelrc.toString()); + +/** + * Options for watch. + */ +var watchOptions = { + ignoreDotFiles: true, + ignoreUnreadableDir: true, + ignoreNotPermitted: true, + interval: 2000, // watch internally use `fs.watchFile` +}; + +/** + * Options for browserify. + */ +var browserifyOptions = { + debug: true, + fullPaths: false, + standalone: pkg.standalone, +}; + +/** + * Watched directories + */ +var srcDirectory = path.join(cwd, 'src'); +var distDirectory = path.join(cwd, 'dist'); + +var bundlePath = path.join(cwd, 'bundle.js'); + +/** + * Define which file should be ignored by every command. + */ +var allowedExtentions = /\.ejs$|\.scss$|\.js$/; +var excludeFiles = /^\./; // exclude hidden files + +/** + * Test the given filename, to ensure it can be processed by any command / tranpsiler + * @param {String} filename - The filename to be checked. + * @param {Boolean} [ensureFile=true] - If set to false, don't test if the file exists. + */ +function isAllowed(filename, ensureFile) { + ensureFile = ensureFile === undefined ? true : ensureFile; + + var basename = path.basename(filename); + var isFile = true; + + if (ensureFile) { + try { + isFile = fse.lstatSync(filename).isFile() && !fse.lstatSync(filename).isSymbolicLink(); + } catch(e) { + console.log(e.message); + isFile = false; + } + } + + var hasAllowedExt = allowedExtentions.test(basename); + var notExcludeFile = !excludeFiles.test(basename); + + return isFile && hasAllowedExt && notExcludeFile; +} + +/** + * Returns a list of the file in a given folder recursively. + */ +function _getFileList(folder, callback) { + var files = []; + + fse.walk(folder) + .on('data', function(item) { + if (item.stats.isFile() && isAllowed(item.path)) + files.push(item.path); + }) + .on('end', function() { + callback(files); + }); +} + +/** + * Watch javascript source files. + */ +function watchFiles(srcDirectory, distDirectory) { + var transpiler = javascripts.getTranspiler(srcDirectory, distDirectory, isAllowed, babelOptions, browserifyOptions); + + watch.createMonitor(srcDirectory, watchOptions, function(monitor) { + monitor.on('created', function(filename, stats) { + if (isAllowed(filename)) + transpiler.transpile(filename, []); + }); + + monitor.on('changed', function(filename, stats) { + if (isAllowed(filename)) + transpiler.transpile(filename, []); + }); + + monitor.on('removed', function(filename, stats) { + if (isAllowed(filename, false)) + transpiler.delete(filename); + }); + }); + + // start a server which bundles sources on `bundle.js` request + var entryPoint = path.join(distDirectory, 'index.js'); + var middleware = server.bundleMiddleware(transpiler, entryPoint, bundlePath); + server.start(middleware); +} + + +function transpileFiles(srcDirectory, distDirectory, callback) { + _getFileList(srcDirectory, function(files) { + var transpiler = javascripts.getTranspiler(srcDirectory, distDirectory, isAllowed, babelOptions); + transpiler.transpile(undefined, files, callback); + }); +} + +function bundle(distDirectory) { + var entryPoint = path.join(distDirectory, 'index.js'); + var transpiler = javascripts.getTranspiler(srcDirectory, distDirectory, isAllowed, babelOptions, browserifyOptions); + + transpileFiles(srcDirectory, distDirectory, function() { + transpiler.bundle(entryPoint, bundlePath); + }); +} + +function serve() { + server.start(); +} + +/* -------------------------------------------------------------------------- + * Process and execute the given command. + * -------------------------------------------------------------------------- */ + +var command = process.argv[2]; +var args = process.argv.slice(3); +var argv = {}; +for (var i = 0; i < args.length; i += 2) { + argv[args[i]] = args[i + 1]; +} + +switch (command) { + /** + * Watch the file system and transpile from es6 to es5. + */ + case '--watch': + watchFiles(srcDirectory, distDirectory); + break; + + /** + * Transpile all files in `src` from es6 to es5. + */ + case '--transpile': + transpileFiles(srcDirectory, distDirectory); + break; + + /** + * Transpile all files in `src` from es6 to es5 and browserify all the things. + */ + case '--bundle': + bundle(distDirectory); + break; + + /** + * Run a static server. + */ + case '--serve': + serve(); + break; +} + +/* -------------------------------------------------------------------------- + * -------------------------------------------------------------------------- */ + diff --git a/examples/sink-bar-chart-display/bin/server b/examples/sink-bar-chart-display/bin/server new file mode 100755 index 0000000..ccf0786 --- /dev/null +++ b/examples/sink-bar-chart-display/bin/server @@ -0,0 +1,42 @@ +#!/usr/bin/env node +var connect = require('connect'); +var log = require('./log'); +var path = require('path'); +var portfinder = require('portfinder'); +var serveStatic = require('serve-static'); +var serveFavicon = require('serve-favicon'); + +'use strict'; + +portfinder.basePort = 3000; + + +const server = { + start: function(middleware) { + var app = connect(); + + if (middleware) + app.use(middleware); + + app.use(serveFavicon('./assets/favicon.ico')); + app.use(serveStatic('.', { index: ['index.html'] })); + + portfinder.getPort(function(err, port) { + if (err) + console.log(err.message); + + app.listen(port, function() { log.serverStart(port); }); + }); + }, + + bundleMiddleware: function(transpiler, entryPoint, outFilename) { + return function(req, res, next) { + if (req.url === '/' + path.basename(outFilename)) + transpiler.bundle(entryPoint, outFilename, next); // rebundle + else + next(); + } + } +} + +module.exports = server; diff --git a/examples/sink-bar-chart-display/bundle.js b/examples/sink-bar-chart-display/bundle.js new file mode 100644 index 0000000..fb5b8c7 --- /dev/null +++ b/examples/sink-bar-chart-display/bundle.js @@ -0,0 +1,13694 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, BarChartDisplay); + return (0, _possibleConstructorReturn3.default)(this, (BarChartDisplay.__proto__ || (0, _getPrototypeOf2.default)(BarChartDisplay)).call(this, definitions, options, false)); + } + + /** @private */ + + + (0, _createClass3.default)(BarChartDisplay, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + var frameSize = this.streamParams.frameSize; + var width = this.canvasWidth; + var height = this.canvasHeight; + var colors = this.params.get('colors'); + var data = frame.data; + + var barWidth = width / frameSize; + var ctx = this.ctx; + + // error handling needs review... + var error = 0; + + for (var i = 0; i < frameSize; i++) { + var x1Float = i * barWidth + error; + var x1Int = Math.round(x1Float); + var x2Float = x1Float + (barWidth - error); + var x2Int = Math.round(x2Float); + + error = x2Int - x2Float; + + if (x1Int !== x2Int) { + var _width = x2Int - x1Int; + var y = this.getYPosition(data[i]); + + ctx.fillStyle = colors[i % colors.length]; + ctx.fillRect(x1Int, y, _width, height - y); + } else { + error -= barWidth; + } + } + } + }]); + return BarChartDisplay; +}(_BaseDisplay3.default); + +exports.default = BarChartDisplay; + +},{"../../common/operator/Fft":24,"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],3:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _assign = require('babel-runtime/core-js/object/assign'); + +var _assign2 = _interopRequireDefault(_assign); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var commonDefinitions = { + min: { + type: 'float', + default: -1, + metas: { kind: 'dynamic' } + }, + max: { + type: 'float', + default: 1, + metas: { kind: 'dynamic' } + }, + width: { + type: 'integer', + default: 300, + metas: { kind: 'dynamic' } + }, + height: { + type: 'integer', + default: 150, + metas: { kind: 'dynamic' } + }, + container: { + type: 'any', + default: null, + constant: true + }, + canvas: { + type: 'any', + default: null, + constant: true + } +}; + +var hasDurationDefinitions = { + duration: { + type: 'float', + min: 0, + max: +Infinity, + default: 1, + metas: { kind: 'dynamic' } + }, + referenceTime: { + type: 'float', + default: 0, + constant: true + } +}; + +/** + * Base class to extend in order to create graphic sinks. + * + * _This class should be considered abstract and only + * be used to be extended._ + * + * @todo - fix float rounding errors (produce decays in sync draws) + * + * @memberof module:client.sink + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.min=-1] - Minimum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.max=1] - Maximum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. This parameter only exists for operators that display several + * consecutive frames on the canvas. _dynamic parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. This parameter only exists + * for operators that display several consecutive frames on the canvas. + */ + +var BaseDisplay = function (_BaseLfo) { + (0, _inherits3.default)(BaseDisplay, _BaseLfo); + + function BaseDisplay(defs) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var hasDuration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + (0, _classCallCheck3.default)(this, BaseDisplay); + + var commonDefs = void 0; + + if (hasDuration) commonDefs = (0, _assign2.default)({}, commonDefinitions, hasDurationDefinitions);else commonDefs = commonDefinitions; + + var definitions = (0, _assign2.default)({}, commonDefs, defs); + + var _this = (0, _possibleConstructorReturn3.default)(this, (BaseDisplay.__proto__ || (0, _getPrototypeOf2.default)(BaseDisplay)).call(this, definitions, options)); + + if (_this.params.get('canvas') === null && _this.params.get('container') === null) throw new Error('Invalid parameter: `canvas` or `container` not defined'); + + var canvasParam = _this.params.get('canvas'); + var containerParam = _this.params.get('container'); + + // prepare canvas + if (canvasParam) { + if (typeof canvasParam === 'string') _this.canvas = document.querySelector(canvasParam);else _this.canvas = canvasParam; + } else if (containerParam) { + var container = void 0; + + if (typeof containerParam === 'string') container = document.querySelector(containerParam);else container = containerParam; + + _this.canvas = document.createElement('canvas'); + container.appendChild(_this.canvas); + } + + _this.ctx = _this.canvas.getContext('2d'); + _this.cachedCanvas = document.createElement('canvas'); + _this.cachedCtx = _this.cachedCanvas.getContext('2d'); + + _this.hasDuration = hasDuration; + _this.previousFrame = null; + _this.currentTime = hasDuration ? _this.params.get('referenceTime') : null; + + /** + * Instance of the `DisplaySync` used to synchronize the different displays + * @private + */ + _this.displaySync = false; + + _this._stack = []; + _this._rafId = null; + + _this.renderStack = _this.renderStack.bind(_this); + _this.shiftError = 0; + + // initialize canvas size and y scale transfert function + _this._resize(); + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(BaseDisplay, [{ + key: '_resize', + value: function _resize() { + var width = this.params.get('width'); + var height = this.params.get('height'); + + var ctx = this.ctx; + var cachedCtx = this.cachedCtx; + + var dPR = window.devicePixelRatio || 1; + var bPR = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; + + this.pixelRatio = dPR / bPR; + + var lastWidth = this.canvasWidth; + var lastHeight = this.canvasHeight; + this.canvasWidth = width * this.pixelRatio; + this.canvasHeight = height * this.pixelRatio; + + cachedCtx.canvas.width = this.canvasWidth; + cachedCtx.canvas.height = this.canvasHeight; + + // copy current image from ctx (resize) + if (lastWidth && lastHeight) { + cachedCtx.drawImage(ctx.canvas, 0, 0, lastWidth, lastHeight, 0, 0, this.canvasWidth, this.canvasHeight); + } + + ctx.canvas.width = this.canvasWidth; + ctx.canvas.height = this.canvasHeight; + ctx.canvas.style.width = width + 'px'; + ctx.canvas.style.height = height + 'px'; + + // update scale + this._setYScale(); + } + + /** + * Create the transfert function used to map values to pixel in the y axis + * @private + */ + + }, { + key: '_setYScale', + value: function _setYScale() { + var min = this.params.get('min'); + var max = this.params.get('max'); + var height = this.canvasHeight; + + var a = (0 - height) / (max - min); + var b = height - a * min; + + this.getYPosition = function (x) { + return a * x + b; + }; + } + + /** + * Returns the width in pixel a `vector` frame needs to be drawn. + * @private + */ + + }, { + key: 'getMinimumFrameWidth', + value: function getMinimumFrameWidth() { + return 1; // need one pixel to draw the line + } + + /** + * Callback function executed when a parameter is updated. + * + * @param {String} name - Parameter name. + * @param {Mixed} value - Parameter value. + * @param {Object} metas - Metadatas of the parameter. + * @private + */ + + }, { + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(BaseDisplay.prototype.__proto__ || (0, _getPrototypeOf2.default)(BaseDisplay.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + switch (name) { + case 'min': + case 'max': + // @todo - make sure that min and max are different + this._setYScale(); + break; + case 'width': + case 'height': + this._resize(); + } + } + + /** @private */ + + }, { + key: 'propagateStreamParams', + value: function propagateStreamParams() { + (0, _get3.default)(BaseDisplay.prototype.__proto__ || (0, _getPrototypeOf2.default)(BaseDisplay.prototype), 'propagateStreamParams', this).call(this); + } + + /** @private */ + + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(BaseDisplay.prototype.__proto__ || (0, _getPrototypeOf2.default)(BaseDisplay.prototype), 'resetStream', this).call(this); + + var width = this.canvasWidth; + var height = this.canvasHeight; + + this.previousFrame = null; + this.currentTime = this.hasDuration ? this.params.get('referenceTime') : null; + + this.ctx.clearRect(0, 0, width, height); + this.cachedCtx.clearRect(0, 0, width, height); + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + this.currentTime = null; + (0, _get3.default)(BaseDisplay.prototype.__proto__ || (0, _getPrototypeOf2.default)(BaseDisplay.prototype), 'finalizeStream', this).call(this, endTime); + + this._rafId = null; + + // clear the stack if not empty + if (this._stack.length > 0) this.renderStack(); + } + + /** + * Add the current frame to the frames to draw. Should not be overriden. + * @private + */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + var frameSize = this.streamParams.frameSize; + var copy = new Float32Array(frameSize); + var data = frame.data; + + // copy values of the input frame as they might be updated + // in reference before being consumed in the draw function + for (var i = 0; i < frameSize; i++) { + copy[i] = data[i]; + }this._stack.push({ + time: frame.time, + data: copy, + metadata: frame.metadata + }); + + if (this._rafId === null) this._rafId = window.requestAnimationFrame(this.renderStack); + } + + /** + * Render the accumulated frames. Method called in `requestAnimationFrame`. + * @private + */ + + }, { + key: 'renderStack', + value: function renderStack() { + if (this.params.has('duration')) { + // render all frame since last `renderStack` call + for (var i = 0, l = this._stack.length; i < l; i++) { + this.scrollModeDraw(this._stack[i]); + } + } else { + // only render last received frame if any + if (this._stack.length > 0) { + var frame = this._stack[this._stack.length - 1]; + this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); + this.processFunction(frame); + } + } + + this._stack.length = 0; // reinit stack for next call + this._rafId = null; + } + + /** + * Draw data from right to left with scrolling + * @private + * @todo - check possibility of maintaining all values from one place to + * minimize float error tracking. + */ + + }, { + key: 'scrollModeDraw', + value: function scrollModeDraw(frame) { + var frameType = this.streamParams.frameType; + var frameRate = this.streamParams.frameRate; + var frameSize = this.streamParams.frameSize; + var sourceSampleRate = this.streamParams.sourceSampleRate; + + var canvasDuration = this.params.get('duration'); + var ctx = this.ctx; + var canvasWidth = this.canvasWidth; + var canvasHeight = this.canvasHeight; + + var previousFrame = this.previousFrame; + + // current time at the left of the canvas + var currentTime = this.currentTime !== null ? this.currentTime : frame.time; + var frameStartTime = frame.time; + var lastFrameTime = previousFrame ? previousFrame.time : 0; + var lastFrameDuration = this.lastFrameDuration ? this.lastFrameDuration : 0; + + var frameDuration = void 0; + + if (frameType === 'scalar' || frameType === 'vector') { + var pixelDuration = canvasDuration / canvasWidth; + frameDuration = this.getMinimumFrameWidth() * pixelDuration; + } else if (this.streamParams.frameType === 'signal') { + frameDuration = frameSize / sourceSampleRate; + } + + var frameEndTime = frameStartTime + frameDuration; + // define if we need to shift the canvas + var shiftTime = frameEndTime - currentTime; + + // if the canvas is not synced, should never go to `else` + if (shiftTime > 0) { + // shift the canvas of shiftTime in pixels + var fShift = shiftTime / canvasDuration * canvasWidth - this.shiftError; + var iShift = Math.floor(fShift + 0.5); + this.shiftError = fShift - iShift; + + var _currentTime = frameStartTime + frameDuration; + this.shiftCanvas(iShift, _currentTime); + + // if siblings, share the information + if (this.displaySync) this.displaySync.shiftSiblings(iShift, _currentTime, this); + } + + // width of the frame in pixels + var floatFrameWidth = frameDuration / canvasDuration * canvasWidth; + var frameWidth = Math.floor(floatFrameWidth + 0.5); + + // define position of the head in the canvas + var canvasStartTime = this.currentTime - canvasDuration; + var startTimeRatio = (frameStartTime - canvasStartTime) / canvasDuration; + var startTimePosition = startTimeRatio * canvasWidth; + + // number of pixels since last frame + var pixelsSinceLastFrame = this.lastFrameWidth; + + if ((frameType === 'scalar' || frameType === 'vector') && previousFrame) { + var frameInterval = frame.time - previousFrame.time; + pixelsSinceLastFrame = frameInterval / canvasDuration * canvasWidth; + } + + // draw current frame + ctx.save(); + ctx.translate(startTimePosition, 0); + this.processFunction(frame, frameWidth, pixelsSinceLastFrame); + ctx.restore(); + + // save current canvas state into cached canvas + this.cachedCtx.clearRect(0, 0, canvasWidth, canvasHeight); + this.cachedCtx.drawImage(this.canvas, 0, 0, canvasWidth, canvasHeight); + + // update lastFrameDuration, lastFrameWidth + this.lastFrameDuration = frameDuration; + this.lastFrameWidth = frameWidth; + this.previousFrame = frame; + } + + /** + * Shift canvas, also called from `DisplaySync` + * @private + */ + + }, { + key: 'shiftCanvas', + value: function shiftCanvas(iShift, time) { + var ctx = this.ctx; + var cache = this.cachedCanvas; + var cachedCtx = this.cachedCtx; + var width = this.canvasWidth; + var height = this.canvasHeight; + var croppedWidth = width - iShift; + this.currentTime = time; + + ctx.clearRect(0, 0, width, height); + ctx.drawImage(cache, iShift, 0, croppedWidth, height, 0, 0, croppedWidth, height); + // save current canvas state into cached canvas + cachedCtx.clearRect(0, 0, width, height); + cachedCtx.drawImage(this.canvas, 0, 0, width, height); + } + + // @todo - Fix trigger mode + // allow to witch easily between the 2 modes + // setTrigger(bool) { + // this.params.trigger = bool; + // // clear canvas and cache + // this.ctx.clearRect(0, 0, this.params.width, this.params.height); + // this.cachedCtx.clearRect(0, 0, this.params.width, this.params.height); + // // reset _currentXPosition + // this._currentXPosition = 0; + // this.lastShiftError = 0; + // } + + // /** + // * Alternative drawing mode. + // * Draw from left to right, go back to left when > width + // */ + // triggerModeDraw(time, frame) { + // const width = this.params.width; + // const height = this.params.height; + // const duration = this.params.duration; + // const ctx = this.ctx; + + // const dt = time - this.previousTime; + // const fShift = (dt / duration) * width - this.lastShiftError; // px + // const iShift = Math.round(fShift); + // this.lastShiftError = iShift - fShift; + + // this.currentXPosition += iShift; + + // // draw the right part + // ctx.save(); + // ctx.translate(this.currentXPosition, 0); + // ctx.clearRect(-iShift, 0, iShift, height); + // this.drawCurve(frame, iShift); + // ctx.restore(); + + // // go back to the left of the canvas and redraw the same thing + // if (this.currentXPosition > width) { + // // go back to start + // this.currentXPosition -= width; + + // ctx.save(); + // ctx.translate(this.currentXPosition, 0); + // ctx.clearRect(-iShift, 0, iShift, height); + // this.drawCurve(frame, this.previousFrame, iShift); + // ctx.restore(); + // } + // } + + }]); + return BaseDisplay; +}(_BaseLfo3.default); + +exports.default = BaseDisplay; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/assign":60,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],4:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + radius: { + type: 'float', + min: 0, + default: 0, + metas: { kind: 'dynamic' } + }, + line: { + type: 'boolean', + default: true, + metas: { kind: 'dynamic' } + }, + colors: { + type: 'any', + default: null + } + + /** + * Breakpoint Function, display a stream of type `vector`. + * + * @memberof module:client.sink + * + * @param {Object} options - Override default parameters. + * @param {String} [options.colors=null] - Array of colors for each index of the + * vector. _dynamic parameter_ + * @param {String} [options.radius=0] - Radius of the dot at each value. + * _dynamic parameter_ + * @param {String} [options.line=true] - Display a line between each consecutive + * values of the vector. _dynamic parameter_ + * @param {Number} [options.min=-1] - Minimum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.max=1] - Maximum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. _dynamic parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const eventIn = new lfo.source.EventIn({ + * frameSize: 2, + * frameRate: 0.1, + * frameType: 'vector' + * }); + * + * const bpf = new lfo.sink.BpfDisplay({ + * canvas: '#bpf', + * duration: 10, + * }); + * + * eventIn.connect(bpf); + * eventIn.start(); + * + * let time = 0; + * const dt = 0.1; + * + * (function generateData() { + * eventIn.process(time, [Math.random() * 2 - 1, Math.random() * 2 - 1]); + * time += dt; + * + * setTimeout(generateData, dt * 1000); + * }()); + */ +}; +var BpfDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(BpfDisplay, _BaseDisplay); + + function BpfDisplay(options) { + (0, _classCallCheck3.default)(this, BpfDisplay); + + var _this = (0, _possibleConstructorReturn3.default)(this, (BpfDisplay.__proto__ || (0, _getPrototypeOf2.default)(BpfDisplay)).call(this, definitions, options)); + + _this.prevFrame = null; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(BpfDisplay, [{ + key: 'getMinimumFrameWidth', + value: function getMinimumFrameWidth() { + return this.params.get('radius'); + } + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(BpfDisplay.prototype.__proto__ || (0, _getPrototypeOf2.default)(BpfDisplay.prototype), 'resetStream', this).call(this); + + this.prevFrame = null; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + if (this.params.get('colors') === null) this.params.set('colors', (0, _displayUtils.getColors)('bpf', this.streamParams.frameSize)); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame, frameWidth, pixelsSinceLastFrame) { + var colors = this.params.get('colors'); + var radius = this.params.get('radius'); + var drawLine = this.params.get('line'); + var frameSize = this.streamParams.frameSize; + var ctx = this.ctx; + var data = frame.data; + var prevData = this.prevFrame ? this.prevFrame.data : null; + + ctx.save(); + + for (var i = 0, l = frameSize; i < l; i++) { + var posY = this.getYPosition(data[i]); + var color = colors[i]; + + ctx.strokeStyle = color; + ctx.fillStyle = color; + + if (prevData && drawLine) { + var lastPosY = this.getYPosition(prevData[i]); + ctx.beginPath(); + ctx.moveTo(-pixelsSinceLastFrame, lastPosY); + ctx.lineTo(0, posY); + ctx.stroke(); + ctx.closePath(); + } + + if (radius > 0) { + ctx.beginPath(); + ctx.arc(0, posY, radius, 0, Math.PI * 2, false); + ctx.fill(); + ctx.closePath(); + } + } + + ctx.restore(); + + this.prevFrame = frame; + } + }]); + return BpfDisplay; +}(_BaseDisplay3.default); + +exports.default = BpfDisplay; + +},{"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],5:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + threshold: { + type: 'float', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + }, + thresholdIndex: { + type: 'integer', + default: 0, + metas: { kind: 'dynamic' } + }, + color: { + type: 'string', + default: (0, _displayUtils.getColors)('marker'), + nullable: true, + metas: { kind: 'dynamic' } + } +}; + +/** + * Display a marker according to a `vector` input frame. + * + * @memberof module:client.sink + * + * @param {Object} options - Override default parameters. + * @param {String} options.color - Color of the marker. + * @param {Number} [options.thresholdIndex=0] - Index of the incomming frame + * data to compare against the threshold. _Should be used in conjonction with + * `threshold`_. + * @param {Number} [options.threshold=null] - Minimum value the incomming value + * must have to trigger the display of a marker. If null each incomming event + * triggers a marker. _Should be used in conjonction with `thresholdIndex`_. + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. This parameter only exists for operators that display several + * consecutive frames on the canvas. _dynamic parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. This parameter only exists + * for operators that display several consecutive frames on the canvas. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const eventIn = new lfo.source.EventIn({ + * frameType: 'scalar', + * }); + * + * const marker = new lfo.sink.MarkerDisplay({ + * canvas: '#marker', + * threshold: 0.5, + * }); + * + * eventIn.connect(marker); + * eventIn.start(); + * + * let time = 0; + * const period = 1; + * + * (function generateData() { + * eventIn.process(time, Math.random()); + * + * time += period; + * setTimeout(generateData, period * 1000); + * }()); + */ + +var MarkerDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(MarkerDisplay, _BaseDisplay); + + function MarkerDisplay() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, MarkerDisplay); + return (0, _possibleConstructorReturn3.default)(this, (MarkerDisplay.__proto__ || (0, _getPrototypeOf2.default)(MarkerDisplay)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(MarkerDisplay, [{ + key: 'processVector', + value: function processVector(frame, frameWidth, pixelsSinceLastFrame) { + var color = this.params.get('color'); + var threshold = this.params.get('threshold'); + var thresholdIndex = this.params.get('thresholdIndex'); + var ctx = this.ctx; + var height = ctx.height; + var value = frame.data[thresholdIndex]; + + if (threshold === null || value >= threshold) { + var yMin = this.getYPosition(this.params.get('min')); + var yMax = this.getYPosition(this.params.get('max')); + + if (yMin > yMax) { + var v = yMax; + yMax = yMin; + yMin = v; + } + + ctx.save(); + ctx.fillStyle = color; + ctx.fillRect(0, yMin, 1, yMax); + ctx.restore(); + } + } + }]); + return MarkerDisplay; +}(_BaseDisplay3.default); + +exports.default = MarkerDisplay; + +},{"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],6:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var floor = Math.floor; +var ceil = Math.ceil; + +function downSample(data, targetLength) { + var length = data.length; + var hop = length / targetLength; + var target = new Float32Array(targetLength); + var counter = 0; + + for (var i = 0; i < targetLength; i++) { + var index = floor(counter); + var phase = counter - index; + var prev = data[index]; + var next = data[index + 1]; + + target[i] = (next - prev) * phase + prev; + counter += hop; + } + + return target; +} + +var definitions = { + color: { + type: 'string', + default: (0, _displayUtils.getColors)('signal'), + nullable: true + } +}; + +/** + * Display a stream of type `signal` on a canvas. + * + * @param {Object} options - Override default parameters. + * @param {String} [options.color='#00e600'] - Color of the signal. + * @param {Number} [options.min=-1] - Minimum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.max=1] - Maximum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. This parameter only exists for operators that display several + * consecutive frames on the canvas. _dynamic parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. This parameter only exists + * for operators that display several consecutive frames on the canvas. + * + * @memberof module:client.sink + * + * @example + * const eventIn = new lfo.source.EventIn({ + * frameType: 'signal', + * sampleRate: 8, + * frameSize: 4, + * }); + * + * const signalDisplay = new lfo.sink.SignalDisplay({ + * canvas: '#signal-canvas', + * }); + * + * eventIn.connect(signalDisplay); + * eventIn.start(); + * + * // push triangle signal in the graph + * eventIn.process(0, [0, 0.5, 1, 0.5]); + * eventIn.process(0.5, [0, -0.5, -1, -0.5]); + * // ... + */ + +var SignalDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(SignalDisplay, _BaseDisplay); + + function SignalDisplay(options) { + (0, _classCallCheck3.default)(this, SignalDisplay); + + var _this = (0, _possibleConstructorReturn3.default)(this, (SignalDisplay.__proto__ || (0, _getPrototypeOf2.default)(SignalDisplay)).call(this, definitions, options, true)); + + _this.lastPosY = null; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(SignalDisplay, [{ + key: 'processSignal', + value: function processSignal(frame, frameWidth, pixelsSinceLastFrame) { + var color = this.params.get('color'); + var frameSize = this.streamParams.frameSize; + var ctx = this.ctx; + var data = frame.data; + + if (frameWidth < frameSize) data = downSample(data, frameWidth); + + var length = data.length; + var hopX = frameWidth / length; + var posX = 0; + var lastY = this.lastPosY; + + ctx.strokeStyle = color; + ctx.beginPath(); + + for (var i = 0; i < data.length; i++) { + var posY = this.getYPosition(data[i]); + + if (lastY === null) { + ctx.moveTo(posX, posY); + } else { + if (i === 0) ctx.moveTo(-hopX, lastY); + + ctx.lineTo(posX, posY); + } + + posX += hopX; + lastY = posY; + } + + ctx.stroke(); + ctx.closePath(); + + this.lastPosY = lastY; + } + }]); + return SignalDisplay; +}(_BaseDisplay3.default); + +exports.default = SignalDisplay; + +},{"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],7:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _promise = require('babel-runtime/core-js/promise'); + +var _promise2 = _interopRequireDefault(_promise); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +var _wsUtils = require('../../common/utils/wsUtils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var parameters = { + port: { + type: 'integer', + default: 8000, + nullable: true, + constant: true + }, + url: { + type: 'string', + default: null, + nullable: true, + constant: true + } + + /** + * Send an lfo frame as a socket message to a `node.source.SocketReceive` + * instance. + * + *

Experimental

+ * + * @memberof module:client.sink + * + * @example + * const eventIn = new lfo.source.EventIn({ + * frameType: 'vector', + * frameSize: 2, + * frameRate: 1, + * }); + * + * const socketSend = new lfo.sink.SocketSend({ + * port: 3000 + * }); + * + * eventIn.connect(socketSend); + * + * eventIn.init().then(() => { + * eventIn.start(); + * + * let time = 0; + * + * (function createFrame() { + * eventIn.process(time, [Math.random(), Math.random()], { test: true }); + * time += 1; + * + * setTimeout(createFrame, 1000); + * }()); + * }); + */ +}; +var SocketSend = function (_BaseLfo) { + (0, _inherits3.default)(SocketSend, _BaseLfo); + + function SocketSend() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, SocketSend); + + var _this = (0, _possibleConstructorReturn3.default)(this, (SocketSend.__proto__ || (0, _getPrototypeOf2.default)(SocketSend)).call(this, parameters, options)); + + var protocol = window.location.protocol.replace(/^http/, 'ws'); + var address = _this.params.get('url') || window.location.hostname; + var port = _this.params.get('port') || ''; // everything falsy becomes '' + var socketAddress = protocol + '//' + address + ':' + port; + + _this.socket = new WebSocket(socketAddress); + _this.socket.binaryType = 'arraybuffer'; + + _this.openedPromise = new _promise2.default(function (resolve, reject) { + _this.socket.onopen = resolve; + }); + + _this.socket.onerror = function (err) { + return console.error(err.stack); + }; + return _this; + } + + (0, _createClass3.default)(SocketSend, [{ + key: 'initModule', + value: function initModule() { + var _this2 = this; + + // send a INIT_MODULE_REQ and wait for INIT_MODULE_ACK + // no need to get children promises as we are in a leef + return this.openedPromise.then(function () { + return new _promise2.default(function (resolve, reject) { + _this2.socket.onmessage = function (e) { + var opcode = _wsUtils.decoders.opcode(e.data); + + if (opcode === _wsUtils.opcodes.INIT_MODULE_ACK) resolve(); + }; + + var buffer = _wsUtils.encoders.initModuleReq(); + _this2.socket.send(buffer); + }); + }); + } + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + (0, _get3.default)(SocketSend.prototype.__proto__ || (0, _getPrototypeOf2.default)(SocketSend.prototype), 'processStreamParams', this).call(this, prevStreamParams); + + var buffer = _wsUtils.encoders.streamParams(this.streamParams); + this.socket.send(buffer); + } + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(SocketSend.prototype.__proto__ || (0, _getPrototypeOf2.default)(SocketSend.prototype), 'resetStream', this).call(this); + + var buffer = _wsUtils.encoders.resetStream(); + this.socket.send(buffer); + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + (0, _get3.default)(SocketSend.prototype.__proto__ || (0, _getPrototypeOf2.default)(SocketSend.prototype), 'finalizeStream', this).call(this, endTime); + + var buffer = _wsUtils.encoders.finalizeStream(endTime); + this.socket.send(buffer); + } + + // process any type + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar() {} + /** @private */ + + }, { + key: 'processVector', + value: function processVector() {} + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal() {} + }, { + key: 'processFrame', + value: function processFrame(frame) { + var frameSize = this.streamParams.frameSize; + this.frame.time = frame.time; + this.frame.data.set(frame.data, 0); + this.frame.metadata = frame.metadata; + + var buffer = _wsUtils.encoders.processFrame(this.frame, frameSize); + this.socket.send(buffer); + } + }]); + return SocketSend; +}(_BaseLfo3.default); + +exports.default = SocketSend; + +},{"../../common/utils/wsUtils":49,"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/core-js/promise":66,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],8:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _log = require('babel-runtime/core-js/math/log10'); + +var _log2 = _interopRequireDefault(_log); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _Fft = require('../../common/operator/Fft'); + +var _Fft2 = _interopRequireDefault(_Fft); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + scale: { + type: 'float', + default: 1, + metas: { kind: 'dynamic' } + }, + color: { + type: 'string', + default: (0, _displayUtils.getColors)('spectrum'), + nullable: true, + metas: { kind: 'dynamic' } + }, + min: { + type: 'float', + default: -80, + metas: { kind: 'dynamic' } + }, + max: { + type: 'float', + default: 6, + metas: { kind: 'dynamic' } + } +}; + +/** + * Display the spectrum of the incomming `signal` input. + * + * @memberof module:client.sink + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.scale=1] - Scale display of the spectrogram. + * @param {String} [options.color=null] - Color of the spectrogram. + * @param {Number} [options.min=-80] - Minimum displayed value (in dB). + * @param {Number} [options.max=6] - Maximum displayed value (in dB). + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * + * @todo - expose more `fft` config options + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * audioContext: audioContext, + * sourceNode: source, + * }); + * + * const spectrum = new lfo.sink.SpectrumDisplay({ + * canvas: '#spectrum', + * }); + * + * audioInNode.connect(spectrum); + * audioInNode.start(); + * } + */ + +var SpectrumDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(SpectrumDisplay, _BaseDisplay); + + function SpectrumDisplay() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, SpectrumDisplay); + return (0, _possibleConstructorReturn3.default)(this, (SpectrumDisplay.__proto__ || (0, _getPrototypeOf2.default)(SpectrumDisplay)).call(this, definitions, options, false)); + } + + /** @private */ + + + (0, _createClass3.default)(SpectrumDisplay, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.fft = new _Fft2.default({ + size: this.streamParams.frameSize, + window: 'hann', + norm: 'linear' + }); + + this.fft.initStream(this.streamParams); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + var bins = this.fft.inputSignal(frame.data); + var nbrBins = bins.length; + + var width = this.canvasWidth; + var height = this.canvasHeight; + var scale = this.params.get('scale'); + + var binWidth = width / nbrBins; + var ctx = this.ctx; + + ctx.fillStyle = this.params.get('color'); + + // error handling needs review... + var error = 0; + + for (var i = 0; i < nbrBins; i++) { + var x1Float = i * binWidth + error; + var x1Int = Math.round(x1Float); + var x2Float = x1Float + (binWidth - error); + var x2Int = Math.round(x2Float); + + error = x2Int - x2Float; + + if (x1Int !== x2Int) { + var _width = x2Int - x1Int; + var db = 20 * (0, _log2.default)(bins[i]); + var y = this.getYPosition(db * scale); + ctx.fillRect(x1Int, y, _width, height - y); + } else { + error -= binWidth; + } + } + } + }]); + return SpectrumDisplay; +}(_BaseDisplay3.default); + +exports.default = SpectrumDisplay; + +},{"../../common/operator/Fft":24,"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/math/log10":58,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],9:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + color: { + type: 'string', + default: (0, _displayUtils.getColors)('trace'), + metas: { kind: 'dynamic' } + }, + colorScheme: { + type: 'enum', + default: 'none', + list: ['none', 'hue', 'opacity'] + } +}; + +/** + * Display a range value around a mean value (for example mean + * and standart deviation). + * + * This sink can handle input of type `vector` of frameSize >= 2. + * + * @param {Object} options - Override default parameters. + * @param {String} [options.color='orange'] - Color. + * @param {String} [options.colorScheme='none'] - If a third value is available + * in the input, can be used to control the opacity or the hue. If input frame + * size is 2, this param is automatically set to `none` + * @param {Number} [options.min=-1] - Minimum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.max=1] - Maximum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. _dynamic parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. + * + * @memberof module:client.sink + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const AudioContext = (window.AudioContext || window.webkitAudioContext); + * const audioContext = new AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * sourceNode: source, + * audioContext: audioContext, + * }); + * + * // not sure it make sens but... + * const meanStddev = new lfo.operator.MeanStddev(); + * + * const traceDisplay = new lfo.sink.TraceDisplay({ + * canvas: '#trace', + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * audioInNode.connect(meanStddev); + * meanStddev.connect(traceDisplay); + * + * audioInNode.start(); + * } + */ + +var TraceDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(TraceDisplay, _BaseDisplay); + + function TraceDisplay() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, TraceDisplay); + + var _this = (0, _possibleConstructorReturn3.default)(this, (TraceDisplay.__proto__ || (0, _getPrototypeOf2.default)(TraceDisplay)).call(this, definitions, options)); + + _this.prevFrame = null; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(TraceDisplay, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + if (this.streamParams.frameSize === 2) this.params.set('colorScheme', 'none'); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame, frameWidth, pixelsSinceLastFrame) { + var colorScheme = this.params.get('colorScheme'); + var ctx = this.ctx; + var prevData = this.prevFrame ? this.prevFrame.data : null; + var data = frame.data; + + var halfRange = data[1] / 2; + var mean = this.getYPosition(data[0]); + var min = this.getYPosition(data[0] - halfRange); + var max = this.getYPosition(data[0] + halfRange); + + var prevHalfRange = void 0; + var prevMean = void 0; + var prevMin = void 0; + var prevMax = void 0; + + if (prevData !== null) { + prevHalfRange = prevData[1] / 2; + prevMean = this.getYPosition(prevData[0]); + prevMin = this.getYPosition(prevData[0] - prevHalfRange); + prevMax = this.getYPosition(prevData[0] + prevHalfRange); + } + + var color = this.params.get('color'); + var gradient = void 0; + var rgb = void 0; + + switch (colorScheme) { + case 'none': + rgb = (0, _displayUtils.hexToRGB)(color); + ctx.fillStyle = 'rgba(' + rgb.join(',') + ', 0.7)'; + ctx.strokeStyle = color; + break; + case 'hue': + gradient = ctx.createLinearGradient(-pixelsSinceLastFrame, 0, 0, 0); + + if (prevData) gradient.addColorStop(0, 'hsl(' + (0, _displayUtils.getHue)(prevData[2]) + ', 100%, 50%)');else gradient.addColorStop(0, 'hsl(' + (0, _displayUtils.getHue)(data[2]) + ', 100%, 50%)'); + + gradient.addColorStop(1, 'hsl(' + (0, _displayUtils.getHue)(data[2]) + ', 100%, 50%)'); + ctx.fillStyle = gradient; + break; + case 'opacity': + rgb = (0, _displayUtils.hexToRGB)(this.params.get('color')); + gradient = ctx.createLinearGradient(-pixelsSinceLastFrame, 0, 0, 0); + + if (prevData) gradient.addColorStop(0, 'rgba(' + rgb.join(',') + ', ' + prevData[2] + ')');else gradient.addColorStop(0, 'rgba(' + rgb.join(',') + ', ' + data[2] + ')'); + + gradient.addColorStop(1, 'rgba(' + rgb.join(',') + ', ' + data[2] + ')'); + ctx.fillStyle = gradient; + break; + } + + ctx.save(); + // draw range + ctx.beginPath(); + ctx.moveTo(0, mean); + ctx.lineTo(0, max); + + if (prevData !== null) { + ctx.lineTo(-pixelsSinceLastFrame, prevMax); + ctx.lineTo(-pixelsSinceLastFrame, prevMin); + } + + ctx.lineTo(0, min); + ctx.closePath(); + + ctx.fill(); + + // draw mean + if (colorScheme === 'none' && prevMean) { + ctx.beginPath(); + ctx.moveTo(-pixelsSinceLastFrame, prevMean); + ctx.lineTo(0, mean); + ctx.closePath(); + ctx.stroke(); + } + + ctx.restore(); + + this.prevFrame = frame; + } + }]); + return TraceDisplay; +}(_BaseDisplay3.default); + +; + +exports.default = TraceDisplay; + +},{"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],10:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _log = require('babel-runtime/core-js/math/log10'); + +var _log2 = _interopRequireDefault(_log); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _Rms = require('../../common/operator/Rms'); + +var _Rms2 = _interopRequireDefault(_Rms); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var log10 = _log2.default; + +var definitions = { + offset: { + type: 'float', + default: -14, + metas: { kind: 'dyanmic' } + }, + min: { + type: 'float', + default: -80, + metas: { kind: 'dynamic' } + }, + max: { + type: 'float', + default: 6, + metas: { kind: 'dynamic' } + }, + width: { + type: 'integer', + default: 6, + metas: { kind: 'dynamic' } + } + + /** + * Simple VU-Meter to used on a `signal` stream. + * + * @memberof module:client.sink + * + * @param {Object} options - Override defaults parameters. + * @param {Number} [options.offset=-14] - dB offset applied to the signal. + * @param {Number} [options.min=-80] - Minimum displayed value (in dB). + * @param {Number} [options.max=6] - Maximum displayed value (in dB). + * @param {Number} [options.width=6] - Width of the display (in pixels). + * @param {Number} [options.height=150] - Height of the canvas. + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new window.AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * audioContext: audioContext, + * sourceNode: source, + * }); + * + * const vuMeter = new lfo.sink.VuMeterDisplay({ + * canvas: '#vu-meter', + * }); + * + * audioInNode.connect(vuMeter); + * audioInNode.start(); + * } + */ +}; +var VuMeterDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(VuMeterDisplay, _BaseDisplay); + + function VuMeterDisplay() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, VuMeterDisplay); + + var _this = (0, _possibleConstructorReturn3.default)(this, (VuMeterDisplay.__proto__ || (0, _getPrototypeOf2.default)(VuMeterDisplay)).call(this, definitions, options, false)); + + _this.rmsOperator = new _Rms2.default(); + + _this.lastDB = 0; + _this.peak = { + value: 0, + time: 0 + }; + + _this.peakLifetime = 1; // sec + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(VuMeterDisplay, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.rmsOperator.initStream(this.streamParams); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + var now = new Date().getTime() / 1000; // sec + var offset = this.params.get('offset'); // offset zero of the vu meter + var height = this.canvasHeight; + var width = this.canvasWidth; + var ctx = this.ctx; + + var lastDB = this.lastDB; + var peak = this.peak; + + var red = '#ff2121'; + var yellow = '#ffff1f'; + var green = '#00ff00'; + + // handle current db value + var rms = this.rmsOperator.inputSignal(frame.data); + var dB = 20 * log10(rms) - offset; + + // slow release (could probably be improved) + if (lastDB > dB) dB = lastDB - 6; + + // handle peak + if (dB > peak.value || now - peak.time > this.peakLifetime) { + peak.value = dB; + peak.time = now; + } + + var y0 = this.getYPosition(0); + var y = this.getYPosition(dB); + var yPeak = this.getYPosition(peak.value); + + ctx.save(); + + ctx.fillStyle = '#000000'; + ctx.fillRect(0, 0, width, height); + + var gradient = ctx.createLinearGradient(0, height, 0, 0); + gradient.addColorStop(0, green); + gradient.addColorStop((height - y0) / height, yellow); + gradient.addColorStop(1, red); + + // dB + ctx.fillStyle = gradient; + ctx.fillRect(0, y, width, height - y); + + // 0 dB marker + ctx.fillStyle = '#dcdcdc'; + ctx.fillRect(0, y0, width, 2); + + // peak + ctx.fillStyle = gradient; + ctx.fillRect(0, yPeak, width, 2); + + ctx.restore(); + + this.lastDB = dB; + } + }]); + return VuMeterDisplay; +}(_BaseDisplay3.default); + +exports.default = VuMeterDisplay; + +},{"../../common/operator/Rms":36,"./BaseDisplay":3,"babel-runtime/core-js/math/log10":58,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],11:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseDisplay2 = require('./BaseDisplay'); + +var _BaseDisplay3 = _interopRequireDefault(_BaseDisplay2); + +var _MinMax = require('../../common/operator/MinMax'); + +var _MinMax2 = _interopRequireDefault(_MinMax); + +var _Rms = require('../../common/operator/Rms'); + +var _Rms2 = _interopRequireDefault(_Rms); + +var _displayUtils = require('../utils/display-utils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + colors: { + type: 'any', + default: (0, _displayUtils.getColors)('waveform'), + metas: { kind: 'dyanmic' } + }, + rms: { + type: 'boolean', + default: false, + metas: { kind: 'dyanmic' } + } +}; + +/** + * Display a waveform (along with optionnal Rms) of a given `signal` input in + * a canvas. + * + * @param {Object} options - Override default parameters. + * @param {Array} [options.colors=['waveform', 'rms']] - Array + * containing the color codes for the waveform (index 0) and rms (index 1). + * _dynamic parameter_ + * @param {Boolean} [options.rms=false] - Set to `true` to display the rms. + * _dynamic parameter_ + * @param {Number} [options.duration=1] - Duration (in seconds) represented in + * the canvas. _dynamic parameter_ + * @param {Number} [options.min=-1] - Minimum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.max=1] - Maximum value represented in the canvas. + * _dynamic parameter_ + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * @param {Number} [options.referenceTime=null] - Optionnal reference time the + * display should considerer as the origin. Is only usefull when synchronizing + * several display using the `DisplaySync` class. + * + * @memberof module:client.sink + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new window.AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const audioIn = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * audioContext: audioContext, + * sourceNode: audioIn, + * frameSize: 512, + * }); + * + * const waveformDisplay = new lfo.sink.WaveformDisplay({ + * canvas: '#waveform', + * duration: 3.5, + * rms: true, + * }); + * + * audioInNode.connect(waveformDisplay); + * audioInNode.start(); + * }); + */ + +var WaveformDisplay = function (_BaseDisplay) { + (0, _inherits3.default)(WaveformDisplay, _BaseDisplay); + + function WaveformDisplay(options) { + (0, _classCallCheck3.default)(this, WaveformDisplay); + + var _this = (0, _possibleConstructorReturn3.default)(this, (WaveformDisplay.__proto__ || (0, _getPrototypeOf2.default)(WaveformDisplay)).call(this, definitions, options, true)); + + _this.minMaxOperator = new _MinMax2.default(); + _this.rmsOperator = new _Rms2.default(); + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(WaveformDisplay, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.minMaxOperator.initStream(this.streamParams); + this.rmsOperator.initStream(this.streamParams); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame, frameWidth, pixelsSinceLastFrame) { + // drop frames that cannot be displayed + if (frameWidth < 1) return; + + var colors = this.params.get('colors'); + var showRms = this.params.get('rms'); + var ctx = this.ctx; + var data = frame.data; + var iSamplesPerPixels = Math.floor(data.length / frameWidth); + + for (var index = 0; index < frameWidth; index++) { + var start = index * iSamplesPerPixels; + var end = index === frameWidth - 1 ? undefined : start + iSamplesPerPixels; + var slice = data.subarray(start, end); + + var minMax = this.minMaxOperator.inputSignal(slice); + var minY = this.getYPosition(minMax[0]); + var maxY = this.getYPosition(minMax[1]); + + ctx.strokeStyle = colors[0]; + ctx.beginPath(); + ctx.moveTo(index, minY); + ctx.lineTo(index, maxY); + ctx.closePath(); + ctx.stroke(); + + if (showRms) { + var rms = this.rmsOperator.inputSignal(slice); + var rmsMaxY = this.getYPosition(rms); + var rmsMinY = this.getYPosition(-rms); + + ctx.strokeStyle = colors[1]; + ctx.beginPath(); + ctx.moveTo(index, rmsMinY); + ctx.lineTo(index, rmsMaxY); + ctx.closePath(); + ctx.stroke(); + } + } + } + }]); + return WaveformDisplay; +}(_BaseDisplay3.default); + +exports.default = WaveformDisplay; + +},{"../../common/operator/MinMax":30,"../../common/operator/Rms":36,"../utils/display-utils":19,"./BaseDisplay":3,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],12:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Bridge = require('../../common/sink/Bridge'); + +var _Bridge2 = _interopRequireDefault(_Bridge); + +var _Logger = require('../../common/sink/Logger'); + +var _Logger2 = _interopRequireDefault(_Logger); + +var _DataRecorder = require('../../common/sink/DataRecorder'); + +var _DataRecorder2 = _interopRequireDefault(_DataRecorder); + +var _SignalRecorder = require('../../common/sink/SignalRecorder'); + +var _SignalRecorder2 = _interopRequireDefault(_SignalRecorder); + +var _BaseDisplay = require('./BaseDisplay'); + +var _BaseDisplay2 = _interopRequireDefault(_BaseDisplay); + +var _BarChartDisplay = require('./BarChartDisplay'); + +var _BarChartDisplay2 = _interopRequireDefault(_BarChartDisplay); + +var _BpfDisplay = require('./BpfDisplay'); + +var _BpfDisplay2 = _interopRequireDefault(_BpfDisplay); + +var _MarkerDisplay = require('./MarkerDisplay'); + +var _MarkerDisplay2 = _interopRequireDefault(_MarkerDisplay); + +var _SignalDisplay = require('./SignalDisplay'); + +var _SignalDisplay2 = _interopRequireDefault(_SignalDisplay); + +var _SocketSend = require('./SocketSend'); + +var _SocketSend2 = _interopRequireDefault(_SocketSend); + +var _SpectrumDisplay = require('./SpectrumDisplay'); + +var _SpectrumDisplay2 = _interopRequireDefault(_SpectrumDisplay); + +var _TraceDisplay = require('./TraceDisplay'); + +var _TraceDisplay2 = _interopRequireDefault(_TraceDisplay); + +var _VuMeterDisplay = require('./VuMeterDisplay'); + +var _VuMeterDisplay2 = _interopRequireDefault(_VuMeterDisplay); + +var _WaveformDisplay = require('./WaveformDisplay'); + +var _WaveformDisplay2 = _interopRequireDefault(_WaveformDisplay); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// client only +// common +exports.default = { + Bridge: _Bridge2.default, + Logger: _Logger2.default, + DataRecorder: _DataRecorder2.default, + SignalRecorder: _SignalRecorder2.default, + + BaseDisplay: _BaseDisplay2.default, + BarChartDisplay: _BarChartDisplay2.default, + BpfDisplay: _BpfDisplay2.default, + MarkerDisplay: _MarkerDisplay2.default, + SignalDisplay: _SignalDisplay2.default, + SocketSend: _SocketSend2.default, + SpectrumDisplay: _SpectrumDisplay2.default, + TraceDisplay: _TraceDisplay2.default, + VuMeterDisplay: _VuMeterDisplay2.default, + WaveformDisplay: _WaveformDisplay2.default +}; + +},{"../../common/sink/Bridge":43,"../../common/sink/DataRecorder":44,"../../common/sink/Logger":45,"../../common/sink/SignalRecorder":46,"./BarChartDisplay":2,"./BaseDisplay":3,"./BpfDisplay":4,"./MarkerDisplay":5,"./SignalDisplay":6,"./SocketSend":7,"./SpectrumDisplay":8,"./TraceDisplay":9,"./VuMeterDisplay":10,"./WaveformDisplay":11}],13:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); + +var _defineProperty3 = _interopRequireDefault(_defineProperty2); + +var _definitions; + +var _BaseLfo = require('../../core/BaseLfo'); + +var _BaseLfo2 = _interopRequireDefault(_BaseLfo); + +var _SourceMixin2 = require('../../core/SourceMixin'); + +var _SourceMixin3 = _interopRequireDefault(_SourceMixin2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = (_definitions = { + audioBuffer: { + type: 'any', + default: null, + constant: true + }, + frameSize: { + type: 'integer', + default: 512, + constant: true + }, + channel: { + type: 'integer', + default: 0, + constant: true + }, + progressCallback: { + type: 'any', + default: null, + nullable: true, + constant: true + } +}, (0, _defineProperty3.default)(_definitions, 'progressCallback', { + type: 'any', + default: null, + nullable: true, + constant: true +}), (0, _defineProperty3.default)(_definitions, 'async', { + type: 'boolean', + default: false +}), _definitions); + +var noop = function noop() {}; + +/** + * Slice an `AudioBuffer` into signal blocks and propagate the resulting frames + * through the graph. + * + * @param {Object} options - Override parameter' default values. + * @param {AudioBuffer} [options.audioBuffer] - Audio buffer to process. + * @param {Number} [options.frameSize=512] - Size of the output blocks. + * @param {Number} [options.channel=0] - Number of the channel to process. + * @param {Number} [options.progressCallback=null] - Callback to be excuted on each + * frame output, receive as argument the current progress ratio. + * + * @memberof module:client.source + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioInBuffer = new lfo.source.AudioInBuffer({ + * audioBuffer: audioBuffer, + * frameSize: 512, + * }); + * + * const waveform = new lfo.sink.Waveform({ + * canvas: '#waveform', + * duration: 1, + * color: 'steelblue', + * rms: true, + * }); + * + * audioInBuffer.connect(waveform); + * audioInBuffer.start(); + */ + +var AudioInBuffer = function (_SourceMixin) { + (0, _inherits3.default)(AudioInBuffer, _SourceMixin); + + function AudioInBuffer() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, AudioInBuffer); + + var _this = (0, _possibleConstructorReturn3.default)(this, (AudioInBuffer.__proto__ || (0, _getPrototypeOf2.default)(AudioInBuffer)).call(this, definitions, options)); + + var audioBuffer = _this.params.get('audioBuffer'); + + if (!audioBuffer) throw new Error('Invalid "audioBuffer" parameter'); + + _this.endTime = 0; + return _this; + } + + /** + * Propagate the `streamParams` in the graph and start propagating frames. + * When called, the slicing of the given `audioBuffer` starts immediately and + * each resulting frame is propagated in graph. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#resetStream} + * @see {@link module:client.source.AudioInBuffer#stop} + */ + + + (0, _createClass3.default)(AudioInBuffer, [{ + key: 'start', + value: function start() { + if (this.initialized === false) { + if (this.initPromise === null) // init has not yet been called + this.initPromise = this.init(); + + this.initPromise.then(this.start); + return; + } + + var channel = this.params.get('channel'); + var audioBuffer = this.params.get('audioBuffer'); + var buffer = audioBuffer.getChannelData(channel); + this.endTime = 0; + this.started = true; + + this.processFrame(buffer); + } + + /** + * Finalize the stream and stop the whole graph. When called, the slicing of + * the `audioBuffer` stops immediately. + * + * @see {@link module:core.BaseLfo#finalizeStream} + * @see {@link module:client.source.AudioInBuffer#start} + */ + + }, { + key: 'stop', + value: function stop() { + this.finalizeStream(this.endTime); + this.started = false; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams() { + var audioBuffer = this.params.get('audioBuffer'); + var frameSize = this.params.get('frameSize'); + var sourceSampleRate = audioBuffer.sampleRate; + var frameRate = sourceSampleRate / frameSize; + + this.streamParams.frameSize = frameSize; + this.streamParams.frameRate = frameRate; + this.streamParams.frameType = 'signal'; + this.streamParams.sourceSampleRate = sourceSampleRate; + this.streamParams.sourceSampleCount = frameSize; + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(buffer) { + var async = this.params.get('async'); + var sampleRate = this.streamParams.sourceSampleRate; + var frameSize = this.streamParams.frameSize; + var progressCallback = this.params.get('progressCallback') || noop; + var length = buffer.length; + var nbrFrames = Math.ceil(buffer.length / frameSize); + var data = this.frame.data; + var that = this; + var i = 0; + + function slice() { + var offset = i * frameSize; + var nbrCopy = Math.min(length - offset, frameSize); + + for (var j = 0; j < frameSize; j++) { + data[j] = j < nbrCopy ? buffer[offset + j] : 0; + }that.frame.time = offset / sampleRate; + that.endTime = that.frame.time + nbrCopy / sampleRate; + that.propagateFrame(); + + i += 1; + progressCallback(i / nbrFrames); + + if (i < nbrFrames) { + if (async) setTimeout(slice, 0);else slice(); + } else { + that.finalizeStream(that.endTime); + } + }; + + // allow the following to do the expected thing: + // audioIn.connect(recorder); + // audioIn.start(); + // recorder.start(); + setTimeout(slice, 0); + } + }]); + return AudioInBuffer; +}((0, _SourceMixin3.default)(_BaseLfo2.default)); + +exports.default = AudioInBuffer; + +},{"../../core/BaseLfo":50,"../../core/SourceMixin":51,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/defineProperty":71,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],14:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo = require('../../core/BaseLfo'); + +var _BaseLfo2 = _interopRequireDefault(_BaseLfo); + +var _SourceMixin2 = require('../../core/SourceMixin'); + +var _SourceMixin3 = _interopRequireDefault(_SourceMixin2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var AudioContext = window.AudioContext || window.webkitAudioContext; + +var definitions = { + frameSize: { + type: 'integer', + default: 512, + constant: true + }, + channel: { + type: 'integer', + default: 0, + constant: true + }, + sourceNode: { + type: 'any', + default: null, + constant: true + }, + audioContext: { + type: 'any', + default: null, + constant: true + } +}; + +/** + * Use a `WebAudio` node as a source for the graph. + * + * @param {Object} options - Override parameter' default values. + * @param {AudioNode} [options.sourceNode=null] - Audio node to process + * (mandatory). + * @param {AudioContext} [options.audioContext=null] - Audio context used to + * create the audio node (mandatory). + * @param {Number} [options.frameSize=512] - Size of the output blocks, define + * the `frameSize` in the `streamParams`. + * @param {Number} [options.channel=0] - Number of the channel to process. + * + * @memberof module:client.source + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new AudioContext(); + * const sine = audioContext.createOscillator(); + * sine.frequency.value = 2; + * + * const audioInNode = new lfo.source.AudioInNode({ + * audioContext: audioContext, + * sourceNode: sine, + * }); + * + * const signalDisplay = new lfo.sink.SignalDisplay({ + * canvas: '#signal', + * duration: 1, + * }); + * + * audioInNode.connect(signalDisplay); + * + * // start the sine oscillator node and the lfo graph + * sine.start(); + * audioInNode.start(); + */ + +var AudioInNode = function (_SourceMixin) { + (0, _inherits3.default)(AudioInNode, _SourceMixin); + + function AudioInNode() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, AudioInNode); + + var _this = (0, _possibleConstructorReturn3.default)(this, (AudioInNode.__proto__ || (0, _getPrototypeOf2.default)(AudioInNode)).call(this, definitions, options)); + + var audioContext = _this.params.get('audioContext'); + var sourceNode = _this.params.get('sourceNode'); + + if (!audioContext || !(audioContext instanceof AudioContext)) throw new Error('Invalid `audioContext` parameter'); + + if (!sourceNode || !(sourceNode instanceof AudioNode)) throw new Error('Invalid `sourceNode` parameter'); + + _this.sourceNode = sourceNode; + _this._channel = _this.params.get('channel'); + _this._blockDuration = null; + + _this.processFrame = _this.processFrame.bind(_this); + return _this; + } + + /** + * Propagate the `streamParams` in the graph and start to propagate signal + * blocks produced by the audio node into the graph. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#resetStream} + * @see {@link module:client.source.AudioInNode#stop} + */ + + + (0, _createClass3.default)(AudioInNode, [{ + key: 'start', + value: function start() { + if (this.initialized === false) { + if (this.initPromise === null) // init has not yet been called + this.initPromise = this.init(); + + this.initPromise.then(this.start); + return; + } + + var audioContext = this.params.get('audioContext'); + var frameSize = this.params.get('frameSize'); + + this.frame.time = 0; + // @note: recreate each time because of a firefox weird behavior + this.scriptProcessor = audioContext.createScriptProcessor(frameSize, 1, 1); + this.scriptProcessor.onaudioprocess = this.processFrame; + + this.started = true; + this.sourceNode.connect(this.scriptProcessor); + this.scriptProcessor.connect(audioContext.destination); + } + + /** + * Finalize the stream and stop the whole graph. + * + * @see {@link module:core.BaseLfo#finalizeStream} + * @see {@link module:client.source.AudioInNode#start} + */ + + }, { + key: 'stop', + value: function stop() { + this.finalizeStream(this.frame.time); + this.started = false; + this.sourceNode.disconnect(); + this.scriptProcessor.disconnect(); + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams() { + var audioContext = this.params.get('audioContext'); + var frameSize = this.params.get('frameSize'); + var sampleRate = audioContext.sampleRate; + + this.streamParams.frameSize = frameSize; + this.streamParams.frameRate = sampleRate / frameSize; + this.streamParams.frameType = 'signal'; + this.streamParams.sourceSampleRate = sampleRate; + this.streamParams.sourceSampleCount = frameSize; + + this._blockDuration = frameSize / sampleRate; + + this.propagateStreamParams(); + } + + /** + * Basically the `scriptProcessor.onaudioprocess` callback + * @private + */ + + }, { + key: 'processFrame', + value: function processFrame(e) { + if (this.started === false) return; + + this.frame.data = e.inputBuffer.getChannelData(this._channel); + this.propagateFrame(); + + this.frame.time += this._blockDuration; + } + }]); + return AudioInNode; +}((0, _SourceMixin3.default)(_BaseLfo2.default)); + +exports.default = AudioInNode; + +},{"../../core/BaseLfo":50,"../../core/SourceMixin":51,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],15:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _promise = require('babel-runtime/core-js/promise'); + +var _promise2 = _interopRequireDefault(_promise); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +var _wsUtils = require('../../common/utils/wsUtils'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var parameters = { + port: { + type: 'integer', + default: 8000, + nullable: true, + constant: true + }, + url: { + type: 'string', + default: null, + nullable: true, + constant: true + } + + /** + * Receive an lfo frame as a socket message from a `node.sink.SocketSend` + * instance. + * + *

Experimental

+ * + * @memberof module:client.source + * + * @todo - handle init / start properly. + */ +}; +var SocketReceive = function (_BaseLfo) { + (0, _inherits3.default)(SocketReceive, _BaseLfo); + + function SocketReceive() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, SocketReceive); + + var _this = (0, _possibleConstructorReturn3.default)(this, (SocketReceive.__proto__ || (0, _getPrototypeOf2.default)(SocketReceive)).call(this, parameters, options)); + + var protocol = window.location.protocol.replace(/^http/, 'ws'); + var address = _this.params.get('url') || window.location.hostname; + var port = _this.params.get('port') || ''; // everything falsy becomes '' + var socketAddress = protocol + '//' + address + ':' + port; + + _this._dispatch = _this._dispatch.bind(_this); + + _this.socket = new WebSocket(socketAddress); + _this.socket.binaryType = 'arraybuffer'; + + _this.openedPromise = new _promise2.default(function (resolve, reject) { + _this.socket.onopen = resolve; + }); + + _this.socket.onmessage = _this._dispatch; + _this.socket.onerror = function (err) { + return console.error(err.stack); + }; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(SocketReceive, [{ + key: 'initModule', + value: function initModule() { + var _this2 = this; + + var promises = this.nextModules.map(function (mod) { + return mod.initModule(); + }); + promises.push(this.openedPromise); + // wait for children promises and send INIT_MODULE_ACK + _promise2.default.all(promises).then(function () { + var buffer = _wsUtils.encoders.initModuleAck(); + _this2.socket.send(buffer); + }); + } + + // process any type + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar() {} + /** @private */ + + }, { + key: 'processVector', + value: function processVector() {} + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal() {} + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + this.frame = frame; + this.propagateFrame(); + } + + /** + * Decode and dispatch incomming frame according to opcode + * @private + */ + + }, { + key: '_dispatch', + value: function _dispatch(e) { + var arrayBuffer = e.data; + var opcode = _wsUtils.decoders.opcode(arrayBuffer); + + switch (opcode) { + case _wsUtils.opcodes.INIT_MODULE_REQ: + this.initModule(); + break; + case _wsUtils.opcodes.PROCESS_STREAM_PARAMS: + var prevStreamParams = _wsUtils.decoders.streamParams(arrayBuffer); + this.processStreamParams(prevStreamParams); + break; + case _wsUtils.opcodes.RESET_STREAM: + this.resetStream(); + break; + case _wsUtils.opcodes.FINALIZE_STREAM: + var endTime = _wsUtils.decoders.finalizeStream(arrayBuffer); + this.finalizeStream(endTime); + break; + case _wsUtils.opcodes.PROCESS_FRAME: + var frameSize = this.streamParams.frameSize; + var frame = _wsUtils.decoders.processFrame(arrayBuffer, frameSize); + this.processFrame(frame); + break; + } + } + }]); + return SocketReceive; +}(_BaseLfo3.default); + +exports.default = SocketReceive; + +},{"../../common/utils/wsUtils":49,"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/core-js/promise":66,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],16:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _EventIn = require('../../common/source/EventIn'); + +var _EventIn2 = _interopRequireDefault(_EventIn); + +var _AudioInBuffer = require('./AudioInBuffer'); + +var _AudioInBuffer2 = _interopRequireDefault(_AudioInBuffer); + +var _AudioInNode = require('./AudioInNode'); + +var _AudioInNode2 = _interopRequireDefault(_AudioInNode); + +var _SocketReceive = require('./SocketReceive'); + +var _SocketReceive2 = _interopRequireDefault(_SocketReceive); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// common +exports.default = { + EventIn: _EventIn2.default, + + AudioInBuffer: _AudioInBuffer2.default, + AudioInNode: _AudioInNode2.default, + SocketReceive: _SocketReceive2.default +}; +// client only + +},{"../../common/source/EventIn":47,"./AudioInBuffer":13,"./AudioInNode":14,"./SocketReceive":15}],17:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require("babel-runtime/helpers/createClass"); + +var _createClass3 = _interopRequireDefault(_createClass2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Synchronize several display sinks to a common time. + * + * @param {...BaseDisplay} views - List of the display to synchronize. + * + * @memberof module:client.utils + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const eventIn1 = new lfo.source.EventIn({ + * frameType: 'scalar', + * frameSize: 1, + * }); + * + * const bpf1 = new lfo.sink.BpfDisplay({ + * canvas: '#bpf-1', + * duration: 2, + * startTime: 0, + * min: 0, + * colors: ['steelblue'], + * }); + * + * eventIn1.connect(bpf1); + * + * const eventIn2 = new lfo.source.EventIn({ + * frameType: 'scalar', + * frameSize: 1, + * }); + * + * const bpf2 = new lfo.sink.BpfDisplay({ + * canvas: '#bpf-2', + * duration: 2, + * startTime: 7, + * min: 0, + * colors: ['orange'], + * }); + * + * const displaySync = new lfo.utils.DisplaySync(bpf1, bpf2); + * + * eventIn2.connect(bpf2); + * + * eventIn1.start(); + * eventIn2.start(); + * + * let time = 0; + * const period = 0.4; + * const offset = 7.2; + * + * (function generateData() { + * const v = Math.random(); + * + * eventIn1.process(time, v); + * eventIn2.process(time + offset, v); + * + * time += period; + * + * setTimeout(generateData, period * 1000); + * }()); + */ +var DisplaySync = function () { + function DisplaySync() { + (0, _classCallCheck3.default)(this, DisplaySync); + + this.views = []; + + this.add.apply(this, arguments); + } + + /** @private */ + + + (0, _createClass3.default)(DisplaySync, [{ + key: "add", + value: function add() { + var _this = this; + + for (var _len = arguments.length, views = Array(_len), _key = 0; _key < _len; _key++) { + views[_key] = arguments[_key]; + } + + views.forEach(function (view) { + return _this.install(view); + }); + } + + /** @private */ + + }, { + key: "install", + value: function install(view) { + this.views.push(view); + + view.displaySync = this; + } + + /** @private */ + + }, { + key: "shiftSiblings", + value: function shiftSiblings(iShift, time, view) { + this.views.forEach(function (display) { + if (display !== view) display.shiftCanvas(iShift, time); + }); + } + }]); + return DisplaySync; +}(); + +exports.default = DisplaySync; + +},{"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70}],18:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _DisplaySync = require('./DisplaySync'); + +var _DisplaySync2 = _interopRequireDefault(_DisplaySync); + +var _windows = require('../../common/utils/windows'); + +var _windows2 = _interopRequireDefault(_windows); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + DisplaySync: _DisplaySync2.default, + initWindows: _windows2.default +}; + +},{"../../common/utils/windows":48,"./DisplaySync":17}],19:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var colors = ['#4682B4', '#ffa500', '#00e600', '#ff0000', '#800080', '#224153']; + +var getColors = exports.getColors = function getColors(type, nbr) { + switch (type) { + case 'signal': + return colors[0]; // steelblue + break; + case 'bpf': + if (nbr <= colors.length) { + return colors.slice(0, nbr); + } else { + var _colors = colors.slice(0); + while (_colors.length < nbr) { + _colors.push(getRandomColor()); + }return _colors; + } + break; + case 'waveform': + return [colors[0], colors[5]]; // steelblue / darkblue + break; + case 'marker': + return colors[3]; // red + break; + case 'spectrum': + return colors[2]; // green + break; + case 'trace': + return colors[1]; // orange + break; + case 'bar-chart': + return colors; + break; + } +}; + +// http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript +var getRandomColor = exports.getRandomColor = function getRandomColor() { + var letters = '0123456789ABCDEF'.split(''); + var color = '#'; + for (var i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; +}; + +// scale from domain [0, 1] to range [270, 0] to consume in +// hsl(x, 100%, 50%) color scheme +var getHue = exports.getHue = function getHue(x) { + var domainMin = 0; + var domainMax = 1; + var rangeMin = 270; + var rangeMax = 0; + + return (rangeMax - rangeMin) * (x - domainMin) / (domainMax - domainMin) + rangeMin; +}; + +var hexToRGB = exports.hexToRGB = function hexToRGB(hex) { + hex = hex.substring(1, 7); + var r = parseInt(hex.substring(0, 2), 16); + var g = parseInt(hex.substring(2, 4), 16); + var b = parseInt(hex.substring(4, 6), 16); + return [r, g, b]; +}; + +},{}],20:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sin = Math.sin; +var cos = Math.cos; +var sqrt = Math.sqrt; +var pow = Math.pow; +var _2PI = Math.PI * 2; + +// plot (from http://www.earlevel.com/scripts/widgets/20131013/biquads2.js) +// var len = 512; +// var magPlot = []; +// for (var idx = 0; idx < len; idx++) { +// var w; +// if (plotType == "linear") +// w = idx / (len - 1) * Math.PI; // 0 to pi, linear scale +// else +// w = Math.exp(Math.log(1 / 0.001) * idx / (len - 1)) * 0.001 * Math.PI; // 0.001 to 1, times pi, log scale + +// var phi = Math.pow(Math.sin(w/2), 2); +// var y = Math.log(Math.pow(a0+a1+a2, 2) - 4*(a0*a1 + 4*a0*a2 + a1*a2)*phi + 16*a0*a2*phi*phi) - Math.log(Math.pow(1+b1+b2, 2) - 4*(b1 + 4*b2 + b1*b2)*phi + 16*b2*phi*phi); +// y = y * 10 / Math.LN10 +// if (y == -Infinity) +// y = -200; + +// if (plotType == "linear") +// magPlot.push([idx / (len - 1) * Fs / 2, y]); +// else +// magPlot.push([idx / (len - 1) / 2, y]); + +// if (idx == 0) +// minVal = maxVal = y; +// else if (y < minVal) +// minVal = y; +// else if (y > maxVal) +// maxVal = y; +// } + +var definitions = { + type: { + type: 'enum', + default: 'lowpass', + list: ['lowpass', 'highpass', 'bandpass_constant_skirt', 'bandpass', 'bandpass_constant_peak', 'notch', 'allpass', 'peaking', 'lowshelf', 'highshelf'], + metas: { kind: 'dyanmic' } + }, + f0: { + type: 'float', + default: 1, + metas: { kind: 'dyanmic' } + }, + gain: { + type: 'float', + default: 1, + min: 0, + metas: { kind: 'dyanmic' } + }, + q: { + type: 'float', + default: 1, + min: 0.001, // PIPO_BIQUAD_MIN_Q + // max: 1, + metas: { kind: 'dyanmic' } + } + // bandwidth: { + // type: 'float', + // default: null, + // nullable: true, + // metas: { kind: 'dyanmic' }, + // }, + + + /** + * Biquad filter (Direct form I). If input is of type `vector` the filter is + * applied on each dimension i parallel. + * + * Based on the ["Cookbook formulae for audio EQ biquad filter coefficients"](http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt) + * by Robert Bristow-Johnson. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default values. + * @param {String} [options.type='lowpass'] - Type of the filter. Available + * filters: 'lowpass', 'highpass', 'bandpass_constant_skirt', 'bandpass_constant_peak' + * (alias 'bandpass'), 'notch', 'allpass', 'peaking', 'lowshelf', 'highshelf'. + * @param {Number} [options.f0=1] - Cutoff or center frequency of the filter + * according to its type. + * @param {Number} [options.gain=1] - Gain of the filter (in dB). + * @param {Number} [options.q=1] - Quality factor of the filter. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioInBuffer = new lfo.source.AudioInBuffer({ + * audioBuffer: buffer, + * }); + * + * const biquad = new lfo.operator.Biquad({ + * type: 'lowpass', + * f0: 2000, + * gain: 3, + * q: 12, + * }); + * + * const spectrumDisplay = new lfo.sink.SpectrumDisplay({ + * canvas: '#spectrum', + * }); + * + * audioInBuffer.connect(biquad); + * biquad.connect(spectrumDisplay); + * + * audioInBuffer.start(); + */ +}; +var Biquad = function (_BaseLfo) { + (0, _inherits3.default)(Biquad, _BaseLfo); + + function Biquad() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Biquad); + return (0, _possibleConstructorReturn3.default)(this, (Biquad.__proto__ || (0, _getPrototypeOf2.default)(Biquad)).call(this, definitions, options)); + } + + (0, _createClass3.default)(Biquad, [{ + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + this._calculateCoefs(); + } + }, { + key: '_calculateCoefs', + value: function _calculateCoefs() { + var sampleRate = this.streamParams.sourceSampleRate; + var frameType = this.streamParams.frameType; + var frameSize = this.streamParams.frameSize; + + var type = this.params.get('type'); + var f0 = this.params.get('f0'); + var gain = this.params.get('gain'); + var q = this.params.get('q'); + // const bandwidth = this.params.get('bandwidth'); + var bandwidth = null; + + var b0 = 0, + b1 = 0, + b2 = 0, + a0 = 0, + a1 = 0, + a2 = 0; + + var A = pow(10, gain / 40); + var w0 = _2PI * f0 / sampleRate; + var cosW0 = cos(w0); + var sinW0 = sin(w0); + var alpha = void 0; // depend of the filter type + var _2RootAAlpha = void 0; // intermediate value for lowshelf and highshelf + + switch (type) { + // H(s) = 1 / (s^2 + s/Q + 1) + case 'lowpass': + alpha = sinW0 / (2 * q); + b0 = (1 - cosW0) / 2; + b1 = 1 - cosW0; + b2 = b0; + a0 = 1 + alpha; + a1 = -2 * cosW0; + a2 = 1 - alpha; + break; + // H(s) = s^2 / (s^2 + s/Q + 1) + case 'highpass': + alpha = sinW0 / (2 * q); + b0 = (1 + cosW0) / 2; + b1 = -(1 + cosW0); + b2 = b0; + a0 = 1 + alpha; + a1 = -2 * cosW0; + a2 = 1 - alpha; + break; + // H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) + case 'bandpass_constant_skirt': + if (bandwidth) { + // sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) + } else { + alpha = sinW0 / (2 * q); + } + + b0 = sinW0 / 2; + b1 = 0; + b2 = -b0; + a0 = 1 + alpha; + a1 = -2 * cosW0; + a2 = 1 - alpha; + break; + // H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) + case 'bandpass': // looks like what is gnerally considered as a bandpass + case 'bandpass_constant_peak': + if (bandwidth) { + // sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) + } else { + alpha = sinW0 / (2 * q); + } + + b0 = alpha; + b1 = 0; + b2 = -alpha; + a0 = 1 + alpha; + a1 = -2 * cosW0; + a2 = 1 - alpha; + break; + // H(s) = (s^2 + 1) / (s^2 + s/Q + 1) + case 'notch': + alpha = sinW0 / (2 * q); + b0 = 1; + b1 = -2 * cosW0; + b2 = 1; + a0 = 1 + alpha; + a1 = b1; + a2 = 1 - alpha; + break; + // H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) + case 'allpass': + alpha = sinW0 / (2 * q); + b0 = 1 - alpha; + b1 = -2 * cosW0; + b2 = 1 + alpha; + a0 = b2; + a1 = b1; + a2 = b0; + break; + // H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) + case 'peaking': + if (bandwidth) { + // sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) + } else { + alpha = sinW0 / (2 * q); + } + + b0 = 1 + alpha * A; + b1 = -2 * cosW0; + b2 = 1 - alpha * A; + a0 = 1 + alpha / A; + a1 = b1; + a2 = 1 - alpha / A; + break; + // H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) + case 'lowshelf': + alpha = sinW0 / (2 * q); + _2RootAAlpha = 2 * sqrt(A) * alpha; + + b0 = A * (A + 1 - (A - 1) * cosW0 + _2RootAAlpha); + b1 = 2 * A * (A - 1 - (A + 1) * cosW0); + b2 = A * (A + 1 - (A - 1) * cosW0 - _2RootAAlpha); + a0 = A + 1 + (A - 1) * cosW0 + _2RootAAlpha; + a1 = -2 * (A - 1 + (A + 1) * cosW0); + a2 = A + 1 + (A - 1) * cosW0 - _2RootAAlpha; + break; + // H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) + case 'highshelf': + alpha = sinW0 / (2 * q); + _2RootAAlpha = 2 * sqrt(A) * alpha; + + b0 = A * (A + 1 + (A - 1) * cosW0 + _2RootAAlpha); + b1 = -2 * A * (A - 1 + (A + 1) * cosW0); + b2 = A * (A + 1 + (A - 1) * cosW0 - _2RootAAlpha); + a0 = A + 1 - (A - 1) * cosW0 + _2RootAAlpha; + a1 = 2 * (A - 1 - (A + 1) * cosW0); + a2 = A + 1 - (A - 1) * cosW0 - _2RootAAlpha; + + break; + } + + this.coefs = { + b0: b0 / a0, + b1: b1 / a0, + b2: b2 / a0, + a1: a1 / a0, + a2: a2 / a0 + }; + + // reset state + if (frameType === 'signal') { + this.state = { x1: 0, x2: 0, y1: 0, y2: 0 }; + } else { + this.state = { + x1: new Float32Array(frameSize), + x2: new Float32Array(frameSize), + y1: new Float32Array(frameSize), + y2: new Float32Array(frameSize) + }; + } + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + // if no `sampleRate` or `sampleRate` is 0 we shall halt! + var sampleRate = this.streamParams.sourceSampleRate; + + if (!sampleRate || sampleRate <= 0) throw new Error('Invalid sampleRate value (0) for biquad'); + + this._calculateCoefs(); + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + var frameSize = this.streamParams.frameSize; + var outData = this.frame.data; + var inData = frame.data; + var state = this.state; + var coefs = this.coefs; + + for (var i = 0; i < frameSize; i++) { + var x = inData[i]; + var y = coefs.b0 * x + coefs.b1 * state.x1[i] + coefs.b2 * state.x2[i] - coefs.a1 * state.y1[i] - coefs.a2 * state.y2[i]; + + outData[i] = y; + + // update states + state.x2[i] = state.x1[i]; + state.x1[i] = x; + state.y2[i] = state.y1[i]; + state.y1[i] = y; + } + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + var frameSize = this.streamParams.frameSize; + var outData = this.frame.data; + var inData = frame.data; + var state = this.state; + var coefs = this.coefs; + + for (var i = 0; i < frameSize; i++) { + var x = inData[i]; + var y = coefs.b0 * x + coefs.b1 * state.x1 + coefs.b2 * state.x2 - coefs.a1 * state.y1 - coefs.a2 * state.y2; + + outData[i] = y; + + // update states + state.x2 = state.x1; + state.x1 = x; + state.y2 = state.y1; + state.y1 = y; + } + } + }]); + return Biquad; +}(_BaseLfo3.default); + +exports.default = Biquad; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],21:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + min: { + type: 'float', + default: 0, + min: -Infinity, + max: +Infinity + }, + max: { + type: 'float', + default: 1, + min: -Infinity, + max: +Infinity + } +}; + +/** + * Clip incomming according to given `min` and `max` parameters + * + * @param {Object} options - Override default paramters + * @param {Number} [options.min=0] - Minimum value + * @param {Number} [options.max=1] - Maximum value + */ + +var Clip = function (_BaseLfo) { + (0, _inherits3.default)(Clip, _BaseLfo); + + function Clip(options) { + (0, _classCallCheck3.default)(this, Clip); + return (0, _possibleConstructorReturn3.default)(this, (Clip.__proto__ || (0, _getPrototypeOf2.default)(Clip)).call(this, definitions, options)); + } + + (0, _createClass3.default)(Clip, [{ + key: 'inputVector', + value: function inputVector(data) { + var min = this.params.get('min'); + var max = this.params.get('max'); + var frameSize = this.streamParams.frameSize; + var outData = this.frame.data; + + // @todo - could handle vector as min and max + for (var i = 0; i < frameSize; i++) { + outData[i] = Math.min(max, Math.max(min, data[i])); + }return outData; + } + }, { + key: 'processVector', + value: function processVector(frame) { + this.frame.data = this.inputVector(frame.data); + } + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var min = this.params.get('min'); + var max = this.params.get('max'); + var frameSize = this.streamParams.frameSize; + var outData = this.frame.data; + + for (var i = 0; i < frameSize; i++) { + outData[i] = Math.min(max, Math.max(min, data[i])); + }return outData; + } + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.frame.data = this.inputSignal(frame.data); + } + }]); + return Clip; +}(_BaseLfo3.default); + +exports.default = Clip; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],22:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sqrt = Math.sqrt; +var cos = Math.cos; +var PI = Math.PI; + +// Dct Type 2 - orthogonal matrix scaling +function getDctWeights(order, N) { + var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'htk'; + + var weights = new Float32Array(N * order); + var piOverN = PI / N; + var scale0 = 1 / sqrt(2); + var scale = sqrt(2 / N); + + for (var k = 0; k < order; k++) { + var s = k === 0 ? scale0 * scale : scale; + // const s = scale; // rta doesn't apply k=0 scaling + + for (var n = 0; n < N; n++) { + weights[k * N + n] = s * cos(k * (n + 0.5) * piOverN); + } + } + + return weights; +} + +var definitions = { + order: { + type: 'integer', + default: 12, + metas: { kind: 'static' } + } +}; + +/** + * Compute the Discrete Cosine Transform of an input `signal` or `vector`. + * (HTK style weighting). + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.order=12] - Number of computed bins. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * // assuming some audio buffer + * const source = new AudioInBuffer({ + * audioBuffer: audioBuffer, + * useWorker: false, + * }); + * + * const slicer = new Slicer({ + * frameSize: 512, + * hopSize: 512, + * }); + * + * const dct = new Dct({ + * order: 12, + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * source.connect(slicer); + * slicer.connect(dct); + * dct.connect(logger); + * + * source.start(); + */ + +var Dct = function (_BaseLfo) { + (0, _inherits3.default)(Dct, _BaseLfo); + + function Dct() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Dct); + return (0, _possibleConstructorReturn3.default)(this, (Dct.__proto__ || (0, _getPrototypeOf2.default)(Dct)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Dct, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var order = this.params.get('order'); + var inFrameSize = prevStreamParams.frameSize; + + this.streamParams.frameSize = order; + this.streamParams.frameType = 'vector'; + this.streamParams.description = []; + + this.weightMatrix = getDctWeights(order, inFrameSize); + + this.propagateStreamParams(); + } + + /** + * Use the `Dct` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array} values - Input values. + * @return {Array} - Dct of the input array. + * + * @example + * const dct = new lfo.operator.Dct({ order: 12 }); + * // mandatory for use in standalone mode + * dct.initStream({ frameSize: 512, frameType: 'signal' }); + * dct.inputSignal(data); + */ + + }, { + key: 'inputSignal', + value: function inputSignal(values) { + var order = this.params.get('order'); + var frameSize = values.length; + var outFrame = this.frame.data; + var weights = this.weightMatrix; + + for (var k = 0; k < order; k++) { + var offset = k * frameSize; + outFrame[k] = 0; + + for (var n = 0; n < frameSize; n++) { + outFrame[k] += values[n] * weights[offset + n]; + } + } + + return outFrame; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.inputSignal(frame.data); + } + }]); + return Dct; +}(_BaseLfo3.default); + +exports.default = Dct; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],23:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function simpleLinearRegression(values, dt) { + // means + var xSum = 0; + var ySum = 0; + var length = values.length; + + for (var i = 0; i < length; i++) { + xSum += i * dt; + ySum += values[i]; + } + + var xMean = xSum / length; + var yMean = ySum / length; + + var sumDiffXMeanSquared = 0; // sum[ pow((x - xMean), 2) ] + var sumDiffYMeanSquared = 0; // sum[ pow((y - yMean), 2) ] + var sumDiffXYMean = 0; // sum[ (x - xMean)(y - yMean) ] + + for (var _i = 0; _i < length; _i++) { + var diffXMean = dt * _i - xMean; + var diffYMean = values[_i] - yMean; + + var diffXMeanSquared = diffXMean * diffXMean; + var diffYMeanSquared = diffYMean * diffYMean; + var diffXYMean = diffXMean * diffYMean; + + sumDiffXMeanSquared += diffXMeanSquared; + sumDiffYMeanSquared += diffYMeanSquared; + sumDiffXYMean += diffXYMean; + } + + // horizontal line, all y on same line + if (sumDiffYMeanSquared === 0) return 0; + + // Pearson correlation coefficient: + // cf. https://www.youtube.com/watch?v=2SCg8Kuh0tE + // + // ∑ [ (x - xMean)(y - yMean) ] + // r = ------------------------------------------------------ + // sqrt( ∑ [ pow((x - xMean), 2), pow((y - yMean), 2) ] ) + // + // + var r = sumDiffXYMean / Math.sqrt(sumDiffXMeanSquared * sumDiffYMeanSquared); + + // then we have: + // cf. https://www.youtube.com/watch?v=GhrxgbQnEEU + // + // y = a + bx + // where: + // Sy + // b = r * -- + // Sx + // + // a = yMean - b * xMean + // + // S for standard deviation + // ∑ [ pow((x - xMean), 2) ] + // Sx = sqrt( ------------------------- ) + // N - 1 + var Sx = Math.sqrt(sumDiffXMeanSquared / (length - 1)); + var Sy = Math.sqrt(sumDiffYMeanSquared / (length - 1)); + var b = r * (Sy / Sx); + + return b; +} + +var definitions = { + size: { + type: 'integer', + min: 2, + max: +Infinity, + default: 3 + }, + useFrameRate: { + type: 'integer', + min: 0, + max: +Infinity, + default: null, + nullable: true + } +}; + +/** + * Returns the simple derivative of successive value using + * simple linear regression. + * The current implementation assumes a fixed `frameRate` (`frame.time` is ignored) + * + * Before the module is filled, it outputs a value of 0. + * + * @param {Object} options - Override default parameters + * @param {Number} [options.size=3] - Size of the window + * @param {Number} [options.useFrameRate=null] - Override stream frame rate for + * the regression + */ + +var Delta = function (_BaseLfo) { + (0, _inherits3.default)(Delta, _BaseLfo); + + function Delta() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Delta); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Delta.__proto__ || (0, _getPrototypeOf2.default)(Delta)).call(this, definitions, options)); + + _this.buffers = null; + _this.ringIndex = 0; + _this.frameRate = null; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Delta, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var frameSize = this.streamParams.frameSize; + var size = this.params.get('size'); + var bufferSize = frameSize * size; + + this.buffers = []; + // counter before the operator starts outputing frames + this.ringIndex = 0; + this.frameRate = this.params.get('useFrameRate') === null ? this.streamParams.frameRate : this.params.get('useFrameRate'); + + for (var i = 0; i < frameSize; i++) { + this.buffers[i] = new Float32Array(size); + }this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(Delta.prototype.__proto__ || (0, _getPrototypeOf2.default)(Delta.prototype), 'resetStream', this).call(this); + + var frameSize = this.streamParams.frameSize; + var size = this.params.get('size'); + var buffers = this.buffers; + + for (var i = 0; i < frameSize; i++) { + for (var j = 0; j < size; j++) { + buffers[i][j] = 0; + } + } + + this.ringIndex = 0; + } + + /** + * Assume a stream of vector at a fixed `frameRate`. + */ + + }, { + key: 'inputVector', + value: function inputVector(data) { + var size = this.params.get('size'); + var outData = this.frame.data; + var frameSize = this.streamParams.frameSize; + // const frameRate = this.streamParams.frameRate; + var buffers = this.buffers; + var dt = 1 / this.frameRate; + + // console.log(dt); + + if (this.ringIndex < size) this.ringIndex += 1; + + // copy incomming data into buffer + for (var i = 0; i < frameSize; i++) { + var buffer = buffers[i]; + + // we need to keep the order of the incomming frames + // so we have to shift all the values in the buffers + for (var j = 1; j < size; j++) { + buffer[j - 1] = buffer[j]; + }buffer[size - 1] = data[i]; + + if (this.ringIndex >= size) outData[i] = simpleLinearRegression(buffer, dt);else outData[i] = 0; + } + + return outData; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.frame.data = this.inputVector(frame.data); + // center time according to delta size + var size = this.params.get('size'); + var frameRate = this.streamParams.frameRate; + this.frame.time -= 0.5 * (size - 1) / frameRate; + } + }]); + return Delta; +}(_BaseLfo3.default); + +exports.default = Delta; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],24:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +var _windows = require('../utils/windows'); + +var _windows2 = _interopRequireDefault(_windows); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js +/* + * Free Fft and convolution (JavaScript) + * + * Copyright (c) 2014 Project Nayuki + * http://www.nayuki.io/page/free-small-fft-in-multiple-languages + * + * (MIT License) + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + * + * Slightly restructured by Chris Cannam, cannam@all-day-breakfast.com + * + * @private + */ +/* + * Construct an object for calculating the discrete Fourier transform (DFT) of + * size n, where n is a power of 2. + * + * @private + */ +function FftNayuki(n) { + + this.n = n; + this.levels = -1; + + for (var i = 0; i < 32; i++) { + if (1 << i == n) { + this.levels = i; // Equal to log2(n) + } + } + + if (this.levels == -1) { + throw "Length is not a power of 2"; + } + + this.cosTable = new Array(n / 2); + this.sinTable = new Array(n / 2); + + for (var i = 0; i < n / 2; i++) { + this.cosTable[i] = Math.cos(2 * Math.PI * i / n); + this.sinTable[i] = Math.sin(2 * Math.PI * i / n); + } + + /* + * Computes the discrete Fourier transform (DFT) of the given complex vector, + * storing the result back into the vector. + * The vector's length must be equal to the size n that was passed to the + * object constructor, and this must be a power of 2. Uses the Cooley-Tukey + * decimation-in-time radix-2 algorithm. + * + * @private + */ + this.forward = function (real, imag) { + var n = this.n; + + // Bit-reversed addressing permutation + for (var i = 0; i < n; i++) { + var j = reverseBits(i, this.levels); + + if (j > i) { + var temp = real[i]; + real[i] = real[j]; + real[j] = temp; + temp = imag[i]; + imag[i] = imag[j]; + imag[j] = temp; + } + } + + // Cooley-Tukey decimation-in-time radix-2 Fft + for (var size = 2; size <= n; size *= 2) { + var halfsize = size / 2; + var tablestep = n / size; + + for (var i = 0; i < n; i += size) { + for (var j = i, k = 0; j < i + halfsize; j++, k += tablestep) { + var tpre = real[j + halfsize] * this.cosTable[k] + imag[j + halfsize] * this.sinTable[k]; + var tpim = -real[j + halfsize] * this.sinTable[k] + imag[j + halfsize] * this.cosTable[k]; + real[j + halfsize] = real[j] - tpre; + imag[j + halfsize] = imag[j] - tpim; + real[j] += tpre; + imag[j] += tpim; + } + } + } + + // Returns the integer whose value is the reverse of the lowest 'bits' + // bits of the integer 'x'. + function reverseBits(x, bits) { + var y = 0; + + for (var i = 0; i < bits; i++) { + y = y << 1 | x & 1; + x >>>= 1; + } + + return y; + } + }; + + /* + * Computes the inverse discrete Fourier transform (IDFT) of the given complex + * vector, storing the result back into the vector. + * The vector's length must be equal to the size n that was passed to the + * object constructor, and this must be a power of 2. This is a wrapper + * function. This transform does not perform scaling, so the inverse is not + * a true inverse. + * + * @private + */ + this.inverse = function (real, imag) { + forward(imag, real); + }; +} + +var sqrt = Math.sqrt; + +var isPowerOfTwo = function isPowerOfTwo(number) { + while (number % 2 === 0 && number > 1) { + number = number / 2; + }return number === 1; +}; + +var definitions = { + size: { + type: 'integer', + default: 1024, + metas: { kind: 'static' } + }, + window: { + type: 'enum', + list: ['none', 'hann', 'hanning', 'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'], + default: 'none', + metas: { kind: 'static' } + }, + mode: { + type: 'enum', + list: ['magnitude', 'power'], // add complex output + default: 'magnitude' + }, + norm: { + type: 'enum', + default: 'auto', + list: ['auto', 'none', 'linear', 'power'] + } + + /** + * Compute the Fast Fourier Transform of an incomming `signal`. + * + * Fft implementation by [Nayuki](https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js). + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.size=1024] - Size of the fft, should be a power of 2. + * If the frame size of the incomming signal is lower than this value, + * it is zero padded to match the fft size. + * @param {String} [options.window='none'] - Name of the window applied on the + * incomming signal. Available windows are: 'none', 'hann', 'hanning', + * 'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'. + * @param {String} [options.mode='magnitude'] - Type of the output (`magnitude` + * or `power`) + * @param {String} [options.norm='auto'] - Type of normalization applied on the + * output. Possible values are 'auto', 'none', 'linear', 'power'. When set to + * `auto`, a `linear` normalization is applied on the magnitude spectrum, while + * a `power` normalization is applied on the power spectrum. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * // assuming an `audioBuffer` exists + * const source = new lfo.source.AudioInBuffer({ audioBuffer }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: 256, + * }); + * + * const fft = new lfo.operator.Fft({ + * mode: 'power', + * window: 'hann', + * norm: 'power', + * size: 256, + * }); + * + * source.connect(slicer); + * slicer.connect(fft); + * source.start(); + * + * // > outputs 129 bins containing the values of the power spectrum (including + * // > DC and Nyuist frequencies). + * + * @todo - check if 'rectangle' and 'none' windows are not redondant. + * @todo - check default values for all params. + */ +}; +var Fft = function (_BaseLfo) { + (0, _inherits3.default)(Fft, _BaseLfo); + + function Fft() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Fft); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Fft.__proto__ || (0, _getPrototypeOf2.default)(Fft)).call(this, definitions, options)); + + _this.windowSize = null; + _this.normalizeCoefs = null; + _this.window = null; + _this.real = null; + _this.imag = null; + _this.fft = null; + + if (!isPowerOfTwo(_this.params.get('size'))) throw new Error('fftSize must be a power of two'); + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Fft, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + // set the output frame size + var inFrameSize = prevStreamParams.frameSize; + var fftSize = this.params.get('size'); + var mode = this.params.get('mode'); + var norm = this.params.get('norm'); + var windowName = this.params.get('window'); + // window `none` and `rectangle` are aliases + if (windowName === 'none') windowName = 'rectangle'; + + this.streamParams.frameSize = fftSize / 2 + 1; + this.streamParams.frameType = 'vector'; + this.streamParams.description = []; + // size of the window to apply on the input frame + this.windowSize = inFrameSize < fftSize ? inFrameSize : fftSize; + + // references to populate in the window functions (cf. `initWindow`) + this.normalizeCoefs = { linear: 0, power: 0 }; + this.window = new Float32Array(this.windowSize); + + (0, _windows2.default)(windowName, // name of the window + this.window, // buffer populated with the window signal + this.windowSize, // size of the window + this.normalizeCoefs // object populated with the normalization coefs + ); + + var _normalizeCoefs = this.normalizeCoefs, + linear = _normalizeCoefs.linear, + power = _normalizeCoefs.power; + + + switch (norm) { + case 'none': + this.windowNorm = 1; + break; + + case 'linear': + this.windowNorm = linear; + break; + + case 'power': + this.windowNorm = power; + break; + + case 'auto': + if (mode === 'magnitude') this.windowNorm = linear;else if (mode === 'power') this.windowNorm = power; + break; + } + + this.real = new Float32Array(fftSize); + this.imag = new Float32Array(fftSize); + this.fft = new FftNayuki(fftSize); + + this.propagateStreamParams(); + } + + /** + * Use the `Fft` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array} signal - Input values. + * @return {Array} - Fft of the input signal. + * + * @example + * const fft = new lfo.operator.Fft({ size: 512, window: 'hann' }); + * // mandatory for use in standalone mode + * fft.initStream({ frameSize: 256, frameType: 'signal' }); + * fft.inputSignal(signal); + */ + + }, { + key: 'inputSignal', + value: function inputSignal(signal) { + var mode = this.params.get('mode'); + var windowSize = this.windowSize; + var frameSize = this.streamParams.frameSize; + var fftSize = this.params.get('size'); + var outData = this.frame.data; + + // apply window on the input signal and reset imag buffer + for (var i = 0; i < windowSize; i++) { + this.real[i] = signal[i] * this.window[i] * this.windowNorm; + this.imag[i] = 0; + } + + // if real is bigger than input signal, fill with zeros + for (var _i = windowSize; _i < fftSize; _i++) { + this.real[_i] = 0; + this.imag[_i] = 0; + } + + this.fft.forward(this.real, this.imag); + + if (mode === 'magnitude') { + var norm = 1 / fftSize; + + // DC index + var realDc = this.real[0]; + var imagDc = this.imag[0]; + outData[0] = sqrt(realDc * realDc + imagDc * imagDc) * norm; + + // Nquyst index + var realNy = this.real[fftSize / 2]; + var imagNy = this.imag[fftSize / 2]; + outData[fftSize / 2] = sqrt(realNy * realNy + imagNy * imagNy) * norm; + + // power spectrum + for (var _i2 = 1, j = fftSize - 1; _i2 < fftSize / 2; _i2++, j--) { + var real = 0.5 * (this.real[_i2] + this.real[j]); + var imag = 0.5 * (this.imag[_i2] - this.imag[j]); + + outData[_i2] = 2 * sqrt(real * real + imag * imag) * norm; + } + } else if (mode === 'power') { + var _norm = 1 / (fftSize * fftSize); + + // DC index + var _realDc = this.real[0]; + var _imagDc = this.imag[0]; + outData[0] = (_realDc * _realDc + _imagDc * _imagDc) * _norm; + + // Nquyst index + var _realNy = this.real[fftSize / 2]; + var _imagNy = this.imag[fftSize / 2]; + outData[fftSize / 2] = (_realNy * _realNy + _imagNy * _imagNy) * _norm; + + // power spectrum + for (var _i3 = 1, _j = fftSize - 1; _i3 < fftSize / 2; _i3++, _j--) { + var _real = 0.5 * (this.real[_i3] + this.real[_j]); + var _imag = 0.5 * (this.imag[_i3] - this.imag[_j]); + + outData[_i3] = 4 * (_real * _real + _imag * _imag) * _norm; + } + } + + return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return Fft; +}(_BaseLfo3.default); + +exports.default = Fft; + +},{"../../core/BaseLfo":50,"../utils/windows":48,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],25:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sqrt = Math.sqrt; + +var definitions = { + normalize: { + type: 'boolean', + default: true, + metas: { kind: 'dynamic' } + }, + power: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + } + + /** + * Compute the magnitude of a `vector` input. + * + * _support `standalone` usage_ + * + * @param {Object} options - Override default parameters. + * @param {Boolean} [options.normalize=true] - Normalize output according to + * the vector size. + * @param {Boolean} [options.power=false] - If true, returns the squared + * magnitude (power). + * + * @memberof module:common.operator + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ frameSize: 2, frameType: 'vector' }); + * const magnitude = new lfo.operator.Magnitude(); + * const logger = new lfo.sink.Logger({ outFrame: true }); + * + * eventIn.connect(magnitude); + * magnitude.connect(logger); + * eventIn.start(); + * + * eventIn.process(null, [1, 1]); + * > [1] + * eventIn.process(null, [2, 2]); + * > [2.82842712475] + * eventIn.process(null, [3, 3]); + * > [4.24264068712] + */ +}; +var Magnitude = function (_BaseLfo) { + (0, _inherits3.default)(Magnitude, _BaseLfo); + + function Magnitude() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Magnitude); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Magnitude.__proto__ || (0, _getPrototypeOf2.default)(Magnitude)).call(this, definitions, options)); + + _this._normalize = _this.params.get('normalize'); + _this._power = _this.params.get('power'); + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Magnitude, [{ + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(Magnitude.prototype.__proto__ || (0, _getPrototypeOf2.default)(Magnitude.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + switch (name) { + case 'normalize': + this._normalize = value; + break; + case 'power': + this._power = value; + break; + } + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + this.streamParams.frameSize = 1; + this.streamParams.frameType = 'scalar'; + this.streamParams.description = ['magnitude']; + this.propagateStreamParams(); + } + + /** + * Use the `Magnitude` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array|Float32Array} values - Values to process. + * @return {Number} - Magnitude value. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const magnitude = new lfo.operator.Magnitude({ power: true }); + * magnitude.initStream({ frameType: 'vector', frameSize: 3 }); + * magnitude.inputVector([3, 3]); + * > 4.24264068712 + */ + + }, { + key: 'inputVector', + value: function inputVector(values) { + var length = values.length; + var sum = 0; + + for (var i = 0; i < length; i++) { + sum += values[i] * values[i]; + }var mag = sum; + + if (this._normalize) mag /= length; + + if (!this._power) mag = sqrt(mag); + + return mag; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.frame.data[0] = this.inputVector(frame.data); + } + }]); + return Magnitude; +}(_BaseLfo3.default); + +exports.default = Magnitude; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],26:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sqrt = Math.sqrt; + +/** + * Compute mean and standard deviation of a given `signal`. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * sourceNode: source, + * audioContext: audioContext, + * }); + * + * const meanStddev = new lfo.operator.MeanStddev(); + * + * const traceDisplay = new lfo.sink.TraceDisplay({ + * canvas: '#trace', + * }); + * + * audioInNode.connect(meanStddev); + * meanStddev.connect(traceDisplay); + * audioInNode.start(); + * } + */ + +var MeanStddev = function (_BaseLfo) { + (0, _inherits3.default)(MeanStddev, _BaseLfo); + + function MeanStddev() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, MeanStddev); + + // no options available, just throw an error if some param try to be set. + return (0, _possibleConstructorReturn3.default)(this, (MeanStddev.__proto__ || (0, _getPrototypeOf2.default)(MeanStddev)).call(this, {}, options)); + } + + /** @private */ + + + (0, _createClass3.default)(MeanStddev, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.streamParams.frameType = 'vector'; + this.streamParams.frameSize = 2; + this.streamParams.description = ['mean', 'stddev']; + + this.propagateStreamParams(); + } + + /** + * Use the `MeanStddev` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array|Float32Array} values - Values to process. + * @return {Array} - Mean and standart deviation of the input values. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const meanStddev = new lfo.operator.MeanStddev(); + * meanStddev.initStream({ frameType: 'vector', frameSize: 1024 }); + * meanStddev.inputVector(someSineSignal); + * > [0, 0.7071] + */ + + }, { + key: 'inputSignal', + value: function inputSignal(values) { + var outData = this.frame.data; + var length = values.length; + + var mean = 0; + var m2 = 0; + + // compute mean and variance with Welford algorithm + // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance + for (var i = 0; i < length; i++) { + var x = values[i]; + var delta = x - mean; + mean += delta / (i + 1); + m2 += delta * (x - mean); + } + + var variance = m2 / (length - 1); + var stddev = sqrt(variance); + + outData[0] = mean; + outData[1] = stddev; + + return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return MeanStddev; +}(_BaseLfo3.default); + +exports.default = MeanStddev; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],27:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _log = require('babel-runtime/core-js/math/log10'); + +var _log2 = _interopRequireDefault(_log); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var min = Math.min; +var max = Math.max; +var pow = Math.pow; +var log10 = _log2.default; + +function hertzToMelHtk(freqHz) { + return 2595 * (0, _log2.default)(1 + freqHz / 700); +} + +function melToHertzHtk(freqMel) { + return 700 * (Math.pow(10, freqMel / 2595) - 1); +} + +/** + * Returns a description of the weights to apply on the fft bins for each + * Mel band filter. + * @note - adapted from imtr-tools/rta + * + * @param {Number} nbrBins - Number of fft bins. + * @param {Number} nbrFilter - Number of mel filters. + * @param {Number} sampleRate - Sample Rate of the signal. + * @param {Number} minFreq - Minimum Frequency to be considerered. + * @param {Number} maxFreq - Maximum frequency to consider. + * @return {Array} - Description of the weights to apply on the bins for + * each mel filter. Each description has the following structure: + * { startIndex: binIndex, centerFreq: binCenterFrequency, weights: [] } + * + * @private + */ +function getMelBandWeights(nbrBins, nbrBands, sampleRate, minFreq, maxFreq) { + var type = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'htk'; + + + var hertzToMel = null; + var melToHertz = null; + var minMel = void 0; + var maxMel = void 0; + + if (type === 'htk') { + hertzToMel = hertzToMelHtk; + melToHertz = melToHertzHtk; + minMel = hertzToMel(minFreq); + maxMel = hertzToMel(maxFreq); + } else { + throw new Error('Invalid mel band type: "' + type + '"'); + } + + var melBandDescriptions = new Array(nbrBands); + // center frequencies of Fft bins + var fftFreqs = new Float32Array(nbrBins); + // center frequencies of mel bands - uniformly spaced in mel domain between + // limits, there are 2 more frequencies than the actual number of filters in + // order to calculate the slopes + var filterFreqs = new Float32Array(nbrBands + 2); + + var fftSize = (nbrBins - 1) * 2; + // compute bins center frequencies + for (var i = 0; i < nbrBins; i++) { + fftFreqs[i] = sampleRate * i / fftSize; + }for (var _i = 0; _i < nbrBands + 2; _i++) { + filterFreqs[_i] = melToHertz(minMel + _i / (nbrBands + 1) * (maxMel - minMel)); + } // loop throught filters + for (var _i2 = 0; _i2 < nbrBands; _i2++) { + var minWeightIndexDefined = 0; + + var description = { + startIndex: null, + centerFreq: null, + weights: [] + + // define contribution of each bin for the filter at index (i + 1) + // do not process the last spectrum component (Nyquist) + };for (var j = 0; j < nbrBins - 1; j++) { + var posSlopeContrib = (fftFreqs[j] - filterFreqs[_i2]) / (filterFreqs[_i2 + 1] - filterFreqs[_i2]); + + var negSlopeContrib = (filterFreqs[_i2 + 2] - fftFreqs[j]) / (filterFreqs[_i2 + 2] - filterFreqs[_i2 + 1]); + // lowerSlope and upper slope intersect at zero and with each other + var contribution = max(0, min(posSlopeContrib, negSlopeContrib)); + + if (contribution > 0) { + if (description.startIndex === null) { + description.startIndex = j; + description.centerFreq = filterFreqs[_i2 + 1]; + } + + description.weights.push(contribution); + } + } + + // empty filter + if (description.startIndex === null) { + description.startIndex = 0; + description.centerFreq = 0; + } + + // @todo - do some scaling for Slaney-style mel + melBandDescriptions[_i2] = description; + } + + return melBandDescriptions; +} + +var definitions = { + log: { + type: 'boolean', + default: false, + metas: { kind: 'static' } + }, + nbrBands: { + type: 'integer', + default: 24, + metas: { kind: 'static' } + }, + minFreq: { + type: 'float', + default: 0, + metas: { kind: 'static' } + }, + maxFreq: { + type: 'float', + default: null, + nullable: true, + metas: { kind: 'static' } + }, + power: { + type: 'integer', + default: 1, + metas: { kind: 'dynamic' } + } +}; + +/** + * Compute the mel bands spectrum from a given spectrum (`vector` type). + * _Implement the `htk` mel band style._ + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Boolean} [options.log=false] - Apply a logarithmic scale on the output. + * @param {Number} [options.nbrBands=24] - Number of filters defining the mel + * bands. + * @param {Number} [options.minFreq=0] - Minimum frequency to consider. + * @param {Number} [options.maxFreq=null] - Maximum frequency to consider. + * If `null`, is set to Nyquist frequency. + * @param {Number} [options.power=1] - Apply a power scaling on each mel band. + * + * @todo - implement Slaney style mel bands + * + * @example + * import lfo from 'waves-lfo/node' + * + * // read a file from path (node only source) + * const audioInFile = new lfo.source.AudioInFile({ + * filename: 'path/to/file', + * frameSize: 512, + * }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: 256, + * hopSize: 256, + * }); + * + * const fft = new lfo.operator.Fft({ + * size: 1024, + * window: 'hann', + * mode: 'power', + * norm: 'power', + * }); + * + * const mel = new lfo.operator.Mel({ + * log: true, + * nbrBands: 24, + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * audioInFile.connect(slicer); + * slicer.connect(fft); + * fft.connect(mel); + * mel.connect(logger); + * + * audioInFile.start(); + */ + +var Mel = function (_BaseLfo) { + (0, _inherits3.default)(Mel, _BaseLfo); + + function Mel() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Mel); + return (0, _possibleConstructorReturn3.default)(this, (Mel.__proto__ || (0, _getPrototypeOf2.default)(Mel)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Mel, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var nbrBins = prevStreamParams.frameSize; + var nbrBands = this.params.get('nbrBands'); + var sampleRate = this.streamParams.sourceSampleRate; + var minFreq = this.params.get('minFreq'); + var maxFreq = this.params.get('maxFreq'); + + // + this.streamParams.frameSize = nbrBands; + this.streamParams.frameType = 'vector'; + this.streamParams.description = []; + + if (maxFreq === null) maxFreq = this.streamParams.sourceSampleRate / 2; + + this.melBandDescriptions = getMelBandWeights(nbrBins, nbrBands, sampleRate, minFreq, maxFreq); + + this.propagateStreamParams(); + } + + /** + * Use the `Mel` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array} spectrum - Fft bins. + * @return {Array} - Mel bands. + * + * @example + * const mel = new lfo.operator.Mel({ nbrBands: 24 }); + * // mandatory for use in standalone mode + * mel.initStream({ frameSize: 256, frameType: 'vector', sourceSampleRate: 44100 }); + * mel.inputVector(fftBins); + */ + + }, { + key: 'inputVector', + value: function inputVector(bins) { + + var power = this.params.get('power'); + var log = this.params.get('log'); + var melBands = this.frame.data; + var nbrBands = this.streamParams.frameSize; + var scale = 1; + + var minLogValue = 1e-48; + var minLog = -480; + + if (log) scale *= nbrBands; + + for (var i = 0; i < nbrBands; i++) { + var _melBandDescriptions$ = this.melBandDescriptions[i], + startIndex = _melBandDescriptions$.startIndex, + weights = _melBandDescriptions$.weights; + + var value = 0; + + for (var j = 0; j < weights.length; j++) { + value += weights[j] * bins[startIndex + j]; + } // apply same logic as in PiPoBands + if (scale !== 1) value *= scale; + + if (log) { + if (value > minLogValue) value = 10 * log10(value);else value = minLog; + } + + if (power !== 1) value = pow(value, power); + + melBands[i] = value; + } + + return melBands; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.inputVector(frame.data); + } + }]); + return Mel; +}(_BaseLfo3.default); + +exports.default = Mel; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/math/log10":58,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],28:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + // array defining the frameSizes of the input streamss + // e.g. if [3, 2, 1], we wait for 3 different sources of respective 3, 2, 1 frameSizes + frameSizes: { + type: 'any', + default: null, + constant: true + } + + /** + * Merge multiple vector frames. The order of execution depends on the + * order the branching was initially made. The first branche is master + * on the time and trigger the output of the frame. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters + * @param {Array} [options.frameSizes=null] - Array that defines the number + * of values to pick from each incomming vectors. + * + * @example + * import * as lfo from 'waves-lfo/comon' + * + * const eventIn = new lfo.operator.EventIn({ + * type: 'vector', + * frameSize: 4, + * frameRate: 0, + * }); + * + * const minMax = new lfo.operator.MinMax(); + * const magnitude = new lfo.operator.Magnitude(); + * + * // take the first 2 values of the first branch and 1 value from the second branch + * const merge = new lfo.operator.Merger({ frameSizes: [2, 1] }); + * + * // this defines the order in which Merger will be called + * eventIn.connect(minMax); + * eventIn.connect(magnitude); + * + * minMax.connect(merger); + * magnitude.connect(merger); + */ +}; +var Merger = function (_BaseLfo) { + (0, _inherits3.default)(Merger, _BaseLfo); + + function Merger(options) { + (0, _classCallCheck3.default)(this, Merger); + return (0, _possibleConstructorReturn3.default)(this, (Merger.__proto__ || (0, _getPrototypeOf2.default)(Merger)).call(this, definitions, options)); + } + + (0, _createClass3.default)(Merger, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + // ... + var frameSizes = this.params.get('frameSizes'); + var numSources = frameSizes.length; + + var frameSize = 0; + for (var i = 0; i < numSources; i++) { + frameSize += frameSizes[i]; + }this.streamParams.frameSize = frameSize; + this.numSources = numSources; + this.sourceIndex = 0; + + this.propagateStreamParams(); + } + }, { + key: 'processVector', + value: function processVector() {} + // processSignal() {} // makes no sens to merge signals (maybe MUX / DEMUX) + + }, { + key: 'processFrame', + value: function processFrame(frame) { + var currentIndex = this.sourceIndex; + var frameSizes = this.params.get('frameSizes'); + var numSources = frameSizes.length; + var input = frame.data; + var output = this.frame.data; + + // first source define time + if (currentIndex === 0) this.frame.time = frame.time; + + var currentFrameSize = frameSizes[currentIndex]; + var offset = 0; + + for (var i = 0; i < currentIndex; i++) { + offset += frameSizes[i]; + } // copy data + for (var _i = 0; _i < currentFrameSize; _i++) { + output[offset + _i] = input[_i]; + }this.sourceIndex = (this.sourceIndex + 1) % numSources; + + // we just received the last input, output the frame + if (this.sourceIndex === 0) this.propagateFrame(); + } + }]); + return Merger; +}(_BaseLfo3.default); + +exports.default = Merger; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],29:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +var _Fft = require('./Fft'); + +var _Fft2 = _interopRequireDefault(_Fft); + +var _Mel = require('./Mel'); + +var _Mel2 = _interopRequireDefault(_Mel); + +var _Dct = require('./Dct'); + +var _Dct2 = _interopRequireDefault(_Dct); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + nbrBands: { + type: 'integer', + default: 24, + meta: { kind: 'static' } + }, + nbrCoefs: { + type: 'integer', + default: 12, + meta: { kind: 'static' } + }, + minFreq: { + type: 'float', + default: 0, + meta: { kind: 'static' } + }, + maxFreq: { + type: 'float', + default: null, + nullable: true, + meta: { kind: 'static' } + } +}; + +/** + * Compute the Mfcc of the incomming `signal`. Is basically a wrapper around + * [`Fft`]{@link module:common.operator.Fft}, [`Mel`]{@link module:common.operator.Mel} + * and [`Dct`]{@link module:common.operator.Dct}. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {nbrBands} [options.nbrBands=24] - Number of Mel bands. + * @param {nbrCoefs} [options.nbrCoefs=12] - Number of output coefs. + * + * @see {@link module:common.operator.Fft} + * @see {@link module:common.operator.Mel} + * @see {@link module:common.operator.Dct} + * + * @example + * import lfo from 'waves-lfo/node' + * + * const audioInFile = new lfo.source.AudioInFile({ + * filename: 'path/to/file', + * frameSize: 512, + * }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: 256, + * }); + * + * const mfcc = new lfo.operator.Mfcc({ + * nbrBands: 24, + * nbrCoefs: 12, + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * audioInFile.connect(slicer); + * slicer.connect(mfcc); + * mfcc.connect(logger); + * + * audioInFile.start(); + */ + +var Mfcc = function (_BaseLfo) { + (0, _inherits3.default)(Mfcc, _BaseLfo); + + function Mfcc(options) { + (0, _classCallCheck3.default)(this, Mfcc); + return (0, _possibleConstructorReturn3.default)(this, (Mfcc.__proto__ || (0, _getPrototypeOf2.default)(Mfcc)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Mfcc, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var nbrBands = this.params.get('nbrBands'); + var nbrCoefs = this.params.get('nbrCoefs'); + var minFreq = this.params.get('minFreq'); + var maxFreq = this.params.get('maxFreq'); + var inputFrameSize = prevStreamParams.frameSize; + var inputFrameRate = prevStreamParams.frameRate; + var inputSampleRate = prevStreamParams.sourceSampleRate; + var nbrBins = inputFrameSize / 2 + 1; + + this.streamParams.frameSize = nbrCoefs; + this.streamParams.frameType = 'vector'; + this.streamParams.description = []; + + this.fft = new _Fft2.default({ + window: 'hann', + mode: 'power', + norm: 'power', + size: inputFrameSize + }); + + this.mel = new _Mel2.default({ + nbrBands: nbrBands, + log: true, + power: 1, + minFreq: minFreq, + maxFreq: maxFreq + }); + + this.dct = new _Dct2.default({ + order: nbrCoefs + }); + + // init streams + this.fft.initStream({ + frameType: 'signal', + frameSize: inputFrameSize, + frameRate: inputFrameRate, + sourceSampleRate: inputSampleRate + }); + + this.mel.initStream({ + frameType: 'vector', + frameSize: nbrBins, + frameRate: inputFrameRate, + sourceSampleRate: inputSampleRate + }); + + this.dct.initStream({ + frameType: 'vector', + frameSize: nbrBands, + frameRate: inputFrameRate, + sourceSampleRate: inputSampleRate + }); + + this.propagateStreamParams(); + } + + /** + * Use the `Mfcc` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array} data - Signal chunk to analyse. + * @return {Array} - Mfcc coefficients. + * + * @example + * const mfcc = new lfo.operator.Mfcc(); + * // mandatory for use in standalone mode + * mfcc.initStream({ frameSize: 256, frameType: 'vector' }); + * mfcc.inputSignal(signal); + */ + + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var output = this.frame.data; + var nbrCoefs = this.params.get('nbrCoefs'); + + var bins = this.fft.inputSignal(data); + var melBands = this.mel.inputVector(bins); + // console.log(melBands); + var coefs = this.dct.inputSignal(melBands); + + for (var i = 0; i < nbrCoefs; i++) { + output[i] = coefs[i]; + }return output; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return Mfcc; +}(_BaseLfo3.default); + +exports.default = Mfcc; + +},{"../../core/BaseLfo":50,"./Dct":22,"./Fft":24,"./Mel":27,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],30:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Find minimun and maximum values of a given `signal`. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameSize: 512, + * frameType: 'signal', + * sampleRate: 0, + * }); + * + * const minMax = new lfo.operator.MinMax(); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * eventIn.connect(minMax); + * minMax.connect(logger); + * eventIn.start() + * + * // create a frame + * const signal = new Float32Array(512); + * for (let i = 0; i < 512; i++) + * signal[i] = i + 1; + * + * eventIn.process(null, signal); + * > [1, 512]; + */ +var MinMax = function (_BaseLfo) { + (0, _inherits3.default)(MinMax, _BaseLfo); + + function MinMax() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, MinMax); + + // throw errors if options are given + return (0, _possibleConstructorReturn3.default)(this, (MinMax.__proto__ || (0, _getPrototypeOf2.default)(MinMax)).call(this, {}, options)); + } + + /** @private */ + + + (0, _createClass3.default)(MinMax, [{ + key: 'processStreamParams', + value: function processStreamParams() { + var prevStreamParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.prepareStreamParams(prevStreamParams); + + this.streamParams.frameType = 'vector'; + this.streamParams.frameSize = 2; + this.streamParams.description = ['min', 'max']; + + this.propagateStreamParams(); + } + + /** + * Use the `MinMax` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Float32Array|Array} data - Input signal. + * @return {Array} - Min and max values. + * + * @example + * const minMax = new MinMax(); + * minMax.initStream({ frameType: 'signal', frameSize: 10 }); + * + * minMax.inputSignal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + * > [0, 5] + */ + + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var outData = this.frame.data; + var min = +Infinity; + var max = -Infinity; + + for (var i = 0, l = data.length; i < l; i++) { + var value = data[i]; + if (value < min) min = value; + if (value > max) max = value; + } + + outData[0] = min; + outData[1] = max; + + return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return MinMax; +}(_BaseLfo3.default); + +exports.default = MinMax; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],31:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + order: { + type: 'integer', + min: 1, + max: 1e9, + default: 10, + metas: { kind: 'dynamic' } + }, + fill: { + type: 'float', + min: -Infinity, + max: +Infinity, + default: 0, + metas: { kind: 'dynamic' } + } +}; + +/** + * Compute a moving average operation on the incomming frames (`scalar` or + * `vector` type). If the input is of type vector, the moving average is + * computed for each dimension in parallel. If the source sample rate is defined + * frame time is shifted to the middle of the window defined by the order. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.order=10] - Number of successive values on which + * the average is computed. + * @param {Number} [options.fill=0] - Value to fill the ring buffer with before + * the first input frame. + * + * @todo - Implement `processSignal` ? + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameSize: 2, + * frameType: 'vector' + * }); + * + * const movingAverage = new lfo.operator.MovingAverage({ + * order: 5, + * fill: 0 + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * eventIn.connect(movingAverage); + * movingAverage.connect(logger); + * + * eventIn.start(); + * + * eventIn.process(null, [1, 1]); + * > [0.2, 0.2] + * eventIn.process(null, [1, 1]); + * > [0.4, 0.4] + * eventIn.process(null, [1, 1]); + * > [0.6, 0.6] + * eventIn.process(null, [1, 1]); + * > [0.8, 0.8] + * eventIn.process(null, [1, 1]); + * > [1, 1] + */ + +var MovingAverage = function (_BaseLfo) { + (0, _inherits3.default)(MovingAverage, _BaseLfo); + + function MovingAverage() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, MovingAverage); + + var _this = (0, _possibleConstructorReturn3.default)(this, (MovingAverage.__proto__ || (0, _getPrototypeOf2.default)(MovingAverage)).call(this, definitions, options)); + + _this.sum = null; + _this.ringBuffer = null; + _this.ringIndex = 0; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(MovingAverage, [{ + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(MovingAverage.prototype.__proto__ || (0, _getPrototypeOf2.default)(MovingAverage.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + // @todo - should be done lazily in process + switch (name) { + case 'order': + this.processStreamParams(); + this.resetStream(); + break; + case 'fill': + this.resetStream(); + break; + } + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var frameSize = this.streamParams.frameSize; + var order = this.params.get('order'); + + this.ringBuffer = new Float32Array(order * frameSize); + + if (frameSize > 1) this.sum = new Float32Array(frameSize);else this.sum = 0; + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(MovingAverage.prototype.__proto__ || (0, _getPrototypeOf2.default)(MovingAverage.prototype), 'resetStream', this).call(this); + + var order = this.params.get('order'); + var fill = this.params.get('fill'); + var ringBuffer = this.ringBuffer; + var ringLength = ringBuffer.length; + + for (var i = 0; i < ringLength; i++) { + ringBuffer[i] = fill; + }var fillSum = order * fill; + var frameSize = this.streamParams.frameSize; + + if (frameSize > 1) { + for (var _i = 0; _i < frameSize; _i++) { + this.sum[_i] = fillSum; + } + } else { + this.sum = fillSum; + } + + this.ringIndex = 0; + } + + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar(frame) { + this.frame.data[0] = this.inputScalar(frame.data[0]); + } + + /** + * Use the `MovingAverage` operator in `standalone` mode (i.e. outside of a + * graph) with a `scalar` input. + * + * @param {Number} value - Value to feed the moving average with. + * @return {Number} - Average value. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const movingAverage = new lfo.operator.MovingAverage({ order: 5 }); + * movingAverage.initStream({ frameSize: 1, frameType: 'scalar' }); + * + * movingAverage.inputScalar(1); + * > 0.2 + * movingAverage.inputScalar(1); + * > 0.4 + * movingAverage.inputScalar(1); + * > 0.6 + */ + + }, { + key: 'inputScalar', + value: function inputScalar(value) { + var order = this.params.get('order'); + var ringIndex = this.ringIndex; + var ringBuffer = this.ringBuffer; + var sum = this.sum; + + sum -= ringBuffer[ringIndex]; + sum += value; + + this.sum = sum; + this.ringBuffer[ringIndex] = value; + this.ringIndex = (ringIndex + 1) % order; + + return sum / order; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.inputVector(frame.data); + } + + /** + * Use the `MovingAverage` operator in `standalone` mode (i.e. outside of a + * graph) with a `vector` input. + * + * @param {Array} values - Values to feed the moving average with. + * @return {Float32Array} - Average value for each dimension. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const movingAverage = new lfo.operator.MovingAverage({ order: 5 }); + * movingAverage.initStream({ frameSize: 2, frameType: 'scalar' }); + * + * movingAverage.inputArray([1, 1]); + * > [0.2, 0.2] + * movingAverage.inputArray([1, 1]); + * > [0.4, 0.4] + * movingAverage.inputArray([1, 1]); + * > [0.6, 0.6] + */ + + }, { + key: 'inputVector', + value: function inputVector(values) { + var order = this.params.get('order'); + var outFrame = this.frame.data; + var frameSize = this.streamParams.frameSize; + var ringIndex = this.ringIndex; + var ringOffset = ringIndex * frameSize; + var ringBuffer = this.ringBuffer; + var sum = this.sum; + var scale = 1 / order; + + for (var i = 0; i < frameSize; i++) { + var ringBufferIndex = ringOffset + i; + var value = values[i]; + var localSum = sum[i]; + + localSum -= ringBuffer[ringBufferIndex]; + localSum += value; + + this.sum[i] = localSum; + outFrame[i] = localSum * scale; + ringBuffer[ringBufferIndex] = value; + } + + this.ringIndex = (ringIndex + 1) % order; + + return outFrame; + } + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + this.processFunction(frame); + + var order = this.params.get('order'); + var time = frame.time; + // shift time to take account of the added latency + if (this.streamParams.sourceSampleRate) time -= 0.5 * (order - 1) / this.streamParams.sourceSampleRate; + + this.frame.time = time; + this.frame.metadata = frame.metadata; + + this.propagateFrame(); + } + }]); + return MovingAverage; +}(_BaseLfo3.default); + +exports.default = MovingAverage; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],32:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + order: { + type: 'integer', + min: 1, + max: 1e9, + default: 9, + metas: { kind: 'static' } + }, + fill: { + type: 'float', + min: -Infinity, + max: +Infinity, + default: 0, + metas: { kind: 'static' } + } +}; + +/** + * Compute a moving median operation on the incomming frames (`scalar` or + * `vector` type). If the input is of type vector, the moving median is + * computed for each dimension in parallel. If the source sample rate is defined + * frame time is shifted to the middle of the window defined by the order. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.order=9] - Number of successive values in which + * the median is searched. This value must be odd. _dynamic parameter_ + * @param {Number} [options.fill=0] - Value to fill the ring buffer with before + * the first input frame. _dynamic parameter_ + * + * @todo - Implement `processSignal` + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameSize: 2, + * frameType: 'vector', + * }); + * + * const movingMedian = new lfo.operator.MovingMedian({ + * order: 5, + * fill: 0, + * }); + * + * const logger = new lfo.sink.Logger({ data: true }); + * + * eventIn.connect(movingMedian); + * movingMedian.connect(logger); + * + * eventIn.start(); + * + * eventIn.processFrame(null, [1, 1]); + * > [0, 0] + * eventIn.processFrame(null, [2, 2]); + * > [0, 0] + * eventIn.processFrame(null, [3, 3]); + * > [1, 1] + * eventIn.processFrame(null, [4, 4]); + * > [2, 2] + * eventIn.processFrame(null, [5, 5]); + * > [3, 3] + */ + +var MovingMedian = function (_BaseLfo) { + (0, _inherits3.default)(MovingMedian, _BaseLfo); + + function MovingMedian() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, MovingMedian); + + var _this = (0, _possibleConstructorReturn3.default)(this, (MovingMedian.__proto__ || (0, _getPrototypeOf2.default)(MovingMedian)).call(this, definitions, options)); + + _this.ringBuffer = null; + _this.sortBuffer = null; + _this.ringIndex = 0; + + _this._ensureOddOrder(); + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(MovingMedian, [{ + key: '_ensureOddOrder', + value: function _ensureOddOrder() { + if (this.params.get('order') % 2 === 0) throw new Error('Invalid value ' + order + ' for param "order" - must be odd'); + } + + /** @private */ + + }, { + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(MovingMedian.prototype.__proto__ || (0, _getPrototypeOf2.default)(MovingMedian.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + switch (name) { + case 'order': + this._ensureOddOrder(); + this.processStreamParams(); + this.resetStream(); + break; + case 'fill': + this.resetStream(); + break; + } + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + // outType is similar to input type + + var frameSize = this.streamParams.frameSize; + var order = this.params.get('order'); + + this.ringBuffer = new Float32Array(frameSize * order); + this.sortBuffer = new Float32Array(frameSize * order); + + this.minIndices = new Uint32Array(frameSize); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(MovingMedian.prototype.__proto__ || (0, _getPrototypeOf2.default)(MovingMedian.prototype), 'resetStream', this).call(this); + + var fill = this.params.get('fill'); + var ringBuffer = this.ringBuffer; + var ringLength = ringBuffer.length; + + for (var i = 0; i < ringLength; i++) { + this.ringBuffer[i] = fill; + }this.ringIndex = 0; + } + + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar(frame) { + this.frame.data[0] = this.inputScalar(frame.data[0]); + } + + /** + * Allows for the use of a `MovingMedian` outside a graph (e.g. inside + * another node), in this case `processStreamParams` and `resetStream` + * should be called manually on the node. + * + * @param {Number} value - Value to feed the moving median with. + * @return {Number} - Median value. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const movingMedian = new MovingMedian({ order: 5 }); + * movingMedian.initStream({ frameSize: 1, frameType: 'scalar' }); + * + * movingMedian.inputScalar(1); + * > 0 + * movingMedian.inputScalar(2); + * > 0 + * movingMedian.inputScalar(3); + * > 1 + * movingMedian.inputScalar(4); + * > 2 + */ + + }, { + key: 'inputScalar', + value: function inputScalar(value) { + var ringIndex = this.ringIndex; + var ringBuffer = this.ringBuffer; + var sortBuffer = this.sortBuffer; + var order = this.params.get('order'); + var medianIndex = (order - 1) / 2; + var startIndex = 0; + + ringBuffer[ringIndex] = value; + + for (var i = 0; i <= medianIndex; i++) { + var min = +Infinity; + var minIndex = null; + + for (var j = startIndex; j < order; j++) { + if (i === 0) sortBuffer[j] = ringBuffer[j]; + + if (sortBuffer[j] < min) { + min = sortBuffer[j]; + minIndex = j; + } + } + + // swap minIndex and startIndex + var cache = sortBuffer[startIndex]; + sortBuffer[startIndex] = sortBuffer[minIndex]; + sortBuffer[minIndex] = cache; + + startIndex += 1; + } + + var median = sortBuffer[medianIndex]; + this.ringIndex = (ringIndex + 1) % order; + + return median; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.inputVector(frame.data); + } + + /** + * Allows for the use of a `MovingMedian` outside a graph (e.g. inside + * another node), in this case `processStreamParams` and `resetStream` + * should be called manually on the node. + * + * @param {Array} values - Values to feed the moving median with. + * @return {Float32Array} - Median values for each dimension. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const movingMedian = new MovingMedian({ order: 3, fill: 0 }); + * movingMedian.initStream({ frameSize: 3, frameType: 'vector' }); + * + * movingMedian.inputArray([1, 1]); + * > [0, 0] + * movingMedian.inputArray([2, 2]); + * > [1, 1] + * movingMedian.inputArray([3, 3]); + * > [2, 2] + */ + + }, { + key: 'inputVector', + value: function inputVector(values) { + var order = this.params.get('order'); + var ringBuffer = this.ringBuffer; + var ringIndex = this.ringIndex; + var sortBuffer = this.sortBuffer; + var outFrame = this.frame.data; + var minIndices = this.minIndices; + var frameSize = this.streamParams.frameSize; + var medianIndex = Math.floor(order / 2); + var startIndex = 0; + + for (var i = 0; i <= medianIndex; i++) { + + for (var j = 0; j < frameSize; j++) { + outFrame[j] = +Infinity; + minIndices[j] = 0; + + for (var k = startIndex; k < order; k++) { + var index = k * frameSize + j; + + // update ring buffer corresponding to current + if (k === ringIndex && i === 0) ringBuffer[index] = values[j]; + + // copy value in sort buffer on first pass + if (i === 0) sortBuffer[index] = ringBuffer[index]; + + // find minium in the remaining array + if (sortBuffer[index] < outFrame[j]) { + outFrame[j] = sortBuffer[index]; + minIndices[j] = index; + } + } + + // swap minimum and curent index + var swapIndex = startIndex * frameSize + j; + var v = sortBuffer[swapIndex]; + sortBuffer[swapIndex] = sortBuffer[minIndices[j]]; + sortBuffer[minIndices[j]] = v; + + // store this minimum value as current result + outFrame[j] = sortBuffer[swapIndex]; + } + + startIndex += 1; + } + + this.ringIndex = (ringIndex + 1) % order; + + return this.frame.data; + } + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.preprocessFrame(); + this.processFunction(frame); + + var order = this.params.get('order'); + var time = frame.time; + // shift time to take account of the added latency + if (this.streamParams.sourceSampleRate) time -= 0.5 * (order - 1) / this.streamParams.sourceSampleRate; + + this.frame.time = time; + this.frame.metadata = frame.metadata; + + this.propagateFrame(time, this.outFrame, metadata); + } + }]); + return MovingMedian; +}(_BaseLfo3.default); + +exports.default = MovingMedian; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],33:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + // float or array + factor: { + type: 'any', + default: 1 + } +}; + +/** + * Multiply a given signal or vector by a given factor. On vector + * streams, `factor` can be an array of values to apply on each dimension of the + * vector frames. + * + * _support `standalone` usage_ + * + * @param {Object} options - override default values + * @param {Number|Array} [options.factor=1] - factor or array of factor to + * apply on the incomming frame. Setting an array is only defined in case of + * a vector stream. + * + * @memberof module:common.operator + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.operator.EventIn({ + * type: 'vector', + * frameSize: 2, + * frameRate: 0, + * }); + * const scaler = new lfo.operator.Multiplier({ factor: 0.1 }); + * + * eventIn.connect(scaler); + * + * eventIn.process(null, [2, 3]); + * > [0.2, 0.3] + */ + +var Multiplier = function (_BaseLfo) { + (0, _inherits3.default)(Multiplier, _BaseLfo); + + function Multiplier(options) { + (0, _classCallCheck3.default)(this, Multiplier); + return (0, _possibleConstructorReturn3.default)(this, (Multiplier.__proto__ || (0, _getPrototypeOf2.default)(Multiplier)).call(this, definitions, options)); + } + + /** + * Use the `Multiplier` operator in standalone mode. + * + * @param {Float32Array|Array} data - Input vector + * @return {Array} - Scaled values + * + * @example + * const scaler = new Multiplier({ factor: [2, 4] }); + * scaler.initStream({ frameType: 'vector', frameSize: 2 }); + * + * scaler.inputVector([3, 2]); + * > [6, 8] + */ + + + (0, _createClass3.default)(Multiplier, [{ + key: 'inputVector', + value: function inputVector(data) { + var output = this.frame.data; + var frameSize = this.streamParams.frameSize; + var factor = this.params.get('factor'); + + if (Array.isArray(factor)) { + for (var i = 0; i < frameSize; i++) { + output[i] = data[i] * factor[i]; + } + } else { + for (var _i = 0; _i < frameSize; _i++) { + output[_i] = data[_i] * factor; + } + } + + return output; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.frame.data = this.inputVector(frame.data); + } + + /** + * Use the `Multiplier` operator in standalone mode. + * + * @param {Float32Array|Array} data - Input signal. + * @return {Array} - Scaled signal. + * + * @example + * const scaler = new Multiplier({ factor: 0.1 }); + * scaler.initStream({ frameType: 'signal', frameSize: 2 }); + * + * scaler.inputVector([1, 2]); + * > [0.1, 0.2] + */ + + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var output = this.frame.data; + var frameSize = this.streamParams.frameSize; + var factor = this.params.get('factor'); + + for (var i = 0; i < frameSize; i++) { + output[i] = data[i] * factor; + }return output; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.frame.data = this.inputSignal(frame.data); + } + }]); + return Multiplier; +}(_BaseLfo3.default); + +exports.default = Multiplier; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],34:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + state: { + type: 'enum', + default: 'on', + list: ['on', 'off'], + metas: { kind: 'dynamic' } + } +}; + +/** + * The OnOff operator allows to stop the propagation of the stream in a + * subgraph. When "on", frames are propagated, when "off" the propagation is + * stopped. + * + * The `streamParams` propagation is never bypassed so the subsequent subgraph + * is always ready for incomming frames. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {String} [options.state='on'] - Default state. + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const frames = [ + * { time: 0, data: [1, 2] }, + * { time: 1, data: [3, 4] }, + * { time: 2, data: [5, 6] }, + * ]; + * + * const eventIn = new EventIn({ + * frameSize: 2, + * frameRate: 0, + * frameType: 'vector', + * }); + * + * const onOff = new OnOff(); + * + * const logger = new Logger({ data: true }); + * + * eventIn.connect(onOff); + * onOff.connect(logger); + * + * eventIn.start(); + * + * eventIn.processFrame(frames[0]); + * > [0, 1] + * + * // bypass subgraph + * onOff.setState('off'); + * eventIn.processFrame(frames[1]); + * + * // re-open subgraph + * onOff.setState('on'); + * eventIn.processFrame(frames[2]); + * > [5, 6] + */ + +var OnOff = function (_BaseLfo) { + (0, _inherits3.default)(OnOff, _BaseLfo); + + function OnOff() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, OnOff); + + var _this = (0, _possibleConstructorReturn3.default)(this, (OnOff.__proto__ || (0, _getPrototypeOf2.default)(OnOff)).call(this, definitions, options)); + + _this.state = _this.params.get('state'); + return _this; + } + + /** + * Set the state of the `OnOff`. + * + * @param {String} state - New state of the operator (`on` or `off`) + */ + + + (0, _createClass3.default)(OnOff, [{ + key: 'setState', + value: function setState(state) { + if (definitions.state.list.indexOf(state) === -1) throw new Error('Invalid switch state value "' + state + '" [valid values: "on"/"off"]'); + + this.state = state; + } + + // define all possible stream API + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar() {} + /** @private */ + + }, { + key: 'processVector', + value: function processVector() {} + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal() {} + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + if (this.state === 'on') { + this.prepareFrame(); + + this.frame.time = frame.time; + this.frame.metadata = frame.metadata; + this.frame.data = frame.data; + + this.propagateFrame(); + } + } + }]); + return OnOff; +}(_BaseLfo3.default); + +exports.default = OnOff; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],35:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + exponent: { + type: 'float', + default: 1 + } +}; + +/** + * Apply an exponant power to the stream. + * + * @param {Object} options - Override default parameters + * @param {Number} exponent - Exponent + */ + +var Power = function (_BaseLfo) { + (0, _inherits3.default)(Power, _BaseLfo); + + function Power(options) { + (0, _classCallCheck3.default)(this, Power); + return (0, _possibleConstructorReturn3.default)(this, (Power.__proto__ || (0, _getPrototypeOf2.default)(Power)).call(this, definitions, options)); + } + + (0, _createClass3.default)(Power, [{ + key: 'inputVector', + value: function inputVector(data) { + var outData = this.frame.data; + var frameSize = this.streamParams.frameSize; + var exponent = this.params.get('exponent'); + + for (var i = 0; i < frameSize; i++) { + outData[i] = Math.pow(data[i], exponent); + }return outData; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.inputVector(frame.data); + } + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var outData = this.frame.data; + var frameSize = this.streamParams.frameSize; + var exponent = this.params.get('exponent'); + + for (var i = 0; i < frameSize; i++) { + outData[i] = Math.pow(data[i], exponent); + }return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return Power; +}(_BaseLfo3.default); + +exports.default = Power; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],36:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var sqrt = Math.sqrt; + +var definitions = { + power: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + } +}; + +/** + * Compute the Root Mean Square of a `signal`. + * + * _support `standalone` usage_ + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Boolean} [options.power=false] - If `true` remove the "R" of the + * "Rms" and return the squared result (i.e. power). + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * // assuming some `AudioBuffer` + * const audioInBuffer = new lfo.source.AudioInBuffer({ + * audioBuffer: audioBuffer, + * frameSize: 512, + * }); + * + * const rms = new lfo.operator.Rms(); + * const logger = new lfo.sink.Logger({ data: true }); + * + * audioInBuffer.connect(rms); + * rms.connect(logger); + * + * audioInBuffer.start(); + */ + +var Rms = function (_BaseLfo) { + (0, _inherits3.default)(Rms, _BaseLfo); + + function Rms() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Rms); + return (0, _possibleConstructorReturn3.default)(this, (Rms.__proto__ || (0, _getPrototypeOf2.default)(Rms)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Rms, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.streamParams.frameSize = 1; + this.streamParams.frameType = 'scalar'; + this.streamParams.description = ['rms']; + + this.propagateStreamParams(); + } + + /** + * Allows for the use of a `Rms` outside a graph (e.g. inside + * another node). Return the rms of the given signal block. + * + * @param {Number} signal - Signal block to be computed. + * @return {Number} - rms of the input signal. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const rms = new lfo.operator.Rms(); + * rms.initStream({ frameType: 'signal', frameSize: 1000 }); + * + * const results = rms.inputSignal([...values]); + */ + + }, { + key: 'inputSignal', + value: function inputSignal(signal) { + var power = this.params.get('power'); + var length = signal.length; + var rms = 0; + + for (var i = 0; i < length; i++) { + rms += signal[i] * signal[i]; + }rms = rms / length; + + if (!power) rms = sqrt(rms); + + return rms; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.frame.data[0] = this.inputSignal(frame.data); + } + }]); + return Rms; +}(_BaseLfo3.default); + +exports.default = Rms; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],37:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + type: { + type: 'enum', + list: ['linear'], + default: 'linear', + metas: { + kind: 'dynamic' + } + }, + inputMin: { + type: 'float', + default: 0, + min: -Infinity, + max: +Infinity, + metas: { + kind: 'dynamic' + } + }, + inputMax: { + type: 'float', + default: 1, + min: -Infinity, + max: +Infinity, + metas: { + kind: 'dynamic' + } + }, + outputMin: { + type: 'float', + default: 1, + min: -Infinity, + max: +Infinity, + metas: { + kind: 'dynamic' + } + }, + outputMax: { + type: 'float', + default: 1, + min: -Infinity, + max: +Infinity, + metas: { + kind: 'dynamic' + } + } + + /** + * Apply a linear scale on the incomming stream. The output is not clipped. + * + * @todo - implement log and exp scale + * + * @param {Object} options - Override default options + * @param {Number} [options.inputMin=0] - Input Minimum + * @param {Number} [options.inputMax=1] - Input Maximum + * @param {Number} [options.outputMin=0] - Output Minimum + * @param {Number} [options.outputMax=1] - Output Maximum + */ +}; +var Scale = function (_BaseLfo) { + (0, _inherits3.default)(Scale, _BaseLfo); + + function Scale(options) { + (0, _classCallCheck3.default)(this, Scale); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Scale.__proto__ || (0, _getPrototypeOf2.default)(Scale)).call(this, definitions, options)); + + _this.scale = null; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Scale, [{ + key: '_setScaleFunction', + value: function _setScaleFunction() { + var inputMin = this.params.get('inputMin'); + var inputMax = this.params.get('inputMax'); + var outputMin = this.params.get('outputMin'); + var outputMax = this.params.get('outputMax'); + + var a = (outputMax - outputMin) / (inputMax - inputMin); + var b = outputMin - a * inputMin; + + this.scale = function (x) { + return a * x + b; + }; + } + + /** @private */ + + }, { + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(Scale.prototype.__proto__ || (0, _getPrototypeOf2.default)(Scale.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + if (name !== 'type') this._setScaleFunction(); + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this._setScaleFunction(); + + this.propagateStreamParams(); + } + }, { + key: 'inputVector', + value: function inputVector(data) { + var outData = this.frame.data; + var frameSize = this.streamParams.frameSize; + var scale = this.scale; + + for (var i = 0; i < frameSize; i++) { + outData[i] = scale(data[i]); + }return outData; + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + this.frame.data = this.inputVector(frame.data); + } + }, { + key: 'inputSignal', + value: function inputSignal(data) { + var outData = this.frame.data; + var frameSize = this.streamParams.frameSize; + var scale = this.scale; + + for (var i = 0; i < frameSize; i++) { + outData[i] = scale(data[i]); + }return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.frame.data = this.inputVector(frame.data); + } + }]); + return Scale; +}(_BaseLfo3.default); + +exports.default = Scale; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],38:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +var _MovingAverage = require('./MovingAverage'); + +var _MovingAverage2 = _interopRequireDefault(_MovingAverage); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var min = Math.min; +var max = Math.max; + +var definitions = { + logInput: { + type: 'boolean', + default: false, + metas: { kind: 'dyanmic' } + }, + minInput: { + type: 'float', + default: 0.000000000001, + metas: { kind: 'dyanmic' } + }, + filterOrder: { + type: 'integer', + default: 5, + metas: { kind: 'dyanmic' } + }, + threshold: { + type: 'float', + default: 3, + metas: { kind: 'dyanmic' } + }, + offThreshold: { + type: 'float', + default: -Infinity, + metas: { kind: 'dyanmic' } + }, + minInter: { + type: 'float', + default: 0.050, + metas: { kind: 'dyanmic' } + }, + maxDuration: { + type: 'float', + default: Infinity, + metas: { kind: 'dyanmic' } + } + + /** + * Create segments based on attacks. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Boolean} [options.logInput=false] - Apply log on the input. + * @param {Number} [options.minInput=0.000000000001] - Minimum value to use as + * input. + * @param {Number} [options.filterOrder=5] - Order of the internally used moving + * average. + * @param {Number} [options.threshold=3] - Threshold that triggers a segment + * start. + * @param {Number} [options.offThreshold=-Infinity] - Threshold that triggers + * a segment end. + * @param {Number} [options.minInter=0.050] - Minimum delay between two semgents. + * @param {Number} [options.maxDuration=Infinity] - Maximum duration of a segment. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * // assuming a stream from the microphone + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * sourceNode: source, + * audioContext: audioContext, + * }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: frameSize, + * hopSize: hopSize, + * centeredTimeTags: true + * }); + * + * const power = new lfo.operator.RMS({ + * power: true, + * }); + * + * const segmenter = new lfo.operator.Segmenter({ + * logInput: true, + * filterOrder: 5, + * threshold: 3, + * offThreshold: -Infinity, + * minInter: 0.050, + * maxDuration: 0.050, + * }); + * + * const logger = new lfo.sink.Logger({ time: true }); + * + * audioInNode.connect(slicer); + * slicer.connect(power); + * power.connect(segmenter); + * segmenter.connect(logger); + * + * audioInNode.start(); + */ +}; +var Segmenter = function (_BaseLfo) { + (0, _inherits3.default)(Segmenter, _BaseLfo); + + function Segmenter(options) { + (0, _classCallCheck3.default)(this, Segmenter); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Segmenter.__proto__ || (0, _getPrototypeOf2.default)(Segmenter)).call(this, definitions, options)); + + _this.insideSegment = false; + _this.onsetTime = -Infinity; + + // stats + _this.min = Infinity; + _this.max = -Infinity; + _this.sum = 0; + _this.sumOfSquares = 0; + _this.count = 0; + + var minInput = _this.params.get('minInput'); + var fill = minInput; + + if (_this.params.get('logInput') && minInput > 0) fill = Math.log(minInput); + + _this.movingAverage = new _MovingAverage2.default({ + order: _this.params.get('filterOrder'), + fill: fill + }); + + _this.lastMvavrg = fill; + return _this; + } + + (0, _createClass3.default)(Segmenter, [{ + key: 'onParamUpdate', + value: function onParamUpdate(name, value, metas) { + (0, _get3.default)(Segmenter.prototype.__proto__ || (0, _getPrototypeOf2.default)(Segmenter.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + if (name === 'filterOrder') this.movingAverage.params.set('order', value); + } + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.streamParams.frameType = 'vector'; + this.streamParams.frameSize = 5; + this.streamParams.frameRate = 0; + this.streamParams.description = ['duration', 'min', 'max', 'mean', 'stddev']; + + this.movingAverage.initStream(prevStreamParams); + + this.propagateStreamParams(); + } + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(Segmenter.prototype.__proto__ || (0, _getPrototypeOf2.default)(Segmenter.prototype), 'resetStream', this).call(this); + this.movingAverage.resetStream(); + this.resetSegment(); + } + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + if (this.insideSegment) this.outputSegment(endTime); + + (0, _get3.default)(Segmenter.prototype.__proto__ || (0, _getPrototypeOf2.default)(Segmenter.prototype), 'finalizeStream', this).call(this, endTime); + } + }, { + key: 'resetSegment', + value: function resetSegment() { + this.insideSegment = false; + this.onsetTime = -Infinity; + // stats + this.min = Infinity; + this.max = -Infinity; + this.sum = 0; + this.sumOfSquares = 0; + this.count = 0; + } + }, { + key: 'outputSegment', + value: function outputSegment(endTime) { + var outData = this.frame.data; + outData[0] = endTime - this.onsetTime; + outData[1] = this.min; + outData[2] = this.max; + + var norm = 1 / this.count; + var mean = this.sum * norm; + var meanOfSquare = this.sumOfSquares * norm; + var squareOfmean = mean * mean; + + outData[3] = mean; + outData[4] = 0; + + if (meanOfSquare > squareOfmean) outData[4] = Math.sqrt(meanOfSquare - squareOfmean); + + this.frame.time = this.onsetTime; + + this.propagateFrame(); + } + }, { + key: 'processSignal', + value: function processSignal(frame) { + var logInput = this.params.get('logInput'); + var minInput = this.params.get('minInput'); + var threshold = this.params.get('threshold'); + var minInter = this.params.get('minInter'); + var maxDuration = this.params.get('maxDuration'); + var offThreshold = this.params.get('offThreshold'); + var rawValue = frame.data[0]; + var time = frame.time; + var value = Math.max(rawValue, minInput); + + if (logInput) value = Math.log(value); + + var diff = value - this.lastMvavrg; + this.lastMvavrg = this.movingAverage.inputScalar(value); + + // update frame metadata + this.frame.metadata = frame.metadata; + + if (diff > threshold && time - this.onsetTime > minInter) { + if (this.insideSegment) this.outputSegment(time); + + // start segment + this.insideSegment = true; + this.onsetTime = time; + this.max = -Infinity; + } + + if (this.insideSegment) { + this.min = min(this.min, rawValue); + this.max = max(this.max, rawValue); + this.sum += rawValue; + this.sumOfSquares += rawValue * rawValue; + this.count++; + + if (time - this.onsetTime >= maxDuration || value <= offThreshold) { + this.outputSegment(time); + this.insideSegment = false; + } + } + } + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + this.processFunction(frame); + // do not propagate here as the frameRate is now zero + } + }]); + return Segmenter; +}(_BaseLfo3.default); + +exports.default = Segmenter; + +},{"../../core/BaseLfo":50,"./MovingAverage":31,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],39:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + index: { + type: 'integer', + default: 0, + metas: { kind: 'static' } + }, + indexes: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + } +}; + +/** + * Select one or several indexes from a `vector` input. If only one index is + * selected, the output will be of type `scalar`, otherwise the output will + * be a vector containing the selected indexes. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default values. + * @param {Number} options.index - Index to select from the input frame. + * @param {Array} options.indexes - Indices to select from the input + * frame, if defined, take precedance over `option.index`. + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameType: 'vector', + * frameSize: 3, + * }); + * + * const select = new lfo.operator.Select({ + * indexes: [2, 0], + * }); + * + * eventIn.start(); + * eventIn.process(0, [0, 2, 4]); + * > [4, 0] + * eventIn.process(0, [1, 3, 5]); + * > [5, 1] + */ + +var Select = function (_BaseLfo) { + (0, _inherits3.default)(Select, _BaseLfo); + + function Select() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Select); + return (0, _possibleConstructorReturn3.default)(this, (Select.__proto__ || (0, _getPrototypeOf2.default)(Select)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Select, [{ + key: 'onParamUpdate', + value: function onParamUpdate(name, value) { + var metas = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + (0, _get3.default)(Select.prototype.__proto__ || (0, _getPrototypeOf2.default)(Select.prototype), 'onParamUpdate', this).call(this, name, value, metas); + + var index = this.params.get('index'); + var indexes = this.params.get('indexes'); + + this.select = indexes !== null ? indexes : [index]; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + var _this2 = this; + + this.prepareStreamParams(prevStreamParams); + + var index = this.params.get('index'); + var indexes = this.params.get('indexes'); + + var max = indexes !== null ? Math.max.apply(null, indexes) : index; + + if (max >= prevStreamParams.frameSize) throw new Error('Invalid select index "' + max + '"'); + + this.streamParams.frameType = indexes !== null ? 'vector' : 'scalar'; + this.streamParams.frameSize = indexes !== null ? indexes.length : 1; + + this.select = indexes !== null ? indexes : [index]; + + // steal description() from parent + if (prevStreamParams.description) { + this.select.forEach(function (val, index) { + _this2.streamParams.description[index] = prevStreamParams.description[val]; + }); + } + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) { + var data = frame.data; + var outData = this.frame.data; + var select = this.select; + + for (var i = 0; i < select.length; i++) { + outData[i] = data[select[i]]; + } + } + }]); + return Select; +}(_BaseLfo3.default); + +exports.default = Select; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],40:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _get2 = require('babel-runtime/helpers/get'); + +var _get3 = _interopRequireDefault(_get2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + frameSize: { + type: 'integer', + default: 512, + metas: { kind: 'static' } + }, + hopSize: { // should be nullable + type: 'integer', + default: null, + nullable: true, + metas: { kind: 'static' } + }, + centeredTimeTags: { + type: 'boolean', + default: false + } + + /** + * Change the `frameSize` and `hopSize` of a `signal` input according to + * the given options. + * This operator updates the stream parameters according to its configuration. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.frameSize=512] - Frame size of the output signal. + * @param {Number} [options.hopSize=null] - Number of samples between two + * consecutive frames. If null, `hopSize` is set to `frameSize`. + * @param {Boolean} [options.centeredTimeTags] - Move the time tag to the middle + * of the frame. + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameType: 'signal', + * frameSize: 10, + * sampleRate: 2, + * }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: 4, + * hopSize: 2 + * }); + * + * const logger = new lfo.sink.Logger({ time: true, data: true }); + * + * eventIn.connect(slicer); + * slicer.connect(logger); + * eventIn.start(); + * + * eventIn.process(0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + * > { time: 0, data: [0, 1, 2, 3] } + * > { time: 1, data: [2, 3, 4, 5] } + * > { time: 2, data: [4, 5, 6, 7] } + * > { time: 3, data: [6, 7, 8, 9] } + */ +}; +var Slicer = function (_BaseLfo) { + (0, _inherits3.default)(Slicer, _BaseLfo); + + function Slicer() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Slicer); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Slicer.__proto__ || (0, _getPrototypeOf2.default)(Slicer)).call(this, definitions, options)); + + var hopSize = _this.params.get('hopSize'); + var frameSize = _this.params.get('frameSize'); + + if (!hopSize) _this.params.set('hopSize', frameSize); + + _this.params.addListener(_this.onParamUpdate.bind(_this)); + + _this.frameIndex = 0; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Slicer, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var hopSize = this.params.get('hopSize'); + var frameSize = this.params.get('frameSize'); + + this.streamParams.frameSize = frameSize; + this.streamParams.frameRate = prevStreamParams.sourceSampleRate / hopSize; + + if (this.streamParams.frameSize === 1) this.streamParams.frameType = 'scalar';else this.streamParams.frameType = 'signal'; + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'resetStream', + value: function resetStream() { + (0, _get3.default)(Slicer.prototype.__proto__ || (0, _getPrototypeOf2.default)(Slicer.prototype), 'resetStream', this).call(this); + this.frameIndex = 0; + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + if (this.frameIndex > 0) { + var frameRate = this.streamParams.frameRate; + var frameSize = this.streamParams.frameSize; + var data = this.frame.data; + // set the time of the last frame + this.frame.time += 1 / frameRate; + + for (var i = this.frameIndex; i < frameSize; i++) { + data[i] = 0; + }this.propagateFrame(); + } + + (0, _get3.default)(Slicer.prototype.__proto__ || (0, _getPrototypeOf2.default)(Slicer.prototype), 'finalizeStream', this).call(this, endTime); + } + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + this.processFunction(frame); + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + var time = frame.time; + var block = frame.data; + var metadata = frame.metadata; + + var centeredTimeTags = this.params.get('centeredTimeTags'); + var hopSize = this.params.get('hopSize'); + var outFrame = this.frame.data; + var frameSize = this.streamParams.frameSize; + var sampleRate = this.streamParams.sourceSampleRate; + var samplePeriod = 1 / sampleRate; + var blockSize = block.length; + + var frameIndex = this.frameIndex; + var blockIndex = 0; + + while (blockIndex < blockSize) { + var numSkip = 0; + + // skip block samples for negative frameIndex (frameSize < hopSize) + if (frameIndex < 0) { + numSkip = -frameIndex; + frameIndex = 0; // reset `frameIndex` + } + + if (numSkip < blockSize) { + blockIndex += numSkip; // skip block segment + // can copy all the rest of the incoming block + var numCopy = blockSize - blockIndex; + // connot copy more than what fits into the frame + var maxCopy = frameSize - frameIndex; + + if (numCopy >= maxCopy) numCopy = maxCopy; + + // copy block segment into frame + var copy = block.subarray(blockIndex, blockIndex + numCopy); + outFrame.set(copy, frameIndex); + // advance block and frame index + blockIndex += numCopy; + frameIndex += numCopy; + + // send frame when completed + if (frameIndex === frameSize) { + // define time tag for the outFrame according to configuration + if (centeredTimeTags) this.frame.time = time + (blockIndex - frameSize / 2) * samplePeriod;else this.frame.time = time + (blockIndex - frameSize) * samplePeriod; + + this.frame.metadata = metadata; + // forward to next nodes + this.propagateFrame(); + + // shift frame left + if (hopSize < frameSize) outFrame.set(outFrame.subarray(hopSize, frameSize), 0); + + frameIndex -= hopSize; // hop forward + } + } else { + // skip entire block + var blockRest = blockSize - blockIndex; + frameIndex += blockRest; + blockIndex += blockRest; + } + } + + this.frameIndex = frameIndex; + } + }]); + return Slicer; +}(_BaseLfo3.default); + +exports.default = Slicer; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/get":72,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],41:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var ceil = Math.ceil; + +/** + * paper: http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf + * implementation based on https://github.com/ashokfernandez/Yin-Pitch-Tracking + * @private + */ + +var definitions = { + threshold: { + type: 'float', + default: 0.1, // default from paper + metas: { kind: 'static' } + }, + downSamplingExp: { // downsampling factor + type: 'integer', + default: 2, + min: 0, + max: 3, + metas: { kind: 'static' } + }, + minFreq: { // + type: 'float', + default: 60, // mean 735 samples + min: 0, + metas: { kind: 'static' } + } + + /** + * Yin fundamental frequency estimator, based on algorithm described in + * [YIN, a fundamental frequency estimator for speech and music](http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf) + * by Cheveigne and Kawahara. + * On each frame, this operator propagate a vector containing the following + * values: `frequency`, `probability`. + * + * For good results the input frame size should be large (1024 or 2048). + * + * _support `standalone` usage_ + * + * @note - In node for a frame of 2048 samples, average computation time is: + * 0.00016742283339993389 second. + * + * @memberof module:common.operator + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.threshold=0.1] - Absolute threshold to test the + * normalized difference (see paper for more informations). + * @param {Number} [options.downSamplingExp=2] - Down sample the input frame by + * a factor of 2 at the power of `downSamplingExp` (min=0 and max=3) for + * performance improvements. + * @param {Number} [options.minFreq=60] - Minimum frequency the operator can + * search for. This parameter defines the size of the autocorrelation performed + * on the signal, the input frame size should be around 2 time this size for + * good results (i.e. `inputFrameSize ≈ 2 * (samplingRate / minFreq)`). + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * // assuming some AudioBuffer + * const source = new lfo.source.AudioInBuffer({ + * audioBuffer: audioBuffer, + * }); + * + * const slicer = new lfo.operator.Slicer({ + * frameSize: 2048, + * }); + * + * const yin = new lfo.operator.Yin(); + * const logger = new lfo.sink.Logger({ data: true }); + * + * source.connect(slicer); + * slicer.connect(yin); + * yin.connect(logger); + * + * source.start(); + */ +}; +var Yin = function (_BaseLfo) { + (0, _inherits3.default)(Yin, _BaseLfo); + + function Yin(options) { + (0, _classCallCheck3.default)(this, Yin); + + var _this = (0, _possibleConstructorReturn3.default)(this, (Yin.__proto__ || (0, _getPrototypeOf2.default)(Yin)).call(this, definitions, options)); + + _this.probability = 0; + _this.pitch = -1; + + _this.test = 0; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(Yin, [{ + key: '_downsample', + value: function _downsample(input, size, output, downSamplingExp) { + var outputSize = size >> downSamplingExp; + var i = void 0, + j = void 0; + + switch (downSamplingExp) { + case 0: + // no down sampling + for (i = 0; i < size; i++) { + output[i] = input[i]; + }break; + case 1: + for (i = 0, j = 0; i < outputSize; i++, j += 2) { + output[i] = 0.5 * (input[j] + input[j + 1]); + }break; + case 2: + for (i = 0, j = 0; i < outputSize; i++, j += 4) { + output[i] = 0.25 * (input[j] + input[j + 1] + input[j + 2] + input[j + 3]); + }break; + case 3: + for (i = 0, j = 0; i < outputSize; i++, j += 8) { + output[i] = 0.125 * (input[j] + input[j + 1] + input[j + 2] + input[j + 3] + input[j + 4] + input[j + 5] + input[j + 6] + input[j + 7]); + }break; + } + + return outputSize; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + this.streamParams.frameType = 'vector'; + this.streamParams.frameSize = 2; + this.streamParams.description = ['frequency', 'confidence']; + + this.inputFrameSize = prevStreamParams.frameSize; + // handle params + var sourceSampleRate = this.streamParams.sourceSampleRate; + var downSamplingExp = this.params.get('downSamplingExp'); + var downFactor = 1 << downSamplingExp; // 2^n + var downSR = sourceSampleRate / downFactor; + var downFrameSize = this.inputFrameSize / downFactor; // n_tick_down // 1 / 2^n + + var minFreq = this.params.get('minFreq'); + // limit min freq, cf. paper IV. sensitivity to parameters + var minFreqNbrSamples = downSR / minFreq; + // const bufferSize = prevStreamParams.frameSize; + this.halfBufferSize = downFrameSize / 2; + + // minimum error to not crash but not enought to have results + if (minFreqNbrSamples > this.halfBufferSize) throw new Error('Invalid input frame size, too small for given "minFreq"'); + + this.downSamplingExp = downSamplingExp; + this.downSamplingRate = downSR; + this.downFrameSize = downFrameSize; + this.buffer = new Float32Array(downFrameSize); + // autocorrelation buffer + this.yinBuffer = new Float32Array(this.halfBufferSize); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: '_downsample', + value: function _downsample(input, size, output, downSamplingExp) { + var outputSize = size >> downSamplingExp; + var i = void 0, + j = void 0; + + switch (downSamplingExp) { + case 0: + // no down sampling + for (i = 0; i < size; i++) { + output[i] = input[i]; + }break; + case 1: + for (i = 0, j = 0; i < outputSize; i++, j += 2) { + output[i] = 0.5 * (input[j] + input[j + 1]); + }break; + case 2: + for (i = 0, j = 0; i < outputSize; i++, j += 4) { + output[i] = 0.25 * (input[j] + input[j + 1] + input[j + 2] + input[j + 3]); + }break; + case 3: + for (i = 0, j = 0; i < outputSize; i++, j += 8) { + output[i] = 0.125 * (input[j] + input[j + 1] + input[j + 2] + input[j + 3] + input[j + 4] + input[j + 5] + input[j + 6] + input[j + 7]); + }break; + } + + return outputSize; + } + + /** + * Step 1, 2 and 3 - Squared difference of the shifted signal with itself. + * cumulative mean normalized difference. + * + * @private + */ + + }, { + key: '_normalizedDifference', + value: function _normalizedDifference(buffer) { + var halfBufferSize = this.halfBufferSize; + var yinBuffer = this.yinBuffer; + var sum = 0; + + // difference for different shift values (tau) + for (var tau = 0; tau < halfBufferSize; tau++) { + var squaredDifference = 0; // reset buffer + + // take difference of the signal with a shifted version of itself then + // sqaure the result + for (var i = 0; i < halfBufferSize; i++) { + var delta = buffer[i] - buffer[i + tau]; + squaredDifference += delta * delta; + } + + // step 3 - normalize yinBuffer + if (tau > 0) { + sum += squaredDifference; + yinBuffer[tau] = squaredDifference * (tau / sum); + } + } + + yinBuffer[0] = 1; + } + + /** + * Step 4 - find first best tau that is under the thresold. + * + * @private + */ + + }, { + key: '_absoluteThreshold', + value: function _absoluteThreshold() { + var threshold = this.params.get('threshold'); + var yinBuffer = this.yinBuffer; + var halfBufferSize = this.halfBufferSize; + var tau = void 0; + + for (tau = 1; tau < halfBufferSize; tau++) { + if (yinBuffer[tau] < threshold) { + // keep increasing tau if next value is better + while (tau + 1 < halfBufferSize && yinBuffer[tau + 1] < yinBuffer[tau]) { + tau += 1; + } // best tau found , yinBuffer[tau] can be seen as an estimation of + // aperiodicity then: periodicity = 1 - aperiodicity + this.probability = 1 - yinBuffer[tau]; + break; + } + } + + // return -1 if not match found + return tau === halfBufferSize ? -1 : tau; + } + + /** + * Step 5 - Find a better fractionnal approximate of tau. + * this can probably be simplified... + * + * @private + */ + + }, { + key: '_parabolicInterpolation', + value: function _parabolicInterpolation(tauEstimate) { + var halfBufferSize = this.halfBufferSize; + var yinBuffer = this.yinBuffer; + var betterTau = void 0; + // @note - tauEstimate cannot be zero as the loop start at 1 in step 4 + var x0 = tauEstimate - 1; + var x2 = tauEstimate < halfBufferSize - 1 ? tauEstimate + 1 : tauEstimate; + + // if `tauEstimate` is last index, we can't interpolate + if (x2 === tauEstimate) { + betterTau = tauEstimate; + } else { + var s0 = yinBuffer[x0]; + var s1 = yinBuffer[tauEstimate]; + var s2 = yinBuffer[x2]; + + // @note - don't fully understand this formula neither... + betterTau = tauEstimate + (s2 - s0) / (2 * (2 * s1 - s2 - s0)); + } + + return betterTau; + } + + /** + * Use the `Yin` operator in `standalone` mode (i.e. outside of a graph). + * + * @param {Array|Float32Array} input - The signal fragment to process. + * @return {Array} - Array containing the `frequency`, `energy`, `periodicity` + * and `AC1` + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const yin = new lfo.operator.Yin(); + * yin.initStream({ + * frameSize: 2048, + * frameType: 'signal', + * sourceSampleRate: 44100 + * }); + * + * const results = yin.inputSignal(signal); + */ + + }, { + key: 'inputSignal', + value: function inputSignal(input) { + this.pitch = -1; + this.probability = 0; + + var buffer = this.buffer; + var inputFrameSize = this.inputFrameSize; + var downSamplingExp = this.downSamplingExp; + var sampleRate = this.downSamplingRate; + var outData = this.frame.data; + var tauEstimate = -1; + + // subsampling + this._downsample(input, inputFrameSize, buffer, downSamplingExp); + // step 1, 2, 3 - normalized squared difference of the signal with a + // shifted version of itself + this._normalizedDifference(buffer); + // step 4 - find first best tau estimate that is over the threshold + tauEstimate = this._absoluteThreshold(); + + if (tauEstimate !== -1) { + // step 5 - so far tau is an integer shift of the signal, check if + // there is a better fractionnal value around + tauEstimate = this._parabolicInterpolation(tauEstimate); + this.pitch = sampleRate / tauEstimate; + } + + outData[0] = this.pitch; + outData[1] = this.probability; + + return outData; + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + this.inputSignal(frame.data); + } + }]); + return Yin; +}(_BaseLfo3.default); + +exports.default = Yin; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],42:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _Biquad = require('./Biquad'); + +var _Biquad2 = _interopRequireDefault(_Biquad); + +var _Clip = require('./Clip'); + +var _Clip2 = _interopRequireDefault(_Clip); + +var _Dct = require('./Dct'); + +var _Dct2 = _interopRequireDefault(_Dct); + +var _Delta = require('./Delta'); + +var _Delta2 = _interopRequireDefault(_Delta); + +var _Fft = require('./Fft'); + +var _Fft2 = _interopRequireDefault(_Fft); + +var _Magnitude = require('./Magnitude'); + +var _Magnitude2 = _interopRequireDefault(_Magnitude); + +var _MeanStddev = require('./MeanStddev'); + +var _MeanStddev2 = _interopRequireDefault(_MeanStddev); + +var _Mel = require('./Mel'); + +var _Mel2 = _interopRequireDefault(_Mel); + +var _Merger = require('./Merger'); + +var _Merger2 = _interopRequireDefault(_Merger); + +var _Mfcc = require('./Mfcc'); + +var _Mfcc2 = _interopRequireDefault(_Mfcc); + +var _MinMax = require('./MinMax'); + +var _MinMax2 = _interopRequireDefault(_MinMax); + +var _MovingAverage = require('./MovingAverage'); + +var _MovingAverage2 = _interopRequireDefault(_MovingAverage); + +var _MovingMedian = require('./MovingMedian'); + +var _MovingMedian2 = _interopRequireDefault(_MovingMedian); + +var _OnOff = require('./OnOff'); + +var _OnOff2 = _interopRequireDefault(_OnOff); + +var _Power = require('./Power'); + +var _Power2 = _interopRequireDefault(_Power); + +var _Rms = require('./Rms'); + +var _Rms2 = _interopRequireDefault(_Rms); + +var _Multiplier = require('./Multiplier'); + +var _Multiplier2 = _interopRequireDefault(_Multiplier); + +var _Scale = require('./Scale'); + +var _Scale2 = _interopRequireDefault(_Scale); + +var _Segmenter = require('./Segmenter'); + +var _Segmenter2 = _interopRequireDefault(_Segmenter); + +var _Select = require('./Select'); + +var _Select2 = _interopRequireDefault(_Select); + +var _Slicer = require('./Slicer'); + +var _Slicer2 = _interopRequireDefault(_Slicer); + +var _Yin = require('./Yin'); + +var _Yin2 = _interopRequireDefault(_Yin); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = { + Biquad: _Biquad2.default, + Clip: _Clip2.default, + Dct: _Dct2.default, + Delta: _Delta2.default, + Fft: _Fft2.default, + Magnitude: _Magnitude2.default, + MeanStddev: _MeanStddev2.default, + Mel: _Mel2.default, + Merger: _Merger2.default, + Mfcc: _Mfcc2.default, + MinMax: _MinMax2.default, + MovingAverage: _MovingAverage2.default, + MovingMedian: _MovingMedian2.default, + OnOff: _OnOff2.default, + Power: _Power2.default, + Rms: _Rms2.default, + Multiplier: _Multiplier2.default, + Scale: _Scale2.default, + Segmenter: _Segmenter2.default, + Select: _Select2.default, + Slicer: _Slicer2.default, + Yin: _Yin2.default +}; + +},{"./Biquad":20,"./Clip":21,"./Dct":22,"./Delta":23,"./Fft":24,"./Magnitude":25,"./MeanStddev":26,"./Mel":27,"./Merger":28,"./Mfcc":29,"./MinMax":30,"./MovingAverage":31,"./MovingMedian":32,"./Multiplier":33,"./OnOff":34,"./Power":35,"./Rms":36,"./Scale":37,"./Segmenter":38,"./Select":39,"./Slicer":40,"./Yin":41}],43:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + processStreamParams: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + }, + processFrame: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + }, + finalizeStream: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + } +}; + +/** + * Create a bridge between the graph and application logic. Handle `push` + * and `pull` paradigms. + * + * This sink can handle any type of input (`signal`, `vector`, `scalar`) + * + * @memberof module:common.sink + * + * @param {Object} options - Override default parameters. + * @param {Function} [options.processFrame=null] - Callback executed on each + * `processFrame` call. + * @param {Function} [options.finalizeStream=null] - Callback executed on each + * `finalizeStream` call. + * + * @see {@link module:core.BaseLfo#processFrame} + * @see {@link module:core.BaseLfo#processStreamParams} + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const frames = [ + * { time: 0, data: [0, 1] }, + * { time: 1, data: [1, 2] }, + * ]; + * + * const eventIn = new EventIn({ + * frameType: 'vector', + * frameSize: 2, + * frameRate: 1, + * }); + * + * const bridge = new Bridge({ + * processFrame: (frame) => console.log(frame), + * }); + * + * eventIn.connect(bridge); + * eventIn.start(); + * + * // callback executed on each frame + * eventIn.processFrame(frame[0]); + * > { time: 0, data: [0, 1] } + * eventIn.processFrame(frame[1]); + * > { time: 1, data: [1, 2] } + * + * // pull current frame when needed + * console.log(bridge.frame); + * > { time: 1, data: [1, 2] } + */ + +var Bridge = function (_BaseLfo) { + (0, _inherits3.default)(Bridge, _BaseLfo); + + function Bridge() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, Bridge); + return (0, _possibleConstructorReturn3.default)(this, (Bridge.__proto__ || (0, _getPrototypeOf2.default)(Bridge)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Bridge, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var processStreamParamsCallback = this.params.get('processStreamParams'); + + if (processStreamParamsCallback !== null) processStreamParamsCallback(this.streamParams); + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + var finalizeStreamCallback = this.params.get('finalizeStream'); + + if (finalizeStreamCallback !== null) finalizeStreamCallback(endTime); + } + + // process any type + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar() {} + /** @private */ + + }, { + key: 'processVector', + value: function processVector() {} + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal() {} + + /** @private */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + + var processFrameCallback = this.params.get('processFrame'); + var output = this.frame; + output.data = new Float32Array(this.streamParams.frameSize); + // pull interface (we copy data since we don't know what could + // be done outside the graph) + for (var i = 0; i < this.streamParams.frameSize; i++) { + output.data[i] = frame.data[i]; + }output.time = frame.time; + output.metadata = frame.metadata; + + // `push` interface + if (processFrameCallback !== null) processFrameCallback(output); + } + }]); + return Bridge; +}(_BaseLfo3.default); + +exports.default = Bridge; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],44:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + separateArrays: { + type: 'boolean', + default: false, + constant: true + }, + callback: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + } +}; + +/** + * Record input frames from a graph. This sink can handle `signal`, `vector` + * or `scalar` inputs. + * + * When the recording is stopped (either by calling `stop` on the node or when + * the stream is finalized), the callback given as parameter is executed with + * the recorder data as argument. + * + * + * @param {Object} options - Override default parameters. + * @param {Boolean} [options.separateArrays=false] - Format of the retrieved + * values: + * - when `false`, format is [{ time, data }, { time, data }, ...] + * - when `true`, format is { time: [...], data: [...] } + * @param {Function} [options.callback] - Callback to execute when a new record + * is ended. This can happen when: + * - `stop` is called on the recorder + * - `stop` is called on the source. + * + * @todo - Add auto record param. + * + * @memberof module:common.sink + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const eventIn = new lfo.source.EventIn({ + * frameType: 'vector', + * frameSize: 2, + * frameRate: 0, + * }); + * + * const recorder = new lfo.sink.DataRecorder({ + * callback: (data) => console.log(data), + * }); + * + * eventIn.connect(recorder); + * eventIn.start(); + * recorder.start(); + * + * eventIn.process(0, [0, 1]); + * eventIn.process(1, [1, 2]); + * + * recorder.stop(); + * > [{ time: 0, data: [0, 1] }, { time: 1, data: [1, 2] }]; + */ + +var DataRecorder = function (_BaseLfo) { + (0, _inherits3.default)(DataRecorder, _BaseLfo); + + function DataRecorder() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, DataRecorder); + + /** + * Define if the node is currently recording. + * + * @type {Boolean} + * @name isRecording + * @instance + * @memberof module:sink.SignalRecorder + */ + var _this = (0, _possibleConstructorReturn3.default)(this, (DataRecorder.__proto__ || (0, _getPrototypeOf2.default)(DataRecorder)).call(this, definitions, options)); + + _this.isRecording = false; + return _this; + } + + /** @private */ + + + (0, _createClass3.default)(DataRecorder, [{ + key: '_initStore', + value: function _initStore() { + var separateArrays = this.params.get('separateArrays'); + + if (separateArrays) this._store = { time: [], data: [] };else this._store = []; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + this._initStore(); + this.propagateStreamParams(); + } + + /** + * Start recording. + * + * @see {@link module:client.sink.DataRecorder#stop} + */ + + }, { + key: 'start', + value: function start() { + this.isRecording = true; + } + + /** + * Stop recording and execute the callback defined in parameters. + * + * @see {@link module:client.sink.DataRecorder#start} + */ + + }, { + key: 'stop', + value: function stop() { + if (this.isRecording) { + this.isRecording = false; + var callback = this.params.get('callback'); + + if (callback !== null) callback(this._store); + + this._initStore(); + } + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream() { + this.stop(); + } + + // handle any input types + /** @private */ + + }, { + key: 'processScalar', + value: function processScalar(frame) {} + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) {} + /** @private */ + + }, { + key: 'processVector', + value: function processVector(frame) {} + }, { + key: 'processFrame', + value: function processFrame(frame) { + if (this.isRecording) { + this.prepareFrame(frame); + + var separateArrays = this.params.get('separateArrays'); + var entry = { + time: frame.time, + data: new Float32Array(frame.data) + }; + + if (!separateArrays) { + this._store.push(entry); + } else { + this._store.time.push(entry.time); + this._store.data.push(entry.data); + } + } + } + }]); + return DataRecorder; +}(_BaseLfo3.default); + +exports.default = DataRecorder; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],45:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + time: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + }, + data: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + }, + metadata: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + }, + streamParams: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + }, + frameIndex: { + type: 'boolean', + default: false, + metas: { kind: 'dynamic' } + } + + /** + * Log `frame.time`, `frame.data`, `frame.metadata` and/or + * `streamAttributes` of any node in the console. + * + * This sink can handle any type if input (`signal`, `vector`, `scalar`) + * + * @param {Object} options - Override parameters default values. + * @param {Boolean} [options.time=false] - Log incomming `frame.time` if `true`. + * @param {Boolean} [options.data=false] - Log incomming `frame.data` if `true`. + * @param {Boolean} [options.metadata=false] - Log incomming `frame.metadata` + * if `true`. + * @param {Boolean} [options.streamParams=false] - Log `streamParams` of the + * previous node when graph is started. + * @param {Boolean} [options.frameIndex=false] - Log index of the incomming + * `frame`. + * + * @memberof module:common.sink + * + * @example + * import * as lfo from 'waves-lfo/common'; + * + * const logger = new lfo.sink.Logger({ data: true }); + * whateverOperator.connect(logger); + */ +}; +var Logger = function (_BaseLfo) { + (0, _inherits3.default)(Logger, _BaseLfo); + + function Logger(options) { + (0, _classCallCheck3.default)(this, Logger); + return (0, _possibleConstructorReturn3.default)(this, (Logger.__proto__ || (0, _getPrototypeOf2.default)(Logger)).call(this, definitions, options)); + } + + /** @private */ + + + (0, _createClass3.default)(Logger, [{ + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + if (this.params.get('streamParams') === true) console.log(prevStreamParams); + + this.frameIndex = 0; + } + + /** @private */ + + }, { + key: 'processFunction', + value: function processFunction(frame) { + if (this.params.get('frameIndex') === true) console.log(this.frameIndex++); + + if (this.params.get('time') === true) console.log(frame.time); + + if (this.params.get('data') === true) console.log(frame.data); + + if (this.params.get('metadata') === true) console.log(frame.metadata); + } + }]); + return Logger; +}(_BaseLfo3.default); + +exports.default = Logger; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],46:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo2 = require('../../core/BaseLfo'); + +var _BaseLfo3 = _interopRequireDefault(_BaseLfo2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var definitions = { + duration: { + type: 'float', + default: 10, + min: 0, + metas: { kind: 'static' } + }, + callback: { + type: 'any', + default: null, + nullable: true, + metas: { kind: 'dynamic' } + }, + ignoreLeadingZeros: { + type: 'boolean', + default: true, + metas: { kind: 'static' } + }, + retrieveAudioBuffer: { + type: 'boolean', + default: false, + constant: true + }, + audioContext: { + type: 'any', + default: null, + nullable: true + } +}; + +/** + * Record an `signal` input stream of arbitrary duration and retrieve it + * when done. + * + * When recording is stopped (either when the `stop` method is called, the + * defined duration has been recorded, or the source of the graph finalized + * the stream), the callback given as parameter is executed with the + * `AudioBuffer` or `Float32Array` containing the recorded signal as argument. + * + * @todo - add option to return only the Float32Array and not an audio buffer + * (node compliant) `retrieveAudioBuffer: false` + * + * @param {Object} options - Override default parameters. + * @param {Number} [options.duration=10] - Maximum duration of the recording. + * @param {Number} [options.callback] - Callback to execute when a new record is + * ended. This can happen: `stop` is called on the recorder, `stop` is called + * on the source or when the buffer is full according to the given `duration`. + * @param {Object} [options.ignoreLeadingZeros=true] - Start the effective + * recording on the first non-zero value. + * @param {Boolean} [options.retrieveAudioBuffer=false] - Define if an `AudioBuffer` + * should be retrieved or only the raw Float32Array of data. + * (works only in browser) + * @param {AudioContext} [options.audioContext=null] - If + * `retrieveAudioBuffer` is set to `true`, audio context to be used + * in order to create the final audio buffer. + * (works only in browser) + * + * @memberof module:common.sink + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const audioContext = new AudioContext(); + * + * navigator.mediaDevices + * .getUserMedia({ audio: true }) + * .then(init) + * .catch((err) => console.error(err.stack)); + * + * function init(stream) { + * const source = audioContext.createMediaStreamSource(stream); + * + * const audioInNode = new lfo.source.AudioInNode({ + * sourceNode: source, + * audioContext: audioContext, + * }); + * + * const signalRecorder = new lfo.sink.SignalRecorder({ + * duration: 6, + * retrieveAudioBuffer: true, + * audioContext: audioContext, + * callback: (buffer) => { + * const bufferSource = audioContext.createBufferSource(); + * bufferSource.buffer = buffer; + * bufferSource.connect(audioContext.destination); + * bufferSource.start(); + * } + * }); + * + * audioInNode.connect(signalRecorder); + * audioInNode.start(); + * signalRecorder.start(); + * }); + */ + +var SignalRecorder = function (_BaseLfo) { + (0, _inherits3.default)(SignalRecorder, _BaseLfo); + + function SignalRecorder() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, SignalRecorder); + + /** + * Define is the node is currently recording or not. + * + * @type {Boolean} + * @name isRecording + * @instance + * @memberof module:client.sink.SignalRecorder + */ + var _this = (0, _possibleConstructorReturn3.default)(this, (SignalRecorder.__proto__ || (0, _getPrototypeOf2.default)(SignalRecorder)).call(this, definitions, options)); + + _this.isRecording = false; + + var retrieveAudioBuffer = _this.params.get('retrieveAudioBuffer'); + var audioContext = _this.params.get('audioContext'); + // needed to retrieve an AudioBuffer + if (retrieveAudioBuffer && audioContext === null) throw new Error('Invalid parameter "audioContext": an AudioContext must be provided when `retrieveAudioBuffer` is set to `true`'); + + _this._audioContext = audioContext; + _this._ignoreZeros = false; + _this._isInfiniteBuffer = false; + _this._stack = []; + _this._buffer = null; + _this._bufferLength = null; + _this._currentIndex = null; + return _this; + } + + (0, _createClass3.default)(SignalRecorder, [{ + key: '_initBuffer', + value: function _initBuffer() { + this._buffer = new Float32Array(this._bufferLength); + this._stack.length = 0; + this._currentIndex = 0; + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + + var duration = this.params.get('duration'); + var sampleRate = this.streamParams.sourceSampleRate; + + if (isFinite(duration)) { + this._isInfiniteBuffer = false; + this._bufferLength = sampleRate * duration; + } else { + this._isInfiniteBuffer = true; + this._bufferLength = sampleRate * 10; + } + + this._initBuffer(); + this.propagateStreamParams(); + } + + /** + * Start recording. + */ + + }, { + key: 'start', + value: function start() { + this.isRecording = true; + this._ignoreZeros = this.params.get('ignoreLeadingZeros'); + } + + /** + * Stop recording and execute the callback defined in parameters. + */ + + }, { + key: 'stop', + value: function stop() { + if (this.isRecording) { + // ignore next incomming frame + this.isRecording = false; + + var retrieveAudioBuffer = this.params.get('retrieveAudioBuffer'); + var callback = this.params.get('callback'); + var currentIndex = this._currentIndex; + var buffer = this._buffer; + var output = void 0; + + if (!this._isInfiniteBuffer) { + output = new Float32Array(currentIndex); + output.set(buffer.subarray(0, currentIndex), 0); + } else { + var bufferLength = this._bufferLength; + var stack = this._stack; + + output = new Float32Array(stack.length * bufferLength + currentIndex); + + // copy all stacked buffers + for (var i = 0; i < stack.length; i++) { + var stackedBuffer = stack[i]; + output.set(stackedBuffer, bufferLength * i); + }; + // copy data contained in current buffer + output.set(buffer.subarray(0, currentIndex), stack.length * bufferLength); + } + + if (retrieveAudioBuffer && this._audioContext) { + var length = output.length; + var sampleRate = this.streamParams.sourceSampleRate; + var audioBuffer = this._audioContext.createBuffer(1, length, sampleRate); + var channelData = audioBuffer.getChannelData(0); + channelData.set(output, 0); + + callback(audioBuffer); + } else { + callback(output); + } + + // reinit buffer, stack, and currentIndex + this._initBuffer(); + } + } + + /** @private */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + this.stop(); + } + + /** @private */ + + }, { + key: 'processSignal', + value: function processSignal(frame) { + if (!this.isRecording) return; + + var block = null; + var input = frame.data; + var bufferLength = this._bufferLength; + var buffer = this._buffer; + + if (this._ignoreZeros === false) { + block = new Float32Array(input); + } else if (input[input.length - 1] !== 0) { + // find first index where value !== 0 + var i = void 0; + + for (i = 0; i < input.length; i++) { + if (input[i] !== 0) break; + } // copy non zero segment + block = new Float32Array(input.subarray(i)); + // don't repeat this logic once a non-zero value has been found + this._ignoreZeros = false; + } + + if (block !== null) { + var availableSpace = bufferLength - this._currentIndex; + var currentBlock = void 0; + + if (availableSpace < block.length) currentBlock = block.subarray(0, availableSpace);else currentBlock = block; + + buffer.set(currentBlock, this._currentIndex); + this._currentIndex += currentBlock.length; + + if (this._isInfiniteBuffer && this._currentIndex === bufferLength) { + this._stack.push(buffer); + + currentBlock = block.subarray(availableSpace); + this._buffer = new Float32Array(bufferLength); + this._buffer.set(currentBlock, 0); + this._currentIndex = currentBlock.length; + } + + // stop if the buffer is finite and full + if (!this._isInfiniteBuffer && this._currentIndex === bufferLength) this.stop(); + } + } + }]); + return SignalRecorder; +}(_BaseLfo3.default); + +exports.default = SignalRecorder; + +},{"../../core/BaseLfo":50,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],47:[function(require,module,exports){ +(function (process){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _isFinite = require('babel-runtime/core-js/number/is-finite'); + +var _isFinite2 = _interopRequireDefault(_isFinite); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _BaseLfo = require('../../core/BaseLfo'); + +var _BaseLfo2 = _interopRequireDefault(_BaseLfo); + +var _SourceMixin2 = require('../../core/SourceMixin'); + +var _SourceMixin3 = _interopRequireDefault(_SourceMixin2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// http://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser +var isNode = new Function('try { return this === global; } catch(e) { return false }'); + +/** + * Create a function that returns time in seconds according to the current + * environnement (node or browser). + * If running in node the time rely on `process.hrtime`, while if in the browser + * it is provided by the `currentTime` of an `AudioContext`, this context can + * optionnaly be provided to keep time consistency between several `EventIn` + * nodes. + * + * @param {AudioContext} [audioContext=null] - Optionnal audio context. + * @return {Function} + * @private + */ +function getTimeFunction() { + var audioContext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (isNode()) { + return function () { + var t = process.hrtime(); + return t[0] + t[1] * 1e-9; + }; + } else { + return function () { + return performance.now() / 1000; + }; + } +} + +var definitions = { + absoluteTime: { + type: 'boolean', + default: false, + constant: true + }, + audioContext: { + type: 'any', + default: null, + constant: true, + nullable: true + }, + frameType: { + type: 'enum', + list: ['signal', 'vector', 'scalar'], + default: 'signal', + constant: true + }, + frameSize: { + type: 'integer', + default: 1, + min: 1, + max: +Infinity, // not recommended... + metas: { kind: 'static' } + }, + sampleRate: { + type: 'float', + default: null, + min: 0, + max: +Infinity, // same here + nullable: true, + metas: { kind: 'static' } + }, + frameRate: { + type: 'float', + default: null, + min: 0, + max: +Infinity, // same here + nullable: true, + metas: { kind: 'static' } + }, + description: { + type: 'any', + default: null, + constant: true + } +}; + +/** + * The `EventIn` operator allows to manually create a stream of data or to feed + * a stream from another source (e.g. sensors) into a processing graph. + * + * @param {Object} options - Override parameters' default values. + * @param {String} [options.frameType='signal'] - Type of the input - allowed + * values: `signal`, `vector` or `scalar`. + * @param {Number} [options.frameSize=1] - Size of the output frame. + * @param {Number} [options.sampleRate=null] - Sample rate of the source stream, + * if of type `signal`. + * @param {Number} [options.frameRate=null] - Rate of the source stream, if of + * type `vector`. + * @param {Array|String} [options.description] - Optionnal description + * describing the dimensions of the output frame + * @param {Boolean} [options.absoluteTime=false] - Define if time should be used + * as forwarded as given in the process method, or relatively to the time of + * the first `process` call after start. + * + * @memberof module:common.source + * + * @todo - Add a `logicalTime` parameter to tag frame according to frame rate. + * + * @example + * import * as lfo from 'waves-lfo/client'; + * + * const eventIn = new lfo.source.EventIn({ + * frameType: 'vector', + * frameSize: 3, + * frameRate: 1 / 50, + * description: ['alpha', 'beta', 'gamma'], + * }); + * + * // connect source to operators and sink(s) + * + * // initialize and start the graph + * eventIn.start(); + * + * // feed `deviceorientation` data into the graph + * window.addEventListener('deviceorientation', (e) => { + * const frame = { + * time: window.performace.now() / 1000, + * data: [e.alpha, e.beta, e.gamma], + * }; + * + * eventIn.processFrame(frame); + * }, false); + */ + +var EventIn = function (_SourceMixin) { + (0, _inherits3.default)(EventIn, _SourceMixin); + + function EventIn() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + (0, _classCallCheck3.default)(this, EventIn); + + var _this = (0, _possibleConstructorReturn3.default)(this, (EventIn.__proto__ || (0, _getPrototypeOf2.default)(EventIn)).call(this, definitions, options)); + + var audioContext = _this.params.get('audioContext'); + _this._getTime = getTimeFunction(audioContext); + _this._startTime = null; + _this._systemTime = null; + _this._absoluteTime = _this.params.get('absoluteTime'); + return _this; + } + + /** + * Propagate the `streamParams` in the graph and allow to push frames into + * the graph. Any call to `process` or `processFrame` before `start` will be + * ignored. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#resetStream} + * @see {@link module:common.source.EventIn#stop} + */ + + + (0, _createClass3.default)(EventIn, [{ + key: 'start', + value: function start() { + var _this2 = this; + + var startTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (this.initialized === false) { + if (this.initPromise === null) // init has not yet been called + this.initPromise = this.init(); + + return this.initPromise.then(function () { + return _this2.start(startTime); + }); + } + + this._startTime = startTime; + this._systemTime = null; // value set in the first `process` call + + this.started = true; + } + + /** + * Finalize the stream and stop the whole graph. Any call to `process` or + * `processFrame` after `stop` will be ignored. + * + * @see {@link module:core.BaseLfo#finalizeStream} + * @see {@link module:common.source.EventIn#start} + */ + + }, { + key: 'stop', + value: function stop() { + if (this.started && this._startTime !== null) { + var currentTime = this._getTime(); + var endTime = this.frame.time + (currentTime - this._systemTime); + + this.finalizeStream(endTime); + this.started = false; + } + } + + /** @private */ + + }, { + key: 'processStreamParams', + value: function processStreamParams() { + var frameSize = this.params.get('frameSize'); + var frameType = this.params.get('frameType'); + var sampleRate = this.params.get('sampleRate'); + var frameRate = this.params.get('frameRate'); + var description = this.params.get('description'); + + // init operator's stream params + this.streamParams.frameSize = frameType === 'scalar' ? 1 : frameSize; + this.streamParams.frameType = frameType; + this.streamParams.description = description; + + if (frameType === 'signal') { + if (sampleRate === null) throw new Error('Undefined "sampleRate" for "signal" stream'); + + this.streamParams.sourceSampleRate = sampleRate; + this.streamParams.frameRate = sampleRate / frameSize; + this.streamParams.sourceSampleCount = frameSize; + } else if (frameType === 'vector' || frameType === 'scalar') { + if (frameRate === null) throw new Error('Undefined "frameRate" for "' + frameType + '" stream'); + + this.streamParams.frameRate = frameRate; + this.streamParams.sourceSampleRate = frameRate; + this.streamParams.sourceSampleCount = 1; + } + + this.propagateStreamParams(); + } + + /** @private */ + + }, { + key: 'processFunction', + value: function processFunction(frame) { + var currentTime = this._getTime(); + var inData = frame.data.length ? frame.data : [frame.data]; + var outData = this.frame.data; + // if no time provided, use system time + var time = (0, _isFinite2.default)(frame.time) ? frame.time : currentTime; + + if (this._startTime === null) this._startTime = time; + + if (this._absoluteTime === false) time = time - this._startTime; + + for (var i = 0, l = this.streamParams.frameSize; i < l; i++) { + outData[i] = inData[i]; + }this.frame.time = time; + this.frame.metadata = frame.metadata; + // store current time to compute `endTime` on stop + this._systemTime = currentTime; + } + + /** + * Alternative interface to propagate a frame in the graph. Pack `time`, + * `data` and `metadata` in a frame object. + * + * @param {Number} time - Frame time. + * @param {Float32Array|Array} data - Frame data. + * @param {Object} metadata - Optionnal frame metadata. + * + * @example + * eventIn.process(1, [0, 1, 2]); + * // is equivalent to + * eventIn.processFrame({ time: 1, data: [0, 1, 2] }); + */ + + }, { + key: 'process', + value: function process(time, data) { + var metadata = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + this.processFrame({ time: time, data: data, metadata: metadata }); + } + + /** + * Propagate a frame object in the graph. + * + * @param {Object} frame - Input frame. + * @param {Number} frame.time - Frame time. + * @param {Float32Array|Array} frame.data - Frame data. + * @param {Object} [frame.metadata=undefined] - Optionnal frame metadata. + * + * @example + * eventIn.processFrame({ time: 1, data: [0, 1, 2] }); + */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + if (!this.started) return; + + this.prepareFrame(); + this.processFunction(frame); + this.propagateFrame(); + } + }]); + return EventIn; +}((0, _SourceMixin3.default)(_BaseLfo2.default)); + +exports.default = EventIn; + +}).call(this,require('_process')) + +},{"../../core/BaseLfo":50,"../../core/SourceMixin":51,"_process":54,"babel-runtime/core-js/number/is-finite":59,"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],48:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +// shortcuts / helpers +var PI = Math.PI; +var cos = Math.cos; +var sin = Math.sin; +var sqrt = Math.sqrt; + +// window creation functions +function initHannWindow(buffer, size, normCoefs) { + var linSum = 0; + var powSum = 0; + var step = 2 * PI / size; + + for (var i = 0; i < size; i++) { + var phi = i * step; + var value = 0.5 - 0.5 * cos(phi); + + buffer[i] = value; + + linSum += value; + powSum += value * value; + } + + normCoefs.linear = size / linSum; + normCoefs.power = sqrt(size / powSum); +} + +function initHammingWindow(buffer, size, normCoefs) { + var linSum = 0; + var powSum = 0; + var step = 2 * PI / size; + + for (var i = 0; i < size; i++) { + var phi = i * step; + var value = 0.54 - 0.46 * cos(phi); + + buffer[i] = value; + + linSum += value; + powSum += value * value; + } + + normCoefs.linear = size / linSum; + normCoefs.power = sqrt(size / powSum); +} + +function initBlackmanWindow(buffer, size, normCoefs) { + var linSum = 0; + var powSum = 0; + var step = 2 * PI / size; + + for (var i = 0; i < size; i++) { + var phi = i * step; + var value = 0.42 - 0.5 * cos(phi) + 0.08 * cos(2 * phi); + + buffer[i] = value; + + linSum += value; + powSum += value * value; + } + + normCoefs.linear = size / linSum; + normCoefs.power = sqrt(size / powSum); +} + +function initBlackmanHarrisWindow(buffer, size, normCoefs) { + var linSum = 0; + var powSum = 0; + var a0 = 0.35875; + var a1 = 0.48829; + var a2 = 0.14128; + var a3 = 0.01168; + var step = 2 * PI / size; + + for (var i = 0; i < size; i++) { + var phi = i * step; + var value = a0 - a1 * cos(phi) + a2 * cos(2 * phi);-a3 * cos(3 * phi); + + buffer[i] = value; + + linSum += value; + powSum += value * value; + } + + normCoefs.linear = size / linSum; + normCoefs.power = sqrt(size / powSum); +} + +function initSineWindow(buffer, size, normCoefs) { + var linSum = 0; + var powSum = 0; + var step = PI / size; + + for (var i = 0; i < size; i++) { + var phi = i * step; + var value = sin(phi); + + buffer[i] = value; + + linSum += value; + powSum += value * value; + } + + normCoefs.linear = size / linSum; + normCoefs.power = sqrt(size / powSum); +} + +function initRectangleWindow(buffer, size, normCoefs) { + for (var i = 0; i < size; i++) { + buffer[i] = 1; + } // @todo - check if these are proper values + normCoefs.linear = 1; + normCoefs.power = 1; +} + +/** + * Create a buffer with window signal. + * + * @memberof module:common.utils + * + * @param {String} name - Name of the window. + * @param {Float32Array} buffer - Buffer to be populated with the window signal. + * @param {Number} size - Size of the buffer. + * @param {Object} normCoefs - Object to be populated with the normailzation + * coefficients. + */ +function initWindow(name, buffer, size, normCoefs) { + name = name.toLowerCase(); + + switch (name) { + case 'hann': + case 'hanning': + initHannWindow(buffer, size, normCoefs); + break; + case 'hamming': + initHammingWindow(buffer, size, normCoefs); + break; + case 'blackman': + initBlackmanWindow(buffer, size, normCoefs); + break; + case 'blackmanharris': + initBlackmanHarrisWindow(buffer, size, normCoefs); + break; + case 'sine': + initSineWindow(buffer, size, normCoefs); + break; + case 'rectangle': + initRectangleWindow(buffer, size, normCoefs); + break; + } +} + +exports.default = initWindow; + +},{}],49:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.decoders = exports.encoders = exports.opcodes = undefined; + +var _stringify = require('babel-runtime/core-js/json/stringify'); + +var _stringify2 = _interopRequireDefault(_stringify); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +//http://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer +// converts a nodejs Buffer to ArrayBuffer +// export function bufferToArrayBuffer(buffer) { +// const ab = new ArrayBuffer(buffer.length); +// const view = new Uint8Array(ab); + +// for (let i = 0; i < buffer.length; ++i) +// view[i] = buffer[i]; + +// return ab; +// } + +// export function arrayBufferToBuffer(arrayBuffer) { +// const buffer = new Buffer(arrayBuffer.byteLength); +// const view = new Uint8Array(arrayBuffer); + +// for (let i = 0; i < buffer.length; ++i) +// buffer[i] = view[i]; + +// return buffer; +// } + +// http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String +function Uint16Array2json(arr) { + var str = String.fromCharCode.apply(null, arr); + return JSON.parse(str.replace(/\u0000/g, '')); +} + +function json2Uint16Array(json) { + var str = (0, _stringify2.default)(json); + var buffer = new ArrayBuffer(str.length * 2); // 2 bytes for each char + var bufferView = new Uint16Array(buffer); + + for (var i = 0, l = str.length; i < l; i++) { + bufferView[i] = str.charCodeAt(i); + }return bufferView; +} + +var opcodes = exports.opcodes = { + INIT_MODULE_REQ: 10, + INIT_MODULE_ACK: 11, + PROCESS_STREAM_PARAMS: 12, + RESET_STREAM: 13, + FINALIZE_STREAM: 14, + PROCESS_FRAME: 15 + + // +};var encoders = exports.encoders = { + opcode: function opcode(name) { + var opcode = opcodes[name]; + var buffer = new Uint16Array(1); + buffer[0] = opcode; + + return buffer; + }, + + // `opcode` 2 bytes (Uint16) | + initModuleReq: function initModuleReq() { + var payload = encoders.opcode('INIT_MODULE_REQ'); + return payload.buffer; + }, + // `opcode` 2 bytes (Uint16) | + initModuleAck: function initModuleAck() { + var payload = encoders.opcode('INIT_MODULE_ACK'); + return payload.buffer; + }, + // `opcode` 2 bytes (Uint16) | + // `streamParams` n bytes (Uint16) + streamParams: function streamParams(_streamParams) { + var opcode = encoders.opcode('PROCESS_STREAM_PARAMS'); + var streamParamsBuffer = json2Uint16Array(_streamParams); + + var payload = new Uint16Array(1 + streamParamsBuffer.length); + payload.set(opcode, 0); + payload.set(streamParamsBuffer, 1); + + return payload.buffer; + }, + // `opcode` 2 bytes (Uint16) | + resetStream: function resetStream() { + var payload = encoders.opcode('RESET_STREAM'); + return payload.buffer; + }, + // `opcode` 2 bytes (Uint16) | + // `endTime` 8 bytes (Float64) + finalizeStream: function finalizeStream(endTime) { + var opcode = encoders.opcode('RESET_STREAM'); + + var endTimeBuffer = new Float64Array(1); + endTimeBuffer[0] = endTime; + + var payload = new Uint16Array(1 + 4); + payload.set(opcode, 0); + payload.set(new Uint16Array(endTimeBuffer.buffer), 1); + + return payload.buffer; + }, + // `opcode` 2 bytes (Uint16) | + // `time` 8 bytes (Float64) | + // `data` frameSize * 4 (Float32) | + // `metadata` n bytes (Uint16) + processFrame: function processFrame(frame, frameSize) { + var opcode = encoders.opcode('PROCESS_FRAME'); + + var time = new Float64Array(1); + time[0] = frame.time; + + var data = new Float32Array(frameSize); + for (var i = 0; i < frameSize; i++) { + data[i] = frame.data[i]; + }var metadata = json2Uint16Array(frame.metadata); + + var length = 1 + 4 + 2 * frameSize + metadata.length; + var payload = new Uint16Array(length); + payload.set(opcode, 0); + payload.set(new Uint16Array(time.buffer), 1); + payload.set(new Uint16Array(data.buffer), 1 + 4); + payload.set(metadata, 1 + 4 + 2 * frameSize); + + return payload.buffer; + } +}; + +var decoders = exports.decoders = { + opcode: function opcode(arrayBuffer) { + return new Uint16Array(arrayBuffer)[0]; + }, + + // `opcode` 2 bytes (Uint16) | + // `streamParams` n bytes (Uint16) + streamParams: function streamParams(arrayBuffer) { + var payload = new Uint16Array(arrayBuffer.slice(2)); + var prevStreamParams = Uint16Array2json(payload); + return prevStreamParams; + }, + + // `opcode` 2 bytes (Uint16) | + // `endTime` 8 bytes (Float64) + finalizeStream: function finalizeStream(arrayBuffer) { + return new Float64Array(arrayBuffer.slice(2))[0]; + }, + + // `opcode` 2 bytes (Uint16) | + // `time` 8 bytes (Float64) | + // `data` frameSize * 4 (Float32) | + // `metadata` n bytes (Uint16) + processFrame: function processFrame(arrayBuffer, frameSize) { + // 1 * 8 bytes + var timeStart = 2; + var timeEnd = timeStart + 8; + var time = new Float64Array(arrayBuffer.slice(timeStart, timeEnd))[0]; + // frameSize * 4 bytes + var dataStart = timeEnd; + var dataEnd = dataStart + 4 * frameSize; + var data = new Float32Array(arrayBuffer.slice(dataStart, dataEnd)); + // rest of payload + var metaStart = dataEnd; + var metaBuffer = new Uint16Array(arrayBuffer.slice(metaStart)); + var metadata = Uint16Array2json(metaBuffer); + + return { time: time, data: data, metadata: metadata }; + } +}; + +},{"babel-runtime/core-js/json/stringify":57}],50:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _assign = require('babel-runtime/core-js/object/assign'); + +var _assign2 = _interopRequireDefault(_assign); + +var _promise = require('babel-runtime/core-js/promise'); + +var _promise2 = _interopRequireDefault(_promise); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _parameters = require('@ircam/parameters'); + +var _parameters2 = _interopRequireDefault(_parameters); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var id = 0; + +/** + * Base `lfo` class to be extended in order to create new nodes. + * + * Nodes are divided in 3 categories: + * - **`source`** are responsible for acquering a signal and its properties + * (frameRate, frameSize, etc.) + * - **`sink`** are endpoints of the graph, such nodes can be recorders, + * visualizers, etc. + * - **`operator`** are used to make computation on the input signal and + * forward the results below in the graph. + * + * In most cases the methods to override / extend are: + * - the **`constructor`** to define the parameters of the new lfo node. + * - the **`processStreamParams`** method to define how the node modify the + * stream attributes (e.g. by changing the frame size) + * - the **`process{FrameType}`** method to define the operations that the + * node apply on the stream. The type of input a node can handle is defined + * by its implemented interface, if it implements `processSignal`, a stream + * of type `signal` can be processed, `processVector` to handle + * an input of type `vector`. + * + * _This class should be considered abstract and only + * be used as a base class to extend._ + * + * #### overview of the interface + * + * **initModule** + * + * Returns a Promise that resolves when the module is initialized. Is + * especially important for modules that rely on asynchronous underlying APIs. + * + * **processStreamParams(prevStreamParams)** + * + * `base` class (default implementation) + * - call `prepareStreamParams` + * - call `propagateStreamParams` + * + * `child` class + * - override some of the inherited `streamParams` + * - creates the any related logic buffers + * - call `propagateStreamParams` + * + * _should not call `super.processStreamParams`_ + * + * **prepareStreamParams()** + * + * - assign prevStreamParams to this.streamParams + * - check if the class implements the correct `processInput` method + * + * _shouldn't be extended, only consumed in `processStreamParams`_ + * + * **propagateStreamParams()** + * + * - creates the `frameData` buffer + * - propagate `streamParams` to children + * + * _shouldn't be extended, only consumed in `processStreamParams`_ + * + * **processFrame()** + * + * `base` class (default implementation) + * - call `prepareFrame` + * - assign frameTime and frameMetadata to identity + * - call the proper function according to inputType + * - call `propagateFrame` + * + * `child` class + * - call `prepareFrame` + * - do whatever you want with incomming frame + * - call `propagateFrame` + * + * _should not call `super.processFrame`_ + * + * **prepareFrame()** + * + * - if `reinit` and trigger `processStreamParams` if needed + * + * _shouldn't be extended, only consumed in `processFrame`_ + * + * **propagateFrame()** + * + * - propagate frame to children + * + * _shouldn't be extended, only consumed in `processFrame`_ + * + * @memberof module:core + */ + +var BaseLfo = function () { + function BaseLfo() { + var definitions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + (0, _classCallCheck3.default)(this, BaseLfo); + + this.cid = id++; + + /** + * Parameter bag containing parameter instances. + * + * @type {Object} + * @name params + * @instance + * @memberof module:core.BaseLfo + */ + this.params = (0, _parameters2.default)(definitions, options); + // listen for param updates + this.params.addListener(this.onParamUpdate.bind(this)); + + /** + * Description of the stream output of the node. + * Set to `null` when the node is destroyed. + * + * @type {Object} + * @property {Number} frameSize - Frame size at the output of the node. + * @property {Number} frameRate - Frame rate at the output of the node. + * @property {String} frameType - Frame type at the output of the node, + * possible values are `signal`, `vector` or `scalar`. + * @property {Array|String} description - If type is `vector`, describe + * the dimension(s) of output stream. + * @property {Number} sourceSampleRate - Sample rate of the source of the + * graph. _The value should be defined by sources and never modified_. + * @property {Number} sourceSampleCount - Number of consecutive discrete + * time values contained in the data frame output by the source. + * _The value should be defined by sources and never modified_. + * + * @name streamParams + * @instance + * @memberof module:core.BaseLfo + */ + this.streamParams = { + frameType: null, + frameSize: 1, + frameRate: 0, + description: null, + sourceSampleRate: 0, + sourceSampleCount: null + }; + + /** + * Current frame. This object and its data are updated at each incomming + * frame without reallocating memory. + * + * @type {Object} + * @name frame + * @property {Number} time - Time of the current frame. + * @property {Float32Array} data - Data of the current frame. + * @property {Object} metadata - Metadata associted to the current frame. + * @instance + * @memberof module:core.BaseLfo + */ + this.frame = { + time: 0, + data: null, + metadata: {} + }; + + /** + * List of nodes connected to the ouput of the node (lower in the graph). + * At each frame, the node forward its `frame` to to all its `nextModules`. + * + * @type {Array} + * @name nextModules + * @instance + * @memberof module:core.BaseLfo + * @see {@link module:core.BaseLfo#connect} + * @see {@link module:core.BaseLfo#disconnect} + */ + this.nextModules = []; + + /** + * The node from which the node receive the frames (upper in the graph). + * + * @type {BaseLfo} + * @name prevModule + * @instance + * @memberof module:core.BaseLfo + * @see {@link module:core.BaseLfo#connect} + * @see {@link module:core.BaseLfo#disconnect} + */ + this.prevModule = null; + + /** + * Is set to true when a static parameter is updated. On the next input + * frame all the subgraph streamParams starting from this node will be + * updated. + * + * @type {Boolean} + * @name _reinit + * @instance + * @memberof module:core.BaseLfo + * @private + */ + this._reinit = false; + } + + /** + * Returns an object describing each available parameter of the node. + * + * @return {Object} + */ + + + (0, _createClass3.default)(BaseLfo, [{ + key: 'getParamsDescription', + value: function getParamsDescription() { + return this.params.getDefinitions(); + } + + /** + * Reset all parameters to their initial value (as defined on instantication) + * + * @see {@link module:core.BaseLfo#streamParams} + */ + + }, { + key: 'resetParams', + value: function resetParams() { + this.params.reset(); + } + + /** + * Function called when a param is updated. By default set the `_reinit` + * flag to `true` if the param is `static` one. This method should be + * extended to handle particular logic bound to a specific parameter. + * + * @param {String} name - Name of the parameter. + * @param {Mixed} value - Value of the parameter. + * @param {Object} metas - Metadata associated to the parameter. + */ + + }, { + key: 'onParamUpdate', + value: function onParamUpdate(name, value) { + var metas = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (metas.kind === 'static') this._reinit = true; + } + + /** + * Connect the current node (`prevModule`) to another node (`nextOp`). + * A given node can be connected to several operators and propagate frames + * to each of them. + * + * @param {BaseLfo} next - Next operator in the graph. + * @see {@link module:core.BaseLfo#processFrame} + * @see {@link module:core.BaseLfo#disconnect} + */ + + }, { + key: 'connect', + value: function connect(next) { + var _this = this; + + if (this.streamParams === null || next.streamParams === null) throw new Error('Invalid connection: cannot connect a dead node'); + + if (this.streamParams.frameType !== null) { + // graph has already been started + // next.processStreamParams(this.streamParams); + next.initModule().then(function () { + next.processStreamParams(_this.streamParams); + // we can forward frame from now + _this.nextModules.push(next); + next.prevModule = _this; + }); + } else { + this.nextModules.push(next); + next.prevModule = this; + } + } + + /** + * Remove the given operator from its previous operators' `nextModules`. + * + * @param {BaseLfo} [next=null] - The operator to disconnect from the current + * operator. If `null` disconnect all the next operators. + */ + + }, { + key: 'disconnect', + value: function disconnect() { + var _this2 = this; + + var next = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (next === null) { + this.nextModules.forEach(function (next) { + return _this2.disconnect(next); + }); + } else { + var index = this.nextModules.indexOf(this); + this.nextModules.splice(index, 1); + next.prevModule = null; + } + } + + /** + * Destroy all the nodes in the sub-graph starting from the current node. + * When detroyed, the `streamParams` of the node are set to `null`, the + * operator is then considered as `dead` and cannot be reconnected. + * + * @see {@link module:core.BaseLfo#connect} + */ + + }, { + key: 'destroy', + value: function destroy() { + // destroy all chidren + var index = this.nextModules.length; + + while (index--) { + this.nextModules[index].destroy(); + } // disconnect itself from the previous operator + if (this.prevModule) this.prevModule.disconnect(this); + + // mark the object as dead + this.streamParams = null; + } + + /** + * Return a `Promise` that resolve when the module is ready to be consumed. + * Some modules relies on asynchronous APIs at initialization and thus could + * be not ready to be consumed when the graph starts. + * A module should be consider as initialized when all next modules (children) + * are themselves initialized. The event bubbles up from sinks to sources. + * When all its next operators are ready, a source can consider the whole graph + * as ready and then start to produce frames. + * The default implementation resolves when all next operators are resolved + * themselves. + * An operator relying on external async API must override this method to + * resolve only when its dependecy is ready. + * + * @return Promise + * @todo - Handle dynamic connections + */ + + }, { + key: 'initModule', + value: function initModule() { + var nextPromises = this.nextModules.map(function (module) { + return module.initModule(); + }); + + return _promise2.default.all(nextPromises); + } + + /** + * Helper to initialize the stream in standalone mode. + * + * @param {Object} [streamParams={}] - Parameters of the stream. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#resetStream} + */ + + }, { + key: 'initStream', + value: function initStream() { + var streamParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.processStreamParams(streamParams); + this.resetStream(); + } + + /** + * Reset the `frame.data` buffer by setting all its values to 0. + * A source operator should call `processStreamParams` and `resetStream` when + * started, each of these method propagate through the graph automaticaly. + * + * @see {@link module:core.BaseLfo#processStreamParams} + */ + + }, { + key: 'resetStream', + value: function resetStream() { + // buttom up + for (var i = 0, l = this.nextModules.length; i < l; i++) { + this.nextModules[i].resetStream(); + } // no buffer for `scalar` type or sink node + // @note - this should be reviewed + if (this.streamParams.frameType !== 'scalar' && this.frame.data !== null) { + var frameSize = this.streamParams.frameSize; + var data = this.frame.data; + + for (var _i = 0; _i < frameSize; _i++) { + data[_i] = 0; + } + } + } + + /** + * Finalize the stream. A source node should call this method when stopped, + * `finalizeStream` is automatically propagated throught the graph. + * + * @param {Number} endTime - Logical time at which the graph is stopped. + */ + + }, { + key: 'finalizeStream', + value: function finalizeStream(endTime) { + for (var i = 0, l = this.nextModules.length; i < l; i++) { + this.nextModules[i].finalizeStream(endTime); + } + } + + /** + * Initialize or update the operator's `streamParams` according to the + * previous operators `streamParams` values. + * + * When implementing a new operator this method should: + * 1. call `this.prepareStreamParams` with the given `prevStreamParams` + * 2. optionnally change values to `this.streamParams` according to the + * logic performed by the operator. + * 3. optionnally allocate memory for ring buffers, etc. + * 4. call `this.propagateStreamParams` to trigger the method on the next + * operators in the graph. + * + * @param {Object} prevStreamParams - `streamParams` of the previous operator. + * + * @see {@link module:core.BaseLfo#prepareStreamParams} + * @see {@link module:core.BaseLfo#propagateStreamParams} + */ + + }, { + key: 'processStreamParams', + value: function processStreamParams() { + var prevStreamParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.prepareStreamParams(prevStreamParams); + this.propagateStreamParams(); + } + + /** + * Common logic to do at the beginning of the `processStreamParam`, must be + * called at the beginning of any `processStreamParam` implementation. + * + * The method mainly check if the current node implement the interface to + * handle the type of frame propagated by it's parent: + * - to handle a `vector` frame type, the class must implement `processVector` + * - to handle a `signal` frame type, the class must implement `processSignal` + * - in case of a 'scalar' frame type, the class can implement any of the + * following by order of preference: `processScalar`, `processVector`, + * `processSignal`. + * + * @param {Object} prevStreamParams - `streamParams` of the previous operator. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#propagateStreamParams} + */ + + }, { + key: 'prepareStreamParams', + value: function prepareStreamParams() { + var prevStreamParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + (0, _assign2.default)(this.streamParams, prevStreamParams); + var prevFrameType = prevStreamParams.frameType; + + switch (prevFrameType) { + case 'scalar': + if (this.processScalar) this.processFunction = this.processScalar;else if (this.processVector) this.processFunction = this.processVector;else if (this.processSignal) this.processFunction = this.processSignal;else throw new Error(this.constructor.name + ' - no "process" function found'); + break; + case 'vector': + if (!('processVector' in this)) throw new Error(this.constructor.name + ' - "processVector" is not defined'); + + this.processFunction = this.processVector; + break; + case 'signal': + if (!('processSignal' in this)) throw new Error(this.constructor.name + ' - "processSignal" is not defined'); + + this.processFunction = this.processSignal; + break; + default: + // defaults to processFunction + break; + } + } + + /** + * Create the `this.frame.data` buffer and forward the operator's `streamParam` + * to all its next operators, must be called at the end of any + * `processStreamParams` implementation. + * + * @see {@link module:core.BaseLfo#processStreamParams} + * @see {@link module:core.BaseLfo#prepareStreamParams} + */ + + }, { + key: 'propagateStreamParams', + value: function propagateStreamParams() { + this.frame.data = new Float32Array(this.streamParams.frameSize); + + for (var i = 0, l = this.nextModules.length; i < l; i++) { + this.nextModules[i].processStreamParams(this.streamParams); + } + } + + /** + * Define the particular logic the operator applies to the stream. + * According to the frame type of the previous node, the method calls one + * of the following method `processVector`, `processSignal` or `processScalar` + * + * @param {Object} frame - Frame (time, data, and metadata) as given by the + * previous operator. The incomming frame should never be modified by + * the operator. + * + * @see {@link module:core.BaseLfo#prepareFrame} + * @see {@link module:core.BaseLfo#propagateFrame} + * @see {@link module:core.BaseLfo#processStreamParams} + */ + + }, { + key: 'processFrame', + value: function processFrame(frame) { + this.prepareFrame(); + + // frameTime and frameMetadata defaults to identity + this.frame.time = frame.time; + this.frame.metadata = frame.metadata; + + this.processFunction(frame); + this.propagateFrame(); + } + + /** + * Pointer to the method called in `processFrame` according to the + * frame type of the previous operator. Is dynamically assigned in + * `prepareStreamParams`. + * + * @see {@link module:core.BaseLfo#prepareStreamParams} + * @see {@link module:core.BaseLfo#processFrame} + */ + + }, { + key: 'processFunction', + value: function processFunction(frame) { + this.frame = frame; + } + + /** + * Common logic to perform at the beginning of the `processFrame`. + * + * @see {@link module:core.BaseLfo#processFrame} + */ + + }, { + key: 'prepareFrame', + value: function prepareFrame() { + if (this._reinit === true) { + var streamParams = this.prevModule !== null ? this.prevModule.streamParams : {}; + this.initStream(streamParams); + this._reinit = false; + } + } + + /** + * Forward the current `frame` to the next operators, is called at the end of + * `processFrame`. + * + * @see {@link module:core.BaseLfo#processFrame} + */ + + }, { + key: 'propagateFrame', + value: function propagateFrame() { + for (var i = 0, l = this.nextModules.length; i < l; i++) { + this.nextModules[i].processFrame(this.frame); + } + } + }]); + return BaseLfo; +}(); + +exports.default = BaseLfo; + +},{"@ircam/parameters":56,"babel-runtime/core-js/object/assign":60,"babel-runtime/core-js/promise":66,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70}],51:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _promise = require("babel-runtime/core-js/promise"); + +var _promise2 = _interopRequireDefault(_promise); + +var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of"); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require("babel-runtime/helpers/createClass"); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require("babel-runtime/helpers/inherits"); + +var _inherits3 = _interopRequireDefault(_inherits2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Interface added to `LfoCore to implement source + * + * Source have some responsability on graph as they mostly control its whole + * lifecycle. They must implement the start and stop method in order to + * make sure the graph is initialized and set `started` to true. + * A source should never accept and propagate incomming frames until `started` + * is set to `true`. + * + * @name SourceMixin + * @memberof module:core + * @mixin + * + * @example + * class MySource extends SourceMixin(BaseLfo) {} + */ +var SourceMixin = function SourceMixin(superclass) { + return function (_superclass) { + (0, _inherits3.default)(_class, _superclass); + + function _class() { + var _ref; + + (0, _classCallCheck3.default)(this, _class); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var _this = (0, _possibleConstructorReturn3.default)(this, (_ref = _class.__proto__ || (0, _getPrototypeOf2.default)(_class)).call.apply(_ref, [this].concat(args))); + + _this.initialized = false; + _this.initPromise = null; + _this.started = false; + + _this.start = _this.start.bind(_this); + _this.stop = _this.stop.bind(_this); + return _this; + } + + /** + * Initialize the graph by calling `initModule`. When the returned `Promise` + * fulfills, the graph can be considered as initialized and `start` can be + * called safely. If `start` is called whithout explicit `init`, `init` is + * made internally, actual start of the graph is then not garanteed to be + * synchronous. + * + * @memberof module:core.SourceMixin + * @instance + * @name init + * + * @return Promise + * + * @example + * // safe initialization and start + * source.init().then(() => source.start()) + * // safe initialization and start + * source.start(); + */ + + + (0, _createClass3.default)(_class, [{ + key: "init", + value: function init() { + var _this2 = this; + + this.initPromise = this.initModule().then(function () { + _this2.initStream(); // this is synchronous + _this2.initialized = true; + return _promise2.default.resolve(true); + }); + + return this.initPromise; + } + + /** + * Interface method to implement that starts the graph. + * + * The method main purpose is to make sure take verify initialization step and + * set `started` to `true` when done. + * Should behave synchronously when called inside `init().then()` and async + * if called without init step. + * + * @memberof module:core.SourceMixin + * @instance + * @name start + * + * @example + * // basic `start` implementation + * start() { + * if (this.initialized === false) { + * if (this.initPromise === null) // init has not yet been called + * this.initPromise = this.init(); + * + * this.initPromise.then(this.start); + * return; + * } + * + * this.started = true; + * } + */ + + }, { + key: "start", + value: function start() {} + + /** + * Interface method to implement that stops the graph. + * + * @memberof module:core.SourceMixin + * @instance + * @name stop + * + * @example + * // basic `stop` implementation + * stop() { + * this.started = false; + * } + */ + + }, { + key: "stop", + value: function stop() {} + + /** + * The implementation should never allow incomming frames + * if `this.started` is not `true`. + * + * @memberof module:core.SourceMixin + * @instance + * @name processFrame + * + * @param {Object} frame + * + * @example + * // basic `processFrame` implementation + * processFrame(frame) { + * if (this.started === true) { + * this.prepareFrame(); + * this.processFunction(frame); + * this.propagateFrame(); + * } + * } + */ + + }, { + key: "processFrame", + value: function processFrame(frame) {} + }]); + return _class; + }(superclass); +}; + +exports.default = SourceMixin; + +},{"babel-runtime/core-js/object/get-prototype-of":64,"babel-runtime/core-js/promise":66,"babel-runtime/helpers/classCallCheck":69,"babel-runtime/helpers/createClass":70,"babel-runtime/helpers/inherits":73,"babel-runtime/helpers/possibleConstructorReturn":74}],52:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _BaseLfo = require('./BaseLfo'); + +Object.defineProperty(exports, 'BaseLfo', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_BaseLfo).default; + } +}); + +var _SourceMixin = require('./SourceMixin'); + +Object.defineProperty(exports, 'SourceMixin', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_SourceMixin).default; + } +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var version = exports.version = '1.1.1'; + +},{"./BaseLfo":50,"./SourceMixin":51}],53:[function(require,module,exports){ +'use strict'; + +var _client = require('waves-lfo/client'); + +var lfo = _interopRequireWildcard(_client); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var frameSize = 5; +var dt = 0.02; + +var eventIn = new lfo.source.EventIn({ + frameSize: frameSize, + frameRate: 1 / dt, + frameType: 'vector' +}); + +var barChart = new lfo.sink.BarChartDisplay({ + canvas: '#bar-chart' +}); + +eventIn.connect(barChart); +eventIn.start(); + +var data = [0, 0.2, 0.4, 0.6, 0.8]; + +(function generateData() { + for (var i = 0; i < frameSize; i++) { + data[i] = (data[i] + 0.001) % 1; + }eventIn.process(null, data); + + setTimeout(generateData, dt * 1000); +})(); + +},{"waves-lfo/client":1}],54:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],55:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var min = Math.min; +var max = Math.max; + +function clip(value) { + var lower = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -Infinity; + var upper = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : +Infinity; + + return max(lower, min(upper, value)); +} + +/** + * Dictionnary of the available types. Each key correspond to the type of the + * implemented param while the corresponding object value should the + * {@link `paramDefinition`} of the defined type. + * + * typedef {Object} paramTemplates + * @type {Object} + */ + +/** + * Definition of a parameter. The definition should at least contain the entries + * `type` and `default`. Every parameter can also accept optionnal configuration + * entries `constant` and `metas`. + * Available definitions are: + * - {@link booleanDefinition} + * - {@link integerDefinition} + * - {@link floatDefinition} + * - {@link stringDefinition} + * - {@link enumDefinition} + * + * typedef {Object} paramDefinition + * @property {String} type - Type of the parameter. + * @property {Mixed} default - Default value of the parameter if no + * initialization value is provided. + * @property {Boolean} [constant=false] - Define if the parameter can be change + * after its initialization. + * @property {Object} [metas=null] - Any user defined data associated to the + * parameter that couls be usefull in the application. + */ + +exports.default = { + /** + * @typedef {Object} booleanDefinition + * @property {String} [type='boolean'] - Define a boolean parameter. + * @property {Boolean} default - Default value of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + boolean: { + definitionTemplate: ['default'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + if (typeof value !== 'boolean') throw new Error('Invalid value for boolean param "' + name + '": ' + value); + + return value; + } + }, + + /** + * @typedef {Object} integerDefinition + * @property {String} [type='integer'] - Define a boolean parameter. + * @property {Mixed} default - Default value of the parameter. + * @property {Number} [min=-Infinity] - Minimum value of the parameter. + * @property {Number} [max=+Infinity] - Maximum value of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + integer: { + definitionTemplate: ['default'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + if (!(typeof value === 'number' && Math.floor(value) === value)) throw new Error('Invalid value for integer param "' + name + '": ' + value); + + return clip(value, definition.min, definition.max); + } + }, + + /** + * @typedef {Object} floatDefinition + * @property {String} [type='float'] - Define a boolean parameter. + * @property {Mixed} default - Default value of the parameter. + * @property {Number} [min=-Infinity] - Minimum value of the parameter. + * @property {Number} [max=+Infinity] - Maximum value of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + float: { + definitionTemplate: ['default'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + if (typeof value !== 'number' || value !== value) // reject NaN + throw new Error('Invalid value for float param "' + name + '": ' + value); + + return clip(value, definition.min, definition.max); + } + }, + + /** + * @typedef {Object} stringDefinition + * @property {String} [type='string'] - Define a boolean parameter. + * @property {Mixed} default - Default value of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + string: { + definitionTemplate: ['default'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + if (typeof value !== 'string') throw new Error('Invalid value for string param "' + name + '": ' + value); + + return value; + } + }, + + /** + * @typedef {Object} enumDefinition + * @property {String} [type='enum'] - Define a boolean parameter. + * @property {Mixed} default - Default value of the parameter. + * @property {Array} list - Possible values of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + enum: { + definitionTemplate: ['default', 'list'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + if (definition.list.indexOf(value) === -1) throw new Error('Invalid value for enum param "' + name + '": ' + value); + + return value; + } + }, + + /** + * @typedef {Object} anyDefinition + * @property {String} [type='enum'] - Define a parameter of any type. + * @property {Mixed} default - Default value of the parameter. + * @property {Boolean} [constant=false] - Define if the parameter is constant. + * @property {Boolean} [nullable=false] - Define if the parameter is nullable. + * @property {Object} [metas={}] - Optionnal metadata of the parameter. + */ + any: { + definitionTemplate: ['default'], + typeCheckFunction: function typeCheckFunction(value, definition, name) { + // no check as it can have any type... + return value; + } + } +}; + +},{}],56:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _paramTemplates = require('./paramTemplates'); + +var _paramTemplates2 = _interopRequireDefault(_paramTemplates); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** + * Generic class for typed parameters. + * + * @param {String} name - Name of the parameter. + * @param {Array} definitionTemplate - List of mandatory keys in the param + * definition. + * @param {Function} typeCheckFunction - Function to be used in order to check + * the value against the param definition. + * @param {Object} definition - Definition of the parameter. + * @param {Mixed} value - Value of the parameter. + * @private + */ +var Param = function () { + function Param(name, definitionTemplate, typeCheckFunction, definition, value) { + _classCallCheck(this, Param); + + definitionTemplate.forEach(function (key) { + if (definition.hasOwnProperty(key) === false) throw new Error('Invalid definition for param "' + name + '", ' + key + ' is not defined'); + }); + + this.name = name; + this.type = definition.type; + this.definition = definition; + + if (this.definition.nullable === true && value === null) this.value = null;else this.value = typeCheckFunction(value, definition, name); + this._typeCheckFunction = typeCheckFunction; + } + + /** + * Returns the current value. + * @return {Mixed} + */ + + + _createClass(Param, [{ + key: 'getValue', + value: function getValue() { + return this.value; + } + + /** + * Update the current value. + * @param {Mixed} value - New value of the parameter. + * @return {Boolean} - `true` if the param has been updated, false otherwise + * (e.g. if the parameter already had this value). + */ + + }, { + key: 'setValue', + value: function setValue(value) { + if (this.definition.constant === true) throw new Error('Invalid assignement to constant param "' + this.name + '"'); + + if (!(this.definition.nullable === true && value === null)) value = this._typeCheckFunction(value, this.definition, this.name); + + if (this.value !== value) { + this.value = value; + return true; + } + + return false; + } + }]); + + return Param; +}(); + +/** + * Bag of parameters. Main interface of the library + */ + + +var ParameterBag = function () { + function ParameterBag(params, definitions) { + _classCallCheck(this, ParameterBag); + + /** + * List of parameters. + * + * @type {Object} + * @name _params + * @memberof ParameterBag + * @instance + * @private + */ + this._params = params; + + /** + * List of definitions with init values. + * + * @type {Object} + * @name _definitions + * @memberof ParameterBag + * @instance + * @private + */ + this._definitions = definitions; + + /** + * List of global listeners. + * + * @type {Set} + * @name _globalListeners + * @memberof ParameterBag + * @instance + * @private + */ + this._globalListeners = new Set(); + + /** + * List of params listeners. + * + * @type {Object} + * @name _paramsListeners + * @memberof ParameterBag + * @instance + * @private + */ + this._paramsListeners = {}; + + // initialize empty Set for each param + for (var name in params) { + this._paramsListeners[name] = new Set(); + } + } + + /** + * Return the given definitions along with the initialization values. + * + * @return {Object} + */ + + + _createClass(ParameterBag, [{ + key: 'getDefinitions', + value: function getDefinitions() { + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (name !== null) return this._definitions[name];else return this._definitions; + } + + /** + * Return the value of the given parameter. + * + * @param {String} name - Name of the parameter. + * @return {Mixed} - Value of the parameter. + */ + + }, { + key: 'get', + value: function get(name) { + if (!this._params[name]) throw new Error('Cannot read property value of undefined parameter "' + name + '"'); + + return this._params[name].value; + } + + /** + * Set the value of a parameter. If the value of the parameter is updated + * (aka if previous value is different from new value) all registered + * callbacks are registered. + * + * @param {String} name - Name of the parameter. + * @param {Mixed} value - Value of the parameter. + * @return {Mixed} - New value of the parameter. + */ + + }, { + key: 'set', + value: function set(name, value) { + var param = this._params[name]; + var updated = param.setValue(value); + value = param.getValue(); + + if (updated) { + var metas = param.definition.metas; + // trigger global listeners + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = this._globalListeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var listener = _step.value; + + listener(name, value, metas); + } // trigger param listeners + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = this._paramsListeners[name][Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var _listener = _step2.value; + + _listener(value, metas); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } + + return value; + } + + /** + * Define if the `name` parameter exists or not. + * + * @param {String} name - Name of the parameter. + * @return {Boolean} + */ + + }, { + key: 'has', + value: function has(name) { + return this._params[name] ? true : false; + } + + /** + * Reset a parameter to its init value. Reset all parameters if no argument. + * + * @param {String} [name=null] - Name of the parameter to reset. + */ + + }, { + key: 'reset', + value: function reset() { + var _this = this; + + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (name !== null) this.set(name, param.definition.initValue);else Object.keys(this._params).forEach(function (name) { + return _this.reset(name); + }); + } + + /** + * @callback ParameterBag~listenerCallback + * @param {String} name - Parameter name. + * @param {Mixed} value - Updated value of the parameter. + * @param {Object} [meta=] - Given meta data of the parameter. + */ + + /** + * Add listener to all param updates. + * + * @param {ParameterBag~listenerCallack} callback - Listener to register. + */ + + }, { + key: 'addListener', + value: function addListener(callback) { + this._globalListeners.add(callback); + } + + /** + * Remove listener from all param changes. + * + * @param {ParameterBag~listenerCallack} callback - Listener to remove. If + * `null` remove all listeners. + */ + + }, { + key: 'removeListener', + value: function removeListener() { + var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (callback === null) this._globalListeners.clear();else this._globalListeners.delete(callback); + } + + /** + * @callback ParameterBag~paramListenerCallack + * @param {Mixed} value - Updated value of the parameter. + * @param {Object} [meta=] - Given meta data of the parameter. + */ + + /** + * Add listener to a given param updates. + * + * @param {String} name - Parameter name. + * @param {ParameterBag~paramListenerCallack} callback - Function to apply + * when the value of the parameter changes. + * @param {Boolean} [trigger=false] - Execute the callback immediately with + * current parameter value. + */ + + }, { + key: 'addParamListener', + value: function addParamListener(name, callback) { + var trigger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + this._paramsListeners[name].add(callback); + + if (trigger) { + var _param = this._params[name]; + var value = _param.getValue(); + var metas = _param.definition.metas; + callback(value, metas); + } + } + + /** + * Remove listener from a given param updates. + * + * @param {String} name - Parameter name. + * @param {ParameterBag~paramListenerCallack} callback - Listener to remove. + * If `null` remove all listeners. + */ + + }, { + key: 'removeParamListener', + value: function removeParamListener(name) { + var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (callback === null) this._paramsListeners[name].clear();else this._paramsListeners[name].delete(callback); + } + }]); + + return ParameterBag; +}(); + +/** + * Factory for the `ParameterBag` class. + * + * @param {Object} definitions - Object describing the + * parameters. + * @param {Object} values - Initialization values for the + * parameters. + * @return {ParameterBag} + */ + + +function parameters(definitions) { + var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var params = {}; + + for (var name in values) { + if (definitions.hasOwnProperty(name) === false) throw new Error('Unknown param "' + name + '"'); + } + + for (var _name in definitions) { + if (params.hasOwnProperty(_name) === true) throw new Error('Parameter "' + _name + '" already defined'); + + var definition = definitions[_name]; + + if (!_paramTemplates2.default[definition.type]) throw new Error('Unknown param type "' + definition.type + '"'); + + var _paramTemplates$defin = _paramTemplates2.default[definition.type], + definitionTemplate = _paramTemplates$defin.definitionTemplate, + typeCheckFunction = _paramTemplates$defin.typeCheckFunction; + + + var value = void 0; + + if (values.hasOwnProperty(_name) === true) value = values[_name];else value = definition.default; + + // store init value in definition + definition.initValue = value; + + if (!typeCheckFunction || !definitionTemplate) throw new Error('Invalid param type definition "' + definition.type + '"'); + + params[_name] = new Param(_name, definitionTemplate, typeCheckFunction, definition, value); + } + + return new ParameterBag(params, definitions); +} + +/** + * Register a new type for the `parameters` factory. + * @param {String} typeName - Value that will be available as the `type` of a + * param definition. + * @param {parameterDefinition} parameterDefinition - Object describing the + * parameter. + */ +parameters.defineType = function (typeName, parameterDefinition) { + _paramTemplates2.default[typeName] = parameterDefinition; +}; + +exports.default = parameters; + +},{"./paramTemplates":55}],57:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/json/stringify"), __esModule: true }; +},{"core-js/library/fn/json/stringify":76}],58:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/math/log10"), __esModule: true }; +},{"core-js/library/fn/math/log10":77}],59:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/number/is-finite"), __esModule: true }; +},{"core-js/library/fn/number/is-finite":78}],60:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/assign"), __esModule: true }; +},{"core-js/library/fn/object/assign":79}],61:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/create"), __esModule: true }; +},{"core-js/library/fn/object/create":80}],62:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/define-property"), __esModule: true }; +},{"core-js/library/fn/object/define-property":81}],63:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/get-own-property-descriptor"), __esModule: true }; +},{"core-js/library/fn/object/get-own-property-descriptor":82}],64:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/get-prototype-of"), __esModule: true }; +},{"core-js/library/fn/object/get-prototype-of":83}],65:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/set-prototype-of"), __esModule: true }; +},{"core-js/library/fn/object/set-prototype-of":84}],66:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/promise"), __esModule: true }; +},{"core-js/library/fn/promise":85}],67:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol"), __esModule: true }; +},{"core-js/library/fn/symbol":86}],68:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol/iterator"), __esModule: true }; +},{"core-js/library/fn/symbol/iterator":87}],69:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; +},{}],70:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _defineProperty = require("../core-js/object/define-property"); + +var _defineProperty2 = _interopRequireDefault(_defineProperty); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + (0, _defineProperty2.default)(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); +},{"../core-js/object/define-property":62}],71:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _defineProperty = require("../core-js/object/define-property"); + +var _defineProperty2 = _interopRequireDefault(_defineProperty); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (obj, key, value) { + if (key in obj) { + (0, _defineProperty2.default)(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +}; +},{"../core-js/object/define-property":62}],72:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getPrototypeOf = require("../core-js/object/get-prototype-of"); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _getOwnPropertyDescriptor = require("../core-js/object/get-own-property-descriptor"); + +var _getOwnPropertyDescriptor2 = _interopRequireDefault(_getOwnPropertyDescriptor); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = (0, _getOwnPropertyDescriptor2.default)(object, property); + + if (desc === undefined) { + var parent = (0, _getPrototypeOf2.default)(object); + + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; + + if (getter === undefined) { + return undefined; + } + + return getter.call(receiver); + } +}; +},{"../core-js/object/get-own-property-descriptor":63,"../core-js/object/get-prototype-of":64}],73:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _setPrototypeOf = require("../core-js/object/set-prototype-of"); + +var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf); + +var _create = require("../core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _typeof2 = require("../helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass))); + } + + subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass; +}; +},{"../core-js/object/create":61,"../core-js/object/set-prototype-of":65,"../helpers/typeof":75}],74:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("../helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self; +}; +},{"../helpers/typeof":75}],75:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _iterator = require("../core-js/symbol/iterator"); + +var _iterator2 = _interopRequireDefault(_iterator); + +var _symbol = require("../core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) { + return typeof obj === "undefined" ? "undefined" : _typeof(obj); +} : function (obj) { + return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj); +}; +},{"../core-js/symbol":67,"../core-js/symbol/iterator":68}],76:[function(require,module,exports){ +var core = require('../../modules/_core'); +var $JSON = core.JSON || (core.JSON = { stringify: JSON.stringify }); +module.exports = function stringify(it) { // eslint-disable-line no-unused-vars + return $JSON.stringify.apply($JSON, arguments); +}; + +},{"../../modules/_core":95}],77:[function(require,module,exports){ +require('../../modules/es6.math.log10'); +module.exports = require('../../modules/_core').Math.log10; + +},{"../../modules/_core":95,"../../modules/es6.math.log10":163}],78:[function(require,module,exports){ +require('../../modules/es6.number.is-finite'); +module.exports = require('../../modules/_core').Number.isFinite; + +},{"../../modules/_core":95,"../../modules/es6.number.is-finite":164}],79:[function(require,module,exports){ +require('../../modules/es6.object.assign'); +module.exports = require('../../modules/_core').Object.assign; + +},{"../../modules/_core":95,"../../modules/es6.object.assign":165}],80:[function(require,module,exports){ +require('../../modules/es6.object.create'); +var $Object = require('../../modules/_core').Object; +module.exports = function create(P, D) { + return $Object.create(P, D); +}; + +},{"../../modules/_core":95,"../../modules/es6.object.create":166}],81:[function(require,module,exports){ +require('../../modules/es6.object.define-property'); +var $Object = require('../../modules/_core').Object; +module.exports = function defineProperty(it, key, desc) { + return $Object.defineProperty(it, key, desc); +}; + +},{"../../modules/_core":95,"../../modules/es6.object.define-property":167}],82:[function(require,module,exports){ +require('../../modules/es6.object.get-own-property-descriptor'); +var $Object = require('../../modules/_core').Object; +module.exports = function getOwnPropertyDescriptor(it, key) { + return $Object.getOwnPropertyDescriptor(it, key); +}; + +},{"../../modules/_core":95,"../../modules/es6.object.get-own-property-descriptor":168}],83:[function(require,module,exports){ +require('../../modules/es6.object.get-prototype-of'); +module.exports = require('../../modules/_core').Object.getPrototypeOf; + +},{"../../modules/_core":95,"../../modules/es6.object.get-prototype-of":169}],84:[function(require,module,exports){ +require('../../modules/es6.object.set-prototype-of'); +module.exports = require('../../modules/_core').Object.setPrototypeOf; + +},{"../../modules/_core":95,"../../modules/es6.object.set-prototype-of":170}],85:[function(require,module,exports){ +require('../modules/es6.object.to-string'); +require('../modules/es6.string.iterator'); +require('../modules/web.dom.iterable'); +require('../modules/es6.promise'); +require('../modules/es7.promise.finally'); +require('../modules/es7.promise.try'); +module.exports = require('../modules/_core').Promise; + +},{"../modules/_core":95,"../modules/es6.object.to-string":171,"../modules/es6.promise":172,"../modules/es6.string.iterator":173,"../modules/es7.promise.finally":175,"../modules/es7.promise.try":176,"../modules/web.dom.iterable":179}],86:[function(require,module,exports){ +require('../../modules/es6.symbol'); +require('../../modules/es6.object.to-string'); +require('../../modules/es7.symbol.async-iterator'); +require('../../modules/es7.symbol.observable'); +module.exports = require('../../modules/_core').Symbol; + +},{"../../modules/_core":95,"../../modules/es6.object.to-string":171,"../../modules/es6.symbol":174,"../../modules/es7.symbol.async-iterator":177,"../../modules/es7.symbol.observable":178}],87:[function(require,module,exports){ +require('../../modules/es6.string.iterator'); +require('../../modules/web.dom.iterable'); +module.exports = require('../../modules/_wks-ext').f('iterator'); + +},{"../../modules/_wks-ext":159,"../../modules/es6.string.iterator":173,"../../modules/web.dom.iterable":179}],88:[function(require,module,exports){ +module.exports = function (it) { + if (typeof it != 'function') throw TypeError(it + ' is not a function!'); + return it; +}; + +},{}],89:[function(require,module,exports){ +module.exports = function () { /* empty */ }; + +},{}],90:[function(require,module,exports){ +module.exports = function (it, Constructor, name, forbiddenField) { + if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + +},{}],91:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function (it) { + if (!isObject(it)) throw TypeError(it + ' is not an object!'); + return it; +}; + +},{"./_is-object":114}],92:[function(require,module,exports){ +// false -> Array#indexOf +// true -> Array#includes +var toIObject = require('./_to-iobject'); +var toLength = require('./_to-length'); +var toAbsoluteIndex = require('./_to-absolute-index'); +module.exports = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; + +},{"./_to-absolute-index":151,"./_to-iobject":153,"./_to-length":154}],93:[function(require,module,exports){ +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof = require('./_cof'); +var TAG = require('./_wks')('toStringTag'); +// ES3 wrong here +var ARG = cof(function () { return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function (it, key) { + try { + return it[key]; + } catch (e) { /* empty */ } +}; + +module.exports = function (it) { + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; + +},{"./_cof":94,"./_wks":160}],94:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function (it) { + return toString.call(it).slice(8, -1); +}; + +},{}],95:[function(require,module,exports){ +var core = module.exports = { version: '2.5.2' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + +},{}],96:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; +}; + +},{"./_a-function":88}],97:[function(require,module,exports){ +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; +}; + +},{}],98:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; +}); + +},{"./_fails":103}],99:[function(require,module,exports){ +var isObject = require('./_is-object'); +var document = require('./_global').document; +// typeof document.createElement is 'object' in old IE +var is = isObject(document) && isObject(document.createElement); +module.exports = function (it) { + return is ? document.createElement(it) : {}; +}; + +},{"./_global":105,"./_is-object":114}],100:[function(require,module,exports){ +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + +},{}],101:[function(require,module,exports){ +// all enumerable object keys, includes symbols +var getKeys = require('./_object-keys'); +var gOPS = require('./_object-gops'); +var pIE = require('./_object-pie'); +module.exports = function (it) { + var result = getKeys(it); + var getSymbols = gOPS.f; + if (getSymbols) { + var symbols = getSymbols(it); + var isEnum = pIE.f; + var i = 0; + var key; + while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key); + } return result; +}; + +},{"./_object-gops":132,"./_object-keys":135,"./_object-pie":136}],102:[function(require,module,exports){ +var global = require('./_global'); +var core = require('./_core'); +var ctx = require('./_ctx'); +var hide = require('./_hide'); +var PROTOTYPE = 'prototype'; + +var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var IS_WRAP = type & $export.W; + var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); + var expProto = exports[PROTOTYPE]; + var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]; + var key, own, out; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if (own && key in exports) continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function (C) { + var F = function (a, b, c) { + if (this instanceof C) { + switch (arguments.length) { + case 0: return new C(); + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if (IS_PROTO) { + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; + +},{"./_core":95,"./_ctx":96,"./_global":105,"./_hide":107}],103:[function(require,module,exports){ +module.exports = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; + } +}; + +},{}],104:[function(require,module,exports){ +var ctx = require('./_ctx'); +var call = require('./_iter-call'); +var isArrayIter = require('./_is-array-iter'); +var anObject = require('./_an-object'); +var toLength = require('./_to-length'); +var getIterFn = require('./core.get-iterator-method'); +var BREAK = {}; +var RETURN = {}; +var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { + var iterFn = ITERATOR ? function () { return iterable; } : getIterFn(iterable); + var f = ctx(fn, that, entries ? 2 : 1); + var index = 0; + var length, step, iterator, result; + if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) { + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if (result === BREAK || result === RETURN) return result; + } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { + result = call(iterator, f, step.value, entries); + if (result === BREAK || result === RETURN) return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; + +},{"./_an-object":91,"./_ctx":96,"./_is-array-iter":112,"./_iter-call":115,"./_to-length":154,"./core.get-iterator-method":161}],105:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + +},{}],106:[function(require,module,exports){ +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function (it, key) { + return hasOwnProperty.call(it, key); +}; + +},{}],107:[function(require,module,exports){ +var dP = require('./_object-dp'); +var createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function (object, key, value) { + return dP.f(object, key, createDesc(1, value)); +} : function (object, key, value) { + object[key] = value; + return object; +}; + +},{"./_descriptors":98,"./_object-dp":127,"./_property-desc":140}],108:[function(require,module,exports){ +var document = require('./_global').document; +module.exports = document && document.documentElement; + +},{"./_global":105}],109:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function () { + return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7; +}); + +},{"./_descriptors":98,"./_dom-create":99,"./_fails":103}],110:[function(require,module,exports){ +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function (fn, args, that) { + var un = that === undefined; + switch (args.length) { + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; + +},{}],111:[function(require,module,exports){ +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = require('./_cof'); +// eslint-disable-next-line no-prototype-builtins +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return cof(it) == 'String' ? it.split('') : Object(it); +}; + +},{"./_cof":94}],112:[function(require,module,exports){ +// check on default Array iterator +var Iterators = require('./_iterators'); +var ITERATOR = require('./_wks')('iterator'); +var ArrayProto = Array.prototype; + +module.exports = function (it) { + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); +}; + +},{"./_iterators":120,"./_wks":160}],113:[function(require,module,exports){ +// 7.2.2 IsArray(argument) +var cof = require('./_cof'); +module.exports = Array.isArray || function isArray(arg) { + return cof(arg) == 'Array'; +}; + +},{"./_cof":94}],114:[function(require,module,exports){ +module.exports = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + +},{}],115:[function(require,module,exports){ +// call something on iterator step with safe closing on error +var anObject = require('./_an-object'); +module.exports = function (iterator, fn, value, entries) { + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch (e) { + var ret = iterator['return']; + if (ret !== undefined) anObject(ret.call(iterator)); + throw e; + } +}; + +},{"./_an-object":91}],116:[function(require,module,exports){ +'use strict'; +var create = require('./_object-create'); +var descriptor = require('./_property-desc'); +var setToStringTag = require('./_set-to-string-tag'); +var IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +require('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; }); + +module.exports = function (Constructor, NAME, next) { + Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); + setToStringTag(Constructor, NAME + ' Iterator'); +}; + +},{"./_hide":107,"./_object-create":126,"./_property-desc":140,"./_set-to-string-tag":145,"./_wks":160}],117:[function(require,module,exports){ +'use strict'; +var LIBRARY = require('./_library'); +var $export = require('./_export'); +var redefine = require('./_redefine'); +var hide = require('./_hide'); +var has = require('./_has'); +var Iterators = require('./_iterators'); +var $iterCreate = require('./_iter-create'); +var setToStringTag = require('./_set-to-string-tag'); +var getPrototypeOf = require('./_object-gpo'); +var ITERATOR = require('./_wks')('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; + +var returnThis = function () { return this; }; + +module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + $iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; + +},{"./_export":102,"./_has":106,"./_hide":107,"./_iter-create":116,"./_iterators":120,"./_library":121,"./_object-gpo":133,"./_redefine":142,"./_set-to-string-tag":145,"./_wks":160}],118:[function(require,module,exports){ +var ITERATOR = require('./_wks')('iterator'); +var SAFE_CLOSING = false; + +try { + var riter = [7][ITERATOR](); + riter['return'] = function () { SAFE_CLOSING = true; }; + // eslint-disable-next-line no-throw-literal + Array.from(riter, function () { throw 2; }); +} catch (e) { /* empty */ } + +module.exports = function (exec, skipClosing) { + if (!skipClosing && !SAFE_CLOSING) return false; + var safe = false; + try { + var arr = [7]; + var iter = arr[ITERATOR](); + iter.next = function () { return { done: safe = true }; }; + arr[ITERATOR] = function () { return iter; }; + exec(arr); + } catch (e) { /* empty */ } + return safe; +}; + +},{"./_wks":160}],119:[function(require,module,exports){ +module.exports = function (done, value) { + return { value: value, done: !!done }; +}; + +},{}],120:[function(require,module,exports){ +module.exports = {}; + +},{}],121:[function(require,module,exports){ +module.exports = true; + +},{}],122:[function(require,module,exports){ +var META = require('./_uid')('meta'); +var isObject = require('./_is-object'); +var has = require('./_has'); +var setDesc = require('./_object-dp').f; +var id = 0; +var isExtensible = Object.isExtensible || function () { + return true; +}; +var FREEZE = !require('./_fails')(function () { + return isExtensible(Object.preventExtensions({})); +}); +var setMeta = function (it) { + setDesc(it, META, { value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + } }); +}; +var fastKey = function (it, create) { + // return primitive with prefix + if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if (!has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return 'F'; + // not necessary to add metadata + if (!create) return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; +}; +var getWeak = function (it, create) { + if (!has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return true; + // not necessary to add metadata + if (!create) return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; +}; +// add metadata on freeze-family methods calling +var onFreeze = function (it) { + if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it); + return it; +}; +var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze +}; + +},{"./_fails":103,"./_has":106,"./_is-object":114,"./_object-dp":127,"./_uid":157}],123:[function(require,module,exports){ +var global = require('./_global'); +var macrotask = require('./_task').set; +var Observer = global.MutationObserver || global.WebKitMutationObserver; +var process = global.process; +var Promise = global.Promise; +var isNode = require('./_cof')(process) == 'process'; + +module.exports = function () { + var head, last, notify; + + var flush = function () { + var parent, fn; + if (isNode && (parent = process.domain)) parent.exit(); + while (head) { + fn = head.fn; + head = head.next; + try { + fn(); + } catch (e) { + if (head) notify(); + else last = undefined; + throw e; + } + } last = undefined; + if (parent) parent.enter(); + }; + + // Node.js + if (isNode) { + notify = function () { + process.nextTick(flush); + }; + // browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339 + } else if (Observer && !(global.navigator && global.navigator.standalone)) { + var toggle = true; + var node = document.createTextNode(''); + new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new + notify = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (Promise && Promise.resolve) { + var promise = Promise.resolve(); + notify = function () { + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function () { + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global, flush); + }; + } + + return function (fn) { + var task = { fn: fn, next: undefined }; + if (last) last.next = task; + if (!head) { + head = task; + notify(); + } last = task; + }; +}; + +},{"./_cof":94,"./_global":105,"./_task":150}],124:[function(require,module,exports){ +'use strict'; +// 25.4.1.5 NewPromiseCapability(C) +var aFunction = require('./_a-function'); + +function PromiseCapability(C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction(resolve); + this.reject = aFunction(reject); +} + +module.exports.f = function (C) { + return new PromiseCapability(C); +}; + +},{"./_a-function":88}],125:[function(require,module,exports){ +'use strict'; +// 19.1.2.1 Object.assign(target, source, ...) +var getKeys = require('./_object-keys'); +var gOPS = require('./_object-gops'); +var pIE = require('./_object-pie'); +var toObject = require('./_to-object'); +var IObject = require('./_iobject'); +var $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +module.exports = !$assign || require('./_fails')(function () { + var A = {}; + var B = {}; + // eslint-disable-next-line no-undef + var S = Symbol(); + var K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function (k) { B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source) { // eslint-disable-line no-unused-vars + var T = toObject(target); + var aLen = arguments.length; + var index = 1; + var getSymbols = gOPS.f; + var isEnum = pIE.f; + while (aLen > index) { + var S = IObject(arguments[index++]); + var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; + } return T; +} : $assign; + +},{"./_fails":103,"./_iobject":111,"./_object-gops":132,"./_object-keys":135,"./_object-pie":136,"./_to-object":155}],126:[function(require,module,exports){ +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = require('./_an-object'); +var dPs = require('./_object-dps'); +var enumBugKeys = require('./_enum-bug-keys'); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); +var Empty = function () { /* empty */ }; +var PROTOTYPE = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = require('./_dom-create')('iframe'); + var i = enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + require('./_html').appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); +}; + +module.exports = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE] = anObject(O); + result = new Empty(); + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); +}; + +},{"./_an-object":91,"./_dom-create":99,"./_enum-bug-keys":100,"./_html":108,"./_object-dps":128,"./_shared-key":146}],127:[function(require,module,exports){ +var anObject = require('./_an-object'); +var IE8_DOM_DEFINE = require('./_ie8-dom-define'); +var toPrimitive = require('./_to-primitive'); +var dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (IE8_DOM_DEFINE) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; +}; + +},{"./_an-object":91,"./_descriptors":98,"./_ie8-dom-define":109,"./_to-primitive":156}],128:[function(require,module,exports){ +var dP = require('./_object-dp'); +var anObject = require('./_an-object'); +var getKeys = require('./_object-keys'); + +module.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = getKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) dP.f(O, P = keys[i++], Properties[P]); + return O; +}; + +},{"./_an-object":91,"./_descriptors":98,"./_object-dp":127,"./_object-keys":135}],129:[function(require,module,exports){ +var pIE = require('./_object-pie'); +var createDesc = require('./_property-desc'); +var toIObject = require('./_to-iobject'); +var toPrimitive = require('./_to-primitive'); +var has = require('./_has'); +var IE8_DOM_DEFINE = require('./_ie8-dom-define'); +var gOPD = Object.getOwnPropertyDescriptor; + +exports.f = require('./_descriptors') ? gOPD : function getOwnPropertyDescriptor(O, P) { + O = toIObject(O); + P = toPrimitive(P, true); + if (IE8_DOM_DEFINE) try { + return gOPD(O, P); + } catch (e) { /* empty */ } + if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]); +}; + +},{"./_descriptors":98,"./_has":106,"./_ie8-dom-define":109,"./_object-pie":136,"./_property-desc":140,"./_to-iobject":153,"./_to-primitive":156}],130:[function(require,module,exports){ +// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window +var toIObject = require('./_to-iobject'); +var gOPN = require('./_object-gopn').f; +var toString = {}.toString; + +var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames + ? Object.getOwnPropertyNames(window) : []; + +var getWindowNames = function (it) { + try { + return gOPN(it); + } catch (e) { + return windowNames.slice(); + } +}; + +module.exports.f = function getOwnPropertyNames(it) { + return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it)); +}; + +},{"./_object-gopn":131,"./_to-iobject":153}],131:[function(require,module,exports){ +// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) +var $keys = require('./_object-keys-internal'); +var hiddenKeys = require('./_enum-bug-keys').concat('length', 'prototype'); + +exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return $keys(O, hiddenKeys); +}; + +},{"./_enum-bug-keys":100,"./_object-keys-internal":134}],132:[function(require,module,exports){ +exports.f = Object.getOwnPropertySymbols; + +},{}],133:[function(require,module,exports){ +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has = require('./_has'); +var toObject = require('./_to-object'); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); +var ObjectProto = Object.prototype; + +module.exports = Object.getPrototypeOf || function (O) { + O = toObject(O); + if (has(O, IE_PROTO)) return O[IE_PROTO]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + +},{"./_has":106,"./_shared-key":146,"./_to-object":155}],134:[function(require,module,exports){ +var has = require('./_has'); +var toIObject = require('./_to-iobject'); +var arrayIndexOf = require('./_array-includes')(false); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); + +module.exports = function (object, names) { + var O = toIObject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; +}; + +},{"./_array-includes":92,"./_has":106,"./_shared-key":146,"./_to-iobject":153}],135:[function(require,module,exports){ +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = require('./_object-keys-internal'); +var enumBugKeys = require('./_enum-bug-keys'); + +module.exports = Object.keys || function keys(O) { + return $keys(O, enumBugKeys); +}; + +},{"./_enum-bug-keys":100,"./_object-keys-internal":134}],136:[function(require,module,exports){ +exports.f = {}.propertyIsEnumerable; + +},{}],137:[function(require,module,exports){ +// most Object methods by ES6 should accept primitives +var $export = require('./_export'); +var core = require('./_core'); +var fails = require('./_fails'); +module.exports = function (KEY, exec) { + var fn = (core.Object || {})[KEY] || Object[KEY]; + var exp = {}; + exp[KEY] = exec(fn); + $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp); +}; + +},{"./_core":95,"./_export":102,"./_fails":103}],138:[function(require,module,exports){ +module.exports = function (exec) { + try { + return { e: false, v: exec() }; + } catch (e) { + return { e: true, v: e }; + } +}; + +},{}],139:[function(require,module,exports){ +var anObject = require('./_an-object'); +var isObject = require('./_is-object'); +var newPromiseCapability = require('./_new-promise-capability'); + +module.exports = function (C, x) { + anObject(C); + if (isObject(x) && x.constructor === C) return x; + var promiseCapability = newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; +}; + +},{"./_an-object":91,"./_is-object":114,"./_new-promise-capability":124}],140:[function(require,module,exports){ +module.exports = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; +}; + +},{}],141:[function(require,module,exports){ +var hide = require('./_hide'); +module.exports = function (target, src, safe) { + for (var key in src) { + if (safe && target[key]) target[key] = src[key]; + else hide(target, key, src[key]); + } return target; +}; + +},{"./_hide":107}],142:[function(require,module,exports){ +module.exports = require('./_hide'); + +},{"./_hide":107}],143:[function(require,module,exports){ +// Works with __proto__ only. Old v8 can't work with null proto objects. +/* eslint-disable no-proto */ +var isObject = require('./_is-object'); +var anObject = require('./_an-object'); +var check = function (O, proto) { + anObject(O); + if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); +}; +module.exports = { + set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line + function (test, buggy, set) { + try { + set = require('./_ctx')(Function.call, require('./_object-gopd').f(Object.prototype, '__proto__').set, 2); + set(test, []); + buggy = !(test instanceof Array); + } catch (e) { buggy = true; } + return function setPrototypeOf(O, proto) { + check(O, proto); + if (buggy) O.__proto__ = proto; + else set(O, proto); + return O; + }; + }({}, false) : undefined), + check: check +}; + +},{"./_an-object":91,"./_ctx":96,"./_is-object":114,"./_object-gopd":129}],144:[function(require,module,exports){ +'use strict'; +var global = require('./_global'); +var core = require('./_core'); +var dP = require('./_object-dp'); +var DESCRIPTORS = require('./_descriptors'); +var SPECIES = require('./_wks')('species'); + +module.exports = function (KEY) { + var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY]; + if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, { + configurable: true, + get: function () { return this; } + }); +}; + +},{"./_core":95,"./_descriptors":98,"./_global":105,"./_object-dp":127,"./_wks":160}],145:[function(require,module,exports){ +var def = require('./_object-dp').f; +var has = require('./_has'); +var TAG = require('./_wks')('toStringTag'); + +module.exports = function (it, tag, stat) { + if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); +}; + +},{"./_has":106,"./_object-dp":127,"./_wks":160}],146:[function(require,module,exports){ +var shared = require('./_shared')('keys'); +var uid = require('./_uid'); +module.exports = function (key) { + return shared[key] || (shared[key] = uid(key)); +}; + +},{"./_shared":147,"./_uid":157}],147:[function(require,module,exports){ +var global = require('./_global'); +var SHARED = '__core-js_shared__'; +var store = global[SHARED] || (global[SHARED] = {}); +module.exports = function (key) { + return store[key] || (store[key] = {}); +}; + +},{"./_global":105}],148:[function(require,module,exports){ +// 7.3.20 SpeciesConstructor(O, defaultConstructor) +var anObject = require('./_an-object'); +var aFunction = require('./_a-function'); +var SPECIES = require('./_wks')('species'); +module.exports = function (O, D) { + var C = anObject(O).constructor; + var S; + return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); +}; + +},{"./_a-function":88,"./_an-object":91,"./_wks":160}],149:[function(require,module,exports){ +var toInteger = require('./_to-integer'); +var defined = require('./_defined'); +// true -> String#at +// false -> String#codePointAt +module.exports = function (TO_STRING) { + return function (that, pos) { + var s = String(defined(that)); + var i = toInteger(pos); + var l = s.length; + var a, b; + if (i < 0 || i >= l) return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; +}; + +},{"./_defined":97,"./_to-integer":152}],150:[function(require,module,exports){ +var ctx = require('./_ctx'); +var invoke = require('./_invoke'); +var html = require('./_html'); +var cel = require('./_dom-create'); +var global = require('./_global'); +var process = global.process; +var setTask = global.setImmediate; +var clearTask = global.clearImmediate; +var MessageChannel = global.MessageChannel; +var Dispatch = global.Dispatch; +var counter = 0; +var queue = {}; +var ONREADYSTATECHANGE = 'onreadystatechange'; +var defer, channel, port; +var run = function () { + var id = +this; + // eslint-disable-next-line no-prototype-builtins + if (queue.hasOwnProperty(id)) { + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function (event) { + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if (!setTask || !clearTask) { + setTask = function setImmediate(fn) { + var args = []; + var i = 1; + while (arguments.length > i) args.push(arguments[i++]); + queue[++counter] = function () { + // eslint-disable-next-line no-new-func + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id) { + delete queue[id]; + }; + // Node.js 0.8- + if (require('./_cof')(process) == 'process') { + defer = function (id) { + process.nextTick(ctx(run, id, 1)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if (MessageChannel) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) { + defer = function (id) { + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if (ONREADYSTATECHANGE in cel('script')) { + defer = function (id) { + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () { + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; + +},{"./_cof":94,"./_ctx":96,"./_dom-create":99,"./_global":105,"./_html":108,"./_invoke":110}],151:[function(require,module,exports){ +var toInteger = require('./_to-integer'); +var max = Math.max; +var min = Math.min; +module.exports = function (index, length) { + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); +}; + +},{"./_to-integer":152}],152:[function(require,module,exports){ +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +module.exports = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + +},{}],153:[function(require,module,exports){ +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject = require('./_iobject'); +var defined = require('./_defined'); +module.exports = function (it) { + return IObject(defined(it)); +}; + +},{"./_defined":97,"./_iobject":111}],154:[function(require,module,exports){ +// 7.1.15 ToLength +var toInteger = require('./_to-integer'); +var min = Math.min; +module.exports = function (it) { + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + +},{"./_to-integer":152}],155:[function(require,module,exports){ +// 7.1.13 ToObject(argument) +var defined = require('./_defined'); +module.exports = function (it) { + return Object(defined(it)); +}; + +},{"./_defined":97}],156:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function (it, S) { + if (!isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); +}; + +},{"./_is-object":114}],157:[function(require,module,exports){ +var id = 0; +var px = Math.random(); +module.exports = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + +},{}],158:[function(require,module,exports){ +var global = require('./_global'); +var core = require('./_core'); +var LIBRARY = require('./_library'); +var wksExt = require('./_wks-ext'); +var defineProperty = require('./_object-dp').f; +module.exports = function (name) { + var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {}); + if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) }); +}; + +},{"./_core":95,"./_global":105,"./_library":121,"./_object-dp":127,"./_wks-ext":159}],159:[function(require,module,exports){ +exports.f = require('./_wks'); + +},{"./_wks":160}],160:[function(require,module,exports){ +var store = require('./_shared')('wks'); +var uid = require('./_uid'); +var Symbol = require('./_global').Symbol; +var USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; + +},{"./_global":105,"./_shared":147,"./_uid":157}],161:[function(require,module,exports){ +var classof = require('./_classof'); +var ITERATOR = require('./_wks')('iterator'); +var Iterators = require('./_iterators'); +module.exports = require('./_core').getIteratorMethod = function (it) { + if (it != undefined) return it[ITERATOR] + || it['@@iterator'] + || Iterators[classof(it)]; +}; + +},{"./_classof":93,"./_core":95,"./_iterators":120,"./_wks":160}],162:[function(require,module,exports){ +'use strict'; +var addToUnscopables = require('./_add-to-unscopables'); +var step = require('./_iter-step'); +var Iterators = require('./_iterators'); +var toIObject = require('./_to-iobject'); + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +module.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) { + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return step(1); + } + if (kind == 'keys') return step(0, index); + if (kind == 'values') return step(0, O[index]); + return step(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators.Arguments = Iterators.Array; + +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); + +},{"./_add-to-unscopables":89,"./_iter-define":117,"./_iter-step":119,"./_iterators":120,"./_to-iobject":153}],163:[function(require,module,exports){ +// 20.2.2.21 Math.log10(x) +var $export = require('./_export'); + +$export($export.S, 'Math', { + log10: function log10(x) { + return Math.log(x) * Math.LOG10E; + } +}); + +},{"./_export":102}],164:[function(require,module,exports){ +// 20.1.2.2 Number.isFinite(number) +var $export = require('./_export'); +var _isFinite = require('./_global').isFinite; + +$export($export.S, 'Number', { + isFinite: function isFinite(it) { + return typeof it == 'number' && _isFinite(it); + } +}); + +},{"./_export":102,"./_global":105}],165:[function(require,module,exports){ +// 19.1.3.1 Object.assign(target, source) +var $export = require('./_export'); + +$export($export.S + $export.F, 'Object', { assign: require('./_object-assign') }); + +},{"./_export":102,"./_object-assign":125}],166:[function(require,module,exports){ +var $export = require('./_export'); +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +$export($export.S, 'Object', { create: require('./_object-create') }); + +},{"./_export":102,"./_object-create":126}],167:[function(require,module,exports){ +var $export = require('./_export'); +// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) +$export($export.S + $export.F * !require('./_descriptors'), 'Object', { defineProperty: require('./_object-dp').f }); + +},{"./_descriptors":98,"./_export":102,"./_object-dp":127}],168:[function(require,module,exports){ +// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) +var toIObject = require('./_to-iobject'); +var $getOwnPropertyDescriptor = require('./_object-gopd').f; + +require('./_object-sap')('getOwnPropertyDescriptor', function () { + return function getOwnPropertyDescriptor(it, key) { + return $getOwnPropertyDescriptor(toIObject(it), key); + }; +}); + +},{"./_object-gopd":129,"./_object-sap":137,"./_to-iobject":153}],169:[function(require,module,exports){ +// 19.1.2.9 Object.getPrototypeOf(O) +var toObject = require('./_to-object'); +var $getPrototypeOf = require('./_object-gpo'); + +require('./_object-sap')('getPrototypeOf', function () { + return function getPrototypeOf(it) { + return $getPrototypeOf(toObject(it)); + }; +}); + +},{"./_object-gpo":133,"./_object-sap":137,"./_to-object":155}],170:[function(require,module,exports){ +// 19.1.3.19 Object.setPrototypeOf(O, proto) +var $export = require('./_export'); +$export($export.S, 'Object', { setPrototypeOf: require('./_set-proto').set }); + +},{"./_export":102,"./_set-proto":143}],171:[function(require,module,exports){ + +},{}],172:[function(require,module,exports){ +'use strict'; +var LIBRARY = require('./_library'); +var global = require('./_global'); +var ctx = require('./_ctx'); +var classof = require('./_classof'); +var $export = require('./_export'); +var isObject = require('./_is-object'); +var aFunction = require('./_a-function'); +var anInstance = require('./_an-instance'); +var forOf = require('./_for-of'); +var speciesConstructor = require('./_species-constructor'); +var task = require('./_task').set; +var microtask = require('./_microtask')(); +var newPromiseCapabilityModule = require('./_new-promise-capability'); +var perform = require('./_perform'); +var promiseResolve = require('./_promise-resolve'); +var PROMISE = 'Promise'; +var TypeError = global.TypeError; +var process = global.process; +var $Promise = global[PROMISE]; +var isNode = classof(process) == 'process'; +var empty = function () { /* empty */ }; +var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; +var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f; + +var USE_NATIVE = !!function () { + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1); + var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) { + exec(empty, empty); + }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + } catch (e) { /* empty */ } +}(); + +// helpers +var isThenable = function (it) { + var then; + return isObject(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var notify = function (promise, isReject) { + if (promise._n) return; + promise._n = true; + var chain = promise._c; + microtask(function () { + var value = promise._v; + var ok = promise._s == 1; + var i = 0; + var run = function (reaction) { + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then; + try { + if (handler) { + if (!ok) { + if (promise._h == 2) onHandleUnhandled(promise); + promise._h = 1; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); + if (domain) domain.exit(); + } + if (result === reaction.promise) { + reject(TypeError('Promise-chain cycle')); + } else if (then = isThenable(result)) { + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (e) { + reject(e); + } + }; + while (chain.length > i) run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if (isReject && !promise._h) onUnhandled(promise); + }); +}; +var onUnhandled = function (promise) { + task.call(global, function () { + var value = promise._v; + var unhandled = isUnhandled(promise); + var result, handler, console; + if (unhandled) { + result = perform(function () { + if (isNode) { + process.emit('unhandledRejection', value, promise); + } else if (handler = global.onunhandledrejection) { + handler({ promise: promise, reason: value }); + } else if ((console = global.console) && console.error) { + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if (unhandled && result.e) throw result.v; + }); +}; +var isUnhandled = function (promise) { + if (promise._h == 1) return false; + var chain = promise._a || promise._c; + var i = 0; + var reaction; + while (chain.length > i) { + reaction = chain[i++]; + if (reaction.fail || !isUnhandled(reaction.promise)) return false; + } return true; +}; +var onHandleUnhandled = function (promise) { + task.call(global, function () { + var handler; + if (isNode) { + process.emit('rejectionHandled', promise); + } else if (handler = global.onrejectionhandled) { + handler({ promise: promise, reason: promise._v }); + } + }); +}; +var $reject = function (value) { + var promise = this; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if (!promise._a) promise._a = promise._c.slice(); + notify(promise, true); +}; +var $resolve = function (value) { + var promise = this; + var then; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if (promise === value) throw TypeError("Promise can't be resolved itself"); + if (then = isThenable(value)) { + microtask(function () { + var wrapper = { _w: promise, _d: false }; // wrap + try { + then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); + } catch (e) { + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch (e) { + $reject.call({ _w: promise, _d: false }, e); // wrap + } +}; + +// constructor polyfill +if (!USE_NATIVE) { + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor) { + anInstance(this, $Promise, PROMISE, '_h'); + aFunction(executor); + Internal.call(this); + try { + executor(ctx($resolve, this, 1), ctx($reject, this, 1)); + } catch (err) { + $reject.call(this, err); + } + }; + // eslint-disable-next-line no-unused-vars + Internal = function Promise(executor) { + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = require('./_redefine-all')($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected) { + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process.domain : undefined; + this._c.push(reaction); + if (this._a) this._a.push(reaction); + if (this._s) notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + OwnPromiseCapability = function () { + var promise = new Internal(); + this.promise = promise; + this.resolve = ctx($resolve, promise, 1); + this.reject = ctx($reject, promise, 1); + }; + newPromiseCapabilityModule.f = newPromiseCapability = function (C) { + return C === $Promise || C === Wrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); +require('./_set-to-string-tag')($Promise, PROMISE); +require('./_set-species')(PROMISE); +Wrapper = require('./_core')[PROMISE]; + +// statics +$export($export.S + $export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r) { + var capability = newPromiseCapability(this); + var $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x) { + return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); + } +}); +$export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) { + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = perform(function () { + var values = []; + var index = 0; + var remaining = 1; + forOf(iterable, false, function (promise) { + var $index = index++; + var alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.e) reject(result.v); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var reject = capability.reject; + var result = perform(function () { + forOf(iterable, false, function (promise) { + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if (result.e) reject(result.v); + return capability.promise; + } +}); + +},{"./_a-function":88,"./_an-instance":90,"./_classof":93,"./_core":95,"./_ctx":96,"./_export":102,"./_for-of":104,"./_global":105,"./_is-object":114,"./_iter-detect":118,"./_library":121,"./_microtask":123,"./_new-promise-capability":124,"./_perform":138,"./_promise-resolve":139,"./_redefine-all":141,"./_set-species":144,"./_set-to-string-tag":145,"./_species-constructor":148,"./_task":150,"./_wks":160}],173:[function(require,module,exports){ +'use strict'; +var $at = require('./_string-at')(true); + +// 21.1.3.27 String.prototype[@@iterator]() +require('./_iter-define')(String, 'String', function (iterated) { + this._t = String(iterated); // target + this._i = 0; // next index +// 21.1.5.2.1 %StringIteratorPrototype%.next() +}, function () { + var O = this._t; + var index = this._i; + var point; + if (index >= O.length) return { value: undefined, done: true }; + point = $at(O, index); + this._i += point.length; + return { value: point, done: false }; +}); + +},{"./_iter-define":117,"./_string-at":149}],174:[function(require,module,exports){ +'use strict'; +// ECMAScript 6 symbols shim +var global = require('./_global'); +var has = require('./_has'); +var DESCRIPTORS = require('./_descriptors'); +var $export = require('./_export'); +var redefine = require('./_redefine'); +var META = require('./_meta').KEY; +var $fails = require('./_fails'); +var shared = require('./_shared'); +var setToStringTag = require('./_set-to-string-tag'); +var uid = require('./_uid'); +var wks = require('./_wks'); +var wksExt = require('./_wks-ext'); +var wksDefine = require('./_wks-define'); +var enumKeys = require('./_enum-keys'); +var isArray = require('./_is-array'); +var anObject = require('./_an-object'); +var isObject = require('./_is-object'); +var toIObject = require('./_to-iobject'); +var toPrimitive = require('./_to-primitive'); +var createDesc = require('./_property-desc'); +var _create = require('./_object-create'); +var gOPNExt = require('./_object-gopn-ext'); +var $GOPD = require('./_object-gopd'); +var $DP = require('./_object-dp'); +var $keys = require('./_object-keys'); +var gOPD = $GOPD.f; +var dP = $DP.f; +var gOPN = gOPNExt.f; +var $Symbol = global.Symbol; +var $JSON = global.JSON; +var _stringify = $JSON && $JSON.stringify; +var PROTOTYPE = 'prototype'; +var HIDDEN = wks('_hidden'); +var TO_PRIMITIVE = wks('toPrimitive'); +var isEnum = {}.propertyIsEnumerable; +var SymbolRegistry = shared('symbol-registry'); +var AllSymbols = shared('symbols'); +var OPSymbols = shared('op-symbols'); +var ObjectProto = Object[PROTOTYPE]; +var USE_NATIVE = typeof $Symbol == 'function'; +var QObject = global.QObject; +// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 +var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild; + +// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 +var setSymbolDesc = DESCRIPTORS && $fails(function () { + return _create(dP({}, 'a', { + get: function () { return dP(this, 'a', { value: 7 }).a; } + })).a != 7; +}) ? function (it, key, D) { + var protoDesc = gOPD(ObjectProto, key); + if (protoDesc) delete ObjectProto[key]; + dP(it, key, D); + if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc); +} : dP; + +var wrap = function (tag) { + var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]); + sym._k = tag; + return sym; +}; + +var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) { + return typeof it == 'symbol'; +} : function (it) { + return it instanceof $Symbol; +}; + +var $defineProperty = function defineProperty(it, key, D) { + if (it === ObjectProto) $defineProperty(OPSymbols, key, D); + anObject(it); + key = toPrimitive(key, true); + anObject(D); + if (has(AllSymbols, key)) { + if (!D.enumerable) { + if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {})); + it[HIDDEN][key] = true; + } else { + if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false; + D = _create(D, { enumerable: createDesc(0, false) }); + } return setSymbolDesc(it, key, D); + } return dP(it, key, D); +}; +var $defineProperties = function defineProperties(it, P) { + anObject(it); + var keys = enumKeys(P = toIObject(P)); + var i = 0; + var l = keys.length; + var key; + while (l > i) $defineProperty(it, key = keys[i++], P[key]); + return it; +}; +var $create = function create(it, P) { + return P === undefined ? _create(it) : $defineProperties(_create(it), P); +}; +var $propertyIsEnumerable = function propertyIsEnumerable(key) { + var E = isEnum.call(this, key = toPrimitive(key, true)); + if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false; + return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true; +}; +var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) { + it = toIObject(it); + key = toPrimitive(key, true); + if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return; + var D = gOPD(it, key); + if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true; + return D; +}; +var $getOwnPropertyNames = function getOwnPropertyNames(it) { + var names = gOPN(toIObject(it)); + var result = []; + var i = 0; + var key; + while (names.length > i) { + if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key); + } return result; +}; +var $getOwnPropertySymbols = function getOwnPropertySymbols(it) { + var IS_OP = it === ObjectProto; + var names = gOPN(IS_OP ? OPSymbols : toIObject(it)); + var result = []; + var i = 0; + var key; + while (names.length > i) { + if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]); + } return result; +}; + +// 19.4.1.1 Symbol([description]) +if (!USE_NATIVE) { + $Symbol = function Symbol() { + if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!'); + var tag = uid(arguments.length > 0 ? arguments[0] : undefined); + var $set = function (value) { + if (this === ObjectProto) $set.call(OPSymbols, value); + if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false; + setSymbolDesc(this, tag, createDesc(1, value)); + }; + if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, { configurable: true, set: $set }); + return wrap(tag); + }; + redefine($Symbol[PROTOTYPE], 'toString', function toString() { + return this._k; + }); + + $GOPD.f = $getOwnPropertyDescriptor; + $DP.f = $defineProperty; + require('./_object-gopn').f = gOPNExt.f = $getOwnPropertyNames; + require('./_object-pie').f = $propertyIsEnumerable; + require('./_object-gops').f = $getOwnPropertySymbols; + + if (DESCRIPTORS && !require('./_library')) { + redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true); + } + + wksExt.f = function (name) { + return wrap(wks(name)); + }; +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol }); + +for (var es6Symbols = ( + // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14 + 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables' +).split(','), j = 0; es6Symbols.length > j;)wks(es6Symbols[j++]); + +for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) wksDefine(wellKnownSymbols[k++]); + +$export($export.S + $export.F * !USE_NATIVE, 'Symbol', { + // 19.4.2.1 Symbol.for(key) + 'for': function (key) { + return has(SymbolRegistry, key += '') + ? SymbolRegistry[key] + : SymbolRegistry[key] = $Symbol(key); + }, + // 19.4.2.5 Symbol.keyFor(sym) + keyFor: function keyFor(sym) { + if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!'); + for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key; + }, + useSetter: function () { setter = true; }, + useSimple: function () { setter = false; } +}); + +$export($export.S + $export.F * !USE_NATIVE, 'Object', { + // 19.1.2.2 Object.create(O [, Properties]) + create: $create, + // 19.1.2.4 Object.defineProperty(O, P, Attributes) + defineProperty: $defineProperty, + // 19.1.2.3 Object.defineProperties(O, Properties) + defineProperties: $defineProperties, + // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) + getOwnPropertyDescriptor: $getOwnPropertyDescriptor, + // 19.1.2.7 Object.getOwnPropertyNames(O) + getOwnPropertyNames: $getOwnPropertyNames, + // 19.1.2.8 Object.getOwnPropertySymbols(O) + getOwnPropertySymbols: $getOwnPropertySymbols +}); + +// 24.3.2 JSON.stringify(value [, replacer [, space]]) +$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () { + var S = $Symbol(); + // MS Edge converts symbol values to JSON as {} + // WebKit converts symbol values to JSON as null + // V8 throws on boxed symbols + return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}'; +})), 'JSON', { + stringify: function stringify(it) { + var args = [it]; + var i = 1; + var replacer, $replacer; + while (arguments.length > i) args.push(arguments[i++]); + $replacer = replacer = args[1]; + if (!isObject(replacer) && it === undefined || isSymbol(it)) return; // IE8 returns string on undefined + if (!isArray(replacer)) replacer = function (key, value) { + if ($replacer) value = $replacer.call(this, key, value); + if (!isSymbol(value)) return value; + }; + args[1] = replacer; + return _stringify.apply($JSON, args); + } +}); + +// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) +$Symbol[PROTOTYPE][TO_PRIMITIVE] || require('./_hide')($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); +// 19.4.3.5 Symbol.prototype[@@toStringTag] +setToStringTag($Symbol, 'Symbol'); +// 20.2.1.9 Math[@@toStringTag] +setToStringTag(Math, 'Math', true); +// 24.3.3 JSON[@@toStringTag] +setToStringTag(global.JSON, 'JSON', true); + +},{"./_an-object":91,"./_descriptors":98,"./_enum-keys":101,"./_export":102,"./_fails":103,"./_global":105,"./_has":106,"./_hide":107,"./_is-array":113,"./_is-object":114,"./_library":121,"./_meta":122,"./_object-create":126,"./_object-dp":127,"./_object-gopd":129,"./_object-gopn":131,"./_object-gopn-ext":130,"./_object-gops":132,"./_object-keys":135,"./_object-pie":136,"./_property-desc":140,"./_redefine":142,"./_set-to-string-tag":145,"./_shared":147,"./_to-iobject":153,"./_to-primitive":156,"./_uid":157,"./_wks":160,"./_wks-define":158,"./_wks-ext":159}],175:[function(require,module,exports){ +// https://github.com/tc39/proposal-promise-finally +'use strict'; +var $export = require('./_export'); +var core = require('./_core'); +var global = require('./_global'); +var speciesConstructor = require('./_species-constructor'); +var promiseResolve = require('./_promise-resolve'); + +$export($export.P + $export.R, 'Promise', { 'finally': function (onFinally) { + var C = speciesConstructor(this, core.Promise || global.Promise); + var isFunction = typeof onFinally == 'function'; + return this.then( + isFunction ? function (x) { + return promiseResolve(C, onFinally()).then(function () { return x; }); + } : onFinally, + isFunction ? function (e) { + return promiseResolve(C, onFinally()).then(function () { throw e; }); + } : onFinally + ); +} }); + +},{"./_core":95,"./_export":102,"./_global":105,"./_promise-resolve":139,"./_species-constructor":148}],176:[function(require,module,exports){ +'use strict'; +// https://github.com/tc39/proposal-promise-try +var $export = require('./_export'); +var newPromiseCapability = require('./_new-promise-capability'); +var perform = require('./_perform'); + +$export($export.S, 'Promise', { 'try': function (callbackfn) { + var promiseCapability = newPromiseCapability.f(this); + var result = perform(callbackfn); + (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v); + return promiseCapability.promise; +} }); + +},{"./_export":102,"./_new-promise-capability":124,"./_perform":138}],177:[function(require,module,exports){ +require('./_wks-define')('asyncIterator'); + +},{"./_wks-define":158}],178:[function(require,module,exports){ +require('./_wks-define')('observable'); + +},{"./_wks-define":158}],179:[function(require,module,exports){ +require('./es6.array.iterator'); +var global = require('./_global'); +var hide = require('./_hide'); +var Iterators = require('./_iterators'); +var TO_STRING_TAG = require('./_wks')('toStringTag'); + +var DOMIterables = ('CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,' + + 'DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,' + + 'MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,' + + 'SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,' + + 'TextTrackList,TouchList').split(','); + +for (var i = 0; i < DOMIterables.length; i++) { + var NAME = DOMIterables[i]; + var Collection = global[NAME]; + var proto = Collection && Collection.prototype; + if (proto && !proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = Iterators.Array; +} + +},{"./_global":105,"./_hide":107,"./_iterators":120,"./_wks":160,"./es6.array.iterator":162}]},{},[53]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi8uLi9jbGllbnQvaW5kZXguanMiLCIuLi8uLi9jbGllbnQvc2luay9CYXJDaGFydERpc3BsYXkuanMiLCIuLi8uLi9jbGllbnQvc2luay9CYXNlRGlzcGxheS5qcyIsIi4uLy4uL2NsaWVudC9zaW5rL0JwZkRpc3BsYXkuanMiLCIuLi8uLi9jbGllbnQvc2luay9NYXJrZXJEaXNwbGF5LmpzIiwiLi4vLi4vY2xpZW50L3NpbmsvU2lnbmFsRGlzcGxheS5qcyIsIi4uLy4uL2NsaWVudC9zaW5rL1NvY2tldFNlbmQuanMiLCIuLi8uLi9jbGllbnQvc2luay9TcGVjdHJ1bURpc3BsYXkuanMiLCIuLi8uLi9jbGllbnQvc2luay9UcmFjZURpc3BsYXkuanMiLCIuLi8uLi9jbGllbnQvc2luay9WdU1ldGVyRGlzcGxheS5qcyIsIi4uLy4uL2NsaWVudC9zaW5rL1dhdmVmb3JtRGlzcGxheS5qcyIsIi4uLy4uL2NsaWVudC9zaW5rL19uYW1lc3BhY2UuanMiLCIuLi8uLi9jbGllbnQvc291cmNlL0F1ZGlvSW5CdWZmZXIuanMiLCIuLi8uLi9jbGllbnQvc291cmNlL0F1ZGlvSW5Ob2RlLmpzIiwiLi4vLi4vY2xpZW50L3NvdXJjZS9Tb2NrZXRSZWNlaXZlLmpzIiwiLi4vLi4vY2xpZW50L3NvdXJjZS9fbmFtZXNwYWNlLmpzIiwiLi4vLi4vY2xpZW50L3V0aWxzL0Rpc3BsYXlTeW5jLmpzIiwiLi4vLi4vY2xpZW50L3V0aWxzL19uYW1lc3BhY2UuanMiLCIuLi8uLi9jbGllbnQvdXRpbHMvZGlzcGxheS11dGlscy5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9CaXF1YWQuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvQ2xpcC5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9EY3QuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvRGVsdGEuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvRmZ0LmpzIiwiLi4vLi4vY29tbW9uL29wZXJhdG9yL01hZ25pdHVkZS5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9NZWFuU3RkZGV2LmpzIiwiLi4vLi4vY29tbW9uL29wZXJhdG9yL01lbC5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9NZXJnZXIuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvTWZjYy5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9NaW5NYXguanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvTW92aW5nQXZlcmFnZS5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9Nb3ZpbmdNZWRpYW4uanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvTXVsdGlwbGllci5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9Pbk9mZi5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9Qb3dlci5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9SbXMuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvU2NhbGUuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvU2VnbWVudGVyLmpzIiwiLi4vLi4vY29tbW9uL29wZXJhdG9yL1NlbGVjdC5qcyIsIi4uLy4uL2NvbW1vbi9vcGVyYXRvci9TbGljZXIuanMiLCIuLi8uLi9jb21tb24vb3BlcmF0b3IvWWluLmpzIiwiLi4vLi4vY29tbW9uL29wZXJhdG9yL19uYW1lc3BhY2UuanMiLCIuLi8uLi9jb21tb24vc2luay9CcmlkZ2UuanMiLCIuLi8uLi9jb21tb24vc2luay9EYXRhUmVjb3JkZXIuanMiLCIuLi8uLi9jb21tb24vc2luay9Mb2dnZXIuanMiLCIuLi8uLi9jb21tb24vc2luay9TaWduYWxSZWNvcmRlci5qcyIsIi4uLy4uL2NvbW1vbi9zb3VyY2UvRXZlbnRJbi5qcyIsIi4uLy4uL2NvbW1vbi91dGlscy93aW5kb3dzLmpzIiwiLi4vLi4vY29tbW9uL3V0aWxzL3dzVXRpbHMuanMiLCIuLi8uLi9jb3JlL0Jhc2VMZm8uanMiLCIuLi8uLi9jb3JlL1NvdXJjZU1peGluLmpzIiwiLi4vLi4vY29yZS9pbmRleC5qcyIsImRpc3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BpcmNhbS9wYXJhbWV0ZXJzL2Rpc3QvcGFyYW1UZW1wbGF0ZXMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQGlyY2FtL3BhcmFtZXRlcnMvZGlzdC9wYXJhbWV0ZXJzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9qc29uL3N0cmluZ2lmeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvbWF0aC9sb2cxMC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvbnVtYmVyL2lzLWZpbml0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2Fzc2lnbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2NyZWF0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9wcm9taXNlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zeW1ib2wuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL3N5bWJvbC9pdGVyYXRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvY2xhc3NDYWxsQ2hlY2suanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9oZWxwZXJzL2NyZWF0ZUNsYXNzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvZ2V0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvaGVscGVycy9pbmhlcml0cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvcG9zc2libGVDb25zdHJ1Y3RvclJldHVybi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2hlbHBlcnMvdHlwZW9mLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9qc29uL3N0cmluZ2lmeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vbWF0aC9sb2cxMC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vbnVtYmVyL2lzLWZpbml0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2NyZWF0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2RlZmluZS1wcm9wZXJ0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9zeW1ib2wvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L2ZuL3N5bWJvbC9pdGVyYXRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYS1mdW5jdGlvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYWRkLXRvLXVuc2NvcGFibGVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hbi1pbnN0YW5jZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYW4tb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1pbmNsdWRlcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY2xhc3NvZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY29mLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb3JlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jdHguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2RlZmluZWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2Rlc2NyaXB0b3JzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kb20tY3JlYXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19lbnVtLWJ1Zy1rZXlzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19lbnVtLWtleXMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2V4cG9ydC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZmFpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2Zvci1vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZ2xvYmFsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19oYXMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2hpZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2h0bWwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2llOC1kb20tZGVmaW5lLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pbnZva2UuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lvYmplY3QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLWFycmF5LWl0ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLWFycmF5LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pcy1vYmplY3QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXItY2FsbC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1jcmVhdGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2l0ZXItZGVmaW5lLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyLWRldGVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlci1zdGVwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyYXRvcnMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2xpYnJhcnkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX21ldGEuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX21pY3JvdGFzay5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fbmV3LXByb21pc2UtY2FwYWJpbGl0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWFzc2lnbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWNyZWF0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWRwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZHBzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wZC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcG4tZXh0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1ncG8uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1rZXlzLWludGVybmFsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qta2V5cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LXBpZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LXNhcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcGVyZm9ybS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fcHJvbWlzZS1yZXNvbHZlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19wcm9wZXJ0eS1kZXNjLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19yZWRlZmluZS1hbGwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3JlZGVmaW5lLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zZXQtcHJvdG8uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3NldC1zcGVjaWVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zZXQtdG8tc3RyaW5nLXRhZy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2hhcmVkLWtleS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2hhcmVkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zcGVjaWVzLWNvbnN0cnVjdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zdHJpbmctYXQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3Rhc2suanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWFic29sdXRlLWluZGV4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1pbnRlZ2VyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1pb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1sZW5ndGguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLW9iamVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tcHJpbWl0aXZlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL191aWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy1kZWZpbmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy1leHQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3drcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LmFycmF5Lml0ZXJhdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5tYXRoLmxvZzEwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5udW1iZXIuaXMtZmluaXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuYXNzaWduLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuY3JlYXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZGVmaW5lLXByb3BlcnR5LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZ2V0LW93bi1wcm9wZXJ0eS1kZXNjcmlwdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuZ2V0LXByb3RvdHlwZS1vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2Lm9iamVjdC50by1zdHJpbmcuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LnByb21pc2UuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9lczYuc3ltYm9sLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNy5wcm9taXNlLmZpbmFsbHkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnByb21pc2UudHJ5LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNy5zeW1ib2wuYXN5bmMtaXRlcmF0b3IuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvZXM3LnN5bWJvbC5vYnNlcnZhYmxlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OENDS1MsTzs7Ozs7Ozs7OytDQUNBLE87Ozs7Ozs7OzsrQ0FDQSxPOzs7Ozs7Ozs7K0NBQ0EsTzs7OztBQU5UOztJQUFZLEs7Ozs7OztBQUZMLElBQU0sNEJBQVUsV0FBaEI7O0FBR0EsSUFBTSxzQkFBTyxLQUFiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0hQOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUdBLElBQU0sY0FBYztBQUNsQixTQUFPO0FBQ0wsVUFBTSxPQUREO0FBRUwsYUFBUyxDQUZKO0FBR0wsV0FBTyxFQUFFLE1BQU0sU0FBUjtBQUhGLEdBRFc7QUFNbEIsVUFB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QUNFLFNBQUssQ0FBTCxJQUFVLENBQUMsS0FBSyxDQUFMLElBQVUsS0FBWCxJQUFvQixDQUE5QjtBQURGLEdBR0EsUUFBUSxPQUFSLENBQWdCLElBQWhCLEVBQXNCLElBQXRCOztBQUVBLGFBQVcsWUFBWCxFQUF5QixLQUFLLElBQTlCO0FBQ0QsQ0FQQSxHQUFEOzs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBOztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7O0FDREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7O0FDREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImV4cG9ydCBjb25zdCB2ZXJzaW9uID0gJyV2ZXJzaW9uJSc7XG5cbmltcG9ydCAqIGFzIF9jb3JlIGZyb20gJy4uL2NvcmUnO1xuZXhwb3J0IGNvbnN0IGNvcmUgPSBfY29yZTtcblxuZXhwb3J0IHsgZGVmYXVsdCBhcyBvcGVyYXRvciB9IGZyb20gJy4uL2NvbW1vbi9vcGVyYXRvci9fbmFtZXNwYWNlJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgdXRpbHMgfSBmcm9tICcuL3V0aWxzL19uYW1lc3BhY2UnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBzb3VyY2UgfSBmcm9tICcuL3NvdXJjZS9fbmFtZXNwYWNlJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgc2luayB9IGZyb20gJy4vc2luay9fbmFtZXNwYWNlJztcbiIsImltcG9ydCBCYXNlRGlzcGxheSBmcm9tICcuL0Jhc2VEaXNwbGF5JztcbmltcG9ydCBGZnQgZnJvbSAnLi4vLi4vY29tbW9uL29wZXJhdG9yL0ZmdCc7XG5pbXBvcnQgeyBnZXRDb2xvcnMgfSBmcm9tICcuLi91dGlscy9kaXNwbGF5LXV0aWxzJztcblxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgc2NhbGU6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDEsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG4gIGNvbG9yczoge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IGdldENvbG9ycygnYmFyLWNoYXJ0JyksXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG4gIG1pbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMCxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgbWF4OiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAxLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9XG59O1xuXG5cbi8qKlxuICogRGlzcGxheSBhIGJhciBjaGFydCBmcm9tIGFuIGluY29tbWluZyBgdmVjdG9yYCBpbnB1dC5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNsaWVudC5zaW5rXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuY29sb3JzPW51bGxdIC0gQ29sb3JzIG9mIHRoZSBiYXJzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1pbj0tODBdIC0gTWluaW11bSBkaXNwbGF5ZWQgdmFsdWUuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4PTZdIC0gTWF4aW11bSBkaXNwbGF5ZWQgdmFsdWUuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMud2lkdGg9MzAwXSAtIFdpZHRoIG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmhlaWdodD0xNTBdIC0gSGVpZ2h0IG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jb250YWluZXI9bnVsbF0gLSBDb250YWluZXIgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGluc2VydCB0aGUgY2FudmFzLiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jYW52YXM9bnVsbF0gLSBDYW52YXMgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGRyYXcuIF9jb25zdGFudCBwYXJhbWV0ZXJfXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqXG4gKiBjb25zdCBmcmFtZVNpemUgPSA1O1xuICogY29uc3QgZHQgPSAwLjAyO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVTaXplOiBmcmFtZVNpemUsXG4gKiAgIGZyYW1lUmF0ZTogMSAvIGR0LFxuICogICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxuICogfSk7XG4gKlxuICogY29uc3QgYmFyQ2hhcnQgPSBuZXcgbGZvLnNpbmsuQmFyQ2hhcnREaXNwbGF5KHtcbiAqICAgY2FudmFzOiAnI2Jhci1jaGFydCcsXG4gKiB9KTtcbiAqXG4gKiBldmVudEluLmNvbm5lY3QoYmFyQ2hhcnQpO1xuICogZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqIGNvbnN0IGRhdGEgPSBbMCwgMC4yLCAwLjQsIDAuNiwgMC44XTtcbiAqXG4gKiAoZnVuY3Rpb24gZ2VuZXJhdGVEYXRhKCkge1xuICogICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICogICAgIGRhdGFbaV0gPSAoZGF0YVtpXSArIDAuMDAxKSAlIDE7XG4gKlxuICogICBldmVudEluLnByb2Nlc3MobnVsbCwgZGF0YSk7XG4gKlxuICogICBzZXRUaW1lb3V0KGdlbmVyYXRlRGF0YSwgZHQgKiAxMDAwKTtcbiAqIH0oKSk7XG4gKi9cbmNsYXNzIEJhckNoYXJ0RGlzcGxheSBleHRlbmRzIEJhc2VEaXNwbGF5IHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMsIGZhbHNlKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKGZyYW1lKSB7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5jYW52YXNXaWR0aDtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmNhbnZhc0hlaWdodDtcbiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLnBhcmFtcy5nZXQoJ2NvbG9ycycpO1xuICAgIGNvbnN0IGRhdGEgPSBmcmFtZS5kYXRhO1xuXG4gICAgY29uc3QgYmFyV2lkdGggPSB3aWR0aCAvIGZyYW1lU2l6ZTtcbiAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcblxuICAgIC8vIGVycm9yIGhhbmRsaW5nIG5lZWRzIHJldmlldy4uLlxuICAgIGxldCBlcnJvciA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKSB7XG4gICAgICBjb25zdCB4MUZsb2F0ID0gaSAqIGJhcldpZHRoICsgZXJyb3I7XG4gICAgICBjb25zdCB4MUludCA9IE1hdGgucm91bmQoeDFGbG9hdCk7XG4gICAgICBjb25zdCB4MkZsb2F0ID0geDFGbG9hdCArIChiYXJXaWR0aCAtIGVycm9yKTtcbiAgICAgIGNvbnN0IHgySW50ID0gTWF0aC5yb3VuZCh4MkZsb2F0KTtcblxuICAgICAgZXJyb3IgPSB4MkludCAtIHgyRmxvYXQ7XG5cbiAgICAgIGlmICh4MUludCAhPT0geDJJbnQpIHtcbiAgICAgICAgY29uc3Qgd2lkdGggPSB4MkludCAtIHgxSW50O1xuICAgICAgICBjb25zdCB5ID0gdGhpcy5nZXRZUG9zaXRpb24oZGF0YVtpXSk7XG5cbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGNvbG9yc1tpICUgY29sb3JzLmxlbmd0aF07XG4gICAgICAgIGN0eC5maWxsUmVjdCh4MUludCwgeSwgd2lkdGgsIGhlaWdodCAtIHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXJyb3IgLT0gYmFyV2lkdGg7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJhckNoYXJ0RGlzcGxheTtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IGNvbW1vbkRlZmluaXRpb25zID0ge1xuICBtaW46IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IC0xLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBtYXg6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDEsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG4gIHdpZHRoOiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IDMwMCxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgaGVpZ2h0OiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IDE1MCxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgY29udGFpbmVyOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogbnVsbCxcbiAgICBjb25zdGFudDogdHJ1ZSxcbiAgfSxcbiAgY2FudmFzOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogbnVsbCxcbiAgICBjb25zdGFudDogdHJ1ZSxcbiAgfSxcbn07XG5cbmNvbnN0IGhhc0R1cmF0aW9uRGVmaW5pdGlvbnMgPSB7XG4gIGR1cmF0aW9uOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBtaW46IDAsXG4gICAgbWF4OiArSW5maW5pdHksXG4gICAgZGVmYXVsdDogMSxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgcmVmZXJlbmNlVGltZToge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMCxcbiAgICBjb25zdGFudDogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogQmFzZSBjbGFzcyB0byBleHRlbmQgaW4gb3JkZXIgdG8gY3JlYXRlIGdyYXBoaWMgc2lua3MuXG4gKlxuICogPHNwYW4gY2xhc3M9XCJ3YXJuaW5nXCI+X1RoaXMgY2xhc3Mgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYWJzdHJhY3QgYW5kIG9ubHlcbiAqIGJlIHVzZWQgdG8gYmUgZXh0ZW5kZWQuXzwvc3Bhbj5cbiAqXG4gKiBAdG9kbyAtIGZpeCBmbG9hdCByb3VuZGluZyBlcnJvcnMgKHByb2R1Y2UgZGVjYXlzIGluIHN5bmMgZHJhd3MpXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjbGllbnQuc2lua1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1pbj0tMV0gLSBNaW5pbXVtIHZhbHVlIHJlcHJlc2VudGVkIGluIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heD0xXSAtIE1heGltdW0gdmFsdWUgcmVwcmVzZW50ZWQgaW4gdGhlIGNhbnZhcy5cbiAqICBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMud2lkdGg9MzAwXSAtIFdpZHRoIG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmhlaWdodD0xNTBdIC0gSGVpZ2h0IG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jb250YWluZXI9bnVsbF0gLSBDb250YWluZXIgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGluc2VydCB0aGUgY2FudmFzLiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jYW52YXM9bnVsbF0gLSBDYW52YXMgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGRyYXcuIF9jb25zdGFudCBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZHVyYXRpb249MV0gLSBEdXJhdGlvbiAoaW4gc2Vjb25kcykgcmVwcmVzZW50ZWQgaW5cbiAqICB0aGUgY2FudmFzLiBUaGlzIHBhcmFtZXRlciBvbmx5IGV4aXN0cyBmb3Igb3BlcmF0b3JzIHRoYXQgZGlzcGxheSBzZXZlcmFsXG4gKiAgY29uc2VjdXRpdmUgZnJhbWVzIG9uIHRoZSBjYW52YXMuIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5yZWZlcmVuY2VUaW1lPW51bGxdIC0gT3B0aW9ubmFsIHJlZmVyZW5jZSB0aW1lIHRoZVxuICogIGRpc3BsYXkgc2hvdWxkIGNvbnNpZGVyZXIgYXMgdGhlIG9yaWdpbi4gSXMgb25seSB1c2VmdWxsIHdoZW4gc3luY2hyb25pemluZ1xuICogIHNldmVyYWwgZGlzcGxheSB1c2luZyB0aGUgYERpc3BsYXlTeW5jYCBjbGFzcy4gVGhpcyBwYXJhbWV0ZXIgb25seSBleGlzdHNcbiAqICBmb3Igb3BlcmF0b3JzIHRoYXQgZGlzcGxheSBzZXZlcmFsIGNvbnNlY3V0aXZlIGZyYW1lcyBvbiB0aGUgY2FudmFzLlxuICovXG5jbGFzcyBCYXNlRGlzcGxheSBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihkZWZzLCBvcHRpb25zID0ge30sIGhhc0R1cmF0aW9uID0gdHJ1ZSkge1xuICAgIGxldCBjb21tb25EZWZzO1xuXG4gICAgaWYgKGhhc0R1cmF0aW9uKVxuICAgICAgY29tbW9uRGVmcyA9IE9iamVjdC5hc3NpZ24oe30sIGNvbW1vbkRlZmluaXRpb25zLCBoYXNEdXJhdGlvbkRlZmluaXRpb25zKTtcbiAgICBlbHNlXG4gICAgICBjb21tb25EZWZzID0gY29tbW9uRGVmaW5pdGlvbnNcblxuICAgIGNvbnN0IGRlZmluaXRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgY29tbW9uRGVmcywgZGVmcyk7XG5cbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICBpZiAodGhpcy5wYXJhbXMuZ2V0KCdjYW52YXMnKSA9PT0gbnVsbCAmJiB0aGlzLnBhcmFtcy5nZXQoJ2NvbnRhaW5lcicpID09PSBudWxsKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcmFtZXRlcjogYGNhbnZhc2Agb3IgYGNvbnRhaW5lcmAgbm90IGRlZmluZWQnKTtcblxuICAgIGNvbnN0IGNhbnZhc1BhcmFtID0gdGhpcy5wYXJhbXMuZ2V0KCdjYW52YXMnKTtcbiAgICBjb25zdCBjb250YWluZXJQYXJhbSA9IHRoaXMucGFyYW1zLmdldCgnY29udGFpbmVyJyk7XG5cbiAgICAvLyBwcmVwYXJlIGNhbnZhc1xuICAgIGlmIChjYW52YXNQYXJhbSkge1xuICAgICAgaWYgKHR5cGVvZiBjYW52YXNQYXJhbSA9PT0gJ3N0cmluZycpXG4gICAgICAgIHRoaXMuY2FudmFzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihjYW52YXNQYXJhbSk7XG4gICAgICBlbHNlXG4gICAgICAgIHRoaXMuY2FudmFzID0gY2FudmFzUGFyYW07XG4gICAgfSBlbHNlIGlmIChjb250YWluZXJQYXJhbSkge1xuICAgICAgbGV0IGNvbnRhaW5lcjtcblxuICAgICAgaWYgKHR5cGVvZiBjb250YWluZXJQYXJhbSA9PT0gJ3N0cmluZycpXG4gICAgICAgIGNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoY29udGFpbmVyUGFyYW0pO1xuICAgICAgZWxzZVxuICAgICAgICBjb250YWluZXIgPSBjb250YWluZXJQYXJhbTtcblxuICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmNhbnZhcyk7XG4gICAgfVxuXG4gICAgdGhpcy5jdHggPSB0aGlzLmNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIHRoaXMuY2FjaGVkQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgdGhpcy5jYWNoZWRDdHggPSB0aGlzLmNhY2hlZENhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgdGhpcy5oYXNEdXJhdGlvbiA9IGhhc0R1cmF0aW9uO1xuICAgIHRoaXMucHJldmlvdXNGcmFtZSA9IG51bGw7XG4gICAgdGhpcy5jdXJyZW50VGltZSA9IGhhc0R1cmF0aW9uID8gdGhpcy5wYXJhbXMuZ2V0KCdyZWZlcmVuY2VUaW1lJykgOiBudWxsO1xuXG4gICAgLyoqXG4gICAgICogSW5zdGFuY2Ugb2YgdGhlIGBEaXNwbGF5U3luY2AgdXNlZCB0byBzeW5jaHJvbml6ZSB0aGUgZGlmZmVyZW50IGRpc3BsYXlzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLmRpc3BsYXlTeW5jID0gZmFsc2U7XG5cbiAgICB0aGlzLl9zdGFjayA9IFtdO1xuICAgIHRoaXMuX3JhZklkID0gbnVsbDtcblxuICAgIHRoaXMucmVuZGVyU3RhY2sgPSB0aGlzLnJlbmRlclN0YWNrLmJpbmQodGhpcyk7XG4gICAgdGhpcy5zaGlmdEVycm9yID0gMDtcblxuICAgIC8vIGluaXRpYWxpemUgY2FudmFzIHNpemUgYW5kIHkgc2NhbGUgdHJhbnNmZXJ0IGZ1bmN0aW9uXG4gICAgdGhpcy5fcmVzaXplKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgX3Jlc2l6ZSgpIHtcbiAgICBjb25zdCB3aWR0aCA9IHRoaXMucGFyYW1zLmdldCgnd2lkdGgnKTtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLnBhcmFtcy5nZXQoJ2hlaWdodCcpO1xuXG4gICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgY2FjaGVkQ3R4ID0gdGhpcy5jYWNoZWRDdHg7XG5cbiAgICBjb25zdCBkUFIgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuICAgIGNvbnN0IGJQUiA9IGN0eC53ZWJraXRCYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8XG4gICAgICBjdHgubW96QmFja2luZ1N0b3JlUGl4ZWxSYXRpbyB8fFxuICAgICAgY3R4Lm1zQmFja2luZ1N0b3JlUGl4ZWxSYXRpbyB8fFxuICAgICAgY3R4Lm9CYWNraW5nU3RvcmVQaXhlbFJhdGlvIHx8XG4gICAgICBjdHguYmFja2luZ1N0b3JlUGl4ZWxSYXRpbyB8fCAxO1xuXG4gICAgdGhpcy5waXhlbFJhdGlvID0gZFBSIC8gYlBSO1xuXG4gICAgY29uc3QgbGFzdFdpZHRoID0gdGhpcy5jYW52YXNXaWR0aDtcbiAgICBjb25zdCBsYXN0SGVpZ2h0ID0gdGhpcy5jYW52YXNIZWlnaHQ7XG4gICAgdGhpcy5jYW52YXNXaWR0aCA9IHdpZHRoICogdGhpcy5waXhlbFJhdGlvO1xuICAgIHRoaXMuY2FudmFzSGVpZ2h0ID0gaGVpZ2h0ICogdGhpcy5waXhlbFJhdGlvO1xuXG4gICAgY2FjaGVkQ3R4LmNhbnZhcy53aWR0aCA9IHRoaXMuY2FudmFzV2lkdGg7XG4gICAgY2FjaGVkQ3R4LmNhbnZhcy5oZWlnaHQgPSB0aGlzLmNhbnZhc0hlaWdodDtcblxuICAgIC8vIGNvcHkgY3VycmVudCBpbWFnZSBmcm9tIGN0eCAocmVzaXplKVxuICAgIGlmIChsYXN0V2lkdGggJiYgbGFzdEhlaWdodCkge1xuICAgICAgY2FjaGVkQ3R4LmRyYXdJbWFnZShjdHguY2FudmFzLFxuICAgICAgICAwLCAwLCBsYXN0V2lkdGgsIGxhc3RIZWlnaHQsXG4gICAgICAgIDAsIDAsIHRoaXMuY2FudmFzV2lkdGgsIHRoaXMuY2FudmFzSGVpZ2h0XG4gICAgICApO1xuICAgIH1cblxuICAgIGN0eC5jYW52YXMud2lkdGggPSB0aGlzLmNhbnZhc1dpZHRoO1xuICAgIGN0eC5jYW52YXMuaGVpZ2h0ID0gdGhpcy5jYW52YXNIZWlnaHQ7XG4gICAgY3R4LmNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3dpZHRofXB4YDtcbiAgICBjdHguY2FudmFzLnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG5cbiAgICAvLyB1cGRhdGUgc2NhbGVcbiAgICB0aGlzLl9zZXRZU2NhbGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgdGhlIHRyYW5zZmVydCBmdW5jdGlvbiB1c2VkIHRvIG1hcCB2YWx1ZXMgdG8gcGl4ZWwgaW4gdGhlIHkgYXhpc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX3NldFlTY2FsZSgpIHtcbiAgICBjb25zdCBtaW4gPSB0aGlzLnBhcmFtcy5nZXQoJ21pbicpO1xuICAgIGNvbnN0IG1heCA9IHRoaXMucGFyYW1zLmdldCgnbWF4Jyk7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5jYW52YXNIZWlnaHQ7XG5cbiAgICBjb25zdCBhID0gKDAgLSBoZWlnaHQpIC8gKG1heCAtIG1pbik7XG4gICAgY29uc3QgYiA9IGhlaWdodCAtIChhICogbWluKTtcblxuICAgIHRoaXMuZ2V0WVBvc2l0aW9uID0gKHgpID0+IGEgKiB4ICsgYjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB3aWR0aCBpbiBwaXhlbCBhIGB2ZWN0b3JgIGZyYW1lIG5lZWRzIHRvIGJlIGRyYXduLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgZ2V0TWluaW11bUZyYW1lV2lkdGgoKSB7XG4gICAgcmV0dXJuIDE7IC8vIG5lZWQgb25lIHBpeGVsIHRvIGRyYXcgdGhlIGxpbmVcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmdW5jdGlvbiBleGVjdXRlZCB3aGVuIGEgcGFyYW1ldGVyIGlzIHVwZGF0ZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gUGFyYW1ldGVyIG5hbWUuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIC0gUGFyYW1ldGVyIHZhbHVlLlxuICAgKiBAcGFyYW0ge09iamVjdH0gbWV0YXMgLSBNZXRhZGF0YXMgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIG9uUGFyYW1VcGRhdGUobmFtZSwgdmFsdWUsIG1ldGFzKSB7XG4gICAgc3VwZXIub25QYXJhbVVwZGF0ZShuYW1lLCB2YWx1ZSwgbWV0YXMpO1xuXG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdtaW4nOlxuICAgICAgY2FzZSAnbWF4JzpcbiAgICAgICAgLy8gQHRvZG8gLSBtYWtlIHN1cmUgdGhhdCBtaW4gYW5kIG1heCBhcmUgZGlmZmVyZW50XG4gICAgICAgIHRoaXMuX3NldFlTY2FsZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3dpZHRoJzpcbiAgICAgIGNhc2UgJ2hlaWdodCc6XG4gICAgICAgIHRoaXMuX3Jlc2l6ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9wYWdhdGVTdHJlYW1QYXJhbXMoKSB7XG4gICAgc3VwZXIucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcblxuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5jYW52YXNXaWR0aDtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmNhbnZhc0hlaWdodDtcblxuICAgIHRoaXMucHJldmlvdXNGcmFtZSA9IG51bGw7XG4gICAgdGhpcy5jdXJyZW50VGltZSA9IHRoaXMuaGFzRHVyYXRpb24gPyB0aGlzLnBhcmFtcy5nZXQoJ3JlZmVyZW5jZVRpbWUnKSA6IG51bGw7XG5cbiAgICB0aGlzLmN0eC5jbGVhclJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgdGhpcy5jYWNoZWRDdHguY2xlYXJSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIGZpbmFsaXplU3RyZWFtKGVuZFRpbWUpIHtcbiAgICB0aGlzLmN1cnJlbnRUaW1lID0gbnVsbDtcbiAgICBzdXBlci5maW5hbGl6ZVN0cmVhbShlbmRUaW1lKTtcblxuICAgIHRoaXMuX3JhZklkID0gbnVsbDtcblxuICAgIC8vIGNsZWFyIHRoZSBzdGFjayBpZiBub3QgZW1wdHlcbiAgICBpZiAodGhpcy5fc3RhY2subGVuZ3RoID4gMClcbiAgICAgIHRoaXMucmVuZGVyU3RhY2soKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgdGhlIGN1cnJlbnQgZnJhbWUgdG8gdGhlIGZyYW1lcyB0byBkcmF3LiBTaG91bGQgbm90IGJlIG92ZXJyaWRlbi5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByb2Nlc3NGcmFtZShmcmFtZSkge1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBjb3B5ID0gbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpO1xuICAgIGNvbnN0IGRhdGEgPSBmcmFtZS5kYXRhO1xuXG4gICAgLy8gY29weSB2YWx1ZXMgb2YgdGhlIGlucHV0IGZyYW1lIGFzIHRoZXkgbWlnaHQgYmUgdXBkYXRlZFxuICAgIC8vIGluIHJlZmVyZW5jZSBiZWZvcmUgYmVpbmcgY29uc3VtZWQgaW4gdGhlIGRyYXcgZnVuY3Rpb25cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICAgICAgY29weVtpXSA9IGRhdGFbaV07XG5cbiAgICB0aGlzLl9zdGFjay5wdXNoKHtcbiAgICAgIHRpbWU6IGZyYW1lLnRpbWUsXG4gICAgICBkYXRhOiBjb3B5LFxuICAgICAgbWV0YWRhdGE6IGZyYW1lLm1ldGFkYXRhLFxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuX3JhZklkID09PSBudWxsKVxuICAgICAgdGhpcy5fcmFmSWQgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMucmVuZGVyU3RhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgYWNjdW11bGF0ZWQgZnJhbWVzLiBNZXRob2QgY2FsbGVkIGluIGByZXF1ZXN0QW5pbWF0aW9uRnJhbWVgLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcmVuZGVyU3RhY2soKSB7XG4gICAgaWYgKHRoaXMucGFyYW1zLmhhcygnZHVyYXRpb24nKSkge1xuICAgICAgLy8gcmVuZGVyIGFsbCBmcmFtZSBzaW5jZSBsYXN0IGByZW5kZXJTdGFja2AgY2FsbFxuICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSB0aGlzLl9zdGFjay5sZW5ndGg7IGkgPCBsOyBpKyspXG4gICAgICAgIHRoaXMuc2Nyb2xsTW9kZURyYXcodGhpcy5fc3RhY2tbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBvbmx5IHJlbmRlciBsYXN0IHJlY2VpdmVkIGZyYW1lIGlmIGFueVxuICAgICAgaWYgKHRoaXMuX3N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgZnJhbWUgPSB0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGggLSAxXTtcbiAgICAgICAgdGhpcy5jdHguY2xlYXJSZWN0KDAsIDAsIHRoaXMuY2FudmFzV2lkdGgsIHRoaXMuY2FudmFzSGVpZ2h0KTtcbiAgICAgICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24oZnJhbWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3N0YWNrLmxlbmd0aCA9IDA7IC8vIHJlaW5pdCBzdGFjayBmb3IgbmV4dCBjYWxsXG4gICAgdGhpcy5fcmFmSWQgPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIERyYXcgZGF0YSBmcm9tIHJpZ2h0IHRvIGxlZnQgd2l0aCBzY3JvbGxpbmdcbiAgICogQHByaXZhdGVcbiAgICogQHRvZG8gLSBjaGVjayBwb3NzaWJpbGl0eSBvZiBtYWludGFpbmluZyBhbGwgdmFsdWVzIGZyb20gb25lIHBsYWNlIHRvXG4gICAqICAgICAgICAgbWluaW1pemUgZmxvYXQgZXJyb3IgdHJhY2tpbmcuXG4gICAqL1xuICBzY3JvbGxNb2RlRHJhdyhmcmFtZSkge1xuICAgIGNvbnN0IGZyYW1lVHlwZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZTtcbiAgICBjb25zdCBmcmFtZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVJhdGU7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHNvdXJjZVNhbXBsZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlO1xuXG4gICAgY29uc3QgY2FudmFzRHVyYXRpb24gPSB0aGlzLnBhcmFtcy5nZXQoJ2R1cmF0aW9uJyk7XG4gICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgY2FudmFzV2lkdGggPSB0aGlzLmNhbnZhc1dpZHRoO1xuICAgIGNvbnN0IGNhbnZhc0hlaWdodCA9IHRoaXMuY2FudmFzSGVpZ2h0O1xuXG4gICAgY29uc3QgcHJldmlvdXNGcmFtZSA9IHRoaXMucHJldmlvdXNGcmFtZTtcblxuICAgIC8vIGN1cnJlbnQgdGltZSBhdCB0aGUgbGVmdCBvZiB0aGUgY2FudmFzXG4gICAgY29uc3QgY3VycmVudFRpbWUgPSAodGhpcy5jdXJyZW50VGltZSAhPT0gbnVsbCkgPyB0aGlzLmN1cnJlbnRUaW1lIDogZnJhbWUudGltZTtcbiAgICBjb25zdCBmcmFtZVN0YXJ0VGltZSA9IGZyYW1lLnRpbWU7XG4gICAgY29uc3QgbGFzdEZyYW1lVGltZSA9IHByZXZpb3VzRnJhbWUgPyBwcmV2aW91c0ZyYW1lLnRpbWUgOiAwO1xuICAgIGNvbnN0IGxhc3RGcmFtZUR1cmF0aW9uID0gdGhpcy5sYXN0RnJhbWVEdXJhdGlvbiA/IHRoaXMubGFzdEZyYW1lRHVyYXRpb24gOiAwO1xuXG4gICAgbGV0IGZyYW1lRHVyYXRpb247XG5cbiAgICBpZiAoZnJhbWVUeXBlID09PSAnc2NhbGFyJyB8fCBmcmFtZVR5cGUgPT09ICd2ZWN0b3InKSB7XG4gICAgICBjb25zdCBwaXhlbER1cmF0aW9uID0gY2FudmFzRHVyYXRpb24gLyBjYW52YXNXaWR0aDtcbiAgICAgIGZyYW1lRHVyYXRpb24gPSB0aGlzLmdldE1pbmltdW1GcmFtZVdpZHRoKCkgKiBwaXhlbER1cmF0aW9uO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlID09PSAnc2lnbmFsJykge1xuICAgICAgZnJhbWVEdXJhdGlvbiA9IGZyYW1lU2l6ZSAvIHNvdXJjZVNhbXBsZVJhdGU7XG4gICAgfVxuXG4gICAgY29uc3QgZnJhbWVFbmRUaW1lID0gZnJhbWVTdGFydFRpbWUgKyBmcmFtZUR1cmF0aW9uO1xuICAgIC8vIGRlZmluZSBpZiB3ZSBuZWVkIHRvIHNoaWZ0IHRoZSBjYW52YXNcbiAgICBjb25zdCBzaGlmdFRpbWUgPSBmcmFtZUVuZFRpbWUgLSBjdXJyZW50VGltZTtcblxuICAgIC8vIGlmIHRoZSBjYW52YXMgaXMgbm90IHN5bmNlZCwgc2hvdWxkIG5ldmVyIGdvIHRvIGBlbHNlYFxuICAgIGlmIChzaGlmdFRpbWUgPiAwKSB7XG4gICAgICAvLyBzaGlmdCB0aGUgY2FudmFzIG9mIHNoaWZ0VGltZSBpbiBwaXhlbHNcbiAgICAgIGNvbnN0IGZTaGlmdCA9IChzaGlmdFRpbWUgLyBjYW52YXNEdXJhdGlvbikgKiBjYW52YXNXaWR0aCAtIHRoaXMuc2hpZnRFcnJvcjtcbiAgICAgIGNvbnN0IGlTaGlmdCA9IE1hdGguZmxvb3IoZlNoaWZ0ICsgMC41KTtcbiAgICAgIHRoaXMuc2hpZnRFcnJvciA9IGZTaGlmdCAtIGlTaGlmdDtcblxuICAgICAgY29uc3QgY3VycmVudFRpbWUgPSBmcmFtZVN0YXJ0VGltZSArIGZyYW1lRHVyYXRpb247XG4gICAgICB0aGlzLnNoaWZ0Q2FudmFzKGlTaGlmdCwgY3VycmVudFRpbWUpO1xuXG4gICAgICAvLyBpZiBzaWJsaW5ncywgc2hhcmUgdGhlIGluZm9ybWF0aW9uXG4gICAgICBpZiAodGhpcy5kaXNwbGF5U3luYylcbiAgICAgICAgdGhpcy5kaXNwbGF5U3luYy5zaGlmdFNpYmxpbmdzKGlTaGlmdCwgY3VycmVudFRpbWUsIHRoaXMpO1xuICAgIH1cblxuICAgIC8vIHdpZHRoIG9mIHRoZSBmcmFtZSBpbiBwaXhlbHNcbiAgICBjb25zdCBmbG9hdEZyYW1lV2lkdGggPSAoZnJhbWVEdXJhdGlvbiAvIGNhbnZhc0R1cmF0aW9uKSAqIGNhbnZhc1dpZHRoO1xuICAgIGNvbnN0IGZyYW1lV2lkdGggPSBNYXRoLmZsb29yKGZsb2F0RnJhbWVXaWR0aCArIDAuNSk7XG5cbiAgICAvLyBkZWZpbmUgcG9zaXRpb24gb2YgdGhlIGhlYWQgaW4gdGhlIGNhbnZhc1xuICAgIGNvbnN0IGNhbnZhc1N0YXJ0VGltZSA9IHRoaXMuY3VycmVudFRpbWUgLSBjYW52YXNEdXJhdGlvbjtcbiAgICBjb25zdCBzdGFydFRpbWVSYXRpbyA9IChmcmFtZVN0YXJ0VGltZSAtIGNhbnZhc1N0YXJ0VGltZSkgLyBjYW52YXNEdXJhdGlvbjtcbiAgICBjb25zdCBzdGFydFRpbWVQb3NpdGlvbiA9IHN0YXJ0VGltZVJhdGlvICogY2FudmFzV2lkdGg7XG5cbiAgICAvLyBudW1iZXIgb2YgcGl4ZWxzIHNpbmNlIGxhc3QgZnJhbWVcbiAgICBsZXQgcGl4ZWxzU2luY2VMYXN0RnJhbWUgPSB0aGlzLmxhc3RGcmFtZVdpZHRoO1xuXG4gICAgaWYgKChmcmFtZVR5cGUgPT09ICdzY2FsYXInIHx8IGZyYW1lVHlwZSA9PT0gJ3ZlY3RvcicpICYmIHByZXZpb3VzRnJhbWUpIHtcbiAgICAgIGNvbnN0IGZyYW1lSW50ZXJ2YWwgPSBmcmFtZS50aW1lIC0gcHJldmlvdXNGcmFtZS50aW1lO1xuICAgICAgcGl4ZWxzU2luY2VMYXN0RnJhbWUgPSAoZnJhbWVJbnRlcnZhbCAvIGNhbnZhc0R1cmF0aW9uKSAqIGNhbnZhc1dpZHRoO1xuICAgIH1cblxuICAgIC8vIGRyYXcgY3VycmVudCBmcmFtZVxuICAgIGN0eC5zYXZlKCk7XG4gICAgY3R4LnRyYW5zbGF0ZShzdGFydFRpbWVQb3NpdGlvbiwgMCk7XG4gICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24oZnJhbWUsIGZyYW1lV2lkdGgsIHBpeGVsc1NpbmNlTGFzdEZyYW1lKTtcbiAgICBjdHgucmVzdG9yZSgpO1xuXG4gICAgLy8gc2F2ZSBjdXJyZW50IGNhbnZhcyBzdGF0ZSBpbnRvIGNhY2hlZCBjYW52YXNcbiAgICB0aGlzLmNhY2hlZEN0eC5jbGVhclJlY3QoMCwgMCwgY2FudmFzV2lkdGgsIGNhbnZhc0hlaWdodCk7XG4gICAgdGhpcy5jYWNoZWRDdHguZHJhd0ltYWdlKHRoaXMuY2FudmFzLCAwLCAwLCBjYW52YXNXaWR0aCwgY2FudmFzSGVpZ2h0KTtcblxuICAgIC8vIHVwZGF0ZSBsYXN0RnJhbWVEdXJhdGlvbiwgbGFzdEZyYW1lV2lkdGhcbiAgICB0aGlzLmxhc3RGcmFtZUR1cmF0aW9uID0gZnJhbWVEdXJhdGlvbjtcbiAgICB0aGlzLmxhc3RGcmFtZVdpZHRoID0gZnJhbWVXaWR0aDtcbiAgICB0aGlzLnByZXZpb3VzRnJhbWUgPSBmcmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaGlmdCBjYW52YXMsIGFsc28gY2FsbGVkIGZyb20gYERpc3BsYXlTeW5jYFxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc2hpZnRDYW52YXMoaVNoaWZ0LCB0aW1lKSB7XG4gICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgY2FjaGUgPSB0aGlzLmNhY2hlZENhbnZhcztcbiAgICBjb25zdCBjYWNoZWRDdHggPSB0aGlzLmNhY2hlZEN0eDtcbiAgICBjb25zdCB3aWR0aCA9IHRoaXMuY2FudmFzV2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5jYW52YXNIZWlnaHQ7XG4gICAgY29uc3QgY3JvcHBlZFdpZHRoID0gd2lkdGggLSBpU2hpZnQ7XG4gICAgdGhpcy5jdXJyZW50VGltZSA9IHRpbWU7XG5cbiAgICBjdHguY2xlYXJSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgIGN0eC5kcmF3SW1hZ2UoY2FjaGUsIGlTaGlmdCwgMCwgY3JvcHBlZFdpZHRoLCBoZWlnaHQsIDAsIDAsIGNyb3BwZWRXaWR0aCwgaGVpZ2h0KTtcbiAgICAvLyBzYXZlIGN1cnJlbnQgY2FudmFzIHN0YXRlIGludG8gY2FjaGVkIGNhbnZhc1xuICAgIGNhY2hlZEN0eC5jbGVhclJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgY2FjaGVkQ3R4LmRyYXdJbWFnZSh0aGlzLmNhbnZhcywgMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gIH1cblxuICAvLyBAdG9kbyAtIEZpeCB0cmlnZ2VyIG1vZGVcbiAgLy8gYWxsb3cgdG8gd2l0Y2ggZWFzaWx5IGJldHdlZW4gdGhlIDIgbW9kZXNcbiAgLy8gc2V0VHJpZ2dlcihib29sKSB7XG4gIC8vICAgdGhpcy5wYXJhbXMudHJpZ2dlciA9IGJvb2w7XG4gIC8vICAgLy8gY2xlYXIgY2FudmFzIGFuZCBjYWNoZVxuICAvLyAgIHRoaXMuY3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLnBhcmFtcy53aWR0aCwgdGhpcy5wYXJhbXMuaGVpZ2h0KTtcbiAgLy8gICB0aGlzLmNhY2hlZEN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5wYXJhbXMud2lkdGgsIHRoaXMucGFyYW1zLmhlaWdodCk7XG4gIC8vICAgLy8gcmVzZXQgX2N1cnJlbnRYUG9zaXRpb25cbiAgLy8gICB0aGlzLl9jdXJyZW50WFBvc2l0aW9uID0gMDtcbiAgLy8gICB0aGlzLmxhc3RTaGlmdEVycm9yID0gMDtcbiAgLy8gfVxuXG4gIC8vIC8qKlxuICAvLyAgKiBBbHRlcm5hdGl2ZSBkcmF3aW5nIG1vZGUuXG4gIC8vICAqIERyYXcgZnJvbSBsZWZ0IHRvIHJpZ2h0LCBnbyBiYWNrIHRvIGxlZnQgd2hlbiA+IHdpZHRoXG4gIC8vICAqL1xuICAvLyB0cmlnZ2VyTW9kZURyYXcodGltZSwgZnJhbWUpIHtcbiAgLy8gICBjb25zdCB3aWR0aCAgPSB0aGlzLnBhcmFtcy53aWR0aDtcbiAgLy8gICBjb25zdCBoZWlnaHQgPSB0aGlzLnBhcmFtcy5oZWlnaHQ7XG4gIC8vICAgY29uc3QgZHVyYXRpb24gPSB0aGlzLnBhcmFtcy5kdXJhdGlvbjtcbiAgLy8gICBjb25zdCBjdHggPSB0aGlzLmN0eDtcblxuICAvLyAgIGNvbnN0IGR0ID0gdGltZSAtIHRoaXMucHJldmlvdXNUaW1lO1xuICAvLyAgIGNvbnN0IGZTaGlmdCA9IChkdCAvIGR1cmF0aW9uKSAqIHdpZHRoIC0gdGhpcy5sYXN0U2hpZnRFcnJvcjsgLy8gcHhcbiAgLy8gICBjb25zdCBpU2hpZnQgPSBNYXRoLnJvdW5kKGZTaGlmdCk7XG4gIC8vICAgdGhpcy5sYXN0U2hpZnRFcnJvciA9IGlTaGlmdCAtIGZTaGlmdDtcblxuICAvLyAgIHRoaXMuY3VycmVudFhQb3NpdGlvbiArPSBpU2hpZnQ7XG5cbiAgLy8gICAvLyBkcmF3IHRoZSByaWdodCBwYXJ0XG4gIC8vICAgY3R4LnNhdmUoKTtcbiAgLy8gICBjdHgudHJhbnNsYXRlKHRoaXMuY3VycmVudFhQb3NpdGlvbiwgMCk7XG4gIC8vICAgY3R4LmNsZWFyUmVjdCgtaVNoaWZ0LCAwLCBpU2hpZnQsIGhlaWdodCk7XG4gIC8vICAgdGhpcy5kcmF3Q3VydmUoZnJhbWUsIGlTaGlmdCk7XG4gIC8vICAgY3R4LnJlc3RvcmUoKTtcblxuICAvLyAgIC8vIGdvIGJhY2sgdG8gdGhlIGxlZnQgb2YgdGhlIGNhbnZhcyBhbmQgcmVkcmF3IHRoZSBzYW1lIHRoaW5nXG4gIC8vICAgaWYgKHRoaXMuY3VycmVudFhQb3NpdGlvbiA+IHdpZHRoKSB7XG4gIC8vICAgICAvLyBnbyBiYWNrIHRvIHN0YXJ0XG4gIC8vICAgICB0aGlzLmN1cnJlbnRYUG9zaXRpb24gLT0gd2lkdGg7XG5cbiAgLy8gICAgIGN0eC5zYXZlKCk7XG4gIC8vICAgICBjdHgudHJhbnNsYXRlKHRoaXMuY3VycmVudFhQb3NpdGlvbiwgMCk7XG4gIC8vICAgICBjdHguY2xlYXJSZWN0KC1pU2hpZnQsIDAsIGlTaGlmdCwgaGVpZ2h0KTtcbiAgLy8gICAgIHRoaXMuZHJhd0N1cnZlKGZyYW1lLCB0aGlzLnByZXZpb3VzRnJhbWUsIGlTaGlmdCk7XG4gIC8vICAgICBjdHgucmVzdG9yZSgpO1xuICAvLyAgIH1cbiAgLy8gfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEJhc2VEaXNwbGF5O1xuIiwiaW1wb3J0IEJhc2VEaXNwbGF5IGZyb20gJy4vQmFzZURpc3BsYXknO1xuaW1wb3J0IHsgZ2V0Q29sb3JzIH0gZnJvbSAnLi4vdXRpbHMvZGlzcGxheS11dGlscyc7XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICByYWRpdXM6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIG1pbjogMCxcbiAgICBkZWZhdWx0OiAwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9XG4gIH0sXG4gIGxpbmU6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgY29sb3JzOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogbnVsbCxcbiAgfVxufVxuXG5cbi8qKlxuICogQnJlYWtwb2ludCBGdW5jdGlvbiwgZGlzcGxheSBhIHN0cmVhbSBvZiB0eXBlIGB2ZWN0b3JgLlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y2xpZW50LnNpbmtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5jb2xvcnM9bnVsbF0gLSBBcnJheSBvZiBjb2xvcnMgZm9yIGVhY2ggaW5kZXggb2YgdGhlXG4gKiAgdmVjdG9yLiBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMucmFkaXVzPTBdIC0gUmFkaXVzIG9mIHRoZSBkb3QgYXQgZWFjaCB2YWx1ZS5cbiAqICBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubGluZT10cnVlXSAtIERpc3BsYXkgYSBsaW5lIGJldHdlZW4gZWFjaCBjb25zZWN1dGl2ZVxuICogIHZhbHVlcyBvZiB0aGUgdmVjdG9yLiBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWluPS0xXSAtIE1pbmltdW0gdmFsdWUgcmVwcmVzZW50ZWQgaW4gdGhlIGNhbnZhcy5cbiAqICBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4PTFdIC0gTWF4aW11bSB2YWx1ZSByZXByZXNlbnRlZCBpbiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy53aWR0aD0zMDBdIC0gV2lkdGggb2YgdGhlIGNhbnZhcy5cbiAqICBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuaGVpZ2h0PTE1MF0gLSBIZWlnaHQgb2YgdGhlIGNhbnZhcy5cbiAqICBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge0VsZW1lbnR8Q1NTU2VsZWN0b3J9IFtvcHRpb25zLmNvbnRhaW5lcj1udWxsXSAtIENvbnRhaW5lciBlbGVtZW50XG4gKiAgaW4gd2hpY2ggdG8gaW5zZXJ0IHRoZSBjYW52YXMuIF9jb25zdGFudCBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge0VsZW1lbnR8Q1NTU2VsZWN0b3J9IFtvcHRpb25zLmNhbnZhcz1udWxsXSAtIENhbnZhcyBlbGVtZW50XG4gKiAgaW4gd2hpY2ggdG8gZHJhdy4gX2NvbnN0YW50IHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5kdXJhdGlvbj0xXSAtIER1cmF0aW9uIChpbiBzZWNvbmRzKSByZXByZXNlbnRlZCBpblxuICogIHRoZSBjYW52YXMuIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5yZWZlcmVuY2VUaW1lPW51bGxdIC0gT3B0aW9ubmFsIHJlZmVyZW5jZSB0aW1lIHRoZVxuICogIGRpc3BsYXkgc2hvdWxkIGNvbnNpZGVyZXIgYXMgdGhlIG9yaWdpbi4gSXMgb25seSB1c2VmdWxsIHdoZW4gc3luY2hyb25pemluZ1xuICogIHNldmVyYWwgZGlzcGxheSB1c2luZyB0aGUgYERpc3BsYXlTeW5jYCBjbGFzcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVTaXplOiAyLFxuICogICBmcmFtZVJhdGU6IDAuMSxcbiAqICAgZnJhbWVUeXBlOiAndmVjdG9yJ1xuICogfSk7XG4gKlxuICogY29uc3QgYnBmID0gbmV3IGxmby5zaW5rLkJwZkRpc3BsYXkoe1xuICogICBjYW52YXM6ICcjYnBmJyxcbiAqICAgZHVyYXRpb246IDEwLFxuICogfSk7XG4gKlxuICogZXZlbnRJbi5jb25uZWN0KGJwZik7XG4gKiBldmVudEluLnN0YXJ0KCk7XG4gKlxuICogbGV0IHRpbWUgPSAwO1xuICogY29uc3QgZHQgPSAwLjE7XG4gKlxuICogKGZ1bmN0aW9uIGdlbmVyYXRlRGF0YSgpIHtcbiAqICAgZXZlbnRJbi5wcm9jZXNzKHRpbWUsIFtNYXRoLnJhbmRvbSgpICogMiAtIDEsIE1hdGgucmFuZG9tKCkgKiAyIC0gMV0pO1xuICogICB0aW1lICs9IGR0O1xuICpcbiAqICAgc2V0VGltZW91dChnZW5lcmF0ZURhdGEsIGR0ICogMTAwMCk7XG4gKiB9KCkpO1xuICovXG5jbGFzcyBCcGZEaXNwbGF5IGV4dGVuZHMgQmFzZURpc3BsYXkge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy5wcmV2RnJhbWUgPSBudWxsO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIGdldE1pbmltdW1GcmFtZVdpZHRoKCkge1xuICAgIHJldHVybiB0aGlzLnBhcmFtcy5nZXQoJ3JhZGl1cycpO1xuICB9XG5cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcblxuICAgIHRoaXMucHJldkZyYW1lID0gbnVsbDtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICBpZiAodGhpcy5wYXJhbXMuZ2V0KCdjb2xvcnMnKSA9PT0gbnVsbClcbiAgICAgIHRoaXMucGFyYW1zLnNldCgnY29sb3JzJywgZ2V0Q29sb3JzKCdicGYnLCB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUpKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSwgZnJhbWVXaWR0aCwgcGl4ZWxzU2luY2VMYXN0RnJhbWUpIHtcbiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLnBhcmFtcy5nZXQoJ2NvbG9ycycpO1xuICAgIGNvbnN0IHJhZGl1cyA9IHRoaXMucGFyYW1zLmdldCgncmFkaXVzJyk7XG4gICAgY29uc3QgZHJhd0xpbmUgPSB0aGlzLnBhcmFtcy5nZXQoJ2xpbmUnKTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgZGF0YSA9IGZyYW1lLmRhdGE7XG4gICAgY29uc3QgcHJldkRhdGEgPSB0aGlzLnByZXZGcmFtZSA/IHRoaXMucHJldkZyYW1lLmRhdGEgOiBudWxsO1xuXG4gICAgY3R4LnNhdmUoKTtcblxuICAgIGZvciAobGV0IGkgPSAwLCBsID0gZnJhbWVTaXplOyBpIDwgbDsgaSsrKSB7XG4gICAgICBjb25zdCBwb3NZID0gdGhpcy5nZXRZUG9zaXRpb24oZGF0YVtpXSk7XG4gICAgICBjb25zdCBjb2xvciA9IGNvbG9yc1tpXTtcblxuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gY29sb3I7XG4gICAgICBjdHguZmlsbFN0eWxlID0gY29sb3I7XG5cbiAgICAgIGlmIChwcmV2RGF0YSAmJiBkcmF3TGluZSkge1xuICAgICAgICBjb25zdCBsYXN0UG9zWSA9IHRoaXMuZ2V0WVBvc2l0aW9uKHByZXZEYXRhW2ldKTtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHgubW92ZVRvKC1waXhlbHNTaW5jZUxhc3RGcmFtZSwgbGFzdFBvc1kpO1xuICAgICAgICBjdHgubGluZVRvKDAsIHBvc1kpO1xuICAgICAgICBjdHguc3Ryb2tlKCk7XG4gICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJhZGl1cyA+IDApIHtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHguYXJjKDAsIHBvc1ksIHJhZGl1cywgMCwgTWF0aC5QSSAqIDIsIGZhbHNlKTtcbiAgICAgICAgY3R4LmZpbGwoKTtcbiAgICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgfVxuXG4gICAgfVxuXG4gICAgY3R4LnJlc3RvcmUoKTtcblxuICAgIHRoaXMucHJldkZyYW1lID0gZnJhbWU7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQnBmRGlzcGxheTtcbiIsImltcG9ydCBCYXNlRGlzcGxheSBmcm9tICcuL0Jhc2VEaXNwbGF5JztcbmltcG9ydCB7IGdldENvbG9ycyB9IGZyb20gJy4uL3V0aWxzL2Rpc3BsYXktdXRpbHMnO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgdGhyZXNob2xkOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICB0aHJlc2hvbGRJbmRleDoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiAwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBjb2xvcjoge1xuICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIGRlZmF1bHQ6IGdldENvbG9ycygnbWFya2VyJyksXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH1cbn07XG5cbi8qKlxuICogRGlzcGxheSBhIG1hcmtlciBhY2NvcmRpbmcgdG8gYSBgdmVjdG9yYCBpbnB1dCBmcmFtZS5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNsaWVudC5zaW5rXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5jb2xvciAtIENvbG9yIG9mIHRoZSBtYXJrZXIuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGhyZXNob2xkSW5kZXg9MF0gLSBJbmRleCBvZiB0aGUgaW5jb21taW5nIGZyYW1lXG4gKiAgZGF0YSB0byBjb21wYXJlIGFnYWluc3QgdGhlIHRocmVzaG9sZC4gX1Nob3VsZCBiZSB1c2VkIGluIGNvbmpvbmN0aW9uIHdpdGhcbiAqICBgdGhyZXNob2xkYF8uXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGhyZXNob2xkPW51bGxdIC0gTWluaW11bSB2YWx1ZSB0aGUgaW5jb21taW5nIHZhbHVlXG4gKiAgbXVzdCBoYXZlIHRvIHRyaWdnZXIgdGhlIGRpc3BsYXkgb2YgYSBtYXJrZXIuIElmIG51bGwgZWFjaCBpbmNvbW1pbmcgZXZlbnRcbiAqICB0cmlnZ2VycyBhIG1hcmtlci4gX1Nob3VsZCBiZSB1c2VkIGluIGNvbmpvbmN0aW9uIHdpdGggYHRocmVzaG9sZEluZGV4YF8uXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMud2lkdGg9MzAwXSAtIFdpZHRoIG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmhlaWdodD0xNTBdIC0gSGVpZ2h0IG9mIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jb250YWluZXI9bnVsbF0gLSBDb250YWluZXIgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGluc2VydCB0aGUgY2FudmFzLiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jYW52YXM9bnVsbF0gLSBDYW52YXMgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGRyYXcuIF9jb25zdGFudCBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZHVyYXRpb249MV0gLSBEdXJhdGlvbiAoaW4gc2Vjb25kcykgcmVwcmVzZW50ZWQgaW5cbiAqICB0aGUgY2FudmFzLiBUaGlzIHBhcmFtZXRlciBvbmx5IGV4aXN0cyBmb3Igb3BlcmF0b3JzIHRoYXQgZGlzcGxheSBzZXZlcmFsXG4gKiAgY29uc2VjdXRpdmUgZnJhbWVzIG9uIHRoZSBjYW52YXMuIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5yZWZlcmVuY2VUaW1lPW51bGxdIC0gT3B0aW9ubmFsIHJlZmVyZW5jZSB0aW1lIHRoZVxuICogIGRpc3BsYXkgc2hvdWxkIGNvbnNpZGVyZXIgYXMgdGhlIG9yaWdpbi4gSXMgb25seSB1c2VmdWxsIHdoZW4gc3luY2hyb25pemluZ1xuICogIHNldmVyYWwgZGlzcGxheSB1c2luZyB0aGUgYERpc3BsYXlTeW5jYCBjbGFzcy4gVGhpcyBwYXJhbWV0ZXIgb25seSBleGlzdHNcbiAqICBmb3Igb3BlcmF0b3JzIHRoYXQgZGlzcGxheSBzZXZlcmFsIGNvbnNlY3V0aXZlIGZyYW1lcyBvbiB0aGUgY2FudmFzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gKlxuICogY29uc3QgZXZlbnRJbiA9IG5ldyBsZm8uc291cmNlLkV2ZW50SW4oe1xuICogICBmcmFtZVR5cGU6ICdzY2FsYXInLFxuICogfSk7XG4gKlxuICogY29uc3QgbWFya2VyID0gbmV3IGxmby5zaW5rLk1hcmtlckRpc3BsYXkoe1xuICogICBjYW52YXM6ICcjbWFya2VyJyxcbiAqICAgdGhyZXNob2xkOiAwLjUsXG4gKiB9KTtcbiAqXG4gKiBldmVudEluLmNvbm5lY3QobWFya2VyKTtcbiAqIGV2ZW50SW4uc3RhcnQoKTtcbiAqXG4gKiBsZXQgdGltZSA9IDA7XG4gKiBjb25zdCBwZXJpb2QgPSAxO1xuICpcbiAqIChmdW5jdGlvbiBnZW5lcmF0ZURhdGEoKSB7XG4gKiAgIGV2ZW50SW4ucHJvY2Vzcyh0aW1lLCBNYXRoLnJhbmRvbSgpKTtcbiAqXG4gKiAgIHRpbWUgKz0gcGVyaW9kO1xuICogICBzZXRUaW1lb3V0KGdlbmVyYXRlRGF0YSwgcGVyaW9kICogMTAwMCk7XG4gKiB9KCkpO1xuICovXG5jbGFzcyBNYXJrZXJEaXNwbGF5IGV4dGVuZHMgQmFzZURpc3BsYXkge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSwgZnJhbWVXaWR0aCwgcGl4ZWxzU2luY2VMYXN0RnJhbWUpIHtcbiAgICBjb25zdCBjb2xvciA9IHRoaXMucGFyYW1zLmdldCgnY29sb3InKTtcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLnBhcmFtcy5nZXQoJ3RocmVzaG9sZCcpO1xuICAgIGNvbnN0IHRocmVzaG9sZEluZGV4ID0gdGhpcy5wYXJhbXMuZ2V0KCd0aHJlc2hvbGRJbmRleCcpO1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgIGNvbnN0IGhlaWdodCA9IGN0eC5oZWlnaHQ7XG4gICAgY29uc3QgdmFsdWUgPSBmcmFtZS5kYXRhW3RocmVzaG9sZEluZGV4XTtcblxuICAgIGlmICh0aHJlc2hvbGQgPT09IG51bGwgfHwgdmFsdWUgPj0gdGhyZXNob2xkKSB7XG4gICAgICBsZXQgeU1pbiA9IHRoaXMuZ2V0WVBvc2l0aW9uKHRoaXMucGFyYW1zLmdldCgnbWluJykpO1xuICAgICAgbGV0IHlNYXggPSB0aGlzLmdldFlQb3NpdGlvbih0aGlzLnBhcmFtcy5nZXQoJ21heCcpKTtcblxuICAgICAgaWYgKHlNaW4gPiB5TWF4KSB7XG4gICAgICAgIGNvbnN0IHYgPSB5TWF4O1xuICAgICAgICB5TWF4ID0geU1pbjtcbiAgICAgICAgeU1pbiA9IHY7XG4gICAgICB9XG5cbiAgICAgIGN0eC5zYXZlKCk7XG4gICAgICBjdHguZmlsbFN0eWxlID0gY29sb3I7XG4gICAgICBjdHguZmlsbFJlY3QoMCwgeU1pbiwgMSwgeU1heCk7XG4gICAgICBjdHgucmVzdG9yZSgpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNYXJrZXJEaXNwbGF5O1xuIiwiaW1wb3J0IEJhc2VEaXNwbGF5IGZyb20gJy4vQmFzZURpc3BsYXknO1xuaW1wb3J0IHsgZ2V0Q29sb3JzIH0gZnJvbSAnLi4vdXRpbHMvZGlzcGxheS11dGlscyc7XG5cbmNvbnN0IGZsb29yID0gTWF0aC5mbG9vcjtcbmNvbnN0IGNlaWwgPSBNYXRoLmNlaWw7XG5cbmZ1bmN0aW9uIGRvd25TYW1wbGUoZGF0YSwgdGFyZ2V0TGVuZ3RoKSB7XG4gIGNvbnN0IGxlbmd0aCA9IGRhdGEubGVuZ3RoO1xuICBjb25zdCBob3AgPSBsZW5ndGggLyB0YXJnZXRMZW5ndGg7XG4gIGNvbnN0IHRhcmdldCA9IG5ldyBGbG9hdDMyQXJyYXkodGFyZ2V0TGVuZ3RoKTtcbiAgbGV0IGNvdW50ZXIgPSAwO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0TGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBpbmRleCA9IGZsb29yKGNvdW50ZXIpO1xuICAgIGNvbnN0IHBoYXNlID0gY291bnRlciAtIGluZGV4O1xuICAgIGNvbnN0IHByZXYgPSBkYXRhW2luZGV4XTtcbiAgICBjb25zdCBuZXh0ID0gZGF0YVtpbmRleCArIDFdO1xuXG4gICAgdGFyZ2V0W2ldID0gKG5leHQgLSBwcmV2KSAqIHBoYXNlICsgcHJldjtcbiAgICBjb3VudGVyICs9IGhvcDtcbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBjb2xvcjoge1xuICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIGRlZmF1bHQ6IGdldENvbG9ycygnc2lnbmFsJyksXG4gICAgbnVsbGFibGU6IHRydWUsXG4gIH0sXG59O1xuXG4vKipcbiAqIERpc3BsYXkgYSBzdHJlYW0gb2YgdHlwZSBgc2lnbmFsYCBvbiBhIGNhbnZhcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5jb2xvcj0nIzAwZTYwMCddIC0gQ29sb3Igb2YgdGhlIHNpZ25hbC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW49LTFdIC0gTWluaW11bSB2YWx1ZSByZXByZXNlbnRlZCBpbiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5tYXg9MV0gLSBNYXhpbXVtIHZhbHVlIHJlcHJlc2VudGVkIGluIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLndpZHRoPTMwMF0gLSBXaWR0aCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5oZWlnaHQ9MTUwXSAtIEhlaWdodCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY29udGFpbmVyPW51bGxdIC0gQ29udGFpbmVyIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBpbnNlcnQgdGhlIGNhbnZhcy4gX2NvbnN0YW50IHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY2FudmFzPW51bGxdIC0gQ2FudmFzIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBkcmF3LiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmR1cmF0aW9uPTFdIC0gRHVyYXRpb24gKGluIHNlY29uZHMpIHJlcHJlc2VudGVkIGluXG4gKiAgdGhlIGNhbnZhcy4gVGhpcyBwYXJhbWV0ZXIgb25seSBleGlzdHMgZm9yIG9wZXJhdG9ycyB0aGF0IGRpc3BsYXkgc2V2ZXJhbFxuICogIGNvbnNlY3V0aXZlIGZyYW1lcyBvbiB0aGUgY2FudmFzLiBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucmVmZXJlbmNlVGltZT1udWxsXSAtIE9wdGlvbm5hbCByZWZlcmVuY2UgdGltZSB0aGVcbiAqICBkaXNwbGF5IHNob3VsZCBjb25zaWRlcmVyIGFzIHRoZSBvcmlnaW4uIElzIG9ubHkgdXNlZnVsbCB3aGVuIHN5bmNocm9uaXppbmdcbiAqICBzZXZlcmFsIGRpc3BsYXkgdXNpbmcgdGhlIGBEaXNwbGF5U3luY2AgY2xhc3MuIFRoaXMgcGFyYW1ldGVyIG9ubHkgZXhpc3RzXG4gKiAgZm9yIG9wZXJhdG9ycyB0aGF0IGRpc3BsYXkgc2V2ZXJhbCBjb25zZWN1dGl2ZSBmcmFtZXMgb24gdGhlIGNhbnZhcy5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNsaWVudC5zaW5rXG4gKlxuICogQGV4YW1wbGVcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVUeXBlOiAnc2lnbmFsJyxcbiAqICAgc2FtcGxlUmF0ZTogOCxcbiAqICAgZnJhbWVTaXplOiA0LFxuICogfSk7XG4gKlxuICogY29uc3Qgc2lnbmFsRGlzcGxheSA9IG5ldyBsZm8uc2luay5TaWduYWxEaXNwbGF5KHtcbiAqICAgY2FudmFzOiAnI3NpZ25hbC1jYW52YXMnLFxuICogfSk7XG4gKlxuICogZXZlbnRJbi5jb25uZWN0KHNpZ25hbERpc3BsYXkpO1xuICogZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqIC8vIHB1c2ggdHJpYW5nbGUgc2lnbmFsIGluIHRoZSBncmFwaFxuICogZXZlbnRJbi5wcm9jZXNzKDAsIFswLCAwLjUsIDEsIDAuNV0pO1xuICogZXZlbnRJbi5wcm9jZXNzKDAuNSwgWzAsIC0wLjUsIC0xLCAtMC41XSk7XG4gKiAvLyAuLi5cbiAqL1xuY2xhc3MgU2lnbmFsRGlzcGxheSBleHRlbmRzIEJhc2VEaXNwbGF5IHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zLCB0cnVlKTtcblxuICAgIHRoaXMubGFzdFBvc1kgPSBudWxsO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUsIGZyYW1lV2lkdGgsIHBpeGVsc1NpbmNlTGFzdEZyYW1lKSB7XG4gICAgY29uc3QgY29sb3IgPSB0aGlzLnBhcmFtcy5nZXQoJ2NvbG9yJyk7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuICAgIGxldCBkYXRhID0gZnJhbWUuZGF0YTtcblxuICAgIGlmIChmcmFtZVdpZHRoIDwgZnJhbWVTaXplKVxuICAgICAgZGF0YSA9IGRvd25TYW1wbGUoZGF0YSwgZnJhbWVXaWR0aCk7XG5cbiAgICBjb25zdCBsZW5ndGggPSBkYXRhLmxlbmd0aDtcbiAgICBjb25zdCBob3BYID0gZnJhbWVXaWR0aCAvIGxlbmd0aDtcbiAgICBsZXQgcG9zWCA9IDA7XG4gICAgbGV0IGxhc3RZID0gdGhpcy5sYXN0UG9zWTtcblxuICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgcG9zWSA9IHRoaXMuZ2V0WVBvc2l0aW9uKGRhdGFbaV0pO1xuXG4gICAgICBpZiAobGFzdFkgPT09IG51bGwpIHtcbiAgICAgICAgY3R4Lm1vdmVUbyhwb3NYLCBwb3NZKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChpID09PSAwKVxuICAgICAgICAgIGN0eC5tb3ZlVG8oLWhvcFgsIGxhc3RZKTtcblxuICAgICAgICBjdHgubGluZVRvKHBvc1gsIHBvc1kpO1xuICAgICAgfVxuXG4gICAgICBwb3NYICs9IGhvcFg7XG4gICAgICBsYXN0WSA9IHBvc1k7XG4gICAgfVxuXG4gICAgY3R4LnN0cm9rZSgpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcblxuICAgIHRoaXMubGFzdFBvc1kgPSBsYXN0WTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTaWduYWxEaXNwbGF5O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcbmltcG9ydCB7IG9wY29kZXMsIGVuY29kZXJzLCBkZWNvZGVycyB9IGZyb20gJy4uLy4uL2NvbW1vbi91dGlscy93c1V0aWxzJztcblxuY29uc3QgcGFyYW1ldGVycyA9IHtcbiAgcG9ydDoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiA4MDAwLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICB1cmw6IHtcbiAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9XG59XG5cbi8qKlxuICogU2VuZCBhbiBsZm8gZnJhbWUgYXMgYSBzb2NrZXQgbWVzc2FnZSB0byBhIGBub2RlLnNvdXJjZS5Tb2NrZXRSZWNlaXZlYFxuICogaW5zdGFuY2UuXG4gKlxuICogPHAgY2xhc3M9XCJ3YXJuaW5nXCI+RXhwZXJpbWVudGFsPC9wPlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y2xpZW50LnNpbmtcbiAqXG4gKiBAZXhhbXBsZVxuICogY29uc3QgZXZlbnRJbiA9IG5ldyBsZm8uc291cmNlLkV2ZW50SW4oe1xuICogICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxuICogICBmcmFtZVNpemU6IDIsXG4gKiAgIGZyYW1lUmF0ZTogMSxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNvY2tldFNlbmQgPSBuZXcgbGZvLnNpbmsuU29ja2V0U2VuZCh7XG4gKiAgIHBvcnQ6IDMwMDBcbiAqIH0pO1xuICpcbiAqIGV2ZW50SW4uY29ubmVjdChzb2NrZXRTZW5kKTtcbiAqXG4gKiBldmVudEluLmluaXQoKS50aGVuKCgpID0+IHtcbiAqICAgZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqICAgbGV0IHRpbWUgPSAwO1xuICpcbiAqICAgKGZ1bmN0aW9uIGNyZWF0ZUZyYW1lKCkge1xuICogICAgIGV2ZW50SW4ucHJvY2Vzcyh0aW1lLCBbTWF0aC5yYW5kb20oKSwgTWF0aC5yYW5kb20oKV0sIHsgdGVzdDogdHJ1ZSB9KTtcbiAqICAgICB0aW1lICs9IDE7XG4gKlxuICogICAgIHNldFRpbWVvdXQoY3JlYXRlRnJhbWUsIDEwMDApO1xuICogICB9KCkpO1xuICogfSk7XG4gKi9cbmNsYXNzIFNvY2tldFNlbmQgZXh0ZW5kcyBCYXNlTGZvIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIocGFyYW1ldGVycywgb3B0aW9ucyk7XG5cbiAgICBjb25zdCBwcm90b2NvbCA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbC5yZXBsYWNlKC9eaHR0cC8sICd3cycpO1xuICAgIGNvbnN0IGFkZHJlc3MgPSB0aGlzLnBhcmFtcy5nZXQoJ3VybCcpIHx8wqB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWU7XG4gICAgY29uc3QgcG9ydCA9IHRoaXMucGFyYW1zLmdldCgncG9ydCcpIHx8ICcnOyAvLyBldmVyeXRoaW5nIGZhbHN5IGJlY29tZXMgJydcbiAgICBjb25zdCBzb2NrZXRBZGRyZXNzID0gYCR7cHJvdG9jb2x9Ly8ke2FkZHJlc3N9OiR7cG9ydH1gO1xuXG4gICAgdGhpcy5zb2NrZXQgPSBuZXcgV2ViU29ja2V0KHNvY2tldEFkZHJlc3MpO1xuICAgIHRoaXMuc29ja2V0LmJpbmFyeVR5cGUgPSAnYXJyYXlidWZmZXInO1xuXG4gICAgdGhpcy5vcGVuZWRQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5zb2NrZXQub25vcGVuID0gcmVzb2x2ZTtcbiAgICB9KTtcblxuICAgIHRoaXMuc29ja2V0Lm9uZXJyb3IgPSAoZXJyKSA9PiBjb25zb2xlLmVycm9yKGVyci5zdGFjayk7XG4gIH1cblxuICBpbml0TW9kdWxlKCkge1xuICAgIC8vIHNlbmQgYSBJTklUX01PRFVMRV9SRVEgYW5kIHdhaXQgZm9yIElOSVRfTU9EVUxFX0FDS1xuICAgIC8vIG5vIG5lZWQgdG8gZ2V0IGNoaWxkcmVuIHByb21pc2VzIGFzIHdlIGFyZSBpbiBhIGxlZWZcbiAgICByZXR1cm4gdGhpcy5vcGVuZWRQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5zb2NrZXQub25tZXNzYWdlID0gKGUpID0+IHtcbiAgICAgICAgICBjb25zdCBvcGNvZGUgPSBkZWNvZGVycy5vcGNvZGUoZS5kYXRhKTtcblxuICAgICAgICAgIGlmIChvcGNvZGUgPT09IG9wY29kZXMuSU5JVF9NT0RVTEVfQUNLKVxuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnVmZmVyID0gZW5jb2RlcnMuaW5pdE1vZHVsZVJlcSgpO1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKGJ1ZmZlcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHN1cGVyLnByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICBjb25zdCBidWZmZXIgPSBlbmNvZGVycy5zdHJlYW1QYXJhbXModGhpcy5zdHJlYW1QYXJhbXMpO1xuICAgIHRoaXMuc29ja2V0LnNlbmQoYnVmZmVyKTtcbiAgfVxuXG4gIHJlc2V0U3RyZWFtKCkge1xuICAgIHN1cGVyLnJlc2V0U3RyZWFtKCk7XG5cbiAgICBjb25zdCBidWZmZXIgPSBlbmNvZGVycy5yZXNldFN0cmVhbSgpO1xuICAgIHRoaXMuc29ja2V0LnNlbmQoYnVmZmVyKTtcbiAgfVxuXG4gICAgLyoqIEBwcml2YXRlICovXG4gIGZpbmFsaXplU3RyZWFtKGVuZFRpbWUpIHtcbiAgICBzdXBlci5maW5hbGl6ZVN0cmVhbShlbmRUaW1lKTtcblxuICAgIGNvbnN0IGJ1ZmZlciA9IGVuY29kZXJzLmZpbmFsaXplU3RyZWFtKGVuZFRpbWUpO1xuICAgIHRoaXMuc29ja2V0LnNlbmQoYnVmZmVyKTtcbiAgfVxuXG4gIC8vIHByb2Nlc3MgYW55IHR5cGVcbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTY2FsYXIoKSB7fVxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcigpIHt9XG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKCkge31cblxuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgdGhpcy5mcmFtZS50aW1lID0gZnJhbWUudGltZTtcbiAgICB0aGlzLmZyYW1lLmRhdGEuc2V0KGZyYW1lLmRhdGEsIDApO1xuICAgIHRoaXMuZnJhbWUubWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcblxuICAgIGNvbnN0IGJ1ZmZlciA9IGVuY29kZXJzLnByb2Nlc3NGcmFtZSh0aGlzLmZyYW1lLCBmcmFtZVNpemUpO1xuICAgIHRoaXMuc29ja2V0LnNlbmQoYnVmZmVyKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTb2NrZXRTZW5kO1xuIiwiaW1wb3J0IEJhc2VEaXNwbGF5IGZyb20gJy4vQmFzZURpc3BsYXknO1xuaW1wb3J0IEZmdCBmcm9tICcuLi8uLi9jb21tb24vb3BlcmF0b3IvRmZ0JztcbmltcG9ydCB7IGdldENvbG9ycyB9IGZyb20gJy4uL3V0aWxzL2Rpc3BsYXktdXRpbHMnO1xuXG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBzY2FsZToge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgY29sb3I6IHtcbiAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICBkZWZhdWx0OiBnZXRDb2xvcnMoJ3NwZWN0cnVtJyksXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG4gIG1pbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogLTgwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBtYXg6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDYsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH1cbn07XG5cblxuLyoqXG4gKiBEaXNwbGF5IHRoZSBzcGVjdHJ1bSBvZiB0aGUgaW5jb21taW5nIGBzaWduYWxgIGlucHV0LlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y2xpZW50LnNpbmtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5zY2FsZT0xXSAtIFNjYWxlIGRpc3BsYXkgb2YgdGhlIHNwZWN0cm9ncmFtLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNvbG9yPW51bGxdIC0gQ29sb3Igb2YgdGhlIHNwZWN0cm9ncmFtLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1pbj0tODBdIC0gTWluaW11bSBkaXNwbGF5ZWQgdmFsdWUgKGluIGRCKS5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5tYXg9Nl0gLSBNYXhpbXVtIGRpc3BsYXllZCB2YWx1ZSAoaW4gZEIpLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLndpZHRoPTMwMF0gLSBXaWR0aCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5oZWlnaHQ9MTUwXSAtIEhlaWdodCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY29udGFpbmVyPW51bGxdIC0gQ29udGFpbmVyIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBpbnNlcnQgdGhlIGNhbnZhcy4gX2NvbnN0YW50IHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY2FudmFzPW51bGxdIC0gQ2FudmFzIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBkcmF3LiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICpcbiAqIEB0b2RvIC0gZXhwb3NlIG1vcmUgYGZmdGAgY29uZmlnIG9wdGlvbnNcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IGF1ZGlvQ29udGV4dCA9IG5ldyBBdWRpb0NvbnRleHQoKTtcbiAqXG4gKiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzXG4gKiAgIC5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSB9KVxuICogICAudGhlbihpbml0KVxuICogICAuY2F0Y2goKGVycikgPT4gY29uc29sZS5lcnJvcihlcnIuc3RhY2spKTtcbiAqXG4gKiBmdW5jdGlvbiBpbml0KHN0cmVhbSkge1xuICogICBjb25zdCBzb3VyY2UgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAqXG4gKiAgIGNvbnN0IGF1ZGlvSW5Ob2RlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9Jbk5vZGUoe1xuICogICAgIGF1ZGlvQ29udGV4dDogYXVkaW9Db250ZXh0LFxuICogICAgIHNvdXJjZU5vZGU6IHNvdXJjZSxcbiAqICAgfSk7XG4gKlxuICogICBjb25zdCBzcGVjdHJ1bSA9IG5ldyBsZm8uc2luay5TcGVjdHJ1bURpc3BsYXkoe1xuICogICAgIGNhbnZhczogJyNzcGVjdHJ1bScsXG4gKiAgIH0pO1xuICpcbiAqICAgYXVkaW9Jbk5vZGUuY29ubmVjdChzcGVjdHJ1bSk7XG4gKiAgIGF1ZGlvSW5Ob2RlLnN0YXJ0KCk7XG4gKiB9XG4gKi9cbmNsYXNzIFNwZWN0cnVtRGlzcGxheSBleHRlbmRzIEJhc2VEaXNwbGF5IHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMsIGZhbHNlKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICB0aGlzLmZmdCA9IG5ldyBGZnQoe1xuICAgICAgc2l6ZTogdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplLFxuICAgICAgd2luZG93OiAnaGFubicsXG4gICAgICBub3JtOiAnbGluZWFyJyxcbiAgICB9KTtcblxuICAgIHRoaXMuZmZ0LmluaXRTdHJlYW0odGhpcy5zdHJlYW1QYXJhbXMpO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgY29uc3QgYmlucyA9IHRoaXMuZmZ0LmlucHV0U2lnbmFsKGZyYW1lLmRhdGEpO1xuICAgIGNvbnN0IG5ickJpbnMgPSBiaW5zLmxlbmd0aDtcblxuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5jYW52YXNXaWR0aDtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmNhbnZhc0hlaWdodDtcbiAgICBjb25zdCBzY2FsZSA9IHRoaXMucGFyYW1zLmdldCgnc2NhbGUnKTtcblxuICAgIGNvbnN0IGJpbldpZHRoID0gd2lkdGggLyBuYnJCaW5zO1xuICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4O1xuXG4gICAgY3R4LmZpbGxTdHlsZSA9IHRoaXMucGFyYW1zLmdldCgnY29sb3InKTtcblxuICAgIC8vIGVycm9yIGhhbmRsaW5nIG5lZWRzIHJldmlldy4uLlxuICAgIGxldCBlcnJvciA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ickJpbnM7IGkrKykge1xuICAgICAgY29uc3QgeDFGbG9hdCA9IGkgKiBiaW5XaWR0aCArIGVycm9yO1xuICAgICAgY29uc3QgeDFJbnQgPSBNYXRoLnJvdW5kKHgxRmxvYXQpO1xuICAgICAgY29uc3QgeDJGbG9hdCA9IHgxRmxvYXQgKyAoYmluV2lkdGggLSBlcnJvcik7XG4gICAgICBjb25zdCB4MkludCA9IE1hdGgucm91bmQoeDJGbG9hdCk7XG5cbiAgICAgIGVycm9yID0geDJJbnQgLSB4MkZsb2F0O1xuXG4gICAgICBpZiAoeDFJbnQgIT09IHgySW50KSB7XG4gICAgICAgIGNvbnN0IHdpZHRoID0geDJJbnQgLSB4MUludDtcbiAgICAgICAgY29uc3QgZGIgPSAyMCAqIE1hdGgubG9nMTAoYmluc1tpXSk7XG4gICAgICAgIGNvbnN0IHkgPSB0aGlzLmdldFlQb3NpdGlvbihkYiAqIHNjYWxlKTtcbiAgICAgICAgY3R4LmZpbGxSZWN0KHgxSW50LCB5LCB3aWR0aCwgaGVpZ2h0IC0geSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlcnJvciAtPSBiaW5XaWR0aDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgU3BlY3RydW1EaXNwbGF5O1xuIiwiaW1wb3J0IEJhc2VEaXNwbGF5IGZyb20gJy4vQmFzZURpc3BsYXknO1xuaW1wb3J0IHsgZ2V0Q29sb3JzLCBnZXRIdWUsIGhleFRvUkdCIH0gZnJvbSAnLi4vdXRpbHMvZGlzcGxheS11dGlscyc7XG5cblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIGNvbG9yOiB7XG4gICAgdHlwZTogJ3N0cmluZycsXG4gICAgZGVmYXVsdDogZ2V0Q29sb3JzKCd0cmFjZScpLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBjb2xvclNjaGVtZToge1xuICAgIHR5cGU6ICdlbnVtJyxcbiAgICBkZWZhdWx0OiAnbm9uZScsXG4gICAgbGlzdDogWydub25lJywgJ2h1ZScsICdvcGFjaXR5J10sXG4gIH0sXG59O1xuXG4vKipcbiAqIERpc3BsYXkgYSByYW5nZSB2YWx1ZSBhcm91bmQgYSBtZWFuIHZhbHVlIChmb3IgZXhhbXBsZSBtZWFuXG4gKiBhbmQgc3RhbmRhcnQgZGV2aWF0aW9uKS5cbiAqXG4gKiBUaGlzIHNpbmsgY2FuIGhhbmRsZSBpbnB1dCBvZiB0eXBlIGB2ZWN0b3JgIG9mIGZyYW1lU2l6ZSA+PSAyLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNvbG9yPSdvcmFuZ2UnXSAtIENvbG9yLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNvbG9yU2NoZW1lPSdub25lJ10gLSBJZiBhIHRoaXJkIHZhbHVlIGlzIGF2YWlsYWJsZVxuICogIGluIHRoZSBpbnB1dCwgY2FuIGJlIHVzZWQgdG8gY29udHJvbCB0aGUgb3BhY2l0eSBvciB0aGUgaHVlLiBJZiBpbnB1dCBmcmFtZVxuICogIHNpemUgaXMgMiwgdGhpcyBwYXJhbSBpcyBhdXRvbWF0aWNhbGx5IHNldCB0byBgbm9uZWBcbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW49LTFdIC0gTWluaW11bSB2YWx1ZSByZXByZXNlbnRlZCBpbiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5tYXg9MV0gLSBNYXhpbXVtIHZhbHVlIHJlcHJlc2VudGVkIGluIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLndpZHRoPTMwMF0gLSBXaWR0aCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5oZWlnaHQ9MTUwXSAtIEhlaWdodCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY29udGFpbmVyPW51bGxdIC0gQ29udGFpbmVyIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBpbnNlcnQgdGhlIGNhbnZhcy4gX2NvbnN0YW50IHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY2FudmFzPW51bGxdIC0gQ2FudmFzIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBkcmF3LiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmR1cmF0aW9uPTFdIC0gRHVyYXRpb24gKGluIHNlY29uZHMpIHJlcHJlc2VudGVkIGluXG4gKiAgdGhlIGNhbnZhcy4gX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnJlZmVyZW5jZVRpbWU9bnVsbF0gLSBPcHRpb25uYWwgcmVmZXJlbmNlIHRpbWUgdGhlXG4gKiAgZGlzcGxheSBzaG91bGQgY29uc2lkZXJlciBhcyB0aGUgb3JpZ2luLiBJcyBvbmx5IHVzZWZ1bGwgd2hlbiBzeW5jaHJvbml6aW5nXG4gKiAgc2V2ZXJhbCBkaXNwbGF5IHVzaW5nIHRoZSBgRGlzcGxheVN5bmNgIGNsYXNzLlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y2xpZW50LnNpbmtcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IEF1ZGlvQ29udGV4dCA9ICh3aW5kb3cuQXVkaW9Db250ZXh0IHx8wqB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0KTtcbiAqIGNvbnN0IGF1ZGlvQ29udGV4dCA9IG5ldyBBdWRpb0NvbnRleHQoKTtcbiAqXG4gKiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzXG4gKiAgIC5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSB9KVxuICogICAudGhlbihpbml0KVxuICogICAuY2F0Y2goKGVycikgPT4gY29uc29sZS5lcnJvcihlcnIuc3RhY2spKTtcbiAqXG4gKiBmdW5jdGlvbiBpbml0KHN0cmVhbSkge1xuICogICBjb25zdCBzb3VyY2UgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAqXG4gKiAgIGNvbnN0IGF1ZGlvSW5Ob2RlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9Jbk5vZGUoe1xuICogICAgIHNvdXJjZU5vZGU6IHNvdXJjZSxcbiAqICAgICBhdWRpb0NvbnRleHQ6IGF1ZGlvQ29udGV4dCxcbiAqICAgfSk7XG4gKlxuICogICAvLyBub3Qgc3VyZSBpdCBtYWtlIHNlbnMgYnV0Li4uXG4gKiAgIGNvbnN0IG1lYW5TdGRkZXYgPSBuZXcgbGZvLm9wZXJhdG9yLk1lYW5TdGRkZXYoKTtcbiAqXG4gKiAgIGNvbnN0IHRyYWNlRGlzcGxheSA9IG5ldyBsZm8uc2luay5UcmFjZURpc3BsYXkoe1xuICogICAgIGNhbnZhczogJyN0cmFjZScsXG4gKiAgIH0pO1xuICpcbiAqICAgY29uc3QgbG9nZ2VyID0gbmV3IGxmby5zaW5rLkxvZ2dlcih7IGRhdGE6IHRydWUgfSk7XG4gKlxuICogICBhdWRpb0luTm9kZS5jb25uZWN0KG1lYW5TdGRkZXYpO1xuICogICBtZWFuU3RkZGV2LmNvbm5lY3QodHJhY2VEaXNwbGF5KTtcbiAqXG4gKiAgIGF1ZGlvSW5Ob2RlLnN0YXJ0KCk7XG4gKiB9XG4gKi9cbmNsYXNzIFRyYWNlRGlzcGxheSBleHRlbmRzIEJhc2VEaXNwbGF5IHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy5wcmV2RnJhbWUgPSBudWxsO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIGlmICh0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPT09IDIpXG4gICAgICB0aGlzLnBhcmFtcy5zZXQoJ2NvbG9yU2NoZW1lJywgJ25vbmUnKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSwgZnJhbWVXaWR0aCwgcGl4ZWxzU2luY2VMYXN0RnJhbWUpIHtcbiAgICBjb25zdCBjb2xvclNjaGVtZSA9IHRoaXMucGFyYW1zLmdldCgnY29sb3JTY2hlbWUnKTtcbiAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICBjb25zdCBwcmV2RGF0YSA9IHRoaXMucHJldkZyYW1lID8gdGhpcy5wcmV2RnJhbWUuZGF0YSA6IG51bGw7XG4gICAgY29uc3QgZGF0YSA9IGZyYW1lLmRhdGE7XG5cbiAgICBjb25zdCBoYWxmUmFuZ2UgPSBkYXRhWzFdIC8gMjtcbiAgICBjb25zdCBtZWFuID0gdGhpcy5nZXRZUG9zaXRpb24oZGF0YVswXSk7XG4gICAgY29uc3QgbWluID0gdGhpcy5nZXRZUG9zaXRpb24oZGF0YVswXSAtIGhhbGZSYW5nZSk7XG4gICAgY29uc3QgbWF4ID0gdGhpcy5nZXRZUG9zaXRpb24oZGF0YVswXSArIGhhbGZSYW5nZSk7XG5cbiAgICBsZXQgcHJldkhhbGZSYW5nZTtcbiAgICBsZXQgcHJldk1lYW47XG4gICAgbGV0IHByZXZNaW47XG4gICAgbGV0IHByZXZNYXg7XG5cbiAgICBpZiAocHJldkRhdGEgIT09IG51bGwpIHtcbiAgICAgIHByZXZIYWxmUmFuZ2UgPSBwcmV2RGF0YVsxXSAvIDI7XG4gICAgICBwcmV2TWVhbiA9IHRoaXMuZ2V0WVBvc2l0aW9uKHByZXZEYXRhWzBdKTtcbiAgICAgIHByZXZNaW4gPSB0aGlzLmdldFlQb3NpdGlvbihwcmV2RGF0YVswXSAtIHByZXZIYWxmUmFuZ2UpO1xuICAgICAgcHJldk1heCA9IHRoaXMuZ2V0WVBvc2l0aW9uKHByZXZEYXRhWzBdICsgcHJldkhhbGZSYW5nZSk7XG4gICAgfVxuXG4gICAgY29uc3QgY29sb3IgPSB0aGlzLnBhcmFtcy5nZXQoJ2NvbG9yJyk7XG4gICAgbGV0IGdyYWRpZW50O1xuICAgIGxldCByZ2I7XG5cbiAgICBzd2l0Y2ggKGNvbG9yU2NoZW1lKSB7XG4gICAgICBjYXNlICdub25lJzpcbiAgICAgICAgcmdiID0gaGV4VG9SR0IoY29sb3IpO1xuICAgICAgICBjdHguZmlsbFN0eWxlID0gYHJnYmEoJHtyZ2Iuam9pbignLCcpfSwgMC43KWA7XG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yO1xuICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdodWUnOlxuICAgICAgICBncmFkaWVudCA9IGN0eC5jcmVhdGVMaW5lYXJHcmFkaWVudCgtcGl4ZWxzU2luY2VMYXN0RnJhbWUsIDAsIDAsIDApO1xuXG4gICAgICAgIGlmIChwcmV2RGF0YSlcbiAgICAgICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMCwgYGhzbCgke2dldEh1ZShwcmV2RGF0YVsyXSl9LCAxMDAlLCA1MCUpYCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMCwgYGhzbCgke2dldEh1ZShkYXRhWzJdKX0sIDEwMCUsIDUwJSlgKTtcblxuICAgICAgICBncmFkaWVudC5hZGRDb2xvclN0b3AoMSwgYGhzbCgke2dldEh1ZShkYXRhWzJdKX0sIDEwMCUsIDUwJSlgKTtcbiAgICAgICAgY3R4LmZpbGxTdHlsZSA9IGdyYWRpZW50O1xuICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdvcGFjaXR5JzpcbiAgICAgICAgcmdiID0gaGV4VG9SR0IodGhpcy5wYXJhbXMuZ2V0KCdjb2xvcicpKTtcbiAgICAgICAgZ3JhZGllbnQgPSBjdHguY3JlYXRlTGluZWFyR3JhZGllbnQoLXBpeGVsc1NpbmNlTGFzdEZyYW1lLCAwLCAwLCAwKTtcblxuICAgICAgICBpZiAocHJldkRhdGEpXG4gICAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDAsIGByZ2JhKCR7cmdiLmpvaW4oJywnKX0sICR7cHJldkRhdGFbMl19KWApO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDAsIGByZ2JhKCR7cmdiLmpvaW4oJywnKX0sICR7ZGF0YVsyXX0pYCk7XG5cbiAgICAgICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDEsIGByZ2JhKCR7cmdiLmpvaW4oJywnKX0sICR7ZGF0YVsyXX0pYCk7XG4gICAgICAgIGN0eC5maWxsU3R5bGUgPSBncmFkaWVudDtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGN0eC5zYXZlKCk7XG4gICAgLy8gZHJhdyByYW5nZVxuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICBjdHgubW92ZVRvKDAsIG1lYW4pO1xuICAgIGN0eC5saW5lVG8oMCwgbWF4KTtcblxuICAgIGlmIChwcmV2RGF0YSAhPT0gbnVsbCkge1xuICAgICAgY3R4LmxpbmVUbygtcGl4ZWxzU2luY2VMYXN0RnJhbWUsIHByZXZNYXgpO1xuICAgICAgY3R4LmxpbmVUbygtcGl4ZWxzU2luY2VMYXN0RnJhbWUsIHByZXZNaW4pO1xuICAgIH1cblxuICAgIGN0eC5saW5lVG8oMCwgbWluKTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG5cbiAgICBjdHguZmlsbCgpO1xuXG4gICAgLy8gZHJhdyBtZWFuXG4gICAgaWYgKGNvbG9yU2NoZW1lID09PSAnbm9uZScgJiYgcHJldk1lYW4pIHtcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgIGN0eC5tb3ZlVG8oLXBpeGVsc1NpbmNlTGFzdEZyYW1lLCBwcmV2TWVhbik7XG4gICAgICBjdHgubGluZVRvKDAsIG1lYW4pO1xuICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH1cblxuXG4gICAgY3R4LnJlc3RvcmUoKTtcblxuICAgIHRoaXMucHJldkZyYW1lID0gZnJhbWU7XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IFRyYWNlRGlzcGxheTtcbiIsImltcG9ydCBCYXNlRGlzcGxheSBmcm9tICcuL0Jhc2VEaXNwbGF5JztcbmltcG9ydCBSbXMgZnJvbSAnLi4vLi4vY29tbW9uL29wZXJhdG9yL1Jtcyc7XG5cbmNvbnN0IGxvZzEwID0gTWF0aC5sb2cxMDtcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIG9mZnNldDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogLTE0LFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeWFubWljJyB9LFxuICB9LFxuICBtaW46IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IC04MCxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbiAgbWF4OiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiA2LFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICB3aWR0aDoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiA2LFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9XG59XG5cbi8qKlxuICogU2ltcGxlIFZVLU1ldGVyIHRvIHVzZWQgb24gYSBgc2lnbmFsYCBzdHJlYW0uXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjbGllbnQuc2lua1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdHMgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5vZmZzZXQ9LTE0XSAtIGRCIG9mZnNldCBhcHBsaWVkIHRvIHRoZSBzaWduYWwuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWluPS04MF0gLSBNaW5pbXVtIGRpc3BsYXllZCB2YWx1ZSAoaW4gZEIpLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heD02XSAtIE1heGltdW0gZGlzcGxheWVkIHZhbHVlIChpbiBkQikuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMud2lkdGg9Nl0gLSBXaWR0aCBvZiB0aGUgZGlzcGxheSAoaW4gcGl4ZWxzKS5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5oZWlnaHQ9MTUwXSAtIEhlaWdodCBvZiB0aGUgY2FudmFzLlxuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jb250YWluZXI9bnVsbF0gLSBDb250YWluZXIgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGluc2VydCB0aGUgY2FudmFzLlxuICogQHBhcmFtIHtFbGVtZW50fENTU1NlbGVjdG9yfSBbb3B0aW9ucy5jYW52YXM9bnVsbF0gLSBDYW52YXMgZWxlbWVudFxuICogIGluIHdoaWNoIHRvIGRyYXcuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqXG4gKiBjb25zdCBhdWRpb0NvbnRleHQgPSBuZXcgd2luZG93LkF1ZGlvQ29udGV4dCgpO1xuICpcbiAqIG5hdmlnYXRvci5tZWRpYURldmljZXNcbiAqICAgLmdldFVzZXJNZWRpYSh7IGF1ZGlvOiB0cnVlIH0pXG4gKiAgIC50aGVuKGluaXQpXG4gKiAgIC5jYXRjaCgoZXJyKSA9PiBjb25zb2xlLmVycm9yKGVyci5zdGFjaykpO1xuICpcbiAqIGZ1bmN0aW9uIGluaXQoc3RyZWFtKSB7XG4gKiAgIGNvbnN0IHNvdXJjZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICpcbiAqICAgY29uc3QgYXVkaW9Jbk5vZGUgPSBuZXcgbGZvLnNvdXJjZS5BdWRpb0luTm9kZSh7XG4gKiAgICAgYXVkaW9Db250ZXh0OiBhdWRpb0NvbnRleHQsXG4gKiAgICAgc291cmNlTm9kZTogc291cmNlLFxuICogICB9KTtcbiAqXG4gKiAgIGNvbnN0IHZ1TWV0ZXIgPSBuZXcgbGZvLnNpbmsuVnVNZXRlckRpc3BsYXkoe1xuICogICAgIGNhbnZhczogJyN2dS1tZXRlcicsXG4gKiAgIH0pO1xuICpcbiAqICAgYXVkaW9Jbk5vZGUuY29ubmVjdCh2dU1ldGVyKTtcbiAqICAgYXVkaW9Jbk5vZGUuc3RhcnQoKTtcbiAqIH1cbiAqL1xuY2xhc3MgVnVNZXRlckRpc3BsYXkgZXh0ZW5kcyBCYXNlRGlzcGxheSB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zLCBmYWxzZSk7XG5cbiAgICB0aGlzLnJtc09wZXJhdG9yID0gbmV3IFJtcygpO1xuXG4gICAgdGhpcy5sYXN0REIgPSAwO1xuICAgIHRoaXMucGVhayA9IHtcbiAgICAgIHZhbHVlOiAwLFxuICAgICAgdGltZTogMCxcbiAgICB9XG5cbiAgICB0aGlzLnBlYWtMaWZldGltZSA9IDE7IC8vIHNlY1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIHRoaXMucm1zT3BlcmF0b3IuaW5pdFN0cmVhbSh0aGlzLnN0cmVhbVBhcmFtcyk7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUpIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDA7IC8vIHNlY1xuICAgIGNvbnN0IG9mZnNldCA9IHRoaXMucGFyYW1zLmdldCgnb2Zmc2V0Jyk7IC8vIG9mZnNldCB6ZXJvIG9mIHRoZSB2dSBtZXRlclxuICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuY2FudmFzSGVpZ2h0O1xuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5jYW52YXNXaWR0aDtcbiAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcblxuICAgIGNvbnN0IGxhc3REQiA9IHRoaXMubGFzdERCO1xuICAgIGNvbnN0IHBlYWsgPSB0aGlzLnBlYWs7XG5cbiAgICBjb25zdCByZWQgPSAnI2ZmMjEyMSc7XG4gICAgY29uc3QgeWVsbG93ID0gJyNmZmZmMWYnO1xuICAgIGNvbnN0IGdyZWVuID0gJyMwMGZmMDAnO1xuXG4gICAgLy8gaGFuZGxlIGN1cnJlbnQgZGIgdmFsdWVcbiAgICBjb25zdCBybXMgPSB0aGlzLnJtc09wZXJhdG9yLmlucHV0U2lnbmFsKGZyYW1lLmRhdGEpO1xuICAgIGxldCBkQiA9IDIwICogbG9nMTAocm1zKSAtIG9mZnNldDtcblxuICAgIC8vIHNsb3cgcmVsZWFzZSAoY291bGQgcHJvYmFibHkgYmUgaW1wcm92ZWQpXG4gICAgaWYgKGxhc3REQiA+IGRCKVxuICAgICAgZEIgPSBsYXN0REIgLSA2O1xuXG4gICAgLy8gaGFuZGxlIHBlYWtcbiAgICBpZiAoZEIgPiBwZWFrLnZhbHVlIHx8wqAobm93IC0gcGVhay50aW1lKSA+IHRoaXMucGVha0xpZmV0aW1lKSB7XG4gICAgICBwZWFrLnZhbHVlID0gZEI7XG4gICAgICBwZWFrLnRpbWUgPSBub3c7XG4gICAgfVxuXG4gICAgY29uc3QgeTAgPSB0aGlzLmdldFlQb3NpdGlvbigwKTtcbiAgICBjb25zdCB5ID0gdGhpcy5nZXRZUG9zaXRpb24oZEIpO1xuICAgIGNvbnN0IHlQZWFrID0gdGhpcy5nZXRZUG9zaXRpb24ocGVhay52YWx1ZSk7XG5cbiAgICBjdHguc2F2ZSgpO1xuXG4gICAgY3R4LmZpbGxTdHlsZSA9ICcjMDAwMDAwJztcbiAgICBjdHguZmlsbFJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG5cbiAgICBjb25zdCBncmFkaWVudCA9IGN0eC5jcmVhdGVMaW5lYXJHcmFkaWVudCgwLCBoZWlnaHQsIDAsIDApO1xuICAgIGdyYWRpZW50LmFkZENvbG9yU3RvcCgwLCBncmVlbik7XG4gICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKChoZWlnaHQgLSB5MCkgLyBoZWlnaHQsIHllbGxvdyk7XG4gICAgZ3JhZGllbnQuYWRkQ29sb3JTdG9wKDEsIHJlZCk7XG5cbiAgICAvLyBkQlxuICAgIGN0eC5maWxsU3R5bGUgPSBncmFkaWVudDtcbiAgICBjdHguZmlsbFJlY3QoMCwgeSwgd2lkdGgsIGhlaWdodCAtIHkpO1xuXG4gICAgLy8gMCBkQiBtYXJrZXJcbiAgICBjdHguZmlsbFN0eWxlID0gJyNkY2RjZGMnO1xuICAgIGN0eC5maWxsUmVjdCgwLCB5MCwgd2lkdGgsIDIpO1xuXG4gICAgLy8gcGVha1xuICAgIGN0eC5maWxsU3R5bGUgPSBncmFkaWVudDtcbiAgICBjdHguZmlsbFJlY3QoMCwgeVBlYWssIHdpZHRoLCAyKTtcblxuICAgIGN0eC5yZXN0b3JlKCk7XG5cbiAgICB0aGlzLmxhc3REQiA9IGRCO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFZ1TWV0ZXJEaXNwbGF5O1xuIiwiaW1wb3J0IEJhc2VEaXNwbGF5IGZyb20gJy4vQmFzZURpc3BsYXknO1xuaW1wb3J0IE1pbk1heCBmcm9tICcuLi8uLi9jb21tb24vb3BlcmF0b3IvTWluTWF4JztcbmltcG9ydCBSbXMgZnJvbSAnLi4vLi4vY29tbW9uL29wZXJhdG9yL1Jtcyc7XG5pbXBvcnQgeyBnZXRDb2xvcnMgfSBmcm9tICcuLi91dGlscy9kaXNwbGF5LXV0aWxzJztcblxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgY29sb3JzOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogZ2V0Q29sb3JzKCd3YXZlZm9ybScpLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeWFubWljJyB9LFxuICB9LFxuICBybXM6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5YW5taWMnIH0sXG4gIH1cbn07XG5cbi8qKlxuICogRGlzcGxheSBhIHdhdmVmb3JtIChhbG9uZyB3aXRoIG9wdGlvbm5hbCBSbXMpIG9mIGEgZ2l2ZW4gYHNpZ25hbGAgaW5wdXQgaW5cbiAqIGEgY2FudmFzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtBcnJheTxTdHJpbmc+fSBbb3B0aW9ucy5jb2xvcnM9Wyd3YXZlZm9ybScsICdybXMnXV0gLSBBcnJheVxuICogIGNvbnRhaW5pbmcgdGhlIGNvbG9yIGNvZGVzIGZvciB0aGUgd2F2ZWZvcm0gKGluZGV4IDApIGFuZCBybXMgKGluZGV4IDEpLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMucm1zPWZhbHNlXSAtIFNldCB0byBgdHJ1ZWAgdG8gZGlzcGxheSB0aGUgcm1zLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5kdXJhdGlvbj0xXSAtIER1cmF0aW9uIChpbiBzZWNvbmRzKSByZXByZXNlbnRlZCBpblxuICogIHRoZSBjYW52YXMuIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW49LTFdIC0gTWluaW11bSB2YWx1ZSByZXByZXNlbnRlZCBpbiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5tYXg9MV0gLSBNYXhpbXVtIHZhbHVlIHJlcHJlc2VudGVkIGluIHRoZSBjYW52YXMuXG4gKiAgX2R5bmFtaWMgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLndpZHRoPTMwMF0gLSBXaWR0aCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5oZWlnaHQ9MTUwXSAtIEhlaWdodCBvZiB0aGUgY2FudmFzLlxuICogIF9keW5hbWljIHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY29udGFpbmVyPW51bGxdIC0gQ29udGFpbmVyIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBpbnNlcnQgdGhlIGNhbnZhcy4gX2NvbnN0YW50IHBhcmFtZXRlcl9cbiAqIEBwYXJhbSB7RWxlbWVudHxDU1NTZWxlY3Rvcn0gW29wdGlvbnMuY2FudmFzPW51bGxdIC0gQ2FudmFzIGVsZW1lbnRcbiAqICBpbiB3aGljaCB0byBkcmF3LiBfY29uc3RhbnQgcGFyYW1ldGVyX1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnJlZmVyZW5jZVRpbWU9bnVsbF0gLSBPcHRpb25uYWwgcmVmZXJlbmNlIHRpbWUgdGhlXG4gKiAgZGlzcGxheSBzaG91bGQgY29uc2lkZXJlciBhcyB0aGUgb3JpZ2luLiBJcyBvbmx5IHVzZWZ1bGwgd2hlbiBzeW5jaHJvbml6aW5nXG4gKiAgc2V2ZXJhbCBkaXNwbGF5IHVzaW5nIHRoZSBgRGlzcGxheVN5bmNgIGNsYXNzLlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y2xpZW50LnNpbmtcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IGF1ZGlvQ29udGV4dCA9IG5ldyB3aW5kb3cuQXVkaW9Db250ZXh0KCk7XG4gKlxuICogbmF2aWdhdG9yLm1lZGlhRGV2aWNlc1xuICogICAuZ2V0VXNlck1lZGlhKHsgYXVkaW86IHRydWUgfSlcbiAqICAgLnRoZW4oaW5pdClcbiAqICAgLmNhdGNoKChlcnIpID0+IGNvbnNvbGUuZXJyb3IoZXJyLnN0YWNrKSk7XG4gKlxuICogZnVuY3Rpb24gaW5pdChzdHJlYW0pIHtcbiAqICAgY29uc3QgYXVkaW9JbiA9IGF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICpcbiAqICAgY29uc3QgYXVkaW9Jbk5vZGUgPSBuZXcgbGZvLnNvdXJjZS5BdWRpb0luTm9kZSh7XG4gKiAgICAgYXVkaW9Db250ZXh0OiBhdWRpb0NvbnRleHQsXG4gKiAgICAgc291cmNlTm9kZTogYXVkaW9JbixcbiAqICAgICBmcmFtZVNpemU6IDUxMixcbiAqICAgfSk7XG4gKlxuICogICBjb25zdCB3YXZlZm9ybURpc3BsYXkgPSBuZXcgbGZvLnNpbmsuV2F2ZWZvcm1EaXNwbGF5KHtcbiAqICAgICBjYW52YXM6ICcjd2F2ZWZvcm0nLFxuICogICAgIGR1cmF0aW9uOiAzLjUsXG4gKiAgICAgcm1zOiB0cnVlLFxuICogICB9KTtcbiAqXG4gKiAgIGF1ZGlvSW5Ob2RlLmNvbm5lY3Qod2F2ZWZvcm1EaXNwbGF5KTtcbiAqICAgYXVkaW9Jbk5vZGUuc3RhcnQoKTtcbiAqIH0pO1xuICovXG5jbGFzcyBXYXZlZm9ybURpc3BsYXkgZXh0ZW5kcyBCYXNlRGlzcGxheSB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucywgdHJ1ZSk7XG5cbiAgICB0aGlzLm1pbk1heE9wZXJhdG9yID0gbmV3IE1pbk1heCgpO1xuICAgIHRoaXMucm1zT3BlcmF0b3IgPSBuZXcgUm1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgdGhpcy5taW5NYXhPcGVyYXRvci5pbml0U3RyZWFtKHRoaXMuc3RyZWFtUGFyYW1zKTtcbiAgICB0aGlzLnJtc09wZXJhdG9yLmluaXRTdHJlYW0odGhpcy5zdHJlYW1QYXJhbXMpO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lLCBmcmFtZVdpZHRoLCBwaXhlbHNTaW5jZUxhc3RGcmFtZSkge1xuICAgIC8vIGRyb3AgZnJhbWVzIHRoYXQgY2Fubm90IGJlIGRpc3BsYXllZFxuICAgIGlmIChmcmFtZVdpZHRoIDwgMSkgcmV0dXJuO1xuXG4gICAgY29uc3QgY29sb3JzID0gdGhpcy5wYXJhbXMuZ2V0KCdjb2xvcnMnKTtcbiAgICBjb25zdCBzaG93Um1zID0gdGhpcy5wYXJhbXMuZ2V0KCdybXMnKTtcbiAgICBjb25zdCBjdHggPSB0aGlzLmN0eDtcbiAgICBjb25zdCBkYXRhID0gZnJhbWUuZGF0YTtcbiAgICBjb25zdCBpU2FtcGxlc1BlclBpeGVscyA9IE1hdGguZmxvb3IoZGF0YS5sZW5ndGggLyBmcmFtZVdpZHRoKTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBmcmFtZVdpZHRoOyBpbmRleCsrKSB7XG4gICAgICBjb25zdCBzdGFydCA9IGluZGV4ICogaVNhbXBsZXNQZXJQaXhlbHM7XG4gICAgICBjb25zdCBlbmQgPSBpbmRleCA9PT0gZnJhbWVXaWR0aCAtIDEgPyB1bmRlZmluZWQgOiBzdGFydCArIGlTYW1wbGVzUGVyUGl4ZWxzO1xuICAgICAgY29uc3Qgc2xpY2UgPSBkYXRhLnN1YmFycmF5KHN0YXJ0LCBlbmQpO1xuXG4gICAgICBjb25zdCBtaW5NYXggPSB0aGlzLm1pbk1heE9wZXJhdG9yLmlucHV0U2lnbmFsKHNsaWNlKTtcbiAgICAgIGNvbnN0IG1pblkgPSB0aGlzLmdldFlQb3NpdGlvbihtaW5NYXhbMF0pO1xuICAgICAgY29uc3QgbWF4WSA9IHRoaXMuZ2V0WVBvc2l0aW9uKG1pbk1heFsxXSk7XG5cbiAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yc1swXTtcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgIGN0eC5tb3ZlVG8oaW5kZXgsIG1pblkpO1xuICAgICAgY3R4LmxpbmVUbyhpbmRleCwgbWF4WSk7XG4gICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICBjdHguc3Ryb2tlKCk7XG5cbiAgICAgIGlmIChzaG93Um1zKSB7XG4gICAgICAgIGNvbnN0IHJtcyA9IHRoaXMucm1zT3BlcmF0b3IuaW5wdXRTaWduYWwoc2xpY2UpO1xuICAgICAgICBjb25zdCBybXNNYXhZID0gdGhpcy5nZXRZUG9zaXRpb24ocm1zKTtcbiAgICAgICAgY29uc3Qgcm1zTWluWSA9IHRoaXMuZ2V0WVBvc2l0aW9uKC1ybXMpO1xuXG4gICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGNvbG9yc1sxXTtcbiAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICBjdHgubW92ZVRvKGluZGV4LCBybXNNaW5ZKTtcbiAgICAgICAgY3R4LmxpbmVUbyhpbmRleCwgcm1zTWF4WSk7XG4gICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgY3R4LnN0cm9rZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBXYXZlZm9ybURpc3BsYXk7XG4iLCIvLyBjb21tb25cbmltcG9ydCBCcmlkZ2UgZnJvbSAnLi4vLi4vY29tbW9uL3NpbmsvQnJpZGdlJztcbmltcG9ydCBMb2dnZXIgZnJvbSAnLi4vLi4vY29tbW9uL3NpbmsvTG9nZ2VyJztcbmltcG9ydCBEYXRhUmVjb3JkZXIgZnJvbSAnLi4vLi4vY29tbW9uL3NpbmsvRGF0YVJlY29yZGVyJztcbmltcG9ydCBTaWduYWxSZWNvcmRlciBmcm9tICcuLi8uLi9jb21tb24vc2luay9TaWduYWxSZWNvcmRlcic7XG5cbi8vIGNsaWVudCBvbmx5XG5pbXBvcnQgQmFzZURpc3BsYXkgZnJvbSAnLi9CYXNlRGlzcGxheSc7XG5pbXBvcnQgQmFyQ2hhcnREaXNwbGF5IGZyb20gJy4vQmFyQ2hhcnREaXNwbGF5JztcbmltcG9ydCBCcGZEaXNwbGF5IGZyb20gJy4vQnBmRGlzcGxheSc7XG5pbXBvcnQgTWFya2VyRGlzcGxheSBmcm9tICcuL01hcmtlckRpc3BsYXknO1xuaW1wb3J0IFNpZ25hbERpc3BsYXkgZnJvbSAnLi9TaWduYWxEaXNwbGF5JztcbmltcG9ydCBTb2NrZXRTZW5kIGZyb20gJy4vU29ja2V0U2VuZCc7XG5pbXBvcnQgU3BlY3RydW1EaXNwbGF5IGZyb20gJy4vU3BlY3RydW1EaXNwbGF5JztcbmltcG9ydCBUcmFjZURpc3BsYXkgZnJvbSAnLi9UcmFjZURpc3BsYXknO1xuaW1wb3J0IFZ1TWV0ZXJEaXNwbGF5IGZyb20gJy4vVnVNZXRlckRpc3BsYXknO1xuaW1wb3J0IFdhdmVmb3JtRGlzcGxheSBmcm9tICcuL1dhdmVmb3JtRGlzcGxheSc7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgQnJpZGdlLFxuICBMb2dnZXIsXG4gIERhdGFSZWNvcmRlcixcbiAgU2lnbmFsUmVjb3JkZXIsXG5cbiAgQmFzZURpc3BsYXksXG4gIEJhckNoYXJ0RGlzcGxheSxcbiAgQnBmRGlzcGxheSxcbiAgTWFya2VyRGlzcGxheSxcbiAgU2lnbmFsRGlzcGxheSxcbiAgU29ja2V0U2VuZCxcbiAgU3BlY3RydW1EaXNwbGF5LFxuICBUcmFjZURpc3BsYXksXG4gIFZ1TWV0ZXJEaXNwbGF5LFxuICBXYXZlZm9ybURpc3BsYXksXG59O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcbmltcG9ydCBTb3VyY2VNaXhpbiBmcm9tICcuLi8uLi9jb3JlL1NvdXJjZU1peGluJztcblxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgYXVkaW9CdWZmZXI6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBmcmFtZVNpemU6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogNTEyLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBjaGFubmVsOiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IDAsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH0sXG4gIHByb2dyZXNzQ2FsbGJhY2s6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBwcm9ncmVzc0NhbGxiYWNrOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogbnVsbCxcbiAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICBjb25zdGFudDogdHJ1ZSxcbiAgfSxcbiAgYXN5bmM6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG59O1xuXG5jb25zdCBub29wID0gZnVuY3Rpb24oKSB7fTtcblxuLyoqXG4gKiBTbGljZSBhbiBgQXVkaW9CdWZmZXJgIGludG8gc2lnbmFsIGJsb2NrcyBhbmQgcHJvcGFnYXRlIHRoZSByZXN1bHRpbmcgZnJhbWVzXG4gKiB0aHJvdWdoIHRoZSBncmFwaC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIHBhcmFtZXRlcicgZGVmYXVsdCB2YWx1ZXMuXG4gKiBAcGFyYW0ge0F1ZGlvQnVmZmVyfSBbb3B0aW9ucy5hdWRpb0J1ZmZlcl0gLSBBdWRpbyBidWZmZXIgdG8gcHJvY2Vzcy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5mcmFtZVNpemU9NTEyXSAtIFNpemUgb2YgdGhlIG91dHB1dCBibG9ja3MuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuY2hhbm5lbD0wXSAtIE51bWJlciBvZiB0aGUgY2hhbm5lbCB0byBwcm9jZXNzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnByb2dyZXNzQ2FsbGJhY2s9bnVsbF0gLSBDYWxsYmFjayB0byBiZSBleGN1dGVkIG9uIGVhY2hcbiAqICBmcmFtZSBvdXRwdXQsIHJlY2VpdmUgYXMgYXJndW1lbnQgdGhlIGN1cnJlbnQgcHJvZ3Jlc3MgcmF0aW8uXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjbGllbnQuc291cmNlXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqXG4gKiBjb25zdCBhdWRpb0luQnVmZmVyID0gbmV3IGxmby5zb3VyY2UuQXVkaW9JbkJ1ZmZlcih7XG4gKiAgIGF1ZGlvQnVmZmVyOiBhdWRpb0J1ZmZlcixcbiAqICAgZnJhbWVTaXplOiA1MTIsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCB3YXZlZm9ybSA9IG5ldyBsZm8uc2luay5XYXZlZm9ybSh7XG4gKiAgIGNhbnZhczogJyN3YXZlZm9ybScsXG4gKiAgIGR1cmF0aW9uOiAxLFxuICogICBjb2xvcjogJ3N0ZWVsYmx1ZScsXG4gKiAgIHJtczogdHJ1ZSxcbiAqIH0pO1xuICpcbiAqIGF1ZGlvSW5CdWZmZXIuY29ubmVjdCh3YXZlZm9ybSk7XG4gKiBhdWRpb0luQnVmZmVyLnN0YXJ0KCk7XG4gKi9cbmNsYXNzIEF1ZGlvSW5CdWZmZXIgZXh0ZW5kcyBTb3VyY2VNaXhpbihCYXNlTGZvKSB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IGF1ZGlvQnVmZmVyID0gdGhpcy5wYXJhbXMuZ2V0KCdhdWRpb0J1ZmZlcicpO1xuXG4gICAgaWYgKCFhdWRpb0J1ZmZlcilcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBcImF1ZGlvQnVmZmVyXCIgcGFyYW1ldGVyJyk7XG5cbiAgICB0aGlzLmVuZFRpbWUgPSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3BhZ2F0ZSB0aGUgYHN0cmVhbVBhcmFtc2AgaW4gdGhlIGdyYXBoIGFuZCBzdGFydCBwcm9wYWdhdGluZyBmcmFtZXMuXG4gICAqIFdoZW4gY2FsbGVkLCB0aGUgc2xpY2luZyBvZiB0aGUgZ2l2ZW4gYGF1ZGlvQnVmZmVyYCBzdGFydHMgaW1tZWRpYXRlbHkgYW5kXG4gICAqIGVhY2ggcmVzdWx0aW5nIGZyYW1lIGlzIHByb3BhZ2F0ZWQgaW4gZ3JhcGguXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJvY2Vzc1N0cmVhbVBhcmFtc31cbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNyZXNldFN0cmVhbX1cbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNsaWVudC5zb3VyY2UuQXVkaW9JbkJ1ZmZlciNzdG9wfVxuICAgKi9cbiAgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuaW5pdGlhbGl6ZWQgPT09IGZhbHNlKSB7XG4gICAgICBpZiAodGhpcy5pbml0UHJvbWlzZSA9PT0gbnVsbCkgLy8gaW5pdCBoYXMgbm90IHlldCBiZWVuIGNhbGxlZFxuICAgICAgICB0aGlzLmluaXRQcm9taXNlID0gdGhpcy5pbml0KCk7XG5cbiAgICAgIHRoaXMuaW5pdFByb21pc2UudGhlbih0aGlzLnN0YXJ0KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5wYXJhbXMuZ2V0KCdjaGFubmVsJyk7XG4gICAgY29uc3QgYXVkaW9CdWZmZXIgPSB0aGlzLnBhcmFtcy5nZXQoJ2F1ZGlvQnVmZmVyJyk7XG4gICAgY29uc3QgYnVmZmVyID0gYXVkaW9CdWZmZXIuZ2V0Q2hhbm5lbERhdGEoY2hhbm5lbCk7XG4gICAgdGhpcy5lbmRUaW1lID0gMDtcbiAgICB0aGlzLnN0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgdGhpcy5wcm9jZXNzRnJhbWUoYnVmZmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5hbGl6ZSB0aGUgc3RyZWFtIGFuZCBzdG9wIHRoZSB3aG9sZSBncmFwaC4gV2hlbiBjYWxsZWQsIHRoZSBzbGljaW5nIG9mXG4gICAqIHRoZSBgYXVkaW9CdWZmZXJgIHN0b3BzIGltbWVkaWF0ZWx5LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI2ZpbmFsaXplU3RyZWFtfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y2xpZW50LnNvdXJjZS5BdWRpb0luQnVmZmVyI3N0YXJ0fVxuICAgKi9cbiAgc3RvcCgpIHtcbiAgICB0aGlzLmZpbmFsaXplU3RyZWFtKHRoaXMuZW5kVGltZSk7XG4gICAgdGhpcy5zdGFydGVkID0gZmFsc2U7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcygpIHtcbiAgICBjb25zdCBhdWRpb0J1ZmZlciA9IHRoaXMucGFyYW1zLmdldCgnYXVkaW9CdWZmZXInKTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZyYW1lU2l6ZScpO1xuICAgIGNvbnN0IHNvdXJjZVNhbXBsZVJhdGUgPSBhdWRpb0J1ZmZlci5zYW1wbGVSYXRlO1xuICAgIGNvbnN0IGZyYW1lUmF0ZSA9IHNvdXJjZVNhbXBsZVJhdGUgLyBmcmFtZVNpemU7XG5cbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSBmcmFtZVNpemU7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVSYXRlID0gZnJhbWVSYXRlO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZSA9ICdzaWduYWwnO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGUgPSBzb3VyY2VTYW1wbGVSYXRlO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZUNvdW50ID0gZnJhbWVTaXplO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzRnJhbWUoYnVmZmVyKSB7XG4gICAgY29uc3QgYXN5bmMgPSB0aGlzLnBhcmFtcy5nZXQoJ2FzeW5jJyk7XG4gICAgY29uc3Qgc2FtcGxlUmF0ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGU7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHByb2dyZXNzQ2FsbGJhY2sgPSB0aGlzLnBhcmFtcy5nZXQoJ3Byb2dyZXNzQ2FsbGJhY2snKSB8fMKgbm9vcDtcbiAgICBjb25zdCBsZW5ndGggPSBidWZmZXIubGVuZ3RoO1xuICAgIGNvbnN0IG5ickZyYW1lcyA9IE1hdGguY2VpbChidWZmZXIubGVuZ3RoIC8gZnJhbWVTaXplKTtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIGxldCBpID0gMDtcblxuICAgIGZ1bmN0aW9uIHNsaWNlKCkge1xuICAgICAgY29uc3Qgb2Zmc2V0ID0gaSAqIGZyYW1lU2l6ZTtcbiAgICAgIGNvbnN0IG5ickNvcHkgPSBNYXRoLm1pbihsZW5ndGggLSBvZmZzZXQsIGZyYW1lU2l6ZSk7XG5cbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZnJhbWVTaXplOyBqKyspXG4gICAgICAgIGRhdGFbal0gPSBqIDwgbmJyQ29weSA/IGJ1ZmZlcltvZmZzZXQgKyBqXSA6IDA7XG5cbiAgICAgIHRoYXQuZnJhbWUudGltZSA9IG9mZnNldCAvIHNhbXBsZVJhdGU7XG4gICAgICB0aGF0LmVuZFRpbWUgPSB0aGF0LmZyYW1lLnRpbWUgKyBuYnJDb3B5IC8gc2FtcGxlUmF0ZTtcbiAgICAgIHRoYXQucHJvcGFnYXRlRnJhbWUoKTtcblxuICAgICAgaSArPSAxO1xuICAgICAgcHJvZ3Jlc3NDYWxsYmFjayhpIC8gbmJyRnJhbWVzKTtcblxuICAgICAgaWYgKGkgPCBuYnJGcmFtZXMpIHtcbiAgICAgICAgaWYgKGFzeW5jKVxuICAgICAgICAgIHNldFRpbWVvdXQoc2xpY2UsIDApO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc2xpY2UoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoYXQuZmluYWxpemVTdHJlYW0odGhhdC5lbmRUaW1lKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gYWxsb3cgdGhlIGZvbGxvd2luZyB0byBkbyB0aGUgZXhwZWN0ZWQgdGhpbmc6XG4gICAgLy8gYXVkaW9Jbi5jb25uZWN0KHJlY29yZGVyKTtcbiAgICAvLyBhdWRpb0luLnN0YXJ0KCk7XG4gICAgLy8gcmVjb3JkZXIuc3RhcnQoKTtcbiAgICBzZXRUaW1lb3V0KHNsaWNlLCAwKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBBdWRpb0luQnVmZmVyO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcbmltcG9ydCBTb3VyY2VNaXhpbiBmcm9tICcuLi8uLi9jb3JlL1NvdXJjZU1peGluJztcblxuY29uc3QgQXVkaW9Db250ZXh0ID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fMKgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIGZyYW1lU2l6ZToge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiA1MTIsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH0sXG4gIGNoYW5uZWw6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogMCxcbiAgICBjb25zdGFudDogdHJ1ZSxcbiAgfSxcbiAgc291cmNlTm9kZToge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH0sXG4gIGF1ZGlvQ29udGV4dDoge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH0sXG59O1xuXG4vKipcbiAqIFVzZSBhIGBXZWJBdWRpb2Agbm9kZSBhcyBhIHNvdXJjZSBmb3IgdGhlIGdyYXBoLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgcGFyYW1ldGVyJyBkZWZhdWx0IHZhbHVlcy5cbiAqIEBwYXJhbSB7QXVkaW9Ob2RlfSBbb3B0aW9ucy5zb3VyY2VOb2RlPW51bGxdIC0gQXVkaW8gbm9kZSB0byBwcm9jZXNzXG4gKiAgKG1hbmRhdG9yeSkuXG4gKiBAcGFyYW0ge0F1ZGlvQ29udGV4dH0gW29wdGlvbnMuYXVkaW9Db250ZXh0PW51bGxdIC0gQXVkaW8gY29udGV4dCB1c2VkIHRvXG4gKiAgY3JlYXRlIHRoZSBhdWRpbyBub2RlIChtYW5kYXRvcnkpLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmZyYW1lU2l6ZT01MTJdIC0gU2l6ZSBvZiB0aGUgb3V0cHV0IGJsb2NrcywgZGVmaW5lXG4gKiAgdGhlIGBmcmFtZVNpemVgIGluIHRoZSBgc3RyZWFtUGFyYW1zYC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5jaGFubmVsPTBdIC0gTnVtYmVyIG9mIHRoZSBjaGFubmVsIHRvIHByb2Nlc3MuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjbGllbnQuc291cmNlXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqXG4gKiBjb25zdCBhdWRpb0NvbnRleHQgPSBuZXcgQXVkaW9Db250ZXh0KCk7XG4gKiBjb25zdCBzaW5lID0gYXVkaW9Db250ZXh0LmNyZWF0ZU9zY2lsbGF0b3IoKTtcbiAqIHNpbmUuZnJlcXVlbmN5LnZhbHVlID0gMjtcbiAqXG4gKiBjb25zdCBhdWRpb0luTm9kZSA9IG5ldyBsZm8uc291cmNlLkF1ZGlvSW5Ob2RlKHtcbiAqICAgYXVkaW9Db250ZXh0OiBhdWRpb0NvbnRleHQsXG4gKiAgIHNvdXJjZU5vZGU6IHNpbmUsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBzaWduYWxEaXNwbGF5ID0gbmV3IGxmby5zaW5rLlNpZ25hbERpc3BsYXkoe1xuICogICBjYW52YXM6ICcjc2lnbmFsJyxcbiAqICAgZHVyYXRpb246IDEsXG4gKiB9KTtcbiAqXG4gKiBhdWRpb0luTm9kZS5jb25uZWN0KHNpZ25hbERpc3BsYXkpO1xuICpcbiAqIC8vIHN0YXJ0IHRoZSBzaW5lIG9zY2lsbGF0b3Igbm9kZSBhbmQgdGhlIGxmbyBncmFwaFxuICogc2luZS5zdGFydCgpO1xuICogYXVkaW9Jbk5vZGUuc3RhcnQoKTtcbiAqL1xuY2xhc3MgQXVkaW9Jbk5vZGUgZXh0ZW5kcyBTb3VyY2VNaXhpbihCYXNlTGZvKSB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IGF1ZGlvQ29udGV4dCA9IHRoaXMucGFyYW1zLmdldCgnYXVkaW9Db250ZXh0Jyk7XG4gICAgY29uc3Qgc291cmNlTm9kZSA9IHRoaXMucGFyYW1zLmdldCgnc291cmNlTm9kZScpO1xuXG4gICAgaWYgKCFhdWRpb0NvbnRleHQgfHwgIShhdWRpb0NvbnRleHQgaW5zdGFuY2VvZiBBdWRpb0NvbnRleHQpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGBhdWRpb0NvbnRleHRgIHBhcmFtZXRlcicpO1xuXG4gICAgaWYgKCFzb3VyY2VOb2RlIHx8ICEoc291cmNlTm9kZSBpbnN0YW5jZW9mIEF1ZGlvTm9kZSkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYHNvdXJjZU5vZGVgIHBhcmFtZXRlcicpO1xuXG4gICAgdGhpcy5zb3VyY2VOb2RlID0gc291cmNlTm9kZTtcbiAgICB0aGlzLl9jaGFubmVsID0gdGhpcy5wYXJhbXMuZ2V0KCdjaGFubmVsJyk7XG4gICAgdGhpcy5fYmxvY2tEdXJhdGlvbiA9IG51bGw7XG5cbiAgICB0aGlzLnByb2Nlc3NGcmFtZSA9IHRoaXMucHJvY2Vzc0ZyYW1lLmJpbmQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogUHJvcGFnYXRlIHRoZSBgc3RyZWFtUGFyYW1zYCBpbiB0aGUgZ3JhcGggYW5kIHN0YXJ0IHRvIHByb3BhZ2F0ZSBzaWduYWxcbiAgICogYmxvY2tzIHByb2R1Y2VkIGJ5IHRoZSBhdWRpbyBub2RlIGludG8gdGhlIGdyYXBoLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb2Nlc3NTdHJlYW1QYXJhbXN9XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcmVzZXRTdHJlYW19XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjbGllbnQuc291cmNlLkF1ZGlvSW5Ob2RlI3N0b3B9XG4gICAqL1xuICBzdGFydCgpIHtcbiAgICBpZiAodGhpcy5pbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGlmICh0aGlzLmluaXRQcm9taXNlID09PSBudWxsKSAvLyBpbml0IGhhcyBub3QgeWV0IGJlZW4gY2FsbGVkXG4gICAgICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXQoKTtcblxuICAgICAgdGhpcy5pbml0UHJvbWlzZS50aGVuKHRoaXMuc3RhcnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGF1ZGlvQ29udGV4dCA9IHRoaXMucGFyYW1zLmdldCgnYXVkaW9Db250ZXh0Jyk7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5wYXJhbXMuZ2V0KCdmcmFtZVNpemUnKTtcblxuICAgIHRoaXMuZnJhbWUudGltZSA9IDA7XG4gICAgLy8gQG5vdGU6IHJlY3JlYXRlIGVhY2ggdGltZSBiZWNhdXNlIG9mIGEgZmlyZWZveCB3ZWlyZCBiZWhhdmlvclxuICAgIHRoaXMuc2NyaXB0UHJvY2Vzc29yID0gYXVkaW9Db250ZXh0LmNyZWF0ZVNjcmlwdFByb2Nlc3NvcihmcmFtZVNpemUsIDEsIDEpO1xuICAgIHRoaXMuc2NyaXB0UHJvY2Vzc29yLm9uYXVkaW9wcm9jZXNzID0gdGhpcy5wcm9jZXNzRnJhbWU7XG5cbiAgICB0aGlzLnN0YXJ0ZWQgPSB0cnVlO1xuICAgIHRoaXMuc291cmNlTm9kZS5jb25uZWN0KHRoaXMuc2NyaXB0UHJvY2Vzc29yKTtcbiAgICB0aGlzLnNjcmlwdFByb2Nlc3Nvci5jb25uZWN0KGF1ZGlvQ29udGV4dC5kZXN0aW5hdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogRmluYWxpemUgdGhlIHN0cmVhbSBhbmQgc3RvcCB0aGUgd2hvbGUgZ3JhcGguXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jZmluYWxpemVTdHJlYW19XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjbGllbnQuc291cmNlLkF1ZGlvSW5Ob2RlI3N0YXJ0fVxuICAgKi9cbiAgc3RvcCgpIHtcbiAgICB0aGlzLmZpbmFsaXplU3RyZWFtKHRoaXMuZnJhbWUudGltZSk7XG4gICAgdGhpcy5zdGFydGVkID0gZmFsc2U7XG4gICAgdGhpcy5zb3VyY2VOb2RlLmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLnNjcmlwdFByb2Nlc3Nvci5kaXNjb25uZWN0KCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcygpIHtcbiAgICBjb25zdCBhdWRpb0NvbnRleHQgPSB0aGlzLnBhcmFtcy5nZXQoJ2F1ZGlvQ29udGV4dCcpO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnZnJhbWVTaXplJyk7XG4gICAgY29uc3Qgc2FtcGxlUmF0ZSA9IGF1ZGlvQ29udGV4dC5zYW1wbGVSYXRlO1xuXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gZnJhbWVTaXplO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lUmF0ZSA9IHNhbXBsZVJhdGUgLyBmcmFtZVNpemU7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlID0gJ3NpZ25hbCc7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlUmF0ZSA9IHNhbXBsZVJhdGU7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlQ291bnQgPSBmcmFtZVNpemU7XG5cbiAgICB0aGlzLl9ibG9ja0R1cmF0aW9uID0gZnJhbWVTaXplIC8gc2FtcGxlUmF0ZTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKipcbiAgICogQmFzaWNhbGx5IHRoZSBgc2NyaXB0UHJvY2Vzc29yLm9uYXVkaW9wcm9jZXNzYCBjYWxsYmFja1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJvY2Vzc0ZyYW1lKGUpIHtcbiAgICBpZiAodGhpcy5zdGFydGVkID09PSBmYWxzZSlcbiAgICAgIHJldHVybjtcblxuICAgIHRoaXMuZnJhbWUuZGF0YSA9IGUuaW5wdXRCdWZmZXIuZ2V0Q2hhbm5lbERhdGEodGhpcy5fY2hhbm5lbCk7XG4gICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuXG4gICAgdGhpcy5mcmFtZS50aW1lICs9IHRoaXMuX2Jsb2NrRHVyYXRpb247XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQXVkaW9Jbk5vZGU7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuaW1wb3J0IHsgb3Bjb2RlcywgZW5jb2RlcnMsIGRlY29kZXJzIH0gZnJvbSAnLi4vLi4vY29tbW9uL3V0aWxzL3dzVXRpbHMnO1xuXG5jb25zdCBwYXJhbWV0ZXJzID0ge1xuICBwb3J0OiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IDgwMDAsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH0sXG4gIHVybDoge1xuICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH1cbn1cblxuLyoqXG4gKiBSZWNlaXZlIGFuIGxmbyBmcmFtZSBhcyBhIHNvY2tldCBtZXNzYWdlIGZyb20gYSBgbm9kZS5zaW5rLlNvY2tldFNlbmRgXG4gKiBpbnN0YW5jZS5cbiAqXG4gKiA8cCBjbGFzcz1cIndhcm5pbmdcIj5FeHBlcmltZW50YWw8L3A+XG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjbGllbnQuc291cmNlXG4gKlxuICogQHRvZG8gLSBoYW5kbGUgaW5pdCAvIHN0YXJ0IHByb3Blcmx5LlxuICovXG5jbGFzcyBTb2NrZXRSZWNlaXZlIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKHBhcmFtZXRlcnMsIG9wdGlvbnMpO1xuXG4gICAgY29uc3QgcHJvdG9jb2wgPSB3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wucmVwbGFjZSgvXmh0dHAvLCAnd3MnKTtcbiAgICBjb25zdCBhZGRyZXNzID0gdGhpcy5wYXJhbXMuZ2V0KCd1cmwnKSB8fMKgd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lO1xuICAgIGNvbnN0IHBvcnQgPSB0aGlzLnBhcmFtcy5nZXQoJ3BvcnQnKSB8fCAnJzsgLy8gZXZlcnl0aGluZyBmYWxzeSBiZWNvbWVzICcnXG4gICAgY29uc3Qgc29ja2V0QWRkcmVzcyA9IGAke3Byb3RvY29sfS8vJHthZGRyZXNzfToke3BvcnR9YDtcblxuICAgIHRoaXMuX2Rpc3BhdGNoID0gdGhpcy5fZGlzcGF0Y2guYmluZCh0aGlzKTtcblxuICAgIHRoaXMuc29ja2V0ID0gbmV3IFdlYlNvY2tldChzb2NrZXRBZGRyZXNzKTtcbiAgICB0aGlzLnNvY2tldC5iaW5hcnlUeXBlID0gJ2FycmF5YnVmZmVyJztcblxuICAgIHRoaXMub3BlbmVkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuc29ja2V0Lm9ub3BlbiA9IHJlc29sdmU7XG4gICAgfSk7XG5cbiAgICB0aGlzLnNvY2tldC5vbm1lc3NhZ2UgPSB0aGlzLl9kaXNwYXRjaDtcbiAgICB0aGlzLnNvY2tldC5vbmVycm9yID0gKGVycikgPT4gY29uc29sZS5lcnJvcihlcnIuc3RhY2spO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIGluaXRNb2R1bGUoKSB7XG4gICAgY29uc3QgcHJvbWlzZXMgPSB0aGlzLm5leHRNb2R1bGVzLm1hcCgobW9kKSA9PiBtb2QuaW5pdE1vZHVsZSgpKTtcbiAgICBwcm9taXNlcy5wdXNoKHRoaXMub3BlbmVkUHJvbWlzZSk7XG4gICAgLy8gd2FpdCBmb3IgY2hpbGRyZW4gcHJvbWlzZXMgYW5kIHNlbmQgSU5JVF9NT0RVTEVfQUNLXG4gICAgUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgYnVmZmVyID0gZW5jb2RlcnMuaW5pdE1vZHVsZUFjaygpO1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChidWZmZXIpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gcHJvY2VzcyBhbnkgdHlwZVxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NjYWxhcigpIHt9XG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKCkge31cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoKSB7fVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICB0aGlzLnByZXBhcmVGcmFtZSgpO1xuICAgIHRoaXMuZnJhbWUgPSBmcmFtZTtcbiAgICB0aGlzLnByb3BhZ2F0ZUZyYW1lKCk7XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlIGFuZCBkaXNwYXRjaCBpbmNvbW1pbmcgZnJhbWUgYWNjb3JkaW5nIHRvIG9wY29kZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2Rpc3BhdGNoKGUpIHtcbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGUuZGF0YTtcbiAgICBjb25zdCBvcGNvZGUgPSBkZWNvZGVycy5vcGNvZGUoYXJyYXlCdWZmZXIpO1xuXG4gICAgc3dpdGNoIChvcGNvZGUpIHtcbiAgICAgIGNhc2Ugb3Bjb2Rlcy5JTklUX01PRFVMRV9SRVE6XG4gICAgICAgIHRoaXMuaW5pdE1vZHVsZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2Ugb3Bjb2Rlcy5QUk9DRVNTX1NUUkVBTV9QQVJBTVM6XG4gICAgICAgIGNvbnN0IHByZXZTdHJlYW1QYXJhbXMgPSBkZWNvZGVycy5zdHJlYW1QYXJhbXMoYXJyYXlCdWZmZXIpO1xuICAgICAgICB0aGlzLnByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBvcGNvZGVzLlJFU0VUX1NUUkVBTTpcbiAgICAgICAgdGhpcy5yZXNldFN0cmVhbSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2Ugb3Bjb2Rlcy5GSU5BTElaRV9TVFJFQU06XG4gICAgICAgIGNvbnN0IGVuZFRpbWUgPSBkZWNvZGVycy5maW5hbGl6ZVN0cmVhbShhcnJheUJ1ZmZlcik7XG4gICAgICAgIHRoaXMuZmluYWxpemVTdHJlYW0oZW5kVGltZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBvcGNvZGVzLlBST0NFU1NfRlJBTUU6XG4gICAgICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICAgICAgY29uc3QgZnJhbWUgPSBkZWNvZGVycy5wcm9jZXNzRnJhbWUoYXJyYXlCdWZmZXIsIGZyYW1lU2l6ZSk7XG4gICAgICAgIHRoaXMucHJvY2Vzc0ZyYW1lKGZyYW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNvY2tldFJlY2VpdmU7XG4iLCIvLyBjb21tb25cbmltcG9ydCBFdmVudEluIGZyb20gJy4uLy4uL2NvbW1vbi9zb3VyY2UvRXZlbnRJbic7XG4vLyBjbGllbnQgb25seVxuaW1wb3J0IEF1ZGlvSW5CdWZmZXIgZnJvbSAnLi9BdWRpb0luQnVmZmVyJztcbmltcG9ydCBBdWRpb0luTm9kZSBmcm9tICcuL0F1ZGlvSW5Ob2RlJztcbmltcG9ydCBTb2NrZXRSZWNlaXZlIGZyb20gJy4vU29ja2V0UmVjZWl2ZSc7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgRXZlbnRJbixcblxuICBBdWRpb0luQnVmZmVyLFxuICBBdWRpb0luTm9kZSxcbiAgU29ja2V0UmVjZWl2ZSxcbn07XG4iLCIvKipcbiAqIFN5bmNocm9uaXplIHNldmVyYWwgZGlzcGxheSBzaW5rcyB0byBhIGNvbW1vbiB0aW1lLlxuICpcbiAqIEBwYXJhbSB7Li4uQmFzZURpc3BsYXl9IHZpZXdzIC0gTGlzdCBvZiB0aGUgZGlzcGxheSB0byBzeW5jaHJvbml6ZS5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNsaWVudC51dGlsc1xuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gKlxuICogY29uc3QgZXZlbnRJbjEgPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVUeXBlOiAnc2NhbGFyJyxcbiAqICAgZnJhbWVTaXplOiAxLFxuICogfSk7XG4gKlxuICogY29uc3QgYnBmMSA9IG5ldyBsZm8uc2luay5CcGZEaXNwbGF5KHtcbiAqICAgY2FudmFzOiAnI2JwZi0xJyxcbiAqICAgZHVyYXRpb246IDIsXG4gKiAgIHN0YXJ0VGltZTogMCxcbiAqICAgbWluOiAwLFxuICogICBjb2xvcnM6IFsnc3RlZWxibHVlJ10sXG4gKiB9KTtcbiAqXG4gKiBldmVudEluMS5jb25uZWN0KGJwZjEpO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4yID0gbmV3IGxmby5zb3VyY2UuRXZlbnRJbih7XG4gKiAgIGZyYW1lVHlwZTogJ3NjYWxhcicsXG4gKiAgIGZyYW1lU2l6ZTogMSxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGJwZjIgPSBuZXcgbGZvLnNpbmsuQnBmRGlzcGxheSh7XG4gKiAgIGNhbnZhczogJyNicGYtMicsXG4gKiAgIGR1cmF0aW9uOiAyLFxuICogICBzdGFydFRpbWU6IDcsXG4gKiAgIG1pbjogMCxcbiAqICAgY29sb3JzOiBbJ29yYW5nZSddLFxuICogfSk7XG4gKlxuICogY29uc3QgZGlzcGxheVN5bmMgPSBuZXcgbGZvLnV0aWxzLkRpc3BsYXlTeW5jKGJwZjEsIGJwZjIpO1xuICpcbiAqIGV2ZW50SW4yLmNvbm5lY3QoYnBmMik7XG4gKlxuICogZXZlbnRJbjEuc3RhcnQoKTtcbiAqIGV2ZW50SW4yLnN0YXJ0KCk7XG4gKlxuICogbGV0IHRpbWUgPSAwO1xuICogY29uc3QgcGVyaW9kID0gMC40O1xuICogY29uc3Qgb2Zmc2V0ID0gNy4yO1xuICpcbiAqIChmdW5jdGlvbiBnZW5lcmF0ZURhdGEoKSB7XG4gKiAgIGNvbnN0IHYgPSBNYXRoLnJhbmRvbSgpO1xuICpcbiAqICAgZXZlbnRJbjEucHJvY2Vzcyh0aW1lLCB2KTtcbiAqICAgZXZlbnRJbjIucHJvY2Vzcyh0aW1lICsgb2Zmc2V0LCB2KTtcbiAqXG4gKiAgIHRpbWUgKz0gcGVyaW9kO1xuICpcbiAqICAgc2V0VGltZW91dChnZW5lcmF0ZURhdGEsIHBlcmlvZCAqIDEwMDApO1xuICogfSgpKTtcbiAqL1xuY2xhc3MgRGlzcGxheVN5bmMge1xuICBjb25zdHJ1Y3RvciguLi52aWV3cykge1xuICAgIHRoaXMudmlld3MgPSBbXTtcblxuICAgIHRoaXMuYWRkKC4uLnZpZXdzKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBhZGQoLi4udmlld3MpIHtcbiAgICB2aWV3cy5mb3JFYWNoKHZpZXcgPT4gdGhpcy5pbnN0YWxsKHZpZXcpKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBpbnN0YWxsKHZpZXcpIHtcbiAgICB0aGlzLnZpZXdzLnB1c2godmlldyk7XG5cbiAgICB2aWV3LmRpc3BsYXlTeW5jID0gdGhpcztcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBzaGlmdFNpYmxpbmdzKGlTaGlmdCwgdGltZSwgdmlldykge1xuICAgIHRoaXMudmlld3MuZm9yRWFjaChmdW5jdGlvbihkaXNwbGF5KSB7XG4gICAgICBpZiAoZGlzcGxheSAhPT0gdmlldylcbiAgICAgICAgZGlzcGxheS5zaGlmdENhbnZhcyhpU2hpZnQsIHRpbWUpO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERpc3BsYXlTeW5jO1xuIiwiaW1wb3J0IERpc3BsYXlTeW5jIGZyb20gJy4vRGlzcGxheVN5bmMnO1xuaW1wb3J0IGluaXRXaW5kb3dzIGZyb20gJy4uLy4uL2NvbW1vbi91dGlscy93aW5kb3dzJztcblxuZXhwb3J0IGRlZmF1bHQge1xuICBEaXNwbGF5U3luYyxcbiAgaW5pdFdpbmRvd3MsXG59O1xuIiwiY29uc3QgY29sb3JzID0gWycjNDY4MkI0JywgJyNmZmE1MDAnLCAnIzAwZTYwMCcsICcjZmYwMDAwJywgJyM4MDAwODAnLCAnIzIyNDE1MyddO1xuXG5leHBvcnQgY29uc3QgZ2V0Q29sb3JzID0gZnVuY3Rpb24odHlwZSwgbmJyKSB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3NpZ25hbCc6XG4gICAgICByZXR1cm4gY29sb3JzWzBdOyAvLyBzdGVlbGJsdWVcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2JwZic6XG4gICAgICBpZiAobmJyIDw9IGNvbG9ycy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9ycy5zbGljZSgwLCBuYnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgX2NvbG9ycyA9IGNvbG9ycy5zbGljZSgwKTtcbiAgICAgICAgd2hpbGUgKF9jb2xvcnMubGVuZ3RoIDwgbmJyKVxuICAgICAgICAgIF9jb2xvcnMucHVzaChnZXRSYW5kb21Db2xvcigpKTtcblxuICAgICAgICByZXR1cm4gX2NvbG9ycztcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3dhdmVmb3JtJzpcbiAgICAgIHJldHVybiBbY29sb3JzWzBdLCBjb2xvcnNbNV1dOyAvLyBzdGVlbGJsdWUgLyBkYXJrYmx1ZVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnbWFya2VyJzpcbiAgICAgIHJldHVybiBjb2xvcnNbM107IC8vIHJlZFxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc3BlY3RydW0nOlxuICAgICAgcmV0dXJuIGNvbG9yc1syXTsgLy8gZ3JlZW5cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3RyYWNlJzpcbiAgICAgIHJldHVybiBjb2xvcnNbMV07IC8vIG9yYW5nZVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnYmFyLWNoYXJ0JzpcbiAgICAgIHJldHVybiBjb2xvcnM7XG4gICAgICBicmVhaztcbiAgfVxufTtcblxuLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xNDg0NTA2L3JhbmRvbS1jb2xvci1nZW5lcmF0b3ItaW4tamF2YXNjcmlwdFxuZXhwb3J0IGNvbnN0IGdldFJhbmRvbUNvbG9yID0gZnVuY3Rpb24oKSB7XG4gIHZhciBsZXR0ZXJzID0gJzAxMjM0NTY3ODlBQkNERUYnLnNwbGl0KCcnKTtcbiAgdmFyIGNvbG9yID0gJyMnO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IDY7IGkrKyApIHtcbiAgICBjb2xvciArPSBsZXR0ZXJzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDE2KV07XG4gIH1cbiAgcmV0dXJuIGNvbG9yO1xufTtcblxuLy8gc2NhbGUgZnJvbSBkb21haW4gWzAsIDFdIHRvIHJhbmdlIFsyNzAsIDBdIHRvIGNvbnN1bWUgaW5cbi8vIGhzbCh4LCAxMDAlLCA1MCUpIGNvbG9yIHNjaGVtZVxuZXhwb3J0IGNvbnN0IGdldEh1ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIGRvbWFpbk1pbiA9IDA7XG4gIHZhciBkb21haW5NYXggPSAxO1xuICB2YXIgcmFuZ2VNaW4gPSAyNzA7XG4gIHZhciByYW5nZU1heCA9IDA7XG5cbiAgcmV0dXJuICgoKHJhbmdlTWF4IC0gcmFuZ2VNaW4pICogKHggLSBkb21haW5NaW4pKSAvIChkb21haW5NYXggLSBkb21haW5NaW4pKSArIHJhbmdlTWluO1xufTtcblxuZXhwb3J0IGNvbnN0IGhleFRvUkdCID0gZnVuY3Rpb24oaGV4KSB7XG4gIGhleCA9IGhleC5zdWJzdHJpbmcoMSwgNyk7XG4gIHZhciByID0gcGFyc2VJbnQoaGV4LnN1YnN0cmluZygwLCAyKSwgMTYpO1xuICB2YXIgZyA9IHBhcnNlSW50KGhleC5zdWJzdHJpbmcoMiwgNCksIDE2KTtcbiAgdmFyIGIgPSBwYXJzZUludChoZXguc3Vic3RyaW5nKDQsIDYpLCAxNik7XG4gIHJldHVybiBbciwgZywgYl07XG59O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3Qgc2luID0gTWF0aC5zaW47XG5jb25zdCBjb3MgPSBNYXRoLmNvcztcbmNvbnN0IHNxcnQgPSBNYXRoLnNxcnQ7XG5jb25zdCBwb3cgPSBNYXRoLnBvdztcbmNvbnN0IF8yUEkgPSBNYXRoLlBJICogMjtcblxuLy8gcGxvdCAoZnJvbSBodHRwOi8vd3d3LmVhcmxldmVsLmNvbS9zY3JpcHRzL3dpZGdldHMvMjAxMzEwMTMvYmlxdWFkczIuanMpXG4vLyB2YXIgbGVuID0gNTEyO1xuLy8gdmFyIG1hZ1Bsb3QgPSBbXTtcbi8vIGZvciAodmFyIGlkeCA9IDA7IGlkeCA8IGxlbjsgaWR4KyspIHtcbi8vICAgdmFyIHc7XG4vLyAgIGlmIChwbG90VHlwZSA9PSBcImxpbmVhclwiKVxuLy8gICAgIHcgPSBpZHggLyAobGVuIC0gMSkgKiBNYXRoLlBJOyAgLy8gMCB0byBwaSwgbGluZWFyIHNjYWxlXG4vLyAgIGVsc2Vcbi8vICAgICB3ID0gTWF0aC5leHAoTWF0aC5sb2coMSAvIDAuMDAxKSAqIGlkeCAvIChsZW4gLSAxKSkgKiAwLjAwMSAqIE1hdGguUEk7ICAvLyAwLjAwMSB0byAxLCB0aW1lcyBwaSwgbG9nIHNjYWxlXG5cbi8vICAgdmFyIHBoaSA9IE1hdGgucG93KE1hdGguc2luKHcvMiksIDIpO1xuLy8gICB2YXIgeSA9IE1hdGgubG9nKE1hdGgucG93KGEwK2ExK2EyLCAyKSAtIDQqKGEwKmExICsgNCphMCphMiArIGExKmEyKSpwaGkgKyAxNiphMCphMipwaGkqcGhpKSAtIE1hdGgubG9nKE1hdGgucG93KDErYjErYjIsIDIpIC0gNCooYjEgKyA0KmIyICsgYjEqYjIpKnBoaSArIDE2KmIyKnBoaSpwaGkpO1xuLy8gICB5ID0geSAqIDEwIC8gTWF0aC5MTjEwXG4vLyAgIGlmICh5ID09IC1JbmZpbml0eSlcbi8vICAgICB5ID0gLTIwMDtcblxuLy8gICBpZiAocGxvdFR5cGUgPT0gXCJsaW5lYXJcIilcbi8vICAgICBtYWdQbG90LnB1c2goW2lkeCAvIChsZW4gLSAxKSAqIEZzIC8gMiwgeV0pO1xuLy8gICBlbHNlXG4vLyAgICAgbWFnUGxvdC5wdXNoKFtpZHggLyAobGVuIC0gMSkgLyAyLCB5XSk7XG5cbi8vICAgaWYgKGlkeCA9PSAwKVxuLy8gICAgIG1pblZhbCA9IG1heFZhbCA9IHk7XG4vLyAgIGVsc2UgaWYgKHkgPCBtaW5WYWwpXG4vLyAgICAgbWluVmFsID0geTtcbi8vICAgZWxzZSBpZiAoeSA+IG1heFZhbClcbi8vICAgICBtYXhWYWwgPSB5O1xuLy8gfVxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgdHlwZToge1xuICAgIHR5cGU6ICdlbnVtJyxcbiAgICBkZWZhdWx0OiAnbG93cGFzcycsXG4gICAgbGlzdDogW1xuICAgICAgJ2xvd3Bhc3MnLFxuICAgICAgJ2hpZ2hwYXNzJyxcbiAgICAgICdiYW5kcGFzc19jb25zdGFudF9za2lydCcsXG4gICAgICAnYmFuZHBhc3MnLFxuICAgICAgJ2JhbmRwYXNzX2NvbnN0YW50X3BlYWsnLFxuICAgICAgJ25vdGNoJyxcbiAgICAgICdhbGxwYXNzJyxcbiAgICAgICdwZWFraW5nJyxcbiAgICAgICdsb3dzaGVsZicsXG4gICAgICAnaGlnaHNoZWxmJyxcbiAgICBdLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeWFubWljJyB9LFxuICB9LFxuICBmMDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtZXRhczogeyBraW5kOiAnZHlhbm1pYycgfSxcbiAgfSxcbiAgZ2Fpbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtaW46IDAsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5YW5taWMnIH0sXG4gIH0sXG4gIHE6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDEsXG4gICAgbWluOiAwLjAwMSwgLy8gUElQT19CSVFVQURfTUlOX1FcbiAgICAvLyBtYXg6IDEsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5YW5taWMnIH0sXG4gIH0sXG4gIC8vIGJhbmR3aWR0aDoge1xuICAvLyAgIHR5cGU6ICdmbG9hdCcsXG4gIC8vICAgZGVmYXVsdDogbnVsbCxcbiAgLy8gICBudWxsYWJsZTogdHJ1ZSxcbiAgLy8gICBtZXRhczogeyBraW5kOiAnZHlhbm1pYycgfSxcbiAgLy8gfSxcbn1cblxuXG4vKipcbiAqIEJpcXVhZCBmaWx0ZXIgKERpcmVjdCBmb3JtIEkpLiBJZiBpbnB1dCBpcyBvZiB0eXBlIGB2ZWN0b3JgIHRoZSBmaWx0ZXIgaXNcbiAqIGFwcGxpZWQgb24gZWFjaCBkaW1lbnNpb24gaSBwYXJhbGxlbC5cbiAqXG4gKiBCYXNlZCBvbiB0aGUgW1wiQ29va2Jvb2sgZm9ybXVsYWUgZm9yIGF1ZGlvIEVRIGJpcXVhZCBmaWx0ZXIgY29lZmZpY2llbnRzXCJdKGh0dHA6Ly93d3cubXVzaWNkc3Aub3JnL2ZpbGVzL0F1ZGlvLUVRLUNvb2tib29rLnR4dClcbiAqIGJ5IFJvYmVydCBCcmlzdG93LUpvaG5zb24uXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgdmFsdWVzLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLnR5cGU9J2xvd3Bhc3MnXSAtIFR5cGUgb2YgdGhlIGZpbHRlci4gQXZhaWxhYmxlXG4gKiAgZmlsdGVyczogJ2xvd3Bhc3MnLCAnaGlnaHBhc3MnLCAnYmFuZHBhc3NfY29uc3RhbnRfc2tpcnQnLCAnYmFuZHBhc3NfY29uc3RhbnRfcGVhaydcbiAqICAoYWxpYXMgJ2JhbmRwYXNzJyksICdub3RjaCcsICdhbGxwYXNzJywgJ3BlYWtpbmcnLCAnbG93c2hlbGYnLCAnaGlnaHNoZWxmJy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5mMD0xXSAtIEN1dG9mZiBvciBjZW50ZXIgZnJlcXVlbmN5IG9mIHRoZSBmaWx0ZXJcbiAqICBhY2NvcmRpbmcgdG8gaXRzIHR5cGUuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZ2Fpbj0xXSAtIEdhaW4gb2YgdGhlIGZpbHRlciAoaW4gZEIpLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnE9MV0gLSBRdWFsaXR5IGZhY3RvciBvZiB0aGUgZmlsdGVyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gKlxuICogY29uc3QgYXVkaW9JbkJ1ZmZlciA9IG5ldyBsZm8uc291cmNlLkF1ZGlvSW5CdWZmZXIoe1xuICogICBhdWRpb0J1ZmZlcjogYnVmZmVyLFxuICogfSk7XG4gKlxuICogY29uc3QgYmlxdWFkID0gbmV3IGxmby5vcGVyYXRvci5CaXF1YWQoe1xuICogICB0eXBlOiAnbG93cGFzcycsXG4gKiAgIGYwOiAyMDAwLFxuICogICBnYWluOiAzLFxuICogICBxOiAxMixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNwZWN0cnVtRGlzcGxheSA9IG5ldyBsZm8uc2luay5TcGVjdHJ1bURpc3BsYXkoe1xuICogICBjYW52YXM6ICcjc3BlY3RydW0nLFxuICogfSk7XG4gKlxuICogYXVkaW9JbkJ1ZmZlci5jb25uZWN0KGJpcXVhZCk7XG4gKiBiaXF1YWQuY29ubmVjdChzcGVjdHJ1bURpc3BsYXkpO1xuICpcbiAqIGF1ZGlvSW5CdWZmZXIuc3RhcnQoKTtcbiAqL1xuY2xhc3MgQmlxdWFkIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcbiAgfVxuXG4gIG9uUGFyYW1VcGRhdGUobmFtZSwgdmFsdWUsIG1ldGFzKSB7XG4gICAgdGhpcy5fY2FsY3VsYXRlQ29lZnMoKTtcbiAgfVxuXG4gIF9jYWxjdWxhdGVDb2VmcygpIHtcbiAgICBjb25zdCBzYW1wbGVSYXRlID0gdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlUmF0ZTtcbiAgICBjb25zdCBmcmFtZVR5cGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGU7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuXG4gICAgY29uc3QgdHlwZSA9IHRoaXMucGFyYW1zLmdldCgndHlwZScpO1xuICAgIGNvbnN0IGYwID0gdGhpcy5wYXJhbXMuZ2V0KCdmMCcpO1xuICAgIGNvbnN0IGdhaW4gPSB0aGlzLnBhcmFtcy5nZXQoJ2dhaW4nKTtcbiAgICBjb25zdCBxID0gdGhpcy5wYXJhbXMuZ2V0KCdxJyk7XG4gICAgLy8gY29uc3QgYmFuZHdpZHRoID0gdGhpcy5wYXJhbXMuZ2V0KCdiYW5kd2lkdGgnKTtcbiAgICBjb25zdCBiYW5kd2lkdGggPSBudWxsO1xuXG4gICAgbGV0IGIwID0gMCwgYjEgPSAwLCBiMiA9IDAsIGEwID0gMCwgYTEgPSAwLCBhMiA9IDA7XG5cbiAgICBjb25zdCBBID0gcG93KDEwLCBnYWluIC8gNDApO1xuICAgIGNvbnN0IHcwID0gXzJQSSAqIGYwIC8gc2FtcGxlUmF0ZTtcbiAgICBjb25zdCBjb3NXMCA9IGNvcyh3MCk7XG4gICAgY29uc3Qgc2luVzAgPSBzaW4odzApO1xuICAgIGxldCBhbHBoYTsgLy8gZGVwZW5kIG9mIHRoZSBmaWx0ZXIgdHlwZVxuICAgIGxldCBfMlJvb3RBQWxwaGE7IC8vIGludGVybWVkaWF0ZSB2YWx1ZSBmb3IgbG93c2hlbGYgYW5kIGhpZ2hzaGVsZlxuXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAvLyBIKHMpID0gMSAvIChzXjIgKyBzL1EgKyAxKVxuICAgICAgY2FzZSAnbG93cGFzcyc6XG4gICAgICAgIGFscGhhID0gc2luVzAgLyAoMiAqIHEpO1xuICAgICAgICBiMCA9ICgxIC0gY29zVzApIC8gMjtcbiAgICAgICAgYjEgPSAxIC0gY29zVzA7XG4gICAgICAgIGIyID0gYjA7XG4gICAgICAgIGEwID0gMSArIGFscGhhO1xuICAgICAgICBhMSA9IC0yICogY29zVzA7XG4gICAgICAgIGEyID0gMSAtYWxwaGE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gSChzKSA9IHNeMiAvIChzXjIgKyBzL1EgKyAxKVxuICAgICAgY2FzZSAnaGlnaHBhc3MnOlxuICAgICAgICBhbHBoYSA9IHNpblcwIC8gKDIgKiBxKTtcbiAgICAgICAgYjAgPSAoMSArIGNvc1cwKSAvIDI7XG4gICAgICAgIGIxID0gLSAoMSArIGNvc1cwKVxuICAgICAgICBiMiA9IGIwO1xuICAgICAgICBhMCA9IDEgKyBhbHBoYTtcbiAgICAgICAgYTEgPSAtMiAqIGNvc1cwO1xuICAgICAgICBhMiA9IDEgLSBhbHBoYTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBIKHMpID0gcyAvIChzXjIgKyBzL1EgKyAxKSAgKGNvbnN0YW50IHNraXJ0IGdhaW4sIHBlYWsgZ2FpbiA9IFEpXG4gICAgICBjYXNlICdiYW5kcGFzc19jb25zdGFudF9za2lydCc6XG4gICAgICAgIGlmIChiYW5kd2lkdGgpIHtcbiAgICAgICAgICAvLyBzaW4odzApKnNpbmgoIGxuKDIpLzIgKiBCVyAqIHcwL3Npbih3MCkgKSAgICAgICAgICAgKGNhc2U6IEJXKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFscGhhID0gc2luVzAgLyAoMiAqIHEpO1xuICAgICAgICB9XG5cbiAgICAgICAgYjAgPSBzaW5XMCAvIDI7XG4gICAgICAgIGIxID0gMDtcbiAgICAgICAgYjIgPSAtYjA7XG4gICAgICAgIGEwID0gMSArIGFscGhhO1xuICAgICAgICBhMSA9IC0yICogY29zVzA7XG4gICAgICAgIGEyID0gMSAtIGFscGhhO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIEgocykgPSAocy9RKSAvIChzXjIgKyBzL1EgKyAxKSAgICAgIChjb25zdGFudCAwIGRCIHBlYWsgZ2FpbilcbiAgICAgIGNhc2UgJ2JhbmRwYXNzJzogLy8gbG9va3MgbGlrZSB3aGF0IGlzIGduZXJhbGx5IGNvbnNpZGVyZWQgYXMgYSBiYW5kcGFzc1xuICAgICAgY2FzZSAnYmFuZHBhc3NfY29uc3RhbnRfcGVhayc6XG4gICAgICAgIGlmIChiYW5kd2lkdGgpIHtcbiAgICAgICAgICAvLyBzaW4odzApKnNpbmgoIGxuKDIpLzIgKiBCVyAqIHcwL3Npbih3MCkgKSAgICAgICAgICAgKGNhc2U6IEJXKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFscGhhID0gc2luVzAgLyAoMiAqIHEpO1xuICAgICAgICB9XG5cbiAgICAgICAgYjAgPSBhbHBoYTtcbiAgICAgICAgYjEgPSAwO1xuICAgICAgICBiMiA9IC1hbHBoYTtcbiAgICAgICAgYTAgPSAxICsgYWxwaGE7XG4gICAgICAgIGExID0gLTIgKiBjb3NXMDtcbiAgICAgICAgYTIgPSAxIC0gYWxwaGE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gSChzKSA9IChzXjIgKyAxKSAvIChzXjIgKyBzL1EgKyAxKVxuICAgICAgY2FzZSAnbm90Y2gnOlxuICAgICAgICBhbHBoYSA9IHNpblcwIC8gKDIgKiBxKTtcbiAgICAgICAgYjAgPSAxO1xuICAgICAgICBiMSA9IC0yICogY29zVzA7XG4gICAgICAgIGIyID0gMTtcbiAgICAgICAgYTAgPSAxICsgYWxwaGE7XG4gICAgICAgIGExID0gYjE7XG4gICAgICAgIGEyID0gMSAtIGFscGhhO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIEgocykgPSAoc14yIC0gcy9RICsgMSkgLyAoc14yICsgcy9RICsgMSlcbiAgICAgIGNhc2UgJ2FsbHBhc3MnOlxuICAgICAgICBhbHBoYSA9IHNpblcwIC8gKDIgKiBxKTtcbiAgICAgICAgYjAgPSAxIC0gYWxwaGE7XG4gICAgICAgIGIxID0gLTIgKiBjb3NXMDtcbiAgICAgICAgYjIgPSAxICsgYWxwaGE7XG4gICAgICAgIGEwID0gYjI7XG4gICAgICAgIGExID0gYjE7XG4gICAgICAgIGEyID0gYjA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gSChzKSA9IChzXjIgKyBzKihBL1EpICsgMSkgLyAoc14yICsgcy8oQSpRKSArIDEpXG4gICAgICBjYXNlICdwZWFraW5nJzpcbiAgICAgICAgaWYgKGJhbmR3aWR0aCkge1xuICAgICAgICAgIC8vIHNpbih3MCkqc2luaCggbG4oMikvMiAqIEJXICogdzAvc2luKHcwKSApICAgICAgICAgICAoY2FzZTogQlcpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWxwaGEgPSBzaW5XMCAvICgyICogcSk7XG4gICAgICAgIH1cblxuICAgICAgICBiMCA9IDEgKyBhbHBoYSAqIEE7XG4gICAgICAgIGIxID0gLTIgKiBjb3NXMDtcbiAgICAgICAgYjIgPSAxIC0gYWxwaGEgKiBBO1xuICAgICAgICBhMCA9IDEgKyBhbHBoYSAvIEE7XG4gICAgICAgIGExID0gYjE7XG4gICAgICAgIGEyID0gMSAtIGFscGhhIC8gQTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBIKHMpID0gQSAqIChzXjIgKyAoc3FydChBKS9RKSpzICsgQSkvKEEqc14yICsgKHNxcnQoQSkvUSkqcyArIDEpXG4gICAgICBjYXNlICdsb3dzaGVsZic6XG4gICAgICAgIGFscGhhID0gc2luVzAgLyAoMiAqIHEpO1xuICAgICAgICBfMlJvb3RBQWxwaGEgPSAyICogc3FydChBKSAqIGFscGhhO1xuXG4gICAgICAgIGIwID0gICAgIEEgKiAoKEEgKyAxKSAtIChBIC0gMSkgKiBjb3NXMCArIF8yUm9vdEFBbHBoYSk7XG4gICAgICAgIGIxID0gMiAqIEEgKiAoKEEgLSAxKSAtIChBICsgMSkgKiBjb3NXMCk7XG4gICAgICAgIGIyID0gICAgIEEgKiAoKEEgKyAxKSAtIChBIC0gMSkgKiBjb3NXMCAtIF8yUm9vdEFBbHBoYSk7XG4gICAgICAgIGEwID0gICAgICAgICAgKEEgKyAxKSArIChBIC0gMSkgKiBjb3NXMCArIF8yUm9vdEFBbHBoYTtcbiAgICAgICAgYTEgPSAgICAtMiAqICgoQSAtIDEpICsgKEEgKyAxKSAqIGNvc1cwKTtcbiAgICAgICAgYTIgPSAgICAgICAgICAoQSArIDEpICsgKEEgLSAxKSAqIGNvc1cwIC0gXzJSb290QUFscGhhO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIEgocykgPSBBICogKEEqc14yICsgKHNxcnQoQSkvUSkqcyArIDEpLyhzXjIgKyAoc3FydChBKS9RKSpzICsgQSlcbiAgICAgIGNhc2UgJ2hpZ2hzaGVsZic6XG4gICAgICAgIGFscGhhID0gc2luVzAgLyAoMiAqIHEpO1xuICAgICAgICBfMlJvb3RBQWxwaGEgPSAyICogc3FydChBKSAqIGFscGhhO1xuXG4gICAgICAgIGIwID0gICAgICBBICogKChBICsgMSkgKyAoQSAtIDEpICogY29zVzAgKyBfMlJvb3RBQWxwaGEpO1xuICAgICAgICBiMSA9IC0yICogQSAqICgoQSAtIDEpICsgKEEgKyAxKSAqIGNvc1cwKTtcbiAgICAgICAgYjIgPSAgICAgIEEgKiAoKEEgKyAxKSArIChBIC0gMSkgKiBjb3NXMCAtIF8yUm9vdEFBbHBoYSk7XG4gICAgICAgIGEwID0gICAgICAgICAgIChBICsgMSkgLSAoQSAtIDEpICogY29zVzAgKyBfMlJvb3RBQWxwaGE7XG4gICAgICAgIGExID0gICAgICAyICogKChBIC0gMSkgLSAoQSArIDEpICogY29zVzApO1xuICAgICAgICBhMiA9ICAgICAgICAgICAoQSArIDEpIC0gKEEgLSAxKSAqIGNvc1cwIC0gXzJSb290QUFscGhhO1xuXG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMuY29lZnMgPSB7XG4gICAgICBiMDogYjAgLyBhMCxcbiAgICAgIGIxOiBiMSAvIGEwLFxuICAgICAgYjI6IGIyIC8gYTAsXG4gICAgICBhMTogYTEgLyBhMCxcbiAgICAgIGEyOiBhMiAvIGEwLFxuICAgIH07XG5cbiAgICAvLyByZXNldCBzdGF0ZVxuICAgIGlmIChmcmFtZVR5cGUgPT09ICdzaWduYWwnKSB7XG4gICAgICB0aGlzLnN0YXRlID0geyB4MTogMCwgeDI6IDAsIHkxOiAwLCB5MjogMCB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICB4MTogbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpLFxuICAgICAgICB4MjogbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpLFxuICAgICAgICB5MTogbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpLFxuICAgICAgICB5MjogbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgLy8gaWYgbm8gYHNhbXBsZVJhdGVgIG9yIGBzYW1wbGVSYXRlYCBpcyAwIHdlIHNoYWxsIGhhbHQhXG4gICAgY29uc3Qgc2FtcGxlUmF0ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGU7XG5cbiAgICBpZiAoIXNhbXBsZVJhdGUgfHwgc2FtcGxlUmF0ZSA8PSAwKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNhbXBsZVJhdGUgdmFsdWUgKDApIGZvciBiaXF1YWQnKTtcblxuICAgIHRoaXMuX2NhbGN1bGF0ZUNvZWZzKCk7XG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKGZyYW1lKSB7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgaW5EYXRhID0gZnJhbWUuZGF0YTtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgY29uc3QgY29lZnMgPSB0aGlzLmNvZWZzO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKykge1xuICAgICAgY29uc3QgeCA9IGluRGF0YVtpXTtcbiAgICAgIGNvbnN0IHkgPSBjb2Vmcy5iMCAqIHhcbiAgICAgICAgICAgICAgKyBjb2Vmcy5iMSAqIHN0YXRlLngxW2ldICsgY29lZnMuYjIgKiBzdGF0ZS54MltpXVxuICAgICAgICAgICAgICAtIGNvZWZzLmExICogc3RhdGUueTFbaV0gLSBjb2Vmcy5hMiAqIHN0YXRlLnkyW2ldO1xuXG4gICAgICBvdXREYXRhW2ldID0geTtcblxuICAgICAgLy8gdXBkYXRlIHN0YXRlc1xuICAgICAgc3RhdGUueDJbaV0gPSBzdGF0ZS54MVtpXTtcbiAgICAgIHN0YXRlLngxW2ldID0geDtcbiAgICAgIHN0YXRlLnkyW2ldID0gc3RhdGUueTFbaV07XG4gICAgICBzdGF0ZS55MVtpXSA9IHk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUpIHtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcbiAgICBjb25zdCBpbkRhdGEgPSBmcmFtZS5kYXRhO1xuICAgIGNvbnN0IHN0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICBjb25zdCBjb2VmcyA9IHRoaXMuY29lZnM7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKSB7XG4gICAgICBjb25zdCB4ID0gaW5EYXRhW2ldO1xuICAgICAgY29uc3QgeSA9IGNvZWZzLmIwICogeFxuICAgICAgICAgICAgICArIGNvZWZzLmIxICogc3RhdGUueDEgKyBjb2Vmcy5iMiAqIHN0YXRlLngyXG4gICAgICAgICAgICAgIC0gY29lZnMuYTEgKiBzdGF0ZS55MSAtIGNvZWZzLmEyICogc3RhdGUueTI7XG5cbiAgICAgIG91dERhdGFbaV0gPSB5O1xuXG4gICAgICAvLyB1cGRhdGUgc3RhdGVzXG4gICAgICBzdGF0ZS54MiA9IHN0YXRlLngxO1xuICAgICAgc3RhdGUueDEgPSB4O1xuICAgICAgc3RhdGUueTIgPSBzdGF0ZS55MTtcbiAgICAgIHN0YXRlLnkxID0geTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQmlxdWFkO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIG1pbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMCxcbiAgICBtaW46IC1JbmZpbml0eSxcbiAgICBtYXg6ICtJbmZpbml0eSxcbiAgfSxcbiAgbWF4OiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAxLFxuICAgIG1pbjogLUluZmluaXR5LFxuICAgIG1heDogK0luZmluaXR5LFxuICB9LFxufTtcblxuLyoqXG4gKiBDbGlwIGluY29tbWluZyBhY2NvcmRpbmcgdG8gZ2l2ZW4gYG1pbmAgYW5kIGBtYXhgIHBhcmFtZXRlcnNcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW10ZXJzXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWluPTBdIC0gTWluaW11bSB2YWx1ZVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heD0xXSAtIE1heGltdW0gdmFsdWVcbiAqL1xuY2xhc3MgQ2xpcCBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICB9XG5cbiAgaW5wdXRWZWN0b3IoZGF0YSkge1xuICAgIGNvbnN0IG1pbiA9IHRoaXMucGFyYW1zLmdldCgnbWluJyk7XG4gICAgY29uc3QgbWF4ID0gdGhpcy5wYXJhbXMuZ2V0KCdtYXgnKTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcblxuICAgIC8vIEB0b2RvIC0gY291bGQgaGFuZGxlIHZlY3RvciBhcyBtaW4gYW5kIG1heFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspXG4gICAgICBvdXREYXRhW2ldID0gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIGRhdGFbaV0pKTtcblxuICAgIHJldHVybiBvdXREYXRhO1xuICB9XG5cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSkge1xuICAgIHRoaXMuZnJhbWUuZGF0YSA9IHRoaXMuaW5wdXRWZWN0b3IoZnJhbWUuZGF0YSk7XG4gIH1cblxuICBpbnB1dFNpZ25hbChkYXRhKSB7XG4gICAgY29uc3QgbWluID0gdGhpcy5wYXJhbXMuZ2V0KCdtaW4nKTtcbiAgICBjb25zdCBtYXggPSB0aGlzLnBhcmFtcy5nZXQoJ21heCcpO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBvdXREYXRhID0gdGhpcy5mcmFtZS5kYXRhO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgIG91dERhdGFbaV0gPSBNYXRoLm1pbihtYXgsIE1hdGgubWF4KG1pbiwgZGF0YVtpXSkpO1xuXG4gICAgcmV0dXJuIG91dERhdGE7XG4gIH1cblxuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgdGhpcy5mcmFtZS5kYXRhID0gdGhpcy5pbnB1dFNpZ25hbChmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDbGlwO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3Qgc3FydCA9IE1hdGguc3FydDtcbmNvbnN0IGNvcyA9IE1hdGguY29zO1xuY29uc3QgUEkgPSBNYXRoLlBJO1xuXG4vLyBEY3QgVHlwZSAyIC0gb3J0aG9nb25hbCBtYXRyaXggc2NhbGluZ1xuZnVuY3Rpb24gZ2V0RGN0V2VpZ2h0cyhvcmRlciwgTiwgdHlwZSA9ICdodGsnKSB7XG4gIGNvbnN0IHdlaWdodHMgPSBuZXcgRmxvYXQzMkFycmF5KE4gKiBvcmRlcik7XG4gIGNvbnN0IHBpT3Zlck4gPSBQSSAvIE47XG4gIGNvbnN0IHNjYWxlMCA9IDEgLyBzcXJ0KDIpO1xuICBjb25zdCBzY2FsZSA9IHNxcnQoMiAvIE4pO1xuXG4gIGZvciAobGV0IGsgPSAwOyBrIDwgb3JkZXI7IGsrKykge1xuICAgIGNvbnN0IHMgPSAoayA9PT0gMCkgPyAoc2NhbGUwICogc2NhbGUpIDogc2NhbGU7XG4gICAgLy8gY29uc3QgcyA9IHNjYWxlOyAvLyBydGEgZG9lc24ndCBhcHBseSBrPTAgc2NhbGluZ1xuXG4gICAgZm9yIChsZXQgbiA9IDA7IG4gPCBOOyBuKyspXG4gICAgICB3ZWlnaHRzW2sgKiBOICsgbl0gPSBzICogY29zKGsgKiAobiArIDAuNSkgKiBwaU92ZXJOKTtcbiAgfVxuXG4gIHJldHVybiB3ZWlnaHRzO1xufVxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgb3JkZXI6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogMTIsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbn07XG5cbi8qKlxuICogQ29tcHV0ZSB0aGUgRGlzY3JldGUgQ29zaW5lIFRyYW5zZm9ybSBvZiBhbiBpbnB1dCBgc2lnbmFsYCBvciBgdmVjdG9yYC5cbiAqIChIVEsgc3R5bGUgd2VpZ2h0aW5nKS5cbiAqXG4gKiBfc3VwcG9ydCBgc3RhbmRhbG9uZWAgdXNhZ2VfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5vcmRlcj0xMl0gLSBOdW1iZXIgb2YgY29tcHV0ZWQgYmlucy5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIC8vIGFzc3VtaW5nIHNvbWUgYXVkaW8gYnVmZmVyXG4gKiBjb25zdCBzb3VyY2UgPSBuZXcgQXVkaW9JbkJ1ZmZlcih7XG4gKiAgIGF1ZGlvQnVmZmVyOiBhdWRpb0J1ZmZlcixcbiAqICAgdXNlV29ya2VyOiBmYWxzZSxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNsaWNlciA9IG5ldyBTbGljZXIoe1xuICogICBmcmFtZVNpemU6IDUxMixcbiAqICAgaG9wU2l6ZTogNTEyLFxuICogfSk7XG4gKlxuICogY29uc3QgZGN0ID0gbmV3IERjdCh7XG4gKiAgIG9yZGVyOiAxMixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIHNvdXJjZS5jb25uZWN0KHNsaWNlcik7XG4gKiBzbGljZXIuY29ubmVjdChkY3QpO1xuICogZGN0LmNvbm5lY3QobG9nZ2VyKTtcbiAqXG4gKiBzb3VyY2Uuc3RhcnQoKTtcbiAqL1xuY2xhc3MgRGN0IGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICBjb25zdCBvcmRlciA9IHRoaXMucGFyYW1zLmdldCgnb3JkZXInKTtcbiAgICBjb25zdCBpbkZyYW1lU2l6ZSA9IHByZXZTdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gb3JkZXI7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlID0gJ3ZlY3Rvcic7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZGVzY3JpcHRpb24gPSBbXTtcblxuICAgIHRoaXMud2VpZ2h0TWF0cml4ID0gZ2V0RGN0V2VpZ2h0cyhvcmRlciwgaW5GcmFtZVNpemUpO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2UgdGhlIGBEY3RgIG9wZXJhdG9yIGluIGBzdGFuZGFsb25lYCBtb2RlIChpLmUuIG91dHNpZGUgb2YgYSBncmFwaCkuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyAtIElucHV0IHZhbHVlcy5cbiAgICogQHJldHVybiB7QXJyYXl9IC0gRGN0IG9mIHRoZSBpbnB1dCBhcnJheS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgZGN0ID0gbmV3IGxmby5vcGVyYXRvci5EY3QoeyBvcmRlcjogMTIgfSk7XG4gICAqIC8vIG1hbmRhdG9yeSBmb3IgdXNlIGluIHN0YW5kYWxvbmUgbW9kZVxuICAgKiBkY3QuaW5pdFN0cmVhbSh7IGZyYW1lU2l6ZTogNTEyLCBmcmFtZVR5cGU6ICdzaWduYWwnIH0pO1xuICAgKiBkY3QuaW5wdXRTaWduYWwoZGF0YSk7XG4gICAqL1xuICBpbnB1dFNpZ25hbCh2YWx1ZXMpIHtcbiAgICBjb25zdCBvcmRlciA9IHRoaXMucGFyYW1zLmdldCgnb3JkZXInKTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB2YWx1ZXMubGVuZ3RoO1xuICAgIGNvbnN0IG91dEZyYW1lID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0aGlzLndlaWdodE1hdHJpeDtcblxuICAgIGZvciAobGV0IGsgPSAwOyBrIDwgb3JkZXI7IGsrKykge1xuICAgICAgY29uc3Qgb2Zmc2V0ID0gayAqIGZyYW1lU2l6ZTtcbiAgICAgIG91dEZyYW1lW2tdID0gMDtcblxuICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCBmcmFtZVNpemU7IG4rKylcbiAgICAgICAgb3V0RnJhbWVba10gKz0gdmFsdWVzW25dICogd2VpZ2h0c1tvZmZzZXQgKyBuXTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0RnJhbWU7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbChmcmFtZSkge1xuICAgIHRoaXMuaW5wdXRTaWduYWwoZnJhbWUuZGF0YSk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSkge1xuICAgIHRoaXMuaW5wdXRTaWduYWwoZnJhbWUuZGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRGN0O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuXG5mdW5jdGlvbiBzaW1wbGVMaW5lYXJSZWdyZXNzaW9uKHZhbHVlcywgZHQpIHtcbiAgLy8gbWVhbnNcbiAgbGV0IHhTdW0gPSAwO1xuICBsZXQgeVN1bSA9IDA7XG4gIGNvbnN0IGxlbmd0aCA9IHZhbHVlcy5sZW5ndGg7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIHhTdW0gKz0gaSAqIGR0O1xuICAgIHlTdW0gKz0gdmFsdWVzW2ldO1xuICB9XG5cbiAgY29uc3QgeE1lYW4gPSB4U3VtIC8gbGVuZ3RoO1xuICBjb25zdCB5TWVhbiA9IHlTdW0gLyBsZW5ndGg7XG5cbiAgbGV0IHN1bURpZmZYTWVhblNxdWFyZWQgPSAwOyAvLyBzdW1bIHBvdygoeCAtIHhNZWFuKSwgMikgXVxuICBsZXQgc3VtRGlmZllNZWFuU3F1YXJlZCA9IDA7IC8vIHN1bVsgcG93KCh5IC0geU1lYW4pLCAyKSBdXG4gIGxldCBzdW1EaWZmWFlNZWFuID0gMDsgICAgICAgLy8gc3VtWyAoeCAtIHhNZWFuKSh5IC0geU1lYW4pIF1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZGlmZlhNZWFuID0gZHQgKiBpIC0geE1lYW47XG4gICAgY29uc3QgZGlmZllNZWFuID0gdmFsdWVzW2ldIC0geU1lYW47XG5cbiAgICBjb25zdCBkaWZmWE1lYW5TcXVhcmVkID0gZGlmZlhNZWFuICogZGlmZlhNZWFuO1xuICAgIGNvbnN0IGRpZmZZTWVhblNxdWFyZWQgPSBkaWZmWU1lYW4gKiBkaWZmWU1lYW47XG4gICAgY29uc3QgZGlmZlhZTWVhbiA9IGRpZmZYTWVhbiAqIGRpZmZZTWVhbjtcblxuICAgIHN1bURpZmZYTWVhblNxdWFyZWQgKz0gZGlmZlhNZWFuU3F1YXJlZDtcbiAgICBzdW1EaWZmWU1lYW5TcXVhcmVkICs9IGRpZmZZTWVhblNxdWFyZWQ7XG4gICAgc3VtRGlmZlhZTWVhbiArPSBkaWZmWFlNZWFuO1xuICB9XG5cbiAgLy8gaG9yaXpvbnRhbCBsaW5lLCBhbGwgeSBvbiBzYW1lIGxpbmVcbiAgaWYgKHN1bURpZmZZTWVhblNxdWFyZWQgPT09IDApXG4gICAgcmV0dXJuIDA7XG5cbiAgLy8gUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudDpcbiAgLy8gY2YuIGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9MlNDZzhLdWgwdEVcbiAgLy9cbiAgLy8gICAgICAgICAgICAgICAgIOKIkSBbICh4IC0geE1lYW4pKHkgLSB5TWVhbikgXVxuICAvLyByID0gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vICAgICBzcXJ0KCDiiJHCoFsgcG93KCh4IC0geE1lYW4pLCAyKSwgcG93KCh5IC0geU1lYW4pLCAyKSBdIClcbiAgLy9cbiAgLy9cbiAgY29uc3QgciA9IHN1bURpZmZYWU1lYW4gLyBNYXRoLnNxcnQoc3VtRGlmZlhNZWFuU3F1YXJlZCAqIHN1bURpZmZZTWVhblNxdWFyZWQpO1xuXG4gIC8vIHRoZW4gd2UgaGF2ZTpcbiAgLy8gY2YuIGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9R2hyeGdiUW5FRVVcbiAgLy9cbiAgLy8geSA9IGEgKyBieFxuICAvLyB3aGVyZTpcbiAgLy8gICAgICAgICBTeVxuICAvLyBiID0gciAqIC0tXG4gIC8vICAgICAgICAgU3hcbiAgLy9cbiAgLy8gYSA9IHlNZWFuIC0gYiAqIHhNZWFuXG4gIC8vXG4gIC8vIFMgZm9yIHN0YW5kYXJkIGRldmlhdGlvblxuICAvLyAgICAgICAgICAgIOKIkSBbIHBvdygoeCAtIHhNZWFuKSwgMikgXVxuICAvLyBTeCA9IHNxcnQoIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIClcbiAgLy8gICAgICAgICAgICAgICAgICAgICAgTiAtIDFcbiAgY29uc3QgU3ggPSBNYXRoLnNxcnQoc3VtRGlmZlhNZWFuU3F1YXJlZCAvIChsZW5ndGggLSAxKSk7XG4gIGNvbnN0IFN5ID0gTWF0aC5zcXJ0KHN1bURpZmZZTWVhblNxdWFyZWQgLyAobGVuZ3RoIC0gMSkpO1xuICBjb25zdCBiID0gciAqIChTeSAvIFN4KTtcblxuICByZXR1cm4gYjtcbn1cblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIHNpemU6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgbWluOiAyLFxuICAgIG1heDogK0luZmluaXR5LFxuICAgIGRlZmF1bHQ6IDMsXG4gIH0sXG4gIHVzZUZyYW1lUmF0ZToge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBtaW46IDAsXG4gICAgbWF4OiArSW5maW5pdHksXG4gICAgZGVmYXVsdDogbnVsbCxcbiAgICBudWxsYWJsZTogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc2ltcGxlIGRlcml2YXRpdmUgb2Ygc3VjY2Vzc2l2ZSB2YWx1ZSB1c2luZ1xuICogc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uLlxuICogVGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24gYXNzdW1lcyBhIGZpeGVkIGBmcmFtZVJhdGVgIChgZnJhbWUudGltZWAgaXMgaWdub3JlZClcbiAqXG4gKiBCZWZvcmUgdGhlIG1vZHVsZSBpcyBmaWxsZWQsIGl0IG91dHB1dHMgYSB2YWx1ZSBvZiAwLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc2l6ZT0zXSAtIFNpemUgb2YgdGhlIHdpbmRvd1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnVzZUZyYW1lUmF0ZT1udWxsXSAtIE92ZXJyaWRlIHN0cmVhbSBmcmFtZSByYXRlIGZvclxuICogIHRoZSByZWdyZXNzaW9uXG4gKi9cbmNsYXNzIERlbHRhIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPcKge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLmJ1ZmZlcnMgPSBudWxsO1xuICAgIHRoaXMucmluZ0luZGV4ID0gMDtcbiAgICB0aGlzLmZyYW1lUmF0ZSA9IG51bGw7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ3NpemUnKTtcbiAgICBjb25zdCBidWZmZXJTaXplID0gZnJhbWVTaXplICogc2l6ZTtcblxuICAgIHRoaXMuYnVmZmVycyA9IFtdO1xuICAgIC8vIGNvdW50ZXIgYmVmb3JlIHRoZSBvcGVyYXRvciBzdGFydHMgb3V0cHV0aW5nIGZyYW1lc1xuICAgIHRoaXMucmluZ0luZGV4ID0gMDtcbiAgICB0aGlzLmZyYW1lUmF0ZSA9IHRoaXMucGFyYW1zLmdldCgndXNlRnJhbWVSYXRlJykgPT09IG51bGwgP1xuICAgICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVSYXRlIDpcbiAgICAgIHRoaXMucGFyYW1zLmdldCgndXNlRnJhbWVSYXRlJyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICAgICAgdGhpcy5idWZmZXJzW2ldID0gbmV3IEZsb2F0MzJBcnJheShzaXplKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcblxuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBzaXplID0gdGhpcy5wYXJhbXMuZ2V0KCdzaXplJyk7XG4gICAgY29uc3QgYnVmZmVycyA9IHRoaXMuYnVmZmVycztcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspIHtcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgc2l6ZTsgaisrKVxuICAgICAgICBidWZmZXJzW2ldW2pdID0gMDtcbiAgICB9XG5cbiAgICB0aGlzLnJpbmdJbmRleCA9IDA7XG4gIH1cblxuICAvKipcbiAgICogQXNzdW1lIGEgc3RyZWFtIG9mIHZlY3RvciBhdCBhIGZpeGVkIGBmcmFtZVJhdGVgLlxuICAgKi9cbiAgaW5wdXRWZWN0b3IoZGF0YSkge1xuICAgIGNvbnN0IHNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ3NpemUnKTtcbiAgICBjb25zdCBvdXREYXRhID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICAvLyBjb25zdCBmcmFtZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVJhdGU7XG4gICAgY29uc3QgYnVmZmVycyA9IHRoaXMuYnVmZmVycztcbiAgICBjb25zdCBkdCA9IDEgLyB0aGlzLmZyYW1lUmF0ZTtcblxuICAgIC8vIGNvbnNvbGUubG9nKGR0KTtcblxuICAgIGlmICh0aGlzLnJpbmdJbmRleCA8IHNpemUpXG4gICAgICB0aGlzLnJpbmdJbmRleCArPSAxO1xuXG4gICAgLy8gY29weSBpbmNvbW1pbmcgZGF0YSBpbnRvIGJ1ZmZlclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspIHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IGJ1ZmZlcnNbaV07XG5cbiAgICAgIC8vIHdlIG5lZWQgdG8ga2VlcCB0aGUgb3JkZXIgb2YgdGhlIGluY29tbWluZyBmcmFtZXNcbiAgICAgIC8vIHNvIHdlIGhhdmUgdG8gc2hpZnQgYWxsIHRoZSB2YWx1ZXMgaW4gdGhlIGJ1ZmZlcnNcbiAgICAgIGZvciAobGV0IGogPSAxOyBqIDwgc2l6ZTsgaisrKVxuICAgICAgICBidWZmZXJbaiAtIDFdID0gYnVmZmVyW2pdO1xuXG4gICAgICBidWZmZXJbc2l6ZSAtIDFdID0gZGF0YVtpXTtcblxuICAgICAgaWYgKHRoaXMucmluZ0luZGV4ID49IHNpemUpXG4gICAgICAgIG91dERhdGFbaV0gPSBzaW1wbGVMaW5lYXJSZWdyZXNzaW9uKGJ1ZmZlciwgZHQpO1xuICAgICAgZWxzZVxuICAgICAgICBvdXREYXRhW2ldID0gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0RGF0YTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKGZyYW1lKSB7XG4gICAgdGhpcy5mcmFtZS5kYXRhID0gdGhpcy5pbnB1dFZlY3RvcihmcmFtZS5kYXRhKTtcbiAgICAvLyBjZW50ZXIgdGltZSBhY2NvcmRpbmcgdG8gZGVsdGEgc2l6ZVxuICAgIGNvbnN0IHNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ3NpemUnKTtcbiAgICBjb25zdCBmcmFtZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVJhdGU7XG4gICAgdGhpcy5mcmFtZS50aW1lIC09IDAuNSAqIChzaXplIC0gMSkgLyBmcmFtZVJhdGU7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRGVsdGE7XG5cblxuXG5cblxuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcbmltcG9ydCBpbml0V2luZG93IGZyb20gJy4uL3V0aWxzL3dpbmRvd3MnO1xuXG4vLyBodHRwczovL2NvZGUuc291bmRzb2Z0d2FyZS5hYy51ay9wcm9qZWN0cy9qcy1kc3AtdGVzdC9yZXBvc2l0b3J5L2VudHJ5L2ZmdC9uYXl1a2ktb2JqL2ZmdC5qc1xuLypcbiAqIEZyZWUgRmZ0IGFuZCBjb252b2x1dGlvbiAoSmF2YVNjcmlwdClcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQgUHJvamVjdCBOYXl1a2lcbiAqIGh0dHA6Ly93d3cubmF5dWtpLmlvL3BhZ2UvZnJlZS1zbWFsbC1mZnQtaW4tbXVsdGlwbGUtbGFuZ3VhZ2VzXG4gKlxuICogKE1JVCBMaWNlbnNlKVxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weSBvZlxuICogdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpblxuICogdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0b1xuICogdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2ZcbiAqIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbyxcbiAqIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICogLSBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuICogICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqIC0gVGhlIFNvZnR3YXJlIGlzIHByb3ZpZGVkIFwiYXMgaXNcIiwgd2l0aG91dCB3YXJyYW50eSBvZiBhbnkga2luZCwgZXhwcmVzcyBvclxuICogICBpbXBsaWVkLCBpbmNsdWRpbmcgYnV0IG5vdCBsaW1pdGVkIHRvIHRoZSB3YXJyYW50aWVzIG9mIG1lcmNoYW50YWJpbGl0eSxcbiAqICAgZml0bmVzcyBmb3IgYSBwYXJ0aWN1bGFyIHB1cnBvc2UgYW5kIG5vbmluZnJpbmdlbWVudC4gSW4gbm8gZXZlbnQgc2hhbGwgdGhlXG4gKiAgIGF1dGhvcnMgb3IgY29weXJpZ2h0IGhvbGRlcnMgYmUgbGlhYmxlIGZvciBhbnkgY2xhaW0sIGRhbWFnZXMgb3Igb3RoZXJcbiAqICAgbGlhYmlsaXR5LCB3aGV0aGVyIGluIGFuIGFjdGlvbiBvZiBjb250cmFjdCwgdG9ydCBvciBvdGhlcndpc2UsIGFyaXNpbmcgZnJvbSxcbiAqICAgb3V0IG9mIG9yIGluIGNvbm5lY3Rpb24gd2l0aCB0aGUgU29mdHdhcmUgb3IgdGhlIHVzZSBvciBvdGhlciBkZWFsaW5ncyBpbiB0aGVcbiAqICAgU29mdHdhcmUuXG4gKlxuICogU2xpZ2h0bHkgcmVzdHJ1Y3R1cmVkIGJ5IENocmlzIENhbm5hbSwgY2FubmFtQGFsbC1kYXktYnJlYWtmYXN0LmNvbVxuICpcbiAqIEBwcml2YXRlXG4gKi9cbi8qXG4gKiBDb25zdHJ1Y3QgYW4gb2JqZWN0IGZvciBjYWxjdWxhdGluZyB0aGUgZGlzY3JldGUgRm91cmllciB0cmFuc2Zvcm0gKERGVCkgb2ZcbiAqIHNpemUgbiwgd2hlcmUgbiBpcyBhIHBvd2VyIG9mIDIuXG4gKlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gRmZ0TmF5dWtpKG4pIHtcblxuICB0aGlzLm4gPSBuO1xuICB0aGlzLmxldmVscyA9IC0xO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzI7IGkrKykge1xuICAgIGlmICgxIDw8IGkgPT0gbikge1xuICAgICAgdGhpcy5sZXZlbHMgPSBpOyAgLy8gRXF1YWwgdG8gbG9nMihuKVxuICAgIH1cbiAgfVxuXG4gIGlmICh0aGlzLmxldmVscyA9PSAtMSkge1xuICAgIHRocm93IFwiTGVuZ3RoIGlzIG5vdCBhIHBvd2VyIG9mIDJcIjtcbiAgfVxuXG4gIHRoaXMuY29zVGFibGUgPSBuZXcgQXJyYXkobiAvIDIpO1xuICB0aGlzLnNpblRhYmxlID0gbmV3IEFycmF5KG4gLyAyKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG4gLyAyOyBpKyspIHtcbiAgICB0aGlzLmNvc1RhYmxlW2ldID0gTWF0aC5jb3MoMiAqIE1hdGguUEkgKiBpIC8gbik7XG4gICAgdGhpcy5zaW5UYWJsZVtpXSA9IE1hdGguc2luKDIgKiBNYXRoLlBJICogaSAvIG4pO1xuICB9XG5cbiAgLypcbiAgICogQ29tcHV0ZXMgdGhlIGRpc2NyZXRlIEZvdXJpZXIgdHJhbnNmb3JtIChERlQpIG9mIHRoZSBnaXZlbiBjb21wbGV4IHZlY3RvcixcbiAgICogc3RvcmluZyB0aGUgcmVzdWx0IGJhY2sgaW50byB0aGUgdmVjdG9yLlxuICAgKiBUaGUgdmVjdG9yJ3MgbGVuZ3RoIG11c3QgYmUgZXF1YWwgdG8gdGhlIHNpemUgbiB0aGF0IHdhcyBwYXNzZWQgdG8gdGhlXG4gICAqIG9iamVjdCBjb25zdHJ1Y3RvciwgYW5kIHRoaXMgbXVzdCBiZSBhIHBvd2VyIG9mIDIuIFVzZXMgdGhlIENvb2xleS1UdWtleVxuICAgKiBkZWNpbWF0aW9uLWluLXRpbWUgcmFkaXgtMiBhbGdvcml0aG0uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB0aGlzLmZvcndhcmQgPSBmdW5jdGlvbihyZWFsLCBpbWFnKSB7XG4gICAgdmFyIG4gPSB0aGlzLm47XG5cbiAgICAvLyBCaXQtcmV2ZXJzZWQgYWRkcmVzc2luZyBwZXJtdXRhdGlvblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICB2YXIgaiA9IHJldmVyc2VCaXRzKGksIHRoaXMubGV2ZWxzKTtcblxuICAgICAgaWYgKGogPiBpKSB7XG4gICAgICAgIHZhciB0ZW1wID0gcmVhbFtpXTtcbiAgICAgICAgcmVhbFtpXSA9IHJlYWxbal07XG4gICAgICAgIHJlYWxbal0gPSB0ZW1wO1xuICAgICAgICB0ZW1wID0gaW1hZ1tpXTtcbiAgICAgICAgaW1hZ1tpXSA9IGltYWdbal07XG4gICAgICAgIGltYWdbal0gPSB0ZW1wO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENvb2xleS1UdWtleSBkZWNpbWF0aW9uLWluLXRpbWUgcmFkaXgtMiBGZnRcbiAgICBmb3IgKHZhciBzaXplID0gMjsgc2l6ZSA8PSBuOyBzaXplICo9IDIpIHtcbiAgICAgIHZhciBoYWxmc2l6ZSA9IHNpemUgLyAyO1xuICAgICAgdmFyIHRhYmxlc3RlcCA9IG4gLyBzaXplO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkgKz0gc2l6ZSkge1xuICAgICAgICBmb3IgKHZhciBqID0gaSwgayA9IDA7IGogPCBpICsgaGFsZnNpemU7IGorKywgayArPSB0YWJsZXN0ZXApIHtcbiAgICAgICAgICB2YXIgdHByZSA9ICByZWFsW2oraGFsZnNpemVdICogdGhpcy5jb3NUYWJsZVtrXSArXG4gICAgICAgICAgICAgICAgICAgICAgaW1hZ1tqK2hhbGZzaXplXSAqIHRoaXMuc2luVGFibGVba107XG4gICAgICAgICAgdmFyIHRwaW0gPSAtcmVhbFtqK2hhbGZzaXplXSAqIHRoaXMuc2luVGFibGVba10gK1xuICAgICAgICAgICAgICAgICAgICAgIGltYWdbaitoYWxmc2l6ZV0gKiB0aGlzLmNvc1RhYmxlW2tdO1xuICAgICAgICAgIHJlYWxbaiArIGhhbGZzaXplXSA9IHJlYWxbal0gLSB0cHJlO1xuICAgICAgICAgIGltYWdbaiArIGhhbGZzaXplXSA9IGltYWdbal0gLSB0cGltO1xuICAgICAgICAgIHJlYWxbal0gKz0gdHByZTtcbiAgICAgICAgICBpbWFnW2pdICs9IHRwaW07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRoZSBpbnRlZ2VyIHdob3NlIHZhbHVlIGlzIHRoZSByZXZlcnNlIG9mIHRoZSBsb3dlc3QgJ2JpdHMnXG4gICAgLy8gYml0cyBvZiB0aGUgaW50ZWdlciAneCcuXG4gICAgZnVuY3Rpb24gcmV2ZXJzZUJpdHMoeCwgYml0cykge1xuICAgICAgdmFyIHkgPSAwO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpdHM7IGkrKykge1xuICAgICAgICB5ID0gKHkgPDwgMSkgfCAoeCAmIDEpO1xuICAgICAgICB4ID4+Pj0gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHk7XG4gICAgfVxuICB9XG5cbiAgLypcbiAgICogQ29tcHV0ZXMgdGhlIGludmVyc2UgZGlzY3JldGUgRm91cmllciB0cmFuc2Zvcm0gKElERlQpIG9mIHRoZSBnaXZlbiBjb21wbGV4XG4gICAqIHZlY3Rvciwgc3RvcmluZyB0aGUgcmVzdWx0IGJhY2sgaW50byB0aGUgdmVjdG9yLlxuICAgKiBUaGUgdmVjdG9yJ3MgbGVuZ3RoIG11c3QgYmUgZXF1YWwgdG8gdGhlIHNpemUgbiB0aGF0IHdhcyBwYXNzZWQgdG8gdGhlXG4gICAqIG9iamVjdCBjb25zdHJ1Y3RvciwgYW5kIHRoaXMgbXVzdCBiZSBhIHBvd2VyIG9mIDIuIFRoaXMgaXMgYSB3cmFwcGVyXG4gICAqIGZ1bmN0aW9uLiBUaGlzIHRyYW5zZm9ybSBkb2VzIG5vdCBwZXJmb3JtIHNjYWxpbmcsIHNvIHRoZSBpbnZlcnNlIGlzIG5vdFxuICAgKiBhIHRydWUgaW52ZXJzZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuaW52ZXJzZSA9IGZ1bmN0aW9uKHJlYWwsIGltYWcpIHtcbiAgICBmb3J3YXJkKGltYWcsIHJlYWwpO1xuICB9XG59XG5cblxuY29uc3Qgc3FydCA9IE1hdGguc3FydDtcblxuY29uc3QgaXNQb3dlck9mVHdvID0gZnVuY3Rpb24obnVtYmVyKSB7XG4gIHdoaWxlICgobnVtYmVyICUgMiA9PT0gMCkgJiYgbnVtYmVyID4gMSlcbiAgICBudW1iZXIgPSBudW1iZXIgLyAyO1xuXG4gIHJldHVybiBudW1iZXIgPT09IDE7XG59XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBzaXplOiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IDEwMjQsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgd2luZG93OiB7XG4gICAgdHlwZTogJ2VudW0nLFxuICAgIGxpc3Q6IFsnbm9uZScsICdoYW5uJywgJ2hhbm5pbmcnLCAnaGFtbWluZycsICdibGFja21hbicsICdibGFja21hbmhhcnJpcycsICdzaW5lJywgJ3JlY3RhbmdsZSddLFxuICAgIGRlZmF1bHQ6ICdub25lJyxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBtb2RlOiB7XG4gICAgdHlwZTogJ2VudW0nLFxuICAgIGxpc3Q6IFsnbWFnbml0dWRlJywgJ3Bvd2VyJ10sIC8vIGFkZCBjb21wbGV4IG91dHB1dFxuICAgIGRlZmF1bHQ6ICdtYWduaXR1ZGUnLFxuICB9LFxuICBub3JtOiB7XG4gICAgdHlwZTogJ2VudW0nLFxuICAgIGRlZmF1bHQ6ICdhdXRvJyxcbiAgICBsaXN0OiBbJ2F1dG8nLCAnbm9uZScsICdsaW5lYXInLCAncG93ZXInXSxcbiAgfSxcbn1cblxuLyoqXG4gKiBDb21wdXRlIHRoZSBGYXN0IEZvdXJpZXIgVHJhbnNmb3JtIG9mIGFuIGluY29tbWluZyBgc2lnbmFsYC5cbiAqXG4gKiBGZnQgaW1wbGVtZW50YXRpb24gYnkgW05heXVraV0oaHR0cHM6Ly9jb2RlLnNvdW5kc29mdHdhcmUuYWMudWsvcHJvamVjdHMvanMtZHNwLXRlc3QvcmVwb3NpdG9yeS9lbnRyeS9mZnQvbmF5dWtpLW9iai9mZnQuanMpLlxuICpcbiAqIF9zdXBwb3J0IGBzdGFuZGFsb25lYCB1c2FnZV9cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnNpemU9MTAyNF0gLSBTaXplIG9mIHRoZSBmZnQsIHNob3VsZCBiZSBhIHBvd2VyIG9mIDIuXG4gKiAgSWYgdGhlIGZyYW1lIHNpemUgb2YgdGhlIGluY29tbWluZyBzaWduYWwgaXMgbG93ZXIgdGhhbiB0aGlzIHZhbHVlLFxuICogIGl0IGlzIHplcm8gcGFkZGVkIHRvIG1hdGNoIHRoZSBmZnQgc2l6ZS5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy53aW5kb3c9J25vbmUnXSAtIE5hbWUgb2YgdGhlIHdpbmRvdyBhcHBsaWVkIG9uIHRoZVxuICogIGluY29tbWluZyBzaWduYWwuIEF2YWlsYWJsZSB3aW5kb3dzIGFyZTogJ25vbmUnLCAnaGFubicsICdoYW5uaW5nJyxcbiAqICAnaGFtbWluZycsICdibGFja21hbicsICdibGFja21hbmhhcnJpcycsICdzaW5lJywgJ3JlY3RhbmdsZScuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubW9kZT0nbWFnbml0dWRlJ10gLSBUeXBlIG9mIHRoZSBvdXRwdXQgKGBtYWduaXR1ZGVgXG4gKiAgb3IgYHBvd2VyYClcbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5ub3JtPSdhdXRvJ10gLSBUeXBlIG9mIG5vcm1hbGl6YXRpb24gYXBwbGllZCBvbiB0aGVcbiAqICBvdXRwdXQuIFBvc3NpYmxlIHZhbHVlcyBhcmUgJ2F1dG8nLCAnbm9uZScsICdsaW5lYXInLCAncG93ZXInLiBXaGVuIHNldCB0b1xuICogIGBhdXRvYCwgYSBgbGluZWFyYCBub3JtYWxpemF0aW9uIGlzIGFwcGxpZWQgb24gdGhlIG1hZ25pdHVkZSBzcGVjdHJ1bSwgd2hpbGVcbiAqICBhIGBwb3dlcmAgbm9ybWFsaXphdGlvbiBpcyBhcHBsaWVkIG9uIHRoZSBwb3dlciBzcGVjdHJ1bS5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIC8vIGFzc3VtaW5nIGFuIGBhdWRpb0J1ZmZlcmAgZXhpc3RzXG4gKiBjb25zdCBzb3VyY2UgPSBuZXcgbGZvLnNvdXJjZS5BdWRpb0luQnVmZmVyKHsgYXVkaW9CdWZmZXIgfSk7XG4gKlxuICogY29uc3Qgc2xpY2VyID0gbmV3IGxmby5vcGVyYXRvci5TbGljZXIoe1xuICogICBmcmFtZVNpemU6IDI1NixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGZmdCA9IG5ldyBsZm8ub3BlcmF0b3IuRmZ0KHtcbiAqICAgbW9kZTogJ3Bvd2VyJyxcbiAqICAgd2luZG93OiAnaGFubicsXG4gKiAgIG5vcm06ICdwb3dlcicsXG4gKiAgIHNpemU6IDI1NixcbiAqIH0pO1xuICpcbiAqIHNvdXJjZS5jb25uZWN0KHNsaWNlcik7XG4gKiBzbGljZXIuY29ubmVjdChmZnQpO1xuICogc291cmNlLnN0YXJ0KCk7XG4gKlxuICogLy8gPiBvdXRwdXRzIDEyOSBiaW5zIGNvbnRhaW5pbmcgdGhlIHZhbHVlcyBvZiB0aGUgcG93ZXIgc3BlY3RydW0gKGluY2x1ZGluZ1xuICogLy8gPiBEQyBhbmQgTnl1aXN0IGZyZXF1ZW5jaWVzKS5cbiAqXG4gKiBAdG9kbyAtIGNoZWNrIGlmICdyZWN0YW5nbGUnIGFuZCAnbm9uZScgd2luZG93cyBhcmUgbm90IHJlZG9uZGFudC5cbiAqIEB0b2RvIC0gY2hlY2sgZGVmYXVsdCB2YWx1ZXMgZm9yIGFsbCBwYXJhbXMuXG4gKi9cbmNsYXNzIEZmdCBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLndpbmRvd1NpemUgPSBudWxsO1xuICAgIHRoaXMubm9ybWFsaXplQ29lZnMgPSBudWxsO1xuICAgIHRoaXMud2luZG93ID0gbnVsbDtcbiAgICB0aGlzLnJlYWwgPSBudWxsO1xuICAgIHRoaXMuaW1hZyA9IG51bGw7XG4gICAgdGhpcy5mZnQgPSBudWxsO1xuXG4gICAgaWYgKCFpc1Bvd2VyT2ZUd28odGhpcy5wYXJhbXMuZ2V0KCdzaXplJykpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdmZnRTaXplIG11c3QgYmUgYSBwb3dlciBvZiB0d28nKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG4gICAgLy8gc2V0IHRoZSBvdXRwdXQgZnJhbWUgc2l6ZVxuICAgIGNvbnN0IGluRnJhbWVTaXplID0gcHJldlN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3QgZmZ0U2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnc2l6ZScpO1xuICAgIGNvbnN0IG1vZGUgPSB0aGlzLnBhcmFtcy5nZXQoJ21vZGUnKTtcbiAgICBjb25zdCBub3JtID0gdGhpcy5wYXJhbXMuZ2V0KCdub3JtJyk7XG4gICAgbGV0IHdpbmRvd05hbWUgPSB0aGlzLnBhcmFtcy5nZXQoJ3dpbmRvdycpO1xuICAgIC8vIHdpbmRvdyBgbm9uZWAgYW5kIGByZWN0YW5nbGVgIGFyZSBhbGlhc2VzXG4gICAgaWYgKHdpbmRvd05hbWUgPT09ICdub25lJylcbiAgICAgIHdpbmRvd05hbWUgPSAncmVjdGFuZ2xlJztcblxuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZSA9IGZmdFNpemUgLyAyICsgMTtcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAndmVjdG9yJztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbiA9IFtdO1xuICAgIC8vIHNpemUgb2YgdGhlIHdpbmRvdyB0byBhcHBseSBvbiB0aGUgaW5wdXQgZnJhbWVcbiAgICB0aGlzLndpbmRvd1NpemUgPSAoaW5GcmFtZVNpemUgPCBmZnRTaXplKSA/IGluRnJhbWVTaXplIDogZmZ0U2l6ZTtcblxuICAgIC8vIHJlZmVyZW5jZXMgdG8gcG9wdWxhdGUgaW4gdGhlIHdpbmRvdyBmdW5jdGlvbnMgKGNmLiBgaW5pdFdpbmRvd2ApXG4gICAgdGhpcy5ub3JtYWxpemVDb2VmcyA9IHsgbGluZWFyOiAwLCBwb3dlcjogMCB9O1xuICAgIHRoaXMud2luZG93ID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLndpbmRvd1NpemUpO1xuXG4gICAgaW5pdFdpbmRvdyhcbiAgICAgIHdpbmRvd05hbWUsICAgICAgICAgLy8gbmFtZSBvZiB0aGUgd2luZG93XG4gICAgICB0aGlzLndpbmRvdywgICAgICAgIC8vIGJ1ZmZlciBwb3B1bGF0ZWQgd2l0aCB0aGUgd2luZG93IHNpZ25hbFxuICAgICAgdGhpcy53aW5kb3dTaXplLCAgICAvLyBzaXplIG9mIHRoZSB3aW5kb3dcbiAgICAgIHRoaXMubm9ybWFsaXplQ29lZnMgLy8gb2JqZWN0IHBvcHVsYXRlZCB3aXRoIHRoZSBub3JtYWxpemF0aW9uIGNvZWZzXG4gICAgKTtcblxuICAgIGNvbnN0IHsgbGluZWFyLCBwb3dlciB9ID0gdGhpcy5ub3JtYWxpemVDb2VmcztcblxuICAgIHN3aXRjaCAobm9ybSkge1xuICAgICAgY2FzZSAnbm9uZSc6XG4gICAgICAgIHRoaXMud2luZG93Tm9ybSA9IDE7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdsaW5lYXInOlxuICAgICAgICB0aGlzLndpbmRvd05vcm0gPSBsaW5lYXI7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdwb3dlcic6XG4gICAgICAgIHRoaXMud2luZG93Tm9ybSA9IHBvd2VyO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnYXV0byc6XG4gICAgICAgIGlmIChtb2RlID09PSAnbWFnbml0dWRlJylcbiAgICAgICAgICB0aGlzLndpbmRvd05vcm0gPSBsaW5lYXI7XG4gICAgICAgIGVsc2UgaWYgKG1vZGUgPT09ICdwb3dlcicpXG4gICAgICAgICAgdGhpcy53aW5kb3dOb3JtID0gcG93ZXI7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMucmVhbCA9IG5ldyBGbG9hdDMyQXJyYXkoZmZ0U2l6ZSk7XG4gICAgdGhpcy5pbWFnID0gbmV3IEZsb2F0MzJBcnJheShmZnRTaXplKTtcbiAgICB0aGlzLmZmdCA9IG5ldyBGZnROYXl1a2koZmZ0U2l6ZSk7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYEZmdGAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhIGdyYXBoKS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gc2lnbmFsIC0gSW5wdXQgdmFsdWVzLlxuICAgKiBAcmV0dXJuIHtBcnJheX0gLSBGZnQgb2YgdGhlIGlucHV0IHNpZ25hbC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgZmZ0ID0gbmV3IGxmby5vcGVyYXRvci5GZnQoeyBzaXplOiA1MTIsIHdpbmRvdzogJ2hhbm4nIH0pO1xuICAgKiAvLyBtYW5kYXRvcnkgZm9yIHVzZSBpbiBzdGFuZGFsb25lIG1vZGVcbiAgICogZmZ0LmluaXRTdHJlYW0oeyBmcmFtZVNpemU6IDI1NiwgZnJhbWVUeXBlOiAnc2lnbmFsJyB9KTtcbiAgICogZmZ0LmlucHV0U2lnbmFsKHNpZ25hbCk7XG4gICAqL1xuICBpbnB1dFNpZ25hbChzaWduYWwpIHtcbiAgICBjb25zdCBtb2RlID0gdGhpcy5wYXJhbXMuZ2V0KCdtb2RlJyk7XG4gICAgY29uc3Qgd2luZG93U2l6ZSA9IHRoaXMud2luZG93U2l6ZTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3QgZmZ0U2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnc2l6ZScpO1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG5cbiAgICAvLyBhcHBseSB3aW5kb3cgb24gdGhlIGlucHV0IHNpZ25hbCBhbmQgcmVzZXQgaW1hZyBidWZmZXJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHdpbmRvd1NpemU7IGkrKykge1xuICAgICAgdGhpcy5yZWFsW2ldID0gc2lnbmFsW2ldICogdGhpcy53aW5kb3dbaV0gKiB0aGlzLndpbmRvd05vcm07XG4gICAgICB0aGlzLmltYWdbaV0gPSAwO1xuICAgIH1cblxuICAgIC8vIGlmIHJlYWwgaXMgYmlnZ2VyIHRoYW4gaW5wdXQgc2lnbmFsLCBmaWxsIHdpdGggemVyb3NcbiAgICBmb3IgKGxldCBpID0gd2luZG93U2l6ZTsgaSA8IGZmdFNpemU7IGkrKykge1xuICAgICAgdGhpcy5yZWFsW2ldID0gMDtcbiAgICAgIHRoaXMuaW1hZ1tpXSA9IDA7XG4gICAgfVxuXG4gICAgdGhpcy5mZnQuZm9yd2FyZCh0aGlzLnJlYWwsIHRoaXMuaW1hZyk7XG5cbiAgICBpZiAobW9kZSA9PT0gJ21hZ25pdHVkZScpIHtcbiAgICAgIGNvbnN0IG5vcm0gPSAxIC8gZmZ0U2l6ZTtcblxuICAgICAgLy8gREMgaW5kZXhcbiAgICAgIGNvbnN0IHJlYWxEYyA9IHRoaXMucmVhbFswXTtcbiAgICAgIGNvbnN0IGltYWdEYyA9IHRoaXMuaW1hZ1swXTtcbiAgICAgIG91dERhdGFbMF0gPSBzcXJ0KHJlYWxEYyAqIHJlYWxEYyArIGltYWdEYyAqIGltYWdEYykgKiBub3JtO1xuXG4gICAgICAvLyBOcXV5c3QgaW5kZXhcbiAgICAgIGNvbnN0IHJlYWxOeSA9IHRoaXMucmVhbFtmZnRTaXplIC8gMl07XG4gICAgICBjb25zdCBpbWFnTnkgPSB0aGlzLmltYWdbZmZ0U2l6ZSAvIDJdO1xuICAgICAgb3V0RGF0YVtmZnRTaXplIC8gMl0gPSBzcXJ0KHJlYWxOeSAqIHJlYWxOeSArIGltYWdOeSAqIGltYWdOeSkgKiBub3JtO1xuXG4gICAgICAvLyBwb3dlciBzcGVjdHJ1bVxuICAgICAgZm9yIChsZXQgaSA9IDEsIGogPSBmZnRTaXplIC0gMTsgaSA8IGZmdFNpemUgLyAyOyBpKyssIGotLSkge1xuICAgICAgICBjb25zdCByZWFsID0gMC41ICogKHRoaXMucmVhbFtpXSArIHRoaXMucmVhbFtqXSk7XG4gICAgICAgIGNvbnN0IGltYWcgPSAwLjUgKiAodGhpcy5pbWFnW2ldIC0gdGhpcy5pbWFnW2pdKTtcblxuICAgICAgICBvdXREYXRhW2ldID0gMiAqIHNxcnQocmVhbCAqIHJlYWwgKyBpbWFnICogaW1hZykgKiBub3JtO1xuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChtb2RlID09PSAncG93ZXInKSB7XG4gICAgICBjb25zdCBub3JtID0gMSAvIChmZnRTaXplICogZmZ0U2l6ZSk7XG5cbiAgICAgIC8vIERDIGluZGV4XG4gICAgICBjb25zdCByZWFsRGMgPSB0aGlzLnJlYWxbMF07XG4gICAgICBjb25zdCBpbWFnRGMgPSB0aGlzLmltYWdbMF07XG4gICAgICBvdXREYXRhWzBdID0gKHJlYWxEYyAqIHJlYWxEYyArIGltYWdEYyAqIGltYWdEYykgKiBub3JtO1xuXG4gICAgICAvLyBOcXV5c3QgaW5kZXhcbiAgICAgIGNvbnN0IHJlYWxOeSA9IHRoaXMucmVhbFtmZnRTaXplIC8gMl07XG4gICAgICBjb25zdCBpbWFnTnkgPSB0aGlzLmltYWdbZmZ0U2l6ZSAvIDJdO1xuICAgICAgb3V0RGF0YVtmZnRTaXplIC8gMl0gPSAocmVhbE55ICogcmVhbE55ICsgaW1hZ055ICogaW1hZ055KSAqIG5vcm07XG5cbiAgICAgIC8vIHBvd2VyIHNwZWN0cnVtXG4gICAgICBmb3IgKGxldCBpID0gMSwgaiA9IGZmdFNpemUgLSAxOyBpIDwgZmZ0U2l6ZSAvIDI7IGkrKywgai0tKSB7XG4gICAgICAgIGNvbnN0IHJlYWwgPSAwLjUgKiAodGhpcy5yZWFsW2ldICsgdGhpcy5yZWFsW2pdKTtcbiAgICAgICAgY29uc3QgaW1hZyA9IDAuNSAqICh0aGlzLmltYWdbaV0gLSB0aGlzLmltYWdbal0pO1xuXG4gICAgICAgIG91dERhdGFbaV0gPSA0ICogKHJlYWwgKiByZWFsICsgaW1hZyAqIGltYWcpICogbm9ybTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0RGF0YTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgdGhpcy5pbnB1dFNpZ25hbChmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBGZnQ7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBzcXJ0ID0gTWF0aC5zcXJ0O1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgbm9ybWFsaXplOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG4gIHBvd2VyOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9XG59XG5cbi8qKlxuICogQ29tcHV0ZSB0aGUgbWFnbml0dWRlIG9mIGEgYHZlY3RvcmAgaW5wdXQuXG4gKlxuICogX3N1cHBvcnQgYHN0YW5kYWxvbmVgIHVzYWdlX1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5ub3JtYWxpemU9dHJ1ZV0gLSBOb3JtYWxpemUgb3V0cHV0IGFjY29yZGluZyB0b1xuICogIHRoZSB2ZWN0b3Igc2l6ZS5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMucG93ZXI9ZmFsc2VdIC0gSWYgdHJ1ZSwgcmV0dXJucyB0aGUgc3F1YXJlZFxuICogIG1hZ25pdHVkZSAocG93ZXIpLlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLm9wZXJhdG9yXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY29tbW9uJztcbiAqXG4gKiBjb25zdCBldmVudEluID0gbmV3IGxmby5zb3VyY2UuRXZlbnRJbih7IGZyYW1lU2l6ZTogMiwgZnJhbWVUeXBlOiAndmVjdG9yJyB9KTtcbiAqIGNvbnN0IG1hZ25pdHVkZSA9IG5ldyBsZm8ub3BlcmF0b3IuTWFnbml0dWRlKCk7XG4gKiBjb25zdCBsb2dnZXIgPSBuZXcgbGZvLnNpbmsuTG9nZ2VyKHsgb3V0RnJhbWU6IHRydWUgfSk7XG4gKlxuICogZXZlbnRJbi5jb25uZWN0KG1hZ25pdHVkZSk7XG4gKiBtYWduaXR1ZGUuY29ubmVjdChsb2dnZXIpO1xuICogZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqIGV2ZW50SW4ucHJvY2VzcyhudWxsLCBbMSwgMV0pO1xuICogPiBbMV1cbiAqIGV2ZW50SW4ucHJvY2VzcyhudWxsLCBbMiwgMl0pO1xuICogPiBbMi44Mjg0MjcxMjQ3NV1cbiAqIGV2ZW50SW4ucHJvY2VzcyhudWxsLCBbMywgM10pO1xuICogPiBbNC4yNDI2NDA2ODcxMl1cbiAqL1xuY2xhc3MgTWFnbml0dWRlIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuX25vcm1hbGl6ZSA9IHRoaXMucGFyYW1zLmdldCgnbm9ybWFsaXplJyk7XG4gICAgdGhpcy5fcG93ZXIgPSB0aGlzLnBhcmFtcy5nZXQoJ3Bvd2VyJyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgb25QYXJhbVVwZGF0ZShuYW1lLCB2YWx1ZSwgbWV0YXMpIHtcbiAgICBzdXBlci5vblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcyk7XG5cbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ25vcm1hbGl6ZSc6XG4gICAgICAgIHRoaXMuX25vcm1hbGl6ZSA9IHZhbHVlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3Bvd2VyJzpcbiAgICAgICAgdGhpcy5fcG93ZXIgPSB2YWx1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSAxO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZSA9ICdzY2FsYXInO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmRlc2NyaXB0aW9uID0gWydtYWduaXR1ZGUnXTtcbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE1hZ25pdHVkZWAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhIGdyYXBoKS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheXxGbG9hdDMyQXJyYXl9IHZhbHVlcyAtIFZhbHVlcyB0byBwcm9jZXNzLlxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9IC0gTWFnbml0dWRlIHZhbHVlLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gICAqXG4gICAqIGNvbnN0IG1hZ25pdHVkZSA9IG5ldyBsZm8ub3BlcmF0b3IuTWFnbml0dWRlKHsgcG93ZXI6IHRydWUgfSk7XG4gICAqIG1hZ25pdHVkZS5pbml0U3RyZWFtKHsgZnJhbWVUeXBlOiAndmVjdG9yJywgZnJhbWVTaXplOiAzIH0pO1xuICAgKiBtYWduaXR1ZGUuaW5wdXRWZWN0b3IoWzMsIDNdKTtcbiAgICogPiA0LjI0MjY0MDY4NzEyXG4gICAqL1xuICBpbnB1dFZlY3Rvcih2YWx1ZXMpIHtcbiAgICBjb25zdCBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoO1xuICAgIGxldCBzdW0gPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKylcbiAgICAgIHN1bSArPSAodmFsdWVzW2ldICogdmFsdWVzW2ldKTtcblxuICAgIGxldCBtYWcgPSBzdW07XG5cbiAgICBpZiAodGhpcy5fbm9ybWFsaXplKVxuICAgICAgbWFnIC89IGxlbmd0aDtcblxuICAgIGlmICghdGhpcy5fcG93ZXIpXG4gICAgICBtYWcgPSBzcXJ0KG1hZyk7XG5cbiAgICByZXR1cm4gbWFnO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICB0aGlzLmZyYW1lLmRhdGFbMF0gPSB0aGlzLmlucHV0VmVjdG9yKGZyYW1lLmRhdGEpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1hZ25pdHVkZTtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IHNxcnQgPSBNYXRoLnNxcnQ7XG5cbi8qKlxuICogQ29tcHV0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYSBnaXZlbiBgc2lnbmFsYC5cbiAqXG4gKiBfc3VwcG9ydCBgc3RhbmRhbG9uZWAgdXNhZ2VfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IGF1ZGlvQ29udGV4dCA9IG5ldyBBdWRpb0NvbnRleHQoKTtcbiAqXG4gKiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzXG4gKiAgIC5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSB9KVxuICogICAudGhlbihpbml0KVxuICogICAuY2F0Y2goKGVycikgPT4gY29uc29sZS5lcnJvcihlcnIuc3RhY2spKTtcbiAqXG4gKiBmdW5jdGlvbiBpbml0KHN0cmVhbSkge1xuICogICBjb25zdCBzb3VyY2UgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAqXG4gKiAgIGNvbnN0IGF1ZGlvSW5Ob2RlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9Jbk5vZGUoe1xuICogICAgIHNvdXJjZU5vZGU6IHNvdXJjZSxcbiAqICAgICBhdWRpb0NvbnRleHQ6IGF1ZGlvQ29udGV4dCxcbiAqICAgfSk7XG4gKlxuICogICBjb25zdCBtZWFuU3RkZGV2ID0gbmV3IGxmby5vcGVyYXRvci5NZWFuU3RkZGV2KCk7XG4gKlxuICogICBjb25zdCB0cmFjZURpc3BsYXkgPSBuZXcgbGZvLnNpbmsuVHJhY2VEaXNwbGF5KHtcbiAqICAgICBjYW52YXM6ICcjdHJhY2UnLFxuICogICB9KTtcbiAqXG4gKiAgIGF1ZGlvSW5Ob2RlLmNvbm5lY3QobWVhblN0ZGRldik7XG4gKiAgIG1lYW5TdGRkZXYuY29ubmVjdCh0cmFjZURpc3BsYXkpO1xuICogICBhdWRpb0luTm9kZS5zdGFydCgpO1xuICogfVxuICovXG5jbGFzcyBNZWFuU3RkZGV2IGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIC8vIG5vIG9wdGlvbnMgYXZhaWxhYmxlLCBqdXN0IHRocm93IGFuIGVycm9yIGlmIHNvbWUgcGFyYW0gdHJ5IHRvIGJlIHNldC5cbiAgICBzdXBlcih7fSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlID0gJ3ZlY3Rvcic7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gMjtcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbiA9IFsnbWVhbicsICdzdGRkZXYnXTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKipcbiAgICogVXNlIHRoZSBgTWVhblN0ZGRldmAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhIGdyYXBoKS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheXxGbG9hdDMyQXJyYXl9IHZhbHVlcyAtIFZhbHVlcyB0byBwcm9jZXNzLlxuICAgKiBAcmV0dXJuIHtBcnJheX0gLSBNZWFuIGFuZCBzdGFuZGFydCBkZXZpYXRpb24gb2YgdGhlIGlucHV0IHZhbHVlcy5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICAgKlxuICAgKiBjb25zdCBtZWFuU3RkZGV2ID0gbmV3IGxmby5vcGVyYXRvci5NZWFuU3RkZGV2KCk7XG4gICAqIG1lYW5TdGRkZXYuaW5pdFN0cmVhbSh7IGZyYW1lVHlwZTogJ3ZlY3RvcicsIGZyYW1lU2l6ZTogMTAyNCB9KTtcbiAgICogbWVhblN0ZGRldi5pbnB1dFZlY3Rvcihzb21lU2luZVNpZ25hbCk7XG4gICAqID4gWzAsIDAuNzA3MV1cbiAgICovXG4gIGlucHV0U2lnbmFsKHZhbHVlcykge1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgbGVuZ3RoID0gdmFsdWVzLmxlbmd0aDtcblxuICAgIGxldCBtZWFuID0gMDtcbiAgICBsZXQgbTIgPSAwO1xuXG4gICAgLy8gY29tcHV0ZSBtZWFuIGFuZCB2YXJpYW5jZSB3aXRoIFdlbGZvcmQgYWxnb3JpdGhtXG4gICAgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQWxnb3JpdGhtc19mb3JfY2FsY3VsYXRpbmdfdmFyaWFuY2VcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB4ID0gdmFsdWVzW2ldO1xuICAgICAgY29uc3QgZGVsdGEgPSB4IC0gbWVhbjtcbiAgICAgIG1lYW4gKz0gZGVsdGEgLyAoaSArIDEpO1xuICAgICAgbTIgKz0gZGVsdGEgKiAoeCAtIG1lYW4pO1xuICAgIH1cblxuICAgIGNvbnN0IHZhcmlhbmNlID0gbTIgLyAobGVuZ3RoIC0gMSk7XG4gICAgY29uc3Qgc3RkZGV2ID0gc3FydCh2YXJpYW5jZSk7XG5cbiAgICBvdXREYXRhWzBdID0gbWVhbjtcbiAgICBvdXREYXRhWzFdID0gc3RkZGV2O1xuXG4gICAgcmV0dXJuIG91dERhdGE7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbChmcmFtZSkge1xuICAgIHRoaXMuaW5wdXRTaWduYWwoZnJhbWUuZGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWVhblN0ZGRldjtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IG1pbiA9IE1hdGgubWluO1xuY29uc3QgbWF4ID0gTWF0aC5tYXg7XG5jb25zdCBwb3cgPSBNYXRoLnBvdztcbmNvbnN0IGxvZzEwID0gTWF0aC5sb2cxMDtcblxuZnVuY3Rpb24gaGVydHpUb01lbEh0ayhmcmVxSHopIHtcbiAgcmV0dXJuIDI1OTUgKiBNYXRoLmxvZzEwKDEgKyAoZnJlcUh6IC8gNzAwKSk7XG59XG5cbmZ1bmN0aW9uIG1lbFRvSGVydHpIdGsoZnJlcU1lbCkge1xuICByZXR1cm4gNzAwICogKE1hdGgucG93KDEwLCBmcmVxTWVsIC8gMjU5NSkgLSAxKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZGVzY3JpcHRpb24gb2YgdGhlIHdlaWdodHMgdG8gYXBwbHkgb24gdGhlIGZmdCBiaW5zIGZvciBlYWNoXG4gKiBNZWwgYmFuZCBmaWx0ZXIuXG4gKiBAbm90ZSAtIGFkYXB0ZWQgZnJvbSBpbXRyLXRvb2xzL3J0YVxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBuYnJCaW5zIC0gTnVtYmVyIG9mIGZmdCBiaW5zLlxuICogQHBhcmFtIHtOdW1iZXJ9IG5ickZpbHRlciAtIE51bWJlciBvZiBtZWwgZmlsdGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBzYW1wbGVSYXRlIC0gU2FtcGxlIFJhdGUgb2YgdGhlIHNpZ25hbC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBtaW5GcmVxIC0gTWluaW11bSBGcmVxdWVuY3kgdG8gYmUgY29uc2lkZXJlcmVkLlxuICogQHBhcmFtIHtOdW1iZXJ9IG1heEZyZXEgLSBNYXhpbXVtIGZyZXF1ZW5jeSB0byBjb25zaWRlci5cbiAqIEByZXR1cm4ge0FycmF5PE9iamVjdD59IC0gRGVzY3JpcHRpb24gb2YgdGhlIHdlaWdodHMgdG8gYXBwbHkgb24gdGhlIGJpbnMgZm9yXG4gKiAgZWFjaCBtZWwgZmlsdGVyLiBFYWNoIGRlc2NyaXB0aW9uIGhhcyB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqICB7IHN0YXJ0SW5kZXg6IGJpbkluZGV4LCBjZW50ZXJGcmVxOiBiaW5DZW50ZXJGcmVxdWVuY3ksIHdlaWdodHM6IFtdIH1cbiAqXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBnZXRNZWxCYW5kV2VpZ2h0cyhuYnJCaW5zLCBuYnJCYW5kcywgc2FtcGxlUmF0ZSwgbWluRnJlcSwgbWF4RnJlcSwgdHlwZSA9ICdodGsnKSB7XG5cbiAgbGV0IGhlcnR6VG9NZWwgPSBudWxsO1xuICBsZXQgbWVsVG9IZXJ0eiA9IG51bGw7XG4gIGxldCBtaW5NZWw7XG4gIGxldCBtYXhNZWw7XG5cbiAgaWYgKHR5cGUgPT09ICdodGsnKSB7XG4gICAgaGVydHpUb01lbCA9IGhlcnR6VG9NZWxIdGs7XG4gICAgbWVsVG9IZXJ0eiA9IG1lbFRvSGVydHpIdGs7XG4gICAgbWluTWVsID0gaGVydHpUb01lbChtaW5GcmVxKTtcbiAgICBtYXhNZWwgPSBoZXJ0elRvTWVsKG1heEZyZXEpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBtZWwgYmFuZCB0eXBlOiBcIiR7dHlwZX1cImApO1xuICB9XG5cbiAgY29uc3QgbWVsQmFuZERlc2NyaXB0aW9ucyA9IG5ldyBBcnJheShuYnJCYW5kcyk7XG4gIC8vIGNlbnRlciBmcmVxdWVuY2llcyBvZiBGZnQgYmluc1xuICBjb25zdCBmZnRGcmVxcyA9IG5ldyBGbG9hdDMyQXJyYXkobmJyQmlucyk7XG4gIC8vIGNlbnRlciBmcmVxdWVuY2llcyBvZiBtZWwgYmFuZHMgLSB1bmlmb3JtbHkgc3BhY2VkIGluIG1lbCBkb21haW4gYmV0d2VlblxuICAvLyBsaW1pdHMsIHRoZXJlIGFyZSAyIG1vcmUgZnJlcXVlbmNpZXMgdGhhbiB0aGUgYWN0dWFsIG51bWJlciBvZiBmaWx0ZXJzIGluXG4gIC8vIG9yZGVyIHRvIGNhbGN1bGF0ZSB0aGUgc2xvcGVzXG4gIGNvbnN0IGZpbHRlckZyZXFzID0gbmV3IEZsb2F0MzJBcnJheShuYnJCYW5kcyArIDIpO1xuXG4gIGNvbnN0IGZmdFNpemUgPSAobmJyQmlucyAtIDEpICogMjtcbiAgLy8gY29tcHV0ZSBiaW5zIGNlbnRlciBmcmVxdWVuY2llc1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ickJpbnM7IGkrKylcbiAgICBmZnRGcmVxc1tpXSA9IHNhbXBsZVJhdGUgKiBpIC8gZmZ0U2l6ZTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IG5ickJhbmRzICsgMjsgaSsrKVxuICAgIGZpbHRlckZyZXFzW2ldID0gbWVsVG9IZXJ0eihtaW5NZWwgKyBpIC8gKG5ickJhbmRzICsgMSkgKiAobWF4TWVsIC0gbWluTWVsKSk7XG5cbiAgLy8gbG9vcCB0aHJvdWdodCBmaWx0ZXJzXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbmJyQmFuZHM7IGkrKykge1xuICAgIGxldCBtaW5XZWlnaHRJbmRleERlZmluZWQgPSAwO1xuXG4gICAgY29uc3QgZGVzY3JpcHRpb24gPSB7XG4gICAgICBzdGFydEluZGV4OiBudWxsLFxuICAgICAgY2VudGVyRnJlcTogbnVsbCxcbiAgICAgIHdlaWdodHM6IFtdLFxuICAgIH1cblxuICAgIC8vIGRlZmluZSBjb250cmlidXRpb24gb2YgZWFjaCBiaW4gZm9yIHRoZSBmaWx0ZXIgYXQgaW5kZXggKGkgKyAxKVxuICAgIC8vIGRvIG5vdCBwcm9jZXNzIHRoZSBsYXN0IHNwZWN0cnVtIGNvbXBvbmVudCAoTnlxdWlzdClcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IG5ickJpbnMgLSAxOyBqKyspIHtcbiAgICAgIGNvbnN0IHBvc1Nsb3BlQ29udHJpYiA9IChmZnRGcmVxc1tqXSAtIGZpbHRlckZyZXFzW2ldKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZmlsdGVyRnJlcXNbaSsxXSAtIGZpbHRlckZyZXFzW2ldKTtcblxuICAgICAgY29uc3QgbmVnU2xvcGVDb250cmliID0gKGZpbHRlckZyZXFzW2krMl0gLSBmZnRGcmVxc1tqXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZpbHRlckZyZXFzW2krMl0gLSBmaWx0ZXJGcmVxc1tpKzFdKTtcbiAgICAgIC8vIGxvd2VyU2xvcGUgYW5kIHVwcGVyIHNsb3BlIGludGVyc2VjdCBhdCB6ZXJvIGFuZCB3aXRoIGVhY2ggb3RoZXJcbiAgICAgIGNvbnN0IGNvbnRyaWJ1dGlvbiA9IG1heCgwLCBtaW4ocG9zU2xvcGVDb250cmliLCBuZWdTbG9wZUNvbnRyaWIpKTtcblxuICAgICAgaWYgKGNvbnRyaWJ1dGlvbiA+IDApIHtcbiAgICAgICAgaWYgKGRlc2NyaXB0aW9uLnN0YXJ0SW5kZXggPT09IG51bGwpIHtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5zdGFydEluZGV4ID0gajtcbiAgICAgICAgICBkZXNjcmlwdGlvbi5jZW50ZXJGcmVxID0gZmlsdGVyRnJlcXNbaSsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlc2NyaXB0aW9uLndlaWdodHMucHVzaChjb250cmlidXRpb24pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGVtcHR5IGZpbHRlclxuICAgIGlmIChkZXNjcmlwdGlvbi5zdGFydEluZGV4ID09PSBudWxsKSB7XG4gICAgICBkZXNjcmlwdGlvbi5zdGFydEluZGV4ID0gMDtcbiAgICAgIGRlc2NyaXB0aW9uLmNlbnRlckZyZXEgPSAwO1xuICAgIH1cblxuICAgIC8vIEB0b2RvIC0gZG8gc29tZSBzY2FsaW5nIGZvciBTbGFuZXktc3R5bGUgbWVsXG4gICAgbWVsQmFuZERlc2NyaXB0aW9uc1tpXSA9IGRlc2NyaXB0aW9uO1xuICB9XG5cbiAgcmV0dXJuIG1lbEJhbmREZXNjcmlwdGlvbnM7XG59XG5cblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIGxvZzoge1xuICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBuYnJCYW5kczoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiAyNCxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBtaW5GcmVxOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdzdGF0aWMnIH0sXG4gIH0sXG4gIG1heEZyZXE6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgcG93ZXI6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbn07XG5cblxuLyoqXG4gKiBDb21wdXRlIHRoZSBtZWwgYmFuZHMgc3BlY3RydW0gZnJvbSBhIGdpdmVuIHNwZWN0cnVtIChgdmVjdG9yYCB0eXBlKS5cbiAqIF9JbXBsZW1lbnQgdGhlIGBodGtgIG1lbCBiYW5kIHN0eWxlLl9cbiAqXG4gKiBfc3VwcG9ydCBgc3RhbmRhbG9uZWAgdXNhZ2VfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMubG9nPWZhbHNlXSAtIEFwcGx5IGEgbG9nYXJpdGhtaWMgc2NhbGUgb24gdGhlIG91dHB1dC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5uYnJCYW5kcz0yNF0gLSBOdW1iZXIgb2YgZmlsdGVycyBkZWZpbmluZyB0aGUgbWVsXG4gKiAgYmFuZHMuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWluRnJlcT0wXSAtIE1pbmltdW0gZnJlcXVlbmN5IHRvIGNvbnNpZGVyLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1heEZyZXE9bnVsbF0gLSBNYXhpbXVtIGZyZXF1ZW5jeSB0byBjb25zaWRlci5cbiAqICBJZiBgbnVsbGAsIGlzIHNldCB0byBOeXF1aXN0IGZyZXF1ZW5jeS5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5wb3dlcj0xXSAtIEFwcGx5IGEgcG93ZXIgc2NhbGluZyBvbiBlYWNoIG1lbCBiYW5kLlxuICpcbiAqIEB0b2RvIC0gaW1wbGVtZW50IFNsYW5leSBzdHlsZSBtZWwgYmFuZHNcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IGxmbyBmcm9tICd3YXZlcy1sZm8vbm9kZSdcbiAqXG4gKiAvLyByZWFkIGEgZmlsZSBmcm9tIHBhdGggKG5vZGUgb25seSBzb3VyY2UpXG4gKiBjb25zdCBhdWRpb0luRmlsZSA9IG5ldyBsZm8uc291cmNlLkF1ZGlvSW5GaWxlKHtcbiAqICAgZmlsZW5hbWU6ICdwYXRoL3RvL2ZpbGUnLFxuICogICBmcmFtZVNpemU6IDUxMixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNsaWNlciA9IG5ldyBsZm8ub3BlcmF0b3IuU2xpY2VyKHtcbiAqICAgZnJhbWVTaXplOiAyNTYsXG4gKiAgIGhvcFNpemU6IDI1NixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGZmdCA9IG5ldyBsZm8ub3BlcmF0b3IuRmZ0KHtcbiAqICAgc2l6ZTogMTAyNCxcbiAqICAgd2luZG93OiAnaGFubicsXG4gKiAgIG1vZGU6ICdwb3dlcicsXG4gKiAgIG5vcm06ICdwb3dlcicsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBtZWwgPSBuZXcgbGZvLm9wZXJhdG9yLk1lbCh7XG4gKiAgIGxvZzogdHJ1ZSxcbiAqICAgbmJyQmFuZHM6IDI0LFxuICogfSk7XG4gKlxuICogY29uc3QgbG9nZ2VyID0gbmV3IGxmby5zaW5rLkxvZ2dlcih7IGRhdGE6IHRydWUgfSk7XG4gKlxuICogYXVkaW9JbkZpbGUuY29ubmVjdChzbGljZXIpO1xuICogc2xpY2VyLmNvbm5lY3QoZmZ0KTtcbiAqIGZmdC5jb25uZWN0KG1lbCk7XG4gKiBtZWwuY29ubmVjdChsb2dnZXIpO1xuICpcbiAqIGF1ZGlvSW5GaWxlLnN0YXJ0KCk7XG4gKi9cbmNsYXNzIE1lbCBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgY29uc3QgbmJyQmlucyA9IHByZXZTdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IG5ickJhbmRzID0gdGhpcy5wYXJhbXMuZ2V0KCduYnJCYW5kcycpO1xuICAgIGNvbnN0IHNhbXBsZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlO1xuICAgIGNvbnN0IG1pbkZyZXEgPSB0aGlzLnBhcmFtcy5nZXQoJ21pbkZyZXEnKTtcbiAgICBsZXQgbWF4RnJlcSA9IHRoaXMucGFyYW1zLmdldCgnbWF4RnJlcScpO1xuXG4gICAgLy9cbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSBuYnJCYW5kcztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAndmVjdG9yJztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbiA9IFtdO1xuXG4gICAgaWYgKG1heEZyZXEgPT09IG51bGwpXG4gICAgICBtYXhGcmVxID0gdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlUmF0ZSAvIDI7XG5cbiAgICB0aGlzLm1lbEJhbmREZXNjcmlwdGlvbnMgPSBnZXRNZWxCYW5kV2VpZ2h0cyhuYnJCaW5zLCBuYnJCYW5kcywgc2FtcGxlUmF0ZSwgbWluRnJlcSwgbWF4RnJlcSk7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE1lbGAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhIGdyYXBoKS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gc3BlY3RydW0gLSBGZnQgYmlucy5cbiAgICogQHJldHVybiB7QXJyYXl9IC0gTWVsIGJhbmRzLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBjb25zdCBtZWwgPSBuZXcgbGZvLm9wZXJhdG9yLk1lbCh7IG5ickJhbmRzOiAyNCB9KTtcbiAgICogLy8gbWFuZGF0b3J5IGZvciB1c2UgaW4gc3RhbmRhbG9uZSBtb2RlXG4gICAqIG1lbC5pbml0U3RyZWFtKHsgZnJhbWVTaXplOiAyNTYsIGZyYW1lVHlwZTogJ3ZlY3RvcicsIHNvdXJjZVNhbXBsZVJhdGU6IDQ0MTAwIH0pO1xuICAgKiBtZWwuaW5wdXRWZWN0b3IoZmZ0Qmlucyk7XG4gICAqL1xuICBpbnB1dFZlY3RvcihiaW5zKSB7XG5cbiAgICBjb25zdCBwb3dlciA9IHRoaXMucGFyYW1zLmdldCgncG93ZXInKTtcbiAgICBjb25zdCBsb2cgPSB0aGlzLnBhcmFtcy5nZXQoJ2xvZycpO1xuICAgIGNvbnN0IG1lbEJhbmRzID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IG5ickJhbmRzID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGxldCBzY2FsZSA9IDE7XG5cbiAgICBjb25zdCBtaW5Mb2dWYWx1ZSA9IDFlLTQ4O1xuICAgIGNvbnN0IG1pbkxvZyA9IC00ODA7XG5cbiAgICBpZiAobG9nKVxuICAgICAgc2NhbGUgKj0gbmJyQmFuZHM7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5ickJhbmRzOyBpKyspIHtcbiAgICAgIGNvbnN0IHsgc3RhcnRJbmRleCwgd2VpZ2h0cyB9ID0gdGhpcy5tZWxCYW5kRGVzY3JpcHRpb25zW2ldO1xuICAgICAgbGV0IHZhbHVlID0gMDtcblxuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3ZWlnaHRzLmxlbmd0aDsgaisrKVxuICAgICAgICB2YWx1ZSArPSB3ZWlnaHRzW2pdICogYmluc1tzdGFydEluZGV4ICsgal07XG5cbiAgICAgIC8vIGFwcGx5IHNhbWUgbG9naWMgYXMgaW4gUGlQb0JhbmRzXG4gICAgICBpZiAoc2NhbGUgIT09IDEpXG4gICAgICAgIHZhbHVlICo9IHNjYWxlO1xuXG4gICAgICBpZiAobG9nKSB7XG4gICAgICAgIGlmICh2YWx1ZSA+IG1pbkxvZ1ZhbHVlKVxuICAgICAgICAgIHZhbHVlID0gMTAgKiBsb2cxMCh2YWx1ZSk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICB2YWx1ZSA9IG1pbkxvZztcbiAgICAgIH1cblxuICAgICAgaWYgKHBvd2VyICE9PSAxKVxuICAgICAgICB2YWx1ZSA9IHBvdyh2YWx1ZSwgcG93ZXIpO1xuXG4gICAgICBtZWxCYW5kc1tpXSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBtZWxCYW5kcztcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKGZyYW1lKSB7XG4gICAgdGhpcy5pbnB1dFZlY3RvcihmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNZWw7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgLy8gYXJyYXkgZGVmaW5pbmcgdGhlIGZyYW1lU2l6ZXMgb2YgdGhlIGlucHV0IHN0cmVhbXNzXG4gIC8vIGUuZy4gaWYgWzMsIDIsIDFdLCB3ZSB3YWl0IGZvciAzIGRpZmZlcmVudCBzb3VyY2VzIG9mIHJlc3BlY3RpdmUgMywgMiwgMSBmcmFtZVNpemVzXG4gIGZyYW1lU2l6ZXM6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9XG59XG5cbi8qKlxuICogTWVyZ2UgbXVsdGlwbGUgdmVjdG9yIGZyYW1lcy4gVGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiBkZXBlbmRzIG9uIHRoZVxuICogb3JkZXIgdGhlIGJyYW5jaGluZyB3YXMgaW5pdGlhbGx5IG1hZGUuIFRoZSBmaXJzdCBicmFuY2hlIGlzIG1hc3RlclxuICogb24gdGhlIHRpbWUgYW5kIHRyaWdnZXIgdGhlIG91dHB1dCBvZiB0aGUgZnJhbWUuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVyc1xuICogQHBhcmFtIHtBcnJheX0gW29wdGlvbnMuZnJhbWVTaXplcz1udWxsXSAtIEFycmF5IHRoYXQgZGVmaW5lcyB0aGUgbnVtYmVyXG4gKiAgb2YgdmFsdWVzIHRvIHBpY2sgZnJvbSBlYWNoIGluY29tbWluZyB2ZWN0b3JzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NvbW9uJ1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLm9wZXJhdG9yLkV2ZW50SW4oe1xuICogICB0eXBlOiAndmVjdG9yJyxcbiAqICAgZnJhbWVTaXplOiA0LFxuICogICBmcmFtZVJhdGU6IDAsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBtaW5NYXggPSBuZXcgbGZvLm9wZXJhdG9yLk1pbk1heCgpO1xuICogY29uc3QgbWFnbml0dWRlID0gbmV3IGxmby5vcGVyYXRvci5NYWduaXR1ZGUoKTtcbiAqXG4gKiAvLyB0YWtlIHRoZSBmaXJzdCAyIHZhbHVlcyBvZiB0aGUgZmlyc3QgYnJhbmNoIGFuZCAxIHZhbHVlIGZyb20gdGhlIHNlY29uZCBicmFuY2hcbiAqIGNvbnN0IG1lcmdlID0gbmV3IGxmby5vcGVyYXRvci5NZXJnZXIoeyBmcmFtZVNpemVzOiBbMiwgMV0gfSk7XG4gKlxuICogLy8gdGhpcyBkZWZpbmVzIHRoZSBvcmRlciBpbiB3aGljaCBNZXJnZXIgd2lsbCBiZSBjYWxsZWRcbiAqIGV2ZW50SW4uY29ubmVjdChtaW5NYXgpO1xuICogZXZlbnRJbi5jb25uZWN0KG1hZ25pdHVkZSk7XG4gKlxuICogbWluTWF4LmNvbm5lY3QobWVyZ2VyKTtcbiAqIG1hZ25pdHVkZS5jb25uZWN0KG1lcmdlcik7XG4gKi9cbmNsYXNzIE1lcmdlciBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgLy8gLi4uXG4gICAgY29uc3QgZnJhbWVTaXplcyA9IHRoaXMucGFyYW1zLmdldCgnZnJhbWVTaXplcycpO1xuICAgIGNvbnN0IG51bVNvdXJjZXMgPSBmcmFtZVNpemVzLmxlbmd0aDtcblxuICAgIGxldCBmcmFtZVNpemUgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtU291cmNlczsgaSsrKVxuICAgICAgZnJhbWVTaXplICs9IGZyYW1lU2l6ZXNbaV07XG5cblxuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZSA9IGZyYW1lU2l6ZTtcbiAgICB0aGlzLm51bVNvdXJjZXMgPSBudW1Tb3VyY2VzO1xuICAgIHRoaXMuc291cmNlSW5kZXggPSAwO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIHByb2Nlc3NWZWN0b3IoKSB7fVxuICAvLyBwcm9jZXNzU2lnbmFsKCkge30gLy8gbWFrZXMgbm8gc2VucyB0byBtZXJnZSBzaWduYWxzIChtYXliZSBNVVggLyBERU1VWClcblxuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICBjb25zdCBjdXJyZW50SW5kZXggPSB0aGlzLnNvdXJjZUluZGV4O1xuICAgIGNvbnN0IGZyYW1lU2l6ZXMgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZyYW1lU2l6ZXMnKTtcbiAgICBjb25zdCBudW1Tb3VyY2VzID0gZnJhbWVTaXplcy5sZW5ndGg7XG4gICAgY29uc3QgaW5wdXQgPSBmcmFtZS5kYXRhO1xuICAgIGNvbnN0IG91dHB1dCA9IHRoaXMuZnJhbWUuZGF0YTtcblxuICAgIC8vIGZpcnN0IHNvdXJjZSBkZWZpbmUgdGltZVxuICAgIGlmIChjdXJyZW50SW5kZXggPT09IDApXG4gICAgICB0aGlzLmZyYW1lLnRpbWUgPSBmcmFtZS50aW1lO1xuXG4gICAgY29uc3QgY3VycmVudEZyYW1lU2l6ZSA9IGZyYW1lU2l6ZXNbY3VycmVudEluZGV4XTtcbiAgICBsZXQgb2Zmc2V0ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY3VycmVudEluZGV4OyBpKyspXG4gICAgICBvZmZzZXQgKz0gZnJhbWVTaXplc1tpXTtcblxuICAgIC8vIGNvcHkgZGF0YVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY3VycmVudEZyYW1lU2l6ZTsgaSsrKVxuICAgICAgb3V0cHV0W29mZnNldCArIGldID0gaW5wdXRbaV07XG5cbiAgICB0aGlzLnNvdXJjZUluZGV4ID0gKHRoaXMuc291cmNlSW5kZXggKyAxKSAlIG51bVNvdXJjZXM7XG5cbiAgICAvLyB3ZSBqdXN0IHJlY2VpdmVkIHRoZSBsYXN0IGlucHV0LCBvdXRwdXQgdGhlIGZyYW1lXG4gICAgaWYgKHRoaXMuc291cmNlSW5kZXggPT09IDApXG4gICAgICB0aGlzLnByb3BhZ2F0ZUZyYW1lKCk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWVyZ2VyO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcbmltcG9ydCBGZnQgZnJvbSAnLi9GZnQnO1xuaW1wb3J0IE1lbCBmcm9tICcuL01lbCc7XG5pbXBvcnQgRGN0IGZyb20gJy4vRGN0JztcblxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgbmJyQmFuZHM6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogMjQsXG4gICAgbWV0YTogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBuYnJDb2Vmczoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiAxMixcbiAgICBtZXRhOiB7IGtpbmQ6ICdzdGF0aWMnIH0sXG4gIH0sXG4gIG1pbkZyZXE6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDAsXG4gICAgbWV0YTogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBtYXhGcmVxOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGE6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfVxufTtcblxuXG4vKipcbiAqIENvbXB1dGUgdGhlIE1mY2Mgb2YgdGhlIGluY29tbWluZyBgc2lnbmFsYC4gSXMgYmFzaWNhbGx5IGEgd3JhcHBlciBhcm91bmRcbiAqIFtgRmZ0YF17QGxpbmsgbW9kdWxlOmNvbW1vbi5vcGVyYXRvci5GZnR9LCBbYE1lbGBde0BsaW5rIG1vZHVsZTpjb21tb24ub3BlcmF0b3IuTWVsfVxuICogYW5kIFtgRGN0YF17QGxpbmsgbW9kdWxlOmNvbW1vbi5vcGVyYXRvci5EY3R9LlxuICpcbiAqIF9zdXBwb3J0IGBzdGFuZGFsb25lYCB1c2FnZV9cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtuYnJCYW5kc30gW29wdGlvbnMubmJyQmFuZHM9MjRdIC0gTnVtYmVyIG9mIE1lbCBiYW5kcy5cbiAqIEBwYXJhbSB7bmJyQ29lZnN9IFtvcHRpb25zLm5ickNvZWZzPTEyXSAtIE51bWJlciBvZiBvdXRwdXQgY29lZnMuXG4gKlxuICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvbW1vbi5vcGVyYXRvci5GZnR9XG4gKiBAc2VlIHtAbGluayBtb2R1bGU6Y29tbW9uLm9wZXJhdG9yLk1lbH1cbiAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb21tb24ub3BlcmF0b3IuRGN0fVxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgbGZvIGZyb20gJ3dhdmVzLWxmby9ub2RlJ1xuICpcbiAqIGNvbnN0IGF1ZGlvSW5GaWxlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9JbkZpbGUoe1xuICogICBmaWxlbmFtZTogJ3BhdGgvdG8vZmlsZScsXG4gKiAgIGZyYW1lU2l6ZTogNTEyLFxuICogfSk7XG4gKlxuICogY29uc3Qgc2xpY2VyID0gbmV3IGxmby5vcGVyYXRvci5TbGljZXIoe1xuICogICBmcmFtZVNpemU6IDI1NixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IG1mY2MgPSBuZXcgbGZvLm9wZXJhdG9yLk1mY2Moe1xuICogICBuYnJCYW5kczogMjQsXG4gKiAgIG5ickNvZWZzOiAxMixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIGF1ZGlvSW5GaWxlLmNvbm5lY3Qoc2xpY2VyKTtcbiAqIHNsaWNlci5jb25uZWN0KG1mY2MpO1xuICogbWZjYy5jb25uZWN0KGxvZ2dlcik7XG4gKlxuICogYXVkaW9JbkZpbGUuc3RhcnQoKTtcbiAqL1xuY2xhc3MgTWZjYyBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIGNvbnN0IG5ickJhbmRzID0gdGhpcy5wYXJhbXMuZ2V0KCduYnJCYW5kcycpO1xuICAgIGNvbnN0IG5ickNvZWZzID0gdGhpcy5wYXJhbXMuZ2V0KCduYnJDb2VmcycpO1xuICAgIGNvbnN0IG1pbkZyZXEgPSB0aGlzLnBhcmFtcy5nZXQoJ21pbkZyZXEnKTtcbiAgICBjb25zdCBtYXhGcmVxID0gdGhpcy5wYXJhbXMuZ2V0KCdtYXhGcmVxJyk7XG4gICAgY29uc3QgaW5wdXRGcmFtZVNpemUgPSBwcmV2U3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBpbnB1dEZyYW1lUmF0ZSA9IHByZXZTdHJlYW1QYXJhbXMuZnJhbWVSYXRlO1xuICAgIGNvbnN0IGlucHV0U2FtcGxlUmF0ZSA9IHByZXZTdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlUmF0ZTtcbiAgICBjb25zdCBuYnJCaW5zID0gaW5wdXRGcmFtZVNpemUgLyAyICsgMTtcblxuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZSA9IG5ickNvZWZzO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZSA9ICd2ZWN0b3InO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmRlc2NyaXB0aW9uID0gW107XG5cbiAgICB0aGlzLmZmdCA9IG5ldyBGZnQoe1xuICAgICAgd2luZG93OiAnaGFubicsXG4gICAgICBtb2RlOiAncG93ZXInLFxuICAgICAgbm9ybTogJ3Bvd2VyJyxcbiAgICAgIHNpemU6IGlucHV0RnJhbWVTaXplLFxuICAgIH0pO1xuXG4gICAgdGhpcy5tZWwgPSBuZXcgTWVsKHtcbiAgICAgIG5ickJhbmRzOiBuYnJCYW5kcyxcbiAgICAgIGxvZzogdHJ1ZSxcbiAgICAgIHBvd2VyOiAxLFxuICAgICAgbWluRnJlcTogbWluRnJlcSxcbiAgICAgIG1heEZyZXE6IG1heEZyZXEsXG4gICAgfSk7XG5cbiAgICB0aGlzLmRjdCA9IG5ldyBEY3Qoe1xuICAgICAgb3JkZXI6IG5ickNvZWZzLFxuICAgIH0pO1xuXG4gICAgLy8gaW5pdCBzdHJlYW1zXG4gICAgdGhpcy5mZnQuaW5pdFN0cmVhbSh7XG4gICAgICBmcmFtZVR5cGU6ICdzaWduYWwnLFxuICAgICAgZnJhbWVTaXplOiBpbnB1dEZyYW1lU2l6ZSxcbiAgICAgIGZyYW1lUmF0ZTogaW5wdXRGcmFtZVJhdGUsXG4gICAgICBzb3VyY2VTYW1wbGVSYXRlOiBpbnB1dFNhbXBsZVJhdGUsXG4gICAgfSk7XG5cbiAgICB0aGlzLm1lbC5pbml0U3RyZWFtKHtcbiAgICAgIGZyYW1lVHlwZTogJ3ZlY3RvcicsXG4gICAgICBmcmFtZVNpemU6IG5ickJpbnMsXG4gICAgICBmcmFtZVJhdGU6IGlucHV0RnJhbWVSYXRlLFxuICAgICAgc291cmNlU2FtcGxlUmF0ZTogaW5wdXRTYW1wbGVSYXRlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5kY3QuaW5pdFN0cmVhbSh7XG4gICAgICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxuICAgICAgZnJhbWVTaXplOiBuYnJCYW5kcyxcbiAgICAgIGZyYW1lUmF0ZTogaW5wdXRGcmFtZVJhdGUsXG4gICAgICBzb3VyY2VTYW1wbGVSYXRlOiBpbnB1dFNhbXBsZVJhdGUsXG4gICAgfSk7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE1mY2NgIG9wZXJhdG9yIGluIGBzdGFuZGFsb25lYCBtb2RlIChpLmUuIG91dHNpZGUgb2YgYSBncmFwaCkuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXl9IGRhdGEgLSBTaWduYWwgY2h1bmsgdG8gYW5hbHlzZS5cbiAgICogQHJldHVybiB7QXJyYXl9IC0gTWZjYyBjb2VmZmljaWVudHMuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGNvbnN0IG1mY2MgPSBuZXcgbGZvLm9wZXJhdG9yLk1mY2MoKTtcbiAgICogLy8gbWFuZGF0b3J5IGZvciB1c2UgaW4gc3RhbmRhbG9uZSBtb2RlXG4gICAqIG1mY2MuaW5pdFN0cmVhbSh7IGZyYW1lU2l6ZTogMjU2LCBmcmFtZVR5cGU6ICd2ZWN0b3InIH0pO1xuICAgKiBtZmNjLmlucHV0U2lnbmFsKHNpZ25hbCk7XG4gICAqL1xuICBpbnB1dFNpZ25hbChkYXRhKSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IG5ickNvZWZzID0gdGhpcy5wYXJhbXMuZ2V0KCduYnJDb2VmcycpO1xuXG4gICAgY29uc3QgYmlucyA9IHRoaXMuZmZ0LmlucHV0U2lnbmFsKGRhdGEpO1xuICAgIGNvbnN0IG1lbEJhbmRzID0gdGhpcy5tZWwuaW5wdXRWZWN0b3IoYmlucyk7XG4gICAgLy8gY29uc29sZS5sb2cobWVsQmFuZHMpO1xuICAgIGNvbnN0IGNvZWZzID0gdGhpcy5kY3QuaW5wdXRTaWduYWwobWVsQmFuZHMpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYnJDb2VmczsgaSsrKVxuICAgICAgb3V0cHV0W2ldID0gY29lZnNbaV07XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUpIHtcbiAgICB0aGlzLmlucHV0U2lnbmFsKGZyYW1lLmRhdGEpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1mY2M7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG4vKipcbiAqIEZpbmQgbWluaW11biBhbmQgbWF4aW11bSB2YWx1ZXMgb2YgYSBnaXZlbiBgc2lnbmFsYC5cbiAqXG4gKiBfc3VwcG9ydCBgc3RhbmRhbG9uZWAgdXNhZ2VfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jb21tb24nO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVTaXplOiA1MTIsXG4gKiAgIGZyYW1lVHlwZTogJ3NpZ25hbCcsXG4gKiAgIHNhbXBsZVJhdGU6IDAsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBtaW5NYXggPSBuZXcgbGZvLm9wZXJhdG9yLk1pbk1heCgpO1xuICpcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIGV2ZW50SW4uY29ubmVjdChtaW5NYXgpO1xuICogbWluTWF4LmNvbm5lY3QobG9nZ2VyKTtcbiAqIGV2ZW50SW4uc3RhcnQoKVxuICpcbiAqIC8vIGNyZWF0ZSBhIGZyYW1lXG4gKiBjb25zdCBzaWduYWwgPSBuZXcgRmxvYXQzMkFycmF5KDUxMik7XG4gKiBmb3IgKGxldCBpID0gMDsgaSA8IDUxMjsgaSsrKVxuICogICBzaWduYWxbaV0gPSBpICsgMTtcbiAqXG4gKiBldmVudEluLnByb2Nlc3MobnVsbCwgc2lnbmFsKTtcbiAqID4gWzEsIDUxMl07XG4gKi9cbmNsYXNzIE1pbk1heCBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICAvLyB0aHJvdyBlcnJvcnMgaWYgb3B0aW9ucyBhcmUgZ2l2ZW5cbiAgICBzdXBlcih7fSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zID0ge30pIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAndmVjdG9yJztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSAyO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmRlc2NyaXB0aW9uID0gWydtaW4nLCAnbWF4J107XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE1pbk1heGAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhIGdyYXBoKS5cbiAgICpcbiAgICogQHBhcmFtIHtGbG9hdDMyQXJyYXl8QXJyYXl9IGRhdGEgLSBJbnB1dCBzaWduYWwuXG4gICAqIEByZXR1cm4ge0FycmF5fSAtIE1pbiBhbmQgbWF4IHZhbHVlcy5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY29uc3QgbWluTWF4ID0gbmV3IE1pbk1heCgpO1xuICAgKiBtaW5NYXguaW5pdFN0cmVhbSh7IGZyYW1lVHlwZTogJ3NpZ25hbCcsIGZyYW1lU2l6ZTogMTAgfSk7XG4gICAqXG4gICAqIG1pbk1heC5pbnB1dFNpZ25hbChbMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOV0pO1xuICAgKiA+IFswLCA1XVxuICAgKi9cbiAgaW5wdXRTaWduYWwoZGF0YSkge1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgbGV0IG1pbiA9ICtJbmZpbml0eTtcbiAgICBsZXQgbWF4ID0gLUluZmluaXR5O1xuXG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSBkYXRhLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgY29uc3QgdmFsdWUgPSBkYXRhW2ldO1xuICAgICAgaWYgKHZhbHVlIDwgbWluKSBtaW4gPSB2YWx1ZTtcbiAgICAgIGlmICh2YWx1ZSA+IG1heCkgbWF4ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgb3V0RGF0YVswXSA9IG1pbjtcbiAgICBvdXREYXRhWzFdID0gbWF4O1xuXG4gICAgcmV0dXJuIG91dERhdGE7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbChmcmFtZSkge1xuICAgIHRoaXMuaW5wdXRTaWduYWwoZnJhbWUuZGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWluTWF4O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIG9yZGVyOiB7XG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIG1pbjogMSxcbiAgICBtYXg6IDFlOSxcbiAgICBkZWZhdWx0OiAxMCxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfVxuICB9LFxuICBmaWxsOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBtaW46IC1JbmZpbml0eSxcbiAgICBtYXg6ICtJbmZpbml0eSxcbiAgICBkZWZhdWx0OiAwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxufTtcblxuLyoqXG4gKiBDb21wdXRlIGEgbW92aW5nIGF2ZXJhZ2Ugb3BlcmF0aW9uIG9uIHRoZSBpbmNvbW1pbmcgZnJhbWVzIChgc2NhbGFyYCBvclxuICogYHZlY3RvcmAgdHlwZSkuIElmIHRoZSBpbnB1dCBpcyBvZiB0eXBlIHZlY3RvciwgdGhlIG1vdmluZyBhdmVyYWdlIGlzXG4gKiBjb21wdXRlZCBmb3IgZWFjaCBkaW1lbnNpb24gaW4gcGFyYWxsZWwuIElmIHRoZSBzb3VyY2Ugc2FtcGxlIHJhdGUgaXMgZGVmaW5lZFxuICogZnJhbWUgdGltZSBpcyBzaGlmdGVkIHRvIHRoZSBtaWRkbGUgb2YgdGhlIHdpbmRvdyBkZWZpbmVkIGJ5IHRoZSBvcmRlci5cbiAqXG4gKiBfc3VwcG9ydCBgc3RhbmRhbG9uZWAgdXNhZ2VfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5vcmRlcj0xMF0gLSBOdW1iZXIgb2Ygc3VjY2Vzc2l2ZSB2YWx1ZXMgb24gd2hpY2hcbiAqICB0aGUgYXZlcmFnZSBpcyBjb21wdXRlZC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5maWxsPTBdIC0gVmFsdWUgdG8gZmlsbCB0aGUgcmluZyBidWZmZXIgd2l0aCBiZWZvcmVcbiAqICB0aGUgZmlyc3QgaW5wdXQgZnJhbWUuXG4gKlxuICogQHRvZG8gLSBJbXBsZW1lbnQgYHByb2Nlc3NTaWduYWxgID9cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jb21tb24nO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVTaXplOiAyLFxuICogICBmcmFtZVR5cGU6ICd2ZWN0b3InXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBtb3ZpbmdBdmVyYWdlID0gbmV3IGxmby5vcGVyYXRvci5Nb3ZpbmdBdmVyYWdlKHtcbiAqICAgb3JkZXI6IDUsXG4gKiAgIGZpbGw6IDBcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIGV2ZW50SW4uY29ubmVjdChtb3ZpbmdBdmVyYWdlKTtcbiAqIG1vdmluZ0F2ZXJhZ2UuY29ubmVjdChsb2dnZXIpO1xuICpcbiAqIGV2ZW50SW4uc3RhcnQoKTtcbiAqXG4gKiBldmVudEluLnByb2Nlc3MobnVsbCwgWzEsIDFdKTtcbiAqID4gWzAuMiwgMC4yXVxuICogZXZlbnRJbi5wcm9jZXNzKG51bGwsIFsxLCAxXSk7XG4gKiA+IFswLjQsIDAuNF1cbiAqIGV2ZW50SW4ucHJvY2VzcyhudWxsLCBbMSwgMV0pO1xuICogPiBbMC42LCAwLjZdXG4gKiBldmVudEluLnByb2Nlc3MobnVsbCwgWzEsIDFdKTtcbiAqID4gWzAuOCwgMC44XVxuICogZXZlbnRJbi5wcm9jZXNzKG51bGwsIFsxLCAxXSk7XG4gKiA+IFsxLCAxXVxuICovXG5jbGFzcyBNb3ZpbmdBdmVyYWdlIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuc3VtID0gbnVsbDtcbiAgICB0aGlzLnJpbmdCdWZmZXIgPSBudWxsO1xuICAgIHRoaXMucmluZ0luZGV4ID0gMDtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBvblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcykge1xuICAgIHN1cGVyLm9uUGFyYW1VcGRhdGUobmFtZSwgdmFsdWUsIG1ldGFzKTtcblxuICAgIC8vIEB0b2RvIC0gc2hvdWxkIGJlIGRvbmUgbGF6aWx5IGluIHByb2Nlc3NcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ29yZGVyJzpcbiAgICAgICAgdGhpcy5wcm9jZXNzU3RyZWFtUGFyYW1zKCk7XG4gICAgICAgIHRoaXMucmVzZXRTdHJlYW0oKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdmaWxsJzpcbiAgICAgICAgdGhpcy5yZXNldFN0cmVhbSgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IG9yZGVyID0gdGhpcy5wYXJhbXMuZ2V0KCdvcmRlcicpO1xuXG4gICAgdGhpcy5yaW5nQnVmZmVyID0gbmV3IEZsb2F0MzJBcnJheShvcmRlciAqIGZyYW1lU2l6ZSk7XG5cbiAgICBpZiAoZnJhbWVTaXplID4gMSlcbiAgICAgIHRoaXMuc3VtID0gbmV3IEZsb2F0MzJBcnJheShmcmFtZVNpemUpO1xuICAgIGVsc2VcbiAgICAgIHRoaXMuc3VtID0gMDtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcblxuICAgIGNvbnN0IG9yZGVyID0gdGhpcy5wYXJhbXMuZ2V0KCdvcmRlcicpO1xuICAgIGNvbnN0IGZpbGwgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZpbGwnKTtcbiAgICBjb25zdCByaW5nQnVmZmVyID0gdGhpcy5yaW5nQnVmZmVyO1xuICAgIGNvbnN0IHJpbmdMZW5ndGggPSByaW5nQnVmZmVyLmxlbmd0aDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmluZ0xlbmd0aDsgaSsrKVxuICAgICAgcmluZ0J1ZmZlcltpXSA9IGZpbGw7XG5cbiAgICBjb25zdCBmaWxsU3VtID0gb3JkZXIgKiBmaWxsO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcblxuICAgIGlmIChmcmFtZVNpemUgPiAxKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICAgICAgICB0aGlzLnN1bVtpXSA9IGZpbGxTdW07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3VtID0gZmlsbFN1bTtcbiAgICB9XG5cbiAgICB0aGlzLnJpbmdJbmRleCA9IDA7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NjYWxhcihmcmFtZSkge1xuICAgIHRoaXMuZnJhbWUuZGF0YVswXSA9IHRoaXMuaW5wdXRTY2FsYXIoZnJhbWUuZGF0YVswXSk7XG4gIH1cblxuICAvKipcbiAgICogVXNlIHRoZSBgTW92aW5nQXZlcmFnZWAgb3BlcmF0b3IgaW4gYHN0YW5kYWxvbmVgIG1vZGUgKGkuZS4gb3V0c2lkZSBvZiBhXG4gICAqIGdyYXBoKSB3aXRoIGEgYHNjYWxhcmAgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZSAtIFZhbHVlIHRvIGZlZWQgdGhlIG1vdmluZyBhdmVyYWdlIHdpdGguXG4gICAqIEByZXR1cm4ge051bWJlcn0gLSBBdmVyYWdlIHZhbHVlLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gICAqXG4gICAqIGNvbnN0IG1vdmluZ0F2ZXJhZ2UgPSBuZXcgbGZvLm9wZXJhdG9yLk1vdmluZ0F2ZXJhZ2UoeyBvcmRlcjogNSB9KTtcbiAgICogbW92aW5nQXZlcmFnZS5pbml0U3RyZWFtKHsgZnJhbWVTaXplOiAxLCBmcmFtZVR5cGU6ICdzY2FsYXInIH0pO1xuICAgKlxuICAgKiBtb3ZpbmdBdmVyYWdlLmlucHV0U2NhbGFyKDEpO1xuICAgKiA+IDAuMlxuICAgKiBtb3ZpbmdBdmVyYWdlLmlucHV0U2NhbGFyKDEpO1xuICAgKiA+IDAuNFxuICAgKiBtb3ZpbmdBdmVyYWdlLmlucHV0U2NhbGFyKDEpO1xuICAgKiA+IDAuNlxuICAgKi9cbiAgaW5wdXRTY2FsYXIodmFsdWUpIHtcbiAgICBjb25zdCBvcmRlciA9IHRoaXMucGFyYW1zLmdldCgnb3JkZXInKTtcbiAgICBjb25zdCByaW5nSW5kZXggPSB0aGlzLnJpbmdJbmRleDtcbiAgICBjb25zdCByaW5nQnVmZmVyID0gdGhpcy5yaW5nQnVmZmVyO1xuICAgIGxldCBzdW0gPSB0aGlzLnN1bTtcblxuICAgIHN1bSAtPSByaW5nQnVmZmVyW3JpbmdJbmRleF07XG4gICAgc3VtICs9IHZhbHVlO1xuXG4gICAgdGhpcy5zdW0gPSBzdW07XG4gICAgdGhpcy5yaW5nQnVmZmVyW3JpbmdJbmRleF0gPSB2YWx1ZTtcbiAgICB0aGlzLnJpbmdJbmRleCA9IChyaW5nSW5kZXggKyAxKSAlIG9yZGVyO1xuXG4gICAgcmV0dXJuIHN1bSAvIG9yZGVyO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICB0aGlzLmlucHV0VmVjdG9yKGZyYW1lLmRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE1vdmluZ0F2ZXJhZ2VgIG9wZXJhdG9yIGluIGBzdGFuZGFsb25lYCBtb2RlIChpLmUuIG91dHNpZGUgb2YgYVxuICAgKiBncmFwaCkgd2l0aCBhIGB2ZWN0b3JgIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgLSBWYWx1ZXMgdG8gZmVlZCB0aGUgbW92aW5nIGF2ZXJhZ2Ugd2l0aC5cbiAgICogQHJldHVybiB7RmxvYXQzMkFycmF5fSAtIEF2ZXJhZ2UgdmFsdWUgZm9yIGVhY2ggZGltZW5zaW9uLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gICAqXG4gICAqIGNvbnN0IG1vdmluZ0F2ZXJhZ2UgPSBuZXcgbGZvLm9wZXJhdG9yLk1vdmluZ0F2ZXJhZ2UoeyBvcmRlcjogNSB9KTtcbiAgICogbW92aW5nQXZlcmFnZS5pbml0U3RyZWFtKHsgZnJhbWVTaXplOiAyLCBmcmFtZVR5cGU6ICdzY2FsYXInIH0pO1xuICAgKlxuICAgKiBtb3ZpbmdBdmVyYWdlLmlucHV0QXJyYXkoWzEsIDFdKTtcbiAgICogPiBbMC4yLCAwLjJdXG4gICAqIG1vdmluZ0F2ZXJhZ2UuaW5wdXRBcnJheShbMSwgMV0pO1xuICAgKiA+IFswLjQsIDAuNF1cbiAgICogbW92aW5nQXZlcmFnZS5pbnB1dEFycmF5KFsxLCAxXSk7XG4gICAqID4gWzAuNiwgMC42XVxuICAgKi9cbiAgaW5wdXRWZWN0b3IodmFsdWVzKSB7XG4gICAgY29uc3Qgb3JkZXIgPSB0aGlzLnBhcmFtcy5nZXQoJ29yZGVyJyk7XG4gICAgY29uc3Qgb3V0RnJhbWUgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHJpbmdJbmRleCA9IHRoaXMucmluZ0luZGV4O1xuICAgIGNvbnN0IHJpbmdPZmZzZXQgPSByaW5nSW5kZXggKiBmcmFtZVNpemU7XG4gICAgY29uc3QgcmluZ0J1ZmZlciA9IHRoaXMucmluZ0J1ZmZlcjtcbiAgICBjb25zdCBzdW0gPSB0aGlzLnN1bTtcbiAgICBjb25zdCBzY2FsZSA9IDEgLyBvcmRlcjtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspIHtcbiAgICAgIGNvbnN0IHJpbmdCdWZmZXJJbmRleCA9IHJpbmdPZmZzZXQgKyBpO1xuICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbaV07XG4gICAgICBsZXQgbG9jYWxTdW0gPSBzdW1baV07XG5cbiAgICAgIGxvY2FsU3VtIC09IHJpbmdCdWZmZXJbcmluZ0J1ZmZlckluZGV4XTtcbiAgICAgIGxvY2FsU3VtICs9IHZhbHVlO1xuXG4gICAgICB0aGlzLnN1bVtpXSA9IGxvY2FsU3VtO1xuICAgICAgb3V0RnJhbWVbaV0gPSBsb2NhbFN1bSAqIHNjYWxlO1xuICAgICAgcmluZ0J1ZmZlcltyaW5nQnVmZmVySW5kZXhdID0gdmFsdWU7XG4gICAgfVxuXG4gICAgdGhpcy5yaW5nSW5kZXggPSAocmluZ0luZGV4ICsgMSkgJSBvcmRlcjtcblxuICAgIHJldHVybiBvdXRGcmFtZTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICB0aGlzLnByZXBhcmVGcmFtZSgpO1xuICAgIHRoaXMucHJvY2Vzc0Z1bmN0aW9uKGZyYW1lKTtcblxuICAgIGNvbnN0IG9yZGVyID0gdGhpcy5wYXJhbXMuZ2V0KCdvcmRlcicpO1xuICAgIGxldCB0aW1lID0gZnJhbWUudGltZTtcbiAgICAvLyBzaGlmdCB0aW1lIHRvIHRha2UgYWNjb3VudCBvZiB0aGUgYWRkZWQgbGF0ZW5jeVxuICAgIGlmICh0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlKVxuICAgICAgdGltZSAtPSAoMC41ICogKG9yZGVyIC0gMSkgLyB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlKTtcblxuICAgIHRoaXMuZnJhbWUudGltZSA9IHRpbWU7XG4gICAgdGhpcy5mcmFtZS5tZXRhZGF0YSA9IGZyYW1lLm1ldGFkYXRhO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1vdmluZ0F2ZXJhZ2U7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgb3JkZXI6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgbWluOiAxLFxuICAgIG1heDogMWU5LFxuICAgIGRlZmF1bHQ6IDksXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgZmlsbDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgbWluOiAtSW5maW5pdHksXG4gICAgbWF4OiArSW5maW5pdHksXG4gICAgZGVmYXVsdDogMCxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxufTtcblxuLyoqXG4gKiBDb21wdXRlIGEgbW92aW5nIG1lZGlhbiBvcGVyYXRpb24gb24gdGhlIGluY29tbWluZyBmcmFtZXMgKGBzY2FsYXJgIG9yXG4gKiBgdmVjdG9yYCB0eXBlKS4gSWYgdGhlIGlucHV0IGlzIG9mIHR5cGUgdmVjdG9yLCB0aGUgbW92aW5nIG1lZGlhbiBpc1xuICogY29tcHV0ZWQgZm9yIGVhY2ggZGltZW5zaW9uIGluIHBhcmFsbGVsLiBJZiB0aGUgc291cmNlIHNhbXBsZSByYXRlIGlzIGRlZmluZWRcbiAqIGZyYW1lIHRpbWUgaXMgc2hpZnRlZCB0byB0aGUgbWlkZGxlIG9mIHRoZSB3aW5kb3cgZGVmaW5lZCBieSB0aGUgb3JkZXIuXG4gKlxuICogX3N1cHBvcnQgYHN0YW5kYWxvbmVgIHVzYWdlX1xuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLm9wZXJhdG9yXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMub3JkZXI9OV0gLSBOdW1iZXIgb2Ygc3VjY2Vzc2l2ZSB2YWx1ZXMgaW4gd2hpY2hcbiAqICB0aGUgbWVkaWFuIGlzIHNlYXJjaGVkLiBUaGlzIHZhbHVlIG11c3QgYmUgb2RkLiBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZmlsbD0wXSAtIFZhbHVlIHRvIGZpbGwgdGhlIHJpbmcgYnVmZmVyIHdpdGggYmVmb3JlXG4gKiAgdGhlIGZpcnN0IGlucHV0IGZyYW1lLiBfZHluYW1pYyBwYXJhbWV0ZXJfXG4gKlxuICogQHRvZG8gLSBJbXBsZW1lbnQgYHByb2Nlc3NTaWduYWxgXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY29tbW9uJztcbiAqXG4gKiBjb25zdCBldmVudEluID0gbmV3IGxmby5zb3VyY2UuRXZlbnRJbih7XG4gKiAgIGZyYW1lU2l6ZTogMixcbiAqICAgZnJhbWVUeXBlOiAndmVjdG9yJyxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IG1vdmluZ01lZGlhbiA9IG5ldyBsZm8ub3BlcmF0b3IuTW92aW5nTWVkaWFuKHtcbiAqICAgb3JkZXI6IDUsXG4gKiAgIGZpbGw6IDAsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBsb2dnZXIgPSBuZXcgbGZvLnNpbmsuTG9nZ2VyKHsgZGF0YTogdHJ1ZSB9KTtcbiAqXG4gKiBldmVudEluLmNvbm5lY3QobW92aW5nTWVkaWFuKTtcbiAqIG1vdmluZ01lZGlhbi5jb25uZWN0KGxvZ2dlcik7XG4gKlxuICogZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqIGV2ZW50SW4ucHJvY2Vzc0ZyYW1lKG51bGwsIFsxLCAxXSk7XG4gKiA+IFswLCAwXVxuICogZXZlbnRJbi5wcm9jZXNzRnJhbWUobnVsbCwgWzIsIDJdKTtcbiAqID4gWzAsIDBdXG4gKiBldmVudEluLnByb2Nlc3NGcmFtZShudWxsLCBbMywgM10pO1xuICogPiBbMSwgMV1cbiAqIGV2ZW50SW4ucHJvY2Vzc0ZyYW1lKG51bGwsIFs0LCA0XSk7XG4gKiA+IFsyLCAyXVxuICogZXZlbnRJbi5wcm9jZXNzRnJhbWUobnVsbCwgWzUsIDVdKTtcbiAqID4gWzMsIDNdXG4gKi9cbmNsYXNzIE1vdmluZ01lZGlhbiBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLnJpbmdCdWZmZXIgPSBudWxsO1xuICAgIHRoaXMuc29ydEJ1ZmZlciA9IG51bGw7XG4gICAgdGhpcy5yaW5nSW5kZXggPSAwO1xuXG4gICAgdGhpcy5fZW5zdXJlT2RkT3JkZXIoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBfZW5zdXJlT2RkT3JkZXIoKSB7XG4gICAgaWYgKHRoaXMucGFyYW1zLmdldCgnb3JkZXInKSAlIDIgPT09IDApXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFsdWUgJHtvcmRlcn0gZm9yIHBhcmFtIFwib3JkZXJcIiAtIG11c3QgYmUgb2RkYCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgb25QYXJhbVVwZGF0ZShuYW1lLCB2YWx1ZSwgbWV0YXMpIHtcbiAgICBzdXBlci5vblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcyk7XG5cbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ29yZGVyJzpcbiAgICAgICAgdGhpcy5fZW5zdXJlT2RkT3JkZXIoKTtcbiAgICAgICAgdGhpcy5wcm9jZXNzU3RyZWFtUGFyYW1zKCk7XG4gICAgICAgIHRoaXMucmVzZXRTdHJlYW0oKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdmaWxsJzpcbiAgICAgICAgdGhpcy5yZXNldFN0cmVhbSgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuICAgIC8vIG91dFR5cGUgaXMgc2ltaWxhciB0byBpbnB1dCB0eXBlXG5cbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3Qgb3JkZXIgPSB0aGlzLnBhcmFtcy5nZXQoJ29yZGVyJyk7XG5cbiAgICB0aGlzLnJpbmdCdWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGZyYW1lU2l6ZSAqIG9yZGVyKTtcbiAgICB0aGlzLnNvcnRCdWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGZyYW1lU2l6ZSAqIG9yZGVyKTtcblxuICAgIHRoaXMubWluSW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheShmcmFtZVNpemUpO1xuXG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICByZXNldFN0cmVhbSgpIHtcbiAgICBzdXBlci5yZXNldFN0cmVhbSgpO1xuXG4gICAgY29uc3QgZmlsbCA9IHRoaXMucGFyYW1zLmdldCgnZmlsbCcpO1xuICAgIGNvbnN0IHJpbmdCdWZmZXIgPSB0aGlzLnJpbmdCdWZmZXI7XG4gICAgY29uc3QgcmluZ0xlbmd0aCA9IHJpbmdCdWZmZXIubGVuZ3RoO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByaW5nTGVuZ3RoOyBpKyspXG4gICAgICB0aGlzLnJpbmdCdWZmZXJbaV0gPSBmaWxsO1xuXG4gICAgdGhpcy5yaW5nSW5kZXggPSAwO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTY2FsYXIoZnJhbWUpIHtcbiAgICB0aGlzLmZyYW1lLmRhdGFbMF0gPSB0aGlzLmlucHV0U2NhbGFyKGZyYW1lLmRhdGFbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyBmb3IgdGhlIHVzZSBvZiBhIGBNb3ZpbmdNZWRpYW5gIG91dHNpZGUgYSBncmFwaCAoZS5nLiBpbnNpZGVcbiAgICogYW5vdGhlciBub2RlKSwgaW4gdGhpcyBjYXNlIGBwcm9jZXNzU3RyZWFtUGFyYW1zYCBhbmQgYHJlc2V0U3RyZWFtYFxuICAgKiBzaG91bGQgYmUgY2FsbGVkIG1hbnVhbGx5IG9uIHRoZSBub2RlLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWUgLSBWYWx1ZSB0byBmZWVkIHRoZSBtb3ZpbmcgbWVkaWFuIHdpdGguXG4gICAqIEByZXR1cm4ge051bWJlcn0gLSBNZWRpYW4gdmFsdWUuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAgICpcbiAgICogY29uc3QgbW92aW5nTWVkaWFuID0gbmV3IE1vdmluZ01lZGlhbih7IG9yZGVyOiA1IH0pO1xuICAgKiBtb3ZpbmdNZWRpYW4uaW5pdFN0cmVhbSh7IGZyYW1lU2l6ZTogMSwgZnJhbWVUeXBlOiAnc2NhbGFyJyB9KTtcbiAgICpcbiAgICogbW92aW5nTWVkaWFuLmlucHV0U2NhbGFyKDEpO1xuICAgKiA+IDBcbiAgICogbW92aW5nTWVkaWFuLmlucHV0U2NhbGFyKDIpO1xuICAgKiA+IDBcbiAgICogbW92aW5nTWVkaWFuLmlucHV0U2NhbGFyKDMpO1xuICAgKiA+IDFcbiAgICogbW92aW5nTWVkaWFuLmlucHV0U2NhbGFyKDQpO1xuICAgKiA+IDJcbiAgICovXG4gIGlucHV0U2NhbGFyKHZhbHVlKSB7XG4gICAgY29uc3QgcmluZ0luZGV4ID0gdGhpcy5yaW5nSW5kZXg7XG4gICAgY29uc3QgcmluZ0J1ZmZlciA9IHRoaXMucmluZ0J1ZmZlcjtcbiAgICBjb25zdCBzb3J0QnVmZmVyID0gdGhpcy5zb3J0QnVmZmVyO1xuICAgIGNvbnN0IG9yZGVyID0gdGhpcy5wYXJhbXMuZ2V0KCdvcmRlcicpO1xuICAgIGNvbnN0IG1lZGlhbkluZGV4ID0gKG9yZGVyIC0gMSkgLyAyO1xuICAgIGxldCBzdGFydEluZGV4ID0gMDtcblxuICAgIHJpbmdCdWZmZXJbcmluZ0luZGV4XSA9IHZhbHVlO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gbWVkaWFuSW5kZXg7IGkrKykge1xuICAgICAgbGV0IG1pbiA9ICtJbmZpbml0eTtcbiAgICAgIGxldCBtaW5JbmRleCA9IG51bGw7XG5cbiAgICAgIGZvciAobGV0IGogPSBzdGFydEluZGV4OyBqIDwgb3JkZXI7IGorKykge1xuICAgICAgICBpZiAoaSA9PT0gMClcbiAgICAgICAgICBzb3J0QnVmZmVyW2pdID0gcmluZ0J1ZmZlcltqXTtcblxuICAgICAgICBpZiAoc29ydEJ1ZmZlcltqXSA8IG1pbikge1xuICAgICAgICAgIG1pbiA9IHNvcnRCdWZmZXJbal07XG4gICAgICAgICAgbWluSW5kZXggPSBqO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIHN3YXAgbWluSW5kZXggYW5kIHN0YXJ0SW5kZXhcbiAgICAgIGNvbnN0IGNhY2hlID0gc29ydEJ1ZmZlcltzdGFydEluZGV4XTtcbiAgICAgIHNvcnRCdWZmZXJbc3RhcnRJbmRleF0gPSBzb3J0QnVmZmVyW21pbkluZGV4XTtcbiAgICAgIHNvcnRCdWZmZXJbbWluSW5kZXhdID0gY2FjaGU7XG5cbiAgICAgIHN0YXJ0SW5kZXggKz0gMTtcbiAgICB9XG5cbiAgICBjb25zdCBtZWRpYW4gPSBzb3J0QnVmZmVyW21lZGlhbkluZGV4XTtcbiAgICB0aGlzLnJpbmdJbmRleCA9IChyaW5nSW5kZXggKyAxKSAlIG9yZGVyO1xuXG4gICAgcmV0dXJuIG1lZGlhbjtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKGZyYW1lKSB7XG4gICAgdGhpcy5pbnB1dFZlY3RvcihmcmFtZS5kYXRhKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgZm9yIHRoZSB1c2Ugb2YgYSBgTW92aW5nTWVkaWFuYCBvdXRzaWRlIGEgZ3JhcGggKGUuZy4gaW5zaWRlXG4gICAqIGFub3RoZXIgbm9kZSksIGluIHRoaXMgY2FzZSBgcHJvY2Vzc1N0cmVhbVBhcmFtc2AgYW5kIGByZXNldFN0cmVhbWBcbiAgICogc2hvdWxkIGJlIGNhbGxlZCBtYW51YWxseSBvbiB0aGUgbm9kZS5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIC0gVmFsdWVzIHRvIGZlZWQgdGhlIG1vdmluZyBtZWRpYW4gd2l0aC5cbiAgICogQHJldHVybiB7RmxvYXQzMkFycmF5fSAtIE1lZGlhbiB2YWx1ZXMgZm9yIGVhY2ggZGltZW5zaW9uLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gICAqXG4gICAqIGNvbnN0IG1vdmluZ01lZGlhbiA9IG5ldyBNb3ZpbmdNZWRpYW4oeyBvcmRlcjogMywgZmlsbDogMCB9KTtcbiAgICogbW92aW5nTWVkaWFuLmluaXRTdHJlYW0oeyBmcmFtZVNpemU6IDMsIGZyYW1lVHlwZTogJ3ZlY3RvcicgfSk7XG4gICAqXG4gICAqIG1vdmluZ01lZGlhbi5pbnB1dEFycmF5KFsxLCAxXSk7XG4gICAqID4gWzAsIDBdXG4gICAqIG1vdmluZ01lZGlhbi5pbnB1dEFycmF5KFsyLCAyXSk7XG4gICAqID4gWzEsIDFdXG4gICAqIG1vdmluZ01lZGlhbi5pbnB1dEFycmF5KFszLCAzXSk7XG4gICAqID4gWzIsIDJdXG4gICAqL1xuICBpbnB1dFZlY3Rvcih2YWx1ZXMpIHtcbiAgICBjb25zdCBvcmRlciA9IHRoaXMucGFyYW1zLmdldCgnb3JkZXInKTtcbiAgICBjb25zdCByaW5nQnVmZmVyID0gdGhpcy5yaW5nQnVmZmVyO1xuICAgIGNvbnN0IHJpbmdJbmRleCA9IHRoaXMucmluZ0luZGV4O1xuICAgIGNvbnN0IHNvcnRCdWZmZXIgPSB0aGlzLnNvcnRCdWZmZXI7XG4gICAgY29uc3Qgb3V0RnJhbWUgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgbWluSW5kaWNlcyA9IHRoaXMubWluSW5kaWNlcztcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3QgbWVkaWFuSW5kZXggPSBNYXRoLmZsb29yKG9yZGVyIC8gMik7XG4gICAgbGV0IHN0YXJ0SW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gbWVkaWFuSW5kZXg7IGkrKykge1xuXG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGZyYW1lU2l6ZTsgaisrKSB7XG4gICAgICAgIG91dEZyYW1lW2pdID0gK0luZmluaXR5O1xuICAgICAgICBtaW5JbmRpY2VzW2pdID0gMDtcblxuICAgICAgICBmb3IgKGxldCBrID0gc3RhcnRJbmRleDsgayA8IG9yZGVyOyBrKyspIHtcbiAgICAgICAgICBjb25zdCBpbmRleCA9IGsgKiBmcmFtZVNpemUgKyBqO1xuXG4gICAgICAgICAgLy8gdXBkYXRlIHJpbmcgYnVmZmVyIGNvcnJlc3BvbmRpbmcgdG8gY3VycmVudFxuICAgICAgICAgIGlmIChrID09PSByaW5nSW5kZXggJiYgaSA9PT0gMClcbiAgICAgICAgICAgIHJpbmdCdWZmZXJbaW5kZXhdID0gdmFsdWVzW2pdO1xuXG4gICAgICAgICAgLy8gY29weSB2YWx1ZSBpbiBzb3J0IGJ1ZmZlciBvbiBmaXJzdCBwYXNzXG4gICAgICAgICAgaWYgKGkgPT09IDApwqBcbiAgICAgICAgICAgIHNvcnRCdWZmZXJbaW5kZXhdID0gcmluZ0J1ZmZlcltpbmRleF07XG5cbiAgICAgICAgICAvLyBmaW5kIG1pbml1bSBpbiB0aGUgcmVtYWluaW5nIGFycmF5XG4gICAgICAgICAgaWYgKHNvcnRCdWZmZXJbaW5kZXhdIDwgb3V0RnJhbWVbal0pIHtcbiAgICAgICAgICAgIG91dEZyYW1lW2pdID0gc29ydEJ1ZmZlcltpbmRleF07XG4gICAgICAgICAgICBtaW5JbmRpY2VzW2pdID0gaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3dhcCBtaW5pbXVtIGFuZCBjdXJlbnQgaW5kZXhcbiAgICAgICAgY29uc3Qgc3dhcEluZGV4ID0gc3RhcnRJbmRleCAqIGZyYW1lU2l6ZSArIGo7XG4gICAgICAgIGNvbnN0IHYgPSBzb3J0QnVmZmVyW3N3YXBJbmRleF07XG4gICAgICAgIHNvcnRCdWZmZXJbc3dhcEluZGV4XSA9IHNvcnRCdWZmZXJbbWluSW5kaWNlc1tqXV07XG4gICAgICAgIHNvcnRCdWZmZXJbbWluSW5kaWNlc1tqXV0gPSB2O1xuXG4gICAgICAgIC8vIHN0b3JlIHRoaXMgbWluaW11bSB2YWx1ZSBhcyBjdXJyZW50IHJlc3VsdFxuICAgICAgICBvdXRGcmFtZVtqXSA9IHNvcnRCdWZmZXJbc3dhcEluZGV4XTtcbiAgICAgIH1cblxuICAgICAgc3RhcnRJbmRleCArPSAxO1xuICAgIH1cblxuICAgIHRoaXMucmluZ0luZGV4ID0gKHJpbmdJbmRleCArIDEpICUgb3JkZXI7XG5cbiAgICByZXR1cm4gdGhpcy5mcmFtZS5kYXRhO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NGcmFtZShmcmFtZSkge1xuICAgIHRoaXMucHJlcHJvY2Vzc0ZyYW1lKCk7XG4gICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24oZnJhbWUpO1xuXG4gICAgY29uc3Qgb3JkZXIgPSB0aGlzLnBhcmFtcy5nZXQoJ29yZGVyJyk7XG4gICAgbGV0IHRpbWUgPSBmcmFtZS50aW1lO1xuICAgIC8vIHNoaWZ0IHRpbWUgdG8gdGFrZSBhY2NvdW50IG9mIHRoZSBhZGRlZCBsYXRlbmN5XG4gICAgaWYgKHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGUpXG4gICAgICB0aW1lIC09ICgwLjUgKiAob3JkZXIgLSAxKSAvIHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGUpO1xuXG4gICAgdGhpcy5mcmFtZS50aW1lID0gdGltZTtcbiAgICB0aGlzLmZyYW1lLm1ldGFkYXRhID0gZnJhbWUubWV0YWRhdGE7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZUZyYW1lKHRpbWUsIHRoaXMub3V0RnJhbWUsIG1ldGFkYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBNb3ZpbmdNZWRpYW47XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgLy8gZmxvYXQgb3IgYXJyYXlcbiAgZmFjdG9yOiB7XG4gICAgdHlwZTogJ2FueScsXG4gICAgZGVmYXVsdDogMSxcbiAgfVxufTtcblxuLyoqXG4gKiBNdWx0aXBseSBhIGdpdmVuIHNpZ25hbCBvciB2ZWN0b3IgYnkgYSBnaXZlbiBmYWN0b3IuIE9uIHZlY3RvclxuICogc3RyZWFtcywgYGZhY3RvcmAgY2FuIGJlIGFuIGFycmF5IG9mIHZhbHVlcyB0byBhcHBseSBvbiBlYWNoIGRpbWVuc2lvbiBvZiB0aGVcbiAqIHZlY3RvciBmcmFtZXMuXG4gKlxuICogX3N1cHBvcnQgYHN0YW5kYWxvbmVgIHVzYWdlX1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gb3ZlcnJpZGUgZGVmYXVsdCB2YWx1ZXNcbiAqIEBwYXJhbSB7TnVtYmVyfEFycmF5fSBbb3B0aW9ucy5mYWN0b3I9MV0gLSBmYWN0b3Igb3IgYXJyYXkgb2YgZmFjdG9yIHRvXG4gKiAgYXBwbHkgb24gdGhlIGluY29tbWluZyBmcmFtZS4gU2V0dGluZyBhbiBhcnJheSBpcyBvbmx5IGRlZmluZWQgaW4gY2FzZSBvZlxuICogIGEgdmVjdG9yIHN0cmVhbS5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NvbW1vbic7XG4gKlxuICogY29uc3QgZXZlbnRJbiA9IG5ldyBsZm8ub3BlcmF0b3IuRXZlbnRJbih7XG4gKiAgIHR5cGU6ICd2ZWN0b3InLFxuICogICBmcmFtZVNpemU6IDIsXG4gKiAgIGZyYW1lUmF0ZTogMCxcbiAqIH0pO1xuICogY29uc3Qgc2NhbGVyID0gbmV3IGxmby5vcGVyYXRvci5NdWx0aXBsaWVyKHsgZmFjdG9yOiAwLjEgfSk7XG4gKlxuICogZXZlbnRJbi5jb25uZWN0KHNjYWxlcik7XG4gKlxuICogZXZlbnRJbi5wcm9jZXNzKG51bGwsIFsyLCAzXSk7XG4gKiA+IFswLjIsIDAuM11cbiAqL1xuY2xhc3MgTXVsdGlwbGllciBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE11bHRpcGxpZXJgIG9wZXJhdG9yIGluIHN0YW5kYWxvbmUgbW9kZS5cbiAgICpcbiAgICogQHBhcmFtIHtGbG9hdDMyQXJyYXl8QXJyYXl9IGRhdGEgLSBJbnB1dCB2ZWN0b3JcbiAgICogQHJldHVybiB7QXJyYXl9IC0gU2NhbGVkIHZhbHVlc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBjb25zdCBzY2FsZXIgPSBuZXcgTXVsdGlwbGllcih7IGZhY3RvcjogWzIsIDRdIH0pO1xuICAgKiBzY2FsZXIuaW5pdFN0cmVhbSh7IGZyYW1lVHlwZTogJ3ZlY3RvcicsIGZyYW1lU2l6ZTogMiB9KTtcbiAgICpcbiAgICogc2NhbGVyLmlucHV0VmVjdG9yKFszLCAyXSk7XG4gICAqID4gWzYsIDhdXG4gICAqL1xuICBpbnB1dFZlY3RvcihkYXRhKSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBmYWN0b3IgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZhY3RvcicpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmFjdG9yKSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgICAgb3V0cHV0W2ldID0gZGF0YVtpXSAqIGZhY3RvcltpXTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgICAgb3V0cHV0W2ldID0gZGF0YVtpXSAqIGZhY3RvcjtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICB0aGlzLmZyYW1lLmRhdGEgPSB0aGlzLmlucHV0VmVjdG9yKGZyYW1lLmRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0aGUgYE11bHRpcGxpZXJgIG9wZXJhdG9yIGluIHN0YW5kYWxvbmUgbW9kZS5cbiAgICpcbiAgICogQHBhcmFtIHtGbG9hdDMyQXJyYXl8QXJyYXl9IGRhdGEgLSBJbnB1dCBzaWduYWwuXG4gICAqIEByZXR1cm4ge0FycmF5fSAtIFNjYWxlZCBzaWduYWwuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGNvbnN0IHNjYWxlciA9IG5ldyBNdWx0aXBsaWVyKHsgZmFjdG9yOiAwLjEgfSk7XG4gICAqIHNjYWxlci5pbml0U3RyZWFtKHsgZnJhbWVUeXBlOiAnc2lnbmFsJywgZnJhbWVTaXplOiAyIH0pO1xuICAgKlxuICAgKiBzY2FsZXIuaW5wdXRWZWN0b3IoWzEsIDJdKTtcbiAgICogPiBbMC4xLCAwLjJdXG4gICAqL1xuICBpbnB1dFNpZ25hbChkYXRhKSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICBjb25zdCBmYWN0b3IgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZhY3RvcicpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgIG91dHB1dFtpXSA9IGRhdGFbaV0gKiBmYWN0b3I7XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUpIHtcbiAgICB0aGlzLmZyYW1lLmRhdGEgPSB0aGlzLmlucHV0U2lnbmFsKGZyYW1lLmRhdGEpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpcGxpZXI7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgc3RhdGU6IHtcbiAgICB0eXBlOiAnZW51bScsXG4gICAgZGVmYXVsdDogJ29uJyxcbiAgICBsaXN0OiBbJ29uJywgJ29mZiddLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxufTtcblxuLyoqXG4gKiBUaGUgT25PZmYgb3BlcmF0b3IgYWxsb3dzIHRvIHN0b3AgdGhlIHByb3BhZ2F0aW9uIG9mIHRoZSBzdHJlYW0gaW4gYVxuICogc3ViZ3JhcGguIFdoZW4gXCJvblwiLCBmcmFtZXMgYXJlIHByb3BhZ2F0ZWQsIHdoZW4gXCJvZmZcIiB0aGUgcHJvcGFnYXRpb24gaXNcbiAqIHN0b3BwZWQuXG4gKlxuICogVGhlIGBzdHJlYW1QYXJhbXNgIHByb3BhZ2F0aW9uIGlzIG5ldmVyIGJ5cGFzc2VkIHNvIHRoZSBzdWJzZXF1ZW50IHN1YmdyYXBoXG4gKiBpcyBhbHdheXMgcmVhZHkgZm9yIGluY29tbWluZyBmcmFtZXMuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zdGF0ZT0nb24nXSAtIERlZmF1bHQgc3RhdGUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY29tbW9uJztcbiAqXG4gKiBjb25zdCBmcmFtZXMgPSBbXG4gKiAgIHsgdGltZTogMCwgZGF0YTogWzEsIDJdIH0sXG4gKiAgIHsgdGltZTogMSwgZGF0YTogWzMsIDRdIH0sXG4gKiAgIHsgdGltZTogMiwgZGF0YTogWzUsIDZdIH0sXG4gKiBdO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgRXZlbnRJbih7XG4gKiAgIGZyYW1lU2l6ZTogMixcbiAqICAgZnJhbWVSYXRlOiAwLFxuICogICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxuICogfSk7XG4gKlxuICogY29uc3Qgb25PZmYgPSBuZXcgT25PZmYoKTtcbiAqXG4gKiBjb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKHsgZGF0YTogdHJ1ZSB9KTtcbiAqXG4gKiBldmVudEluLmNvbm5lY3Qob25PZmYpO1xuICogb25PZmYuY29ubmVjdChsb2dnZXIpO1xuICpcbiAqIGV2ZW50SW4uc3RhcnQoKTtcbiAqXG4gKiBldmVudEluLnByb2Nlc3NGcmFtZShmcmFtZXNbMF0pO1xuICogPiBbMCwgMV1cbiAqXG4gKiAvLyBieXBhc3Mgc3ViZ3JhcGhcbiAqIG9uT2ZmLnNldFN0YXRlKCdvZmYnKTtcbiAqIGV2ZW50SW4ucHJvY2Vzc0ZyYW1lKGZyYW1lc1sxXSk7XG4gKlxuICogLy8gcmUtb3BlbiBzdWJncmFwaFxuICogb25PZmYuc2V0U3RhdGUoJ29uJyk7XG4gKiBldmVudEluLnByb2Nlc3NGcmFtZShmcmFtZXNbMl0pO1xuICogPiBbNSwgNl1cbiAqL1xuY2xhc3MgT25PZmYgZXh0ZW5kcyBCYXNlTGZvIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgdGhpcy5zdGF0ZSA9IHRoaXMucGFyYW1zLmdldCgnc3RhdGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIHN0YXRlIG9mIHRoZSBgT25PZmZgLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RhdGUgLSBOZXcgc3RhdGUgb2YgdGhlIG9wZXJhdG9yIChgb25gIG9yIGBvZmZgKVxuICAgKi9cbiAgc2V0U3RhdGUoc3RhdGUpIHtcbiAgICBpZiAoZGVmaW5pdGlvbnMuc3RhdGUubGlzdC5pbmRleE9mKHN0YXRlKSA9PT0gLTEpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc3dpdGNoIHN0YXRlIHZhbHVlIFwiJHtzdGF0ZX1cIiBbdmFsaWQgdmFsdWVzOiBcIm9uXCIvXCJvZmZcIl1gKTtcblxuICAgIHRoaXMuc3RhdGUgPSBzdGF0ZTtcbiAgfVxuXG4gIC8vIGRlZmluZSBhbGwgcG9zc2libGUgc3RyZWFtIEFQSVxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NjYWxhcigpIHt9XG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzVmVjdG9yKCkge31cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoKSB7fVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICBpZiAodGhpcy5zdGF0ZSA9PT0gJ29uJykge1xuICAgICAgdGhpcy5wcmVwYXJlRnJhbWUoKTtcblxuICAgICAgdGhpcy5mcmFtZS50aW1lID0gZnJhbWUudGltZTtcbiAgICAgIHRoaXMuZnJhbWUubWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcbiAgICAgIHRoaXMuZnJhbWUuZGF0YSA9IGZyYW1lLmRhdGE7XG5cbiAgICAgIHRoaXMucHJvcGFnYXRlRnJhbWUoKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgT25PZmY7XG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgZXhwb25lbnQ6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDEsXG4gIH0sXG59O1xuXG4vKipcbiAqIEFwcGx5IGFuIGV4cG9uYW50IHBvd2VyIHRvIHRoZSBzdHJlYW0uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7TnVtYmVyfSBleHBvbmVudCAtIEV4cG9uZW50XG4gKi9cbmNsYXNzIFBvd2VyIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICBpbnB1dFZlY3RvcihkYXRhKSB7XG4gICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3QgZXhwb25lbnQgPSB0aGlzLnBhcmFtcy5nZXQoJ2V4cG9uZW50Jyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICAgICAgb3V0RGF0YVtpXSA9IE1hdGgucG93KGRhdGFbaV0sIGV4cG9uZW50KTtcblxuICAgIHJldHVybiBvdXREYXRhO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICB0aGlzLmlucHV0VmVjdG9yKGZyYW1lLmRhdGEpO1xuICB9XG5cbiAgaW5wdXRTaWduYWwoZGF0YSkge1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IGV4cG9uZW50ID0gdGhpcy5wYXJhbXMuZ2V0KCdleHBvbmVudCcpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgIG91dERhdGFbaV0gPSBNYXRoLnBvdyhkYXRhW2ldLCBleHBvbmVudCk7XG5cbiAgICByZXR1cm4gb3V0RGF0YTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgdGhpcy5pbnB1dFNpZ25hbChmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBQb3dlcjtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IHNxcnQgPSBNYXRoLnNxcnQ7XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBwb3dlcjoge1xuICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgICBtZXRhczogeyBraW5kOiAnZHluYW1pYycgfSxcbiAgfSxcbn07XG5cbi8qKlxuICogQ29tcHV0ZSB0aGUgUm9vdCBNZWFuIFNxdWFyZSBvZiBhIGBzaWduYWxgLlxuICpcbiAqIF9zdXBwb3J0IGBzdGFuZGFsb25lYCB1c2FnZV9cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5wb3dlcj1mYWxzZV0gLSBJZiBgdHJ1ZWAgcmVtb3ZlIHRoZSBcIlJcIiBvZiB0aGVcbiAqICBcIlJtc1wiIGFuZCByZXR1cm4gdGhlIHNxdWFyZWQgcmVzdWx0IChpLmUuIHBvd2VyKS5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIC8vIGFzc3VtaW5nIHNvbWUgYEF1ZGlvQnVmZmVyYFxuICogY29uc3QgYXVkaW9JbkJ1ZmZlciA9IG5ldyBsZm8uc291cmNlLkF1ZGlvSW5CdWZmZXIoe1xuICogICBhdWRpb0J1ZmZlcjogYXVkaW9CdWZmZXIsXG4gKiAgIGZyYW1lU2l6ZTogNTEyLFxuICogfSk7XG4gKlxuICogY29uc3Qgcm1zID0gbmV3IGxmby5vcGVyYXRvci5SbXMoKTtcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIGF1ZGlvSW5CdWZmZXIuY29ubmVjdChybXMpO1xuICogcm1zLmNvbm5lY3QobG9nZ2VyKTtcbiAqXG4gKiBhdWRpb0luQnVmZmVyLnN0YXJ0KCk7XG4gKi9cbmNsYXNzIFJtcyBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gMTtcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAnc2NhbGFyJztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbiA9IFsncm1zJ107XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbG93cyBmb3IgdGhlIHVzZSBvZiBhIGBSbXNgIG91dHNpZGUgYSBncmFwaCAoZS5nLiBpbnNpZGVcbiAgICogYW5vdGhlciBub2RlKS4gUmV0dXJuIHRoZSBybXMgb2YgdGhlIGdpdmVuIHNpZ25hbCBibG9jay5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHNpZ25hbCAtIFNpZ25hbCBibG9jayB0byBiZSBjb21wdXRlZC5cbiAgICogQHJldHVybiB7TnVtYmVyfSAtIHJtcyBvZiB0aGUgaW5wdXQgc2lnbmFsLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gICAqXG4gICAqIGNvbnN0IHJtcyA9IG5ldyBsZm8ub3BlcmF0b3IuUm1zKCk7XG4gICAqIHJtcy5pbml0U3RyZWFtKHsgZnJhbWVUeXBlOiAnc2lnbmFsJywgZnJhbWVTaXplOiAxMDAwIH0pO1xuICAgKlxuICAgKiBjb25zdCByZXN1bHRzID0gcm1zLmlucHV0U2lnbmFsKFsuLi52YWx1ZXNdKTtcbiAgICovXG4gIGlucHV0U2lnbmFsKHNpZ25hbCkge1xuICAgIGNvbnN0IHBvd2VyID0gdGhpcy5wYXJhbXMuZ2V0KCdwb3dlcicpO1xuICAgIGNvbnN0IGxlbmd0aCA9IHNpZ25hbC5sZW5ndGg7XG4gICAgbGV0IHJtcyA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKVxuICAgICAgcm1zICs9IChzaWduYWxbaV0gKiBzaWduYWxbaV0pO1xuXG4gICAgcm1zID0gcm1zIC8gbGVuZ3RoO1xuXG4gICAgaWYgKCFwb3dlcilcbiAgICAgIHJtcyA9IHNxcnQocm1zKTtcblxuICAgIHJldHVybiBybXM7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbChmcmFtZSkge1xuICAgIHRoaXMuZnJhbWUuZGF0YVswXSA9IHRoaXMuaW5wdXRTaWduYWwoZnJhbWUuZGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUm1zO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIHR5cGU6IHtcbiAgICB0eXBlOiAnZW51bScsXG4gICAgbGlzdDogWydsaW5lYXInXSxcbiAgICBkZWZhdWx0OiAnbGluZWFyJyxcbiAgICBtZXRhczoge1xuICAgICAga2luZDogJ2R5bmFtaWMnLFxuICAgIH1cbiAgfSxcbiAgaW5wdXRNaW46IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDAsXG4gICAgbWluOiAtSW5maW5pdHksXG4gICAgbWF4OiArSW5maW5pdHksXG4gICAgbWV0YXM6IHtcbiAgICAgIGtpbmQ6ICdkeW5hbWljJyxcbiAgICB9LFxuICB9LFxuICBpbnB1dE1heDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtaW46IC1JbmZpbml0eSxcbiAgICBtYXg6ICtJbmZpbml0eSxcbiAgICBtZXRhczoge1xuICAgICAga2luZDogJ2R5bmFtaWMnLFxuICAgIH0sXG4gIH0sXG4gIG91dHB1dE1pbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtaW46IC1JbmZpbml0eSxcbiAgICBtYXg6ICtJbmZpbml0eSxcbiAgICBtZXRhczoge1xuICAgICAga2luZDogJ2R5bmFtaWMnLFxuICAgIH0sXG4gIH0sXG4gIG91dHB1dE1heDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtaW46IC1JbmZpbml0eSxcbiAgICBtYXg6ICtJbmZpbml0eSxcbiAgICBtZXRhczoge1xuICAgICAga2luZDogJ2R5bmFtaWMnLFxuICAgIH0sXG4gIH0sXG59XG5cbi8qKlxuICogQXBwbHkgYSBsaW5lYXIgc2NhbGUgb24gdGhlIGluY29tbWluZyBzdHJlYW0uIFRoZSBvdXRwdXQgaXMgbm90IGNsaXBwZWQuXG4gKlxuICogQHRvZG8gLSBpbXBsZW1lbnQgbG9nIGFuZCBleHAgc2NhbGVcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgb3B0aW9uc1xuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmlucHV0TWluPTBdIC0gSW5wdXQgTWluaW11bVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmlucHV0TWF4PTFdIC0gSW5wdXQgTWF4aW11bVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm91dHB1dE1pbj0wXSAtIE91dHB1dCBNaW5pbXVtXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMub3V0cHV0TWF4PTFdIC0gT3V0cHV0IE1heGltdW1cbiAqL1xuY2xhc3MgU2NhbGUgZXh0ZW5kcyBCYXNlTGZvIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIHRoaXMuc2NhbGUgPSBudWxsO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIF9zZXRTY2FsZUZ1bmN0aW9uKCkge1xuICAgIGNvbnN0IGlucHV0TWluID0gdGhpcy5wYXJhbXMuZ2V0KCdpbnB1dE1pbicpO1xuICAgIGNvbnN0IGlucHV0TWF4ID0gdGhpcy5wYXJhbXMuZ2V0KCdpbnB1dE1heCcpO1xuICAgIGNvbnN0IG91dHB1dE1pbiA9IHRoaXMucGFyYW1zLmdldCgnb3V0cHV0TWluJyk7XG4gICAgY29uc3Qgb3V0cHV0TWF4ID0gdGhpcy5wYXJhbXMuZ2V0KCdvdXRwdXRNYXgnKTtcblxuICAgIGNvbnN0IGEgPSAob3V0cHV0TWF4IC0gb3V0cHV0TWluKSAvIChpbnB1dE1heCAtIGlucHV0TWluKTtcbiAgICBjb25zdCBiID0gb3V0cHV0TWluIC0gYSAqIGlucHV0TWluO1xuXG4gICAgdGhpcy5zY2FsZSA9ICh4KSA9PiBhICogeCArIGI7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgb25QYXJhbVVwZGF0ZShuYW1lLCB2YWx1ZSwgbWV0YXMpIHtcbiAgICBzdXBlci5vblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcyk7XG5cbiAgICBpZiAobmFtZSAhPT0gJ3R5cGUnKVxuICAgICAgdGhpcy5fc2V0U2NhbGVGdW5jdGlvbigpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIHRoaXMuX3NldFNjYWxlRnVuY3Rpb24oKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICBpbnB1dFZlY3RvcihkYXRhKSB7XG4gICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgY29uc3Qgc2NhbGUgPSB0aGlzLnNjYWxlO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgIG91dERhdGFbaV0gPSBzY2FsZShkYXRhW2ldKTtcblxuICAgIHJldHVybiBvdXREYXRhO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICB0aGlzLmZyYW1lLmRhdGEgPSB0aGlzLmlucHV0VmVjdG9yKGZyYW1lLmRhdGEpO1xuICB9XG5cbiAgaW5wdXRTaWduYWwoZGF0YSkge1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHNjYWxlID0gdGhpcy5zY2FsZTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspXG4gICAgICBvdXREYXRhW2ldID0gc2NhbGUoZGF0YVtpXSk7XG5cbiAgICByZXR1cm4gb3V0RGF0YTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgdGhpcy5mcmFtZS5kYXRhID0gdGhpcy5pbnB1dFZlY3RvcihmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBTY2FsZTtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5pbXBvcnQgTW92aW5nQXZlcmFnZSBmcm9tICcuL01vdmluZ0F2ZXJhZ2UnO1xuXG5jb25zdCBtaW4gPSBNYXRoLm1pbjtcbmNvbnN0IG1heCA9IE1hdGgubWF4O1xuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgbG9nSW5wdXQ6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5YW5taWMnIH0sXG4gIH0sXG4gIG1pbklucHV0OiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAwLjAwMDAwMDAwMDAwMSxcbiAgICBtZXRhczogeyBraW5kOiAnZHlhbm1pYycgfSxcbiAgfSxcbiAgZmlsdGVyT3JkZXI6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogNSxcbiAgICBtZXRhczogeyBraW5kOiAnZHlhbm1pYycgfSxcbiAgfSxcbiAgdGhyZXNob2xkOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAzLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeWFubWljJyB9LFxuICB9LFxuICBvZmZUaHJlc2hvbGQ6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IC1JbmZpbml0eSxcbiAgICBtZXRhczogeyBraW5kOiAnZHlhbm1pYycgfSxcbiAgfSxcbiAgbWluSW50ZXI6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IDAuMDUwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeWFubWljJyB9LFxuICB9LFxuICBtYXhEdXJhdGlvbjoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogSW5maW5pdHksXG4gICAgbWV0YXM6IHsga2luZDogJ2R5YW5taWMnIH0sXG4gIH0sXG59XG5cbi8qKlxuICogQ3JlYXRlIHNlZ21lbnRzIGJhc2VkIG9uIGF0dGFja3MuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMubG9nSW5wdXQ9ZmFsc2VdIC0gQXBwbHkgbG9nIG9uIHRoZSBpbnB1dC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5taW5JbnB1dD0wLjAwMDAwMDAwMDAwMV0gLSBNaW5pbXVtIHZhbHVlIHRvIHVzZSBhc1xuICogIGlucHV0LlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmZpbHRlck9yZGVyPTVdIC0gT3JkZXIgb2YgdGhlIGludGVybmFsbHkgdXNlZCBtb3ZpbmdcbiAqICBhdmVyYWdlLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnRocmVzaG9sZD0zXSAtIFRocmVzaG9sZCB0aGF0IHRyaWdnZXJzIGEgc2VnbWVudFxuICogIHN0YXJ0LlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm9mZlRocmVzaG9sZD0tSW5maW5pdHldIC0gVGhyZXNob2xkIHRoYXQgdHJpZ2dlcnNcbiAqICBhIHNlZ21lbnQgZW5kLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1pbkludGVyPTAuMDUwXSAtIE1pbmltdW0gZGVsYXkgYmV0d2VlbiB0d28gc2VtZ2VudHMuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMubWF4RHVyYXRpb249SW5maW5pdHldIC0gTWF4aW11bSBkdXJhdGlvbiBvZiBhIHNlZ21lbnQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY2xpZW50JztcbiAqXG4gKiAvLyBhc3N1bWluZyBhIHN0cmVhbSBmcm9tIHRoZSBtaWNyb3Bob25lXG4gKiBjb25zdCBzb3VyY2UgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAqXG4gKiBjb25zdCBhdWRpb0luTm9kZSA9IG5ldyBsZm8uc291cmNlLkF1ZGlvSW5Ob2RlKHtcbiAqICAgc291cmNlTm9kZTogc291cmNlLFxuICogICBhdWRpb0NvbnRleHQ6IGF1ZGlvQ29udGV4dCxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNsaWNlciA9IG5ldyBsZm8ub3BlcmF0b3IuU2xpY2VyKHtcbiAqICAgZnJhbWVTaXplOiBmcmFtZVNpemUsXG4gKiAgIGhvcFNpemU6IGhvcFNpemUsXG4gKiAgIGNlbnRlcmVkVGltZVRhZ3M6IHRydWVcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHBvd2VyID0gbmV3IGxmby5vcGVyYXRvci5STVMoe1xuICogICBwb3dlcjogdHJ1ZSxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNlZ21lbnRlciA9IG5ldyBsZm8ub3BlcmF0b3IuU2VnbWVudGVyKHtcbiAqICAgbG9nSW5wdXQ6IHRydWUsXG4gKiAgIGZpbHRlck9yZGVyOiA1LFxuICogICB0aHJlc2hvbGQ6IDMsXG4gKiAgIG9mZlRocmVzaG9sZDogLUluZmluaXR5LFxuICogICBtaW5JbnRlcjogMC4wNTAsXG4gKiAgIG1heER1cmF0aW9uOiAwLjA1MCxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyB0aW1lOiB0cnVlIH0pO1xuICpcbiAqIGF1ZGlvSW5Ob2RlLmNvbm5lY3Qoc2xpY2VyKTtcbiAqIHNsaWNlci5jb25uZWN0KHBvd2VyKTtcbiAqIHBvd2VyLmNvbm5lY3Qoc2VnbWVudGVyKTtcbiAqIHNlZ21lbnRlci5jb25uZWN0KGxvZ2dlcik7XG4gKlxuICogYXVkaW9Jbk5vZGUuc3RhcnQoKTtcbiAqL1xuY2xhc3MgU2VnbWVudGVyIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLmluc2lkZVNlZ21lbnQgPSBmYWxzZTtcbiAgICB0aGlzLm9uc2V0VGltZSA9IC1JbmZpbml0eTtcblxuICAgIC8vIHN0YXRzXG4gICAgdGhpcy5taW4gPSBJbmZpbml0eTtcbiAgICB0aGlzLm1heCA9IC1JbmZpbml0eTtcbiAgICB0aGlzLnN1bSA9IDA7XG4gICAgdGhpcy5zdW1PZlNxdWFyZXMgPSAwO1xuICAgIHRoaXMuY291bnQgPSAwO1xuXG4gICAgY29uc3QgbWluSW5wdXQgPSB0aGlzLnBhcmFtcy5nZXQoJ21pbklucHV0Jyk7XG4gICAgbGV0IGZpbGwgPSBtaW5JbnB1dDtcblxuICAgIGlmICh0aGlzLnBhcmFtcy5nZXQoJ2xvZ0lucHV0JykgJiYgbWluSW5wdXQgPiAwKVxuICAgICAgZmlsbCA9IE1hdGgubG9nKG1pbklucHV0KTtcblxuICAgIHRoaXMubW92aW5nQXZlcmFnZSA9IG5ldyBNb3ZpbmdBdmVyYWdlKHtcbiAgICAgIG9yZGVyOiB0aGlzLnBhcmFtcy5nZXQoJ2ZpbHRlck9yZGVyJyksXG4gICAgICBmaWxsOiBmaWxsLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sYXN0TXZhdnJnID0gZmlsbDtcbiAgfVxuXG4gIG9uUGFyYW1VcGRhdGUobmFtZSwgdmFsdWUsIG1ldGFzKSB7XG4gICAgc3VwZXIub25QYXJhbVVwZGF0ZShuYW1lLCB2YWx1ZSwgbWV0YXMpO1xuXG4gICAgaWYgKG5hbWUgPT09ICdmaWx0ZXJPcmRlcicpXG4gICAgICB0aGlzLm1vdmluZ0F2ZXJhZ2UucGFyYW1zLnNldCgnb3JkZXInLCB2YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAndmVjdG9yJztcbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSA1O1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lUmF0ZSA9IDA7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZGVzY3JpcHRpb24gPSBbJ2R1cmF0aW9uJywgJ21pbicsICdtYXgnLCAnbWVhbicsICdzdGRkZXYnXTtcblxuXG4gICAgdGhpcy5tb3ZpbmdBdmVyYWdlLmluaXRTdHJlYW0ocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcbiAgICB0aGlzLm1vdmluZ0F2ZXJhZ2UucmVzZXRTdHJlYW0oKTtcbiAgICB0aGlzLnJlc2V0U2VnbWVudCgpO1xuICB9XG5cbiAgZmluYWxpemVTdHJlYW0oZW5kVGltZSkge1xuICAgIGlmICh0aGlzLmluc2lkZVNlZ21lbnQpXG4gICAgICB0aGlzLm91dHB1dFNlZ21lbnQoZW5kVGltZSk7XG5cbiAgICBzdXBlci5maW5hbGl6ZVN0cmVhbShlbmRUaW1lKTtcbiAgfVxuXG4gIHJlc2V0U2VnbWVudCgpIHtcbiAgICB0aGlzLmluc2lkZVNlZ21lbnQgPSBmYWxzZTtcbiAgICB0aGlzLm9uc2V0VGltZSA9IC1JbmZpbml0eTtcbiAgICAvLyBzdGF0c1xuICAgIHRoaXMubWluID0gSW5maW5pdHk7XG4gICAgdGhpcy5tYXggPSAtSW5maW5pdHk7XG4gICAgdGhpcy5zdW0gPSAwO1xuICAgIHRoaXMuc3VtT2ZTcXVhcmVzID0gMDtcbiAgICB0aGlzLmNvdW50ID0gMDtcbiAgfVxuXG4gIG91dHB1dFNlZ21lbnQoZW5kVGltZSkge1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgb3V0RGF0YVswXSA9IGVuZFRpbWUgLSB0aGlzLm9uc2V0VGltZTtcbiAgICBvdXREYXRhWzFdID0gdGhpcy5taW47XG4gICAgb3V0RGF0YVsyXSA9IHRoaXMubWF4O1xuXG4gICAgY29uc3Qgbm9ybSA9IDEgLyB0aGlzLmNvdW50O1xuICAgIGNvbnN0IG1lYW4gPSB0aGlzLnN1bSAqIG5vcm07XG4gICAgY29uc3QgbWVhbk9mU3F1YXJlID0gdGhpcy5zdW1PZlNxdWFyZXMgKiBub3JtO1xuICAgIGNvbnN0IHNxdWFyZU9mbWVhbiA9IG1lYW4gKiBtZWFuO1xuXG4gICAgb3V0RGF0YVszXSA9IG1lYW47XG4gICAgb3V0RGF0YVs0XSA9IDA7XG5cbiAgICBpZiAobWVhbk9mU3F1YXJlID4gc3F1YXJlT2ZtZWFuKVxuICAgICAgb3V0RGF0YVs0XSA9IE1hdGguc3FydChtZWFuT2ZTcXVhcmUgLSBzcXVhcmVPZm1lYW4pO1xuXG4gICAgdGhpcy5mcmFtZS50aW1lID0gdGhpcy5vbnNldFRpbWU7XG5cbiAgICB0aGlzLnByb3BhZ2F0ZUZyYW1lKCk7XG4gIH1cblxuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgY29uc3QgbG9nSW5wdXQgPSB0aGlzLnBhcmFtcy5nZXQoJ2xvZ0lucHV0Jyk7XG4gICAgY29uc3QgbWluSW5wdXQgPSB0aGlzLnBhcmFtcy5nZXQoJ21pbklucHV0Jyk7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGhpcy5wYXJhbXMuZ2V0KCd0aHJlc2hvbGQnKTtcbiAgICBjb25zdCBtaW5JbnRlciA9IHRoaXMucGFyYW1zLmdldCgnbWluSW50ZXInKTtcbiAgICBjb25zdCBtYXhEdXJhdGlvbiA9IHRoaXMucGFyYW1zLmdldCgnbWF4RHVyYXRpb24nKTtcbiAgICBjb25zdCBvZmZUaHJlc2hvbGQgPSB0aGlzLnBhcmFtcy5nZXQoJ29mZlRocmVzaG9sZCcpO1xuICAgIGNvbnN0IHJhd1ZhbHVlID0gZnJhbWUuZGF0YVswXTtcbiAgICBjb25zdCB0aW1lID0gZnJhbWUudGltZTtcbiAgICBsZXQgdmFsdWUgPSBNYXRoLm1heChyYXdWYWx1ZSwgbWluSW5wdXQpO1xuXG4gICAgaWYgKGxvZ0lucHV0KVxuICAgICAgdmFsdWUgPSBNYXRoLmxvZyh2YWx1ZSk7XG5cbiAgICBjb25zdCBkaWZmID0gdmFsdWUgLSB0aGlzLmxhc3RNdmF2cmc7XG4gICAgdGhpcy5sYXN0TXZhdnJnID0gdGhpcy5tb3ZpbmdBdmVyYWdlLmlucHV0U2NhbGFyKHZhbHVlKTtcblxuICAgIC8vIHVwZGF0ZSBmcmFtZSBtZXRhZGF0YVxuICAgIHRoaXMuZnJhbWUubWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcblxuICAgIGlmIChkaWZmID4gdGhyZXNob2xkICYmIHRpbWUgLSB0aGlzLm9uc2V0VGltZSA+IG1pbkludGVyKSB7XG4gICAgICBpZiAodGhpcy5pbnNpZGVTZWdtZW50KVxuICAgICAgICB0aGlzLm91dHB1dFNlZ21lbnQodGltZSk7XG5cbiAgICAgIC8vIHN0YXJ0IHNlZ21lbnRcbiAgICAgIHRoaXMuaW5zaWRlU2VnbWVudCA9IHRydWU7XG4gICAgICB0aGlzLm9uc2V0VGltZSA9IHRpbWU7XG4gICAgICB0aGlzLm1heCA9IC1JbmZpbml0eTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pbnNpZGVTZWdtZW50KSB7XG4gICAgICB0aGlzLm1pbiA9IG1pbih0aGlzLm1pbiwgcmF3VmFsdWUpO1xuICAgICAgdGhpcy5tYXggPSBtYXgodGhpcy5tYXgsIHJhd1ZhbHVlKTtcbiAgICAgIHRoaXMuc3VtICs9IHJhd1ZhbHVlO1xuICAgICAgdGhpcy5zdW1PZlNxdWFyZXMgKz0gcmF3VmFsdWUgKiByYXdWYWx1ZTtcbiAgICAgIHRoaXMuY291bnQrKztcblxuICAgICAgaWYgKHRpbWUgLSB0aGlzLm9uc2V0VGltZSA+PSBtYXhEdXJhdGlvbiB8fCB2YWx1ZSA8PSBvZmZUaHJlc2hvbGQpIHtcbiAgICAgICAgdGhpcy5vdXRwdXRTZWdtZW50KHRpbWUpO1xuICAgICAgICB0aGlzLmluc2lkZVNlZ21lbnQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICB0aGlzLnByZXBhcmVGcmFtZSgpO1xuICAgIHRoaXMucHJvY2Vzc0Z1bmN0aW9uKGZyYW1lKTtcbiAgICAvLyBkbyBub3QgcHJvcGFnYXRlIGhlcmUgYXMgdGhlIGZyYW1lUmF0ZSBpcyBub3cgemVyb1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNlZ21lbnRlcjtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBpbmRleDoge1xuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiAwLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdzdGF0aWMnIH0sXG4gIH0sXG4gIGluZGV4ZXM6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9XG59O1xuXG4vKipcbiAqIFNlbGVjdCBvbmUgb3Igc2V2ZXJhbCBpbmRleGVzIGZyb20gYSBgdmVjdG9yYCBpbnB1dC4gSWYgb25seSBvbmUgaW5kZXggaXNcbiAqIHNlbGVjdGVkLCB0aGUgb3V0cHV0IHdpbGwgYmUgb2YgdHlwZSBgc2NhbGFyYCwgb3RoZXJ3aXNlIHRoZSBvdXRwdXQgd2lsbFxuICogYmUgYSB2ZWN0b3IgY29udGFpbmluZyB0aGUgc2VsZWN0ZWQgaW5kZXhlcy5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCB2YWx1ZXMuXG4gKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5pbmRleCAtIEluZGV4IHRvIHNlbGVjdCBmcm9tIHRoZSBpbnB1dCBmcmFtZS5cbiAqIEBwYXJhbSB7QXJyYXk8TnVtYmVyPn0gb3B0aW9ucy5pbmRleGVzIC0gSW5kaWNlcyB0byBzZWxlY3QgZnJvbSB0aGUgaW5wdXRcbiAqICBmcmFtZSwgaWYgZGVmaW5lZCwgdGFrZSBwcmVjZWRhbmNlIG92ZXIgYG9wdGlvbi5pbmRleGAuXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY29tbW9uJztcbiAqXG4gKiBjb25zdCBldmVudEluID0gbmV3IGxmby5zb3VyY2UuRXZlbnRJbih7XG4gKiAgIGZyYW1lVHlwZTogJ3ZlY3RvcicsXG4gKiAgIGZyYW1lU2l6ZTogMyxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNlbGVjdCA9IG5ldyBsZm8ub3BlcmF0b3IuU2VsZWN0KHtcbiAqICAgaW5kZXhlczogWzIsIDBdLFxuICogfSk7XG4gKlxuICogZXZlbnRJbi5zdGFydCgpO1xuICogZXZlbnRJbi5wcm9jZXNzKDAsIFswLCAyLCA0XSk7XG4gKiA+IFs0LCAwXVxuICogZXZlbnRJbi5wcm9jZXNzKDAsIFsxLCAzLCA1XSk7XG4gKiA+IFs1LCAxXVxuICovXG5jbGFzcyBTZWxlY3QgZXh0ZW5kcyBCYXNlTGZvIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIG9uUGFyYW1VcGRhdGUobmFtZSwgdmFsdWUsIG1ldGFzID0ge30pIHtcbiAgICBzdXBlci5vblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcyk7XG5cbiAgICBjb25zdCBpbmRleCA9IHRoaXMucGFyYW1zLmdldCgnaW5kZXgnKTtcbiAgICBjb25zdCBpbmRleGVzID0gdGhpcy5wYXJhbXMuZ2V0KCdpbmRleGVzJyk7XG5cbiAgICB0aGlzLnNlbGVjdCA9IChpbmRleGVzICE9PSBudWxsKSA/IGluZGV4ZXMgOiBbaW5kZXhdO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYXJhbXMuZ2V0KCdpbmRleCcpO1xuICAgIGNvbnN0IGluZGV4ZXMgPSB0aGlzLnBhcmFtcy5nZXQoJ2luZGV4ZXMnKTtcblxuICAgIGxldCBtYXggPSAoaW5kZXhlcyAhPT0gbnVsbCkgPyAgTWF0aC5tYXguYXBwbHkobnVsbCwgaW5kZXhlcykgOiBpbmRleDtcblxuICAgIGlmIChtYXggPj0gcHJldlN0cmVhbVBhcmFtcy5mcmFtZVNpemUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc2VsZWN0IGluZGV4IFwiJHttYXh9XCJgKTtcblxuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZSA9IChpbmRleGVzICE9PSBudWxsKSA/ICd2ZWN0b3InIDogJ3NjYWxhcic7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gKGluZGV4ZXMgIT09IG51bGwpID8gaW5kZXhlcy5sZW5ndGggOiAxO1xuXG4gICAgdGhpcy5zZWxlY3QgPSAoaW5kZXhlcyAhPT0gbnVsbCkgPyBpbmRleGVzIDogW2luZGV4XTtcblxuICAgIC8vIHN0ZWFsIGRlc2NyaXB0aW9uKCkgZnJvbSBwYXJlbnRcbiAgICBpZiAocHJldlN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbikge1xuICAgICAgdGhpcy5zZWxlY3QuZm9yRWFjaCgodmFsLCBpbmRleCkgPT4ge1xuICAgICAgICB0aGlzLnN0cmVhbVBhcmFtcy5kZXNjcmlwdGlvbltpbmRleF0gPSBwcmV2U3RyZWFtUGFyYW1zLmRlc2NyaXB0aW9uW3ZhbF07XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnByb3BhZ2F0ZVN0cmVhbVBhcmFtcygpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoZnJhbWUpIHtcbiAgICBjb25zdCBkYXRhID0gZnJhbWUuZGF0YTtcbiAgICBjb25zdCBvdXREYXRhID0gdGhpcy5mcmFtZS5kYXRhO1xuICAgIGNvbnN0IHNlbGVjdCA9IHRoaXMuc2VsZWN0O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3QubGVuZ3RoOyBpKyspXG4gICAgICBvdXREYXRhW2ldID0gZGF0YVtzZWxlY3RbaV1dO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNlbGVjdDtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICBmcmFtZVNpemU6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogNTEyLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdzdGF0aWMnIH0sXG4gIH0sXG4gIGhvcFNpemU6IHsgLy8gc2hvdWxkIGJlIG51bGxhYmxlXG4gICAgdHlwZTogJ2ludGVnZXInLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgY2VudGVyZWRUaW1lVGFnczoge1xuICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfVxufVxuXG4vKipcbiAqIENoYW5nZSB0aGUgYGZyYW1lU2l6ZWAgYW5kIGBob3BTaXplYCBvZiBhIGBzaWduYWxgIGlucHV0IGFjY29yZGluZyB0b1xuICogdGhlIGdpdmVuIG9wdGlvbnMuXG4gKiBUaGlzIG9wZXJhdG9yIHVwZGF0ZXMgdGhlIHN0cmVhbSBwYXJhbWV0ZXJzIGFjY29yZGluZyB0byBpdHMgY29uZmlndXJhdGlvbi5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5vcGVyYXRvclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gT3ZlcnJpZGUgZGVmYXVsdCBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmZyYW1lU2l6ZT01MTJdIC0gRnJhbWUgc2l6ZSBvZiB0aGUgb3V0cHV0IHNpZ25hbC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5ob3BTaXplPW51bGxdIC0gTnVtYmVyIG9mIHNhbXBsZXMgYmV0d2VlbiB0d29cbiAqICBjb25zZWN1dGl2ZSBmcmFtZXMuIElmIG51bGwsIGBob3BTaXplYCBpcyBzZXQgdG8gYGZyYW1lU2l6ZWAuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmNlbnRlcmVkVGltZVRhZ3NdIC0gTW92ZSB0aGUgdGltZSB0YWcgdG8gdGhlIG1pZGRsZVxuICogIG9mIHRoZSBmcmFtZS5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jb21tb24nO1xuICpcbiAqIGNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAqICAgZnJhbWVUeXBlOiAnc2lnbmFsJyxcbiAqICAgZnJhbWVTaXplOiAxMCxcbiAqICAgc2FtcGxlUmF0ZTogMixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNsaWNlciA9IG5ldyBsZm8ub3BlcmF0b3IuU2xpY2VyKHtcbiAqICAgZnJhbWVTaXplOiA0LFxuICogICBob3BTaXplOiAyXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBsb2dnZXIgPSBuZXcgbGZvLnNpbmsuTG9nZ2VyKHsgdGltZTogdHJ1ZSwgZGF0YTogdHJ1ZSB9KTtcbiAqXG4gKiBldmVudEluLmNvbm5lY3Qoc2xpY2VyKTtcbiAqIHNsaWNlci5jb25uZWN0KGxvZ2dlcik7XG4gKiBldmVudEluLnN0YXJ0KCk7XG4gKlxuICogZXZlbnRJbi5wcm9jZXNzKDAsIFswLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5XSk7XG4gKiA+IHsgdGltZTogMCwgZGF0YTogWzAsIDEsIDIsIDNdIH1cbiAqID4geyB0aW1lOiAxLCBkYXRhOiBbMiwgMywgNCwgNV0gfVxuICogPiB7IHRpbWU6IDIsIGRhdGE6IFs0LCA1LCA2LCA3XSB9XG4gKiA+IHsgdGltZTogMywgZGF0YTogWzYsIDcsIDgsIDldIH1cbiAqL1xuY2xhc3MgU2xpY2VyIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKGRlZmluaXRpb25zLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IGhvcFNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ2hvcFNpemUnKTtcbiAgICBjb25zdCBmcmFtZVNpemUgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZyYW1lU2l6ZScpO1xuXG4gICAgaWYgKCFob3BTaXplKVxuICAgICAgdGhpcy5wYXJhbXMuc2V0KCdob3BTaXplJywgZnJhbWVTaXplKTtcblxuICAgIHRoaXMucGFyYW1zLmFkZExpc3RlbmVyKHRoaXMub25QYXJhbVVwZGF0ZS5iaW5kKHRoaXMpKTtcblxuICAgIHRoaXMuZnJhbWVJbmRleCA9IDA7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgY29uc3QgaG9wU2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnaG9wU2l6ZScpO1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnZnJhbWVTaXplJyk7XG5cbiAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPSBmcmFtZVNpemU7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVSYXRlID0gcHJldlN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlIC8gaG9wU2l6ZTtcblxuICAgIGlmICh0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUgPT09IDEpXG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAnc2NhbGFyJztcbiAgICBlbHNlXG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgPSAnc2lnbmFsJztcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcmVzZXRTdHJlYW0oKSB7XG4gICAgc3VwZXIucmVzZXRTdHJlYW0oKTtcbiAgICB0aGlzLmZyYW1lSW5kZXggPSAwO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIGZpbmFsaXplU3RyZWFtKGVuZFRpbWUpIHtcbiAgICBpZiAodGhpcy5mcmFtZUluZGV4ID4gMCkge1xuICAgICAgY29uc3QgZnJhbWVSYXRlID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVSYXRlO1xuICAgICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcbiAgICAgIC8vIHNldCB0aGUgdGltZSBvZiB0aGUgbGFzdCBmcmFtZVxuICAgICAgdGhpcy5mcmFtZS50aW1lICs9ICgxIC8gZnJhbWVSYXRlKTtcblxuICAgICAgZm9yIChsZXQgaSA9IHRoaXMuZnJhbWVJbmRleDsgaSA8IGZyYW1lU2l6ZTsgaSsrKVxuICAgICAgICBkYXRhW2ldID0gMDtcblxuICAgICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuICAgIH1cblxuICAgIHN1cGVyLmZpbmFsaXplU3RyZWFtKGVuZFRpbWUpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NGcmFtZShmcmFtZSkge1xuICAgIHRoaXMucHJlcGFyZUZyYW1lKCk7XG4gICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24oZnJhbWUpO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTaWduYWwoZnJhbWUpIHtcbiAgICBjb25zdCB0aW1lID0gZnJhbWUudGltZTtcbiAgICBjb25zdCBibG9jayA9IGZyYW1lLmRhdGE7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcblxuICAgIGNvbnN0IGNlbnRlcmVkVGltZVRhZ3MgPSB0aGlzLnBhcmFtcy5nZXQoJ2NlbnRlcmVkVGltZVRhZ3MnKTtcbiAgICBjb25zdCBob3BTaXplID0gdGhpcy5wYXJhbXMuZ2V0KCdob3BTaXplJyk7XG4gICAgY29uc3Qgb3V0RnJhbWUgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgY29uc3QgZnJhbWVTaXplID0gdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplO1xuICAgIGNvbnN0IHNhbXBsZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlO1xuICAgIGNvbnN0IHNhbXBsZVBlcmlvZCA9IDEgLyBzYW1wbGVSYXRlO1xuICAgIGNvbnN0IGJsb2NrU2l6ZSA9IGJsb2NrLmxlbmd0aDtcblxuICAgIGxldCBmcmFtZUluZGV4ID0gdGhpcy5mcmFtZUluZGV4O1xuICAgIGxldCBibG9ja0luZGV4ID0gMDtcblxuICAgIHdoaWxlIChibG9ja0luZGV4IDwgYmxvY2tTaXplKSB7XG4gICAgICBsZXQgbnVtU2tpcCA9IDA7XG5cbiAgICAgIC8vIHNraXAgYmxvY2sgc2FtcGxlcyBmb3IgbmVnYXRpdmUgZnJhbWVJbmRleCAoZnJhbWVTaXplIDwgaG9wU2l6ZSlcbiAgICAgIGlmIChmcmFtZUluZGV4IDwgMCkge1xuICAgICAgICBudW1Ta2lwID0gLWZyYW1lSW5kZXg7XG4gICAgICAgIGZyYW1lSW5kZXggPSAwOyAvLyByZXNldCBgZnJhbWVJbmRleGBcbiAgICAgIH1cblxuICAgICAgaWYgKG51bVNraXAgPCBibG9ja1NpemUpIHtcbiAgICAgICAgYmxvY2tJbmRleCArPSBudW1Ta2lwOyAvLyBza2lwIGJsb2NrIHNlZ21lbnRcbiAgICAgICAgLy8gY2FuIGNvcHkgYWxsIHRoZSByZXN0IG9mIHRoZSBpbmNvbWluZyBibG9ja1xuICAgICAgICBsZXQgbnVtQ29weSA9IGJsb2NrU2l6ZSAtIGJsb2NrSW5kZXg7XG4gICAgICAgIC8vIGNvbm5vdCBjb3B5IG1vcmUgdGhhbiB3aGF0IGZpdHMgaW50byB0aGUgZnJhbWVcbiAgICAgICAgY29uc3QgbWF4Q29weSA9IGZyYW1lU2l6ZSAtIGZyYW1lSW5kZXg7XG5cbiAgICAgICAgaWYgKG51bUNvcHkgPj0gbWF4Q29weSlcbiAgICAgICAgICBudW1Db3B5ID0gbWF4Q29weTtcblxuICAgICAgICAvLyBjb3B5IGJsb2NrIHNlZ21lbnQgaW50byBmcmFtZVxuICAgICAgICBjb25zdCBjb3B5ID0gYmxvY2suc3ViYXJyYXkoYmxvY2tJbmRleCwgYmxvY2tJbmRleCArIG51bUNvcHkpO1xuICAgICAgICBvdXRGcmFtZS5zZXQoY29weSwgZnJhbWVJbmRleCk7XG4gICAgICAgIC8vIGFkdmFuY2UgYmxvY2sgYW5kIGZyYW1lIGluZGV4XG4gICAgICAgIGJsb2NrSW5kZXggKz0gbnVtQ29weTtcbiAgICAgICAgZnJhbWVJbmRleCArPSBudW1Db3B5O1xuXG4gICAgICAgIC8vIHNlbmQgZnJhbWUgd2hlbiBjb21wbGV0ZWRcbiAgICAgICAgaWYgKGZyYW1lSW5kZXggPT09IGZyYW1lU2l6ZSkge1xuICAgICAgICAgIC8vIGRlZmluZSB0aW1lIHRhZyBmb3IgdGhlIG91dEZyYW1lIGFjY29yZGluZyB0byBjb25maWd1cmF0aW9uXG4gICAgICAgICAgaWYgKGNlbnRlcmVkVGltZVRhZ3MpXG4gICAgICAgICAgICB0aGlzLmZyYW1lLnRpbWUgPSB0aW1lICsgKGJsb2NrSW5kZXggLSBmcmFtZVNpemUgLyAyKSAqIHNhbXBsZVBlcmlvZDtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLmZyYW1lLnRpbWUgPSB0aW1lICsgKGJsb2NrSW5kZXggLSBmcmFtZVNpemUpICogc2FtcGxlUGVyaW9kO1xuXG4gICAgICAgICAgdGhpcy5mcmFtZS5tZXRhZGF0YSA9IG1ldGFkYXRhO1xuICAgICAgICAgIC8vIGZvcndhcmQgdG8gbmV4dCBub2Rlc1xuICAgICAgICAgIHRoaXMucHJvcGFnYXRlRnJhbWUoKTtcblxuICAgICAgICAgIC8vIHNoaWZ0IGZyYW1lIGxlZnRcbiAgICAgICAgICBpZiAoaG9wU2l6ZSA8IGZyYW1lU2l6ZSlcbiAgICAgICAgICAgIG91dEZyYW1lLnNldChvdXRGcmFtZS5zdWJhcnJheShob3BTaXplLCBmcmFtZVNpemUpLCAwKTtcblxuICAgICAgICAgIGZyYW1lSW5kZXggLT0gaG9wU2l6ZTsgLy8gaG9wIGZvcndhcmRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gc2tpcCBlbnRpcmUgYmxvY2tcbiAgICAgICAgY29uc3QgYmxvY2tSZXN0ID0gYmxvY2tTaXplIC0gYmxvY2tJbmRleDtcbiAgICAgICAgZnJhbWVJbmRleCArPSBibG9ja1Jlc3Q7XG4gICAgICAgIGJsb2NrSW5kZXggKz0gYmxvY2tSZXN0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZnJhbWVJbmRleCA9IGZyYW1lSW5kZXg7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgU2xpY2VyO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgY2VpbCA9IE1hdGguY2VpbDtcblxuLyoqXG4gKiBwYXBlcjogaHR0cDovL3JlY2hlcmNoZS5pcmNhbS5mci9lcXVpcGVzL3BjbS9jaGV2ZWlnbi9wc3MvMjAwMl9KQVNBX1lJTi5wZGZcbiAqIGltcGxlbWVudGF0aW9uIGJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS9hc2hva2Zlcm5hbmRlei9ZaW4tUGl0Y2gtVHJhY2tpbmdcbiAqIEBwcml2YXRlXG4gKi9cblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIHRocmVzaG9sZDoge1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogMC4xLCAvLyBkZWZhdWx0IGZyb20gcGFwZXJcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBkb3duU2FtcGxpbmdFeHA6IHsgLy8gZG93bnNhbXBsaW5nIGZhY3RvclxuICAgIHR5cGU6ICdpbnRlZ2VyJyxcbiAgICBkZWZhdWx0OiAyLFxuICAgIG1pbjogMCxcbiAgICBtYXg6IDMsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgbWluRnJlcTogeyAvL1xuICAgIHR5cGU6ICdmbG9hdCcsXG4gICAgZGVmYXVsdDogNjAsIC8vIG1lYW4gNzM1IHNhbXBsZXNcbiAgICBtaW46IDAsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbn1cblxuLyoqXG4gKiBZaW4gZnVuZGFtZW50YWwgZnJlcXVlbmN5IGVzdGltYXRvciwgYmFzZWQgb24gYWxnb3JpdGhtIGRlc2NyaWJlZCBpblxuICogW1lJTiwgYSBmdW5kYW1lbnRhbCBmcmVxdWVuY3kgZXN0aW1hdG9yIGZvciBzcGVlY2ggYW5kIG11c2ljXShodHRwOi8vcmVjaGVyY2hlLmlyY2FtLmZyL2VxdWlwZXMvcGNtL2NoZXZlaWduL3Bzcy8yMDAyX0pBU0FfWUlOLnBkZilcbiAqIGJ5IENoZXZlaWduZSBhbmQgS2F3YWhhcmEuXG4gKiBPbiBlYWNoIGZyYW1lLCB0aGlzIG9wZXJhdG9yIHByb3BhZ2F0ZSBhIHZlY3RvciBjb250YWluaW5nIHRoZSBmb2xsb3dpbmdcbiAqIHZhbHVlczogYGZyZXF1ZW5jeWAsIGBwcm9iYWJpbGl0eWAuXG4gKlxuICogRm9yIGdvb2QgcmVzdWx0cyB0aGUgaW5wdXQgZnJhbWUgc2l6ZSBzaG91bGQgYmUgbGFyZ2UgKDEwMjQgb3IgMjA0OCkuXG4gKlxuICogX3N1cHBvcnQgYHN0YW5kYWxvbmVgIHVzYWdlX1xuICpcbiAqIEBub3RlIC0gSW4gbm9kZSBmb3IgYSBmcmFtZSBvZiAyMDQ4IHNhbXBsZXMsIGF2ZXJhZ2UgY29tcHV0YXRpb24gdGltZSBpczpcbiAqICAgICAgICAgMC4wMDAxNjc0MjI4MzMzOTk5MzM4OSBzZWNvbmQuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24ub3BlcmF0b3JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy50aHJlc2hvbGQ9MC4xXSAtIEFic29sdXRlIHRocmVzaG9sZCB0byB0ZXN0IHRoZVxuICogIG5vcm1hbGl6ZWQgZGlmZmVyZW5jZSAoc2VlIHBhcGVyIGZvciBtb3JlIGluZm9ybWF0aW9ucykuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZG93blNhbXBsaW5nRXhwPTJdIC0gRG93biBzYW1wbGUgdGhlIGlucHV0IGZyYW1lIGJ5XG4gKiAgYSBmYWN0b3Igb2YgMiBhdCB0aGUgcG93ZXIgb2YgYGRvd25TYW1wbGluZ0V4cGAgKG1pbj0wIGFuZCBtYXg9MykgZm9yXG4gKiAgcGVyZm9ybWFuY2UgaW1wcm92ZW1lbnRzLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLm1pbkZyZXE9NjBdIC0gTWluaW11bSBmcmVxdWVuY3kgdGhlIG9wZXJhdG9yIGNhblxuICogIHNlYXJjaCBmb3IuIFRoaXMgcGFyYW1ldGVyIGRlZmluZXMgdGhlIHNpemUgb2YgdGhlIGF1dG9jb3JyZWxhdGlvbiBwZXJmb3JtZWRcbiAqICBvbiB0aGUgc2lnbmFsLCB0aGUgaW5wdXQgZnJhbWUgc2l6ZSBzaG91bGQgYmUgYXJvdW5kIDIgdGltZSB0aGlzIHNpemUgZm9yXG4gKiAgZ29vZCByZXN1bHRzIChpLmUuIGBpbnB1dEZyYW1lU2l6ZSDiiYggMiAqIChzYW1wbGluZ1JhdGUgLyBtaW5GcmVxKWApLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gKlxuICogLy8gYXNzdW1pbmcgc29tZSBBdWRpb0J1ZmZlclxuICogY29uc3Qgc291cmNlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9JbkJ1ZmZlcih7XG4gKiAgIGF1ZGlvQnVmZmVyOiBhdWRpb0J1ZmZlcixcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHNsaWNlciA9IG5ldyBsZm8ub3BlcmF0b3IuU2xpY2VyKHtcbiAqICAgZnJhbWVTaXplOiAyMDQ4LFxuICogfSk7XG4gKlxuICogY29uc3QgeWluID0gbmV3IGxmby5vcGVyYXRvci5ZaW4oKTtcbiAqIGNvbnN0IGxvZ2dlciA9IG5ldyBsZm8uc2luay5Mb2dnZXIoeyBkYXRhOiB0cnVlIH0pO1xuICpcbiAqIHNvdXJjZS5jb25uZWN0KHNsaWNlcik7XG4gKiBzbGljZXIuY29ubmVjdCh5aW4pO1xuICogeWluLmNvbm5lY3QobG9nZ2VyKTtcbiAqXG4gKiBzb3VyY2Uuc3RhcnQoKTtcbiAqL1xuY2xhc3MgWWluIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLnByb2JhYmlsaXR5ID0gMDtcbiAgICB0aGlzLnBpdGNoID0gLTE7XG5cbiAgICB0aGlzLnRlc3QgPSAwO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIF9kb3duc2FtcGxlKGlucHV0LCBzaXplLCBvdXRwdXQsIGRvd25TYW1wbGluZ0V4cCkge1xuICAgIGNvbnN0IG91dHB1dFNpemUgPSBzaXplID4+IGRvd25TYW1wbGluZ0V4cDtcbiAgICBsZXQgaSwgajtcblxuICAgIHN3aXRjaCAoZG93blNhbXBsaW5nRXhwKSB7XG4gICAgICBjYXNlIDA6IC8vIG5vIGRvd24gc2FtcGxpbmdcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHNpemU7IGkrKylcbiAgICAgICAgICBvdXRwdXRbaV0gPSBpbnB1dFtpXTtcblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgZm9yIChpID0gMCwgaiA9IDA7IGkgPCBvdXRwdXRTaXplOyBpKyssIGogKz0gMilcbiAgICAgICAgICBvdXRwdXRbaV0gPSAwLjUgKiAoaW5wdXRbal0gKyBpbnB1dFtqICsgMV0pO1xuXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIDI6XG4gICAgICAgIGZvciAoaSA9IDAsIGogPSAwOyBpIDwgb3V0cHV0U2l6ZTsgaSsrLCBqICs9IDQpXG4gICAgICAgICAgb3V0cHV0W2ldID0gMC4yNSAqIChpbnB1dFtqXSArIGlucHV0W2ogKyAxXSArIGlucHV0W2ogKyAyXSArIGlucHV0W2ogKyAzXSk7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIGZvciAoaSA9IDAsIGogPSAwOyBpIDwgb3V0cHV0U2l6ZTsgaSsrLCBqICs9IDgpXG4gICAgICAgICAgb3V0cHV0W2ldID0gMC4xMjUgKiAoaW5wdXRbal0gKyBpbnB1dFtqICsgMV0gKyBpbnB1dFtqICsgMl0gKyBpbnB1dFtqICsgM10gKyBpbnB1dFtqICsgNF0gKyBpbnB1dFtqICsgNV0gKyBpbnB1dFtqICsgNl0gKyBpbnB1dFtqICsgN10pO1xuXG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXRTaXplO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykge1xuICAgIHRoaXMucHJlcGFyZVN0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lVHlwZSA9ICd2ZWN0b3InO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZSA9IDI7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZGVzY3JpcHRpb24gPSBbJ2ZyZXF1ZW5jeScsICdjb25maWRlbmNlJ107XG5cbiAgICB0aGlzLmlucHV0RnJhbWVTaXplID0gcHJldlN0cmVhbVBhcmFtcy5mcmFtZVNpemU7XG4gICAgLy8gaGFuZGxlIHBhcmFtc1xuICAgIGNvbnN0IHNvdXJjZVNhbXBsZVJhdGUgPSB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlO1xuICAgIGNvbnN0IGRvd25TYW1wbGluZ0V4cCA9IHRoaXMucGFyYW1zLmdldCgnZG93blNhbXBsaW5nRXhwJyk7XG4gICAgY29uc3QgZG93bkZhY3RvciA9IDEgPDwgZG93blNhbXBsaW5nRXhwOyAvLyAyXm5cbiAgICBjb25zdCBkb3duU1IgPSBzb3VyY2VTYW1wbGVSYXRlIC8gZG93bkZhY3RvcjtcbiAgICBjb25zdCBkb3duRnJhbWVTaXplID0gdGhpcy5pbnB1dEZyYW1lU2l6ZSAvIGRvd25GYWN0b3I7IC8vIG5fdGlja19kb3duIC8vIDEgLyAyXm5cblxuICAgIGNvbnN0IG1pbkZyZXEgPSB0aGlzLnBhcmFtcy5nZXQoJ21pbkZyZXEnKTtcbiAgICAvLyBsaW1pdCBtaW4gZnJlcSwgY2YuIHBhcGVyIElWLiBzZW5zaXRpdml0eSB0byBwYXJhbWV0ZXJzXG4gICAgY29uc3QgbWluRnJlcU5iclNhbXBsZXMgPSBkb3duU1IgLyBtaW5GcmVxO1xuICAgIC8vIGNvbnN0IGJ1ZmZlclNpemUgPSBwcmV2U3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICB0aGlzLmhhbGZCdWZmZXJTaXplID0gZG93bkZyYW1lU2l6ZSAvIDI7XG5cbiAgICAvLyBtaW5pbXVtIGVycm9yIHRvIG5vdCBjcmFzaCBidXQgbm90IGVub3VnaHQgdG8gaGF2ZSByZXN1bHRzXG4gICAgaWYgKG1pbkZyZXFOYnJTYW1wbGVzID4gdGhpcy5oYWxmQnVmZmVyU2l6ZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCBmcmFtZSBzaXplLCB0b28gc21hbGwgZm9yIGdpdmVuIFwibWluRnJlcVwiJyk7XG5cbiAgICB0aGlzLmRvd25TYW1wbGluZ0V4cCA9IGRvd25TYW1wbGluZ0V4cDtcbiAgICB0aGlzLmRvd25TYW1wbGluZ1JhdGUgPSBkb3duU1I7XG4gICAgdGhpcy5kb3duRnJhbWVTaXplID0gZG93bkZyYW1lU2l6ZTtcbiAgICB0aGlzLmJ1ZmZlciA9IG5ldyBGbG9hdDMyQXJyYXkoZG93bkZyYW1lU2l6ZSk7XG4gICAgLy8gYXV0b2NvcnJlbGF0aW9uIGJ1ZmZlclxuICAgIHRoaXMueWluQnVmZmVyID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLmhhbGZCdWZmZXJTaXplKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgX2Rvd25zYW1wbGUoaW5wdXQsIHNpemUsIG91dHB1dCwgZG93blNhbXBsaW5nRXhwKSB7XG4gICAgY29uc3Qgb3V0cHV0U2l6ZSA9IHNpemUgPj4gZG93blNhbXBsaW5nRXhwO1xuICAgIGxldCBpLCBqO1xuXG4gICAgc3dpdGNoIChkb3duU2FtcGxpbmdFeHApIHtcbiAgICAgIGNhc2UgMDogLy8gbm8gZG93biBzYW1wbGluZ1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2l6ZTsgaSsrKVxuICAgICAgICAgIG91dHB1dFtpXSA9IGlucHV0W2ldO1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxOlxuICAgICAgICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IG91dHB1dFNpemU7IGkrKywgaiArPSAyKVxuICAgICAgICAgIG91dHB1dFtpXSA9IDAuNSAqIChpbnB1dFtqXSArIGlucHV0W2ogKyAxXSk7XG5cbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgZm9yIChpID0gMCwgaiA9IDA7IGkgPCBvdXRwdXRTaXplOyBpKyssIGogKz0gNClcbiAgICAgICAgICBvdXRwdXRbaV0gPSAwLjI1ICogKGlucHV0W2pdICsgaW5wdXRbaiArIDFdICsgaW5wdXRbaiArIDJdICsgaW5wdXRbaiArIDNdKTtcblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgZm9yIChpID0gMCwgaiA9IDA7IGkgPCBvdXRwdXRTaXplOyBpKyssIGogKz0gOClcbiAgICAgICAgICBvdXRwdXRbaV0gPSAwLjEyNSAqIChpbnB1dFtqXSArIGlucHV0W2ogKyAxXSArIGlucHV0W2ogKyAyXSArIGlucHV0W2ogKyAzXSArIGlucHV0W2ogKyA0XSArIGlucHV0W2ogKyA1XSArIGlucHV0W2ogKyA2XSArIGlucHV0W2ogKyA3XSk7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dFNpemU7XG4gIH1cblxuICAvKipcbiAgICogU3RlcCAxLCAyIGFuZCAzIC0gU3F1YXJlZCBkaWZmZXJlbmNlIG9mIHRoZSBzaGlmdGVkIHNpZ25hbCB3aXRoIGl0c2VsZi5cbiAgICogY3VtdWxhdGl2ZSBtZWFuIG5vcm1hbGl6ZWQgZGlmZmVyZW5jZS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG4gIF9ub3JtYWxpemVkRGlmZmVyZW5jZShidWZmZXIpIHtcbiAgICBjb25zdCBoYWxmQnVmZmVyU2l6ZSA9IHRoaXMuaGFsZkJ1ZmZlclNpemU7XG4gICAgY29uc3QgeWluQnVmZmVyID0gdGhpcy55aW5CdWZmZXI7XG4gICAgbGV0IHN1bSA9IDA7XG5cbiAgICAvLyBkaWZmZXJlbmNlIGZvciBkaWZmZXJlbnQgc2hpZnQgdmFsdWVzICh0YXUpXG4gICAgZm9yIChsZXQgdGF1ID0gMDsgdGF1IDwgaGFsZkJ1ZmZlclNpemU7IHRhdSsrKSB7XG4gICAgICBsZXQgc3F1YXJlZERpZmZlcmVuY2UgPSAwOyAvLyByZXNldCBidWZmZXJcblxuICAgICAgLy8gdGFrZSBkaWZmZXJlbmNlIG9mIHRoZSBzaWduYWwgd2l0aCBhIHNoaWZ0ZWQgdmVyc2lvbiBvZiBpdHNlbGYgdGhlblxuICAgICAgLy8gc3FhdXJlIHRoZSByZXN1bHRcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGFsZkJ1ZmZlclNpemU7IGkrKykge1xuICAgICAgICBjb25zdCBkZWx0YSA9IGJ1ZmZlcltpXSAtIGJ1ZmZlcltpICsgdGF1XTtcbiAgICAgICAgc3F1YXJlZERpZmZlcmVuY2UgKz0gZGVsdGEgKiBkZWx0YTtcbiAgICAgIH1cblxuICAgICAgLy8gc3RlcCAzIC0gbm9ybWFsaXplIHlpbkJ1ZmZlclxuICAgICAgaWYgKHRhdSA+IDApIHtcbiAgICAgICAgc3VtICs9IHNxdWFyZWREaWZmZXJlbmNlO1xuICAgICAgICB5aW5CdWZmZXJbdGF1XSA9IHNxdWFyZWREaWZmZXJlbmNlICogKHRhdSAvIHN1bSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgeWluQnVmZmVyWzBdID0gMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGVwIDQgLSBmaW5kIGZpcnN0IGJlc3QgdGF1IHRoYXQgaXMgdW5kZXIgdGhlIHRocmVzb2xkLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgX2Fic29sdXRlVGhyZXNob2xkKCkge1xuICAgIGNvbnN0IHRocmVzaG9sZCA9IHRoaXMucGFyYW1zLmdldCgndGhyZXNob2xkJyk7XG4gICAgY29uc3QgeWluQnVmZmVyID0gdGhpcy55aW5CdWZmZXI7XG4gICAgY29uc3QgaGFsZkJ1ZmZlclNpemUgPSB0aGlzLmhhbGZCdWZmZXJTaXplO1xuICAgIGxldCB0YXU7XG5cbiAgICBmb3IgKHRhdSA9IDE7IHRhdSA8IGhhbGZCdWZmZXJTaXplOyB0YXUrKykge1xuICAgICAgaWYgKHlpbkJ1ZmZlclt0YXVdIDwgdGhyZXNob2xkKSB7XG4gICAgICAgIC8vIGtlZXAgaW5jcmVhc2luZyB0YXUgaWYgbmV4dCB2YWx1ZSBpcyBiZXR0ZXJcbiAgICAgICAgd2hpbGUgKHRhdSArIDEgPCBoYWxmQnVmZmVyU2l6ZSAmJiB5aW5CdWZmZXJbdGF1ICsgMV0gPCB5aW5CdWZmZXJbdGF1XSlcbiAgICAgICAgICB0YXUgKz0gMTtcblxuICAgICAgICAvLyBiZXN0IHRhdSBmb3VuZCAsIHlpbkJ1ZmZlclt0YXVdIGNhbiBiZSBzZWVuIGFzIGFuIGVzdGltYXRpb24gb2ZcbiAgICAgICAgLy8gYXBlcmlvZGljaXR5IHRoZW46IHBlcmlvZGljaXR5ID0gMSAtIGFwZXJpb2RpY2l0eVxuICAgICAgICB0aGlzLnByb2JhYmlsaXR5ID0gMSAtIHlpbkJ1ZmZlclt0YXVdO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZXR1cm4gLTEgaWYgbm90IG1hdGNoIGZvdW5kXG4gICAgcmV0dXJuICh0YXUgPT09IGhhbGZCdWZmZXJTaXplKSA/IC0xIDogdGF1O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0ZXAgNSAtIEZpbmQgYSBiZXR0ZXIgZnJhY3Rpb25uYWwgYXBwcm94aW1hdGUgb2YgdGF1LlxuICAgKiB0aGlzIGNhbiBwcm9iYWJseSBiZSBzaW1wbGlmaWVkLi4uXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBfcGFyYWJvbGljSW50ZXJwb2xhdGlvbih0YXVFc3RpbWF0ZSkge1xuICAgIGNvbnN0IGhhbGZCdWZmZXJTaXplID0gdGhpcy5oYWxmQnVmZmVyU2l6ZTtcbiAgICBjb25zdCB5aW5CdWZmZXIgPSB0aGlzLnlpbkJ1ZmZlcjtcbiAgICBsZXQgYmV0dGVyVGF1O1xuICAgIC8vIEBub3RlIC0gdGF1RXN0aW1hdGUgY2Fubm90IGJlIHplcm8gYXMgdGhlIGxvb3Agc3RhcnQgYXQgMSBpbiBzdGVwIDRcbiAgICBjb25zdCB4MCA9IHRhdUVzdGltYXRlIC0gMTtcbiAgICBjb25zdCB4MiA9ICh0YXVFc3RpbWF0ZSA8IGhhbGZCdWZmZXJTaXplIC0gMSkgPyB0YXVFc3RpbWF0ZSArIDEgOiB0YXVFc3RpbWF0ZTtcblxuICAgIC8vIGlmIGB0YXVFc3RpbWF0ZWAgaXMgbGFzdCBpbmRleCwgd2UgY2FuJ3QgaW50ZXJwb2xhdGVcbiAgICBpZiAoeDIgPT09IHRhdUVzdGltYXRlKSB7XG4gICAgICAgIGJldHRlclRhdSA9IHRhdUVzdGltYXRlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzMCA9IHlpbkJ1ZmZlclt4MF07XG4gICAgICBjb25zdCBzMSA9IHlpbkJ1ZmZlclt0YXVFc3RpbWF0ZV07XG4gICAgICBjb25zdCBzMiA9IHlpbkJ1ZmZlclt4Ml07XG5cbiAgICAgIC8vIEBub3RlIC0gZG9uJ3QgZnVsbHkgdW5kZXJzdGFuZCB0aGlzIGZvcm11bGEgbmVpdGhlci4uLlxuICAgICAgYmV0dGVyVGF1ID0gdGF1RXN0aW1hdGUgKyAoczIgLSBzMCkgLyAoMiAqICgyICogczEgLSBzMiAtIHMwKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJldHRlclRhdTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2UgdGhlIGBZaW5gIG9wZXJhdG9yIGluIGBzdGFuZGFsb25lYCBtb2RlIChpLmUuIG91dHNpZGUgb2YgYSBncmFwaCkuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXl8RmxvYXQzMkFycmF5fSBpbnB1dCAtIFRoZSBzaWduYWwgZnJhZ21lbnQgdG8gcHJvY2Vzcy5cbiAgICogQHJldHVybiB7QXJyYXl9IC0gQXJyYXkgY29udGFpbmluZyB0aGUgYGZyZXF1ZW5jeWAsIGBlbmVyZ3lgLCBgcGVyaW9kaWNpdHlgXG4gICAqICBhbmQgYEFDMWBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICAgKlxuICAgKiBjb25zdCB5aW4gPSBuZXcgbGZvLm9wZXJhdG9yLllpbigpO1xuICAgKiB5aW4uaW5pdFN0cmVhbSh7XG4gICAqICAgZnJhbWVTaXplOiAyMDQ4LFxuICAgKiAgIGZyYW1lVHlwZTogJ3NpZ25hbCcsXG4gICAqICAgc291cmNlU2FtcGxlUmF0ZTogNDQxMDBcbiAgICogfSk7XG4gICAqXG4gICAqIGNvbnN0IHJlc3VsdHMgPSB5aW4uaW5wdXRTaWduYWwoc2lnbmFsKTtcbiAgICovXG4gIGlucHV0U2lnbmFsKGlucHV0KSB7XG4gICAgdGhpcy5waXRjaCA9IC0xO1xuICAgIHRoaXMucHJvYmFiaWxpdHkgPSAwO1xuXG4gICAgY29uc3QgYnVmZmVyID0gdGhpcy5idWZmZXI7XG4gICAgY29uc3QgaW5wdXRGcmFtZVNpemUgPSB0aGlzLmlucHV0RnJhbWVTaXplO1xuICAgIGNvbnN0IGRvd25TYW1wbGluZ0V4cCA9IHRoaXMuZG93blNhbXBsaW5nRXhwO1xuICAgIGNvbnN0IHNhbXBsZVJhdGUgPSB0aGlzLmRvd25TYW1wbGluZ1JhdGU7XG4gICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuZnJhbWUuZGF0YTtcbiAgICBsZXQgdGF1RXN0aW1hdGUgPSAtMTtcblxuICAgIC8vIHN1YnNhbXBsaW5nXG4gICAgdGhpcy5fZG93bnNhbXBsZShpbnB1dCwgaW5wdXRGcmFtZVNpemUsIGJ1ZmZlciwgZG93blNhbXBsaW5nRXhwKTtcbiAgICAvLyBzdGVwIDEsIDIsIDMgLSBub3JtYWxpemVkIHNxdWFyZWQgZGlmZmVyZW5jZSBvZiB0aGUgc2lnbmFsIHdpdGggYVxuICAgIC8vIHNoaWZ0ZWQgdmVyc2lvbiBvZiBpdHNlbGZcbiAgICB0aGlzLl9ub3JtYWxpemVkRGlmZmVyZW5jZShidWZmZXIpO1xuICAgIC8vIHN0ZXAgNCAtIGZpbmQgZmlyc3QgYmVzdCB0YXUgZXN0aW1hdGUgdGhhdCBpcyBvdmVyIHRoZSB0aHJlc2hvbGRcbiAgICB0YXVFc3RpbWF0ZSA9IHRoaXMuX2Fic29sdXRlVGhyZXNob2xkKCk7XG5cbiAgICBpZiAodGF1RXN0aW1hdGUgIT09IC0xKSB7XG4gICAgICAvLyBzdGVwIDUgLSBzbyBmYXIgdGF1IGlzIGFuIGludGVnZXIgc2hpZnQgb2YgdGhlIHNpZ25hbCwgY2hlY2sgaWZcbiAgICAgIC8vIHRoZXJlIGlzIGEgYmV0dGVyIGZyYWN0aW9ubmFsIHZhbHVlIGFyb3VuZFxuICAgICAgdGF1RXN0aW1hdGUgPSB0aGlzLl9wYXJhYm9saWNJbnRlcnBvbGF0aW9uKHRhdUVzdGltYXRlKTtcbiAgICAgIHRoaXMucGl0Y2ggPSBzYW1wbGVSYXRlIC8gdGF1RXN0aW1hdGU7XG4gICAgfVxuXG4gICAgb3V0RGF0YVswXSA9IHRoaXMucGl0Y2g7XG4gICAgb3V0RGF0YVsxXSA9IHRoaXMucHJvYmFiaWxpdHk7XG5cbiAgICByZXR1cm4gb3V0RGF0YTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7XG4gICAgdGhpcy5pbnB1dFNpZ25hbChmcmFtZS5kYXRhKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBZaW47XG4iLCJpbXBvcnQgQmlxdWFkIGZyb20gJy4vQmlxdWFkJztcbmltcG9ydCBDbGlwIGZyb20gJy4vQ2xpcCc7XG5pbXBvcnQgRGN0IGZyb20gJy4vRGN0JztcbmltcG9ydCBEZWx0YSBmcm9tICcuL0RlbHRhJztcbmltcG9ydCBGZnQgZnJvbSAnLi9GZnQnO1xuaW1wb3J0IE1hZ25pdHVkZSBmcm9tICcuL01hZ25pdHVkZSc7XG5pbXBvcnQgTWVhblN0ZGRldiBmcm9tICcuL01lYW5TdGRkZXYnO1xuaW1wb3J0IE1lbCBmcm9tICcuL01lbCc7XG5pbXBvcnQgTWVyZ2VyIGZyb20gJy4vTWVyZ2VyJztcbmltcG9ydCBNZmNjIGZyb20gJy4vTWZjYyc7XG5pbXBvcnQgTWluTWF4IGZyb20gJy4vTWluTWF4JztcbmltcG9ydCBNb3ZpbmdBdmVyYWdlIGZyb20gJy4vTW92aW5nQXZlcmFnZSc7XG5pbXBvcnQgTW92aW5nTWVkaWFuIGZyb20gJy4vTW92aW5nTWVkaWFuJztcbmltcG9ydCBPbk9mZiBmcm9tICcuL09uT2ZmJztcbmltcG9ydCBQb3dlciBmcm9tICcuL1Bvd2VyJztcbmltcG9ydCBSbXMgZnJvbSAnLi9SbXMnO1xuaW1wb3J0IE11bHRpcGxpZXIgZnJvbSAnLi9NdWx0aXBsaWVyJztcbmltcG9ydCBTY2FsZSBmcm9tICcuL1NjYWxlJztcbmltcG9ydCBTZWdtZW50ZXIgZnJvbSAnLi9TZWdtZW50ZXInO1xuaW1wb3J0IFNlbGVjdCBmcm9tICcuL1NlbGVjdCc7XG5pbXBvcnQgU2xpY2VyIGZyb20gJy4vU2xpY2VyJztcbmltcG9ydCBZaW4gZnJvbSAnLi9ZaW4nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIEJpcXVhZCxcbiAgQ2xpcCxcbiAgRGN0LFxuICBEZWx0YSxcbiAgRmZ0LFxuICBNYWduaXR1ZGUsXG4gIE1lYW5TdGRkZXYsXG4gIE1lbCxcbiAgTWVyZ2VyLFxuICBNZmNjLFxuICBNaW5NYXgsXG4gIE1vdmluZ0F2ZXJhZ2UsXG4gIE1vdmluZ01lZGlhbixcbiAgT25PZmYsXG4gIFBvd2VyLFxuICBSbXMsXG4gIE11bHRpcGxpZXIsXG4gIFNjYWxlLFxuICBTZWdtZW50ZXIsXG4gIFNlbGVjdCxcbiAgU2xpY2VyLFxuICBZaW4sXG59O1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIHByb2Nlc3NTdHJlYW1QYXJhbXM6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBwcm9jZXNzRnJhbWU6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBmaW5hbGl6ZVN0cmVhbToge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIGJyaWRnZSBiZXR3ZWVuIHRoZSBncmFwaCBhbmQgYXBwbGljYXRpb24gbG9naWMuIEhhbmRsZSBgcHVzaGBcbiAqIGFuZCBgcHVsbGAgcGFyYWRpZ21zLlxuICpcbiAqIFRoaXMgc2luayBjYW4gaGFuZGxlIGFueSB0eXBlIG9mIGlucHV0IChgc2lnbmFsYCwgYHZlY3RvcmAsIGBzY2FsYXJgKVxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLnNpbmtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIGRlZmF1bHQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLnByb2Nlc3NGcmFtZT1udWxsXSAtIENhbGxiYWNrIGV4ZWN1dGVkIG9uIGVhY2hcbiAqICBgcHJvY2Vzc0ZyYW1lYCBjYWxsLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuZmluYWxpemVTdHJlYW09bnVsbF0gLSBDYWxsYmFjayBleGVjdXRlZCBvbiBlYWNoXG4gKiAgYGZpbmFsaXplU3RyZWFtYCBjYWxsLlxuICpcbiAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJvY2Vzc0ZyYW1lfVxuICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNwcm9jZXNzU3RyZWFtUGFyYW1zfVxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NvbW1vbic7XG4gKlxuICogY29uc3QgZnJhbWVzID0gW1xuICogIHsgdGltZTogMCwgZGF0YTogWzAsIDFdIH0sXG4gKiAgeyB0aW1lOiAxLCBkYXRhOiBbMSwgMl0gfSxcbiAqIF07XG4gKlxuICogY29uc3QgZXZlbnRJbiA9IG5ldyBFdmVudEluKHtcbiAqICAgZnJhbWVUeXBlOiAndmVjdG9yJyxcbiAqICAgZnJhbWVTaXplOiAyLFxuICogICBmcmFtZVJhdGU6IDEsXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBicmlkZ2UgPSBuZXcgQnJpZGdlKHtcbiAqICAgcHJvY2Vzc0ZyYW1lOiAoZnJhbWUpID0+IGNvbnNvbGUubG9nKGZyYW1lKSxcbiAqIH0pO1xuICpcbiAqIGV2ZW50SW4uY29ubmVjdChicmlkZ2UpO1xuICogZXZlbnRJbi5zdGFydCgpO1xuICpcbiAqIC8vIGNhbGxiYWNrIGV4ZWN1dGVkIG9uIGVhY2ggZnJhbWVcbiAqIGV2ZW50SW4ucHJvY2Vzc0ZyYW1lKGZyYW1lWzBdKTtcbiAqID4geyB0aW1lOiAwLCBkYXRhOiBbMCwgMV0gfVxuICogZXZlbnRJbi5wcm9jZXNzRnJhbWUoZnJhbWVbMV0pO1xuICogPiB7IHRpbWU6IDEsIGRhdGE6IFsxLCAyXSB9XG4gKlxuICogLy8gcHVsbCBjdXJyZW50IGZyYW1lIHdoZW4gbmVlZGVkXG4gKiBjb25zb2xlLmxvZyhicmlkZ2UuZnJhbWUpO1xuICogPiB7IHRpbWU6IDEsIGRhdGE6IFsxLCAyXSB9XG4gKi9cbmNsYXNzIEJyaWRnZSBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuXG4gICAgY29uc3QgcHJvY2Vzc1N0cmVhbVBhcmFtc0NhbGxiYWNrID0gdGhpcy5wYXJhbXMuZ2V0KCdwcm9jZXNzU3RyZWFtUGFyYW1zJyk7XG5cbiAgICBpZiAocHJvY2Vzc1N0cmVhbVBhcmFtc0NhbGxiYWNrICE9PSBudWxsKVxuICAgICAgcHJvY2Vzc1N0cmVhbVBhcmFtc0NhbGxiYWNrKHRoaXMuc3RyZWFtUGFyYW1zKTtcblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgZmluYWxpemVTdHJlYW0oZW5kVGltZSkge1xuICAgIGNvbnN0IGZpbmFsaXplU3RyZWFtQ2FsbGJhY2sgPSB0aGlzLnBhcmFtcy5nZXQoJ2ZpbmFsaXplU3RyZWFtJyk7XG5cbiAgICBpZiAoZmluYWxpemVTdHJlYW1DYWxsYmFjayAhPT0gbnVsbClcbiAgICAgIGZpbmFsaXplU3RyZWFtQ2FsbGJhY2soZW5kVGltZSk7XG4gIH1cblxuICAvLyBwcm9jZXNzIGFueSB0eXBlXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2NhbGFyKCkge31cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NWZWN0b3IoKSB7fVxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbCgpIHt9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NGcmFtZShmcmFtZSkge1xuICAgIHRoaXMucHJlcGFyZUZyYW1lKCk7XG5cbiAgICBjb25zdCBwcm9jZXNzRnJhbWVDYWxsYmFjayA9IHRoaXMucGFyYW1zLmdldCgncHJvY2Vzc0ZyYW1lJyk7XG4gICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5mcmFtZTtcbiAgICBvdXRwdXQuZGF0YSA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplKTtcbiAgICAvLyBwdWxsIGludGVyZmFjZSAod2UgY29weSBkYXRhIHNpbmNlIHdlIGRvbid0IGtub3cgd2hhdCBjb3VsZFxuICAgIC8vIGJlIGRvbmUgb3V0c2lkZSB0aGUgZ3JhcGgpXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemU7IGkrKylcbiAgICAgIG91dHB1dC5kYXRhW2ldID0gZnJhbWUuZGF0YVtpXTtcblxuICAgIG91dHB1dC50aW1lID0gZnJhbWUudGltZTtcbiAgICBvdXRwdXQubWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcblxuICAgIC8vIGBwdXNoYCBpbnRlcmZhY2VcbiAgICBpZiAocHJvY2Vzc0ZyYW1lQ2FsbGJhY2sgIT09IG51bGwpXG4gICAgICBwcm9jZXNzRnJhbWVDYWxsYmFjayhvdXRwdXQpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJyaWRnZTtcbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIHNlcGFyYXRlQXJyYXlzOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBjYWxsYmFjazoge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbnVsbGFibGU6IHRydWUsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH0sXG4gIH0sXG59O1xuXG4vKipcbiAqIFJlY29yZCBpbnB1dCBmcmFtZXMgZnJvbSBhIGdyYXBoLiBUaGlzIHNpbmsgY2FuIGhhbmRsZSBgc2lnbmFsYCwgYHZlY3RvcmBcbiAqIG9yIGBzY2FsYXJgIGlucHV0cy5cbiAqXG4gKiBXaGVuIHRoZSByZWNvcmRpbmcgaXMgc3RvcHBlZCAoZWl0aGVyIGJ5IGNhbGxpbmcgYHN0b3BgIG9uIHRoZSBub2RlIG9yIHdoZW5cbiAqIHRoZSBzdHJlYW0gaXMgZmluYWxpemVkKSwgdGhlIGNhbGxiYWNrIGdpdmVuIGFzIHBhcmFtZXRlciBpcyBleGVjdXRlZCB3aXRoXG4gKiB0aGUgcmVjb3JkZXIgZGF0YSBhcyBhcmd1bWVudC5cbiAqXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnNlcGFyYXRlQXJyYXlzPWZhbHNlXSAtIEZvcm1hdCBvZiB0aGUgcmV0cmlldmVkXG4gKiAgdmFsdWVzOlxuICogIC0gd2hlbiBgZmFsc2VgLCBmb3JtYXQgaXMgW3sgdGltZSwgZGF0YSB9LCB7IHRpbWUsIGRhdGEgfSwgLi4uXVxuICogIC0gd2hlbiBgdHJ1ZWAsIGZvcm1hdCBpcyB7IHRpbWU6IFsuLi5dLCBkYXRhOiBbLi4uXSB9XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja10gLSBDYWxsYmFjayB0byBleGVjdXRlIHdoZW4gYSBuZXcgcmVjb3JkXG4gKiAgaXMgZW5kZWQuIFRoaXMgY2FuIGhhcHBlbiB3aGVuOlxuICogIC0gYHN0b3BgIGlzIGNhbGxlZCBvbiB0aGUgcmVjb3JkZXJcbiAqICAtIGBzdG9wYCBpcyBjYWxsZWQgb24gdGhlIHNvdXJjZS5cbiAqXG4gKiBAdG9kbyAtIEFkZCBhdXRvIHJlY29yZCBwYXJhbS5cbiAqXG4gKiBAbWVtYmVyb2YgbW9kdWxlOmNvbW1vbi5zaW5rXG4gKlxuICogQGV4YW1wbGVcbiAqIGltcG9ydCAqIGFzIGxmbyBmcm9tICd3YXZlcy1sZm8vY29tbW9uJztcbiAqXG4gKiBjb25zdCBldmVudEluID0gbmV3IGxmby5zb3VyY2UuRXZlbnRJbih7XG4gKiAgZnJhbWVUeXBlOiAndmVjdG9yJyxcbiAqICBmcmFtZVNpemU6IDIsXG4gKiAgZnJhbWVSYXRlOiAwLFxuICogfSk7XG4gKlxuICogY29uc3QgcmVjb3JkZXIgPSBuZXcgbGZvLnNpbmsuRGF0YVJlY29yZGVyKHtcbiAqICAgY2FsbGJhY2s6IChkYXRhKSA9PiBjb25zb2xlLmxvZyhkYXRhKSxcbiAqIH0pO1xuICpcbiAqIGV2ZW50SW4uY29ubmVjdChyZWNvcmRlcik7XG4gKiBldmVudEluLnN0YXJ0KCk7XG4gKiByZWNvcmRlci5zdGFydCgpO1xuICpcbiAqIGV2ZW50SW4ucHJvY2VzcygwLCBbMCwgMV0pO1xuICogZXZlbnRJbi5wcm9jZXNzKDEsIFsxLCAyXSk7XG4gKlxuICogcmVjb3JkZXIuc3RvcCgpO1xuICogPiBbeyB0aW1lOiAwLCBkYXRhOiBbMCwgMV0gfSwgeyB0aW1lOiAxLCBkYXRhOiBbMSwgMl0gfV07XG4gKi9cbmNsYXNzIERhdGFSZWNvcmRlciBleHRlbmRzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmUgaWYgdGhlIG5vZGUgaXMgY3VycmVudGx5IHJlY29yZGluZy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBuYW1lIGlzUmVjb3JkaW5nXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIG1vZHVsZTpzaW5rLlNpZ25hbFJlY29yZGVyXG4gICAgICovXG4gICAgdGhpcy5pc1JlY29yZGluZyA9IGZhbHNlO1xuICB9XG5cbiAgLyoqIEBwcml2YXRlICovXG4gIF9pbml0U3RvcmUoKSB7XG4gICAgY29uc3Qgc2VwYXJhdGVBcnJheXMgPSB0aGlzLnBhcmFtcy5nZXQoJ3NlcGFyYXRlQXJyYXlzJyk7XG5cbiAgICBpZiAoc2VwYXJhdGVBcnJheXMpXG4gICAgICB0aGlzLl9zdG9yZSA9IHsgdGltZTogW10sIGRhdGE6IFtdIH07XG4gICAgZWxzZVxuICAgICAgdGhpcy5fc3RvcmUgPSBbXTtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG4gICAgdGhpcy5faW5pdFN0b3JlKCk7XG4gICAgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydCByZWNvcmRpbmcuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjbGllbnQuc2luay5EYXRhUmVjb3JkZXIjc3RvcH1cbiAgICovXG4gIHN0YXJ0KCkge1xuICAgIHRoaXMuaXNSZWNvcmRpbmcgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3AgcmVjb3JkaW5nIGFuZCBleGVjdXRlIHRoZSBjYWxsYmFjayBkZWZpbmVkIGluIHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjbGllbnQuc2luay5EYXRhUmVjb3JkZXIjc3RhcnR9XG4gICAqL1xuICBzdG9wKCkge1xuICAgIGlmICh0aGlzLmlzUmVjb3JkaW5nKSB7XG4gICAgICB0aGlzLmlzUmVjb3JkaW5nID0gZmFsc2U7XG4gICAgICBjb25zdCBjYWxsYmFjayA9IHRoaXMucGFyYW1zLmdldCgnY2FsbGJhY2snKTtcblxuICAgICAgaWYgKGNhbGxiYWNrICE9PSBudWxsKVxuICAgICAgICBjYWxsYmFjayh0aGlzLl9zdG9yZSk7XG5cbiAgICAgIHRoaXMuX2luaXRTdG9yZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBmaW5hbGl6ZVN0cmVhbSgpIHtcbiAgICB0aGlzLnN0b3AoKTtcbiAgfVxuXG4gIC8vIGhhbmRsZSBhbnkgaW5wdXQgdHlwZXNcbiAgLyoqIEBwcml2YXRlICovXG4gIHByb2Nlc3NTY2FsYXIoZnJhbWUpIHt9XG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU2lnbmFsKGZyYW1lKSB7fVxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1ZlY3RvcihmcmFtZSkge31cblxuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICBpZiAodGhpcy5pc1JlY29yZGluZykge1xuICAgICAgdGhpcy5wcmVwYXJlRnJhbWUoZnJhbWUpO1xuXG4gICAgICBjb25zdCBzZXBhcmF0ZUFycmF5cyA9IHRoaXMucGFyYW1zLmdldCgnc2VwYXJhdGVBcnJheXMnKTtcbiAgICAgIGNvbnN0IGVudHJ5ID0ge1xuICAgICAgICB0aW1lOiBmcmFtZS50aW1lLFxuICAgICAgICBkYXRhOiBuZXcgRmxvYXQzMkFycmF5KGZyYW1lLmRhdGEpLFxuICAgICAgfTtcblxuICAgICAgaWYgKCFzZXBhcmF0ZUFycmF5cykge1xuICAgICAgICB0aGlzLl9zdG9yZS5wdXNoKGVudHJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3N0b3JlLnRpbWUucHVzaChlbnRyeS50aW1lKTtcbiAgICAgICAgdGhpcy5fc3RvcmUuZGF0YS5wdXNoKGVudHJ5LmRhdGEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBEYXRhUmVjb3JkZXI7XG5cbiIsImltcG9ydCBCYXNlTGZvIGZyb20gJy4uLy4uL2NvcmUvQmFzZUxmbyc7XG5cbmNvbnN0IGRlZmluaXRpb25zID0ge1xuICB0aW1lOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9XG4gIH0sXG4gIGRhdGE6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH1cbiAgfSxcbiAgbWV0YWRhdGE6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH1cbiAgfSxcbiAgc3RyZWFtUGFyYW1zOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9XG4gIH0sXG4gIGZyYW1lSW5kZXg6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gICAgbWV0YXM6IHsga2luZDogJ2R5bmFtaWMnIH1cbiAgfSxcbn1cblxuLyoqXG4gKiBMb2cgYGZyYW1lLnRpbWVgLCBgZnJhbWUuZGF0YWAsIGBmcmFtZS5tZXRhZGF0YWAgYW5kL29yXG4gKiBgc3RyZWFtQXR0cmlidXRlc2Agb2YgYW55IG5vZGUgaW4gdGhlIGNvbnNvbGUuXG4gKlxuICogVGhpcyBzaW5rIGNhbiBoYW5kbGUgYW55IHR5cGUgaWYgaW5wdXQgKGBzaWduYWxgLCBgdmVjdG9yYCwgYHNjYWxhcmApXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBwYXJhbWV0ZXJzIGRlZmF1bHQgdmFsdWVzLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy50aW1lPWZhbHNlXSAtIExvZyBpbmNvbW1pbmcgYGZyYW1lLnRpbWVgIGlmIGB0cnVlYC5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuZGF0YT1mYWxzZV0gLSBMb2cgaW5jb21taW5nIGBmcmFtZS5kYXRhYCBpZiBgdHJ1ZWAuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLm1ldGFkYXRhPWZhbHNlXSAtIExvZyBpbmNvbW1pbmcgYGZyYW1lLm1ldGFkYXRhYFxuICogIGlmIGB0cnVlYC5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuc3RyZWFtUGFyYW1zPWZhbHNlXSAtIExvZyBgc3RyZWFtUGFyYW1zYCBvZiB0aGVcbiAqICBwcmV2aW91cyBub2RlIHdoZW4gZ3JhcGggaXMgc3RhcnRlZC5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuZnJhbWVJbmRleD1mYWxzZV0gLSBMb2cgaW5kZXggb2YgdGhlIGluY29tbWluZ1xuICogIGBmcmFtZWAuXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb21tb24uc2lua1xuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NvbW1vbic7XG4gKlxuICogY29uc3QgbG9nZ2VyID0gbmV3IGxmby5zaW5rLkxvZ2dlcih7IGRhdGE6IHRydWUgfSk7XG4gKiB3aGF0ZXZlck9wZXJhdG9yLmNvbm5lY3QobG9nZ2VyKTtcbiAqL1xuY2xhc3MgTG9nZ2VyIGV4dGVuZHMgQmFzZUxmbyB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1N0cmVhbVBhcmFtcyhwcmV2U3RyZWFtUGFyYW1zKSB7XG4gICAgaWYgKHRoaXMucGFyYW1zLmdldCgnc3RyZWFtUGFyYW1zJykgPT09IHRydWUpXG4gICAgICBjb25zb2xlLmxvZyhwcmV2U3RyZWFtUGFyYW1zKTtcblxuICAgIHRoaXMuZnJhbWVJbmRleCA9IDA7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc0Z1bmN0aW9uKGZyYW1lKSB7XG4gICAgaWYgKHRoaXMucGFyYW1zLmdldCgnZnJhbWVJbmRleCcpID09PSB0cnVlKVxuICAgICAgY29uc29sZS5sb2codGhpcy5mcmFtZUluZGV4KyspO1xuXG4gICAgaWYgKHRoaXMucGFyYW1zLmdldCgndGltZScpID09PSB0cnVlKVxuICAgICAgY29uc29sZS5sb2coZnJhbWUudGltZSk7XG5cbiAgICBpZiAodGhpcy5wYXJhbXMuZ2V0KCdkYXRhJykgPT09IHRydWUpXG4gICAgICBjb25zb2xlLmxvZyhmcmFtZS5kYXRhKTtcblxuICAgIGlmICh0aGlzLnBhcmFtcy5nZXQoJ21ldGFkYXRhJykgPT09IHRydWUpXG4gICAgICBjb25zb2xlLmxvZyhmcmFtZS5tZXRhZGF0YSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9nZ2VyO1xuIiwiaW1wb3J0IEJhc2VMZm8gZnJvbSAnLi4vLi4vY29yZS9CYXNlTGZvJztcblxuY29uc3QgZGVmaW5pdGlvbnMgPSB7XG4gIGR1cmF0aW9uOiB7XG4gICAgdHlwZTogJ2Zsb2F0JyxcbiAgICBkZWZhdWx0OiAxMCxcbiAgICBtaW46IDAsXG4gICAgbWV0YXM6IHsga2luZDogJ3N0YXRpYycgfSxcbiAgfSxcbiAgY2FsbGJhY2s6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICAgIG1ldGFzOiB7IGtpbmQ6ICdkeW5hbWljJyB9LFxuICB9LFxuICBpZ25vcmVMZWFkaW5nWmVyb3M6IHtcbiAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICByZXRyaWV2ZUF1ZGlvQnVmZmVyOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBhdWRpb0NvbnRleHQ6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICB9LFxufTtcblxuLyoqXG4gKiBSZWNvcmQgYW4gYHNpZ25hbGAgaW5wdXQgc3RyZWFtIG9mIGFyYml0cmFyeSBkdXJhdGlvbiBhbmQgcmV0cmlldmUgaXRcbiAqIHdoZW4gZG9uZS5cbiAqXG4gKiBXaGVuIHJlY29yZGluZyBpcyBzdG9wcGVkIChlaXRoZXIgd2hlbiB0aGUgYHN0b3BgIG1ldGhvZCBpcyBjYWxsZWQsIHRoZVxuICogZGVmaW5lZCBkdXJhdGlvbiBoYXMgYmVlbiByZWNvcmRlZCwgb3IgdGhlIHNvdXJjZSBvZiB0aGUgZ3JhcGggZmluYWxpemVkXG4gKiB0aGUgc3RyZWFtKSwgdGhlIGNhbGxiYWNrIGdpdmVuIGFzIHBhcmFtZXRlciBpcyBleGVjdXRlZCAgd2l0aCB0aGVcbiAqIGBBdWRpb0J1ZmZlcmAgb3IgYEZsb2F0MzJBcnJheWAgY29udGFpbmluZyB0aGUgcmVjb3JkZWQgc2lnbmFsIGFzIGFyZ3VtZW50LlxuICpcbiAqIEB0b2RvIC0gYWRkIG9wdGlvbiB0byByZXR1cm4gb25seSB0aGUgRmxvYXQzMkFycmF5IGFuZCBub3QgYW4gYXVkaW8gYnVmZmVyXG4gKiAgKG5vZGUgY29tcGxpYW50KSBgcmV0cmlldmVBdWRpb0J1ZmZlcjogZmFsc2VgXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPdmVycmlkZSBkZWZhdWx0IHBhcmFtZXRlcnMuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZHVyYXRpb249MTBdIC0gTWF4aW11bSBkdXJhdGlvbiBvZiB0aGUgcmVjb3JkaW5nLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLmNhbGxiYWNrXSAtIENhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiBhIG5ldyByZWNvcmQgaXNcbiAqICBlbmRlZC4gVGhpcyBjYW4gaGFwcGVuOiBgc3RvcGAgaXMgY2FsbGVkIG9uIHRoZSByZWNvcmRlciwgYHN0b3BgIGlzIGNhbGxlZFxuICogIG9uIHRoZSBzb3VyY2Ugb3Igd2hlbiB0aGUgYnVmZmVyIGlzIGZ1bGwgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBgZHVyYXRpb25gLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmlnbm9yZUxlYWRpbmdaZXJvcz10cnVlXSAtIFN0YXJ0IHRoZSBlZmZlY3RpdmVcbiAqICByZWNvcmRpbmcgb24gdGhlIGZpcnN0IG5vbi16ZXJvIHZhbHVlLlxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5yZXRyaWV2ZUF1ZGlvQnVmZmVyPWZhbHNlXSAtIERlZmluZSBpZiBhbiBgQXVkaW9CdWZmZXJgXG4gKiAgc2hvdWxkIGJlIHJldHJpZXZlZCBvciBvbmx5IHRoZSByYXcgRmxvYXQzMkFycmF5IG9mIGRhdGEuXG4gKiAgKHdvcmtzIG9ubHkgaW4gYnJvd3NlcilcbiAqIEBwYXJhbSB7QXVkaW9Db250ZXh0fSBbb3B0aW9ucy5hdWRpb0NvbnRleHQ9bnVsbF0gLSBJZlxuICogIGByZXRyaWV2ZUF1ZGlvQnVmZmVyYCBpcyBzZXQgdG8gYHRydWVgLCBhdWRpbyBjb250ZXh0IHRvIGJlIHVzZWRcbiAqICBpbiBvcmRlciB0byBjcmVhdGUgdGhlIGZpbmFsIGF1ZGlvIGJ1ZmZlci5cbiAqICAod29ya3Mgb25seSBpbiBicm93c2VyKVxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLnNpbmtcbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0ICogYXMgbGZvIGZyb20gJ3dhdmVzLWxmby9jbGllbnQnO1xuICpcbiAqIGNvbnN0IGF1ZGlvQ29udGV4dCA9IG5ldyBBdWRpb0NvbnRleHQoKTtcbiAqXG4gKiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzXG4gKiAgIC5nZXRVc2VyTWVkaWEoeyBhdWRpbzogdHJ1ZSB9KVxuICogICAudGhlbihpbml0KVxuICogICAuY2F0Y2goKGVycikgPT4gY29uc29sZS5lcnJvcihlcnIuc3RhY2spKTtcbiAqXG4gKiBmdW5jdGlvbiBpbml0KHN0cmVhbSkge1xuICogICBjb25zdCBzb3VyY2UgPSBhdWRpb0NvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcbiAqXG4gKiAgIGNvbnN0IGF1ZGlvSW5Ob2RlID0gbmV3IGxmby5zb3VyY2UuQXVkaW9Jbk5vZGUoe1xuICogICAgIHNvdXJjZU5vZGU6IHNvdXJjZSxcbiAqICAgICBhdWRpb0NvbnRleHQ6IGF1ZGlvQ29udGV4dCxcbiAqICAgfSk7XG4gKlxuICogICBjb25zdCBzaWduYWxSZWNvcmRlciA9IG5ldyBsZm8uc2luay5TaWduYWxSZWNvcmRlcih7XG4gKiAgICAgZHVyYXRpb246IDYsXG4gKiAgICAgcmV0cmlldmVBdWRpb0J1ZmZlcjogdHJ1ZSxcbiAqICAgICBhdWRpb0NvbnRleHQ6IGF1ZGlvQ29udGV4dCxcbiAqICAgICBjYWxsYmFjazogKGJ1ZmZlcikgPT4ge1xuICogICAgICAgY29uc3QgYnVmZmVyU291cmNlID0gYXVkaW9Db250ZXh0LmNyZWF0ZUJ1ZmZlclNvdXJjZSgpO1xuICogICAgICAgYnVmZmVyU291cmNlLmJ1ZmZlciA9IGJ1ZmZlcjtcbiAqICAgICAgIGJ1ZmZlclNvdXJjZS5jb25uZWN0KGF1ZGlvQ29udGV4dC5kZXN0aW5hdGlvbik7XG4gKiAgICAgICBidWZmZXJTb3VyY2Uuc3RhcnQoKTtcbiAqICAgICB9XG4gKiAgIH0pO1xuICpcbiAqICAgYXVkaW9Jbk5vZGUuY29ubmVjdChzaWduYWxSZWNvcmRlcik7XG4gKiAgIGF1ZGlvSW5Ob2RlLnN0YXJ0KCk7XG4gKiAgIHNpZ25hbFJlY29yZGVyLnN0YXJ0KCk7XG4gKiB9KTtcbiAqL1xuY2xhc3MgU2lnbmFsUmVjb3JkZXIgZXh0ZW5kcyBCYXNlTGZvIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lIGlzIHRoZSBub2RlIGlzIGN1cnJlbnRseSByZWNvcmRpbmcgb3Igbm90LlxuICAgICAqXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQG5hbWUgaXNSZWNvcmRpbmdcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgbW9kdWxlOmNsaWVudC5zaW5rLlNpZ25hbFJlY29yZGVyXG4gICAgICovXG4gICAgdGhpcy5pc1JlY29yZGluZyA9IGZhbHNlO1xuXG4gICAgY29uc3QgcmV0cmlldmVBdWRpb0J1ZmZlciA9IHRoaXMucGFyYW1zLmdldCgncmV0cmlldmVBdWRpb0J1ZmZlcicpO1xuICAgIGNvbnN0IGF1ZGlvQ29udGV4dCA9IHRoaXMucGFyYW1zLmdldCgnYXVkaW9Db250ZXh0Jyk7XG4gICAgLy8gbmVlZGVkIHRvIHJldHJpZXZlIGFuIEF1ZGlvQnVmZmVyXG4gICAgaWYgKHJldHJpZXZlQXVkaW9CdWZmZXIgJiYgYXVkaW9Db250ZXh0ID09PSBudWxsKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcmFtZXRlciBcImF1ZGlvQ29udGV4dFwiOiBhbiBBdWRpb0NvbnRleHQgbXVzdCBiZSBwcm92aWRlZCB3aGVuIGByZXRyaWV2ZUF1ZGlvQnVmZmVyYCBpcyBzZXQgdG8gYHRydWVgJylcblxuICAgIHRoaXMuX2F1ZGlvQ29udGV4dCA9IGF1ZGlvQ29udGV4dDtcbiAgICB0aGlzLl9pZ25vcmVaZXJvcyA9IGZhbHNlO1xuICAgIHRoaXMuX2lzSW5maW5pdGVCdWZmZXIgPSBmYWxzZTtcbiAgICB0aGlzLl9zdGFjayA9IFtdO1xuICAgIHRoaXMuX2J1ZmZlciA9IG51bGw7XG4gICAgdGhpcy5fYnVmZmVyTGVuZ3RoID0gbnVsbDtcbiAgICB0aGlzLl9jdXJyZW50SW5kZXggPSBudWxsO1xuICB9XG5cbiAgX2luaXRCdWZmZXIoKSB7XG4gICAgdGhpcy5fYnVmZmVyID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLl9idWZmZXJMZW5ndGgpO1xuICAgIHRoaXMuX3N0YWNrLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5fY3VycmVudEluZGV4ID0gMDtcbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpIHtcbiAgICB0aGlzLnByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyk7XG5cbiAgICBjb25zdCBkdXJhdGlvbiA9IHRoaXMucGFyYW1zLmdldCgnZHVyYXRpb24nKTtcbiAgICBjb25zdCBzYW1wbGVSYXRlID0gdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlUmF0ZTtcblxuICAgIGlmIChpc0Zpbml0ZShkdXJhdGlvbikpIHtcbiAgICAgIHRoaXMuX2lzSW5maW5pdGVCdWZmZXIgPSBmYWxzZTtcbiAgICAgIHRoaXMuX2J1ZmZlckxlbmd0aCA9IHNhbXBsZVJhdGUgKiBkdXJhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5faXNJbmZpbml0ZUJ1ZmZlciA9IHRydWU7XG4gICAgICB0aGlzLl9idWZmZXJMZW5ndGggPSBzYW1wbGVSYXRlICogMTA7XG4gICAgfVxuXG4gICAgdGhpcy5faW5pdEJ1ZmZlcigpO1xuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQgcmVjb3JkaW5nLlxuICAgKi9cbiAgc3RhcnQoKSB7XG4gICAgdGhpcy5pc1JlY29yZGluZyA9IHRydWU7XG4gICAgdGhpcy5faWdub3JlWmVyb3MgPSB0aGlzLnBhcmFtcy5nZXQoJ2lnbm9yZUxlYWRpbmdaZXJvcycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3AgcmVjb3JkaW5nIGFuZCBleGVjdXRlIHRoZSBjYWxsYmFjayBkZWZpbmVkIGluIHBhcmFtZXRlcnMuXG4gICAqL1xuICBzdG9wKCkge1xuICAgIGlmICh0aGlzLmlzUmVjb3JkaW5nKSB7XG4gICAgICAvLyBpZ25vcmUgbmV4dCBpbmNvbW1pbmcgZnJhbWVcbiAgICAgIHRoaXMuaXNSZWNvcmRpbmcgPSBmYWxzZTtcblxuICAgICAgY29uc3QgcmV0cmlldmVBdWRpb0J1ZmZlciA9IHRoaXMucGFyYW1zLmdldCgncmV0cmlldmVBdWRpb0J1ZmZlcicpO1xuICAgICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLnBhcmFtcy5nZXQoJ2NhbGxiYWNrJyk7XG4gICAgICBjb25zdCBjdXJyZW50SW5kZXggPSB0aGlzLl9jdXJyZW50SW5kZXg7XG4gICAgICBjb25zdCBidWZmZXIgPSB0aGlzLl9idWZmZXI7XG4gICAgICBsZXQgb3V0cHV0O1xuXG4gICAgICBpZiAoIXRoaXMuX2lzSW5maW5pdGVCdWZmZXIpIHtcbiAgICAgICAgb3V0cHV0ID0gbmV3IEZsb2F0MzJBcnJheShjdXJyZW50SW5kZXgpO1xuICAgICAgICBvdXRwdXQuc2V0KGJ1ZmZlci5zdWJhcnJheSgwLCBjdXJyZW50SW5kZXgpLCAwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuX2J1ZmZlckxlbmd0aDtcbiAgICAgICAgY29uc3Qgc3RhY2sgPSB0aGlzLl9zdGFjaztcblxuICAgICAgICBvdXRwdXQgPSBuZXcgRmxvYXQzMkFycmF5KHN0YWNrLmxlbmd0aCAqIGJ1ZmZlckxlbmd0aCArIGN1cnJlbnRJbmRleCk7XG5cbiAgICAgICAgLy8gY29weSBhbGwgc3RhY2tlZCBidWZmZXJzXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjb25zdCBzdGFja2VkQnVmZmVyID0gc3RhY2tbaV07XG4gICAgICAgICAgb3V0cHV0LnNldChzdGFja2VkQnVmZmVyLCBidWZmZXJMZW5ndGggKiBpKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gY29weSBkYXRhIGNvbnRhaW5lZCBpbiBjdXJyZW50IGJ1ZmZlclxuICAgICAgICBvdXRwdXQuc2V0KGJ1ZmZlci5zdWJhcnJheSgwLCBjdXJyZW50SW5kZXgpLCBzdGFjay5sZW5ndGggKiBidWZmZXJMZW5ndGgpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmV0cmlldmVBdWRpb0J1ZmZlciAmJiB0aGlzLl9hdWRpb0NvbnRleHQpIHtcbiAgICAgICAgY29uc3QgbGVuZ3RoID0gb3V0cHV0Lmxlbmd0aDtcbiAgICAgICAgY29uc3Qgc2FtcGxlUmF0ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLnNvdXJjZVNhbXBsZVJhdGU7XG4gICAgICAgIGNvbnN0IGF1ZGlvQnVmZmVyID0gdGhpcy5fYXVkaW9Db250ZXh0LmNyZWF0ZUJ1ZmZlcigxLCBsZW5ndGgsIHNhbXBsZVJhdGUpO1xuICAgICAgICBjb25zdCBjaGFubmVsRGF0YSA9IGF1ZGlvQnVmZmVyLmdldENoYW5uZWxEYXRhKDApO1xuICAgICAgICBjaGFubmVsRGF0YS5zZXQob3V0cHV0LCAwKTtcblxuICAgICAgICBjYWxsYmFjayhhdWRpb0J1ZmZlcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjayhvdXRwdXQpO1xuICAgICAgfVxuXG4gICAgICAvLyByZWluaXQgYnVmZmVyLCBzdGFjaywgYW5kIGN1cnJlbnRJbmRleFxuICAgICAgdGhpcy5faW5pdEJ1ZmZlcigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBmaW5hbGl6ZVN0cmVhbShlbmRUaW1lKSB7XG4gICAgdGhpcy5zdG9wKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc1NpZ25hbChmcmFtZSkge1xuICAgIGlmICghdGhpcy5pc1JlY29yZGluZylcbiAgICAgIHJldHVybjtcblxuICAgIGxldCBibG9jayA9IG51bGw7XG4gICAgY29uc3QgaW5wdXQgPSBmcmFtZS5kYXRhO1xuICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuX2J1ZmZlckxlbmd0aDtcbiAgICBjb25zdCBidWZmZXIgPSB0aGlzLl9idWZmZXI7XG5cbiAgICBpZiAodGhpcy5faWdub3JlWmVyb3MgPT09IGZhbHNlKSB7XG4gICAgICBibG9jayA9IG5ldyBGbG9hdDMyQXJyYXkoaW5wdXQpO1xuICAgIH0gZWxzZSBpZiAoaW5wdXRbaW5wdXQubGVuZ3RoIC0gMV0gIT09IDApIHtcbiAgICAgIC8vIGZpbmQgZmlyc3QgaW5kZXggd2hlcmUgdmFsdWUgIT09IDBcbiAgICAgIGxldCBpO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspXG4gICAgICAgIGlmIChpbnB1dFtpXSAhPT0gMCkgYnJlYWs7XG5cbiAgICAgIC8vIGNvcHkgbm9uIHplcm8gc2VnbWVudFxuICAgICAgYmxvY2sgPSBuZXcgRmxvYXQzMkFycmF5KGlucHV0LnN1YmFycmF5KGkpKTtcbiAgICAgIC8vIGRvbid0IHJlcGVhdCB0aGlzIGxvZ2ljIG9uY2UgYSBub24temVybyB2YWx1ZSBoYXMgYmVlbiBmb3VuZFxuICAgICAgdGhpcy5faWdub3JlWmVyb3MgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoYmxvY2sgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IGF2YWlsYWJsZVNwYWNlID0gYnVmZmVyTGVuZ3RoIC0gdGhpcy5fY3VycmVudEluZGV4O1xuICAgICAgbGV0IGN1cnJlbnRCbG9jaztcblxuICAgICAgaWYgKGF2YWlsYWJsZVNwYWNlIDwgYmxvY2subGVuZ3RoKVxuICAgICAgICBjdXJyZW50QmxvY2sgPSBibG9jay5zdWJhcnJheSgwLCBhdmFpbGFibGVTcGFjZSk7XG4gICAgICBlbHNlXG4gICAgICAgIGN1cnJlbnRCbG9jayA9IGJsb2NrO1xuXG4gICAgICBidWZmZXIuc2V0KGN1cnJlbnRCbG9jaywgdGhpcy5fY3VycmVudEluZGV4KTtcbiAgICAgIHRoaXMuX2N1cnJlbnRJbmRleCArPSBjdXJyZW50QmxvY2subGVuZ3RoO1xuXG4gICAgICBpZiAodGhpcy5faXNJbmZpbml0ZUJ1ZmZlciAmJiB0aGlzLl9jdXJyZW50SW5kZXggPT09IGJ1ZmZlckxlbmd0aCkge1xuICAgICAgICB0aGlzLl9zdGFjay5wdXNoKGJ1ZmZlcik7XG5cbiAgICAgICAgY3VycmVudEJsb2NrID0gYmxvY2suc3ViYXJyYXkoYXZhaWxhYmxlU3BhY2UpO1xuICAgICAgICB0aGlzLl9idWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlckxlbmd0aCk7XG4gICAgICAgIHRoaXMuX2J1ZmZlci5zZXQoY3VycmVudEJsb2NrLCAwKTtcbiAgICAgICAgdGhpcy5fY3VycmVudEluZGV4ID0gY3VycmVudEJsb2NrLmxlbmd0aDtcbiAgICAgIH1cblxuICAgICAgLy8gIHN0b3AgaWYgdGhlIGJ1ZmZlciBpcyBmaW5pdGUgYW5kIGZ1bGxcbiAgICAgIGlmICghdGhpcy5faXNJbmZpbml0ZUJ1ZmZlciAmJiB0aGlzLl9jdXJyZW50SW5kZXggPT09IGJ1ZmZlckxlbmd0aClcbiAgICAgICAgdGhpcy5zdG9wKCk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNpZ25hbFJlY29yZGVyO1xuXG4iLCJpbXBvcnQgQmFzZUxmbyBmcm9tICcuLi8uLi9jb3JlL0Jhc2VMZm8nO1xuaW1wb3J0IFNvdXJjZU1peGluIGZyb20gJy4uLy4uL2NvcmUvU291cmNlTWl4aW4nO1xuXG4vLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE3NTc1NzkwL2Vudmlyb25tZW50LWRldGVjdGlvbi1ub2RlLWpzLW9yLWJyb3dzZXJcbmNvbnN0IGlzTm9kZSA9IG5ldyBGdW5jdGlvbigndHJ5IHsgcmV0dXJuIHRoaXMgPT09IGdsb2JhbDsgfSBjYXRjaChlKSB7IHJldHVybiBmYWxzZSB9Jyk7XG5cbi8qKlxuICogQ3JlYXRlIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRpbWUgaW4gc2Vjb25kcyBhY2NvcmRpbmcgdG8gdGhlIGN1cnJlbnRcbiAqIGVudmlyb25uZW1lbnQgKG5vZGUgb3IgYnJvd3NlcikuXG4gKiBJZiBydW5uaW5nIGluIG5vZGUgdGhlIHRpbWUgcmVseSBvbiBgcHJvY2Vzcy5ocnRpbWVgLCB3aGlsZSBpZiBpbiB0aGUgYnJvd3NlclxuICogaXQgaXMgcHJvdmlkZWQgYnkgdGhlIGBjdXJyZW50VGltZWAgb2YgYW4gYEF1ZGlvQ29udGV4dGAsIHRoaXMgY29udGV4dCBjYW5cbiAqIG9wdGlvbm5hbHkgYmUgcHJvdmlkZWQgdG8ga2VlcCB0aW1lIGNvbnNpc3RlbmN5IGJldHdlZW4gc2V2ZXJhbCBgRXZlbnRJbmBcbiAqIG5vZGVzLlxuICpcbiAqIEBwYXJhbSB7QXVkaW9Db250ZXh0fSBbYXVkaW9Db250ZXh0PW51bGxdIC0gT3B0aW9ubmFsIGF1ZGlvIGNvbnRleHQuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGdldFRpbWVGdW5jdGlvbihhdWRpb0NvbnRleHQgPSBudWxsKSB7XG4gIGlmIChpc05vZGUoKSkge1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjb25zdCB0ID0gcHJvY2Vzcy5ocnRpbWUoKTtcbiAgICAgIHJldHVybiB0WzBdICsgdFsxXSAqIDFlLTk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiAoKSA9PiBwZXJmb3JtYW5jZS5ub3coKSAvIDEwMDA7XG4gIH1cbn1cblxuXG5jb25zdCBkZWZpbml0aW9ucyA9IHtcbiAgYWJzb2x1dGVUaW1lOiB7XG4gICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBhdWRpb0NvbnRleHQ6IHtcbiAgICB0eXBlOiAnYW55JyxcbiAgICBkZWZhdWx0OiBudWxsLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICAgIG51bGxhYmxlOiB0cnVlLFxuICB9LFxuICBmcmFtZVR5cGU6IHtcbiAgICB0eXBlOiAnZW51bScsXG4gICAgbGlzdDogWydzaWduYWwnLCAndmVjdG9yJywgJ3NjYWxhciddLFxuICAgIGRlZmF1bHQ6ICdzaWduYWwnLFxuICAgIGNvbnN0YW50OiB0cnVlLFxuICB9LFxuICBmcmFtZVNpemU6IHtcbiAgICB0eXBlOiAnaW50ZWdlcicsXG4gICAgZGVmYXVsdDogMSxcbiAgICBtaW46IDEsXG4gICAgbWF4OiArSW5maW5pdHksIC8vIG5vdCByZWNvbW1lbmRlZC4uLlxuICAgIG1ldGFzOiB7IGtpbmQ6ICdzdGF0aWMnIH0sXG4gIH0sXG4gIHNhbXBsZVJhdGU6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbWluOiAwLFxuICAgIG1heDogK0luZmluaXR5LCAvLyBzYW1lIGhlcmVcbiAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBmcmFtZVJhdGU6IHtcbiAgICB0eXBlOiAnZmxvYXQnLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgbWluOiAwLFxuICAgIG1heDogK0luZmluaXR5LCAvLyBzYW1lIGhlcmVcbiAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICBtZXRhczogeyBraW5kOiAnc3RhdGljJyB9LFxuICB9LFxuICBkZXNjcmlwdGlvbjoge1xuICAgIHR5cGU6ICdhbnknLFxuICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgY29uc3RhbnQ6IHRydWUsXG4gIH1cbn07XG5cbi8qKlxuICogVGhlIGBFdmVudEluYCBvcGVyYXRvciBhbGxvd3MgdG8gbWFudWFsbHkgY3JlYXRlIGEgc3RyZWFtIG9mIGRhdGEgb3IgdG8gZmVlZFxuICogYSBzdHJlYW0gZnJvbSBhbm90aGVyIHNvdXJjZSAoZS5nLiBzZW5zb3JzKSBpbnRvIGEgcHJvY2Vzc2luZyBncmFwaC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE92ZXJyaWRlIHBhcmFtZXRlcnMnIGRlZmF1bHQgdmFsdWVzLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmZyYW1lVHlwZT0nc2lnbmFsJ10gLSBUeXBlIG9mIHRoZSBpbnB1dCAtIGFsbG93ZWRcbiAqIHZhbHVlczogYHNpZ25hbGAsICBgdmVjdG9yYCBvciBgc2NhbGFyYC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5mcmFtZVNpemU9MV0gLSBTaXplIG9mIHRoZSBvdXRwdXQgZnJhbWUuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuc2FtcGxlUmF0ZT1udWxsXSAtIFNhbXBsZSByYXRlIG9mIHRoZSBzb3VyY2Ugc3RyZWFtLFxuICogIGlmIG9mIHR5cGUgYHNpZ25hbGAuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMuZnJhbWVSYXRlPW51bGxdIC0gUmF0ZSBvZiB0aGUgc291cmNlIHN0cmVhbSwgaWYgb2ZcbiAqICB0eXBlIGB2ZWN0b3JgLlxuICogQHBhcmFtIHtBcnJheXxTdHJpbmd9IFtvcHRpb25zLmRlc2NyaXB0aW9uXSAtIE9wdGlvbm5hbCBkZXNjcmlwdGlvblxuICogIGRlc2NyaWJpbmcgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIG91dHB1dCBmcmFtZVxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5hYnNvbHV0ZVRpbWU9ZmFsc2VdIC0gRGVmaW5lIGlmIHRpbWUgc2hvdWxkIGJlIHVzZWRcbiAqICBhcyBmb3J3YXJkZWQgYXMgZ2l2ZW4gaW4gdGhlIHByb2Nlc3MgbWV0aG9kLCBvciByZWxhdGl2ZWx5IHRvIHRoZSB0aW1lIG9mXG4gKiAgdGhlIGZpcnN0IGBwcm9jZXNzYCBjYWxsIGFmdGVyIHN0YXJ0LlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLnNvdXJjZVxuICpcbiAqIEB0b2RvIC0gQWRkIGEgYGxvZ2ljYWxUaW1lYCBwYXJhbWV0ZXIgdG8gdGFnIGZyYW1lIGFjY29yZGluZyB0byBmcmFtZSByYXRlLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG4gKlxuICogY29uc3QgZXZlbnRJbiA9IG5ldyBsZm8uc291cmNlLkV2ZW50SW4oe1xuICogICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxuICogICBmcmFtZVNpemU6IDMsXG4gKiAgIGZyYW1lUmF0ZTogMSAvIDUwLFxuICogICBkZXNjcmlwdGlvbjogWydhbHBoYScsICdiZXRhJywgJ2dhbW1hJ10sXG4gKiB9KTtcbiAqXG4gKiAvLyBjb25uZWN0IHNvdXJjZSB0byBvcGVyYXRvcnMgYW5kIHNpbmsocylcbiAqXG4gKiAvLyBpbml0aWFsaXplIGFuZCBzdGFydCB0aGUgZ3JhcGhcbiAqIGV2ZW50SW4uc3RhcnQoKTtcbiAqXG4gKiAvLyBmZWVkIGBkZXZpY2VvcmllbnRhdGlvbmAgZGF0YSBpbnRvIHRoZSBncmFwaFxuICogd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZW9yaWVudGF0aW9uJywgKGUpID0+IHtcbiAqICAgY29uc3QgZnJhbWUgPSB7XG4gKiAgICAgdGltZTogd2luZG93LnBlcmZvcm1hY2Uubm93KCkgLyAxMDAwLFxuICogICAgIGRhdGE6IFtlLmFscGhhLCBlLmJldGEsIGUuZ2FtbWFdLFxuICogICB9O1xuICpcbiAqICAgZXZlbnRJbi5wcm9jZXNzRnJhbWUoZnJhbWUpO1xuICogfSwgZmFsc2UpO1xuICovXG5jbGFzcyBFdmVudEluIGV4dGVuZHMgU291cmNlTWl4aW4oQmFzZUxmbykge1xuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihkZWZpbml0aW9ucywgb3B0aW9ucyk7XG5cbiAgICBjb25zdCBhdWRpb0NvbnRleHQgPSB0aGlzLnBhcmFtcy5nZXQoJ2F1ZGlvQ29udGV4dCcpO1xuICAgIHRoaXMuX2dldFRpbWUgPSBnZXRUaW1lRnVuY3Rpb24oYXVkaW9Db250ZXh0KTtcbiAgICB0aGlzLl9zdGFydFRpbWUgPSBudWxsO1xuICAgIHRoaXMuX3N5c3RlbVRpbWUgPSBudWxsO1xuICAgIHRoaXMuX2Fic29sdXRlVGltZSA9IHRoaXMucGFyYW1zLmdldCgnYWJzb2x1dGVUaW1lJyk7XG4gIH1cblxuICAvKipcbiAgICogUHJvcGFnYXRlIHRoZSBgc3RyZWFtUGFyYW1zYCBpbiB0aGUgZ3JhcGggYW5kIGFsbG93IHRvIHB1c2ggZnJhbWVzIGludG9cbiAgICogdGhlIGdyYXBoLiBBbnkgY2FsbCB0byBgcHJvY2Vzc2Agb3IgYHByb2Nlc3NGcmFtZWAgYmVmb3JlIGBzdGFydGAgd2lsbCBiZVxuICAgKiBpZ25vcmVkLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb2Nlc3NTdHJlYW1QYXJhbXN9XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcmVzZXRTdHJlYW19XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb21tb24uc291cmNlLkV2ZW50SW4jc3RvcH1cbiAgICovXG4gIHN0YXJ0KHN0YXJ0VGltZSA9IG51bGwpIHtcbiAgICBpZiAodGhpcy5pbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICAgIGlmICh0aGlzLmluaXRQcm9taXNlID09PSBudWxsKSAvLyBpbml0IGhhcyBub3QgeWV0IGJlZW4gY2FsbGVkXG4gICAgICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXQoKTtcblxuICAgICAgcmV0dXJuIHRoaXMuaW5pdFByb21pc2UudGhlbigoKSA9PiB0aGlzLnN0YXJ0KHN0YXJ0VGltZSkpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXJ0VGltZSA9IHN0YXJ0VGltZTtcbiAgICB0aGlzLl9zeXN0ZW1UaW1lID0gbnVsbDsgLy8gdmFsdWUgc2V0IGluIHRoZSBmaXJzdCBgcHJvY2Vzc2AgY2FsbFxuXG4gICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5hbGl6ZSB0aGUgc3RyZWFtIGFuZCBzdG9wIHRoZSB3aG9sZSBncmFwaC4gQW55IGNhbGwgdG8gYHByb2Nlc3NgIG9yXG4gICAqIGBwcm9jZXNzRnJhbWVgIGFmdGVyIGBzdG9wYCB3aWxsIGJlIGlnbm9yZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jZmluYWxpemVTdHJlYW19XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb21tb24uc291cmNlLkV2ZW50SW4jc3RhcnR9XG4gICAqL1xuICBzdG9wKCkge1xuICAgIGlmICh0aGlzLnN0YXJ0ZWQgJiYgdGhpcy5fc3RhcnRUaW1lICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBjdXJyZW50VGltZSA9IHRoaXMuX2dldFRpbWUoKTtcbiAgICAgIGNvbnN0IGVuZFRpbWUgPSB0aGlzLmZyYW1lLnRpbWUgKyAoY3VycmVudFRpbWUgLSB0aGlzLl9zeXN0ZW1UaW1lKTtcblxuICAgICAgdGhpcy5maW5hbGl6ZVN0cmVhbShlbmRUaW1lKTtcbiAgICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAcHJpdmF0ZSAqL1xuICBwcm9jZXNzU3RyZWFtUGFyYW1zKCkge1xuICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMucGFyYW1zLmdldCgnZnJhbWVTaXplJyk7XG4gICAgY29uc3QgZnJhbWVUeXBlID0gdGhpcy5wYXJhbXMuZ2V0KCdmcmFtZVR5cGUnKTtcbiAgICBjb25zdCBzYW1wbGVSYXRlID0gdGhpcy5wYXJhbXMuZ2V0KCdzYW1wbGVSYXRlJyk7XG4gICAgY29uc3QgZnJhbWVSYXRlID0gdGhpcy5wYXJhbXMuZ2V0KCdmcmFtZVJhdGUnKTtcbiAgICBjb25zdCBkZXNjcmlwdGlvbiA9IHRoaXMucGFyYW1zLmdldCgnZGVzY3JpcHRpb24nKTtcblxuICAgIC8vIGluaXQgb3BlcmF0b3IncyBzdHJlYW0gcGFyYW1zXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVTaXplID0gZnJhbWVUeXBlID09PSAnc2NhbGFyJyA/IDEgOiBmcmFtZVNpemU7XG4gICAgdGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlID0gZnJhbWVUeXBlO1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb247XG5cbiAgICBpZiAoZnJhbWVUeXBlID09PSAnc2lnbmFsJykge1xuICAgICAgaWYgKHNhbXBsZVJhdGUgPT09IG51bGwpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5kZWZpbmVkIFwic2FtcGxlUmF0ZVwiIGZvciBcInNpZ25hbFwiIHN0cmVhbScpO1xuXG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlID0gc2FtcGxlUmF0ZTtcbiAgICAgIHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lUmF0ZSA9IHNhbXBsZVJhdGUgLyBmcmFtZVNpemU7XG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVDb3VudCA9IGZyYW1lU2l6ZTtcblxuICAgIH0gZWxzZSBpZiAoZnJhbWVUeXBlID09PSAndmVjdG9yJyB8fCBmcmFtZVR5cGUgPT09ICdzY2FsYXInKSB7XG4gICAgICBpZiAoZnJhbWVSYXRlID09PSBudWxsKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZGVmaW5lZCBcImZyYW1lUmF0ZVwiIGZvciBcIiR7ZnJhbWVUeXBlfVwiIHN0cmVhbWApO1xuXG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVJhdGUgPSBmcmFtZVJhdGU7XG4gICAgICB0aGlzLnN0cmVhbVBhcmFtcy5zb3VyY2VTYW1wbGVSYXRlID0gZnJhbWVSYXRlO1xuICAgICAgdGhpcy5zdHJlYW1QYXJhbXMuc291cmNlU2FtcGxlQ291bnQgPSAxO1xuICAgIH1cblxuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKiogQHByaXZhdGUgKi9cbiAgcHJvY2Vzc0Z1bmN0aW9uKGZyYW1lKSB7XG4gICAgY29uc3QgY3VycmVudFRpbWUgPSB0aGlzLl9nZXRUaW1lKCk7XG4gICAgY29uc3QgaW5EYXRhID0gZnJhbWUuZGF0YS5sZW5ndGggPyBmcmFtZS5kYXRhIDogW2ZyYW1lLmRhdGFdO1xuICAgIGNvbnN0IG91dERhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG4gICAgLy8gaWYgbm8gdGltZSBwcm92aWRlZCwgdXNlIHN5c3RlbSB0aW1lXG4gICAgbGV0IHRpbWUgPSBOdW1iZXIuaXNGaW5pdGUoZnJhbWUudGltZSkgPyBmcmFtZS50aW1lIDogY3VycmVudFRpbWU7XG5cbiAgICBpZiAodGhpcy5fc3RhcnRUaW1lID09PSBudWxsKVxuICAgICAgdGhpcy5fc3RhcnRUaW1lID0gdGltZTtcblxuICAgIGlmICh0aGlzLl9hYnNvbHV0ZVRpbWUgPT09IGZhbHNlKVxuICAgICAgdGltZSA9IHRpbWUgLSB0aGlzLl9zdGFydFRpbWU7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTsgaSA8IGw7IGkrKylcbiAgICAgIG91dERhdGFbaV0gPSBpbkRhdGFbaV07XG5cbiAgICB0aGlzLmZyYW1lLnRpbWUgPSB0aW1lO1xuICAgIHRoaXMuZnJhbWUubWV0YWRhdGEgPSBmcmFtZS5tZXRhZGF0YTtcbiAgICAvLyBzdG9yZSBjdXJyZW50IHRpbWUgdG8gY29tcHV0ZSBgZW5kVGltZWAgb24gc3RvcFxuICAgIHRoaXMuX3N5c3RlbVRpbWUgPSBjdXJyZW50VGltZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbHRlcm5hdGl2ZSBpbnRlcmZhY2UgdG8gcHJvcGFnYXRlIGEgZnJhbWUgaW4gdGhlIGdyYXBoLiBQYWNrIGB0aW1lYCxcbiAgICogYGRhdGFgIGFuZCBgbWV0YWRhdGFgIGluIGEgZnJhbWUgb2JqZWN0LlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gdGltZSAtIEZyYW1lIHRpbWUuXG4gICAqIEBwYXJhbSB7RmxvYXQzMkFycmF5fEFycmF5fSBkYXRhIC0gRnJhbWUgZGF0YS5cbiAgICogQHBhcmFtIHtPYmplY3R9IG1ldGFkYXRhIC0gT3B0aW9ubmFsIGZyYW1lIG1ldGFkYXRhLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBldmVudEluLnByb2Nlc3MoMSwgWzAsIDEsIDJdKTtcbiAgICogLy8gaXMgZXF1aXZhbGVudCB0b1xuICAgKiBldmVudEluLnByb2Nlc3NGcmFtZSh7IHRpbWU6IDEsIGRhdGE6IFswLCAxLCAyXSB9KTtcbiAgICovXG4gIHByb2Nlc3ModGltZSwgZGF0YSwgbWV0YWRhdGEgPSBudWxsKSB7XG4gICAgdGhpcy5wcm9jZXNzRnJhbWUoeyB0aW1lLCBkYXRhLCBtZXRhZGF0YSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9wYWdhdGUgYSBmcmFtZSBvYmplY3QgaW4gdGhlIGdyYXBoLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZnJhbWUgLSBJbnB1dCBmcmFtZS5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGZyYW1lLnRpbWUgLSBGcmFtZSB0aW1lLlxuICAgKiBAcGFyYW0ge0Zsb2F0MzJBcnJheXxBcnJheX0gZnJhbWUuZGF0YSAtIEZyYW1lIGRhdGEuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbZnJhbWUubWV0YWRhdGE9dW5kZWZpbmVkXSAtIE9wdGlvbm5hbCBmcmFtZSBtZXRhZGF0YS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogZXZlbnRJbi5wcm9jZXNzRnJhbWUoeyB0aW1lOiAxLCBkYXRhOiBbMCwgMSwgMl0gfSk7XG4gICAqL1xuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICBpZiAoIXRoaXMuc3RhcnRlZCkgcmV0dXJuO1xuXG4gICAgdGhpcy5wcmVwYXJlRnJhbWUoKTtcbiAgICB0aGlzLnByb2Nlc3NGdW5jdGlvbihmcmFtZSk7XG4gICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEV2ZW50SW47XG4iLCJcbi8vIHNob3J0Y3V0cyAvIGhlbHBlcnNcbmNvbnN0IFBJICAgPSBNYXRoLlBJO1xuY29uc3QgY29zICA9IE1hdGguY29zO1xuY29uc3Qgc2luICA9IE1hdGguc2luO1xuY29uc3Qgc3FydCA9IE1hdGguc3FydDtcblxuLy8gd2luZG93IGNyZWF0aW9uIGZ1bmN0aW9uc1xuZnVuY3Rpb24gaW5pdEhhbm5XaW5kb3coYnVmZmVyLCBzaXplLCBub3JtQ29lZnMpIHtcbiAgbGV0IGxpblN1bSA9IDA7XG4gIGxldCBwb3dTdW0gPSAwO1xuICBjb25zdCBzdGVwID0gMiAqIFBJIC8gc2l6ZTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgIGNvbnN0IHBoaSA9IGkgKiBzdGVwO1xuICAgIGNvbnN0IHZhbHVlID0gMC41IC0gMC41ICogY29zKHBoaSk7XG5cbiAgICBidWZmZXJbaV0gPSB2YWx1ZTtcblxuICAgIGxpblN1bSArPSB2YWx1ZTtcbiAgICBwb3dTdW0gKz0gdmFsdWUgKiB2YWx1ZTtcbiAgfVxuXG4gIG5vcm1Db2Vmcy5saW5lYXIgPSBzaXplIC8gbGluU3VtO1xuICBub3JtQ29lZnMucG93ZXIgPSBzcXJ0KHNpemUgLyBwb3dTdW0pO1xufVxuXG5mdW5jdGlvbiBpbml0SGFtbWluZ1dpbmRvdyhidWZmZXIsIHNpemUsIG5vcm1Db2Vmcykge1xuICBsZXQgbGluU3VtID0gMDtcbiAgbGV0IHBvd1N1bSA9IDA7XG4gIGNvbnN0IHN0ZXAgPSAyICogUEkgLyBzaXplO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgY29uc3QgcGhpID0gaSAqIHN0ZXA7XG4gICAgY29uc3QgdmFsdWUgPSAwLjU0IC0gMC40NiAqIGNvcyhwaGkpO1xuXG4gICAgYnVmZmVyW2ldID0gdmFsdWU7XG5cbiAgICBsaW5TdW0gKz0gdmFsdWU7XG4gICAgcG93U3VtICs9IHZhbHVlICogdmFsdWU7XG4gIH1cblxuICBub3JtQ29lZnMubGluZWFyID0gc2l6ZSAvIGxpblN1bTtcbiAgbm9ybUNvZWZzLnBvd2VyID0gc3FydChzaXplIC8gcG93U3VtKTtcbn1cblxuZnVuY3Rpb24gaW5pdEJsYWNrbWFuV2luZG93KGJ1ZmZlciwgc2l6ZSwgbm9ybUNvZWZzKSB7XG4gIGxldCBsaW5TdW0gPSAwO1xuICBsZXQgcG93U3VtID0gMDtcbiAgY29uc3Qgc3RlcCA9IDIgKiBQSSAvIHNpemU7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICBjb25zdCBwaGkgPSBpICogc3RlcDtcbiAgICBjb25zdCB2YWx1ZSA9IDAuNDIgLSAwLjUgKiBjb3MocGhpKSArIDAuMDggKiBjb3MoMiAqIHBoaSk7XG5cbiAgICBidWZmZXJbaV0gPSB2YWx1ZTtcblxuICAgIGxpblN1bSArPSB2YWx1ZTtcbiAgICBwb3dTdW0gKz0gdmFsdWUgKiB2YWx1ZTtcbiAgfVxuXG4gIG5vcm1Db2Vmcy5saW5lYXIgPSBzaXplIC8gbGluU3VtO1xuICBub3JtQ29lZnMucG93ZXIgPSBzcXJ0KHNpemUgLyBwb3dTdW0pO1xufVxuXG5mdW5jdGlvbiBpbml0QmxhY2ttYW5IYXJyaXNXaW5kb3coYnVmZmVyLCBzaXplLCBub3JtQ29lZnMpIHtcbiAgbGV0IGxpblN1bSA9IDA7XG4gIGxldCBwb3dTdW0gPSAwO1xuICBjb25zdCBhMCA9IDAuMzU4NzU7XG4gIGNvbnN0IGExID0gMC40ODgyOTtcbiAgY29uc3QgYTIgPSAwLjE0MTI4O1xuICBjb25zdCBhMyA9IDAuMDExNjg7XG4gIGNvbnN0IHN0ZXAgPSAyICogUEkgLyBzaXplO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgY29uc3QgcGhpID0gaSAqIHN0ZXA7XG4gICAgY29uc3QgdmFsdWUgPSBhMCAtIGExICogY29zKHBoaSkgKyBhMiAqIGNvcygyICogcGhpKTsgLSBhMyAqIGNvcygzICogcGhpKTtcblxuICAgIGJ1ZmZlcltpXSA9IHZhbHVlO1xuXG4gICAgbGluU3VtICs9IHZhbHVlO1xuICAgIHBvd1N1bSArPSB2YWx1ZSAqIHZhbHVlO1xuICB9XG5cbiAgbm9ybUNvZWZzLmxpbmVhciA9IHNpemUgLyBsaW5TdW07XG4gIG5vcm1Db2Vmcy5wb3dlciA9IHNxcnQoc2l6ZSAvIHBvd1N1bSk7XG59XG5cbmZ1bmN0aW9uIGluaXRTaW5lV2luZG93KGJ1ZmZlciwgc2l6ZSwgbm9ybUNvZWZzKSB7XG4gIGxldCBsaW5TdW0gPSAwO1xuICBsZXQgcG93U3VtID0gMDtcbiAgY29uc3Qgc3RlcCA9IFBJIC8gc2l6ZTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKykge1xuICAgIGNvbnN0IHBoaSA9IGkgKiBzdGVwO1xuICAgIGNvbnN0IHZhbHVlID0gc2luKHBoaSk7XG5cbiAgICBidWZmZXJbaV0gPSB2YWx1ZTtcblxuICAgIGxpblN1bSArPSB2YWx1ZTtcbiAgICBwb3dTdW0gKz0gdmFsdWUgKiB2YWx1ZTtcbiAgfVxuXG4gIG5vcm1Db2Vmcy5saW5lYXIgPSBzaXplIC8gbGluU3VtO1xuICBub3JtQ29lZnMucG93ZXIgPSBzcXJ0KHNpemUgLyBwb3dTdW0pO1xufVxuXG5mdW5jdGlvbiBpbml0UmVjdGFuZ2xlV2luZG93KGJ1ZmZlciwgc2l6ZSwgbm9ybUNvZWZzKSB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKVxuICAgIGJ1ZmZlcltpXSA9IDE7XG5cbiAgLy8gQHRvZG8gLSBjaGVjayBpZiB0aGVzZSBhcmUgcHJvcGVyIHZhbHVlc1xuICBub3JtQ29lZnMubGluZWFyID0gMTtcbiAgbm9ybUNvZWZzLnBvd2VyID0gMTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBidWZmZXIgd2l0aCB3aW5kb3cgc2lnbmFsLlxuICpcbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29tbW9uLnV0aWxzXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBOYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge0Zsb2F0MzJBcnJheX0gYnVmZmVyIC0gQnVmZmVyIHRvIGJlIHBvcHVsYXRlZCB3aXRoIHRoZSB3aW5kb3cgc2lnbmFsLlxuICogQHBhcmFtIHtOdW1iZXJ9IHNpemUgLSBTaXplIG9mIHRoZSBidWZmZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gbm9ybUNvZWZzIC0gT2JqZWN0IHRvIGJlIHBvcHVsYXRlZCB3aXRoIHRoZSBub3JtYWlsemF0aW9uXG4gKiAgY29lZmZpY2llbnRzLlxuICovXG5mdW5jdGlvbiBpbml0V2luZG93KG5hbWUsIGJ1ZmZlciwgc2l6ZSwgbm9ybUNvZWZzKSB7XG4gIG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cbiAgc3dpdGNoIChuYW1lKSB7XG4gICAgY2FzZSAnaGFubic6XG4gICAgY2FzZSAnaGFubmluZyc6XG4gICAgICBpbml0SGFubldpbmRvdyhidWZmZXIsIHNpemUsIG5vcm1Db2Vmcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdoYW1taW5nJzpcbiAgICAgIGluaXRIYW1taW5nV2luZG93KGJ1ZmZlciwgc2l6ZSwgbm9ybUNvZWZzKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2JsYWNrbWFuJzpcbiAgICAgIGluaXRCbGFja21hbldpbmRvdyhidWZmZXIsIHNpemUsIG5vcm1Db2Vmcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdibGFja21hbmhhcnJpcyc6XG4gICAgICBpbml0QmxhY2ttYW5IYXJyaXNXaW5kb3coYnVmZmVyLCBzaXplLCBub3JtQ29lZnMpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnc2luZSc6XG4gICAgICBpbml0U2luZVdpbmRvdyhidWZmZXIsIHNpemUsIG5vcm1Db2Vmcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdyZWN0YW5nbGUnOlxuICAgICAgaW5pdFJlY3RhbmdsZVdpbmRvdyhidWZmZXIsIHNpemUsIG5vcm1Db2Vmcyk7XG4gICAgICBicmVhaztcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBpbml0V2luZG93O1xuXG5cbiIsIi8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy84NjA5Mjg5L2NvbnZlcnQtYS1iaW5hcnktbm9kZWpzLWJ1ZmZlci10by1qYXZhc2NyaXB0LWFycmF5YnVmZmVyXG4vLyBjb252ZXJ0cyBhIG5vZGVqcyBCdWZmZXIgdG8gQXJyYXlCdWZmZXJcbi8vIGV4cG9ydCBmdW5jdGlvbiBidWZmZXJUb0FycmF5QnVmZmVyKGJ1ZmZlcikge1xuLy8gICBjb25zdCBhYiA9IG5ldyBBcnJheUJ1ZmZlcihidWZmZXIubGVuZ3RoKTtcbi8vICAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGFiKTtcblxuLy8gICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1ZmZlci5sZW5ndGg7ICsraSlcbi8vICAgICB2aWV3W2ldID0gYnVmZmVyW2ldO1xuXG4vLyAgIHJldHVybiBhYjtcbi8vIH1cblxuLy8gZXhwb3J0IGZ1bmN0aW9uIGFycmF5QnVmZmVyVG9CdWZmZXIoYXJyYXlCdWZmZXIpIHtcbi8vICAgY29uc3QgYnVmZmVyID0gbmV3IEJ1ZmZlcihhcnJheUJ1ZmZlci5ieXRlTGVuZ3RoKTtcbi8vICAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKTtcblxuLy8gICBmb3IgKGxldCBpID0gMDsgaSA8IGJ1ZmZlci5sZW5ndGg7ICsraSlcbi8vICAgICBidWZmZXJbaV0gPSB2aWV3W2ldO1xuXG4vLyAgIHJldHVybiBidWZmZXI7XG4vLyB9XG5cbi8vIGh0dHA6Ly91cGRhdGVzLmh0bWw1cm9ja3MuY29tLzIwMTIvMDYvSG93LXRvLWNvbnZlcnQtQXJyYXlCdWZmZXItdG8tYW5kLWZyb20tU3RyaW5nXG5mdW5jdGlvbiBVaW50MTZBcnJheTJqc29uKGFycikge1xuICBjb25zdCBzdHIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGFycik7XG4gIHJldHVybiBKU09OLnBhcnNlKHN0ci5yZXBsYWNlKC9cXHUwMDAwL2csICcnKSlcbn1cblxuZnVuY3Rpb24ganNvbjJVaW50MTZBcnJheShqc29uKSB7XG4gIGNvbnN0IHN0ciA9IEpTT04uc3RyaW5naWZ5KGpzb24pO1xuICBjb25zdCBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoc3RyLmxlbmd0aCAqIDIpOyAvLyAyIGJ5dGVzIGZvciBlYWNoIGNoYXJcbiAgY29uc3QgYnVmZmVyVmlldyA9IG5ldyBVaW50MTZBcnJheShidWZmZXIpO1xuXG4gIGZvciAobGV0IGkgPSAwLCBsID0gc3RyLmxlbmd0aDsgaSA8IGw7IGkrKylcbiAgICBidWZmZXJWaWV3W2ldID0gc3RyLmNoYXJDb2RlQXQoaSk7XG5cbiAgcmV0dXJuIGJ1ZmZlclZpZXc7XG59XG5cblxuZXhwb3J0IGNvbnN0IG9wY29kZXMgPSB7XG4gIElOSVRfTU9EVUxFX1JFUTogMTAsXG4gIElOSVRfTU9EVUxFX0FDSzogMTEsXG4gIFBST0NFU1NfU1RSRUFNX1BBUkFNUzogMTIsXG4gIFJFU0VUX1NUUkVBTTogMTMsXG4gIEZJTkFMSVpFX1NUUkVBTTogMTQsXG4gIFBST0NFU1NfRlJBTUU6IDE1XG59XG5cbi8vXG5leHBvcnQgY29uc3QgZW5jb2RlcnMgPSB7XG4gIG9wY29kZShuYW1lKSB7XG4gICAgY29uc3Qgb3Bjb2RlID0gb3Bjb2Rlc1tuYW1lXTtcbiAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDE2QXJyYXkoMSk7XG4gICAgYnVmZmVyWzBdID0gb3Bjb2RlO1xuXG4gICAgcmV0dXJuIGJ1ZmZlcjtcbiAgfSxcbiAgLy8gYG9wY29kZWAgICAgMiBieXRlcyAoVWludDE2KSB8XG4gIGluaXRNb2R1bGVSZXE6IGZ1bmN0aW9uKCkge1xuICAgIGNvbnN0IHBheWxvYWQgPSBlbmNvZGVycy5vcGNvZGUoJ0lOSVRfTU9EVUxFX1JFUScpO1xuICAgIHJldHVybiBwYXlsb2FkLmJ1ZmZlcjtcbiAgfSxcbiAgLy8gYG9wY29kZWAgICAgMiBieXRlcyAoVWludDE2KSB8XG4gIGluaXRNb2R1bGVBY2s6IGZ1bmN0aW9uKCkge1xuICAgIGNvbnN0IHBheWxvYWQgPSBlbmNvZGVycy5vcGNvZGUoJ0lOSVRfTU9EVUxFX0FDSycpO1xuICAgIHJldHVybiBwYXlsb2FkLmJ1ZmZlcjtcbiAgfSxcbiAgLy8gYG9wY29kZWAgICAgMiBieXRlcyAoVWludDE2KSB8XG4gIC8vIGBzdHJlYW1QYXJhbXNgICBuIGJ5dGVzIChVaW50MTYpXG4gIHN0cmVhbVBhcmFtczogZnVuY3Rpb24oc3RyZWFtUGFyYW1zKSB7XG4gICAgY29uc3Qgb3Bjb2RlID0gZW5jb2RlcnMub3Bjb2RlKCdQUk9DRVNTX1NUUkVBTV9QQVJBTVMnKTtcbiAgICBjb25zdCBzdHJlYW1QYXJhbXNCdWZmZXIgPSBqc29uMlVpbnQxNkFycmF5KHN0cmVhbVBhcmFtcyk7XG5cbiAgICBjb25zdCBwYXlsb2FkID0gbmV3IFVpbnQxNkFycmF5KDEgKyBzdHJlYW1QYXJhbXNCdWZmZXIubGVuZ3RoKTtcbiAgICBwYXlsb2FkLnNldChvcGNvZGUsIDApO1xuICAgIHBheWxvYWQuc2V0KHN0cmVhbVBhcmFtc0J1ZmZlciwgMSk7XG5cbiAgICByZXR1cm4gcGF5bG9hZC5idWZmZXI7XG4gIH0sXG4gIC8vIGBvcGNvZGVgICAgIDIgYnl0ZXMgKFVpbnQxNikgfFxuICByZXNldFN0cmVhbTogZnVuY3Rpb24oKSB7XG4gICAgY29uc3QgcGF5bG9hZCA9IGVuY29kZXJzLm9wY29kZSgnUkVTRVRfU1RSRUFNJyk7XG4gICAgcmV0dXJuIHBheWxvYWQuYnVmZmVyO1xuICB9LFxuICAvLyBgb3Bjb2RlYCAgICAyIGJ5dGVzIChVaW50MTYpIHxcbiAgLy8gYGVuZFRpbWVgICAgOCBieXRlcyAoRmxvYXQ2NClcbiAgZmluYWxpemVTdHJlYW06IGZ1bmN0aW9uKGVuZFRpbWUpIHtcbiAgICBjb25zdCBvcGNvZGUgPSBlbmNvZGVycy5vcGNvZGUoJ1JFU0VUX1NUUkVBTScpO1xuXG4gICAgY29uc3QgZW5kVGltZUJ1ZmZlciA9IG5ldyBGbG9hdDY0QXJyYXkoMSk7XG4gICAgZW5kVGltZUJ1ZmZlclswXSA9IGVuZFRpbWU7XG5cbiAgICBjb25zdCBwYXlsb2FkID0gbmV3IFVpbnQxNkFycmF5KDEgKyA0KTtcbiAgICBwYXlsb2FkLnNldChvcGNvZGUsIDApO1xuICAgIHBheWxvYWQuc2V0KG5ldyBVaW50MTZBcnJheShlbmRUaW1lQnVmZmVyLmJ1ZmZlciksIDEpO1xuXG4gICAgcmV0dXJuIHBheWxvYWQuYnVmZmVyO1xuICB9LFxuICAvLyBgb3Bjb2RlYCAgICAyIGJ5dGVzIChVaW50MTYpIHxcbiAgLy8gYHRpbWVgICAgICAgOCBieXRlcyAoRmxvYXQ2NCkgfFxuICAvLyBgZGF0YWAgICAgICBmcmFtZVNpemUgKiA0IChGbG9hdDMyKSB8XG4gIC8vIGBtZXRhZGF0YWAgIG4gYnl0ZXMgKFVpbnQxNilcbiAgcHJvY2Vzc0ZyYW1lOiBmdW5jdGlvbihmcmFtZSwgZnJhbWVTaXplKSB7XG4gICAgY29uc3Qgb3Bjb2RlID0gZW5jb2RlcnMub3Bjb2RlKCdQUk9DRVNTX0ZSQU1FJyk7XG5cbiAgICBjb25zdCB0aW1lID0gbmV3IEZsb2F0NjRBcnJheSgxKTtcbiAgICB0aW1lWzBdID0gZnJhbWUudGltZTtcblxuICAgIGNvbnN0IGRhdGEgPSBuZXcgRmxvYXQzMkFycmF5KGZyYW1lU2l6ZSk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICAgIGRhdGFbaV0gPSBmcmFtZS5kYXRhW2ldO1xuXG4gICAgY29uc3QgbWV0YWRhdGEgPSBqc29uMlVpbnQxNkFycmF5KGZyYW1lLm1ldGFkYXRhKTtcblxuICAgIGNvbnN0IGxlbmd0aCA9IDEgKyA0ICsgKDIgKiBmcmFtZVNpemUpICsgbWV0YWRhdGEubGVuZ3RoO1xuICAgIGNvbnN0IHBheWxvYWQgPSBuZXcgVWludDE2QXJyYXkobGVuZ3RoKTtcbiAgICBwYXlsb2FkLnNldChvcGNvZGUsIDApO1xuICAgIHBheWxvYWQuc2V0KG5ldyBVaW50MTZBcnJheSh0aW1lLmJ1ZmZlciksIDEpO1xuICAgIHBheWxvYWQuc2V0KG5ldyBVaW50MTZBcnJheShkYXRhLmJ1ZmZlciksIDEgKyA0KTtcbiAgICBwYXlsb2FkLnNldChtZXRhZGF0YSwgMSArIDQgKyAoMiAqIGZyYW1lU2l6ZSkpO1xuXG4gICAgcmV0dXJuIHBheWxvYWQuYnVmZmVyO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBkZWNvZGVycyA9IHtcbiAgb3Bjb2RlKGFycmF5QnVmZmVyKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50MTZBcnJheShhcnJheUJ1ZmZlcilbMF07XG4gIH0sXG4gIC8vIGBvcGNvZGVgICAgIDIgYnl0ZXMgKFVpbnQxNikgfFxuICAvLyBgc3RyZWFtUGFyYW1zYCAgbiBieXRlcyAoVWludDE2KVxuICBzdHJlYW1QYXJhbXMoYXJyYXlCdWZmZXIpIHtcbiAgICBjb25zdCBwYXlsb2FkID0gbmV3IFVpbnQxNkFycmF5KGFycmF5QnVmZmVyLnNsaWNlKDIpKTtcbiAgICBjb25zdCBwcmV2U3RyZWFtUGFyYW1zID0gVWludDE2QXJyYXkyanNvbihwYXlsb2FkKTtcbiAgICByZXR1cm4gcHJldlN0cmVhbVBhcmFtcztcbiAgfSxcbiAgLy8gYG9wY29kZWAgICAgMiBieXRlcyAoVWludDE2KSB8XG4gIC8vIGBlbmRUaW1lYCAgIDggYnl0ZXMgKEZsb2F0NjQpXG4gIGZpbmFsaXplU3RyZWFtKGFycmF5QnVmZmVyKSB7XG4gICAgcmV0dXJuIG5ldyBGbG9hdDY0QXJyYXkoYXJyYXlCdWZmZXIuc2xpY2UoMikpWzBdO1xuICB9LFxuICAvLyBgb3Bjb2RlYCAgICAyIGJ5dGVzIChVaW50MTYpIHxcbiAgLy8gYHRpbWVgICAgICAgOCBieXRlcyAoRmxvYXQ2NCkgfFxuICAvLyBgZGF0YWAgICAgICBmcmFtZVNpemUgKiA0IChGbG9hdDMyKSB8XG4gIC8vIGBtZXRhZGF0YWAgIG4gYnl0ZXMgKFVpbnQxNilcbiAgcHJvY2Vzc0ZyYW1lKGFycmF5QnVmZmVyLCBmcmFtZVNpemUpIHtcbiAgICAgIC8vIDEgKiA4IGJ5dGVzXG4gICAgICBjb25zdCB0aW1lU3RhcnQgPSAyO1xuICAgICAgY29uc3QgdGltZUVuZCA9IHRpbWVTdGFydCArIDg7XG4gICAgICBjb25zdCB0aW1lID0gbmV3IEZsb2F0NjRBcnJheShhcnJheUJ1ZmZlci5zbGljZSh0aW1lU3RhcnQsIHRpbWVFbmQpKVswXTtcbiAgICAgIC8vIGZyYW1lU2l6ZSAqIDQgYnl0ZXNcbiAgICAgIGNvbnN0IGRhdGFTdGFydCA9IHRpbWVFbmQ7XG4gICAgICBjb25zdCBkYXRhRW5kID0gZGF0YVN0YXJ0ICsgNCAqIGZyYW1lU2l6ZTtcbiAgICAgIGNvbnN0IGRhdGEgPSBuZXcgRmxvYXQzMkFycmF5KGFycmF5QnVmZmVyLnNsaWNlKGRhdGFTdGFydCwgZGF0YUVuZCkpO1xuICAgICAgLy8gcmVzdCBvZiBwYXlsb2FkXG4gICAgICBjb25zdCBtZXRhU3RhcnQgPSBkYXRhRW5kO1xuICAgICAgY29uc3QgbWV0YUJ1ZmZlciA9IG5ldyBVaW50MTZBcnJheShhcnJheUJ1ZmZlci5zbGljZShtZXRhU3RhcnQpKTtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gVWludDE2QXJyYXkyanNvbihtZXRhQnVmZmVyKTtcblxuICAgICAgcmV0dXJuIHsgdGltZSwgZGF0YSwgbWV0YWRhdGEgfTtcbiAgfVxufVxuIiwiaW1wb3J0IHBhcmFtZXRlcnMgZnJvbSAnQGlyY2FtL3BhcmFtZXRlcnMnO1xuXG5sZXQgaWQgPSAwO1xuXG4vKipcbiAqIEJhc2UgYGxmb2AgY2xhc3MgdG8gYmUgZXh0ZW5kZWQgaW4gb3JkZXIgdG8gY3JlYXRlIG5ldyBub2Rlcy5cbiAqXG4gKiBOb2RlcyBhcmUgZGl2aWRlZCBpbiAzIGNhdGVnb3JpZXM6XG4gKiAtICoqYHNvdXJjZWAqKiBhcmUgcmVzcG9uc2libGUgZm9yIGFjcXVlcmluZyBhIHNpZ25hbCBhbmQgaXRzIHByb3BlcnRpZXNcbiAqICAgKGZyYW1lUmF0ZSwgZnJhbWVTaXplLCBldGMuKVxuICogLSAqKmBzaW5rYCoqIGFyZSBlbmRwb2ludHMgb2YgdGhlIGdyYXBoLCBzdWNoIG5vZGVzIGNhbiBiZSByZWNvcmRlcnMsXG4gKiAgIHZpc3VhbGl6ZXJzLCBldGMuXG4gKiAtICoqYG9wZXJhdG9yYCoqIGFyZSB1c2VkIHRvIG1ha2UgY29tcHV0YXRpb24gb24gdGhlIGlucHV0IHNpZ25hbCBhbmRcbiAqICAgZm9yd2FyZCB0aGUgcmVzdWx0cyBiZWxvdyBpbiB0aGUgZ3JhcGguXG4gKlxuICogSW4gbW9zdCBjYXNlcyB0aGUgbWV0aG9kcyB0byBvdmVycmlkZSAvIGV4dGVuZCBhcmU6XG4gKiAtIHRoZSAqKmBjb25zdHJ1Y3RvcmAqKiB0byBkZWZpbmUgdGhlIHBhcmFtZXRlcnMgb2YgdGhlIG5ldyBsZm8gbm9kZS5cbiAqIC0gdGhlICoqYHByb2Nlc3NTdHJlYW1QYXJhbXNgKiogbWV0aG9kIHRvIGRlZmluZSBob3cgdGhlIG5vZGUgbW9kaWZ5IHRoZVxuICogICBzdHJlYW0gYXR0cmlidXRlcyAoZS5nLiBieSBjaGFuZ2luZyB0aGUgZnJhbWUgc2l6ZSlcbiAqIC0gdGhlICoqYHByb2Nlc3N7RnJhbWVUeXBlfWAqKiBtZXRob2QgdG8gZGVmaW5lIHRoZSBvcGVyYXRpb25zIHRoYXQgdGhlXG4gKiAgIG5vZGUgYXBwbHkgb24gdGhlIHN0cmVhbS4gVGhlIHR5cGUgb2YgaW5wdXQgYSBub2RlIGNhbiBoYW5kbGUgaXMgZGVmaW5lZFxuICogICBieSBpdHMgaW1wbGVtZW50ZWQgaW50ZXJmYWNlLCBpZiBpdCBpbXBsZW1lbnRzIGBwcm9jZXNzU2lnbmFsYCwgYSBzdHJlYW1cbiAqICAgb2YgdHlwZSBgc2lnbmFsYCBjYW4gYmUgcHJvY2Vzc2VkLCBgcHJvY2Vzc1ZlY3RvcmAgdG8gaGFuZGxlXG4gKiAgIGFuIGlucHV0IG9mIHR5cGUgYHZlY3RvcmAuXG4gKlxuICogPHNwYW4gY2xhc3M9XCJ3YXJuaW5nXCI+X1RoaXMgY2xhc3Mgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYWJzdHJhY3QgYW5kIG9ubHlcbiAqIGJlIHVzZWQgYXMgYSBiYXNlIGNsYXNzIHRvIGV4dGVuZC5fPC9zcGFuPlxuICpcbiAqICMjIyMgb3ZlcnZpZXcgb2YgdGhlIGludGVyZmFjZVxuICpcbiAqICoqaW5pdE1vZHVsZSoqXG4gKlxuICogUmV0dXJucyBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBtb2R1bGUgaXMgaW5pdGlhbGl6ZWQuIElzXG4gKiBlc3BlY2lhbGx5IGltcG9ydGFudCBmb3IgbW9kdWxlcyB0aGF0IHJlbHkgb24gYXN5bmNocm9ub3VzIHVuZGVybHlpbmcgQVBJcy5cbiAqXG4gKiAqKnByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcykqKlxuICpcbiAqIGBiYXNlYCBjbGFzcyAoZGVmYXVsdCBpbXBsZW1lbnRhdGlvbilcbiAqIC0gY2FsbCBgcHJlcGFyZVN0cmVhbVBhcmFtc2BcbiAqIC0gY2FsbCBgcHJvcGFnYXRlU3RyZWFtUGFyYW1zYFxuICpcbiAqIGBjaGlsZGAgY2xhc3NcbiAqIC0gb3ZlcnJpZGUgc29tZSBvZiB0aGUgaW5oZXJpdGVkIGBzdHJlYW1QYXJhbXNgXG4gKiAtIGNyZWF0ZXMgdGhlIGFueSByZWxhdGVkIGxvZ2ljIGJ1ZmZlcnNcbiAqIC0gY2FsbCBgcHJvcGFnYXRlU3RyZWFtUGFyYW1zYFxuICpcbiAqIF9zaG91bGQgbm90IGNhbGwgYHN1cGVyLnByb2Nlc3NTdHJlYW1QYXJhbXNgX1xuICpcbiAqICoqcHJlcGFyZVN0cmVhbVBhcmFtcygpKipcbiAqXG4gKiAtIGFzc2lnbiBwcmV2U3RyZWFtUGFyYW1zIHRvIHRoaXMuc3RyZWFtUGFyYW1zXG4gKiAtIGNoZWNrIGlmIHRoZSBjbGFzcyBpbXBsZW1lbnRzIHRoZSBjb3JyZWN0IGBwcm9jZXNzSW5wdXRgIG1ldGhvZFxuICpcbiAqIF9zaG91bGRuJ3QgYmUgZXh0ZW5kZWQsIG9ubHkgY29uc3VtZWQgaW4gYHByb2Nlc3NTdHJlYW1QYXJhbXNgX1xuICpcbiAqICoqcHJvcGFnYXRlU3RyZWFtUGFyYW1zKCkqKlxuICpcbiAqIC0gY3JlYXRlcyB0aGUgYGZyYW1lRGF0YWAgYnVmZmVyXG4gKiAtIHByb3BhZ2F0ZSBgc3RyZWFtUGFyYW1zYCB0byBjaGlsZHJlblxuICpcbiAqIF9zaG91bGRuJ3QgYmUgZXh0ZW5kZWQsIG9ubHkgY29uc3VtZWQgaW4gYHByb2Nlc3NTdHJlYW1QYXJhbXNgX1xuICpcbiAqICoqcHJvY2Vzc0ZyYW1lKCkqKlxuICpcbiAqIGBiYXNlYCBjbGFzcyAoZGVmYXVsdCBpbXBsZW1lbnRhdGlvbilcbiAqIC0gY2FsbCBgcHJlcGFyZUZyYW1lYFxuICogLSBhc3NpZ24gZnJhbWVUaW1lIGFuZCBmcmFtZU1ldGFkYXRhIHRvIGlkZW50aXR5XG4gKiAtIGNhbGwgdGhlIHByb3BlciBmdW5jdGlvbiBhY2NvcmRpbmcgdG8gaW5wdXRUeXBlXG4gKiAtIGNhbGwgYHByb3BhZ2F0ZUZyYW1lYFxuICpcbiAqIGBjaGlsZGAgY2xhc3NcbiAqIC0gY2FsbCBgcHJlcGFyZUZyYW1lYFxuICogLSBkbyB3aGF0ZXZlciB5b3Ugd2FudCB3aXRoIGluY29tbWluZyBmcmFtZVxuICogLSBjYWxsIGBwcm9wYWdhdGVGcmFtZWBcbiAqXG4gKiBfc2hvdWxkIG5vdCBjYWxsIGBzdXBlci5wcm9jZXNzRnJhbWVgX1xuICpcbiAqICoqcHJlcGFyZUZyYW1lKCkqKlxuICpcbiAqIC0gaWYgYHJlaW5pdGAgYW5kIHRyaWdnZXIgYHByb2Nlc3NTdHJlYW1QYXJhbXNgIGlmIG5lZWRlZFxuICpcbiAqIF9zaG91bGRuJ3QgYmUgZXh0ZW5kZWQsIG9ubHkgY29uc3VtZWQgaW4gYHByb2Nlc3NGcmFtZWBfXG4gKlxuICogKipwcm9wYWdhdGVGcmFtZSgpKipcbiAqXG4gKiAtIHByb3BhZ2F0ZSBmcmFtZSB0byBjaGlsZHJlblxuICpcbiAqIF9zaG91bGRuJ3QgYmUgZXh0ZW5kZWQsIG9ubHkgY29uc3VtZWQgaW4gYHByb2Nlc3NGcmFtZWBfXG4gKlxuICogQG1lbWJlcm9mIG1vZHVsZTpjb3JlXG4gKi9cbmNsYXNzIEJhc2VMZm8ge1xuICBjb25zdHJ1Y3RvcihkZWZpbml0aW9ucyA9IHt9LCBvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLmNpZCA9IGlkKys7XG5cbiAgICAvKipcbiAgICAgKiBQYXJhbWV0ZXIgYmFnIGNvbnRhaW5pbmcgcGFyYW1ldGVyIGluc3RhbmNlcy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQG5hbWUgcGFyYW1zXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIG1vZHVsZTpjb3JlLkJhc2VMZm9cbiAgICAgKi9cbiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtZXRlcnMoZGVmaW5pdGlvbnMsIG9wdGlvbnMpO1xuICAgIC8vIGxpc3RlbiBmb3IgcGFyYW0gdXBkYXRlc1xuICAgIHRoaXMucGFyYW1zLmFkZExpc3RlbmVyKHRoaXMub25QYXJhbVVwZGF0ZS5iaW5kKHRoaXMpKTtcblxuICAgIC8qKlxuICAgICAqIERlc2NyaXB0aW9uIG9mIHRoZSBzdHJlYW0gb3V0cHV0IG9mIHRoZSBub2RlLlxuICAgICAqIFNldCB0byBgbnVsbGAgd2hlbiB0aGUgbm9kZSBpcyBkZXN0cm95ZWQuXG4gICAgICpcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBmcmFtZVNpemUgLSBGcmFtZSBzaXplIGF0IHRoZSBvdXRwdXQgb2YgdGhlIG5vZGUuXG4gICAgICogQHByb3BlcnR5IHtOdW1iZXJ9IGZyYW1lUmF0ZSAtIEZyYW1lIHJhdGUgYXQgdGhlIG91dHB1dCBvZiB0aGUgbm9kZS5cbiAgICAgKiBAcHJvcGVydHkge1N0cmluZ30gZnJhbWVUeXBlIC0gRnJhbWUgdHlwZSBhdCB0aGUgb3V0cHV0IG9mIHRoZSBub2RlLFxuICAgICAqICBwb3NzaWJsZSB2YWx1ZXMgYXJlIGBzaWduYWxgLCBgdmVjdG9yYCBvciBgc2NhbGFyYC5cbiAgICAgKiBAcHJvcGVydHkge0FycmF5fFN0cmluZ30gZGVzY3JpcHRpb24gLSBJZiB0eXBlIGlzIGB2ZWN0b3JgLCBkZXNjcmliZVxuICAgICAqICB0aGUgZGltZW5zaW9uKHMpIG9mIG91dHB1dCBzdHJlYW0uXG4gICAgICogQHByb3BlcnR5IHtOdW1iZXJ9IHNvdXJjZVNhbXBsZVJhdGUgLSBTYW1wbGUgcmF0ZSBvZiB0aGUgc291cmNlIG9mIHRoZVxuICAgICAqICBncmFwaC4gX1RoZSB2YWx1ZSBzaG91bGQgYmUgZGVmaW5lZCBieSBzb3VyY2VzIGFuZCBuZXZlciBtb2RpZmllZF8uXG4gICAgICogQHByb3BlcnR5IHtOdW1iZXJ9IHNvdXJjZVNhbXBsZUNvdW50IC0gTnVtYmVyIG9mIGNvbnNlY3V0aXZlIGRpc2NyZXRlXG4gICAgICogIHRpbWUgdmFsdWVzIGNvbnRhaW5lZCBpbiB0aGUgZGF0YSBmcmFtZSBvdXRwdXQgYnkgdGhlIHNvdXJjZS5cbiAgICAgKiAgX1RoZSB2YWx1ZSBzaG91bGQgYmUgZGVmaW5lZCBieSBzb3VyY2VzIGFuZCBuZXZlciBtb2RpZmllZF8uXG4gICAgICpcbiAgICAgKiBAbmFtZSBzdHJlYW1QYXJhbXNcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgbW9kdWxlOmNvcmUuQmFzZUxmb1xuICAgICAqL1xuICAgIHRoaXMuc3RyZWFtUGFyYW1zID0ge1xuICAgICAgZnJhbWVUeXBlOiBudWxsLFxuICAgICAgZnJhbWVTaXplOiAxLFxuICAgICAgZnJhbWVSYXRlOiAwLFxuICAgICAgZGVzY3JpcHRpb246IG51bGwsXG4gICAgICBzb3VyY2VTYW1wbGVSYXRlOiAwLFxuICAgICAgc291cmNlU2FtcGxlQ291bnQ6IG51bGwsXG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEN1cnJlbnQgZnJhbWUuIFRoaXMgb2JqZWN0IGFuZCBpdHMgZGF0YSBhcmUgdXBkYXRlZCBhdCBlYWNoIGluY29tbWluZ1xuICAgICAqIGZyYW1lIHdpdGhvdXQgcmVhbGxvY2F0aW5nIG1lbW9yeS5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQG5hbWUgZnJhbWVcbiAgICAgKiBAcHJvcGVydHkge051bWJlcn0gdGltZSAtIFRpbWUgb2YgdGhlIGN1cnJlbnQgZnJhbWUuXG4gICAgICogQHByb3BlcnR5IHtGbG9hdDMyQXJyYXl9IGRhdGEgLSBEYXRhIG9mIHRoZSBjdXJyZW50IGZyYW1lLlxuICAgICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtZXRhZGF0YSAtIE1ldGFkYXRhIGFzc29jaXRlZCB0byB0aGUgY3VycmVudCBmcmFtZS5cbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgbW9kdWxlOmNvcmUuQmFzZUxmb1xuICAgICAqL1xuICAgIHRoaXMuZnJhbWUgPSB7XG4gICAgICB0aW1lOiAwLFxuICAgICAgZGF0YTogbnVsbCxcbiAgICAgIG1ldGFkYXRhOiB7fSxcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogTGlzdCBvZiBub2RlcyBjb25uZWN0ZWQgdG8gdGhlIG91cHV0IG9mIHRoZSBub2RlIChsb3dlciBpbiB0aGUgZ3JhcGgpLlxuICAgICAqIEF0IGVhY2ggZnJhbWUsIHRoZSBub2RlIGZvcndhcmQgaXRzIGBmcmFtZWAgdG8gdG8gYWxsIGl0cyBgbmV4dE1vZHVsZXNgLlxuICAgICAqXG4gICAgICogQHR5cGUge0FycmF5PEJhc2VMZm8+fVxuICAgICAqIEBuYW1lIG5leHRNb2R1bGVzXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQG1lbWJlcm9mIG1vZHVsZTpjb3JlLkJhc2VMZm9cbiAgICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI2Nvbm5lY3R9XG4gICAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNkaXNjb25uZWN0fVxuICAgICAqL1xuICAgIHRoaXMubmV4dE1vZHVsZXMgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBub2RlIGZyb20gd2hpY2ggdGhlIG5vZGUgcmVjZWl2ZSB0aGUgZnJhbWVzICh1cHBlciBpbiB0aGUgZ3JhcGgpLlxuICAgICAqXG4gICAgICogQHR5cGUge0Jhc2VMZm99XG4gICAgICogQG5hbWUgcHJldk1vZHVsZVxuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBtZW1iZXJvZiBtb2R1bGU6Y29yZS5CYXNlTGZvXG4gICAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNjb25uZWN0fVxuICAgICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jZGlzY29ubmVjdH1cbiAgICAgKi9cbiAgICB0aGlzLnByZXZNb2R1bGUgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogSXMgc2V0IHRvIHRydWUgd2hlbiBhIHN0YXRpYyBwYXJhbWV0ZXIgaXMgdXBkYXRlZC4gT24gdGhlIG5leHQgaW5wdXRcbiAgICAgKiBmcmFtZSBhbGwgdGhlIHN1YmdyYXBoIHN0cmVhbVBhcmFtcyBzdGFydGluZyBmcm9tIHRoaXMgbm9kZSB3aWxsIGJlXG4gICAgICogdXBkYXRlZC5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBuYW1lIF9yZWluaXRcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAbWVtYmVyb2YgbW9kdWxlOmNvcmUuQmFzZUxmb1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fcmVpbml0ID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBvYmplY3QgZGVzY3JpYmluZyBlYWNoIGF2YWlsYWJsZSBwYXJhbWV0ZXIgb2YgdGhlIG5vZGUuXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIGdldFBhcmFtc0Rlc2NyaXB0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnBhcmFtcy5nZXREZWZpbml0aW9ucygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IGFsbCBwYXJhbWV0ZXJzIHRvIHRoZWlyIGluaXRpYWwgdmFsdWUgKGFzIGRlZmluZWQgb24gaW5zdGFudGljYXRpb24pXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jc3RyZWFtUGFyYW1zfVxuICAgKi9cbiAgcmVzZXRQYXJhbXMoKSB7XG4gICAgdGhpcy5wYXJhbXMucmVzZXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGdW5jdGlvbiBjYWxsZWQgd2hlbiBhIHBhcmFtIGlzIHVwZGF0ZWQuIEJ5IGRlZmF1bHQgc2V0IHRoZSBgX3JlaW5pdGBcbiAgICogZmxhZyB0byBgdHJ1ZWAgaWYgdGhlIHBhcmFtIGlzIGBzdGF0aWNgIG9uZS4gVGhpcyBtZXRob2Qgc2hvdWxkIGJlXG4gICAqIGV4dGVuZGVkIHRvIGhhbmRsZSBwYXJ0aWN1bGFyIGxvZ2ljIGJvdW5kIHRvIGEgc3BlY2lmaWMgcGFyYW1ldGVyLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSAtIE5hbWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWUgLSBWYWx1ZSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0ge09iamVjdH0gbWV0YXMgLSBNZXRhZGF0YSBhc3NvY2lhdGVkIHRvIHRoZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBvblBhcmFtVXBkYXRlKG5hbWUsIHZhbHVlLCBtZXRhcyA9IHt9KSB7XG4gICAgaWYgKG1ldGFzLmtpbmQgPT09ICdzdGF0aWMnKVxuICAgICAgdGhpcy5fcmVpbml0ID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25uZWN0IHRoZSBjdXJyZW50IG5vZGUgKGBwcmV2TW9kdWxlYCkgdG8gYW5vdGhlciBub2RlIChgbmV4dE9wYCkuXG4gICAqIEEgZ2l2ZW4gbm9kZSBjYW4gYmUgY29ubmVjdGVkIHRvIHNldmVyYWwgb3BlcmF0b3JzIGFuZCBwcm9wYWdhdGUgZnJhbWVzXG4gICAqIHRvIGVhY2ggb2YgdGhlbS5cbiAgICpcbiAgICogQHBhcmFtIHtCYXNlTGZvfSBuZXh0IC0gTmV4dCBvcGVyYXRvciBpbiB0aGUgZ3JhcGguXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJvY2Vzc0ZyYW1lfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI2Rpc2Nvbm5lY3R9XG4gICAqL1xuICBjb25uZWN0KG5leHQpIHtcbiAgICBpZiAodGhpcy5zdHJlYW1QYXJhbXMgPT09IG51bGwgfHwgbmV4dC5zdHJlYW1QYXJhbXMgPT09IG51bGwpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29ubmVjdGlvbjogY2Fubm90IGNvbm5lY3QgYSBkZWFkIG5vZGUnKTtcblxuICAgIGlmICh0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVR5cGUgIT09IG51bGwpIHsgLy8gZ3JhcGggaGFzIGFscmVhZHkgYmVlbiBzdGFydGVkXG4gICAgICAvLyBuZXh0LnByb2Nlc3NTdHJlYW1QYXJhbXModGhpcy5zdHJlYW1QYXJhbXMpO1xuICAgICAgbmV4dC5pbml0TW9kdWxlKCkudGhlbigoKSA9PiB7XG4gICAgICAgIG5leHQucHJvY2Vzc1N0cmVhbVBhcmFtcyh0aGlzLnN0cmVhbVBhcmFtcyk7XG4gICAgICAgIC8vIHdlIGNhbiBmb3J3YXJkIGZyYW1lIGZyb20gbm93XG4gICAgICAgIHRoaXMubmV4dE1vZHVsZXMucHVzaChuZXh0KTtcbiAgICAgICAgbmV4dC5wcmV2TW9kdWxlID0gdGhpcztcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm5leHRNb2R1bGVzLnB1c2gobmV4dCk7XG4gICAgICBuZXh0LnByZXZNb2R1bGUgPSB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9wZXJhdG9yIGZyb20gaXRzIHByZXZpb3VzIG9wZXJhdG9ycycgYG5leHRNb2R1bGVzYC5cbiAgICpcbiAgICogQHBhcmFtIHtCYXNlTGZvfSBbbmV4dD1udWxsXSAtIFRoZSBvcGVyYXRvciB0byBkaXNjb25uZWN0IGZyb20gdGhlIGN1cnJlbnRcbiAgICogIG9wZXJhdG9yLiBJZiBgbnVsbGAgZGlzY29ubmVjdCBhbGwgdGhlIG5leHQgb3BlcmF0b3JzLlxuICAgKi9cbiAgZGlzY29ubmVjdChuZXh0ID0gbnVsbCkge1xuICAgIGlmIChuZXh0ID09PSBudWxsKSB7XG4gICAgICB0aGlzLm5leHRNb2R1bGVzLmZvckVhY2goKG5leHQpID0+IHRoaXMuZGlzY29ubmVjdChuZXh0KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5uZXh0TW9kdWxlcy5pbmRleE9mKHRoaXMpO1xuICAgICAgdGhpcy5uZXh0TW9kdWxlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgbmV4dC5wcmV2TW9kdWxlID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVzdHJveSBhbGwgdGhlIG5vZGVzIGluIHRoZSBzdWItZ3JhcGggc3RhcnRpbmcgZnJvbSB0aGUgY3VycmVudCBub2RlLlxuICAgKiBXaGVuIGRldHJveWVkLCB0aGUgYHN0cmVhbVBhcmFtc2Agb2YgdGhlIG5vZGUgYXJlIHNldCB0byBgbnVsbGAsIHRoZVxuICAgKiBvcGVyYXRvciBpcyB0aGVuIGNvbnNpZGVyZWQgYXMgYGRlYWRgIGFuZCBjYW5ub3QgYmUgcmVjb25uZWN0ZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jY29ubmVjdH1cbiAgICovXG4gIGRlc3Ryb3koKSB7XG4gICAgLy8gZGVzdHJveSBhbGwgY2hpZHJlblxuICAgIGxldCBpbmRleCA9IHRoaXMubmV4dE1vZHVsZXMubGVuZ3RoO1xuXG4gICAgd2hpbGUgKGluZGV4LS0pXG4gICAgICB0aGlzLm5leHRNb2R1bGVzW2luZGV4XS5kZXN0cm95KCk7XG5cbiAgICAvLyBkaXNjb25uZWN0IGl0c2VsZiBmcm9tIHRoZSBwcmV2aW91cyBvcGVyYXRvclxuICAgIGlmICh0aGlzLnByZXZNb2R1bGUpXG4gICAgICB0aGlzLnByZXZNb2R1bGUuZGlzY29ubmVjdCh0aGlzKTtcblxuICAgIC8vIG1hcmsgdGhlIG9iamVjdCBhcyBkZWFkXG4gICAgdGhpcy5zdHJlYW1QYXJhbXMgPSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIGBQcm9taXNlYCB0aGF0IHJlc29sdmUgd2hlbiB0aGUgbW9kdWxlIGlzIHJlYWR5IHRvIGJlIGNvbnN1bWVkLlxuICAgKiBTb21lIG1vZHVsZXMgcmVsaWVzIG9uIGFzeW5jaHJvbm91cyBBUElzIGF0IGluaXRpYWxpemF0aW9uIGFuZCB0aHVzIGNvdWxkXG4gICAqIGJlIG5vdCByZWFkeSB0byBiZSBjb25zdW1lZCB3aGVuIHRoZSBncmFwaCBzdGFydHMuXG4gICAqIEEgbW9kdWxlIHNob3VsZCBiZSBjb25zaWRlciBhcyBpbml0aWFsaXplZCB3aGVuIGFsbCBuZXh0IG1vZHVsZXMgKGNoaWxkcmVuKVxuICAgKiBhcmUgdGhlbXNlbHZlcyBpbml0aWFsaXplZC4gVGhlIGV2ZW50IGJ1YmJsZXMgdXAgZnJvbSBzaW5rcyB0byBzb3VyY2VzLlxuICAgKiBXaGVuIGFsbCBpdHMgbmV4dCBvcGVyYXRvcnMgYXJlIHJlYWR5LCBhIHNvdXJjZSBjYW4gY29uc2lkZXIgdGhlIHdob2xlIGdyYXBoXG4gICAqIGFzIHJlYWR5IGFuZCB0aGVuIHN0YXJ0IHRvIHByb2R1Y2UgZnJhbWVzLlxuICAgKiBUaGUgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiByZXNvbHZlcyB3aGVuIGFsbCBuZXh0IG9wZXJhdG9ycyBhcmUgcmVzb2x2ZWRcbiAgICogdGhlbXNlbHZlcy5cbiAgICogQW4gb3BlcmF0b3IgcmVseWluZyBvbiBleHRlcm5hbCBhc3luYyBBUEkgbXVzdCBvdmVycmlkZSB0aGlzIG1ldGhvZCB0b1xuICAgKiByZXNvbHZlIG9ubHkgd2hlbiBpdHMgZGVwZW5kZWN5IGlzIHJlYWR5LlxuICAgKlxuICAgKiBAcmV0dXJuIFByb21pc2VcbiAgICogQHRvZG8gLSBIYW5kbGUgZHluYW1pYyBjb25uZWN0aW9uc1xuICAgKi9cbiAgaW5pdE1vZHVsZSgpIHtcbiAgICBjb25zdCBuZXh0UHJvbWlzZXMgPSB0aGlzLm5leHRNb2R1bGVzLm1hcCgobW9kdWxlKSA9PiB7XG4gICAgICByZXR1cm4gbW9kdWxlLmluaXRNb2R1bGUoKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChuZXh0UHJvbWlzZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciB0byBpbml0aWFsaXplIHRoZSBzdHJlYW0gaW4gc3RhbmRhbG9uZSBtb2RlLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gW3N0cmVhbVBhcmFtcz17fV0gLSBQYXJhbWV0ZXJzIG9mIHRoZSBzdHJlYW0uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJvY2Vzc1N0cmVhbVBhcmFtc31cbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNyZXNldFN0cmVhbX1cbiAgICovXG4gIGluaXRTdHJlYW0oc3RyZWFtUGFyYW1zID0ge30pIHtcbiAgICB0aGlzLnByb2Nlc3NTdHJlYW1QYXJhbXMoc3RyZWFtUGFyYW1zKTtcbiAgICB0aGlzLnJlc2V0U3RyZWFtKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgdGhlIGBmcmFtZS5kYXRhYCBidWZmZXIgYnkgc2V0dGluZyBhbGwgaXRzIHZhbHVlcyB0byAwLlxuICAgKiBBIHNvdXJjZSBvcGVyYXRvciBzaG91bGQgY2FsbCBgcHJvY2Vzc1N0cmVhbVBhcmFtc2AgYW5kIGByZXNldFN0cmVhbWAgd2hlblxuICAgKiBzdGFydGVkLCBlYWNoIG9mIHRoZXNlIG1ldGhvZCBwcm9wYWdhdGUgdGhyb3VnaCB0aGUgZ3JhcGggYXV0b21hdGljYWx5LlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb2Nlc3NTdHJlYW1QYXJhbXN9XG4gICAqL1xuICByZXNldFN0cmVhbSgpIHtcbiAgICAvLyBidXR0b20gdXBcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMubmV4dE1vZHVsZXMubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgdGhpcy5uZXh0TW9kdWxlc1tpXS5yZXNldFN0cmVhbSgpO1xuXG4gICAgLy8gbm8gYnVmZmVyIGZvciBgc2NhbGFyYCB0eXBlIG9yIHNpbmsgbm9kZVxuICAgIC8vIEBub3RlIC0gdGhpcyBzaG91bGQgYmUgcmV2aWV3ZWRcbiAgICBpZiAodGhpcy5zdHJlYW1QYXJhbXMuZnJhbWVUeXBlICE9PSAnc2NhbGFyJyAmJiB0aGlzLmZyYW1lLmRhdGEgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IGZyYW1lU2l6ZSA9IHRoaXMuc3RyZWFtUGFyYW1zLmZyYW1lU2l6ZTtcbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmZyYW1lLmRhdGE7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhbWVTaXplOyBpKyspXG4gICAgICAgIGRhdGFbaV0gPSAwO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5hbGl6ZSB0aGUgc3RyZWFtLiBBIHNvdXJjZSBub2RlIHNob3VsZCBjYWxsIHRoaXMgbWV0aG9kIHdoZW4gc3RvcHBlZCxcbiAgICogYGZpbmFsaXplU3RyZWFtYCBpcyBhdXRvbWF0aWNhbGx5IHByb3BhZ2F0ZWQgdGhyb3VnaHQgdGhlIGdyYXBoLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gZW5kVGltZSAtIExvZ2ljYWwgdGltZSBhdCB3aGljaCB0aGUgZ3JhcGggaXMgc3RvcHBlZC5cbiAgICovXG4gIGZpbmFsaXplU3RyZWFtKGVuZFRpbWUpIHtcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMubmV4dE1vZHVsZXMubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgdGhpcy5uZXh0TW9kdWxlc1tpXS5maW5hbGl6ZVN0cmVhbShlbmRUaW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIG9yIHVwZGF0ZSB0aGUgb3BlcmF0b3IncyBgc3RyZWFtUGFyYW1zYCBhY2NvcmRpbmcgdG8gdGhlXG4gICAqIHByZXZpb3VzIG9wZXJhdG9ycyBgc3RyZWFtUGFyYW1zYCB2YWx1ZXMuXG4gICAqXG4gICAqIFdoZW4gaW1wbGVtZW50aW5nIGEgbmV3IG9wZXJhdG9yIHRoaXMgbWV0aG9kIHNob3VsZDpcbiAgICogMS4gY2FsbCBgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zYCB3aXRoIHRoZSBnaXZlbiBgcHJldlN0cmVhbVBhcmFtc2BcbiAgICogMi4gb3B0aW9ubmFsbHkgY2hhbmdlIHZhbHVlcyB0byBgdGhpcy5zdHJlYW1QYXJhbXNgIGFjY29yZGluZyB0byB0aGVcbiAgICogICAgbG9naWMgcGVyZm9ybWVkIGJ5IHRoZSBvcGVyYXRvci5cbiAgICogMy4gb3B0aW9ubmFsbHkgYWxsb2NhdGUgbWVtb3J5IGZvciByaW5nIGJ1ZmZlcnMsIGV0Yy5cbiAgICogNC4gY2FsbCBgdGhpcy5wcm9wYWdhdGVTdHJlYW1QYXJhbXNgIHRvIHRyaWdnZXIgdGhlIG1ldGhvZCBvbiB0aGUgbmV4dFxuICAgKiAgICBvcGVyYXRvcnMgaW4gdGhlIGdyYXBoLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJldlN0cmVhbVBhcmFtcyAtIGBzdHJlYW1QYXJhbXNgIG9mIHRoZSBwcmV2aW91cyBvcGVyYXRvci5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNwcmVwYXJlU3RyZWFtUGFyYW1zfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb3BhZ2F0ZVN0cmVhbVBhcmFtc31cbiAgICovXG4gIHByb2Nlc3NTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyA9IHt9KSB7XG4gICAgdGhpcy5wcmVwYXJlU3RyZWFtUGFyYW1zKHByZXZTdHJlYW1QYXJhbXMpO1xuICAgIHRoaXMucHJvcGFnYXRlU3RyZWFtUGFyYW1zKCk7XG4gIH1cblxuICAvKipcbiAgICogQ29tbW9uIGxvZ2ljIHRvIGRvIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGBwcm9jZXNzU3RyZWFtUGFyYW1gLCBtdXN0IGJlXG4gICAqIGNhbGxlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIGFueSBgcHJvY2Vzc1N0cmVhbVBhcmFtYCBpbXBsZW1lbnRhdGlvbi5cbiAgICpcbiAgICogVGhlIG1ldGhvZCBtYWlubHkgY2hlY2sgaWYgdGhlIGN1cnJlbnQgbm9kZSBpbXBsZW1lbnQgdGhlIGludGVyZmFjZSB0b1xuICAgKiBoYW5kbGUgdGhlIHR5cGUgb2YgZnJhbWUgcHJvcGFnYXRlZCBieSBpdCdzIHBhcmVudDpcbiAgICogLSB0byBoYW5kbGUgYSBgdmVjdG9yYCBmcmFtZSB0eXBlLCB0aGUgY2xhc3MgbXVzdCBpbXBsZW1lbnQgYHByb2Nlc3NWZWN0b3JgXG4gICAqIC0gdG8gaGFuZGxlIGEgYHNpZ25hbGAgZnJhbWUgdHlwZSwgdGhlIGNsYXNzIG11c3QgaW1wbGVtZW50IGBwcm9jZXNzU2lnbmFsYFxuICAgKiAtIGluIGNhc2Ugb2YgYSAnc2NhbGFyJyBmcmFtZSB0eXBlLCB0aGUgY2xhc3MgY2FuIGltcGxlbWVudCBhbnkgb2YgdGhlXG4gICAqIGZvbGxvd2luZyBieSBvcmRlciBvZiBwcmVmZXJlbmNlOiBgcHJvY2Vzc1NjYWxhcmAsIGBwcm9jZXNzVmVjdG9yYCxcbiAgICogYHByb2Nlc3NTaWduYWxgLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJldlN0cmVhbVBhcmFtcyAtIGBzdHJlYW1QYXJhbXNgIG9mIHRoZSBwcmV2aW91cyBvcGVyYXRvci5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNwcm9jZXNzU3RyZWFtUGFyYW1zfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb3BhZ2F0ZVN0cmVhbVBhcmFtc31cbiAgICovXG4gIHByZXBhcmVTdHJlYW1QYXJhbXMocHJldlN0cmVhbVBhcmFtcyA9IHt9KSB7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLnN0cmVhbVBhcmFtcywgcHJldlN0cmVhbVBhcmFtcyk7XG4gICAgY29uc3QgcHJldkZyYW1lVHlwZSA9IHByZXZTdHJlYW1QYXJhbXMuZnJhbWVUeXBlO1xuXG4gICAgc3dpdGNoIChwcmV2RnJhbWVUeXBlKSB7XG4gICAgICBjYXNlICdzY2FsYXInOlxuICAgICAgICBpZiAodGhpcy5wcm9jZXNzU2NhbGFyKVxuICAgICAgICAgIHRoaXMucHJvY2Vzc0Z1bmN0aW9uID0gdGhpcy5wcm9jZXNzU2NhbGFyO1xuICAgICAgICBlbHNlIGlmICh0aGlzLnByb2Nlc3NWZWN0b3IpXG4gICAgICAgICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24gPSB0aGlzLnByb2Nlc3NWZWN0b3I7XG4gICAgICAgIGVsc2UgaWYgKHRoaXMucHJvY2Vzc1NpZ25hbClcbiAgICAgICAgICB0aGlzLnByb2Nlc3NGdW5jdGlvbiA9IHRoaXMucHJvY2Vzc1NpZ25hbDtcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmNvbnN0cnVjdG9yLm5hbWV9IC0gbm8gXCJwcm9jZXNzXCIgZnVuY3Rpb24gZm91bmRgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd2ZWN0b3InOlxuICAgICAgICBpZiAoISgncHJvY2Vzc1ZlY3RvcicgaW4gdGhpcykpXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gLSBcInByb2Nlc3NWZWN0b3JcIiBpcyBub3QgZGVmaW5lZGApO1xuXG4gICAgICAgIHRoaXMucHJvY2Vzc0Z1bmN0aW9uID0gdGhpcy5wcm9jZXNzVmVjdG9yO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3NpZ25hbCc6XG4gICAgICAgIGlmICghKCdwcm9jZXNzU2lnbmFsJyBpbiB0aGlzKSlcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfSAtIFwicHJvY2Vzc1NpZ25hbFwiIGlzIG5vdCBkZWZpbmVkYCk7XG5cbiAgICAgICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24gPSB0aGlzLnByb2Nlc3NTaWduYWw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gZGVmYXVsdHMgdG8gcHJvY2Vzc0Z1bmN0aW9uXG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgdGhlIGB0aGlzLmZyYW1lLmRhdGFgIGJ1ZmZlciBhbmQgZm9yd2FyZCB0aGUgb3BlcmF0b3IncyBgc3RyZWFtUGFyYW1gXG4gICAqIHRvIGFsbCBpdHMgbmV4dCBvcGVyYXRvcnMsIG11c3QgYmUgY2FsbGVkIGF0IHRoZSBlbmQgb2YgYW55XG4gICAqIGBwcm9jZXNzU3RyZWFtUGFyYW1zYCBpbXBsZW1lbnRhdGlvbi5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNwcm9jZXNzU3RyZWFtUGFyYW1zfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3ByZXBhcmVTdHJlYW1QYXJhbXN9XG4gICAqL1xuICBwcm9wYWdhdGVTdHJlYW1QYXJhbXMoKSB7XG4gICAgdGhpcy5mcmFtZS5kYXRhID0gbmV3IEZsb2F0MzJBcnJheSh0aGlzLnN0cmVhbVBhcmFtcy5mcmFtZVNpemUpO1xuXG4gICAgZm9yIChsZXQgaSA9IDAsIGwgPSB0aGlzLm5leHRNb2R1bGVzLmxlbmd0aDsgaSA8IGw7IGkrKylcbiAgICAgIHRoaXMubmV4dE1vZHVsZXNbaV0ucHJvY2Vzc1N0cmVhbVBhcmFtcyh0aGlzLnN0cmVhbVBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lIHRoZSBwYXJ0aWN1bGFyIGxvZ2ljIHRoZSBvcGVyYXRvciBhcHBsaWVzIHRvIHRoZSBzdHJlYW0uXG4gICAqIEFjY29yZGluZyB0byB0aGUgZnJhbWUgdHlwZSBvZiB0aGUgcHJldmlvdXMgbm9kZSwgdGhlIG1ldGhvZCBjYWxscyBvbmVcbiAgICogb2YgdGhlIGZvbGxvd2luZyBtZXRob2QgYHByb2Nlc3NWZWN0b3JgLCBgcHJvY2Vzc1NpZ25hbGAgb3IgYHByb2Nlc3NTY2FsYXJgXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBmcmFtZSAtIEZyYW1lICh0aW1lLCBkYXRhLCBhbmQgbWV0YWRhdGEpIGFzIGdpdmVuIGJ5IHRoZVxuICAgKiAgcHJldmlvdXMgb3BlcmF0b3IuIFRoZSBpbmNvbW1pbmcgZnJhbWUgc2hvdWxkIG5ldmVyIGJlIG1vZGlmaWVkIGJ5XG4gICAqICB0aGUgb3BlcmF0b3IuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJlcGFyZUZyYW1lfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb3BhZ2F0ZUZyYW1lfVxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb2Nlc3NTdHJlYW1QYXJhbXN9XG4gICAqL1xuICBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICB0aGlzLnByZXBhcmVGcmFtZSgpO1xuXG4gICAgLy8gZnJhbWVUaW1lIGFuZCBmcmFtZU1ldGFkYXRhIGRlZmF1bHRzIHRvIGlkZW50aXR5XG4gICAgdGhpcy5mcmFtZS50aW1lID0gZnJhbWUudGltZTtcbiAgICB0aGlzLmZyYW1lLm1ldGFkYXRhID0gZnJhbWUubWV0YWRhdGE7XG5cbiAgICB0aGlzLnByb2Nlc3NGdW5jdGlvbihmcmFtZSk7XG4gICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBvaW50ZXIgdG8gdGhlIG1ldGhvZCBjYWxsZWQgaW4gYHByb2Nlc3NGcmFtZWAgYWNjb3JkaW5nIHRvIHRoZVxuICAgKiBmcmFtZSB0eXBlIG9mIHRoZSBwcmV2aW91cyBvcGVyYXRvci4gSXMgZHluYW1pY2FsbHkgYXNzaWduZWQgaW5cbiAgICogYHByZXBhcmVTdHJlYW1QYXJhbXNgLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3ByZXBhcmVTdHJlYW1QYXJhbXN9XG4gICAqIEBzZWUge0BsaW5rIG1vZHVsZTpjb3JlLkJhc2VMZm8jcHJvY2Vzc0ZyYW1lfVxuICAgKi9cbiAgcHJvY2Vzc0Z1bmN0aW9uKGZyYW1lKSB7XG4gICAgdGhpcy5mcmFtZSA9IGZyYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbW1vbiBsb2dpYyB0byBwZXJmb3JtIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGBwcm9jZXNzRnJhbWVgLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBtb2R1bGU6Y29yZS5CYXNlTGZvI3Byb2Nlc3NGcmFtZX1cbiAgICovXG4gIHByZXBhcmVGcmFtZSgpIHtcbiAgICBpZiAodGhpcy5fcmVpbml0ID09PSB0cnVlKSB7XG4gICAgICBjb25zdCBzdHJlYW1QYXJhbXMgPSB0aGlzLnByZXZNb2R1bGUgIT09IG51bGwgPyB0aGlzLnByZXZNb2R1bGUuc3RyZWFtUGFyYW1zIDoge307XG4gICAgICB0aGlzLmluaXRTdHJlYW0oc3RyZWFtUGFyYW1zKTtcbiAgICAgIHRoaXMuX3JlaW5pdCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3J3YXJkIHRoZSBjdXJyZW50IGBmcmFtZWAgdG8gdGhlIG5leHQgb3BlcmF0b3JzLCBpcyBjYWxsZWQgYXQgdGhlIGVuZCBvZlxuICAgKiBgcHJvY2Vzc0ZyYW1lYC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgbW9kdWxlOmNvcmUuQmFzZUxmbyNwcm9jZXNzRnJhbWV9XG4gICAqL1xuICBwcm9wYWdhdGVGcmFtZSgpIHtcbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMubmV4dE1vZHVsZXMubGVuZ3RoOyBpIDwgbDsgaSsrKVxuICAgICAgdGhpcy5uZXh0TW9kdWxlc1tpXS5wcm9jZXNzRnJhbWUodGhpcy5mcmFtZSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQmFzZUxmbztcbiIsIlxuLyoqXG4gKiBJbnRlcmZhY2UgYWRkZWQgdG8gYExmb0NvcmUgdG8gaW1wbGVtZW50IHNvdXJjZVxuICpcbiAqIFNvdXJjZSBoYXZlIHNvbWUgcmVzcG9uc2FiaWxpdHkgb24gZ3JhcGggYXMgdGhleSBtb3N0bHkgY29udHJvbCBpdHMgd2hvbGVcbiAqIGxpZmVjeWNsZS4gVGhleSBtdXN0IGltcGxlbWVudCB0aGUgc3RhcnQgYW5kIHN0b3AgbWV0aG9kIGluIG9yZGVyIHRvXG4gKiBtYWtlIHN1cmUgdGhlIGdyYXBoIGlzIGluaXRpYWxpemVkIGFuZCBzZXQgYHN0YXJ0ZWRgIHRvIHRydWUuXG4gKiBBIHNvdXJjZSBzaG91bGQgbmV2ZXIgYWNjZXB0IGFuZCBwcm9wYWdhdGUgaW5jb21taW5nIGZyYW1lcyB1bnRpbCBgc3RhcnRlZGBcbiAqIGlzIHNldCB0byBgdHJ1ZWAuXG4gKlxuICogQG5hbWUgU291cmNlTWl4aW5cbiAqIEBtZW1iZXJvZiBtb2R1bGU6Y29yZVxuICogQG1peGluXG4gKlxuICogQGV4YW1wbGVcbiAqIGNsYXNzIE15U291cmNlIGV4dGVuZHMgU291cmNlTWl4aW4oQmFzZUxmbykge31cbiAqL1xuIGNvbnN0IFNvdXJjZU1peGluID0gKHN1cGVyY2xhc3MpID0+IGNsYXNzIGV4dGVuZHMgc3VwZXJjbGFzcyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICBzdXBlciguLi5hcmdzKTtcblxuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmluaXRQcm9taXNlID0gbnVsbDtcbiAgICB0aGlzLnN0YXJ0ZWQgPSBmYWxzZTtcblxuICAgIHRoaXMuc3RhcnQgPSB0aGlzLnN0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5zdG9wID0gdGhpcy5zdG9wLmJpbmQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgZ3JhcGggYnkgY2FsbGluZyBgaW5pdE1vZHVsZWAuIFdoZW4gdGhlIHJldHVybmVkIGBQcm9taXNlYFxuICAgKiBmdWxmaWxscywgdGhlIGdyYXBoIGNhbiBiZSBjb25zaWRlcmVkIGFzIGluaXRpYWxpemVkIGFuZCBgc3RhcnRgIGNhbiBiZVxuICAgKiBjYWxsZWQgc2FmZWx5LiBJZiBgc3RhcnRgIGlzIGNhbGxlZCB3aGl0aG91dCBleHBsaWNpdCBgaW5pdGAsIGBpbml0YCBpc1xuICAgKiBtYWRlIGludGVybmFsbHksIGFjdHVhbCBzdGFydCBvZiB0aGUgZ3JhcGggaXMgdGhlbiBub3QgZ2FyYW50ZWVkIHRvIGJlXG4gICAqIHN5bmNocm9ub3VzLlxuICAgKlxuICAgKiBAbWVtYmVyb2YgbW9kdWxlOmNvcmUuU291cmNlTWl4aW5cbiAgICogQGluc3RhbmNlXG4gICAqIEBuYW1lIGluaXRcbiAgICpcbiAgICogQHJldHVybiBQcm9taXNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIHNhZmUgaW5pdGlhbGl6YXRpb24gYW5kIHN0YXJ0XG4gICAqIHNvdXJjZS5pbml0KCkudGhlbigoKSA9PiBzb3VyY2Uuc3RhcnQoKSlcbiAgICogLy8gc2FmZSBpbml0aWFsaXphdGlvbiBhbmQgc3RhcnRcbiAgICogc291cmNlLnN0YXJ0KCk7XG4gICAqL1xuICBpbml0KCkge1xuICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXRNb2R1bGUoKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMuaW5pdFN0cmVhbSgpOyAvLyB0aGlzIGlzIHN5bmNocm9ub3VzXG4gICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5pbml0UHJvbWlzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnRlcmZhY2UgbWV0aG9kIHRvIGltcGxlbWVudCB0aGF0IHN0YXJ0cyB0aGUgZ3JhcGguXG4gICAqXG4gICAqIFRoZSBtZXRob2QgbWFpbiBwdXJwb3NlIGlzIHRvIG1ha2Ugc3VyZSB0YWtlIHZlcmlmeSBpbml0aWFsaXphdGlvbiBzdGVwIGFuZFxuICAgKiBzZXQgYHN0YXJ0ZWRgIHRvIGB0cnVlYCB3aGVuIGRvbmUuXG4gICAqIFNob3VsZCBiZWhhdmUgc3luY2hyb25vdXNseSB3aGVuIGNhbGxlZCBpbnNpZGUgYGluaXQoKS50aGVuKClgIGFuZCBhc3luY1xuICAgKiBpZiBjYWxsZWQgd2l0aG91dCBpbml0IHN0ZXAuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2R1bGU6Y29yZS5Tb3VyY2VNaXhpblxuICAgKiBAaW5zdGFuY2VcbiAgICogQG5hbWUgc3RhcnRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gYmFzaWMgYHN0YXJ0YCBpbXBsZW1lbnRhdGlvblxuICAgKiBzdGFydCgpIHtcbiAgICogICBpZiAodGhpcy5pbml0aWFsaXplZCA9PT0gZmFsc2UpIHtcbiAgICogICAgIGlmICh0aGlzLmluaXRQcm9taXNlID09PSBudWxsKSAvLyBpbml0IGhhcyBub3QgeWV0IGJlZW4gY2FsbGVkXG4gICAqICAgICAgIHRoaXMuaW5pdFByb21pc2UgPSB0aGlzLmluaXQoKTtcbiAgICpcbiAgICogICAgIHRoaXMuaW5pdFByb21pc2UudGhlbih0aGlzLnN0YXJ0KTtcbiAgICogICAgIHJldHVybjtcbiAgICogICB9XG4gICAqXG4gICAqICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcbiAgICogfVxuICAgKi9cbiAgc3RhcnQoKSB7fVxuXG4gIC8qKlxuICAgKiBJbnRlcmZhY2UgbWV0aG9kIHRvIGltcGxlbWVudCB0aGF0IHN0b3BzIHRoZSBncmFwaC5cbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZHVsZTpjb3JlLlNvdXJjZU1peGluXG4gICAqIEBpbnN0YW5jZVxuICAgKiBAbmFtZSBzdG9wXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIGJhc2ljIGBzdG9wYCBpbXBsZW1lbnRhdGlvblxuICAgKiBzdG9wKCkge1xuICAgKiAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlO1xuICAgKiB9XG4gICAqL1xuICBzdG9wKCkge31cblxuICAvKipcbiAgICogVGhlIGltcGxlbWVudGF0aW9uIHNob3VsZCBuZXZlciBhbGxvdyBpbmNvbW1pbmcgZnJhbWVzXG4gICAqIGlmIGB0aGlzLnN0YXJ0ZWRgIGlzIG5vdCBgdHJ1ZWAuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2R1bGU6Y29yZS5Tb3VyY2VNaXhpblxuICAgKiBAaW5zdGFuY2VcbiAgICogQG5hbWUgcHJvY2Vzc0ZyYW1lXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBmcmFtZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBiYXNpYyBgcHJvY2Vzc0ZyYW1lYCBpbXBsZW1lbnRhdGlvblxuICAgKiBwcm9jZXNzRnJhbWUoZnJhbWUpIHtcbiAgICogICBpZiAodGhpcy5zdGFydGVkID09PSB0cnVlKSB7XG4gICAqICAgICB0aGlzLnByZXBhcmVGcmFtZSgpO1xuICAgKiAgICAgdGhpcy5wcm9jZXNzRnVuY3Rpb24oZnJhbWUpO1xuICAgKiAgICAgdGhpcy5wcm9wYWdhdGVGcmFtZSgpO1xuICAgKiAgIH1cbiAgICogfVxuICAgKi9cbiAgcHJvY2Vzc0ZyYW1lKGZyYW1lKSB7fVxufVxuXG5leHBvcnQgZGVmYXVsdCBTb3VyY2VNaXhpbjtcbiIsImV4cG9ydCBjb25zdCB2ZXJzaW9uID0gJyV2ZXJzaW9uJSc7XG5cbmV4cG9ydCB7IGRlZmF1bHQgYXMgQmFzZUxmbyB9IGZyb20gJy4vQmFzZUxmbyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIFNvdXJjZU1peGluIH0gZnJvbSAnLi9Tb3VyY2VNaXhpbic7XG4iLCJpbXBvcnQgKiBhcyBsZm8gZnJvbSAnd2F2ZXMtbGZvL2NsaWVudCc7XG5cbmNvbnN0IGZyYW1lU2l6ZSA9IDU7XG5jb25zdCBkdCA9IDAuMDI7XG5cbmNvbnN0IGV2ZW50SW4gPSBuZXcgbGZvLnNvdXJjZS5FdmVudEluKHtcbiAgZnJhbWVTaXplOiBmcmFtZVNpemUsXG4gIGZyYW1lUmF0ZTogMSAvIGR0LFxuICBmcmFtZVR5cGU6ICd2ZWN0b3InLFxufSk7XG5cbmNvbnN0IGJhckNoYXJ0ID0gbmV3IGxmby5zaW5rLkJhckNoYXJ0RGlzcGxheSh7XG4gIGNhbnZhczogJyNiYXItY2hhcnQnLFxufSk7XG5cbmV2ZW50SW4uY29ubmVjdChiYXJDaGFydCk7XG5ldmVudEluLnN0YXJ0KCk7XG5cbmNvbnN0IGRhdGEgPSBbMCwgMC4yLCAwLjQsIDAuNiwgMC44XTtcblxuKGZ1bmN0aW9uIGdlbmVyYXRlRGF0YSgpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBmcmFtZVNpemU7IGkrKylcbiAgICBkYXRhW2ldID0gKGRhdGFbaV0gKyAwLjAwMSkgJSAxO1xuXG4gIGV2ZW50SW4ucHJvY2VzcyhudWxsLCBkYXRhKTtcblxuICBzZXRUaW1lb3V0KGdlbmVyYXRlRGF0YSwgZHQgKiAxMDAwKTtcbn0oKSk7XG4iLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiY29uc3QgbWluID0gTWF0aC5taW47XG5jb25zdCBtYXggPSBNYXRoLm1heDtcblxuZnVuY3Rpb24gY2xpcCh2YWx1ZSwgbG93ZXIgPSAtSW5maW5pdHksIHVwcGVyID0gK0luZmluaXR5KSB7XG4gIHJldHVybiBtYXgobG93ZXIsIG1pbih1cHBlciwgdmFsdWUpKVxufVxuXG4vKipcbiAqIERpY3Rpb25uYXJ5IG9mIHRoZSBhdmFpbGFibGUgdHlwZXMuIEVhY2gga2V5IGNvcnJlc3BvbmQgdG8gdGhlIHR5cGUgb2YgdGhlXG4gKiBpbXBsZW1lbnRlZCBwYXJhbSB3aGlsZSB0aGUgY29ycmVzcG9uZGluZyBvYmplY3QgdmFsdWUgc2hvdWxkIHRoZVxuICoge0BsaW5rIGBwYXJhbURlZmluaXRpb25gfSBvZiB0aGUgZGVmaW5lZCB0eXBlLlxuICpcbiAqIHR5cGVkZWYge09iamVjdH0gcGFyYW1UZW1wbGF0ZXNcbiAqIEB0eXBlIHtPYmplY3Q8U3RyaW5nLCBwYXJhbVRlbXBsYXRlPn1cbiAqL1xuXG4vKipcbiAqIERlZmluaXRpb24gb2YgYSBwYXJhbWV0ZXIuIFRoZSBkZWZpbml0aW9uIHNob3VsZCBhdCBsZWFzdCBjb250YWluIHRoZSBlbnRyaWVzXG4gKiBgdHlwZWAgYW5kIGBkZWZhdWx0YC4gRXZlcnkgcGFyYW1ldGVyIGNhbiBhbHNvIGFjY2VwdCBvcHRpb25uYWwgY29uZmlndXJhdGlvblxuICogZW50cmllcyBgY29uc3RhbnRgIGFuZCBgbWV0YXNgLlxuICogQXZhaWxhYmxlIGRlZmluaXRpb25zIGFyZTpcbiAqIC0ge0BsaW5rIGJvb2xlYW5EZWZpbml0aW9ufVxuICogLSB7QGxpbmsgaW50ZWdlckRlZmluaXRpb259XG4gKiAtIHtAbGluayBmbG9hdERlZmluaXRpb259XG4gKiAtIHtAbGluayBzdHJpbmdEZWZpbml0aW9ufVxuICogLSB7QGxpbmsgZW51bURlZmluaXRpb259XG4gKlxuICogdHlwZWRlZiB7T2JqZWN0fSBwYXJhbURlZmluaXRpb25cbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSB0eXBlIC0gVHlwZSBvZiB0aGUgcGFyYW1ldGVyLlxuICogQHByb3BlcnR5IHtNaXhlZH0gZGVmYXVsdCAtIERlZmF1bHQgdmFsdWUgb2YgdGhlIHBhcmFtZXRlciBpZiBub1xuICogIGluaXRpYWxpemF0aW9uIHZhbHVlIGlzIHByb3ZpZGVkLlxuICogQHByb3BlcnR5IHtCb29sZWFufSBbY29uc3RhbnQ9ZmFsc2VdIC0gRGVmaW5lIGlmIHRoZSBwYXJhbWV0ZXIgY2FuIGJlIGNoYW5nZVxuICogIGFmdGVyIGl0cyBpbml0aWFsaXphdGlvbi5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBbbWV0YXM9bnVsbF0gLSBBbnkgdXNlciBkZWZpbmVkIGRhdGEgYXNzb2NpYXRlZCB0byB0aGVcbiAqICBwYXJhbWV0ZXIgdGhhdCBjb3VscyBiZSB1c2VmdWxsIGluIHRoZSBhcHBsaWNhdGlvbi5cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBib29sZWFuRGVmaW5pdGlvblxuICAgKiBAcHJvcGVydHkge1N0cmluZ30gW3R5cGU9J2Jvb2xlYW4nXSAtIERlZmluZSBhIGJvb2xlYW4gcGFyYW1ldGVyLlxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IGRlZmF1bHQgLSBEZWZhdWx0IHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gW2NvbnN0YW50PWZhbHNlXSAtIERlZmluZSBpZiB0aGUgcGFyYW1ldGVyIGlzIGNvbnN0YW50LlxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IFtudWxsYWJsZT1mYWxzZV0gLSBEZWZpbmUgaWYgdGhlIHBhcmFtZXRlciBpcyBudWxsYWJsZS5cbiAgICogQHByb3BlcnR5IHtPYmplY3R9IFttZXRhcz17fV0gLSBPcHRpb25uYWwgbWV0YWRhdGEgb2YgdGhlIHBhcmFtZXRlci5cbiAgICovXG4gIGJvb2xlYW46IHtcbiAgICBkZWZpbml0aW9uVGVtcGxhdGU6IFsnZGVmYXVsdCddLFxuICAgIHR5cGVDaGVja0Z1bmN0aW9uKHZhbHVlLCBkZWZpbml0aW9uLCBuYW1lKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnYm9vbGVhbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgYm9vbGVhbiBwYXJhbSBcIiR7bmFtZX1cIjogJHt2YWx1ZX1gKTtcblxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gaW50ZWdlckRlZmluaXRpb25cbiAgICogQHByb3BlcnR5IHtTdHJpbmd9IFt0eXBlPSdpbnRlZ2VyJ10gLSBEZWZpbmUgYSBib29sZWFuIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtNaXhlZH0gZGVmYXVsdCAtIERlZmF1bHQgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttaW49LUluZmluaXR5XSAtIE1pbmltdW0gdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttYXg9K0luZmluaXR5XSAtIE1heGltdW0gdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtCb29sZWFufSBbY29uc3RhbnQ9ZmFsc2VdIC0gRGVmaW5lIGlmIHRoZSBwYXJhbWV0ZXIgaXMgY29uc3RhbnQuXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gW251bGxhYmxlPWZhbHNlXSAtIERlZmluZSBpZiB0aGUgcGFyYW1ldGVyIGlzIG51bGxhYmxlLlxuICAgKiBAcHJvcGVydHkge09iamVjdH0gW21ldGFzPXt9XSAtIE9wdGlvbm5hbCBtZXRhZGF0YSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKi9cbiAgaW50ZWdlcjoge1xuICAgIGRlZmluaXRpb25UZW1wbGF0ZTogWydkZWZhdWx0J10sXG4gICAgdHlwZUNoZWNrRnVuY3Rpb24odmFsdWUsIGRlZmluaXRpb24sIG5hbWUpIHtcbiAgICAgIGlmICghKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHZhbHVlIGZvciBpbnRlZ2VyIHBhcmFtIFwiJHtuYW1lfVwiOiAke3ZhbHVlfWApO1xuXG4gICAgICByZXR1cm4gY2xpcCh2YWx1ZSwgZGVmaW5pdGlvbi5taW4sIGRlZmluaXRpb24ubWF4KTtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IGZsb2F0RGVmaW5pdGlvblxuICAgKiBAcHJvcGVydHkge1N0cmluZ30gW3R5cGU9J2Zsb2F0J10gLSBEZWZpbmUgYSBib29sZWFuIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtNaXhlZH0gZGVmYXVsdCAtIERlZmF1bHQgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttaW49LUluZmluaXR5XSAtIE1pbmltdW0gdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtOdW1iZXJ9IFttYXg9K0luZmluaXR5XSAtIE1heGltdW0gdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtCb29sZWFufSBbY29uc3RhbnQ9ZmFsc2VdIC0gRGVmaW5lIGlmIHRoZSBwYXJhbWV0ZXIgaXMgY29uc3RhbnQuXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gW251bGxhYmxlPWZhbHNlXSAtIERlZmluZSBpZiB0aGUgcGFyYW1ldGVyIGlzIG51bGxhYmxlLlxuICAgKiBAcHJvcGVydHkge09iamVjdH0gW21ldGFzPXt9XSAtIE9wdGlvbm5hbCBtZXRhZGF0YSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKi9cbiAgZmxvYXQ6IHtcbiAgICBkZWZpbml0aW9uVGVtcGxhdGU6IFsnZGVmYXVsdCddLFxuICAgIHR5cGVDaGVja0Z1bmN0aW9uKHZhbHVlLCBkZWZpbml0aW9uLCBuYW1lKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fMKgdmFsdWUgIT09IHZhbHVlKSAvLyByZWplY3QgTmFOXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgZmxvYXQgcGFyYW0gXCIke25hbWV9XCI6ICR7dmFsdWV9YCk7XG5cbiAgICAgIHJldHVybiBjbGlwKHZhbHVlLCBkZWZpbml0aW9uLm1pbiwgZGVmaW5pdGlvbi5tYXgpO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gc3RyaW5nRGVmaW5pdGlvblxuICAgKiBAcHJvcGVydHkge1N0cmluZ30gW3R5cGU9J3N0cmluZyddIC0gRGVmaW5lIGEgYm9vbGVhbiBwYXJhbWV0ZXIuXG4gICAqIEBwcm9wZXJ0eSB7TWl4ZWR9IGRlZmF1bHQgLSBEZWZhdWx0IHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gW2NvbnN0YW50PWZhbHNlXSAtIERlZmluZSBpZiB0aGUgcGFyYW1ldGVyIGlzIGNvbnN0YW50LlxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IFtudWxsYWJsZT1mYWxzZV0gLSBEZWZpbmUgaWYgdGhlIHBhcmFtZXRlciBpcyBudWxsYWJsZS5cbiAgICogQHByb3BlcnR5IHtPYmplY3R9IFttZXRhcz17fV0gLSBPcHRpb25uYWwgbWV0YWRhdGEgb2YgdGhlIHBhcmFtZXRlci5cbiAgICovXG4gIHN0cmluZzoge1xuICAgIGRlZmluaXRpb25UZW1wbGF0ZTogWydkZWZhdWx0J10sXG4gICAgdHlwZUNoZWNrRnVuY3Rpb24odmFsdWUsIGRlZmluaXRpb24sIG5hbWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFsdWUgZm9yIHN0cmluZyBwYXJhbSBcIiR7bmFtZX1cIjogJHt2YWx1ZX1gKTtcblxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gZW51bURlZmluaXRpb25cbiAgICogQHByb3BlcnR5IHtTdHJpbmd9IFt0eXBlPSdlbnVtJ10gLSBEZWZpbmUgYSBib29sZWFuIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtNaXhlZH0gZGVmYXVsdCAtIERlZmF1bHQgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHByb3BlcnR5IHtBcnJheX0gbGlzdCAtIFBvc3NpYmxlIHZhbHVlcyBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IFtjb25zdGFudD1mYWxzZV0gLSBEZWZpbmUgaWYgdGhlIHBhcmFtZXRlciBpcyBjb25zdGFudC5cbiAgICogQHByb3BlcnR5IHtCb29sZWFufSBbbnVsbGFibGU9ZmFsc2VdIC0gRGVmaW5lIGlmIHRoZSBwYXJhbWV0ZXIgaXMgbnVsbGFibGUuXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBbbWV0YXM9e31dIC0gT3B0aW9ubmFsIG1ldGFkYXRhIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBlbnVtOiB7XG4gICAgZGVmaW5pdGlvblRlbXBsYXRlOiBbJ2RlZmF1bHQnLCAnbGlzdCddLFxuICAgIHR5cGVDaGVja0Z1bmN0aW9uKHZhbHVlLCBkZWZpbml0aW9uLCBuYW1lKSB7XG4gICAgICBpZiAoZGVmaW5pdGlvbi5saXN0LmluZGV4T2YodmFsdWUpID09PSAtMSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHZhbHVlIGZvciBlbnVtIHBhcmFtIFwiJHtuYW1lfVwiOiAke3ZhbHVlfWApO1xuXG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBhbnlEZWZpbml0aW9uXG4gICAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBbdHlwZT0nZW51bSddIC0gRGVmaW5lIGEgcGFyYW1ldGVyIG9mIGFueSB0eXBlLlxuICAgKiBAcHJvcGVydHkge01peGVkfSBkZWZhdWx0IC0gRGVmYXVsdCB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IFtjb25zdGFudD1mYWxzZV0gLSBEZWZpbmUgaWYgdGhlIHBhcmFtZXRlciBpcyBjb25zdGFudC5cbiAgICogQHByb3BlcnR5IHtCb29sZWFufSBbbnVsbGFibGU9ZmFsc2VdIC0gRGVmaW5lIGlmIHRoZSBwYXJhbWV0ZXIgaXMgbnVsbGFibGUuXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBbbWV0YXM9e31dIC0gT3B0aW9ubmFsIG1ldGFkYXRhIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBhbnk6IHtcbiAgICBkZWZpbml0aW9uVGVtcGxhdGU6IFsnZGVmYXVsdCddLFxuICAgIHR5cGVDaGVja0Z1bmN0aW9uKHZhbHVlLCBkZWZpbml0aW9uLCBuYW1lKSB7XG4gICAgICAvLyBubyBjaGVjayBhcyBpdCBjYW4gaGF2ZSBhbnkgdHlwZS4uLlxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuIiwiaW1wb3J0IHBhcmFtVGVtcGxhdGVzIGZyb20gJy4vcGFyYW1UZW1wbGF0ZXMnO1xuXG4vKipcbiAqIEdlbmVyaWMgY2xhc3MgZm9yIHR5cGVkIHBhcmFtZXRlcnMuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBOYW1lIG9mIHRoZSBwYXJhbWV0ZXIuXG4gKiBAcGFyYW0ge0FycmF5fSBkZWZpbml0aW9uVGVtcGxhdGUgLSBMaXN0IG9mIG1hbmRhdG9yeSBrZXlzIGluIHRoZSBwYXJhbVxuICogIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSB0eXBlQ2hlY2tGdW5jdGlvbiAtIEZ1bmN0aW9uIHRvIGJlIHVzZWQgaW4gb3JkZXIgdG8gY2hlY2tcbiAqICB0aGUgdmFsdWUgYWdhaW5zdCB0aGUgcGFyYW0gZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7T2JqZWN0fSBkZWZpbml0aW9uIC0gRGVmaW5pdGlvbiBvZiB0aGUgcGFyYW1ldGVyLlxuICogQHBhcmFtIHtNaXhlZH0gdmFsdWUgLSBWYWx1ZSBvZiB0aGUgcGFyYW1ldGVyLlxuICogQHByaXZhdGVcbiAqL1xuY2xhc3MgUGFyYW0ge1xuICBjb25zdHJ1Y3RvcihuYW1lLCBkZWZpbml0aW9uVGVtcGxhdGUsIHR5cGVDaGVja0Z1bmN0aW9uLCBkZWZpbml0aW9uLCB2YWx1ZSkge1xuICAgIGRlZmluaXRpb25UZW1wbGF0ZS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgaWYgKGRlZmluaXRpb24uaGFzT3duUHJvcGVydHkoa2V5KSA9PT0gZmFsc2UpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBkZWZpbml0aW9uIGZvciBwYXJhbSBcIiR7bmFtZX1cIiwgJHtrZXl9IGlzIG5vdCBkZWZpbmVkYCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMudHlwZSA9IGRlZmluaXRpb24udHlwZTtcbiAgICB0aGlzLmRlZmluaXRpb24gPSBkZWZpbml0aW9uO1xuXG4gICAgaWYgKHRoaXMuZGVmaW5pdGlvbi5udWxsYWJsZSA9PT0gdHJ1ZSAmJiB2YWx1ZSA9PT0gbnVsbClcbiAgICAgIHRoaXMudmFsdWUgPSBudWxsO1xuICAgIGVsc2VcbiAgICAgIHRoaXMudmFsdWUgPSB0eXBlQ2hlY2tGdW5jdGlvbih2YWx1ZSwgZGVmaW5pdGlvbiwgbmFtZSk7XG4gICAgdGhpcy5fdHlwZUNoZWNrRnVuY3Rpb24gPSB0eXBlQ2hlY2tGdW5jdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHZhbHVlLlxuICAgKiBAcmV0dXJuIHtNaXhlZH1cbiAgICovXG4gIGdldFZhbHVlKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgY3VycmVudCB2YWx1ZS5cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWUgLSBOZXcgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gLSBgdHJ1ZWAgaWYgdGhlIHBhcmFtIGhhcyBiZWVuIHVwZGF0ZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgKiAgKGUuZy4gaWYgdGhlIHBhcmFtZXRlciBhbHJlYWR5IGhhZCB0aGlzIHZhbHVlKS5cbiAgICovXG4gIHNldFZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHRoaXMuZGVmaW5pdGlvbi5jb25zdGFudCA9PT0gdHJ1ZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhc3NpZ25lbWVudCB0byBjb25zdGFudCBwYXJhbSBcIiR7dGhpcy5uYW1lfVwiYCk7XG5cbiAgICBpZiAoISh0aGlzLmRlZmluaXRpb24ubnVsbGFibGUgPT09IHRydWUgJiYgdmFsdWUgPT09IG51bGwpKVxuICAgICAgdmFsdWUgPSB0aGlzLl90eXBlQ2hlY2tGdW5jdGlvbih2YWx1ZSwgdGhpcy5kZWZpbml0aW9uLCB0aGlzLm5hbWUpO1xuXG4gICAgaWYgKHRoaXMudmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuXG4vKipcbiAqIEJhZyBvZiBwYXJhbWV0ZXJzLiBNYWluIGludGVyZmFjZSBvZiB0aGUgbGlicmFyeVxuICovXG5jbGFzcyBQYXJhbWV0ZXJCYWcge1xuICBjb25zdHJ1Y3RvcihwYXJhbXMsIGRlZmluaXRpb25zKSB7XG4gICAgLyoqXG4gICAgICogTGlzdCBvZiBwYXJhbWV0ZXJzLlxuICAgICAqXG4gICAgICogQHR5cGUge09iamVjdDxTdHJpbmcsIFBhcmFtPn1cbiAgICAgKiBAbmFtZSBfcGFyYW1zXG4gICAgICogQG1lbWJlcm9mIFBhcmFtZXRlckJhZ1xuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fcGFyYW1zID0gcGFyYW1zO1xuXG4gICAgLyoqXG4gICAgICogTGlzdCBvZiBkZWZpbml0aW9ucyB3aXRoIGluaXQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge09iamVjdDxTdHJpbmcsIHBhcmFtRGVmaW5pdGlvbj59XG4gICAgICogQG5hbWUgX2RlZmluaXRpb25zXG4gICAgICogQG1lbWJlcm9mIFBhcmFtZXRlckJhZ1xuICAgICAqIEBpbnN0YW5jZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5fZGVmaW5pdGlvbnMgPSBkZWZpbml0aW9ucztcblxuICAgIC8qKlxuICAgICAqIExpc3Qgb2YgZ2xvYmFsIGxpc3RlbmVycy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtTZXR9XG4gICAgICogQG5hbWUgX2dsb2JhbExpc3RlbmVyc1xuICAgICAqIEBtZW1iZXJvZiBQYXJhbWV0ZXJCYWdcbiAgICAgKiBAaW5zdGFuY2VcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX2dsb2JhbExpc3RlbmVycyA9IG5ldyBTZXQoKTtcblxuICAgIC8qKlxuICAgICAqIExpc3Qgb2YgcGFyYW1zIGxpc3RlbmVycy5cbiAgICAgKlxuICAgICAqIEB0eXBlIHtPYmplY3Q8U3RyaW5nLCBTZXQ+fVxuICAgICAqIEBuYW1lIF9wYXJhbXNMaXN0ZW5lcnNcbiAgICAgKiBAbWVtYmVyb2YgUGFyYW1ldGVyQmFnXG4gICAgICogQGluc3RhbmNlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLl9wYXJhbXNMaXN0ZW5lcnMgPSB7fTtcblxuICAgIC8vIGluaXRpYWxpemUgZW1wdHkgU2V0IGZvciBlYWNoIHBhcmFtXG4gICAgZm9yIChsZXQgbmFtZSBpbiBwYXJhbXMpXG4gICAgICB0aGlzLl9wYXJhbXNMaXN0ZW5lcnNbbmFtZV0gPSBuZXcgU2V0KCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBnaXZlbiBkZWZpbml0aW9ucyBhbG9uZyB3aXRoIHRoZSBpbml0aWFsaXphdGlvbiB2YWx1ZXMuXG4gICAqXG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIGdldERlZmluaXRpb25zKG5hbWUgPSBudWxsKSB7XG4gICAgaWYgKG5hbWUgIT09IG51bGwpXG4gICAgICByZXR1cm4gdGhpcy5fZGVmaW5pdGlvbnNbbmFtZV07XG4gICAgZWxzZVxuICAgICAgcmV0dXJuIHRoaXMuX2RlZmluaXRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdmFsdWUgb2YgdGhlIGdpdmVuIHBhcmFtZXRlci5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBOYW1lIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqIEByZXR1cm4ge01peGVkfSAtIFZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBnZXQobmFtZSkge1xuICAgIGlmICghdGhpcy5fcGFyYW1zW25hbWVdKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVhZCBwcm9wZXJ0eSB2YWx1ZSBvZiB1bmRlZmluZWQgcGFyYW1ldGVyIFwiJHtuYW1lfVwiYCk7XG5cbiAgICByZXR1cm4gdGhpcy5fcGFyYW1zW25hbWVdLnZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgdmFsdWUgb2YgYSBwYXJhbWV0ZXIuIElmIHRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyIGlzIHVwZGF0ZWRcbiAgICogKGFrYSBpZiBwcmV2aW91cyB2YWx1ZSBpcyBkaWZmZXJlbnQgZnJvbSBuZXcgdmFsdWUpIGFsbCByZWdpc3RlcmVkXG4gICAqIGNhbGxiYWNrcyBhcmUgcmVnaXN0ZXJlZC5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBOYW1lIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIC0gVmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHJldHVybiB7TWl4ZWR9IC0gTmV3IHZhbHVlIG9mIHRoZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBzZXQobmFtZSwgdmFsdWUpIHtcbiAgICBjb25zdCBwYXJhbSA9IHRoaXMuX3BhcmFtc1tuYW1lXTtcbiAgICBjb25zdCB1cGRhdGVkID0gcGFyYW0uc2V0VmFsdWUodmFsdWUpO1xuICAgIHZhbHVlID0gcGFyYW0uZ2V0VmFsdWUoKTtcblxuICAgIGlmICh1cGRhdGVkKSB7XG4gICAgICBjb25zdCBtZXRhcyA9IHBhcmFtLmRlZmluaXRpb24ubWV0YXM7XG4gICAgICAvLyB0cmlnZ2VyIGdsb2JhbCBsaXN0ZW5lcnNcbiAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIHRoaXMuX2dsb2JhbExpc3RlbmVycylcbiAgICAgICAgbGlzdGVuZXIobmFtZSwgdmFsdWUsIG1ldGFzKTtcblxuICAgICAgLy8gdHJpZ2dlciBwYXJhbSBsaXN0ZW5lcnNcbiAgICAgIGZvciAobGV0IGxpc3RlbmVyIG9mIHRoaXMuX3BhcmFtc0xpc3RlbmVyc1tuYW1lXSlcbiAgICAgICAgbGlzdGVuZXIodmFsdWUsIG1ldGFzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lIGlmIHRoZSBgbmFtZWAgcGFyYW1ldGVyIGV4aXN0cyBvciBub3QuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gTmFtZSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaGFzKG5hbWUpIHtcbiAgICByZXR1cm4gKHRoaXMuX3BhcmFtc1tuYW1lXSkgPyB0cnVlIDogZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgYSBwYXJhbWV0ZXIgdG8gaXRzIGluaXQgdmFsdWUuIFJlc2V0IGFsbCBwYXJhbWV0ZXJzIGlmIG5vIGFyZ3VtZW50LlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gW25hbWU9bnVsbF0gLSBOYW1lIG9mIHRoZSBwYXJhbWV0ZXIgdG8gcmVzZXQuXG4gICAqL1xuICByZXNldChuYW1lID0gbnVsbCkge1xuICAgIGlmIChuYW1lICE9PSBudWxsKVxuICAgICAgdGhpcy5zZXQobmFtZSwgcGFyYW0uZGVmaW5pdGlvbi5pbml0VmFsdWUpO1xuICAgIGVsc2VcbiAgICAgIE9iamVjdC5rZXlzKHRoaXMuX3BhcmFtcykuZm9yRWFjaCgobmFtZSkgPT4gdGhpcy5yZXNldChuYW1lKSk7XG4gIH1cblxuICAvKipcbiAgICogQGNhbGxiYWNrIFBhcmFtZXRlckJhZ35saXN0ZW5lckNhbGxiYWNrXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gUGFyYW1ldGVyIG5hbWUuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIC0gVXBkYXRlZCB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0ge09iamVjdH0gW21ldGE9XSAtIEdpdmVuIG1ldGEgZGF0YSBvZiB0aGUgcGFyYW1ldGVyLlxuICAgKi9cblxuICAvKipcbiAgICogQWRkIGxpc3RlbmVyIHRvIGFsbCBwYXJhbSB1cGRhdGVzLlxuICAgKlxuICAgKiBAcGFyYW0ge1BhcmFtZXRlckJhZ35saXN0ZW5lckNhbGxhY2t9IGNhbGxiYWNrIC0gTGlzdGVuZXIgdG8gcmVnaXN0ZXIuXG4gICAqL1xuICBhZGRMaXN0ZW5lcihjYWxsYmFjaykge1xuICAgIHRoaXMuX2dsb2JhbExpc3RlbmVycy5hZGQoY2FsbGJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBsaXN0ZW5lciBmcm9tIGFsbCBwYXJhbSBjaGFuZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0ge1BhcmFtZXRlckJhZ35saXN0ZW5lckNhbGxhY2t9IGNhbGxiYWNrIC0gTGlzdGVuZXIgdG8gcmVtb3ZlLiBJZlxuICAgKiAgYG51bGxgIHJlbW92ZSBhbGwgbGlzdGVuZXJzLlxuICAgKi9cbiAgcmVtb3ZlTGlzdGVuZXIoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgaWYgKGNhbGxiYWNrID09PSBudWxsKVxuICAgICAgdGhpcy5fZ2xvYmFsTGlzdGVuZXJzLmNsZWFyKCk7XG4gICAgZWxzZVxuICAgICAgdGhpcy5fZ2xvYmFsTGlzdGVuZXJzLmRlbGV0ZShjYWxsYmFjayk7XG4gIH1cblxuICAvKipcbiAgICogQGNhbGxiYWNrIFBhcmFtZXRlckJhZ35wYXJhbUxpc3RlbmVyQ2FsbGFja1xuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZSAtIFVwZGF0ZWQgdmFsdWUgb2YgdGhlIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIHtPYmplY3R9IFttZXRhPV0gLSBHaXZlbiBtZXRhIGRhdGEgb2YgdGhlIHBhcmFtZXRlci5cbiAgICovXG5cbiAgLyoqXG4gICAqIEFkZCBsaXN0ZW5lciB0byBhIGdpdmVuIHBhcmFtIHVwZGF0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gUGFyYW1ldGVyIG5hbWUuXG4gICAqIEBwYXJhbSB7UGFyYW1ldGVyQmFnfnBhcmFtTGlzdGVuZXJDYWxsYWNrfSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGFwcGx5XG4gICAqICB3aGVuIHRoZSB2YWx1ZSBvZiB0aGUgcGFyYW1ldGVyIGNoYW5nZXMuXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gW3RyaWdnZXI9ZmFsc2VdIC0gRXhlY3V0ZSB0aGUgY2FsbGJhY2sgaW1tZWRpYXRlbHkgd2l0aFxuICAgKiAgY3VycmVudCBwYXJhbWV0ZXIgdmFsdWUuXG4gICAqL1xuICBhZGRQYXJhbUxpc3RlbmVyKG5hbWUsIGNhbGxiYWNrLCB0cmlnZ2VyID0gZmFsc2UpIHtcbiAgICB0aGlzLl9wYXJhbXNMaXN0ZW5lcnNbbmFtZV0uYWRkKGNhbGxiYWNrKTtcblxuICAgIGlmICh0cmlnZ2VyKSB7XG4gICAgICBjb25zdCBwYXJhbSA9IHRoaXMuX3BhcmFtc1tuYW1lXTtcbiAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW0uZ2V0VmFsdWUoKTtcbiAgICAgIGNvbnN0IG1ldGFzID0gcGFyYW0uZGVmaW5pdGlvbi5tZXRhcztcbiAgICAgIGNhbGxiYWNrKHZhbHVlLCBtZXRhcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBsaXN0ZW5lciBmcm9tIGEgZ2l2ZW4gcGFyYW0gdXBkYXRlcy5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBQYXJhbWV0ZXIgbmFtZS5cbiAgICogQHBhcmFtIHtQYXJhbWV0ZXJCYWd+cGFyYW1MaXN0ZW5lckNhbGxhY2t9IGNhbGxiYWNrIC0gTGlzdGVuZXIgdG8gcmVtb3ZlLlxuICAgKiAgSWYgYG51bGxgIHJlbW92ZSBhbGwgbGlzdGVuZXJzLlxuICAgKi9cbiAgcmVtb3ZlUGFyYW1MaXN0ZW5lcihuYW1lLCBjYWxsYmFjayA9IG51bGwpIHtcbiAgICBpZiAoY2FsbGJhY2sgPT09IG51bGwpXG4gICAgICB0aGlzLl9wYXJhbXNMaXN0ZW5lcnNbbmFtZV0uY2xlYXIoKTtcbiAgICBlbHNlXG4gICAgICB0aGlzLl9wYXJhbXNMaXN0ZW5lcnNbbmFtZV0uZGVsZXRlKGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vKipcbiAqIEZhY3RvcnkgZm9yIHRoZSBgUGFyYW1ldGVyQmFnYCBjbGFzcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdDxTdHJpbmcsIHBhcmFtRGVmaW5pdGlvbj59IGRlZmluaXRpb25zIC0gT2JqZWN0IGRlc2NyaWJpbmcgdGhlXG4gKiAgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7T2JqZWN0PFN0cmluZywgTWl4ZWQ+fSB2YWx1ZXMgLSBJbml0aWFsaXphdGlvbiB2YWx1ZXMgZm9yIHRoZVxuICogIHBhcmFtZXRlcnMuXG4gKiBAcmV0dXJuIHtQYXJhbWV0ZXJCYWd9XG4gKi9cbmZ1bmN0aW9uIHBhcmFtZXRlcnMoZGVmaW5pdGlvbnMsIHZhbHVlcyA9IHt9KSB7XG4gIGNvbnN0IHBhcmFtcyA9IHt9O1xuXG4gIGZvciAobGV0IG5hbWUgaW4gdmFsdWVzKSB7XG4gICAgaWYgKGRlZmluaXRpb25zLmhhc093blByb3BlcnR5KG5hbWUpID09PSBmYWxzZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBwYXJhbSBcIiR7bmFtZX1cImApO1xuICB9XG5cbiAgZm9yIChsZXQgbmFtZSBpbiBkZWZpbml0aW9ucykge1xuICAgIGlmIChwYXJhbXMuaGFzT3duUHJvcGVydHkobmFtZSkgPT09IHRydWUpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFBhcmFtZXRlciBcIiR7bmFtZX1cIiBhbHJlYWR5IGRlZmluZWRgKTtcblxuICAgIGNvbnN0IGRlZmluaXRpb24gPSBkZWZpbml0aW9uc1tuYW1lXTtcblxuICAgIGlmICghcGFyYW1UZW1wbGF0ZXNbZGVmaW5pdGlvbi50eXBlXSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBwYXJhbSB0eXBlIFwiJHtkZWZpbml0aW9uLnR5cGV9XCJgKTtcblxuICAgIGNvbnN0IHtcbiAgICAgIGRlZmluaXRpb25UZW1wbGF0ZSxcbiAgICAgIHR5cGVDaGVja0Z1bmN0aW9uXG4gICAgfSA9IHBhcmFtVGVtcGxhdGVzW2RlZmluaXRpb24udHlwZV07XG5cbiAgICBsZXQgdmFsdWU7XG5cbiAgICBpZiAodmFsdWVzLmhhc093blByb3BlcnR5KG5hbWUpID09PSB0cnVlKVxuICAgICAgdmFsdWUgPSB2YWx1ZXNbbmFtZV07XG4gICAgZWxzZVxuICAgICAgdmFsdWUgPSBkZWZpbml0aW9uLmRlZmF1bHQ7XG5cbiAgICAvLyBzdG9yZSBpbml0IHZhbHVlIGluIGRlZmluaXRpb25cbiAgICBkZWZpbml0aW9uLmluaXRWYWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCF0eXBlQ2hlY2tGdW5jdGlvbiB8fMKgIWRlZmluaXRpb25UZW1wbGF0ZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwYXJhbSB0eXBlIGRlZmluaXRpb24gXCIke2RlZmluaXRpb24udHlwZX1cImApO1xuXG4gICAgcGFyYW1zW25hbWVdID0gbmV3IFBhcmFtKG5hbWUsIGRlZmluaXRpb25UZW1wbGF0ZSwgdHlwZUNoZWNrRnVuY3Rpb24sIGRlZmluaXRpb24sIHZhbHVlKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgUGFyYW1ldGVyQmFnKHBhcmFtcywgZGVmaW5pdGlvbnMpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgbmV3IHR5cGUgZm9yIHRoZSBgcGFyYW1ldGVyc2AgZmFjdG9yeS5cbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlTmFtZSAtIFZhbHVlIHRoYXQgd2lsbCBiZSBhdmFpbGFibGUgYXMgdGhlIGB0eXBlYCBvZiBhXG4gKiAgcGFyYW0gZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7cGFyYW1ldGVyRGVmaW5pdGlvbn0gcGFyYW1ldGVyRGVmaW5pdGlvbiAtIE9iamVjdCBkZXNjcmliaW5nIHRoZVxuICogIHBhcmFtZXRlci5cbiAqL1xucGFyYW1ldGVycy5kZWZpbmVUeXBlID0gZnVuY3Rpb24odHlwZU5hbWUsIHBhcmFtZXRlckRlZmluaXRpb24pIHtcbiAgcGFyYW1UZW1wbGF0ZXNbdHlwZU5hbWVdID0gcGFyYW1ldGVyRGVmaW5pdGlvbjtcbn1cblxuZXhwb3J0IGRlZmF1bHQgcGFyYW1ldGVycztcbiIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9qc29uL3N0cmluZ2lmeVwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9tYXRoL2xvZzEwXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL251bWJlci9pcy1maW5pdGVcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnblwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvY3JlYXRlXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL29iamVjdC9kZWZpbmUtcHJvcGVydHlcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvclwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZlwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07IiwibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL3N5bWJvbFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9zeW1ib2wvaXRlcmF0b3JcIiksIF9fZXNNb2R1bGU6IHRydWUgfTsiLCJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKGluc3RhbmNlLCBDb25zdHJ1Y3Rvcikge1xuICBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7XG4gIH1cbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3QvZGVmaW5lLXByb3BlcnR5XCIpO1xuXG52YXIgX2RlZmluZVByb3BlcnR5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2RlZmluZVByb3BlcnR5KTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldO1xuICAgICAgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlO1xuICAgICAgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlO1xuICAgICAgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTtcbiAgICAgICgwLCBfZGVmaW5lUHJvcGVydHkyLmRlZmF1bHQpKHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7XG4gICAgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTtcbiAgICBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH07XG59KCk7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3QvZGVmaW5lLXByb3BlcnR5XCIpO1xuXG52YXIgX2RlZmluZVByb3BlcnR5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX2RlZmluZVByb3BlcnR5KTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG9iaikge1xuICAgICgwLCBfZGVmaW5lUHJvcGVydHkyLmRlZmF1bHQpKG9iaiwga2V5LCB7XG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgd3JpdGFibGU6IHRydWVcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBvYmpba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfZ2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3QvZ2V0LXByb3RvdHlwZS1vZlwiKTtcblxudmFyIF9nZXRQcm90b3R5cGVPZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9nZXRQcm90b3R5cGVPZik7XG5cbnZhciBfZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2dldC1vd24tcHJvcGVydHktZGVzY3JpcHRvclwiKTtcblxudmFyIF9nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gZ2V0KG9iamVjdCwgcHJvcGVydHksIHJlY2VpdmVyKSB7XG4gIGlmIChvYmplY3QgPT09IG51bGwpIG9iamVjdCA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcbiAgdmFyIGRlc2MgPSAoMCwgX2dldE93blByb3BlcnR5RGVzY3JpcHRvcjIuZGVmYXVsdCkob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgaWYgKGRlc2MgPT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBwYXJlbnQgPSAoMCwgX2dldFByb3RvdHlwZU9mMi5kZWZhdWx0KShvYmplY3QpO1xuXG4gICAgaWYgKHBhcmVudCA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdldChwYXJlbnQsIHByb3BlcnR5LCByZWNlaXZlcik7XG4gICAgfVxuICB9IGVsc2UgaWYgKFwidmFsdWVcIiBpbiBkZXNjKSB7XG4gICAgcmV0dXJuIGRlc2MudmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGdldHRlciA9IGRlc2MuZ2V0O1xuXG4gICAgaWYgKGdldHRlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiBnZXR0ZXIuY2FsbChyZWNlaXZlcik7XG4gIH1cbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKFwiLi4vY29yZS1qcy9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiKTtcblxudmFyIF9zZXRQcm90b3R5cGVPZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9zZXRQcm90b3R5cGVPZik7XG5cbnZhciBfY3JlYXRlID0gcmVxdWlyZShcIi4uL2NvcmUtanMvb2JqZWN0L2NyZWF0ZVwiKTtcblxudmFyIF9jcmVhdGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfY3JlYXRlKTtcblxudmFyIF90eXBlb2YyID0gcmVxdWlyZShcIi4uL2hlbHBlcnMvdHlwZW9mXCIpO1xuXG52YXIgX3R5cGVvZjMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF90eXBlb2YyKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKHN1YkNsYXNzLCBzdXBlckNsYXNzKSB7XG4gIGlmICh0eXBlb2Ygc3VwZXJDbGFzcyAhPT0gXCJmdW5jdGlvblwiICYmIHN1cGVyQ2xhc3MgIT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArICh0eXBlb2Ygc3VwZXJDbGFzcyA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiAoMCwgX3R5cGVvZjMuZGVmYXVsdCkoc3VwZXJDbGFzcykpKTtcbiAgfVxuXG4gIHN1YkNsYXNzLnByb3RvdHlwZSA9ICgwLCBfY3JlYXRlMi5kZWZhdWx0KShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7XG4gICAgY29uc3RydWN0b3I6IHtcbiAgICAgIHZhbHVlOiBzdWJDbGFzcyxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9XG4gIH0pO1xuICBpZiAoc3VwZXJDbGFzcykgX3NldFByb3RvdHlwZU9mMi5kZWZhdWx0ID8gKDAsIF9zZXRQcm90b3R5cGVPZjIuZGVmYXVsdCkoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzcztcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbnZhciBfdHlwZW9mMiA9IHJlcXVpcmUoXCIuLi9oZWxwZXJzL3R5cGVvZlwiKTtcblxudmFyIF90eXBlb2YzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdHlwZW9mMik7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uIChzZWxmLCBjYWxsKSB7XG4gIGlmICghc2VsZikge1xuICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTtcbiAgfVxuXG4gIHJldHVybiBjYWxsICYmICgodHlwZW9mIGNhbGwgPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogKDAsIF90eXBlb2YzLmRlZmF1bHQpKGNhbGwpKSA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgY2FsbCA9PT0gXCJmdW5jdGlvblwiKSA/IGNhbGwgOiBzZWxmO1xufTsiLCJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9pdGVyYXRvciA9IHJlcXVpcmUoXCIuLi9jb3JlLWpzL3N5bWJvbC9pdGVyYXRvclwiKTtcblxudmFyIF9pdGVyYXRvcjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9pdGVyYXRvcik7XG5cbnZhciBfc3ltYm9sID0gcmVxdWlyZShcIi4uL2NvcmUtanMvc3ltYm9sXCIpO1xuXG52YXIgX3N5bWJvbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9zeW1ib2wpO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBfc3ltYm9sMi5kZWZhdWx0ID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIF9pdGVyYXRvcjIuZGVmYXVsdCA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH0gOiBmdW5jdGlvbiAob2JqKSB7IHJldHVybiBvYmogJiYgdHlwZW9mIF9zeW1ib2wyLmRlZmF1bHQgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IF9zeW1ib2wyLmRlZmF1bHQgJiYgb2JqICE9PSBfc3ltYm9sMi5kZWZhdWx0LnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqOyB9O1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5leHBvcnRzLmRlZmF1bHQgPSB0eXBlb2YgX3N5bWJvbDIuZGVmYXVsdCA9PT0gXCJmdW5jdGlvblwiICYmIF90eXBlb2YoX2l0ZXJhdG9yMi5kZWZhdWx0KSA9PT0gXCJzeW1ib2xcIiA/IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuIHR5cGVvZiBvYmogPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihvYmopO1xufSA6IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuIG9iaiAmJiB0eXBlb2YgX3N5bWJvbDIuZGVmYXVsdCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gX3N5bWJvbDIuZGVmYXVsdCAmJiBvYmogIT09IF9zeW1ib2wyLmRlZmF1bHQucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmogPT09IFwidW5kZWZpbmVkXCIgPyBcInVuZGVmaW5lZFwiIDogX3R5cGVvZihvYmopO1xufTsiLCJ2YXIgY29yZSA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKTtcbnZhciAkSlNPTiA9IGNvcmUuSlNPTiB8fCAoY29yZS5KU09OID0geyBzdHJpbmdpZnk6IEpTT04uc3RyaW5naWZ5IH0pO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHJpbmdpZnkoaXQpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICByZXR1cm4gJEpTT04uc3RyaW5naWZ5LmFwcGx5KCRKU09OLCBhcmd1bWVudHMpO1xufTtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm1hdGgubG9nMTAnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk1hdGgubG9nMTA7XG4iLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5udW1iZXIuaXMtZmluaXRlJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5OdW1iZXIuaXNGaW5pdGU7XG4iLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5vYmplY3QuYXNzaWduJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuYXNzaWduO1xuIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LmNyZWF0ZScpO1xudmFyICRPYmplY3QgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuT2JqZWN0O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGUoUCwgRCkge1xuICByZXR1cm4gJE9iamVjdC5jcmVhdGUoUCwgRCk7XG59O1xuIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYub2JqZWN0LmRlZmluZS1wcm9wZXJ0eScpO1xudmFyICRPYmplY3QgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuT2JqZWN0O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShpdCwga2V5LCBkZXNjKSB7XG4gIHJldHVybiAkT2JqZWN0LmRlZmluZVByb3BlcnR5KGl0LCBrZXksIGRlc2MpO1xufTtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtb3duLXByb3BlcnR5LWRlc2NyaXB0b3InKTtcbnZhciAkT2JqZWN0ID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdDtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpIHtcbiAgcmV0dXJuICRPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGl0LCBrZXkpO1xufTtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5nZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3QuZ2V0UHJvdG90eXBlT2Y7XG4iLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5vYmplY3Quc2V0LXByb3RvdHlwZS1vZicpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuT2JqZWN0LnNldFByb3RvdHlwZU9mO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnByb21pc2UnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM3LnByb21pc2UuZmluYWxseScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcucHJvbWlzZS50cnknKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlByb21pc2U7XG4iLCJyZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5zeW1ib2wnKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC50by1zdHJpbmcnKTtcbnJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM3LnN5bWJvbC5hc3luYy1pdGVyYXRvcicpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczcuc3ltYm9sLm9ic2VydmFibGUnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLlN5bWJvbDtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvcicpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX3drcy1leHQnKS5mKCdpdGVyYXRvcicpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKHR5cGVvZiBpdCAhPSAnZnVuY3Rpb24nKSB0aHJvdyBUeXBlRXJyb3IoaXQgKyAnIGlzIG5vdCBhIGZ1bmN0aW9uIScpO1xuICByZXR1cm4gaXQ7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwgQ29uc3RydWN0b3IsIG5hbWUsIGZvcmJpZGRlbkZpZWxkKSB7XG4gIGlmICghKGl0IGluc3RhbmNlb2YgQ29uc3RydWN0b3IpIHx8IChmb3JiaWRkZW5GaWVsZCAhPT0gdW5kZWZpbmVkICYmIGZvcmJpZGRlbkZpZWxkIGluIGl0KSkge1xuICAgIHRocm93IFR5cGVFcnJvcihuYW1lICsgJzogaW5jb3JyZWN0IGludm9jYXRpb24hJyk7XG4gIH0gcmV0dXJuIGl0O1xufTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGFuIG9iamVjdCEnKTtcbiAgcmV0dXJuIGl0O1xufTtcbiIsIi8vIGZhbHNlIC0+IEFycmF5I2luZGV4T2Zcbi8vIHRydWUgIC0+IEFycmF5I2luY2x1ZGVzXG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgdG9BYnNvbHV0ZUluZGV4ID0gcmVxdWlyZSgnLi9fdG8tYWJzb2x1dGUtaW5kZXgnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKElTX0lOQ0xVREVTKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGVsLCBmcm9tSW5kZXgpIHtcbiAgICB2YXIgTyA9IHRvSU9iamVjdCgkdGhpcyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpO1xuICAgIHZhciB2YWx1ZTtcbiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZVxuICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7XG4gICAgICB2YWx1ZSA9IE9baW5kZXgrK107XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlXG4gICAgICBpZiAodmFsdWUgIT0gdmFsdWUpIHJldHVybiB0cnVlO1xuICAgIC8vIEFycmF5I2luZGV4T2YgaWdub3JlcyBob2xlcywgQXJyYXkjaW5jbHVkZXMgLSBub3RcbiAgICB9IGVsc2UgZm9yICg7bGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIGlmIChJU19JTkNMVURFUyB8fCBpbmRleCBpbiBPKSB7XG4gICAgICBpZiAoT1tpbmRleF0gPT09IGVsKSByZXR1cm4gSVNfSU5DTFVERVMgfHwgaW5kZXggfHwgMDtcbiAgICB9IHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7XG4gIH07XG59O1xuIiwiLy8gZ2V0dGluZyB0YWcgZnJvbSAxOS4xLjMuNiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbnZhciBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcbi8vIEVTMyB3cm9uZyBoZXJlXG52YXIgQVJHID0gY29mKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PSAnQXJndW1lbnRzJztcblxuLy8gZmFsbGJhY2sgZm9yIElFMTEgU2NyaXB0IEFjY2VzcyBEZW5pZWQgZXJyb3JcbnZhciB0cnlHZXQgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHZhciBPLCBULCBCO1xuICByZXR1cm4gaXQgPT09IHVuZGVmaW5lZCA/ICdVbmRlZmluZWQnIDogaXQgPT09IG51bGwgPyAnTnVsbCdcbiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2VcbiAgICA6IHR5cGVvZiAoVCA9IHRyeUdldChPID0gT2JqZWN0KGl0KSwgVEFHKSkgPT0gJ3N0cmluZycgPyBUXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBBUkcgPyBjb2YoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAoQiA9IGNvZihPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IEI7XG59O1xuIiwidmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKGl0KS5zbGljZSg4LCAtMSk7XG59O1xuIiwidmFyIGNvcmUgPSBtb2R1bGUuZXhwb3J0cyA9IHsgdmVyc2lvbjogJzIuNS4yJyB9O1xuaWYgKHR5cGVvZiBfX2UgPT0gJ251bWJlcicpIF9fZSA9IGNvcmU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiIsIi8vIG9wdGlvbmFsIC8gc2ltcGxlIGNvbnRleHQgYmluZGluZ1xudmFyIGFGdW5jdGlvbiA9IHJlcXVpcmUoJy4vX2EtZnVuY3Rpb24nKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuLCB0aGF0LCBsZW5ndGgpIHtcbiAgYUZ1bmN0aW9uKGZuKTtcbiAgaWYgKHRoYXQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZuO1xuICBzd2l0Y2ggKGxlbmd0aCkge1xuICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uIChhKSB7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhKTtcbiAgICB9O1xuICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhLCBiKTtcbiAgICB9O1xuICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICByZXR1cm4gZm4uY2FsbCh0aGF0LCBhLCBiLCBjKTtcbiAgICB9O1xuICB9XG4gIHJldHVybiBmdW5jdGlvbiAoLyogLi4uYXJncyAqLykge1xuICAgIHJldHVybiBmbi5hcHBseSh0aGF0LCBhcmd1bWVudHMpO1xuICB9O1xufTtcbiIsIi8vIDcuMi4xIFJlcXVpcmVPYmplY3RDb2VyY2libGUoYXJndW1lbnQpXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoaXQgPT0gdW5kZWZpbmVkKSB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIvLyBUaGFuaydzIElFOCBmb3IgaGlzIGZ1bm55IGRlZmluZVByb3BlcnR5XG5tb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ2EnLCB7IGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfSB9KS5hICE9IDc7XG59KTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGRvY3VtZW50ID0gcmVxdWlyZSgnLi9fZ2xvYmFsJykuZG9jdW1lbnQ7XG4vLyB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCBpcyAnb2JqZWN0JyBpbiBvbGQgSUVcbnZhciBpcyA9IGlzT2JqZWN0KGRvY3VtZW50KSAmJiBpc09iamVjdChkb2N1bWVudC5jcmVhdGVFbGVtZW50KTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpcyA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoaXQpIDoge307XG59O1xuIiwiLy8gSUUgOC0gZG9uJ3QgZW51bSBidWcga2V5c1xubW9kdWxlLmV4cG9ydHMgPSAoXG4gICdjb25zdHJ1Y3RvcixoYXNPd25Qcm9wZXJ0eSxpc1Byb3RvdHlwZU9mLHByb3BlcnR5SXNFbnVtZXJhYmxlLHRvTG9jYWxlU3RyaW5nLHRvU3RyaW5nLHZhbHVlT2YnXG4pLnNwbGl0KCcsJyk7XG4iLCIvLyBhbGwgZW51bWVyYWJsZSBvYmplY3Qga2V5cywgaW5jbHVkZXMgc3ltYm9sc1xudmFyIGdldEtleXMgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cycpO1xudmFyIGdPUFMgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wcycpO1xudmFyIHBJRSA9IHJlcXVpcmUoJy4vX29iamVjdC1waWUnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHZhciByZXN1bHQgPSBnZXRLZXlzKGl0KTtcbiAgdmFyIGdldFN5bWJvbHMgPSBnT1BTLmY7XG4gIGlmIChnZXRTeW1ib2xzKSB7XG4gICAgdmFyIHN5bWJvbHMgPSBnZXRTeW1ib2xzKGl0KTtcbiAgICB2YXIgaXNFbnVtID0gcElFLmY7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciBrZXk7XG4gICAgd2hpbGUgKHN5bWJvbHMubGVuZ3RoID4gaSkgaWYgKGlzRW51bS5jYWxsKGl0LCBrZXkgPSBzeW1ib2xzW2krK10pKSByZXN1bHQucHVzaChrZXkpO1xuICB9IHJldHVybiByZXN1bHQ7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGNvcmUgPSByZXF1aXJlKCcuL19jb3JlJyk7XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxudmFyICRleHBvcnQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgc291cmNlKSB7XG4gIHZhciBJU19GT1JDRUQgPSB0eXBlICYgJGV4cG9ydC5GO1xuICB2YXIgSVNfR0xPQkFMID0gdHlwZSAmICRleHBvcnQuRztcbiAgdmFyIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlM7XG4gIHZhciBJU19QUk9UTyA9IHR5cGUgJiAkZXhwb3J0LlA7XG4gIHZhciBJU19CSU5EID0gdHlwZSAmICRleHBvcnQuQjtcbiAgdmFyIElTX1dSQVAgPSB0eXBlICYgJGV4cG9ydC5XO1xuICB2YXIgZXhwb3J0cyA9IElTX0dMT0JBTCA/IGNvcmUgOiBjb3JlW25hbWVdIHx8IChjb3JlW25hbWVdID0ge30pO1xuICB2YXIgZXhwUHJvdG8gPSBleHBvcnRzW1BST1RPVFlQRV07XG4gIHZhciB0YXJnZXQgPSBJU19HTE9CQUwgPyBnbG9iYWwgOiBJU19TVEFUSUMgPyBnbG9iYWxbbmFtZV0gOiAoZ2xvYmFsW25hbWVdIHx8IHt9KVtQUk9UT1RZUEVdO1xuICB2YXIga2V5LCBvd24sIG91dDtcbiAgaWYgKElTX0dMT0JBTCkgc291cmNlID0gbmFtZTtcbiAgZm9yIChrZXkgaW4gc291cmNlKSB7XG4gICAgLy8gY29udGFpbnMgaW4gbmF0aXZlXG4gICAgb3duID0gIUlTX0ZPUkNFRCAmJiB0YXJnZXQgJiYgdGFyZ2V0W2tleV0gIT09IHVuZGVmaW5lZDtcbiAgICBpZiAob3duICYmIGtleSBpbiBleHBvcnRzKSBjb250aW51ZTtcbiAgICAvLyBleHBvcnQgbmF0aXZlIG9yIHBhc3NlZFxuICAgIG91dCA9IG93biA/IHRhcmdldFtrZXldIDogc291cmNlW2tleV07XG4gICAgLy8gcHJldmVudCBnbG9iYWwgcG9sbHV0aW9uIGZvciBuYW1lc3BhY2VzXG4gICAgZXhwb3J0c1trZXldID0gSVNfR0xPQkFMICYmIHR5cGVvZiB0YXJnZXRba2V5XSAhPSAnZnVuY3Rpb24nID8gc291cmNlW2tleV1cbiAgICAvLyBiaW5kIHRpbWVycyB0byBnbG9iYWwgZm9yIGNhbGwgZnJvbSBleHBvcnQgY29udGV4dFxuICAgIDogSVNfQklORCAmJiBvd24gPyBjdHgob3V0LCBnbG9iYWwpXG4gICAgLy8gd3JhcCBnbG9iYWwgY29uc3RydWN0b3JzIGZvciBwcmV2ZW50IGNoYW5nZSB0aGVtIGluIGxpYnJhcnlcbiAgICA6IElTX1dSQVAgJiYgdGFyZ2V0W2tleV0gPT0gb3V0ID8gKGZ1bmN0aW9uIChDKSB7XG4gICAgICB2YXIgRiA9IGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgQykge1xuICAgICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gbmV3IEMoKTtcbiAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDKGEpO1xuICAgICAgICAgICAgY2FzZSAyOiByZXR1cm4gbmV3IEMoYSwgYik7XG4gICAgICAgICAgfSByZXR1cm4gbmV3IEMoYSwgYiwgYyk7XG4gICAgICAgIH0gcmV0dXJuIEMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgICBGW1BST1RPVFlQRV0gPSBDW1BST1RPVFlQRV07XG4gICAgICByZXR1cm4gRjtcbiAgICAvLyBtYWtlIHN0YXRpYyB2ZXJzaW9ucyBmb3IgcHJvdG90eXBlIG1ldGhvZHNcbiAgICB9KShvdXQpIDogSVNfUFJPVE8gJiYgdHlwZW9mIG91dCA9PSAnZnVuY3Rpb24nID8gY3R4KEZ1bmN0aW9uLmNhbGwsIG91dCkgOiBvdXQ7XG4gICAgLy8gZXhwb3J0IHByb3RvIG1ldGhvZHMgdG8gY29yZS4lQ09OU1RSVUNUT1IlLm1ldGhvZHMuJU5BTUUlXG4gICAgaWYgKElTX1BST1RPKSB7XG4gICAgICAoZXhwb3J0cy52aXJ0dWFsIHx8IChleHBvcnRzLnZpcnR1YWwgPSB7fSkpW2tleV0gPSBvdXQ7XG4gICAgICAvLyBleHBvcnQgcHJvdG8gbWV0aG9kcyB0byBjb3JlLiVDT05TVFJVQ1RPUiUucHJvdG90eXBlLiVOQU1FJVxuICAgICAgaWYgKHR5cGUgJiAkZXhwb3J0LlIgJiYgZXhwUHJvdG8gJiYgIWV4cFByb3RvW2tleV0pIGhpZGUoZXhwUHJvdG8sIGtleSwgb3V0KTtcbiAgICB9XG4gIH1cbn07XG4vLyB0eXBlIGJpdG1hcFxuJGV4cG9ydC5GID0gMTsgICAvLyBmb3JjZWRcbiRleHBvcnQuRyA9IDI7ICAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgIC8vIHN0YXRpY1xuJGV4cG9ydC5QID0gODsgICAvLyBwcm90b1xuJGV4cG9ydC5CID0gMTY7ICAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgIC8vIHdyYXBcbiRleHBvcnQuVSA9IDY0OyAgLy8gc2FmZVxuJGV4cG9ydC5SID0gMTI4OyAvLyByZWFsIHByb3RvIG1ldGhvZCBmb3IgYGxpYnJhcnlgXG5tb2R1bGUuZXhwb3J0cyA9ICRleHBvcnQ7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChleGVjKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuICEhZXhlYygpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07XG4iLCJ2YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgY2FsbCA9IHJlcXVpcmUoJy4vX2l0ZXItY2FsbCcpO1xudmFyIGlzQXJyYXlJdGVyID0gcmVxdWlyZSgnLi9faXMtYXJyYXktaXRlcicpO1xudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgdG9MZW5ndGggPSByZXF1aXJlKCcuL190by1sZW5ndGgnKTtcbnZhciBnZXRJdGVyRm4gPSByZXF1aXJlKCcuL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZCcpO1xudmFyIEJSRUFLID0ge307XG52YXIgUkVUVVJOID0ge307XG52YXIgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXJhYmxlLCBlbnRyaWVzLCBmbiwgdGhhdCwgSVRFUkFUT1IpIHtcbiAgdmFyIGl0ZXJGbiA9IElURVJBVE9SID8gZnVuY3Rpb24gKCkgeyByZXR1cm4gaXRlcmFibGU7IH0gOiBnZXRJdGVyRm4oaXRlcmFibGUpO1xuICB2YXIgZiA9IGN0eChmbiwgdGhhdCwgZW50cmllcyA/IDIgOiAxKTtcbiAgdmFyIGluZGV4ID0gMDtcbiAgdmFyIGxlbmd0aCwgc3RlcCwgaXRlcmF0b3IsIHJlc3VsdDtcbiAgaWYgKHR5cGVvZiBpdGVyRm4gIT0gJ2Z1bmN0aW9uJykgdGhyb3cgVHlwZUVycm9yKGl0ZXJhYmxlICsgJyBpcyBub3QgaXRlcmFibGUhJyk7XG4gIC8vIGZhc3QgY2FzZSBmb3IgYXJyYXlzIHdpdGggZGVmYXVsdCBpdGVyYXRvclxuICBpZiAoaXNBcnJheUl0ZXIoaXRlckZuKSkgZm9yIChsZW5ndGggPSB0b0xlbmd0aChpdGVyYWJsZS5sZW5ndGgpOyBsZW5ndGggPiBpbmRleDsgaW5kZXgrKykge1xuICAgIHJlc3VsdCA9IGVudHJpZXMgPyBmKGFuT2JqZWN0KHN0ZXAgPSBpdGVyYWJsZVtpbmRleF0pWzBdLCBzdGVwWzFdKSA6IGYoaXRlcmFibGVbaW5kZXhdKTtcbiAgICBpZiAocmVzdWx0ID09PSBCUkVBSyB8fCByZXN1bHQgPT09IFJFVFVSTikgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIGZvciAoaXRlcmF0b3IgPSBpdGVyRm4uY2FsbChpdGVyYWJsZSk7ICEoc3RlcCA9IGl0ZXJhdG9yLm5leHQoKSkuZG9uZTspIHtcbiAgICByZXN1bHQgPSBjYWxsKGl0ZXJhdG9yLCBmLCBzdGVwLnZhbHVlLCBlbnRyaWVzKTtcbiAgICBpZiAocmVzdWx0ID09PSBCUkVBSyB8fCByZXN1bHQgPT09IFJFVFVSTikgcmV0dXJuIHJlc3VsdDtcbiAgfVxufTtcbmV4cG9ydHMuQlJFQUsgPSBCUkVBSztcbmV4cG9ydHMuUkVUVVJOID0gUkVUVVJOO1xuIiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjhcbnZhciBnbG9iYWwgPSBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93Lk1hdGggPT0gTWF0aFxuICA/IHdpbmRvdyA6IHR5cGVvZiBzZWxmICE9ICd1bmRlZmluZWQnICYmIHNlbGYuTWF0aCA9PSBNYXRoID8gc2VsZlxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tbmV3LWZ1bmNcbiAgOiBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuaWYgKHR5cGVvZiBfX2cgPT0gJ251bWJlcicpIF9fZyA9IGdsb2JhbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZlxuIiwidmFyIGhhc093blByb3BlcnR5ID0ge30uaGFzT3duUHJvcGVydHk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwga2V5KSB7XG4gIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGl0LCBrZXkpO1xufTtcbiIsInZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIGNyZWF0ZURlc2MgPSByZXF1aXJlKCcuL19wcm9wZXJ0eS1kZXNjJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIHJldHVybiBkUC5mKG9iamVjdCwga2V5LCBjcmVhdGVEZXNjKDEsIHZhbHVlKSk7XG59IDogZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICByZXR1cm4gb2JqZWN0O1xufTtcbiIsInZhciBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50O1xubW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4iLCJtb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpICYmICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXF1aXJlKCcuL19kb20tY3JlYXRlJykoJ2RpdicpLCAnYScsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pLmEgIT0gNztcbn0pO1xuIiwiLy8gZmFzdCBhcHBseSwgaHR0cDovL2pzcGVyZi5sbmtpdC5jb20vZmFzdC1hcHBseS81XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbiwgYXJncywgdGhhdCkge1xuICB2YXIgdW4gPSB0aGF0ID09PSB1bmRlZmluZWQ7XG4gIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICBjYXNlIDA6IHJldHVybiB1biA/IGZuKClcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCk7XG4gICAgY2FzZSAxOiByZXR1cm4gdW4gPyBmbihhcmdzWzBdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdKTtcbiAgICBjYXNlIDI6IHJldHVybiB1biA/IGZuKGFyZ3NbMF0sIGFyZ3NbMV0pXG4gICAgICAgICAgICAgICAgICAgICAgOiBmbi5jYWxsKHRoYXQsIGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgIGNhc2UgMzogcmV0dXJuIHVuID8gZm4oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSlcbiAgICAgICAgICAgICAgICAgICAgICA6IGZuLmNhbGwodGhhdCwgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgY2FzZSA0OiByZXR1cm4gdW4gPyBmbihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdKVxuICAgICAgICAgICAgICAgICAgICAgIDogZm4uY2FsbCh0aGF0LCBhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdKTtcbiAgfSByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJncyk7XG59O1xuIiwiLy8gZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBhbmQgbm9uLWVudW1lcmFibGUgb2xkIFY4IHN0cmluZ3NcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wcm90b3R5cGUtYnVpbHRpbnNcbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0KCd6JykucHJvcGVydHlJc0VudW1lcmFibGUoMCkgPyBPYmplY3QgOiBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGNvZihpdCkgPT0gJ1N0cmluZycgPyBpdC5zcGxpdCgnJykgOiBPYmplY3QoaXQpO1xufTtcbiIsIi8vIGNoZWNrIG9uIGRlZmF1bHQgQXJyYXkgaXRlcmF0b3JcbnZhciBJdGVyYXRvcnMgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKTtcbnZhciBJVEVSQVRPUiA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpO1xudmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCAhPT0gdW5kZWZpbmVkICYmIChJdGVyYXRvcnMuQXJyYXkgPT09IGl0IHx8IEFycmF5UHJvdG9bSVRFUkFUT1JdID09PSBpdCk7XG59O1xuIiwiLy8gNy4yLjIgSXNBcnJheShhcmd1bWVudClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KGFyZykge1xuICByZXR1cm4gY29mKGFyZykgPT0gJ0FycmF5Jztcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcbiIsIi8vIGNhbGwgc29tZXRoaW5nIG9uIGl0ZXJhdG9yIHN0ZXAgd2l0aCBzYWZlIGNsb3Npbmcgb24gZXJyb3JcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXRlcmF0b3IsIGZuLCB2YWx1ZSwgZW50cmllcykge1xuICB0cnkge1xuICAgIHJldHVybiBlbnRyaWVzID8gZm4oYW5PYmplY3QodmFsdWUpWzBdLCB2YWx1ZVsxXSkgOiBmbih2YWx1ZSk7XG4gIC8vIDcuNC42IEl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsIGNvbXBsZXRpb24pXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB2YXIgcmV0ID0gaXRlcmF0b3JbJ3JldHVybiddO1xuICAgIGlmIChyZXQgIT09IHVuZGVmaW5lZCkgYW5PYmplY3QocmV0LmNhbGwoaXRlcmF0b3IpKTtcbiAgICB0aHJvdyBlO1xuICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGNyZWF0ZSA9IHJlcXVpcmUoJy4vX29iamVjdC1jcmVhdGUnKTtcbnZhciBkZXNjcmlwdG9yID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpO1xudmFyIHNldFRvU3RyaW5nVGFnID0gcmVxdWlyZSgnLi9fc2V0LXRvLXN0cmluZy10YWcnKTtcbnZhciBJdGVyYXRvclByb3RvdHlwZSA9IHt9O1xuXG4vLyAyNS4xLjIuMS4xICVJdGVyYXRvclByb3RvdHlwZSVbQEBpdGVyYXRvcl0oKVxucmVxdWlyZSgnLi9faGlkZScpKEl0ZXJhdG9yUHJvdG90eXBlLCByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKSwgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KSB7XG4gIENvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSwgeyBuZXh0OiBkZXNjcmlwdG9yKDEsIG5leHQpIH0pO1xuICBzZXRUb1N0cmluZ1RhZyhDb25zdHJ1Y3RvciwgTkFNRSArICcgSXRlcmF0b3InKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgTElCUkFSWSA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKTtcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIGhpZGUgPSByZXF1aXJlKCcuL19oaWRlJyk7XG52YXIgaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgJGl0ZXJDcmVhdGUgPSByZXF1aXJlKCcuL19pdGVyLWNyZWF0ZScpO1xudmFyIHNldFRvU3RyaW5nVGFnID0gcmVxdWlyZSgnLi9fc2V0LXRvLXN0cmluZy10YWcnKTtcbnZhciBnZXRQcm90b3R5cGVPZiA9IHJlcXVpcmUoJy4vX29iamVjdC1ncG8nKTtcbnZhciBJVEVSQVRPUiA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpO1xudmFyIEJVR0dZID0gIShbXS5rZXlzICYmICduZXh0JyBpbiBbXS5rZXlzKCkpOyAvLyBTYWZhcmkgaGFzIGJ1Z2d5IGl0ZXJhdG9ycyB3L28gYG5leHRgXG52YXIgRkZfSVRFUkFUT1IgPSAnQEBpdGVyYXRvcic7XG52YXIgS0VZUyA9ICdrZXlzJztcbnZhciBWQUxVRVMgPSAndmFsdWVzJztcblxudmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChCYXNlLCBOQU1FLCBDb25zdHJ1Y3RvciwgbmV4dCwgREVGQVVMVCwgSVNfU0VULCBGT1JDRUQpIHtcbiAgJGl0ZXJDcmVhdGUoQ29uc3RydWN0b3IsIE5BTUUsIG5leHQpO1xuICB2YXIgZ2V0TWV0aG9kID0gZnVuY3Rpb24gKGtpbmQpIHtcbiAgICBpZiAoIUJVR0dZICYmIGtpbmQgaW4gcHJvdG8pIHJldHVybiBwcm90b1traW5kXTtcbiAgICBzd2l0Y2ggKGtpbmQpIHtcbiAgICAgIGNhc2UgS0VZUzogcmV0dXJuIGZ1bmN0aW9uIGtleXMoKSB7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gICAgICBjYXNlIFZBTFVFUzogcmV0dXJuIGZ1bmN0aW9uIHZhbHVlcygpIHsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgICB9IHJldHVybiBmdW5jdGlvbiBlbnRyaWVzKCkgeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICB9O1xuICB2YXIgVEFHID0gTkFNRSArICcgSXRlcmF0b3InO1xuICB2YXIgREVGX1ZBTFVFUyA9IERFRkFVTFQgPT0gVkFMVUVTO1xuICB2YXIgVkFMVUVTX0JVRyA9IGZhbHNlO1xuICB2YXIgcHJvdG8gPSBCYXNlLnByb3RvdHlwZTtcbiAgdmFyICRuYXRpdmUgPSBwcm90b1tJVEVSQVRPUl0gfHwgcHJvdG9bRkZfSVRFUkFUT1JdIHx8IERFRkFVTFQgJiYgcHJvdG9bREVGQVVMVF07XG4gIHZhciAkZGVmYXVsdCA9ICRuYXRpdmUgfHwgZ2V0TWV0aG9kKERFRkFVTFQpO1xuICB2YXIgJGVudHJpZXMgPSBERUZBVUxUID8gIURFRl9WQUxVRVMgPyAkZGVmYXVsdCA6IGdldE1ldGhvZCgnZW50cmllcycpIDogdW5kZWZpbmVkO1xuICB2YXIgJGFueU5hdGl2ZSA9IE5BTUUgPT0gJ0FycmF5JyA/IHByb3RvLmVudHJpZXMgfHwgJG5hdGl2ZSA6ICRuYXRpdmU7XG4gIHZhciBtZXRob2RzLCBrZXksIEl0ZXJhdG9yUHJvdG90eXBlO1xuICAvLyBGaXggbmF0aXZlXG4gIGlmICgkYW55TmF0aXZlKSB7XG4gICAgSXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90b3R5cGVPZigkYW55TmF0aXZlLmNhbGwobmV3IEJhc2UoKSkpO1xuICAgIGlmIChJdGVyYXRvclByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSAmJiBJdGVyYXRvclByb3RvdHlwZS5uZXh0KSB7XG4gICAgICAvLyBTZXQgQEB0b1N0cmluZ1RhZyB0byBuYXRpdmUgaXRlcmF0b3JzXG4gICAgICBzZXRUb1N0cmluZ1RhZyhJdGVyYXRvclByb3RvdHlwZSwgVEFHLCB0cnVlKTtcbiAgICAgIC8vIGZpeCBmb3Igc29tZSBvbGQgZW5naW5lc1xuICAgICAgaWYgKCFMSUJSQVJZICYmICFoYXMoSXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SKSkgaGlkZShJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IsIHJldHVyblRoaXMpO1xuICAgIH1cbiAgfVxuICAvLyBmaXggQXJyYXkje3ZhbHVlcywgQEBpdGVyYXRvcn0ubmFtZSBpbiBWOCAvIEZGXG4gIGlmIChERUZfVkFMVUVTICYmICRuYXRpdmUgJiYgJG5hdGl2ZS5uYW1lICE9PSBWQUxVRVMpIHtcbiAgICBWQUxVRVNfQlVHID0gdHJ1ZTtcbiAgICAkZGVmYXVsdCA9IGZ1bmN0aW9uIHZhbHVlcygpIHsgcmV0dXJuICRuYXRpdmUuY2FsbCh0aGlzKTsgfTtcbiAgfVxuICAvLyBEZWZpbmUgaXRlcmF0b3JcbiAgaWYgKCghTElCUkFSWSB8fCBGT1JDRUQpICYmIChCVUdHWSB8fCBWQUxVRVNfQlVHIHx8ICFwcm90b1tJVEVSQVRPUl0pKSB7XG4gICAgaGlkZShwcm90bywgSVRFUkFUT1IsICRkZWZhdWx0KTtcbiAgfVxuICAvLyBQbHVnIGZvciBsaWJyYXJ5XG4gIEl0ZXJhdG9yc1tOQU1FXSA9ICRkZWZhdWx0O1xuICBJdGVyYXRvcnNbVEFHXSA9IHJldHVyblRoaXM7XG4gIGlmIChERUZBVUxUKSB7XG4gICAgbWV0aG9kcyA9IHtcbiAgICAgIHZhbHVlczogREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKFZBTFVFUyksXG4gICAgICBrZXlzOiBJU19TRVQgPyAkZGVmYXVsdCA6IGdldE1ldGhvZChLRVlTKSxcbiAgICAgIGVudHJpZXM6ICRlbnRyaWVzXG4gICAgfTtcbiAgICBpZiAoRk9SQ0VEKSBmb3IgKGtleSBpbiBtZXRob2RzKSB7XG4gICAgICBpZiAoIShrZXkgaW4gcHJvdG8pKSByZWRlZmluZShwcm90bywga2V5LCBtZXRob2RzW2tleV0pO1xuICAgIH0gZWxzZSAkZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuRiAqIChCVUdHWSB8fCBWQUxVRVNfQlVHKSwgTkFNRSwgbWV0aG9kcyk7XG4gIH1cbiAgcmV0dXJuIG1ldGhvZHM7XG59O1xuIiwidmFyIElURVJBVE9SID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyk7XG52YXIgU0FGRV9DTE9TSU5HID0gZmFsc2U7XG5cbnRyeSB7XG4gIHZhciByaXRlciA9IFs3XVtJVEVSQVRPUl0oKTtcbiAgcml0ZXJbJ3JldHVybiddID0gZnVuY3Rpb24gKCkgeyBTQUZFX0NMT1NJTkcgPSB0cnVlOyB9O1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdGhyb3ctbGl0ZXJhbFxuICBBcnJheS5mcm9tKHJpdGVyLCBmdW5jdGlvbiAoKSB7IHRocm93IDI7IH0pO1xufSBjYXRjaCAoZSkgeyAvKiBlbXB0eSAqLyB9XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMsIHNraXBDbG9zaW5nKSB7XG4gIGlmICghc2tpcENsb3NpbmcgJiYgIVNBRkVfQ0xPU0lORykgcmV0dXJuIGZhbHNlO1xuICB2YXIgc2FmZSA9IGZhbHNlO1xuICB0cnkge1xuICAgIHZhciBhcnIgPSBbN107XG4gICAgdmFyIGl0ZXIgPSBhcnJbSVRFUkFUT1JdKCk7XG4gICAgaXRlci5uZXh0ID0gZnVuY3Rpb24gKCkgeyByZXR1cm4geyBkb25lOiBzYWZlID0gdHJ1ZSB9OyB9O1xuICAgIGFycltJVEVSQVRPUl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiBpdGVyOyB9O1xuICAgIGV4ZWMoYXJyKTtcbiAgfSBjYXRjaCAoZSkgeyAvKiBlbXB0eSAqLyB9XG4gIHJldHVybiBzYWZlO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGRvbmUsIHZhbHVlKSB7XG4gIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZG9uZTogISFkb25lIH07XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7fTtcbiIsIm1vZHVsZS5leHBvcnRzID0gdHJ1ZTtcbiIsInZhciBNRVRBID0gcmVxdWlyZSgnLi9fdWlkJykoJ21ldGEnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHNldERlc2MgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGlkID0gMDtcbnZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlIHx8IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xudmFyIEZSRUVaRSA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTtcbn0pO1xudmFyIHNldE1ldGEgPSBmdW5jdGlvbiAoaXQpIHtcbiAgc2V0RGVzYyhpdCwgTUVUQSwgeyB2YWx1ZToge1xuICAgIGk6ICdPJyArICsraWQsIC8vIG9iamVjdCBJRFxuICAgIHc6IHt9ICAgICAgICAgIC8vIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH0gfSk7XG59O1xudmFyIGZhc3RLZXkgPSBmdW5jdGlvbiAoaXQsIGNyZWF0ZSkge1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0O1xuICBpZiAoIWhhcyhpdCwgTUVUQSkpIHtcbiAgICAvLyBjYW4ndCBzZXQgbWV0YWRhdGEgdG8gdW5jYXVnaHQgZnJvemVuIG9iamVjdFxuICAgIGlmICghaXNFeHRlbnNpYmxlKGl0KSkgcmV0dXJuICdGJztcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBvYmplY3QgSURcbiAgfSByZXR1cm4gaXRbTUVUQV0uaTtcbn07XG52YXIgZ2V0V2VhayA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7XG4gIGlmICghaGFzKGl0LCBNRVRBKSkge1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYgKCFpc0V4dGVuc2libGUoaXQpKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gYWRkIG1pc3NpbmcgbWV0YWRhdGFcbiAgICBzZXRNZXRhKGl0KTtcbiAgLy8gcmV0dXJuIGhhc2ggd2VhayBjb2xsZWN0aW9ucyBJRHNcbiAgfSByZXR1cm4gaXRbTUVUQV0udztcbn07XG4vLyBhZGQgbWV0YWRhdGEgb24gZnJlZXplLWZhbWlseSBtZXRob2RzIGNhbGxpbmdcbnZhciBvbkZyZWV6ZSA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoRlJFRVpFICYmIG1ldGEuTkVFRCAmJiBpc0V4dGVuc2libGUoaXQpICYmICFoYXMoaXQsIE1FVEEpKSBzZXRNZXRhKGl0KTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciBtZXRhID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIEtFWTogTUVUQSxcbiAgTkVFRDogZmFsc2UsXG4gIGZhc3RLZXk6IGZhc3RLZXksXG4gIGdldFdlYWs6IGdldFdlYWssXG4gIG9uRnJlZXplOiBvbkZyZWV6ZVxufTtcbiIsInZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBtYWNyb3Rhc2sgPSByZXF1aXJlKCcuL190YXNrJykuc2V0O1xudmFyIE9ic2VydmVyID0gZ2xvYmFsLk11dGF0aW9uT2JzZXJ2ZXIgfHwgZ2xvYmFsLldlYktpdE11dGF0aW9uT2JzZXJ2ZXI7XG52YXIgcHJvY2VzcyA9IGdsb2JhbC5wcm9jZXNzO1xudmFyIFByb21pc2UgPSBnbG9iYWwuUHJvbWlzZTtcbnZhciBpc05vZGUgPSByZXF1aXJlKCcuL19jb2YnKShwcm9jZXNzKSA9PSAncHJvY2Vzcyc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICB2YXIgaGVhZCwgbGFzdCwgbm90aWZ5O1xuXG4gIHZhciBmbHVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcGFyZW50LCBmbjtcbiAgICBpZiAoaXNOb2RlICYmIChwYXJlbnQgPSBwcm9jZXNzLmRvbWFpbikpIHBhcmVudC5leGl0KCk7XG4gICAgd2hpbGUgKGhlYWQpIHtcbiAgICAgIGZuID0gaGVhZC5mbjtcbiAgICAgIGhlYWQgPSBoZWFkLm5leHQ7XG4gICAgICB0cnkge1xuICAgICAgICBmbigpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoaGVhZCkgbm90aWZ5KCk7XG4gICAgICAgIGVsc2UgbGFzdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9IGxhc3QgPSB1bmRlZmluZWQ7XG4gICAgaWYgKHBhcmVudCkgcGFyZW50LmVudGVyKCk7XG4gIH07XG5cbiAgLy8gTm9kZS5qc1xuICBpZiAoaXNOb2RlKSB7XG4gICAgbm90aWZ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgcHJvY2Vzcy5uZXh0VGljayhmbHVzaCk7XG4gICAgfTtcbiAgLy8gYnJvd3NlcnMgd2l0aCBNdXRhdGlvbk9ic2VydmVyLCBleGNlcHQgaU9TIFNhZmFyaSAtIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy8zMzlcbiAgfSBlbHNlIGlmIChPYnNlcnZlciAmJiAhKGdsb2JhbC5uYXZpZ2F0b3IgJiYgZ2xvYmFsLm5hdmlnYXRvci5zdGFuZGFsb25lKSkge1xuICAgIHZhciB0b2dnbGUgPSB0cnVlO1xuICAgIHZhciBub2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICAgIG5ldyBPYnNlcnZlcihmbHVzaCkub2JzZXJ2ZShub2RlLCB7IGNoYXJhY3RlckRhdGE6IHRydWUgfSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tbmV3XG4gICAgbm90aWZ5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgbm9kZS5kYXRhID0gdG9nZ2xlID0gIXRvZ2dsZTtcbiAgICB9O1xuICAvLyBlbnZpcm9ubWVudHMgd2l0aCBtYXliZSBub24tY29tcGxldGVseSBjb3JyZWN0LCBidXQgZXhpc3RlbnQgUHJvbWlzZVxuICB9IGVsc2UgaWYgKFByb21pc2UgJiYgUHJvbWlzZS5yZXNvbHZlKSB7XG4gICAgdmFyIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICBub3RpZnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBwcm9taXNlLnRoZW4oZmx1c2gpO1xuICAgIH07XG4gIC8vIGZvciBvdGhlciBlbnZpcm9ubWVudHMgLSBtYWNyb3Rhc2sgYmFzZWQgb246XG4gIC8vIC0gc2V0SW1tZWRpYXRlXG4gIC8vIC0gTWVzc2FnZUNoYW5uZWxcbiAgLy8gLSB3aW5kb3cucG9zdE1lc3NhZ1xuICAvLyAtIG9ucmVhZHlzdGF0ZWNoYW5nZVxuICAvLyAtIHNldFRpbWVvdXRcbiAgfSBlbHNlIHtcbiAgICBub3RpZnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBzdHJhbmdlIElFICsgd2VicGFjayBkZXYgc2VydmVyIGJ1ZyAtIHVzZSAuY2FsbChnbG9iYWwpXG4gICAgICBtYWNyb3Rhc2suY2FsbChnbG9iYWwsIGZsdXNoKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChmbikge1xuICAgIHZhciB0YXNrID0geyBmbjogZm4sIG5leHQ6IHVuZGVmaW5lZCB9O1xuICAgIGlmIChsYXN0KSBsYXN0Lm5leHQgPSB0YXNrO1xuICAgIGlmICghaGVhZCkge1xuICAgICAgaGVhZCA9IHRhc2s7XG4gICAgICBub3RpZnkoKTtcbiAgICB9IGxhc3QgPSB0YXNrO1xuICB9O1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIDI1LjQuMS41IE5ld1Byb21pc2VDYXBhYmlsaXR5KEMpXG52YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpO1xuXG5mdW5jdGlvbiBQcm9taXNlQ2FwYWJpbGl0eShDKSB7XG4gIHZhciByZXNvbHZlLCByZWplY3Q7XG4gIHRoaXMucHJvbWlzZSA9IG5ldyBDKGZ1bmN0aW9uICgkJHJlc29sdmUsICQkcmVqZWN0KSB7XG4gICAgaWYgKHJlc29sdmUgIT09IHVuZGVmaW5lZCB8fCByZWplY3QgIT09IHVuZGVmaW5lZCkgdGhyb3cgVHlwZUVycm9yKCdCYWQgUHJvbWlzZSBjb25zdHJ1Y3RvcicpO1xuICAgIHJlc29sdmUgPSAkJHJlc29sdmU7XG4gICAgcmVqZWN0ID0gJCRyZWplY3Q7XG4gIH0pO1xuICB0aGlzLnJlc29sdmUgPSBhRnVuY3Rpb24ocmVzb2x2ZSk7XG4gIHRoaXMucmVqZWN0ID0gYUZ1bmN0aW9uKHJlamVjdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzLmYgPSBmdW5jdGlvbiAoQykge1xuICByZXR1cm4gbmV3IFByb21pc2VDYXBhYmlsaXR5KEMpO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIDE5LjEuMi4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UsIC4uLilcbnZhciBnZXRLZXlzID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMnKTtcbnZhciBnT1BTID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKTtcbnZhciBwSUUgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKTtcbnZhciBJT2JqZWN0ID0gcmVxdWlyZSgnLi9faW9iamVjdCcpO1xudmFyICRhc3NpZ24gPSBPYmplY3QuYXNzaWduO1xuXG4vLyBzaG91bGQgd29yayB3aXRoIHN5bWJvbHMgYW5kIHNob3VsZCBoYXZlIGRldGVybWluaXN0aWMgcHJvcGVydHkgb3JkZXIgKFY4IGJ1Zylcbm1vZHVsZS5leHBvcnRzID0gISRhc3NpZ24gfHwgcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbiAoKSB7XG4gIHZhciBBID0ge307XG4gIHZhciBCID0ge307XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZlxuICB2YXIgUyA9IFN5bWJvbCgpO1xuICB2YXIgSyA9ICdhYmNkZWZnaGlqa2xtbm9wcXJzdCc7XG4gIEFbU10gPSA3O1xuICBLLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChrKSB7IEJba10gPSBrOyB9KTtcbiAgcmV0dXJuICRhc3NpZ24oe30sIEEpW1NdICE9IDcgfHwgT2JqZWN0LmtleXMoJGFzc2lnbih7fSwgQikpLmpvaW4oJycpICE9IEs7XG59KSA/IGZ1bmN0aW9uIGFzc2lnbih0YXJnZXQsIHNvdXJjZSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIHZhciBUID0gdG9PYmplY3QodGFyZ2V0KTtcbiAgdmFyIGFMZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICB2YXIgaW5kZXggPSAxO1xuICB2YXIgZ2V0U3ltYm9scyA9IGdPUFMuZjtcbiAgdmFyIGlzRW51bSA9IHBJRS5mO1xuICB3aGlsZSAoYUxlbiA+IGluZGV4KSB7XG4gICAgdmFyIFMgPSBJT2JqZWN0KGFyZ3VtZW50c1tpbmRleCsrXSk7XG4gICAgdmFyIGtleXMgPSBnZXRTeW1ib2xzID8gZ2V0S2V5cyhTKS5jb25jYXQoZ2V0U3ltYm9scyhTKSkgOiBnZXRLZXlzKFMpO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgaiA9IDA7XG4gICAgdmFyIGtleTtcbiAgICB3aGlsZSAobGVuZ3RoID4gaikgaWYgKGlzRW51bS5jYWxsKFMsIGtleSA9IGtleXNbaisrXSkpIFRba2V5XSA9IFNba2V5XTtcbiAgfSByZXR1cm4gVDtcbn0gOiAkYXNzaWduO1xuIiwiLy8gMTkuMS4yLjIgLyAxNS4yLjMuNSBPYmplY3QuY3JlYXRlKE8gWywgUHJvcGVydGllc10pXG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBkUHMgPSByZXF1aXJlKCcuL19vYmplY3QtZHBzJyk7XG52YXIgZW51bUJ1Z0tleXMgPSByZXF1aXJlKCcuL19lbnVtLWJ1Zy1rZXlzJyk7XG52YXIgSUVfUFJPVE8gPSByZXF1aXJlKCcuL19zaGFyZWQta2V5JykoJ0lFX1BST1RPJyk7XG52YXIgRW1wdHkgPSBmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH07XG52YXIgUFJPVE9UWVBFID0gJ3Byb3RvdHlwZSc7XG5cbi8vIENyZWF0ZSBvYmplY3Qgd2l0aCBmYWtlIGBudWxsYCBwcm90b3R5cGU6IHVzZSBpZnJhbWUgT2JqZWN0IHdpdGggY2xlYXJlZCBwcm90b3R5cGVcbnZhciBjcmVhdGVEaWN0ID0gZnVuY3Rpb24gKCkge1xuICAvLyBUaHJhc2gsIHdhc3RlIGFuZCBzb2RvbXk6IElFIEdDIGJ1Z1xuICB2YXIgaWZyYW1lID0gcmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpKCdpZnJhbWUnKTtcbiAgdmFyIGkgPSBlbnVtQnVnS2V5cy5sZW5ndGg7XG4gIHZhciBsdCA9ICc8JztcbiAgdmFyIGd0ID0gJz4nO1xuICB2YXIgaWZyYW1lRG9jdW1lbnQ7XG4gIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICByZXF1aXJlKCcuL19odG1sJykuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgaWZyYW1lLnNyYyA9ICdqYXZhc2NyaXB0Oic7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tc2NyaXB0LXVybFxuICAvLyBjcmVhdGVEaWN0ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cuT2JqZWN0O1xuICAvLyBodG1sLnJlbW92ZUNoaWxkKGlmcmFtZSk7XG4gIGlmcmFtZURvY3VtZW50ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cuZG9jdW1lbnQ7XG4gIGlmcmFtZURvY3VtZW50Lm9wZW4oKTtcbiAgaWZyYW1lRG9jdW1lbnQud3JpdGUobHQgKyAnc2NyaXB0JyArIGd0ICsgJ2RvY3VtZW50LkY9T2JqZWN0JyArIGx0ICsgJy9zY3JpcHQnICsgZ3QpO1xuICBpZnJhbWVEb2N1bWVudC5jbG9zZSgpO1xuICBjcmVhdGVEaWN0ID0gaWZyYW1lRG9jdW1lbnQuRjtcbiAgd2hpbGUgKGktLSkgZGVsZXRlIGNyZWF0ZURpY3RbUFJPVE9UWVBFXVtlbnVtQnVnS2V5c1tpXV07XG4gIHJldHVybiBjcmVhdGVEaWN0KCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5jcmVhdGUgfHwgZnVuY3Rpb24gY3JlYXRlKE8sIFByb3BlcnRpZXMpIHtcbiAgdmFyIHJlc3VsdDtcbiAgaWYgKE8gIT09IG51bGwpIHtcbiAgICBFbXB0eVtQUk9UT1RZUEVdID0gYW5PYmplY3QoTyk7XG4gICAgcmVzdWx0ID0gbmV3IEVtcHR5KCk7XG4gICAgRW1wdHlbUFJPVE9UWVBFXSA9IG51bGw7XG4gICAgLy8gYWRkIFwiX19wcm90b19fXCIgZm9yIE9iamVjdC5nZXRQcm90b3R5cGVPZiBwb2x5ZmlsbFxuICAgIHJlc3VsdFtJRV9QUk9UT10gPSBPO1xuICB9IGVsc2UgcmVzdWx0ID0gY3JlYXRlRGljdCgpO1xuICByZXR1cm4gUHJvcGVydGllcyA9PT0gdW5kZWZpbmVkID8gcmVzdWx0IDogZFBzKHJlc3VsdCwgUHJvcGVydGllcyk7XG59O1xuIiwidmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgSUU4X0RPTV9ERUZJTkUgPSByZXF1aXJlKCcuL19pZTgtZG9tLWRlZmluZScpO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJyk7XG52YXIgZFAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCEnKTtcbiAgaWYgKCd2YWx1ZScgaW4gQXR0cmlidXRlcykgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTtcbiIsInZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICB2YXIga2V5cyA9IGdldEtleXMoUHJvcGVydGllcyk7XG4gIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgdmFyIGkgPSAwO1xuICB2YXIgUDtcbiAgd2hpbGUgKGxlbmd0aCA+IGkpIGRQLmYoTywgUCA9IGtleXNbaSsrXSwgUHJvcGVydGllc1tQXSk7XG4gIHJldHVybiBPO1xufTtcbiIsInZhciBwSUUgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciB0b0lPYmplY3QgPSByZXF1aXJlKCcuL190by1pb2JqZWN0Jyk7XG52YXIgdG9QcmltaXRpdmUgPSByZXF1aXJlKCcuL190by1wcmltaXRpdmUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJyk7XG52YXIgZ09QRCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBnT1BEIDogZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApIHtcbiAgTyA9IHRvSU9iamVjdChPKTtcbiAgUCA9IHRvUHJpbWl0aXZlKFAsIHRydWUpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGdPUEQoTywgUCk7XG4gIH0gY2F0Y2ggKGUpIHsgLyogZW1wdHkgKi8gfVxuICBpZiAoaGFzKE8sIFApKSByZXR1cm4gY3JlYXRlRGVzYyghcElFLmYuY2FsbChPLCBQKSwgT1tQXSk7XG59O1xuIiwiLy8gZmFsbGJhY2sgZm9yIElFMTEgYnVnZ3kgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgd2l0aCBpZnJhbWUgYW5kIHdpbmRvd1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcbnZhciBnT1BOID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcG4nKS5mO1xudmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XG5cbnZhciB3aW5kb3dOYW1lcyA9IHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgd2luZG93ICYmIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzXG4gID8gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMod2luZG93KSA6IFtdO1xuXG52YXIgZ2V0V2luZG93TmFtZXMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZ09QTihpdCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gd2luZG93TmFtZXMuc2xpY2UoKTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMuZiA9IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoaXQpIHtcbiAgcmV0dXJuIHdpbmRvd05hbWVzICYmIHRvU3RyaW5nLmNhbGwoaXQpID09ICdbb2JqZWN0IFdpbmRvd10nID8gZ2V0V2luZG93TmFtZXMoaXQpIDogZ09QTih0b0lPYmplY3QoaXQpKTtcbn07XG4iLCIvLyAxOS4xLjIuNyAvIDE1LjIuMy40IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE8pXG52YXIgJGtleXMgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cy1pbnRlcm5hbCcpO1xudmFyIGhpZGRlbktleXMgPSByZXF1aXJlKCcuL19lbnVtLWJ1Zy1rZXlzJykuY29uY2F0KCdsZW5ndGgnLCAncHJvdG90eXBlJyk7XG5cbmV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoTykge1xuICByZXR1cm4gJGtleXMoTywgaGlkZGVuS2V5cyk7XG59O1xuIiwiZXhwb3J0cy5mID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcbiIsIi8vIDE5LjEuMi45IC8gMTUuMi4zLjIgT2JqZWN0LmdldFByb3RvdHlwZU9mKE8pXG52YXIgaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKTtcbnZhciBJRV9QUk9UTyA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKTtcbnZhciBPYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmdldFByb3RvdHlwZU9mIHx8IGZ1bmN0aW9uIChPKSB7XG4gIE8gPSB0b09iamVjdChPKTtcbiAgaWYgKGhhcyhPLCBJRV9QUk9UTykpIHJldHVybiBPW0lFX1BST1RPXTtcbiAgaWYgKHR5cGVvZiBPLmNvbnN0cnVjdG9yID09ICdmdW5jdGlvbicgJiYgTyBpbnN0YW5jZW9mIE8uY29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gTy5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gIH0gcmV0dXJuIE8gaW5zdGFuY2VvZiBPYmplY3QgPyBPYmplY3RQcm90byA6IG51bGw7XG59O1xuIiwidmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcbnZhciBhcnJheUluZGV4T2YgPSByZXF1aXJlKCcuL19hcnJheS1pbmNsdWRlcycpKGZhbHNlKTtcbnZhciBJRV9QUk9UTyA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBuYW1lcykge1xuICB2YXIgTyA9IHRvSU9iamVjdChvYmplY3QpO1xuICB2YXIgaSA9IDA7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIGtleTtcbiAgZm9yIChrZXkgaW4gTykgaWYgKGtleSAhPSBJRV9QUk9UTykgaGFzKE8sIGtleSkgJiYgcmVzdWx0LnB1c2goa2V5KTtcbiAgLy8gRG9uJ3QgZW51bSBidWcgJiBoaWRkZW4ga2V5c1xuICB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkgaWYgKGhhcyhPLCBrZXkgPSBuYW1lc1tpKytdKSkge1xuICAgIH5hcnJheUluZGV4T2YocmVzdWx0LCBrZXkpIHx8IHJlc3VsdC5wdXNoKGtleSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvLyAxOS4xLjIuMTQgLyAxNS4yLjMuMTQgT2JqZWN0LmtleXMoTylcbnZhciAka2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzLWludGVybmFsJyk7XG52YXIgZW51bUJ1Z0tleXMgPSByZXF1aXJlKCcuL19lbnVtLWJ1Zy1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmtleXMgfHwgZnVuY3Rpb24ga2V5cyhPKSB7XG4gIHJldHVybiAka2V5cyhPLCBlbnVtQnVnS2V5cyk7XG59O1xuIiwiZXhwb3J0cy5mID0ge30ucHJvcGVydHlJc0VudW1lcmFibGU7XG4iLCIvLyBtb3N0IE9iamVjdCBtZXRob2RzIGJ5IEVTNiBzaG91bGQgYWNjZXB0IHByaW1pdGl2ZXNcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgY29yZSA9IHJlcXVpcmUoJy4vX2NvcmUnKTtcbnZhciBmYWlscyA9IHJlcXVpcmUoJy4vX2ZhaWxzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChLRVksIGV4ZWMpIHtcbiAgdmFyIGZuID0gKGNvcmUuT2JqZWN0IHx8IHt9KVtLRVldIHx8IE9iamVjdFtLRVldO1xuICB2YXIgZXhwID0ge307XG4gIGV4cFtLRVldID0gZXhlYyhmbik7XG4gICRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogZmFpbHMoZnVuY3Rpb24gKCkgeyBmbigxKTsgfSksICdPYmplY3QnLCBleHApO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4geyBlOiBmYWxzZSwgdjogZXhlYygpIH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4geyBlOiB0cnVlLCB2OiBlIH07XG4gIH1cbn07XG4iLCJ2YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIG5ld1Byb21pc2VDYXBhYmlsaXR5ID0gcmVxdWlyZSgnLi9fbmV3LXByb21pc2UtY2FwYWJpbGl0eScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDLCB4KSB7XG4gIGFuT2JqZWN0KEMpO1xuICBpZiAoaXNPYmplY3QoeCkgJiYgeC5jb25zdHJ1Y3RvciA9PT0gQykgcmV0dXJuIHg7XG4gIHZhciBwcm9taXNlQ2FwYWJpbGl0eSA9IG5ld1Byb21pc2VDYXBhYmlsaXR5LmYoQyk7XG4gIHZhciByZXNvbHZlID0gcHJvbWlzZUNhcGFiaWxpdHkucmVzb2x2ZTtcbiAgcmVzb2x2ZSh4KTtcbiAgcmV0dXJuIHByb21pc2VDYXBhYmlsaXR5LnByb21pc2U7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYml0bWFwLCB2YWx1ZSkge1xuICByZXR1cm4ge1xuICAgIGVudW1lcmFibGU6ICEoYml0bWFwICYgMSksXG4gICAgY29uZmlndXJhYmxlOiAhKGJpdG1hcCAmIDIpLFxuICAgIHdyaXRhYmxlOiAhKGJpdG1hcCAmIDQpLFxuICAgIHZhbHVlOiB2YWx1ZVxuICB9O1xufTtcbiIsInZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodGFyZ2V0LCBzcmMsIHNhZmUpIHtcbiAgZm9yICh2YXIga2V5IGluIHNyYykge1xuICAgIGlmIChzYWZlICYmIHRhcmdldFtrZXldKSB0YXJnZXRba2V5XSA9IHNyY1trZXldO1xuICAgIGVsc2UgaGlkZSh0YXJnZXQsIGtleSwgc3JjW2tleV0pO1xuICB9IHJldHVybiB0YXJnZXQ7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19oaWRlJyk7XG4iLCIvLyBXb3JrcyB3aXRoIF9fcHJvdG9fXyBvbmx5LiBPbGQgdjggY2FuJ3Qgd29yayB3aXRoIG51bGwgcHJvdG8gb2JqZWN0cy5cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGNoZWNrID0gZnVuY3Rpb24gKE8sIHByb3RvKSB7XG4gIGFuT2JqZWN0KE8pO1xuICBpZiAoIWlzT2JqZWN0KHByb3RvKSAmJiBwcm90byAhPT0gbnVsbCkgdGhyb3cgVHlwZUVycm9yKHByb3RvICsgXCI6IGNhbid0IHNldCBhcyBwcm90b3R5cGUhXCIpO1xufTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBzZXQ6IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCAoJ19fcHJvdG9fXycgaW4ge30gPyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gICAgZnVuY3Rpb24gKHRlc3QsIGJ1Z2d5LCBzZXQpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHNldCA9IHJlcXVpcmUoJy4vX2N0eCcpKEZ1bmN0aW9uLmNhbGwsIHJlcXVpcmUoJy4vX29iamVjdC1nb3BkJykuZihPYmplY3QucHJvdG90eXBlLCAnX19wcm90b19fJykuc2V0LCAyKTtcbiAgICAgICAgc2V0KHRlc3QsIFtdKTtcbiAgICAgICAgYnVnZ3kgPSAhKHRlc3QgaW5zdGFuY2VvZiBBcnJheSk7XG4gICAgICB9IGNhdGNoIChlKSB7IGJ1Z2d5ID0gdHJ1ZTsgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uIHNldFByb3RvdHlwZU9mKE8sIHByb3RvKSB7XG4gICAgICAgIGNoZWNrKE8sIHByb3RvKTtcbiAgICAgICAgaWYgKGJ1Z2d5KSBPLl9fcHJvdG9fXyA9IHByb3RvO1xuICAgICAgICBlbHNlIHNldChPLCBwcm90byk7XG4gICAgICAgIHJldHVybiBPO1xuICAgICAgfTtcbiAgICB9KHt9LCBmYWxzZSkgOiB1bmRlZmluZWQpLFxuICBjaGVjazogY2hlY2tcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgY29yZSA9IHJlcXVpcmUoJy4vX2NvcmUnKTtcbnZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcbnZhciBTUEVDSUVTID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoS0VZKSB7XG4gIHZhciBDID0gdHlwZW9mIGNvcmVbS0VZXSA9PSAnZnVuY3Rpb24nID8gY29yZVtLRVldIDogZ2xvYmFsW0tFWV07XG4gIGlmIChERVNDUklQVE9SUyAmJiBDICYmICFDW1NQRUNJRVNdKSBkUC5mKEMsIFNQRUNJRVMsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gIH0pO1xufTtcbiIsInZhciBkZWYgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIFRBRyA9IHJlcXVpcmUoJy4vX3drcycpKCd0b1N0cmluZ1RhZycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwgdGFnLCBzdGF0KSB7XG4gIGlmIChpdCAmJiAhaGFzKGl0ID0gc3RhdCA/IGl0IDogaXQucHJvdG90eXBlLCBUQUcpKSBkZWYoaXQsIFRBRywgeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiB0YWcgfSk7XG59O1xuIiwidmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCdrZXlzJyk7XG52YXIgdWlkID0gcmVxdWlyZSgnLi9fdWlkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHNoYXJlZFtrZXldIHx8IChzaGFyZWRba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXyc7XG52YXIgc3RvcmUgPSBnbG9iYWxbU0hBUkVEXSB8fCAoZ2xvYmFsW1NIQVJFRF0gPSB7fSk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHN0b3JlW2tleV0gfHwgKHN0b3JlW2tleV0gPSB7fSk7XG59O1xuIiwiLy8gNy4zLjIwIFNwZWNpZXNDb25zdHJ1Y3RvcihPLCBkZWZhdWx0Q29uc3RydWN0b3IpXG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBhRnVuY3Rpb24gPSByZXF1aXJlKCcuL19hLWZ1bmN0aW9uJyk7XG52YXIgU1BFQ0lFUyA9IHJlcXVpcmUoJy4vX3drcycpKCdzcGVjaWVzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBEKSB7XG4gIHZhciBDID0gYW5PYmplY3QoTykuY29uc3RydWN0b3I7XG4gIHZhciBTO1xuICByZXR1cm4gQyA9PT0gdW5kZWZpbmVkIHx8IChTID0gYW5PYmplY3QoQylbU1BFQ0lFU10pID09IHVuZGVmaW5lZCA/IEQgOiBhRnVuY3Rpb24oUyk7XG59O1xuIiwidmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xuLy8gdHJ1ZSAgLT4gU3RyaW5nI2F0XG4vLyBmYWxzZSAtPiBTdHJpbmcjY29kZVBvaW50QXRcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFRPX1NUUklORykge1xuICByZXR1cm4gZnVuY3Rpb24gKHRoYXQsIHBvcykge1xuICAgIHZhciBzID0gU3RyaW5nKGRlZmluZWQodGhhdCkpO1xuICAgIHZhciBpID0gdG9JbnRlZ2VyKHBvcyk7XG4gICAgdmFyIGwgPSBzLmxlbmd0aDtcbiAgICB2YXIgYSwgYjtcbiAgICBpZiAoaSA8IDAgfHwgaSA+PSBsKSByZXR1cm4gVE9fU1RSSU5HID8gJycgOiB1bmRlZmluZWQ7XG4gICAgYSA9IHMuY2hhckNvZGVBdChpKTtcbiAgICByZXR1cm4gYSA8IDB4ZDgwMCB8fCBhID4gMHhkYmZmIHx8IGkgKyAxID09PSBsIHx8IChiID0gcy5jaGFyQ29kZUF0KGkgKyAxKSkgPCAweGRjMDAgfHwgYiA+IDB4ZGZmZlxuICAgICAgPyBUT19TVFJJTkcgPyBzLmNoYXJBdChpKSA6IGFcbiAgICAgIDogVE9fU1RSSU5HID8gcy5zbGljZShpLCBpICsgMikgOiAoYSAtIDB4ZDgwMCA8PCAxMCkgKyAoYiAtIDB4ZGMwMCkgKyAweDEwMDAwO1xuICB9O1xufTtcbiIsInZhciBjdHggPSByZXF1aXJlKCcuL19jdHgnKTtcbnZhciBpbnZva2UgPSByZXF1aXJlKCcuL19pbnZva2UnKTtcbnZhciBodG1sID0gcmVxdWlyZSgnLi9faHRtbCcpO1xudmFyIGNlbCA9IHJlcXVpcmUoJy4vX2RvbS1jcmVhdGUnKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBwcm9jZXNzID0gZ2xvYmFsLnByb2Nlc3M7XG52YXIgc2V0VGFzayA9IGdsb2JhbC5zZXRJbW1lZGlhdGU7XG52YXIgY2xlYXJUYXNrID0gZ2xvYmFsLmNsZWFySW1tZWRpYXRlO1xudmFyIE1lc3NhZ2VDaGFubmVsID0gZ2xvYmFsLk1lc3NhZ2VDaGFubmVsO1xudmFyIERpc3BhdGNoID0gZ2xvYmFsLkRpc3BhdGNoO1xudmFyIGNvdW50ZXIgPSAwO1xudmFyIHF1ZXVlID0ge307XG52YXIgT05SRUFEWVNUQVRFQ0hBTkdFID0gJ29ucmVhZHlzdGF0ZWNoYW5nZSc7XG52YXIgZGVmZXIsIGNoYW5uZWwsIHBvcnQ7XG52YXIgcnVuID0gZnVuY3Rpb24gKCkge1xuICB2YXIgaWQgPSArdGhpcztcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGluc1xuICBpZiAocXVldWUuaGFzT3duUHJvcGVydHkoaWQpKSB7XG4gICAgdmFyIGZuID0gcXVldWVbaWRdO1xuICAgIGRlbGV0ZSBxdWV1ZVtpZF07XG4gICAgZm4oKTtcbiAgfVxufTtcbnZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudCkge1xuICBydW4uY2FsbChldmVudC5kYXRhKTtcbn07XG4vLyBOb2RlLmpzIDAuOSsgJiBJRTEwKyBoYXMgc2V0SW1tZWRpYXRlLCBvdGhlcndpc2U6XG5pZiAoIXNldFRhc2sgfHwgIWNsZWFyVGFzaykge1xuICBzZXRUYXNrID0gZnVuY3Rpb24gc2V0SW1tZWRpYXRlKGZuKSB7XG4gICAgdmFyIGFyZ3MgPSBbXTtcbiAgICB2YXIgaSA9IDE7XG4gICAgd2hpbGUgKGFyZ3VtZW50cy5sZW5ndGggPiBpKSBhcmdzLnB1c2goYXJndW1lbnRzW2krK10pO1xuICAgIHF1ZXVlWysrY291bnRlcl0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tbmV3LWZ1bmNcbiAgICAgIGludm9rZSh0eXBlb2YgZm4gPT0gJ2Z1bmN0aW9uJyA/IGZuIDogRnVuY3Rpb24oZm4pLCBhcmdzKTtcbiAgICB9O1xuICAgIGRlZmVyKGNvdW50ZXIpO1xuICAgIHJldHVybiBjb3VudGVyO1xuICB9O1xuICBjbGVhclRhc2sgPSBmdW5jdGlvbiBjbGVhckltbWVkaWF0ZShpZCkge1xuICAgIGRlbGV0ZSBxdWV1ZVtpZF07XG4gIH07XG4gIC8vIE5vZGUuanMgMC44LVxuICBpZiAocmVxdWlyZSgnLi9fY29mJykocHJvY2VzcykgPT0gJ3Byb2Nlc3MnKSB7XG4gICAgZGVmZXIgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soY3R4KHJ1biwgaWQsIDEpKTtcbiAgICB9O1xuICAvLyBTcGhlcmUgKEpTIGdhbWUgZW5naW5lKSBEaXNwYXRjaCBBUElcbiAgfSBlbHNlIGlmIChEaXNwYXRjaCAmJiBEaXNwYXRjaC5ub3cpIHtcbiAgICBkZWZlciA9IGZ1bmN0aW9uIChpZCkge1xuICAgICAgRGlzcGF0Y2gubm93KGN0eChydW4sIGlkLCAxKSk7XG4gICAgfTtcbiAgLy8gQnJvd3NlcnMgd2l0aCBNZXNzYWdlQ2hhbm5lbCwgaW5jbHVkZXMgV2ViV29ya2Vyc1xuICB9IGVsc2UgaWYgKE1lc3NhZ2VDaGFubmVsKSB7XG4gICAgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICAgIHBvcnQgPSBjaGFubmVsLnBvcnQyO1xuICAgIGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gbGlzdGVuZXI7XG4gICAgZGVmZXIgPSBjdHgocG9ydC5wb3N0TWVzc2FnZSwgcG9ydCwgMSk7XG4gIC8vIEJyb3dzZXJzIHdpdGggcG9zdE1lc3NhZ2UsIHNraXAgV2ViV29ya2Vyc1xuICAvLyBJRTggaGFzIHBvc3RNZXNzYWdlLCBidXQgaXQncyBzeW5jICYgdHlwZW9mIGl0cyBwb3N0TWVzc2FnZSBpcyAnb2JqZWN0J1xuICB9IGVsc2UgaWYgKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyICYmIHR5cGVvZiBwb3N0TWVzc2FnZSA9PSAnZnVuY3Rpb24nICYmICFnbG9iYWwuaW1wb3J0U2NyaXB0cykge1xuICAgIGRlZmVyID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICBnbG9iYWwucG9zdE1lc3NhZ2UoaWQgKyAnJywgJyonKTtcbiAgICB9O1xuICAgIGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgbGlzdGVuZXIsIGZhbHNlKTtcbiAgLy8gSUU4LVxuICB9IGVsc2UgaWYgKE9OUkVBRFlTVEFURUNIQU5HRSBpbiBjZWwoJ3NjcmlwdCcpKSB7XG4gICAgZGVmZXIgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICAgIGh0bWwuYXBwZW5kQ2hpbGQoY2VsKCdzY3JpcHQnKSlbT05SRUFEWVNUQVRFQ0hBTkdFXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaHRtbC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgICAgICAgcnVuLmNhbGwoaWQpO1xuICAgICAgfTtcbiAgICB9O1xuICAvLyBSZXN0IG9sZCBicm93c2Vyc1xuICB9IGVsc2Uge1xuICAgIGRlZmVyID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgICBzZXRUaW1lb3V0KGN0eChydW4sIGlkLCAxKSwgMCk7XG4gICAgfTtcbiAgfVxufVxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNldDogc2V0VGFzayxcbiAgY2xlYXI6IGNsZWFyVGFza1xufTtcbiIsInZhciB0b0ludGVnZXIgPSByZXF1aXJlKCcuL190by1pbnRlZ2VyJyk7XG52YXIgbWF4ID0gTWF0aC5tYXg7XG52YXIgbWluID0gTWF0aC5taW47XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpbmRleCwgbGVuZ3RoKSB7XG4gIGluZGV4ID0gdG9JbnRlZ2VyKGluZGV4KTtcbiAgcmV0dXJuIGluZGV4IDwgMCA/IG1heChpbmRleCArIGxlbmd0aCwgMCkgOiBtaW4oaW5kZXgsIGxlbmd0aCk7XG59O1xuIiwiLy8gNy4xLjQgVG9JbnRlZ2VyXG52YXIgY2VpbCA9IE1hdGguY2VpbDtcbnZhciBmbG9vciA9IE1hdGguZmxvb3I7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaXNOYU4oaXQgPSAraXQpID8gMCA6IChpdCA+IDAgPyBmbG9vciA6IGNlaWwpKGl0KTtcbn07XG4iLCIvLyB0byBpbmRleGVkIG9iamVjdCwgdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3NcbnZhciBJT2JqZWN0ID0gcmVxdWlyZSgnLi9faW9iamVjdCcpO1xudmFyIGRlZmluZWQgPSByZXF1aXJlKCcuL19kZWZpbmVkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gSU9iamVjdChkZWZpbmVkKGl0KSk7XG59O1xuIiwiLy8gNy4xLjE1IFRvTGVuZ3RoXG52YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGl0ID4gMCA/IG1pbih0b0ludGVnZXIoaXQpLCAweDFmZmZmZmZmZmZmZmZmKSA6IDA7IC8vIHBvdygyLCA1MykgLSAxID09IDkwMDcxOTkyNTQ3NDA5OTFcbn07XG4iLCIvLyA3LjEuMTMgVG9PYmplY3QoYXJndW1lbnQpXG52YXIgZGVmaW5lZCA9IHJlcXVpcmUoJy4vX2RlZmluZWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBPYmplY3QoZGVmaW5lZChpdCkpO1xufTtcbiIsIi8vIDcuMS4xIFRvUHJpbWl0aXZlKGlucHV0IFssIFByZWZlcnJlZFR5cGVdKVxudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG4vLyBpbnN0ZWFkIG9mIHRoZSBFUzYgc3BlYyB2ZXJzaW9uLCB3ZSBkaWRuJ3QgaW1wbGVtZW50IEBAdG9QcmltaXRpdmUgY2FzZVxuLy8gYW5kIHRoZSBzZWNvbmQgYXJndW1lbnQgLSBmbGFnIC0gcHJlZmVycmVkIHR5cGUgaXMgYSBzdHJpbmdcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBTKSB7XG4gIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gaXQ7XG4gIHZhciBmbiwgdmFsO1xuICBpZiAoUyAmJiB0eXBlb2YgKGZuID0gaXQudG9TdHJpbmcpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKHR5cGVvZiAoZm4gPSBpdC52YWx1ZU9mKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpIHJldHVybiB2YWw7XG4gIGlmICghUyAmJiB0eXBlb2YgKGZuID0gaXQudG9TdHJpbmcpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSkgcmV0dXJuIHZhbDtcbiAgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlXCIpO1xufTtcbiIsInZhciBpZCA9IDA7XG52YXIgcHggPSBNYXRoLnJhbmRvbSgpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiAnU3ltYm9sKCcuY29uY2F0KGtleSA9PT0gdW5kZWZpbmVkID8gJycgOiBrZXksICcpXycsICgrK2lkICsgcHgpLnRvU3RyaW5nKDM2KSk7XG59O1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGNvcmUgPSByZXF1aXJlKCcuL19jb3JlJyk7XG52YXIgTElCUkFSWSA9IHJlcXVpcmUoJy4vX2xpYnJhcnknKTtcbnZhciB3a3NFeHQgPSByZXF1aXJlKCcuL193a3MtZXh0Jyk7XG52YXIgZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSkge1xuICB2YXIgJFN5bWJvbCA9IGNvcmUuU3ltYm9sIHx8IChjb3JlLlN5bWJvbCA9IExJQlJBUlkgPyB7fSA6IGdsb2JhbC5TeW1ib2wgfHwge30pO1xuICBpZiAobmFtZS5jaGFyQXQoMCkgIT0gJ18nICYmICEobmFtZSBpbiAkU3ltYm9sKSkgZGVmaW5lUHJvcGVydHkoJFN5bWJvbCwgbmFtZSwgeyB2YWx1ZTogd2tzRXh0LmYobmFtZSkgfSk7XG59O1xuIiwiZXhwb3J0cy5mID0gcmVxdWlyZSgnLi9fd2tzJyk7XG4iLCJ2YXIgc3RvcmUgPSByZXF1aXJlKCcuL19zaGFyZWQnKSgnd2tzJyk7XG52YXIgdWlkID0gcmVxdWlyZSgnLi9fdWlkJyk7XG52YXIgU3ltYm9sID0gcmVxdWlyZSgnLi9fZ2xvYmFsJykuU3ltYm9sO1xudmFyIFVTRV9TWU1CT0wgPSB0eXBlb2YgU3ltYm9sID09ICdmdW5jdGlvbic7XG5cbnZhciAkZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgcmV0dXJuIHN0b3JlW25hbWVdIHx8IChzdG9yZVtuYW1lXSA9XG4gICAgVVNFX1NZTUJPTCAmJiBTeW1ib2xbbmFtZV0gfHwgKFVTRV9TWU1CT0wgPyBTeW1ib2wgOiB1aWQpKCdTeW1ib2wuJyArIG5hbWUpKTtcbn07XG5cbiRleHBvcnRzLnN0b3JlID0gc3RvcmU7XG4iLCJ2YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciBJVEVSQVRPUiA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19jb3JlJykuZ2V0SXRlcmF0b3JNZXRob2QgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKGl0ICE9IHVuZGVmaW5lZCkgcmV0dXJuIGl0W0lURVJBVE9SXVxuICAgIHx8IGl0WydAQGl0ZXJhdG9yJ11cbiAgICB8fCBJdGVyYXRvcnNbY2xhc3NvZihpdCldO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi9fYWRkLXRvLXVuc2NvcGFibGVzJyk7XG52YXIgc3RlcCA9IHJlcXVpcmUoJy4vX2l0ZXItc3RlcCcpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcblxuLy8gMjIuMS4zLjQgQXJyYXkucHJvdG90eXBlLmVudHJpZXMoKVxuLy8gMjIuMS4zLjEzIEFycmF5LnByb3RvdHlwZS5rZXlzKClcbi8vIDIyLjEuMy4yOSBBcnJheS5wcm90b3R5cGUudmFsdWVzKClcbi8vIDIyLjEuMy4zMCBBcnJheS5wcm90b3R5cGVbQEBpdGVyYXRvcl0oKVxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpKEFycmF5LCAnQXJyYXknLCBmdW5jdGlvbiAoaXRlcmF0ZWQsIGtpbmQpIHtcbiAgdGhpcy5fdCA9IHRvSU9iamVjdChpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuICB0aGlzLl9rID0ga2luZDsgICAgICAgICAgICAgICAgLy8ga2luZFxuLy8gMjIuMS41LjIuMSAlQXJyYXlJdGVyYXRvclByb3RvdHlwZSUubmV4dCgpXG59LCBmdW5jdGlvbiAoKSB7XG4gIHZhciBPID0gdGhpcy5fdDtcbiAgdmFyIGtpbmQgPSB0aGlzLl9rO1xuICB2YXIgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmICghTyB8fCBpbmRleCA+PSBPLmxlbmd0aCkge1xuICAgIHRoaXMuX3QgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHN0ZXAoMSk7XG4gIH1cbiAgaWYgKGtpbmQgPT0gJ2tleXMnKSByZXR1cm4gc3RlcCgwLCBpbmRleCk7XG4gIGlmIChraW5kID09ICd2YWx1ZXMnKSByZXR1cm4gc3RlcCgwLCBPW2luZGV4XSk7XG4gIHJldHVybiBzdGVwKDAsIFtpbmRleCwgT1tpbmRleF1dKTtcbn0sICd2YWx1ZXMnKTtcblxuLy8gYXJndW1lbnRzTGlzdFtAQGl0ZXJhdG9yXSBpcyAlQXJyYXlQcm90b192YWx1ZXMlICg5LjQuNC42LCA5LjQuNC43KVxuSXRlcmF0b3JzLkFyZ3VtZW50cyA9IEl0ZXJhdG9ycy5BcnJheTtcblxuYWRkVG9VbnNjb3BhYmxlcygna2V5cycpO1xuYWRkVG9VbnNjb3BhYmxlcygndmFsdWVzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCdlbnRyaWVzJyk7XG4iLCIvLyAyMC4yLjIuMjEgTWF0aC5sb2cxMCh4KVxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlMsICdNYXRoJywge1xuICBsb2cxMDogZnVuY3Rpb24gbG9nMTAoeCkge1xuICAgIHJldHVybiBNYXRoLmxvZyh4KSAqIE1hdGguTE9HMTBFO1xuICB9XG59KTtcbiIsIi8vIDIwLjEuMi4yIE51bWJlci5pc0Zpbml0ZShudW1iZXIpXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIF9pc0Zpbml0ZSA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmlzRmluaXRlO1xuXG4kZXhwb3J0KCRleHBvcnQuUywgJ051bWJlcicsIHtcbiAgaXNGaW5pdGU6IGZ1bmN0aW9uIGlzRmluaXRlKGl0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnbnVtYmVyJyAmJiBfaXNGaW5pdGUoaXQpO1xuICB9XG59KTtcbiIsIi8vIDE5LjEuMy4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UpXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiwgJ09iamVjdCcsIHsgYXNzaWduOiByZXF1aXJlKCcuL19vYmplY3QtYXNzaWduJykgfSk7XG4iLCJ2YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuLy8gMTkuMS4yLjIgLyAxNS4yLjMuNSBPYmplY3QuY3JlYXRlKE8gWywgUHJvcGVydGllc10pXG4kZXhwb3J0KCRleHBvcnQuUywgJ09iamVjdCcsIHsgY3JlYXRlOiByZXF1aXJlKCcuL19vYmplY3QtY3JlYXRlJykgfSk7XG4iLCJ2YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuLy8gMTkuMS4yLjQgLyAxNS4yLjMuNiBPYmplY3QuZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcylcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIXJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJyksICdPYmplY3QnLCB7IGRlZmluZVByb3BlcnR5OiByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mIH0pO1xuIiwiLy8gMTkuMS4yLjYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKVxudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcbnZhciAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcGQnKS5mO1xuXG5yZXF1aXJlKCcuL19vYmplY3Qtc2FwJykoJ2dldE93blByb3BlcnR5RGVzY3JpcHRvcicsIGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihpdCwga2V5KSB7XG4gICAgcmV0dXJuICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodG9JT2JqZWN0KGl0KSwga2V5KTtcbiAgfTtcbn0pO1xuIiwiLy8gMTkuMS4yLjkgT2JqZWN0LmdldFByb3RvdHlwZU9mKE8pXG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKTtcbnZhciAkZ2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCcuL19vYmplY3QtZ3BvJyk7XG5cbnJlcXVpcmUoJy4vX29iamVjdC1zYXAnKSgnZ2V0UHJvdG90eXBlT2YnLCBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBmdW5jdGlvbiBnZXRQcm90b3R5cGVPZihpdCkge1xuICAgIHJldHVybiAkZ2V0UHJvdG90eXBlT2YodG9PYmplY3QoaXQpKTtcbiAgfTtcbn0pO1xuIiwiLy8gMTkuMS4zLjE5IE9iamVjdC5zZXRQcm90b3R5cGVPZihPLCBwcm90bylcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG4kZXhwb3J0KCRleHBvcnQuUywgJ09iamVjdCcsIHsgc2V0UHJvdG90eXBlT2Y6IHJlcXVpcmUoJy4vX3NldC1wcm90bycpLnNldCB9KTtcbiIsIiIsIid1c2Ugc3RyaWN0JztcbnZhciBMSUJSQVJZID0gcmVxdWlyZSgnLi9fbGlicmFyeScpO1xudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGN0eCA9IHJlcXVpcmUoJy4vX2N0eCcpO1xudmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuL19jbGFzc29mJyk7XG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpO1xudmFyIGFuSW5zdGFuY2UgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpO1xudmFyIGZvck9mID0gcmVxdWlyZSgnLi9fZm9yLW9mJyk7XG52YXIgc3BlY2llc0NvbnN0cnVjdG9yID0gcmVxdWlyZSgnLi9fc3BlY2llcy1jb25zdHJ1Y3RvcicpO1xudmFyIHRhc2sgPSByZXF1aXJlKCcuL190YXNrJykuc2V0O1xudmFyIG1pY3JvdGFzayA9IHJlcXVpcmUoJy4vX21pY3JvdGFzaycpKCk7XG52YXIgbmV3UHJvbWlzZUNhcGFiaWxpdHlNb2R1bGUgPSByZXF1aXJlKCcuL19uZXctcHJvbWlzZS1jYXBhYmlsaXR5Jyk7XG52YXIgcGVyZm9ybSA9IHJlcXVpcmUoJy4vX3BlcmZvcm0nKTtcbnZhciBwcm9taXNlUmVzb2x2ZSA9IHJlcXVpcmUoJy4vX3Byb21pc2UtcmVzb2x2ZScpO1xudmFyIFBST01JU0UgPSAnUHJvbWlzZSc7XG52YXIgVHlwZUVycm9yID0gZ2xvYmFsLlR5cGVFcnJvcjtcbnZhciBwcm9jZXNzID0gZ2xvYmFsLnByb2Nlc3M7XG52YXIgJFByb21pc2UgPSBnbG9iYWxbUFJPTUlTRV07XG52YXIgaXNOb2RlID0gY2xhc3NvZihwcm9jZXNzKSA9PSAncHJvY2Vzcyc7XG52YXIgZW1wdHkgPSBmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH07XG52YXIgSW50ZXJuYWwsIG5ld0dlbmVyaWNQcm9taXNlQ2FwYWJpbGl0eSwgT3duUHJvbWlzZUNhcGFiaWxpdHksIFdyYXBwZXI7XG52YXIgbmV3UHJvbWlzZUNhcGFiaWxpdHkgPSBuZXdHZW5lcmljUHJvbWlzZUNhcGFiaWxpdHkgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eU1vZHVsZS5mO1xuXG52YXIgVVNFX05BVElWRSA9ICEhZnVuY3Rpb24gKCkge1xuICB0cnkge1xuICAgIC8vIGNvcnJlY3Qgc3ViY2xhc3Npbmcgd2l0aCBAQHNwZWNpZXMgc3VwcG9ydFxuICAgIHZhciBwcm9taXNlID0gJFByb21pc2UucmVzb2x2ZSgxKTtcbiAgICB2YXIgRmFrZVByb21pc2UgPSAocHJvbWlzZS5jb25zdHJ1Y3RvciA9IHt9KVtyZXF1aXJlKCcuL193a3MnKSgnc3BlY2llcycpXSA9IGZ1bmN0aW9uIChleGVjKSB7XG4gICAgICBleGVjKGVtcHR5LCBlbXB0eSk7XG4gICAgfTtcbiAgICAvLyB1bmhhbmRsZWQgcmVqZWN0aW9ucyB0cmFja2luZyBzdXBwb3J0LCBOb2RlSlMgUHJvbWlzZSB3aXRob3V0IGl0IGZhaWxzIEBAc3BlY2llcyB0ZXN0XG4gICAgcmV0dXJuIChpc05vZGUgfHwgdHlwZW9mIFByb21pc2VSZWplY3Rpb25FdmVudCA9PSAnZnVuY3Rpb24nKSAmJiBwcm9taXNlLnRoZW4oZW1wdHkpIGluc3RhbmNlb2YgRmFrZVByb21pc2U7XG4gIH0gY2F0Y2ggKGUpIHsgLyogZW1wdHkgKi8gfVxufSgpO1xuXG4vLyBoZWxwZXJzXG52YXIgaXNUaGVuYWJsZSA9IGZ1bmN0aW9uIChpdCkge1xuICB2YXIgdGhlbjtcbiAgcmV0dXJuIGlzT2JqZWN0KGl0KSAmJiB0eXBlb2YgKHRoZW4gPSBpdC50aGVuKSA9PSAnZnVuY3Rpb24nID8gdGhlbiA6IGZhbHNlO1xufTtcbnZhciBub3RpZnkgPSBmdW5jdGlvbiAocHJvbWlzZSwgaXNSZWplY3QpIHtcbiAgaWYgKHByb21pc2UuX24pIHJldHVybjtcbiAgcHJvbWlzZS5fbiA9IHRydWU7XG4gIHZhciBjaGFpbiA9IHByb21pc2UuX2M7XG4gIG1pY3JvdGFzayhmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHVlID0gcHJvbWlzZS5fdjtcbiAgICB2YXIgb2sgPSBwcm9taXNlLl9zID09IDE7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciBydW4gPSBmdW5jdGlvbiAocmVhY3Rpb24pIHtcbiAgICAgIHZhciBoYW5kbGVyID0gb2sgPyByZWFjdGlvbi5vayA6IHJlYWN0aW9uLmZhaWw7XG4gICAgICB2YXIgcmVzb2x2ZSA9IHJlYWN0aW9uLnJlc29sdmU7XG4gICAgICB2YXIgcmVqZWN0ID0gcmVhY3Rpb24ucmVqZWN0O1xuICAgICAgdmFyIGRvbWFpbiA9IHJlYWN0aW9uLmRvbWFpbjtcbiAgICAgIHZhciByZXN1bHQsIHRoZW47XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoaGFuZGxlcikge1xuICAgICAgICAgIGlmICghb2spIHtcbiAgICAgICAgICAgIGlmIChwcm9taXNlLl9oID09IDIpIG9uSGFuZGxlVW5oYW5kbGVkKHByb21pc2UpO1xuICAgICAgICAgICAgcHJvbWlzZS5faCA9IDE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChoYW5kbGVyID09PSB0cnVlKSByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkb21haW4pIGRvbWFpbi5lbnRlcigpO1xuICAgICAgICAgICAgcmVzdWx0ID0gaGFuZGxlcih2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoZG9tYWluKSBkb21haW4uZXhpdCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocmVzdWx0ID09PSByZWFjdGlvbi5wcm9taXNlKSB7XG4gICAgICAgICAgICByZWplY3QoVHlwZUVycm9yKCdQcm9taXNlLWNoYWluIGN5Y2xlJykpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGhlbiA9IGlzVGhlbmFibGUocmVzdWx0KSkge1xuICAgICAgICAgICAgdGhlbi5jYWxsKHJlc3VsdCwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICB9IGVsc2UgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGVsc2UgcmVqZWN0KHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH07XG4gICAgd2hpbGUgKGNoYWluLmxlbmd0aCA+IGkpIHJ1bihjaGFpbltpKytdKTsgLy8gdmFyaWFibGUgbGVuZ3RoIC0gY2FuJ3QgdXNlIGZvckVhY2hcbiAgICBwcm9taXNlLl9jID0gW107XG4gICAgcHJvbWlzZS5fbiA9IGZhbHNlO1xuICAgIGlmIChpc1JlamVjdCAmJiAhcHJvbWlzZS5faCkgb25VbmhhbmRsZWQocHJvbWlzZSk7XG4gIH0pO1xufTtcbnZhciBvblVuaGFuZGxlZCA9IGZ1bmN0aW9uIChwcm9taXNlKSB7XG4gIHRhc2suY2FsbChnbG9iYWwsIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdmFsdWUgPSBwcm9taXNlLl92O1xuICAgIHZhciB1bmhhbmRsZWQgPSBpc1VuaGFuZGxlZChwcm9taXNlKTtcbiAgICB2YXIgcmVzdWx0LCBoYW5kbGVyLCBjb25zb2xlO1xuICAgIGlmICh1bmhhbmRsZWQpIHtcbiAgICAgIHJlc3VsdCA9IHBlcmZvcm0oZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaXNOb2RlKSB7XG4gICAgICAgICAgcHJvY2Vzcy5lbWl0KCd1bmhhbmRsZWRSZWplY3Rpb24nLCB2YWx1ZSwgcHJvbWlzZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaGFuZGxlciA9IGdsb2JhbC5vbnVuaGFuZGxlZHJlamVjdGlvbikge1xuICAgICAgICAgIGhhbmRsZXIoeyBwcm9taXNlOiBwcm9taXNlLCByZWFzb246IHZhbHVlIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKChjb25zb2xlID0gZ2xvYmFsLmNvbnNvbGUpICYmIGNvbnNvbGUuZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdVbmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24nLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgLy8gQnJvd3NlcnMgc2hvdWxkIG5vdCB0cmlnZ2VyIGByZWplY3Rpb25IYW5kbGVkYCBldmVudCBpZiBpdCB3YXMgaGFuZGxlZCBoZXJlLCBOb2RlSlMgLSBzaG91bGRcbiAgICAgIHByb21pc2UuX2ggPSBpc05vZGUgfHwgaXNVbmhhbmRsZWQocHJvbWlzZSkgPyAyIDogMTtcbiAgICB9IHByb21pc2UuX2EgPSB1bmRlZmluZWQ7XG4gICAgaWYgKHVuaGFuZGxlZCAmJiByZXN1bHQuZSkgdGhyb3cgcmVzdWx0LnY7XG4gIH0pO1xufTtcbnZhciBpc1VuaGFuZGxlZCA9IGZ1bmN0aW9uIChwcm9taXNlKSB7XG4gIGlmIChwcm9taXNlLl9oID09IDEpIHJldHVybiBmYWxzZTtcbiAgdmFyIGNoYWluID0gcHJvbWlzZS5fYSB8fCBwcm9taXNlLl9jO1xuICB2YXIgaSA9IDA7XG4gIHZhciByZWFjdGlvbjtcbiAgd2hpbGUgKGNoYWluLmxlbmd0aCA+IGkpIHtcbiAgICByZWFjdGlvbiA9IGNoYWluW2krK107XG4gICAgaWYgKHJlYWN0aW9uLmZhaWwgfHwgIWlzVW5oYW5kbGVkKHJlYWN0aW9uLnByb21pc2UpKSByZXR1cm4gZmFsc2U7XG4gIH0gcmV0dXJuIHRydWU7XG59O1xudmFyIG9uSGFuZGxlVW5oYW5kbGVkID0gZnVuY3Rpb24gKHByb21pc2UpIHtcbiAgdGFzay5jYWxsKGdsb2JhbCwgZnVuY3Rpb24gKCkge1xuICAgIHZhciBoYW5kbGVyO1xuICAgIGlmIChpc05vZGUpIHtcbiAgICAgIHByb2Nlc3MuZW1pdCgncmVqZWN0aW9uSGFuZGxlZCcsIHByb21pc2UpO1xuICAgIH0gZWxzZSBpZiAoaGFuZGxlciA9IGdsb2JhbC5vbnJlamVjdGlvbmhhbmRsZWQpIHtcbiAgICAgIGhhbmRsZXIoeyBwcm9taXNlOiBwcm9taXNlLCByZWFzb246IHByb21pc2UuX3YgfSk7XG4gICAgfVxuICB9KTtcbn07XG52YXIgJHJlamVjdCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICB2YXIgcHJvbWlzZSA9IHRoaXM7XG4gIGlmIChwcm9taXNlLl9kKSByZXR1cm47XG4gIHByb21pc2UuX2QgPSB0cnVlO1xuICBwcm9taXNlID0gcHJvbWlzZS5fdyB8fCBwcm9taXNlOyAvLyB1bndyYXBcbiAgcHJvbWlzZS5fdiA9IHZhbHVlO1xuICBwcm9taXNlLl9zID0gMjtcbiAgaWYgKCFwcm9taXNlLl9hKSBwcm9taXNlLl9hID0gcHJvbWlzZS5fYy5zbGljZSgpO1xuICBub3RpZnkocHJvbWlzZSwgdHJ1ZSk7XG59O1xudmFyICRyZXNvbHZlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gIHZhciBwcm9taXNlID0gdGhpcztcbiAgdmFyIHRoZW47XG4gIGlmIChwcm9taXNlLl9kKSByZXR1cm47XG4gIHByb21pc2UuX2QgPSB0cnVlO1xuICBwcm9taXNlID0gcHJvbWlzZS5fdyB8fCBwcm9taXNlOyAvLyB1bndyYXBcbiAgdHJ5IHtcbiAgICBpZiAocHJvbWlzZSA9PT0gdmFsdWUpIHRocm93IFR5cGVFcnJvcihcIlByb21pc2UgY2FuJ3QgYmUgcmVzb2x2ZWQgaXRzZWxmXCIpO1xuICAgIGlmICh0aGVuID0gaXNUaGVuYWJsZSh2YWx1ZSkpIHtcbiAgICAgIG1pY3JvdGFzayhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB3cmFwcGVyID0geyBfdzogcHJvbWlzZSwgX2Q6IGZhbHNlIH07IC8vIHdyYXBcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGVuLmNhbGwodmFsdWUsIGN0eCgkcmVzb2x2ZSwgd3JhcHBlciwgMSksIGN0eCgkcmVqZWN0LCB3cmFwcGVyLCAxKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAkcmVqZWN0LmNhbGwod3JhcHBlciwgZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9taXNlLl92ID0gdmFsdWU7XG4gICAgICBwcm9taXNlLl9zID0gMTtcbiAgICAgIG5vdGlmeShwcm9taXNlLCBmYWxzZSk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgJHJlamVjdC5jYWxsKHsgX3c6IHByb21pc2UsIF9kOiBmYWxzZSB9LCBlKTsgLy8gd3JhcFxuICB9XG59O1xuXG4vLyBjb25zdHJ1Y3RvciBwb2x5ZmlsbFxuaWYgKCFVU0VfTkFUSVZFKSB7XG4gIC8vIDI1LjQuMy4xIFByb21pc2UoZXhlY3V0b3IpXG4gICRQcm9taXNlID0gZnVuY3Rpb24gUHJvbWlzZShleGVjdXRvcikge1xuICAgIGFuSW5zdGFuY2UodGhpcywgJFByb21pc2UsIFBST01JU0UsICdfaCcpO1xuICAgIGFGdW5jdGlvbihleGVjdXRvcik7XG4gICAgSW50ZXJuYWwuY2FsbCh0aGlzKTtcbiAgICB0cnkge1xuICAgICAgZXhlY3V0b3IoY3R4KCRyZXNvbHZlLCB0aGlzLCAxKSwgY3R4KCRyZWplY3QsIHRoaXMsIDEpKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICRyZWplY3QuY2FsbCh0aGlzLCBlcnIpO1xuICAgIH1cbiAgfTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gIEludGVybmFsID0gZnVuY3Rpb24gUHJvbWlzZShleGVjdXRvcikge1xuICAgIHRoaXMuX2MgPSBbXTsgICAgICAgICAgICAgLy8gPC0gYXdhaXRpbmcgcmVhY3Rpb25zXG4gICAgdGhpcy5fYSA9IHVuZGVmaW5lZDsgICAgICAvLyA8LSBjaGVja2VkIGluIGlzVW5oYW5kbGVkIHJlYWN0aW9uc1xuICAgIHRoaXMuX3MgPSAwOyAgICAgICAgICAgICAgLy8gPC0gc3RhdGVcbiAgICB0aGlzLl9kID0gZmFsc2U7ICAgICAgICAgIC8vIDwtIGRvbmVcbiAgICB0aGlzLl92ID0gdW5kZWZpbmVkOyAgICAgIC8vIDwtIHZhbHVlXG4gICAgdGhpcy5faCA9IDA7ICAgICAgICAgICAgICAvLyA8LSByZWplY3Rpb24gc3RhdGUsIDAgLSBkZWZhdWx0LCAxIC0gaGFuZGxlZCwgMiAtIHVuaGFuZGxlZFxuICAgIHRoaXMuX24gPSBmYWxzZTsgICAgICAgICAgLy8gPC0gbm90aWZ5XG4gIH07XG4gIEludGVybmFsLnByb3RvdHlwZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpKCRQcm9taXNlLnByb3RvdHlwZSwge1xuICAgIC8vIDI1LjQuNS4zIFByb21pc2UucHJvdG90eXBlLnRoZW4ob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpXG4gICAgdGhlbjogZnVuY3Rpb24gdGhlbihvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuICAgICAgdmFyIHJlYWN0aW9uID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkoc3BlY2llc0NvbnN0cnVjdG9yKHRoaXMsICRQcm9taXNlKSk7XG4gICAgICByZWFjdGlvbi5vayA9IHR5cGVvZiBvbkZ1bGZpbGxlZCA9PSAnZnVuY3Rpb24nID8gb25GdWxmaWxsZWQgOiB0cnVlO1xuICAgICAgcmVhY3Rpb24uZmFpbCA9IHR5cGVvZiBvblJlamVjdGVkID09ICdmdW5jdGlvbicgJiYgb25SZWplY3RlZDtcbiAgICAgIHJlYWN0aW9uLmRvbWFpbiA9IGlzTm9kZSA/IHByb2Nlc3MuZG9tYWluIDogdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fYy5wdXNoKHJlYWN0aW9uKTtcbiAgICAgIGlmICh0aGlzLl9hKSB0aGlzLl9hLnB1c2gocmVhY3Rpb24pO1xuICAgICAgaWYgKHRoaXMuX3MpIG5vdGlmeSh0aGlzLCBmYWxzZSk7XG4gICAgICByZXR1cm4gcmVhY3Rpb24ucHJvbWlzZTtcbiAgICB9LFxuICAgIC8vIDI1LjQuNS4xIFByb21pc2UucHJvdG90eXBlLmNhdGNoKG9uUmVqZWN0ZWQpXG4gICAgJ2NhdGNoJzogZnVuY3Rpb24gKG9uUmVqZWN0ZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnRoZW4odW5kZWZpbmVkLCBvblJlamVjdGVkKTtcbiAgICB9XG4gIH0pO1xuICBPd25Qcm9taXNlQ2FwYWJpbGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcHJvbWlzZSA9IG5ldyBJbnRlcm5hbCgpO1xuICAgIHRoaXMucHJvbWlzZSA9IHByb21pc2U7XG4gICAgdGhpcy5yZXNvbHZlID0gY3R4KCRyZXNvbHZlLCBwcm9taXNlLCAxKTtcbiAgICB0aGlzLnJlamVjdCA9IGN0eCgkcmVqZWN0LCBwcm9taXNlLCAxKTtcbiAgfTtcbiAgbmV3UHJvbWlzZUNhcGFiaWxpdHlNb2R1bGUuZiA9IG5ld1Byb21pc2VDYXBhYmlsaXR5ID0gZnVuY3Rpb24gKEMpIHtcbiAgICByZXR1cm4gQyA9PT0gJFByb21pc2UgfHwgQyA9PT0gV3JhcHBlclxuICAgICAgPyBuZXcgT3duUHJvbWlzZUNhcGFiaWxpdHkoQylcbiAgICAgIDogbmV3R2VuZXJpY1Byb21pc2VDYXBhYmlsaXR5KEMpO1xuICB9O1xufVxuXG4kZXhwb3J0KCRleHBvcnQuRyArICRleHBvcnQuVyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCB7IFByb21pc2U6ICRQcm9taXNlIH0pO1xucmVxdWlyZSgnLi9fc2V0LXRvLXN0cmluZy10YWcnKSgkUHJvbWlzZSwgUFJPTUlTRSk7XG5yZXF1aXJlKCcuL19zZXQtc3BlY2llcycpKFBST01JU0UpO1xuV3JhcHBlciA9IHJlcXVpcmUoJy4vX2NvcmUnKVtQUk9NSVNFXTtcblxuLy8gc3RhdGljc1xuJGV4cG9ydCgkZXhwb3J0LlMgKyAkZXhwb3J0LkYgKiAhVVNFX05BVElWRSwgUFJPTUlTRSwge1xuICAvLyAyNS40LjQuNSBQcm9taXNlLnJlamVjdChyKVxuICByZWplY3Q6IGZ1bmN0aW9uIHJlamVjdChyKSB7XG4gICAgdmFyIGNhcGFiaWxpdHkgPSBuZXdQcm9taXNlQ2FwYWJpbGl0eSh0aGlzKTtcbiAgICB2YXIgJCRyZWplY3QgPSBjYXBhYmlsaXR5LnJlamVjdDtcbiAgICAkJHJlamVjdChyKTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTtcbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogKExJQlJBUlkgfHwgIVVTRV9OQVRJVkUpLCBQUk9NSVNFLCB7XG4gIC8vIDI1LjQuNC42IFByb21pc2UucmVzb2x2ZSh4KVxuICByZXNvbHZlOiBmdW5jdGlvbiByZXNvbHZlKHgpIHtcbiAgICByZXR1cm4gcHJvbWlzZVJlc29sdmUoTElCUkFSWSAmJiB0aGlzID09PSBXcmFwcGVyID8gJFByb21pc2UgOiB0aGlzLCB4KTtcbiAgfVxufSk7XG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICEoVVNFX05BVElWRSAmJiByZXF1aXJlKCcuL19pdGVyLWRldGVjdCcpKGZ1bmN0aW9uIChpdGVyKSB7XG4gICRQcm9taXNlLmFsbChpdGVyKVsnY2F0Y2gnXShlbXB0eSk7XG59KSksIFBST01JU0UsIHtcbiAgLy8gMjUuNC40LjEgUHJvbWlzZS5hbGwoaXRlcmFibGUpXG4gIGFsbDogZnVuY3Rpb24gYWxsKGl0ZXJhYmxlKSB7XG4gICAgdmFyIEMgPSB0aGlzO1xuICAgIHZhciBjYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHkoQyk7XG4gICAgdmFyIHJlc29sdmUgPSBjYXBhYmlsaXR5LnJlc29sdmU7XG4gICAgdmFyIHJlamVjdCA9IGNhcGFiaWxpdHkucmVqZWN0O1xuICAgIHZhciByZXN1bHQgPSBwZXJmb3JtKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICAgIHZhciBpbmRleCA9IDA7XG4gICAgICB2YXIgcmVtYWluaW5nID0gMTtcbiAgICAgIGZvck9mKGl0ZXJhYmxlLCBmYWxzZSwgZnVuY3Rpb24gKHByb21pc2UpIHtcbiAgICAgICAgdmFyICRpbmRleCA9IGluZGV4Kys7XG4gICAgICAgIHZhciBhbHJlYWR5Q2FsbGVkID0gZmFsc2U7XG4gICAgICAgIHZhbHVlcy5wdXNoKHVuZGVmaW5lZCk7XG4gICAgICAgIHJlbWFpbmluZysrO1xuICAgICAgICBDLnJlc29sdmUocHJvbWlzZSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICBpZiAoYWxyZWFkeUNhbGxlZCkgcmV0dXJuO1xuICAgICAgICAgIGFscmVhZHlDYWxsZWQgPSB0cnVlO1xuICAgICAgICAgIHZhbHVlc1skaW5kZXhdID0gdmFsdWU7XG4gICAgICAgICAgLS1yZW1haW5pbmcgfHwgcmVzb2x2ZSh2YWx1ZXMpO1xuICAgICAgICB9LCByZWplY3QpO1xuICAgICAgfSk7XG4gICAgICAtLXJlbWFpbmluZyB8fCByZXNvbHZlKHZhbHVlcyk7XG4gICAgfSk7XG4gICAgaWYgKHJlc3VsdC5lKSByZWplY3QocmVzdWx0LnYpO1xuICAgIHJldHVybiBjYXBhYmlsaXR5LnByb21pc2U7XG4gIH0sXG4gIC8vIDI1LjQuNC40IFByb21pc2UucmFjZShpdGVyYWJsZSlcbiAgcmFjZTogZnVuY3Rpb24gcmFjZShpdGVyYWJsZSkge1xuICAgIHZhciBDID0gdGhpcztcbiAgICB2YXIgY2FwYWJpbGl0eSA9IG5ld1Byb21pc2VDYXBhYmlsaXR5KEMpO1xuICAgIHZhciByZWplY3QgPSBjYXBhYmlsaXR5LnJlamVjdDtcbiAgICB2YXIgcmVzdWx0ID0gcGVyZm9ybShmdW5jdGlvbiAoKSB7XG4gICAgICBmb3JPZihpdGVyYWJsZSwgZmFsc2UsIGZ1bmN0aW9uIChwcm9taXNlKSB7XG4gICAgICAgIEMucmVzb2x2ZShwcm9taXNlKS50aGVuKGNhcGFiaWxpdHkucmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGlmIChyZXN1bHQuZSkgcmVqZWN0KHJlc3VsdC52KTtcbiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlO1xuICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciAkYXQgPSByZXF1aXJlKCcuL19zdHJpbmctYXQnKSh0cnVlKTtcblxuLy8gMjEuMS4zLjI3IFN0cmluZy5wcm90b3R5cGVbQEBpdGVyYXRvcl0oKVxucmVxdWlyZSgnLi9faXRlci1kZWZpbmUnKShTdHJpbmcsICdTdHJpbmcnLCBmdW5jdGlvbiAoaXRlcmF0ZWQpIHtcbiAgdGhpcy5fdCA9IFN0cmluZyhpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuLy8gMjEuMS41LjIuMSAlU3RyaW5nSXRlcmF0b3JQcm90b3R5cGUlLm5leHQoKVxufSwgZnVuY3Rpb24gKCkge1xuICB2YXIgTyA9IHRoaXMuX3Q7XG4gIHZhciBpbmRleCA9IHRoaXMuX2k7XG4gIHZhciBwb2ludDtcbiAgaWYgKGluZGV4ID49IE8ubGVuZ3RoKSByZXR1cm4geyB2YWx1ZTogdW5kZWZpbmVkLCBkb25lOiB0cnVlIH07XG4gIHBvaW50ID0gJGF0KE8sIGluZGV4KTtcbiAgdGhpcy5faSArPSBwb2ludC5sZW5ndGg7XG4gIHJldHVybiB7IHZhbHVlOiBwb2ludCwgZG9uZTogZmFsc2UgfTtcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gRUNNQVNjcmlwdCA2IHN5bWJvbHMgc2hpbVxudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIE1FVEEgPSByZXF1aXJlKCcuL19tZXRhJykuS0VZO1xudmFyICRmYWlscyA9IHJlcXVpcmUoJy4vX2ZhaWxzJyk7XG52YXIgc2hhcmVkID0gcmVxdWlyZSgnLi9fc2hhcmVkJyk7XG52YXIgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4vX3VpZCcpO1xudmFyIHdrcyA9IHJlcXVpcmUoJy4vX3drcycpO1xudmFyIHdrc0V4dCA9IHJlcXVpcmUoJy4vX3drcy1leHQnKTtcbnZhciB3a3NEZWZpbmUgPSByZXF1aXJlKCcuL193a3MtZGVmaW5lJyk7XG52YXIgZW51bUtleXMgPSByZXF1aXJlKCcuL19lbnVtLWtleXMnKTtcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnLi9faXMtYXJyYXknKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciBfY3JlYXRlID0gcmVxdWlyZSgnLi9fb2JqZWN0LWNyZWF0ZScpO1xudmFyIGdPUE5FeHQgPSByZXF1aXJlKCcuL19vYmplY3QtZ29wbi1leHQnKTtcbnZhciAkR09QRCA9IHJlcXVpcmUoJy4vX29iamVjdC1nb3BkJyk7XG52YXIgJERQID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJyk7XG52YXIgJGtleXMgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cycpO1xudmFyIGdPUEQgPSAkR09QRC5mO1xudmFyIGRQID0gJERQLmY7XG52YXIgZ09QTiA9IGdPUE5FeHQuZjtcbnZhciAkU3ltYm9sID0gZ2xvYmFsLlN5bWJvbDtcbnZhciAkSlNPTiA9IGdsb2JhbC5KU09OO1xudmFyIF9zdHJpbmdpZnkgPSAkSlNPTiAmJiAkSlNPTi5zdHJpbmdpZnk7XG52YXIgUFJPVE9UWVBFID0gJ3Byb3RvdHlwZSc7XG52YXIgSElEREVOID0gd2tzKCdfaGlkZGVuJyk7XG52YXIgVE9fUFJJTUlUSVZFID0gd2tzKCd0b1ByaW1pdGl2ZScpO1xudmFyIGlzRW51bSA9IHt9LnByb3BlcnR5SXNFbnVtZXJhYmxlO1xudmFyIFN5bWJvbFJlZ2lzdHJ5ID0gc2hhcmVkKCdzeW1ib2wtcmVnaXN0cnknKTtcbnZhciBBbGxTeW1ib2xzID0gc2hhcmVkKCdzeW1ib2xzJyk7XG52YXIgT1BTeW1ib2xzID0gc2hhcmVkKCdvcC1zeW1ib2xzJyk7XG52YXIgT2JqZWN0UHJvdG8gPSBPYmplY3RbUFJPVE9UWVBFXTtcbnZhciBVU0VfTkFUSVZFID0gdHlwZW9mICRTeW1ib2wgPT0gJ2Z1bmN0aW9uJztcbnZhciBRT2JqZWN0ID0gZ2xvYmFsLlFPYmplY3Q7XG4vLyBEb24ndCB1c2Ugc2V0dGVycyBpbiBRdCBTY3JpcHQsIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy8xNzNcbnZhciBzZXR0ZXIgPSAhUU9iamVjdCB8fCAhUU9iamVjdFtQUk9UT1RZUEVdIHx8ICFRT2JqZWN0W1BST1RPVFlQRV0uZmluZENoaWxkO1xuXG4vLyBmYWxsYmFjayBmb3Igb2xkIEFuZHJvaWQsIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD02ODdcbnZhciBzZXRTeW1ib2xEZXNjID0gREVTQ1JJUFRPUlMgJiYgJGZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIF9jcmVhdGUoZFAoe30sICdhJywge1xuICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gZFAodGhpcywgJ2EnLCB7IHZhbHVlOiA3IH0pLmE7IH1cbiAgfSkpLmEgIT0gNztcbn0pID8gZnVuY3Rpb24gKGl0LCBrZXksIEQpIHtcbiAgdmFyIHByb3RvRGVzYyA9IGdPUEQoT2JqZWN0UHJvdG8sIGtleSk7XG4gIGlmIChwcm90b0Rlc2MpIGRlbGV0ZSBPYmplY3RQcm90b1trZXldO1xuICBkUChpdCwga2V5LCBEKTtcbiAgaWYgKHByb3RvRGVzYyAmJiBpdCAhPT0gT2JqZWN0UHJvdG8pIGRQKE9iamVjdFByb3RvLCBrZXksIHByb3RvRGVzYyk7XG59IDogZFA7XG5cbnZhciB3cmFwID0gZnVuY3Rpb24gKHRhZykge1xuICB2YXIgc3ltID0gQWxsU3ltYm9sc1t0YWddID0gX2NyZWF0ZSgkU3ltYm9sW1BST1RPVFlQRV0pO1xuICBzeW0uX2sgPSB0YWc7XG4gIHJldHVybiBzeW07XG59O1xuXG52YXIgaXNTeW1ib2wgPSBVU0VfTkFUSVZFICYmIHR5cGVvZiAkU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnID8gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiB0eXBlb2YgaXQgPT0gJ3N5bWJvbCc7XG59IDogZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCBpbnN0YW5jZW9mICRTeW1ib2w7XG59O1xuXG52YXIgJGRlZmluZVByb3BlcnR5ID0gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoaXQsIGtleSwgRCkge1xuICBpZiAoaXQgPT09IE9iamVjdFByb3RvKSAkZGVmaW5lUHJvcGVydHkoT1BTeW1ib2xzLCBrZXksIEQpO1xuICBhbk9iamVjdChpdCk7XG4gIGtleSA9IHRvUHJpbWl0aXZlKGtleSwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEQpO1xuICBpZiAoaGFzKEFsbFN5bWJvbHMsIGtleSkpIHtcbiAgICBpZiAoIUQuZW51bWVyYWJsZSkge1xuICAgICAgaWYgKCFoYXMoaXQsIEhJRERFTikpIGRQKGl0LCBISURERU4sIGNyZWF0ZURlc2MoMSwge30pKTtcbiAgICAgIGl0W0hJRERFTl1ba2V5XSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChoYXMoaXQsIEhJRERFTikgJiYgaXRbSElEREVOXVtrZXldKSBpdFtISURERU5dW2tleV0gPSBmYWxzZTtcbiAgICAgIEQgPSBfY3JlYXRlKEQsIHsgZW51bWVyYWJsZTogY3JlYXRlRGVzYygwLCBmYWxzZSkgfSk7XG4gICAgfSByZXR1cm4gc2V0U3ltYm9sRGVzYyhpdCwga2V5LCBEKTtcbiAgfSByZXR1cm4gZFAoaXQsIGtleSwgRCk7XG59O1xudmFyICRkZWZpbmVQcm9wZXJ0aWVzID0gZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhpdCwgUCkge1xuICBhbk9iamVjdChpdCk7XG4gIHZhciBrZXlzID0gZW51bUtleXMoUCA9IHRvSU9iamVjdChQKSk7XG4gIHZhciBpID0gMDtcbiAgdmFyIGwgPSBrZXlzLmxlbmd0aDtcbiAgdmFyIGtleTtcbiAgd2hpbGUgKGwgPiBpKSAkZGVmaW5lUHJvcGVydHkoaXQsIGtleSA9IGtleXNbaSsrXSwgUFtrZXldKTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciAkY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGl0LCBQKSB7XG4gIHJldHVybiBQID09PSB1bmRlZmluZWQgPyBfY3JlYXRlKGl0KSA6ICRkZWZpbmVQcm9wZXJ0aWVzKF9jcmVhdGUoaXQpLCBQKTtcbn07XG52YXIgJHByb3BlcnR5SXNFbnVtZXJhYmxlID0gZnVuY3Rpb24gcHJvcGVydHlJc0VudW1lcmFibGUoa2V5KSB7XG4gIHZhciBFID0gaXNFbnVtLmNhbGwodGhpcywga2V5ID0gdG9QcmltaXRpdmUoa2V5LCB0cnVlKSk7XG4gIGlmICh0aGlzID09PSBPYmplY3RQcm90byAmJiBoYXMoQWxsU3ltYm9scywga2V5KSAmJiAhaGFzKE9QU3ltYm9scywga2V5KSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gRSB8fCAhaGFzKHRoaXMsIGtleSkgfHwgIWhhcyhBbGxTeW1ib2xzLCBrZXkpIHx8IGhhcyh0aGlzLCBISURERU4pICYmIHRoaXNbSElEREVOXVtrZXldID8gRSA6IHRydWU7XG59O1xudmFyICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoaXQsIGtleSkge1xuICBpdCA9IHRvSU9iamVjdChpdCk7XG4gIGtleSA9IHRvUHJpbWl0aXZlKGtleSwgdHJ1ZSk7XG4gIGlmIChpdCA9PT0gT2JqZWN0UHJvdG8gJiYgaGFzKEFsbFN5bWJvbHMsIGtleSkgJiYgIWhhcyhPUFN5bWJvbHMsIGtleSkpIHJldHVybjtcbiAgdmFyIEQgPSBnT1BEKGl0LCBrZXkpO1xuICBpZiAoRCAmJiBoYXMoQWxsU3ltYm9scywga2V5KSAmJiAhKGhhcyhpdCwgSElEREVOKSAmJiBpdFtISURERU5dW2tleV0pKSBELmVudW1lcmFibGUgPSB0cnVlO1xuICByZXR1cm4gRDtcbn07XG52YXIgJGdldE93blByb3BlcnR5TmFtZXMgPSBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKGl0KSB7XG4gIHZhciBuYW1lcyA9IGdPUE4odG9JT2JqZWN0KGl0KSk7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIGkgPSAwO1xuICB2YXIga2V5O1xuICB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkge1xuICAgIGlmICghaGFzKEFsbFN5bWJvbHMsIGtleSA9IG5hbWVzW2krK10pICYmIGtleSAhPSBISURERU4gJiYga2V5ICE9IE1FVEEpIHJlc3VsdC5wdXNoKGtleSk7XG4gIH0gcmV0dXJuIHJlc3VsdDtcbn07XG52YXIgJGdldE93blByb3BlcnR5U3ltYm9scyA9IGZ1bmN0aW9uIGdldE93blByb3BlcnR5U3ltYm9scyhpdCkge1xuICB2YXIgSVNfT1AgPSBpdCA9PT0gT2JqZWN0UHJvdG87XG4gIHZhciBuYW1lcyA9IGdPUE4oSVNfT1AgPyBPUFN5bWJvbHMgOiB0b0lPYmplY3QoaXQpKTtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIgaSA9IDA7XG4gIHZhciBrZXk7XG4gIHdoaWxlIChuYW1lcy5sZW5ndGggPiBpKSB7XG4gICAgaWYgKGhhcyhBbGxTeW1ib2xzLCBrZXkgPSBuYW1lc1tpKytdKSAmJiAoSVNfT1AgPyBoYXMoT2JqZWN0UHJvdG8sIGtleSkgOiB0cnVlKSkgcmVzdWx0LnB1c2goQWxsU3ltYm9sc1trZXldKTtcbiAgfSByZXR1cm4gcmVzdWx0O1xufTtcblxuLy8gMTkuNC4xLjEgU3ltYm9sKFtkZXNjcmlwdGlvbl0pXG5pZiAoIVVTRV9OQVRJVkUpIHtcbiAgJFN5bWJvbCA9IGZ1bmN0aW9uIFN5bWJvbCgpIHtcbiAgICBpZiAodGhpcyBpbnN0YW5jZW9mICRTeW1ib2wpIHRocm93IFR5cGVFcnJvcignU3ltYm9sIGlzIG5vdCBhIGNvbnN0cnVjdG9yIScpO1xuICAgIHZhciB0YWcgPSB1aWQoYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpO1xuICAgIHZhciAkc2V0ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICBpZiAodGhpcyA9PT0gT2JqZWN0UHJvdG8pICRzZXQuY2FsbChPUFN5bWJvbHMsIHZhbHVlKTtcbiAgICAgIGlmIChoYXModGhpcywgSElEREVOKSAmJiBoYXModGhpc1tISURERU5dLCB0YWcpKSB0aGlzW0hJRERFTl1bdGFnXSA9IGZhbHNlO1xuICAgICAgc2V0U3ltYm9sRGVzYyh0aGlzLCB0YWcsIGNyZWF0ZURlc2MoMSwgdmFsdWUpKTtcbiAgICB9O1xuICAgIGlmIChERVNDUklQVE9SUyAmJiBzZXR0ZXIpIHNldFN5bWJvbERlc2MoT2JqZWN0UHJvdG8sIHRhZywgeyBjb25maWd1cmFibGU6IHRydWUsIHNldDogJHNldCB9KTtcbiAgICByZXR1cm4gd3JhcCh0YWcpO1xuICB9O1xuICByZWRlZmluZSgkU3ltYm9sW1BST1RPVFlQRV0sICd0b1N0cmluZycsIGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLl9rO1xuICB9KTtcblxuICAkR09QRC5mID0gJGdldE93blByb3BlcnR5RGVzY3JpcHRvcjtcbiAgJERQLmYgPSAkZGVmaW5lUHJvcGVydHk7XG4gIHJlcXVpcmUoJy4vX29iamVjdC1nb3BuJykuZiA9IGdPUE5FeHQuZiA9ICRnZXRPd25Qcm9wZXJ0eU5hbWVzO1xuICByZXF1aXJlKCcuL19vYmplY3QtcGllJykuZiA9ICRwcm9wZXJ0eUlzRW51bWVyYWJsZTtcbiAgcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKS5mID0gJGdldE93blByb3BlcnR5U3ltYm9scztcblxuICBpZiAoREVTQ1JJUFRPUlMgJiYgIXJlcXVpcmUoJy4vX2xpYnJhcnknKSkge1xuICAgIHJlZGVmaW5lKE9iamVjdFByb3RvLCAncHJvcGVydHlJc0VudW1lcmFibGUnLCAkcHJvcGVydHlJc0VudW1lcmFibGUsIHRydWUpO1xuICB9XG5cbiAgd2tzRXh0LmYgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHJldHVybiB3cmFwKHdrcyhuYW1lKSk7XG4gIH07XG59XG5cbiRleHBvcnQoJGV4cG9ydC5HICsgJGV4cG9ydC5XICsgJGV4cG9ydC5GICogIVVTRV9OQVRJVkUsIHsgU3ltYm9sOiAkU3ltYm9sIH0pO1xuXG5mb3IgKHZhciBlczZTeW1ib2xzID0gKFxuICAvLyAxOS40LjIuMiwgMTkuNC4yLjMsIDE5LjQuMi40LCAxOS40LjIuNiwgMTkuNC4yLjgsIDE5LjQuMi45LCAxOS40LjIuMTAsIDE5LjQuMi4xMSwgMTkuNC4yLjEyLCAxOS40LjIuMTMsIDE5LjQuMi4xNFxuICAnaGFzSW5zdGFuY2UsaXNDb25jYXRTcHJlYWRhYmxlLGl0ZXJhdG9yLG1hdGNoLHJlcGxhY2Usc2VhcmNoLHNwZWNpZXMsc3BsaXQsdG9QcmltaXRpdmUsdG9TdHJpbmdUYWcsdW5zY29wYWJsZXMnXG4pLnNwbGl0KCcsJyksIGogPSAwOyBlczZTeW1ib2xzLmxlbmd0aCA+IGo7KXdrcyhlczZTeW1ib2xzW2orK10pO1xuXG5mb3IgKHZhciB3ZWxsS25vd25TeW1ib2xzID0gJGtleXMod2tzLnN0b3JlKSwgayA9IDA7IHdlbGxLbm93blN5bWJvbHMubGVuZ3RoID4gazspIHdrc0RlZmluZSh3ZWxsS25vd25TeW1ib2xzW2srK10pO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFVU0VfTkFUSVZFLCAnU3ltYm9sJywge1xuICAvLyAxOS40LjIuMSBTeW1ib2wuZm9yKGtleSlcbiAgJ2Zvcic6IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gaGFzKFN5bWJvbFJlZ2lzdHJ5LCBrZXkgKz0gJycpXG4gICAgICA/IFN5bWJvbFJlZ2lzdHJ5W2tleV1cbiAgICAgIDogU3ltYm9sUmVnaXN0cnlba2V5XSA9ICRTeW1ib2woa2V5KTtcbiAgfSxcbiAgLy8gMTkuNC4yLjUgU3ltYm9sLmtleUZvcihzeW0pXG4gIGtleUZvcjogZnVuY3Rpb24ga2V5Rm9yKHN5bSkge1xuICAgIGlmICghaXNTeW1ib2woc3ltKSkgdGhyb3cgVHlwZUVycm9yKHN5bSArICcgaXMgbm90IGEgc3ltYm9sIScpO1xuICAgIGZvciAodmFyIGtleSBpbiBTeW1ib2xSZWdpc3RyeSkgaWYgKFN5bWJvbFJlZ2lzdHJ5W2tleV0gPT09IHN5bSkgcmV0dXJuIGtleTtcbiAgfSxcbiAgdXNlU2V0dGVyOiBmdW5jdGlvbiAoKSB7IHNldHRlciA9IHRydWU7IH0sXG4gIHVzZVNpbXBsZTogZnVuY3Rpb24gKCkgeyBzZXR0ZXIgPSBmYWxzZTsgfVxufSk7XG5cbiRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogIVVTRV9OQVRJVkUsICdPYmplY3QnLCB7XG4gIC8vIDE5LjEuMi4yIE9iamVjdC5jcmVhdGUoTyBbLCBQcm9wZXJ0aWVzXSlcbiAgY3JlYXRlOiAkY3JlYXRlLFxuICAvLyAxOS4xLjIuNCBPYmplY3QuZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcylcbiAgZGVmaW5lUHJvcGVydHk6ICRkZWZpbmVQcm9wZXJ0eSxcbiAgLy8gMTkuMS4yLjMgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoTywgUHJvcGVydGllcylcbiAgZGVmaW5lUHJvcGVydGllczogJGRlZmluZVByb3BlcnRpZXMsXG4gIC8vIDE5LjEuMi42IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUClcbiAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLFxuICAvLyAxOS4xLjIuNyBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhPKVxuICBnZXRPd25Qcm9wZXJ0eU5hbWVzOiAkZ2V0T3duUHJvcGVydHlOYW1lcyxcbiAgLy8gMTkuMS4yLjggT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhPKVxuICBnZXRPd25Qcm9wZXJ0eVN5bWJvbHM6ICRnZXRPd25Qcm9wZXJ0eVN5bWJvbHNcbn0pO1xuXG4vLyAyNC4zLjIgSlNPTi5zdHJpbmdpZnkodmFsdWUgWywgcmVwbGFjZXIgWywgc3BhY2VdXSlcbiRKU09OICYmICRleHBvcnQoJGV4cG9ydC5TICsgJGV4cG9ydC5GICogKCFVU0VfTkFUSVZFIHx8ICRmYWlscyhmdW5jdGlvbiAoKSB7XG4gIHZhciBTID0gJFN5bWJvbCgpO1xuICAvLyBNUyBFZGdlIGNvbnZlcnRzIHN5bWJvbCB2YWx1ZXMgdG8gSlNPTiBhcyB7fVxuICAvLyBXZWJLaXQgY29udmVydHMgc3ltYm9sIHZhbHVlcyB0byBKU09OIGFzIG51bGxcbiAgLy8gVjggdGhyb3dzIG9uIGJveGVkIHN5bWJvbHNcbiAgcmV0dXJuIF9zdHJpbmdpZnkoW1NdKSAhPSAnW251bGxdJyB8fCBfc3RyaW5naWZ5KHsgYTogUyB9KSAhPSAne30nIHx8IF9zdHJpbmdpZnkoT2JqZWN0KFMpKSAhPSAne30nO1xufSkpLCAnSlNPTicsIHtcbiAgc3RyaW5naWZ5OiBmdW5jdGlvbiBzdHJpbmdpZnkoaXQpIHtcbiAgICB2YXIgYXJncyA9IFtpdF07XG4gICAgdmFyIGkgPSAxO1xuICAgIHZhciByZXBsYWNlciwgJHJlcGxhY2VyO1xuICAgIHdoaWxlIChhcmd1bWVudHMubGVuZ3RoID4gaSkgYXJncy5wdXNoKGFyZ3VtZW50c1tpKytdKTtcbiAgICAkcmVwbGFjZXIgPSByZXBsYWNlciA9IGFyZ3NbMV07XG4gICAgaWYgKCFpc09iamVjdChyZXBsYWNlcikgJiYgaXQgPT09IHVuZGVmaW5lZCB8fCBpc1N5bWJvbChpdCkpIHJldHVybjsgLy8gSUU4IHJldHVybnMgc3RyaW5nIG9uIHVuZGVmaW5lZFxuICAgIGlmICghaXNBcnJheShyZXBsYWNlcikpIHJlcGxhY2VyID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgIGlmICgkcmVwbGFjZXIpIHZhbHVlID0gJHJlcGxhY2VyLmNhbGwodGhpcywga2V5LCB2YWx1ZSk7XG4gICAgICBpZiAoIWlzU3ltYm9sKHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gICAgYXJnc1sxXSA9IHJlcGxhY2VyO1xuICAgIHJldHVybiBfc3RyaW5naWZ5LmFwcGx5KCRKU09OLCBhcmdzKTtcbiAgfVxufSk7XG5cbi8vIDE5LjQuMy40IFN5bWJvbC5wcm90b3R5cGVbQEB0b1ByaW1pdGl2ZV0oaGludClcbiRTeW1ib2xbUFJPVE9UWVBFXVtUT19QUklNSVRJVkVdIHx8IHJlcXVpcmUoJy4vX2hpZGUnKSgkU3ltYm9sW1BST1RPVFlQRV0sIFRPX1BSSU1JVElWRSwgJFN5bWJvbFtQUk9UT1RZUEVdLnZhbHVlT2YpO1xuLy8gMTkuNC4zLjUgU3ltYm9sLnByb3RvdHlwZVtAQHRvU3RyaW5nVGFnXVxuc2V0VG9TdHJpbmdUYWcoJFN5bWJvbCwgJ1N5bWJvbCcpO1xuLy8gMjAuMi4xLjkgTWF0aFtAQHRvU3RyaW5nVGFnXVxuc2V0VG9TdHJpbmdUYWcoTWF0aCwgJ01hdGgnLCB0cnVlKTtcbi8vIDI0LjMuMyBKU09OW0BAdG9TdHJpbmdUYWddXG5zZXRUb1N0cmluZ1RhZyhnbG9iYWwuSlNPTiwgJ0pTT04nLCB0cnVlKTtcbiIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXByb21pc2UtZmluYWxseVxuJ3VzZSBzdHJpY3QnO1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcbnZhciBjb3JlID0gcmVxdWlyZSgnLi9fY29yZScpO1xudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIHNwZWNpZXNDb25zdHJ1Y3RvciA9IHJlcXVpcmUoJy4vX3NwZWNpZXMtY29uc3RydWN0b3InKTtcbnZhciBwcm9taXNlUmVzb2x2ZSA9IHJlcXVpcmUoJy4vX3Byb21pc2UtcmVzb2x2ZScpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ1Byb21pc2UnLCB7ICdmaW5hbGx5JzogZnVuY3Rpb24gKG9uRmluYWxseSkge1xuICB2YXIgQyA9IHNwZWNpZXNDb25zdHJ1Y3Rvcih0aGlzLCBjb3JlLlByb21pc2UgfHwgZ2xvYmFsLlByb21pc2UpO1xuICB2YXIgaXNGdW5jdGlvbiA9IHR5cGVvZiBvbkZpbmFsbHkgPT0gJ2Z1bmN0aW9uJztcbiAgcmV0dXJuIHRoaXMudGhlbihcbiAgICBpc0Z1bmN0aW9uID8gZnVuY3Rpb24gKHgpIHtcbiAgICAgIHJldHVybiBwcm9taXNlUmVzb2x2ZShDLCBvbkZpbmFsbHkoKSkudGhlbihmdW5jdGlvbiAoKSB7IHJldHVybiB4OyB9KTtcbiAgICB9IDogb25GaW5hbGx5LFxuICAgIGlzRnVuY3Rpb24gPyBmdW5jdGlvbiAoZSkge1xuICAgICAgcmV0dXJuIHByb21pc2VSZXNvbHZlKEMsIG9uRmluYWxseSgpKS50aGVuKGZ1bmN0aW9uICgpIHsgdGhyb3cgZTsgfSk7XG4gICAgfSA6IG9uRmluYWxseVxuICApO1xufSB9KTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXByb21pc2UtdHJ5XG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIG5ld1Byb21pc2VDYXBhYmlsaXR5ID0gcmVxdWlyZSgnLi9fbmV3LXByb21pc2UtY2FwYWJpbGl0eScpO1xudmFyIHBlcmZvcm0gPSByZXF1aXJlKCcuL19wZXJmb3JtJyk7XG5cbiRleHBvcnQoJGV4cG9ydC5TLCAnUHJvbWlzZScsIHsgJ3RyeSc6IGZ1bmN0aW9uIChjYWxsYmFja2ZuKSB7XG4gIHZhciBwcm9taXNlQ2FwYWJpbGl0eSA9IG5ld1Byb21pc2VDYXBhYmlsaXR5LmYodGhpcyk7XG4gIHZhciByZXN1bHQgPSBwZXJmb3JtKGNhbGxiYWNrZm4pO1xuICAocmVzdWx0LmUgPyBwcm9taXNlQ2FwYWJpbGl0eS5yZWplY3QgOiBwcm9taXNlQ2FwYWJpbGl0eS5yZXNvbHZlKShyZXN1bHQudik7XG4gIHJldHVybiBwcm9taXNlQ2FwYWJpbGl0eS5wcm9taXNlO1xufSB9KTtcbiIsInJlcXVpcmUoJy4vX3drcy1kZWZpbmUnKSgnYXN5bmNJdGVyYXRvcicpO1xuIiwicmVxdWlyZSgnLi9fd2tzLWRlZmluZScpKCdvYnNlcnZhYmxlJyk7XG4iLCJyZXF1aXJlKCcuL2VzNi5hcnJheS5pdGVyYXRvcicpO1xudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGhpZGUgPSByZXF1aXJlKCcuL19oaWRlJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgVE9fU1RSSU5HX1RBRyA9IHJlcXVpcmUoJy4vX3drcycpKCd0b1N0cmluZ1RhZycpO1xuXG52YXIgRE9NSXRlcmFibGVzID0gKCdDU1NSdWxlTGlzdCxDU1NTdHlsZURlY2xhcmF0aW9uLENTU1ZhbHVlTGlzdCxDbGllbnRSZWN0TGlzdCxET01SZWN0TGlzdCxET01TdHJpbmdMaXN0LCcgK1xuICAnRE9NVG9rZW5MaXN0LERhdGFUcmFuc2Zlckl0ZW1MaXN0LEZpbGVMaXN0LEhUTUxBbGxDb2xsZWN0aW9uLEhUTUxDb2xsZWN0aW9uLEhUTUxGb3JtRWxlbWVudCxIVE1MU2VsZWN0RWxlbWVudCwnICtcbiAgJ01lZGlhTGlzdCxNaW1lVHlwZUFycmF5LE5hbWVkTm9kZU1hcCxOb2RlTGlzdCxQYWludFJlcXVlc3RMaXN0LFBsdWdpbixQbHVnaW5BcnJheSxTVkdMZW5ndGhMaXN0LFNWR051bWJlckxpc3QsJyArXG4gICdTVkdQYXRoU2VnTGlzdCxTVkdQb2ludExpc3QsU1ZHU3RyaW5nTGlzdCxTVkdUcmFuc2Zvcm1MaXN0LFNvdXJjZUJ1ZmZlckxpc3QsU3R5bGVTaGVldExpc3QsVGV4dFRyYWNrQ3VlTGlzdCwnICtcbiAgJ1RleHRUcmFja0xpc3QsVG91Y2hMaXN0Jykuc3BsaXQoJywnKTtcblxuZm9yICh2YXIgaSA9IDA7IGkgPCBET01JdGVyYWJsZXMubGVuZ3RoOyBpKyspIHtcbiAgdmFyIE5BTUUgPSBET01JdGVyYWJsZXNbaV07XG4gIHZhciBDb2xsZWN0aW9uID0gZ2xvYmFsW05BTUVdO1xuICB2YXIgcHJvdG8gPSBDb2xsZWN0aW9uICYmIENvbGxlY3Rpb24ucHJvdG90eXBlO1xuICBpZiAocHJvdG8gJiYgIXByb3RvW1RPX1NUUklOR19UQUddKSBoaWRlKHByb3RvLCBUT19TVFJJTkdfVEFHLCBOQU1FKTtcbiAgSXRlcmF0b3JzW05BTUVdID0gSXRlcmF0b3JzLkFycmF5O1xufVxuIl19 diff --git a/examples/sink-bar-chart-display/css/styles.css b/examples/sink-bar-chart-display/css/styles.css new file mode 100644 index 0000000..ae3f6c4 --- /dev/null +++ b/examples/sink-bar-chart-display/css/styles.css @@ -0,0 +1,20 @@ +html { + font-size: 62.5%; + font-family: arial; +} + +body { + margin: 0; + padding: 20px; +} + +h1 { + font-size: 2.2rem; + margin: 0 0 20px 0; + color: rgba(0, 0, 0, 0.4); + font-family: "Courier New", Courier, monospace; +} + +canvas { + outline: 1px solid #cdcdcd; +} diff --git a/examples/sink-bar-chart-display/index.html b/examples/sink-bar-chart-display/index.html new file mode 100644 index 0000000..8fb8ad6 --- /dev/null +++ b/examples/sink-bar-chart-display/index.html @@ -0,0 +1,15 @@ + + + + + + lfo.sink.BarChartDisplay + + + +

lfo.sink.BarChartDisplay

+ + + + + diff --git a/examples/sink-bar-chart-display/package.json b/examples/sink-bar-chart-display/package.json new file mode 100644 index 0000000..7fdc8c4 --- /dev/null +++ b/examples/sink-bar-chart-display/package.json @@ -0,0 +1,36 @@ +{ + "name": "es6-next-prototyping-client", + "version": "1.0.1", + "description": "ESNext client prototyping boilerplate", + "main": "dist/main.js", + "author": "Benjamin Matuszewski", + "license": "ISC", + "scripts": { + "bundle": "./bin/runner --bundle", + "transpile": "./bin/runner --transpile", + "prewatch": "npm run transpile", + "watch": "./bin/runner --watch", + "serve": "./bin/runner --serve", + "postinstall": "npm run bundle" + }, + "dependencies": { + "babel-runtime": "^6.9.2", + "waves-lfo": "^1.1.5" + }, + "devDependencies": { + "babel-core": "^6.14.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.14.0", + "babel-plugin-transform-runtime": "^6.12.0", + "babel-preset-latest": "^6.14.0", + "benchmark": "^1.0.0", + "browserify": "^13.0.0", + "colors": "^1.1.2", + "connect": "^3.3.5", + "fs-extra": "^0.26.5", + "ora": "^0.2.0", + "portfinder": "^0.4.0", + "serve-favicon": "^2.2.0", + "serve-static": "^1.9.2", + "watch": "^0.17.1" + } +} diff --git a/examples/sink-bar-chart-display/src/index.js b/examples/sink-bar-chart-display/src/index.js new file mode 100644 index 0000000..10079d9 --- /dev/null +++ b/examples/sink-bar-chart-display/src/index.js @@ -0,0 +1,28 @@ +import * as lfo from 'waves-lfo/client'; + +const frameSize = 5; +const dt = 0.02; + +const eventIn = new lfo.source.EventIn({ + frameSize: frameSize, + frameRate: 1 / dt, + frameType: 'vector', +}); + +const barChart = new lfo.sink.BarChartDisplay({ + canvas: '#bar-chart', +}); + +eventIn.connect(barChart); +eventIn.start(); + +const data = [0, 0.2, 0.4, 0.6, 0.8]; + +(function generateData() { + for (let i = 0; i < frameSize; i++) + data[i] = (data[i] + 0.001) % 1; + + eventIn.process(null, data); + + setTimeout(generateData, dt * 1000); +}()); diff --git a/jsdoc.json b/jsdoc.json index 8fea701..627a5bb 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -6,7 +6,9 @@ "src/core/SourceMixin.js", "src/common/operator/Biquad.js", + "src/common/operator/Clip.js", "src/common/operator/Dct.js", + "src/common/operator/Delta.js", "src/common/operator/Fft.js", "src/common/operator/Magnitude.js", "src/common/operator/MeanStddev.js", @@ -15,8 +17,11 @@ "src/common/operator/MinMax.js", "src/common/operator/MovingAverage.js", "src/common/operator/MovingMedian.js", + "src/common/operator/Multiplier.js", "src/common/operator/OnOff.js", + "src/common/operator/Power.js", "src/common/operator/Rms.js", + "src/common/operator/Scale.js", "src/common/operator/Segmenter.js", "src/common/operator/Select.js", "src/common/operator/Slicer.js", @@ -30,6 +35,7 @@ "src/common/source/EventIn.js", "src/client/sink/BaseDisplay.js", + "src/client/sink/BarChartDisplay.js", "src/client/sink/BpfDisplay.js", "src/client/sink/MarkerDisplay.js", "src/client/sink/SignalDisplay.js", diff --git a/src/client/sink/BarChartDisplay.js b/src/client/sink/BarChartDisplay.js new file mode 100644 index 0000000..1abf876 --- /dev/null +++ b/src/client/sink/BarChartDisplay.js @@ -0,0 +1,126 @@ +import BaseDisplay from './BaseDisplay'; +import Fft from '../../common/operator/Fft'; +import { getColors } from '../utils/display-utils'; + + +const definitions = { + scale: { + type: 'float', + default: 1, + metas: { kind: 'dynamic' }, + }, + colors: { + type: 'any', + default: getColors('bar-chart'), + nullable: true, + metas: { kind: 'dynamic' }, + }, + min: { + type: 'float', + default: 0, + metas: { kind: 'dynamic' }, + }, + max: { + type: 'float', + default: 1, + metas: { kind: 'dynamic' }, + } +}; + + +/** + * Display a bar chart from an incomming `vector` input. + * + * @memberof module:client.sink + * + * @param {Object} options - Override default parameters. + * @param {String} [options.colors=null] - Colors of the bars. + * @param {Number} [options.min=-80] - Minimum displayed value. + * @param {Number} [options.max=6] - Maximum displayed value. + * @param {Number} [options.width=300] - Width of the canvas. + * _dynamic parameter_ + * @param {Number} [options.height=150] - Height of the canvas. + * _dynamic parameter_ + * @param {Element|CSSSelector} [options.container=null] - Container element + * in which to insert the canvas. _constant parameter_ + * @param {Element|CSSSelector} [options.canvas=null] - Canvas element + * in which to draw. _constant parameter_ + * + * @example + * import * as lfo from 'waves-lfo/client'; + * import * as lfo from 'waves-lfo/client'; + * + * const frameSize = 5; + * const dt = 0.02; + * + * const eventIn = new lfo.source.EventIn({ + * frameSize: frameSize, + * frameRate: 1 / dt, + * frameType: 'vector', + * }); + * + * const barChart = new lfo.sink.BarChartDisplay({ + * canvas: '#bar-chart', + * }); + * + * eventIn.connect(barChart); + * eventIn.start(); + * + * const data = [0, 0.2, 0.4, 0.6, 0.8]; + * + * (function generateData() { + * for (let i = 0; i < frameSize; i++) + * data[i] = (data[i] + 0.001) % 1; + * + * eventIn.process(null, data); + * + * setTimeout(generateData, dt * 1000); + * }()); + */ +class BarChartDisplay extends BaseDisplay { + constructor(options = {}) { + super(definitions, options, false); + } + + /** @private */ + processStreamParams(prevStreamParams) { + this.prepareStreamParams(prevStreamParams); + this.propagateStreamParams(); + } + + /** @private */ + processVector(frame) { + const frameSize = this.streamParams.frameSize; + const width = this.canvasWidth; + const height = this.canvasHeight; + const colors = this.params.get('colors'); + const data = frame.data; + + const barWidth = width / frameSize; + const ctx = this.ctx; + + // error handling needs review... + let error = 0; + + for (let i = 0; i < frameSize; i++) { + const x1Float = i * barWidth + error; + const x1Int = Math.round(x1Float); + const x2Float = x1Float + (barWidth - error); + const x2Int = Math.round(x2Float); + + error = x2Int - x2Float; + + if (x1Int !== x2Int) { + const width = x2Int - x1Int; + const y = this.getYPosition(data[i]); + + ctx.fillStyle = colors[i % colors.length]; + ctx.fillRect(x1Int, y, width, height - y); + } else { + error -= barWidth; + } + } + } +} + +export default BarChartDisplay; diff --git a/src/client/sink/_namespace.js b/src/client/sink/_namespace.js index a72adc3..ad31d8d 100644 --- a/src/client/sink/_namespace.js +++ b/src/client/sink/_namespace.js @@ -6,6 +6,7 @@ import SignalRecorder from '../../common/sink/SignalRecorder'; // client only import BaseDisplay from './BaseDisplay'; +import BarChartDisplay from './BarChartDisplay'; import BpfDisplay from './BpfDisplay'; import MarkerDisplay from './MarkerDisplay'; import SignalDisplay from './SignalDisplay'; @@ -22,6 +23,7 @@ export default { SignalRecorder, BaseDisplay, + BarChartDisplay, BpfDisplay, MarkerDisplay, SignalDisplay, diff --git a/src/client/utils/display-utils.js b/src/client/utils/display-utils.js index 3e5124d..28d9e54 100755 --- a/src/client/utils/display-utils.js +++ b/src/client/utils/display-utils.js @@ -28,6 +28,9 @@ export const getColors = function(type, nbr) { case 'trace': return colors[1]; // orange break; + case 'bar-chart': + return colors; + break; } };