12580 lines
943 KiB
JavaScript
12580 lines
943 KiB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||
var Charts = require('../lib/index')
|
||
|
||
window.Charts = Charts
|
||
},{"../lib/index":29}],2:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
||
|
||
require("../extend/index");
|
||
|
||
var _cRender = _interopRequireDefault(require("@jiaminghi/c-render"));
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _core = require("../core");
|
||
|
||
var Charts = function Charts(dom) {
|
||
(0, _classCallCheck2["default"])(this, Charts);
|
||
|
||
if (!dom) {
|
||
console.error('Charts Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var clientWidth = dom.clientWidth,
|
||
clientHeight = dom.clientHeight;
|
||
var canvas = document.createElement('canvas');
|
||
canvas.setAttribute('width', clientWidth);
|
||
canvas.setAttribute('height', clientHeight);
|
||
dom.appendChild(canvas);
|
||
var attribute = {
|
||
container: dom,
|
||
canvas: canvas,
|
||
render: new _cRender["default"](canvas),
|
||
option: null
|
||
};
|
||
Object.assign(this, attribute);
|
||
};
|
||
/**
|
||
* @description Set chart option
|
||
* @param {Object} option Chart option
|
||
* @param {Boolean} animationEnd Execute animationEnd
|
||
* @return {Undefined} No return
|
||
*/
|
||
|
||
|
||
exports["default"] = Charts;
|
||
|
||
Charts.prototype.setOption = function (option) {
|
||
var animationEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
|
||
if (!option || (0, _typeof2["default"])(option) !== 'object') {
|
||
console.error('setOption Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
if (animationEnd) this.render.graphs.forEach(function (graph) {
|
||
return graph.animationEnd();
|
||
});
|
||
var optionCloned = (0, _util.deepClone)(option, true);
|
||
(0, _core.mergeColor)(this, optionCloned);
|
||
(0, _core.grid)(this, optionCloned);
|
||
(0, _core.axis)(this, optionCloned);
|
||
(0, _core.radarAxis)(this, optionCloned);
|
||
(0, _core.title)(this, optionCloned);
|
||
(0, _core.bar)(this, optionCloned);
|
||
(0, _core.line)(this, optionCloned);
|
||
(0, _core.pie)(this, optionCloned);
|
||
(0, _core.radar)(this, optionCloned);
|
||
(0, _core.gauge)(this, optionCloned);
|
||
(0, _core.legend)(this, optionCloned);
|
||
this.option = option;
|
||
this.render.launchAnimation(); // console.warn(this)
|
||
};
|
||
/**
|
||
* @description Resize chart
|
||
* @return {Undefined} No return
|
||
*/
|
||
|
||
|
||
Charts.prototype.resize = function () {
|
||
var container = this.container,
|
||
canvas = this.canvas,
|
||
render = this.render,
|
||
option = this.option;
|
||
var clientWidth = container.clientWidth,
|
||
clientHeight = container.clientHeight;
|
||
canvas.setAttribute('width', clientWidth);
|
||
canvas.setAttribute('height', clientHeight);
|
||
render.area = [clientWidth, clientHeight];
|
||
this.setOption(option);
|
||
};
|
||
},{"../core":20,"../extend/index":28,"@babel/runtime/helpers/classCallCheck":34,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render":52,"@jiaminghi/c-render/lib/plugin/util":54}],3:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.doUpdate = doUpdate;
|
||
exports.Updater = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
||
|
||
var Updater = function Updater(config, series) {
|
||
(0, _classCallCheck2["default"])(this, Updater);
|
||
var chart = config.chart,
|
||
key = config.key,
|
||
getGraphConfig = config.getGraphConfig;
|
||
|
||
if (typeof getGraphConfig !== 'function') {
|
||
console.warn('Updater need function getGraphConfig!');
|
||
return;
|
||
}
|
||
|
||
if (!chart[key]) this.graphs = chart[key] = [];
|
||
Object.assign(this, config);
|
||
this.update(series);
|
||
};
|
||
|
||
exports.Updater = Updater;
|
||
|
||
Updater.prototype.update = function (series) {
|
||
var _this = this;
|
||
|
||
var graphs = this.graphs,
|
||
beforeUpdate = this.beforeUpdate;
|
||
delRedundanceGraph(this, series);
|
||
if (!series.length) return;
|
||
var beforeUpdateType = (0, _typeof2["default"])(beforeUpdate);
|
||
series.forEach(function (seriesItem, i) {
|
||
if (beforeUpdateType === 'function') beforeUpdate(graphs, seriesItem, i, _this);
|
||
var cache = graphs[i];
|
||
|
||
if (cache) {
|
||
changeGraphs(cache, seriesItem, i, _this);
|
||
} else {
|
||
addGraphs(graphs, seriesItem, i, _this);
|
||
}
|
||
});
|
||
};
|
||
|
||
function delRedundanceGraph(updater, series) {
|
||
var graphs = updater.graphs,
|
||
render = updater.chart.render;
|
||
var cacheGraphNum = graphs.length;
|
||
var needGraphNum = series.length;
|
||
|
||
if (cacheGraphNum > needGraphNum) {
|
||
var needDelGraphs = graphs.splice(needGraphNum);
|
||
needDelGraphs.forEach(function (item) {
|
||
return item.forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
function changeGraphs(cache, seriesItem, i, updater) {
|
||
var getGraphConfig = updater.getGraphConfig,
|
||
render = updater.chart.render,
|
||
beforeChange = updater.beforeChange;
|
||
var configs = getGraphConfig(seriesItem, updater);
|
||
balanceGraphsNum(cache, configs, render);
|
||
cache.forEach(function (graph, j) {
|
||
var config = configs[j];
|
||
if (typeof beforeChange === 'function') beforeChange(graph, config);
|
||
updateGraphConfigByKey(graph, config);
|
||
});
|
||
}
|
||
|
||
function balanceGraphsNum(graphs, graphConfig, render) {
|
||
var cacheGraphNum = graphs.length;
|
||
var needGraphNum = graphConfig.length;
|
||
|
||
if (needGraphNum > cacheGraphNum) {
|
||
var lastCacheGraph = graphs.slice(-1)[0];
|
||
var needAddGraphNum = needGraphNum - cacheGraphNum;
|
||
var needAddGraphs = new Array(needAddGraphNum).fill(0).map(function (foo) {
|
||
return render.clone(lastCacheGraph);
|
||
});
|
||
graphs.push.apply(graphs, (0, _toConsumableArray2["default"])(needAddGraphs));
|
||
} else if (needGraphNum < cacheGraphNum) {
|
||
var needDelCache = graphs.splice(needGraphNum);
|
||
needDelCache.forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
}
|
||
}
|
||
|
||
function addGraphs(graphs, seriesItem, i, updater) {
|
||
var getGraphConfig = updater.getGraphConfig,
|
||
getStartGraphConfig = updater.getStartGraphConfig,
|
||
chart = updater.chart;
|
||
var render = chart.render;
|
||
var startConfigs = null;
|
||
if (typeof getStartGraphConfig === 'function') startConfigs = getStartGraphConfig(seriesItem, updater);
|
||
var configs = getGraphConfig(seriesItem, updater);
|
||
if (!configs.length) return;
|
||
|
||
if (startConfigs) {
|
||
graphs[i] = startConfigs.map(function (config) {
|
||
return render.add(config);
|
||
});
|
||
graphs[i].forEach(function (graph, i) {
|
||
var config = configs[i];
|
||
updateGraphConfigByKey(graph, config);
|
||
});
|
||
} else {
|
||
graphs[i] = configs.map(function (config) {
|
||
return render.add(config);
|
||
});
|
||
}
|
||
|
||
var afterAddGraph = updater.afterAddGraph;
|
||
if (typeof afterAddGraph === 'function') afterAddGraph(graphs[i]);
|
||
}
|
||
|
||
function updateGraphConfigByKey(graph, config) {
|
||
var keys = Object.keys(config);
|
||
keys.forEach(function (key) {
|
||
if (key === 'shape' || key === 'style') {
|
||
graph.animation(key, config[key], true);
|
||
} else {
|
||
graph[key] = config[key];
|
||
}
|
||
});
|
||
}
|
||
|
||
function doUpdate() {
|
||
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
||
chart = _ref.chart,
|
||
series = _ref.series,
|
||
key = _ref.key,
|
||
getGraphConfig = _ref.getGraphConfig,
|
||
getStartGraphConfig = _ref.getStartGraphConfig,
|
||
beforeChange = _ref.beforeChange,
|
||
beforeUpdate = _ref.beforeUpdate,
|
||
afterAddGraph = _ref.afterAddGraph;
|
||
|
||
if (chart[key]) {
|
||
chart[key].update(series);
|
||
} else {
|
||
chart[key] = new Updater({
|
||
chart: chart,
|
||
key: key,
|
||
getGraphConfig: getGraphConfig,
|
||
getStartGraphConfig: getStartGraphConfig,
|
||
beforeChange: beforeChange,
|
||
beforeUpdate: beforeUpdate,
|
||
afterAddGraph: afterAddGraph
|
||
}, series);
|
||
}
|
||
}
|
||
},{"@babel/runtime/helpers/classCallCheck":34,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43}],4:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.yAxisConfig = exports.xAxisConfig = void 0;
|
||
var xAxisConfig = {
|
||
/**
|
||
* @description Axis name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Whether to display this axis
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis position
|
||
* @type {String}
|
||
* @default position = 'bottom'
|
||
* @example position = 'bottom' | 'top'
|
||
*/
|
||
position: 'bottom',
|
||
|
||
/**
|
||
* @description Name gap
|
||
* @type {Number}
|
||
* @default nameGap = 15
|
||
*/
|
||
nameGap: 15,
|
||
|
||
/**
|
||
* @description Name location
|
||
* @type {String}
|
||
* @default nameLocation = 'end'
|
||
* @example nameLocation = 'end' | 'center' | 'start'
|
||
*/
|
||
nameLocation: 'end',
|
||
|
||
/**
|
||
* @description Name default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
nameTextStyle: {
|
||
fill: '#333',
|
||
fontSize: 10
|
||
},
|
||
|
||
/**
|
||
* @description Axis min value
|
||
* @type {String|Number}
|
||
* @default min = '20%'
|
||
* @example min = '20%' | 0
|
||
*/
|
||
min: '20%',
|
||
|
||
/**
|
||
* @description Axis max value
|
||
* @type {String|Number}
|
||
* @default max = '20%'
|
||
* @example max = '20%' | 0
|
||
*/
|
||
max: '20%',
|
||
|
||
/**
|
||
* @description Axis value interval
|
||
* @type {Number}
|
||
* @default interval = null
|
||
* @example interval = 100
|
||
*/
|
||
interval: null,
|
||
|
||
/**
|
||
* @description Min interval
|
||
* @type {Number}
|
||
* @default minInterval = null
|
||
* @example minInterval = 1
|
||
*/
|
||
minInterval: null,
|
||
|
||
/**
|
||
* @description Max interval
|
||
* @type {Number}
|
||
* @default maxInterval = null
|
||
* @example maxInterval = 100
|
||
*/
|
||
maxInterval: null,
|
||
|
||
/**
|
||
* @description Boundary gap
|
||
* @type {Boolean}
|
||
* @default boundaryGap = null
|
||
* @example boundaryGap = true
|
||
*/
|
||
boundaryGap: null,
|
||
|
||
/**
|
||
* @description Axis split number
|
||
* @type {Number}
|
||
* @default splitNumber = 5
|
||
*/
|
||
splitNumber: 5,
|
||
|
||
/**
|
||
* @description Axis line configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLine: {
|
||
/**
|
||
* @description Whether to display axis line
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#333',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis tick configuration
|
||
* @type {Object}
|
||
*/
|
||
axisTick: {
|
||
/**
|
||
* @description Whether to display axis tick
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis tick default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#333',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis label configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLabel: {
|
||
/**
|
||
* @description Whether to display axis label
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}件'
|
||
* @example formatter = (dataItem) => (dataItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Axis label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#333',
|
||
fontSize: 10,
|
||
rotate: 0
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis split line configuration
|
||
* @type {Object}
|
||
*/
|
||
splitLine: {
|
||
/**
|
||
* @description Whether to display axis split line
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Axis split line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#d4d4d4',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description X axis render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = -20
|
||
*/
|
||
rLevel: -20,
|
||
|
||
/**
|
||
* @description X axis animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description X axis animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.xAxisConfig = xAxisConfig;
|
||
var yAxisConfig = {
|
||
/**
|
||
* @description Axis name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Whether to display this axis
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis position
|
||
* @type {String}
|
||
* @default position = 'left'
|
||
* @example position = 'left' | 'right'
|
||
*/
|
||
position: 'left',
|
||
|
||
/**
|
||
* @description Name gap
|
||
* @type {Number}
|
||
* @default nameGap = 15
|
||
*/
|
||
nameGap: 15,
|
||
|
||
/**
|
||
* @description Name location
|
||
* @type {String}
|
||
* @default nameLocation = 'end'
|
||
* @example nameLocation = 'end' | 'center' | 'start'
|
||
*/
|
||
nameLocation: 'end',
|
||
|
||
/**
|
||
* @description name default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
nameTextStyle: {
|
||
fill: '#333',
|
||
fontSize: 10
|
||
},
|
||
|
||
/**
|
||
* @description Axis min value
|
||
* @type {String|Number}
|
||
* @default min = '20%'
|
||
* @example min = '20%' | 0
|
||
*/
|
||
min: '20%',
|
||
|
||
/**
|
||
* @description Axis max value
|
||
* @type {String|Number}
|
||
* @default max = '20%'
|
||
* @example max = '20%' | 0
|
||
*/
|
||
max: '20%',
|
||
|
||
/**
|
||
* @description Axis value interval
|
||
* @type {Number}
|
||
* @default interval = null
|
||
* @example interval = 100
|
||
*/
|
||
interval: null,
|
||
|
||
/**
|
||
* @description Min interval
|
||
* @type {Number}
|
||
* @default minInterval = null
|
||
* @example minInterval = 1
|
||
*/
|
||
minInterval: null,
|
||
|
||
/**
|
||
* @description Max interval
|
||
* @type {Number}
|
||
* @default maxInterval = null
|
||
* @example maxInterval = 100
|
||
*/
|
||
maxInterval: null,
|
||
|
||
/**
|
||
* @description Boundary gap
|
||
* @type {Boolean}
|
||
* @default boundaryGap = null
|
||
* @example boundaryGap = true
|
||
*/
|
||
boundaryGap: null,
|
||
|
||
/**
|
||
* @description Axis split number
|
||
* @type {Number}
|
||
* @default splitNumber = 5
|
||
*/
|
||
splitNumber: 5,
|
||
|
||
/**
|
||
* @description Axis line configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLine: {
|
||
/**
|
||
* @description Whether to display axis line
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#333',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis tick configuration
|
||
* @type {Object}
|
||
*/
|
||
axisTick: {
|
||
/**
|
||
* @description Whether to display axis tick
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis tick default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#333',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis label configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLabel: {
|
||
/**
|
||
* @description Whether to display axis label
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}件'
|
||
* @example formatter = (dataItem) => (dataItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Axis label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#333',
|
||
fontSize: 10,
|
||
rotate: 0
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis split line configuration
|
||
* @type {Object}
|
||
*/
|
||
splitLine: {
|
||
/**
|
||
* @description Whether to display axis split line
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis split line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#d4d4d4',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Y axis render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = -20
|
||
*/
|
||
rLevel: -20,
|
||
|
||
/**
|
||
* @description Y axis animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Y axis animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.yAxisConfig = yAxisConfig;
|
||
},{}],5:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.barConfig = void 0;
|
||
var barConfig = {
|
||
/**
|
||
* @description Whether to display this bar chart
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Data stacking
|
||
* The data value of the series element of the same stack
|
||
* will be superimposed (the latter value will be superimposed on the previous value)
|
||
* @type {String}
|
||
* @default stack = ''
|
||
*/
|
||
stack: '',
|
||
|
||
/**
|
||
* @description Bar shape type
|
||
* @type {String}
|
||
* @default shapeType = 'normal'
|
||
* @example shapeType = 'normal' | 'leftEchelon' | 'rightEchelon'
|
||
*/
|
||
shapeType: 'normal',
|
||
|
||
/**
|
||
* @description Echelon bar sharpness offset
|
||
* @type {Number}
|
||
* @default echelonOffset = 10
|
||
*/
|
||
echelonOffset: 10,
|
||
|
||
/**
|
||
* @description Bar width
|
||
* This property should be set on the last 'bar' series
|
||
* in this coordinate system to take effect and will be in effect
|
||
* for all 'bar' series in this coordinate system
|
||
* @type {String|Number}
|
||
* @default barWidth = 'auto'
|
||
* @example barWidth = 'auto' | '10%' | 20
|
||
*/
|
||
barWidth: 'auto',
|
||
|
||
/**
|
||
* @description Bar gap
|
||
* This property should be set on the last 'bar' series
|
||
* in this coordinate system to take effect and will be in effect
|
||
* for all 'bar' series in this coordinate system
|
||
* @type {String|Number}
|
||
* @default barGap = '30%'
|
||
* @example barGap = '30%' | 30
|
||
*/
|
||
barGap: '30%',
|
||
|
||
/**
|
||
* @description Bar category gap
|
||
* This property should be set on the last 'bar' series
|
||
* in this coordinate system to take effect and will be in effect
|
||
* for all 'bar' series in this coordinate system
|
||
* @type {String|Number}
|
||
* @default barCategoryGap = '20%'
|
||
* @example barCategoryGap = '20%' | 20
|
||
*/
|
||
barCategoryGap: '20%',
|
||
|
||
/**
|
||
* @description Bar x axis index
|
||
* @type {Number}
|
||
* @default xAxisIndex = 0
|
||
* @example xAxisIndex = 0 | 1
|
||
*/
|
||
xAxisIndex: 0,
|
||
|
||
/**
|
||
* @description Bar y axis index
|
||
* @type {Number}
|
||
* @default yAxisIndex = 0
|
||
* @example yAxisIndex = 0 | 1
|
||
*/
|
||
yAxisIndex: 0,
|
||
|
||
/**
|
||
* @description Bar chart data
|
||
* @type {Array}
|
||
* @default data = []
|
||
* @example data = [100, 200, 300]
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Background bar configuration
|
||
* @type {Object}
|
||
*/
|
||
backgroundBar: {
|
||
/**
|
||
* @description Whether to display background bar
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Background bar width
|
||
* @type {String|Number}
|
||
* @default width = 'auto'
|
||
* @example width = 'auto' | '30%' | 30
|
||
*/
|
||
width: 'auto',
|
||
|
||
/**
|
||
* @description Background bar default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: 'rgba(200, 200, 200, .4)'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Bar label configuration
|
||
* @type {Object}
|
||
*/
|
||
label: {
|
||
/**
|
||
* @description Whether to display bar label
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Bar label position
|
||
* @type {String}
|
||
* @default position = 'top'
|
||
* @example position = 'top' | 'center' | 'bottom'
|
||
*/
|
||
position: 'top',
|
||
|
||
/**
|
||
* @description Bar label offset
|
||
* @type {Array}
|
||
* @default offset = [0, -10]
|
||
*/
|
||
offset: [0, -10],
|
||
|
||
/**
|
||
* @description Bar label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}件'
|
||
* @example formatter = (dataItem) => (dataItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Bar label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 10
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Bar gradient configuration
|
||
* @type {Object}
|
||
*/
|
||
gradient: {
|
||
/**
|
||
* @description Gradient color (Hex|rgb|rgba)
|
||
* @type {Array}
|
||
* @default color = []
|
||
*/
|
||
color: [],
|
||
|
||
/**
|
||
* @description Local gradient
|
||
* @type {Boolean}
|
||
* @default local = true
|
||
*/
|
||
local: true
|
||
},
|
||
|
||
/**
|
||
* @description Bar style default configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
barStyle: {},
|
||
|
||
/**
|
||
* @description Independent color mode
|
||
* When set to true, independent color mode is enabled
|
||
* @type {Boolean}
|
||
* @default independentColor = false
|
||
*/
|
||
independentColor: false,
|
||
|
||
/**
|
||
* @description Independent colors
|
||
* Only effective when independent color mode is enabled
|
||
* Default value is the same as the color in the root configuration
|
||
* Two-dimensional color array can produce gradient colors
|
||
* @type {Array}
|
||
* @example independentColor = ['#fff', '#000']
|
||
* @example independentColor = [['#fff', '#000'], '#000']
|
||
*/
|
||
independentColors: [],
|
||
|
||
/**
|
||
* @description Bar chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 0
|
||
*/
|
||
rLevel: 0,
|
||
|
||
/**
|
||
* @description Bar animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Bar animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.barConfig = barConfig;
|
||
},{}],6:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.colorConfig = void 0;
|
||
var colorConfig = ['#37a2da', '#32c5e9', '#67e0e3', '#9fe6b8', '#ffdb5c', '#ff9f7f', '#fb7293', '#e062ae', '#e690d1', '#e7bcf3', '#9d96f5', '#8378ea', '#96bfff'];
|
||
exports.colorConfig = colorConfig;
|
||
},{}],7:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.gaugeConfig = void 0;
|
||
var gaugeConfig = {
|
||
/**
|
||
* @description Whether to display this gauge
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Radius of gauge
|
||
* @type {String|Number}
|
||
* @default radius = '60%'
|
||
* @example radius = '60%' | 100
|
||
*/
|
||
radius: '60%',
|
||
|
||
/**
|
||
* @description Center point of gauge
|
||
* @type {Array}
|
||
* @default center = ['50%','50%']
|
||
* @example center = ['50%','50%'] | [100, 100]
|
||
*/
|
||
center: ['50%', '50%'],
|
||
|
||
/**
|
||
* @description Gauge start angle
|
||
* @type {Number}
|
||
* @default startAngle = -(Math.PI / 4) * 5
|
||
* @example startAngle = -Math.PI
|
||
*/
|
||
startAngle: -(Math.PI / 4) * 5,
|
||
|
||
/**
|
||
* @description Gauge end angle
|
||
* @type {Number}
|
||
* @default endAngle = Math.PI / 4
|
||
* @example endAngle = 0
|
||
*/
|
||
endAngle: Math.PI / 4,
|
||
|
||
/**
|
||
* @description Gauge min value
|
||
* @type {Number}
|
||
* @default min = 0
|
||
*/
|
||
min: 0,
|
||
|
||
/**
|
||
* @description Gauge max value
|
||
* @type {Number}
|
||
* @default max = 100
|
||
*/
|
||
max: 100,
|
||
|
||
/**
|
||
* @description Gauge split number
|
||
* @type {Number}
|
||
* @default splitNum = 5
|
||
*/
|
||
splitNum: 5,
|
||
|
||
/**
|
||
* @description Gauge arc line width
|
||
* @type {Number}
|
||
* @default arcLineWidth = 15
|
||
*/
|
||
arcLineWidth: 15,
|
||
|
||
/**
|
||
* @description Gauge chart data
|
||
* @type {Array}
|
||
* @default data = []
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Data item arc default style configuration
|
||
* @type {Object}
|
||
* @default dataItemStyle = {Configuration Of Class Style}
|
||
*/
|
||
dataItemStyle: {},
|
||
|
||
/**
|
||
* @description Axis tick configuration
|
||
* @type {Object}
|
||
*/
|
||
axisTick: {
|
||
/**
|
||
* @description Whether to display axis tick
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis tick length
|
||
* @type {Number}
|
||
* @default tickLength = 6
|
||
*/
|
||
tickLength: 6,
|
||
|
||
/**
|
||
* @description Axis tick default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#999',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis label configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLabel: {
|
||
/**
|
||
* @description Whether to display axis label
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Axis label data (Can be calculated automatically)
|
||
* @type {Array}
|
||
* @default data = [Number...]
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Axis label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}%'
|
||
* @example formatter = (labelItem) => (labelItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Axis label gap between label and axis tick
|
||
* @type {String|Function}
|
||
* @default labelGap = 5
|
||
*/
|
||
labelGap: 5,
|
||
|
||
/**
|
||
* @description Axis label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {}
|
||
},
|
||
|
||
/**
|
||
* @description Gauge pointer configuration
|
||
* @type {Object}
|
||
*/
|
||
pointer: {
|
||
/**
|
||
* @description Whether to display pointer
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Pointer value index of data
|
||
* @type {Number}
|
||
* @default valueIndex = 0 (pointer.value = data[0].value)
|
||
*/
|
||
valueIndex: 0,
|
||
|
||
/**
|
||
* @description Pointer default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
scale: [1, 1],
|
||
fill: '#fb7293'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Data item arc detail configuration
|
||
* @type {Object}
|
||
*/
|
||
details: {
|
||
/**
|
||
* @description Whether to display details
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Details formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}%'
|
||
* @example formatter = '{name}%'
|
||
* @example formatter = (dataItem) => (dataItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Details position offset
|
||
* @type {Array}
|
||
* @default offset = [0, 0]
|
||
* @example offset = [10, 10]
|
||
*/
|
||
offset: [0, 0],
|
||
|
||
/**
|
||
* @description Value fractional precision
|
||
* @type {Number}
|
||
* @default valueToFixed = 0
|
||
*/
|
||
valueToFixed: 0,
|
||
|
||
/**
|
||
* @description Details position
|
||
* @type {String}
|
||
* @default position = 'center'
|
||
* @example position = 'start' | 'center' | 'end'
|
||
*/
|
||
position: 'center',
|
||
|
||
/**
|
||
* @description Details default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 20,
|
||
fontWeight: 'bold',
|
||
textAlign: 'center',
|
||
textBaseline: 'middle'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Gauge background arc configuration
|
||
* @type {Object}
|
||
*/
|
||
backgroundArc: {
|
||
/**
|
||
* @description Whether to display background arc
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Background arc default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#e0e0e0'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Gauge chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 10
|
||
*/
|
||
rLevel: 10,
|
||
|
||
/**
|
||
* @description Gauge animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Gauge animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.gaugeConfig = gaugeConfig;
|
||
},{}],8:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.gridConfig = void 0;
|
||
var gridConfig = {
|
||
/**
|
||
* @description Grid left margin
|
||
* @type {String|Number}
|
||
* @default left = '10%'
|
||
* @example left = '10%' | 10
|
||
*/
|
||
left: '10%',
|
||
|
||
/**
|
||
* @description Grid right margin
|
||
* @type {String|Number}
|
||
* @default right = '10%'
|
||
* @example right = '10%' | 10
|
||
*/
|
||
right: '10%',
|
||
|
||
/**
|
||
* @description Grid top margin
|
||
* @type {String|Number}
|
||
* @default top = 60
|
||
* @example top = '10%' | 60
|
||
*/
|
||
top: 60,
|
||
|
||
/**
|
||
* @description Grid bottom margin
|
||
* @type {String|Number}
|
||
* @default bottom = 60
|
||
* @example bottom = '10%' | 60
|
||
*/
|
||
bottom: 60,
|
||
|
||
/**
|
||
* @description Grid default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: 'rgba(0, 0, 0, 0)'
|
||
},
|
||
|
||
/**
|
||
* @description Grid render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = -30
|
||
*/
|
||
rLevel: -30,
|
||
|
||
/**
|
||
* @description Grid animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Grid animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 30
|
||
};
|
||
exports.gridConfig = gridConfig;
|
||
},{}],9:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.changeDefaultConfig = changeDefaultConfig;
|
||
Object.defineProperty(exports, "colorConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _color.colorConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "gridConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _grid.gridConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "xAxisConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _axis.xAxisConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "yAxisConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _axis.yAxisConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "titleConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _title.titleConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "lineConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _line.lineConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "barConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _bar.barConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "pieConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _pie.pieConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "radarAxisConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _radarAxis.radarAxisConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "radarConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _radar.radarConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "gaugeConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _gauge.gaugeConfig;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "legendConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _legend.legendConfig;
|
||
}
|
||
});
|
||
exports.keys = void 0;
|
||
|
||
var _color = require("./color");
|
||
|
||
var _grid = require("./grid");
|
||
|
||
var _axis = require("./axis");
|
||
|
||
var _title = require("./title");
|
||
|
||
var _line = require("./line");
|
||
|
||
var _bar = require("./bar");
|
||
|
||
var _pie = require("./pie");
|
||
|
||
var _radarAxis = require("./radarAxis");
|
||
|
||
var _radar = require("./radar");
|
||
|
||
var _gauge = require("./gauge");
|
||
|
||
var _legend = require("./legend");
|
||
|
||
var _util = require("../util");
|
||
|
||
var allConfig = {
|
||
colorConfig: _color.colorConfig,
|
||
gridConfig: _grid.gridConfig,
|
||
xAxisConfig: _axis.xAxisConfig,
|
||
yAxisConfig: _axis.yAxisConfig,
|
||
titleConfig: _title.titleConfig,
|
||
lineConfig: _line.lineConfig,
|
||
barConfig: _bar.barConfig,
|
||
pieConfig: _pie.pieConfig,
|
||
radarAxisConfig: _radarAxis.radarAxisConfig,
|
||
radarConfig: _radar.radarConfig,
|
||
gaugeConfig: _gauge.gaugeConfig,
|
||
legendConfig: _legend.legendConfig
|
||
/**
|
||
* @description Change default configuration
|
||
* @param {String} key Configuration key
|
||
* @param {Object|Array} config Your config
|
||
* @return {Undefined} No return
|
||
*/
|
||
|
||
};
|
||
|
||
function changeDefaultConfig(key, config) {
|
||
if (!allConfig["".concat(key, "Config")]) {
|
||
console.warn('Change default config Error - Invalid key!');
|
||
return;
|
||
}
|
||
|
||
(0, _util.deepMerge)(allConfig["".concat(key, "Config")], config);
|
||
}
|
||
|
||
var keys = ['color', 'title', 'legend', 'xAxis', 'yAxis', 'grid', 'radarAxis', 'line', 'bar', 'pie', 'radar', 'gauge'];
|
||
exports.keys = keys;
|
||
},{"../util":30,"./axis":4,"./bar":5,"./color":6,"./gauge":7,"./grid":8,"./legend":10,"./line":11,"./pie":12,"./radar":13,"./radarAxis":14,"./title":15}],10:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.legendConfig = void 0;
|
||
var legendConfig = {
|
||
/**
|
||
* @description Whether to display legend
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend orient
|
||
* @type {String}
|
||
* @default orient = 'horizontal'
|
||
* @example orient = 'horizontal' | 'vertical'
|
||
*/
|
||
orient: 'horizontal',
|
||
|
||
/**
|
||
* @description Legend left
|
||
* @type {String|Number}
|
||
* @default left = 'auto'
|
||
* @example left = 'auto' | '10%' | 10
|
||
*/
|
||
left: 'auto',
|
||
|
||
/**
|
||
* @description Legend right
|
||
* @type {String|Number}
|
||
* @default right = 'auto'
|
||
* @example right = 'auto' | '10%' | 10
|
||
*/
|
||
right: 'auto',
|
||
|
||
/**
|
||
* @description Legend top
|
||
* @type {String|Number}
|
||
* @default top = 'auto'
|
||
* @example top = 'auto' | '10%' | 10
|
||
*/
|
||
top: 'auto',
|
||
|
||
/**
|
||
* @description Legend bottom
|
||
* @type {String|Number}
|
||
* @default bottom = 'auto'
|
||
* @example bottom = 'auto' | '10%' | 10
|
||
*/
|
||
bottom: 'auto',
|
||
|
||
/**
|
||
* @description Legend item gap
|
||
* @type {Number}
|
||
* @default itemGap = 10
|
||
*/
|
||
itemGap: 10,
|
||
|
||
/**
|
||
* @description Icon width
|
||
* @type {Number}
|
||
* @default iconWidth = 25
|
||
*/
|
||
iconWidth: 25,
|
||
|
||
/**
|
||
* @description Icon height
|
||
* @type {Number}
|
||
* @default iconHeight = 10
|
||
*/
|
||
iconHeight: 10,
|
||
|
||
/**
|
||
* @description Whether legend is optional
|
||
* @type {Boolean}
|
||
* @default selectAble = true
|
||
*/
|
||
selectAble: true,
|
||
|
||
/**
|
||
* @description Legend data
|
||
* @type {Array}
|
||
* @default data = []
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Legend text default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
textStyle: {
|
||
fontFamily: 'Arial',
|
||
fontSize: 13,
|
||
fill: '#000'
|
||
},
|
||
|
||
/**
|
||
* @description Legend icon default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
iconStyle: {},
|
||
|
||
/**
|
||
* @description Legend text unselected default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
textUnselectedStyle: {
|
||
fontFamily: 'Arial',
|
||
fontSize: 13,
|
||
fill: '#999'
|
||
},
|
||
|
||
/**
|
||
* @description Legend icon unselected default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
iconUnselectedStyle: {
|
||
fill: '#999'
|
||
},
|
||
|
||
/**
|
||
* @description Legend render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 20
|
||
*/
|
||
rLevel: 20,
|
||
|
||
/**
|
||
* @description Legend animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Legend animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.legendConfig = legendConfig;
|
||
},{}],11:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.lineConfig = void 0;
|
||
var lineConfig = {
|
||
/**
|
||
* @description Whether to display this line chart
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Data stacking
|
||
* The data value of the series element of the same stack
|
||
* will be superimposed (the latter value will be superimposed on the previous value)
|
||
* @type {String}
|
||
* @default stack = ''
|
||
*/
|
||
stack: '',
|
||
|
||
/**
|
||
* @description Smooth line
|
||
* @type {Boolean}
|
||
* @default smooth = false
|
||
*/
|
||
smooth: false,
|
||
|
||
/**
|
||
* @description Line x axis index
|
||
* @type {Number}
|
||
* @default xAxisIndex = 0
|
||
* @example xAxisIndex = 0 | 1
|
||
*/
|
||
xAxisIndex: 0,
|
||
|
||
/**
|
||
* @description Line y axis index
|
||
* @type {Number}
|
||
* @default yAxisIndex = 0
|
||
* @example yAxisIndex = 0 | 1
|
||
*/
|
||
yAxisIndex: 0,
|
||
|
||
/**
|
||
* @description Line chart data
|
||
* @type {Array}
|
||
* @default data = []
|
||
* @example data = [100, 200, 300]
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
lineStyle: {
|
||
lineWidth: 1
|
||
},
|
||
|
||
/**
|
||
* @description Line point configuration
|
||
* @type {Object}
|
||
*/
|
||
linePoint: {
|
||
/**
|
||
* @description Whether to display line point
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Line point radius
|
||
* @type {Number}
|
||
* @default radius = 2
|
||
*/
|
||
radius: 2,
|
||
|
||
/**
|
||
* @description Line point default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#fff',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Line area configuration
|
||
* @type {Object}
|
||
*/
|
||
lineArea: {
|
||
/**
|
||
* @description Whether to display line area
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Line area gradient color (Hex|rgb|rgba)
|
||
* @type {Array}
|
||
* @default gradient = []
|
||
*/
|
||
gradient: [],
|
||
|
||
/**
|
||
* @description Line area style default configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
opacity: 0.5
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Line label configuration
|
||
* @type {Object}
|
||
*/
|
||
label: {
|
||
/**
|
||
* @description Whether to display line label
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Line label position
|
||
* @type {String}
|
||
* @default position = 'top'
|
||
* @example position = 'top' | 'center' | 'bottom'
|
||
*/
|
||
position: 'top',
|
||
|
||
/**
|
||
* @description Line label offset
|
||
* @type {Array}
|
||
* @default offset = [0, -10]
|
||
*/
|
||
offset: [0, -10],
|
||
|
||
/**
|
||
* @description Line label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = '{value}件'
|
||
* @example formatter = (dataItem) => (dataItem.value)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Line label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 10
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Line chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 10
|
||
*/
|
||
rLevel: 10,
|
||
|
||
/**
|
||
* @description Line animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Line animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.lineConfig = lineConfig;
|
||
},{}],12:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.pieConfig = void 0;
|
||
var pieConfig = {
|
||
/**
|
||
* @description Whether to display this pie chart
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Radius of pie
|
||
* @type {String|Number}
|
||
* @default radius = '50%'
|
||
* @example radius = '50%' | 100
|
||
*/
|
||
radius: '50%',
|
||
|
||
/**
|
||
* @description Center point of pie
|
||
* @type {Array}
|
||
* @default center = ['50%','50%']
|
||
* @example center = ['50%','50%'] | [100, 100]
|
||
*/
|
||
center: ['50%', '50%'],
|
||
|
||
/**
|
||
* @description Pie chart start angle
|
||
* @type {Number}
|
||
* @default startAngle = -Math.PI / 2
|
||
* @example startAngle = -Math.PI
|
||
*/
|
||
startAngle: -Math.PI / 2,
|
||
|
||
/**
|
||
* @description Whether to enable rose type
|
||
* @type {Boolean}
|
||
* @default roseType = false
|
||
*/
|
||
roseType: false,
|
||
|
||
/**
|
||
* @description Automatic sorting in rose type
|
||
* @type {Boolean}
|
||
* @default roseSort = true
|
||
*/
|
||
roseSort: true,
|
||
|
||
/**
|
||
* @description Rose radius increasing
|
||
* @type {String|Number}
|
||
* @default roseIncrement = 'auto'
|
||
* @example roseIncrement = 'auto' | '10%' | 10
|
||
*/
|
||
roseIncrement: 'auto',
|
||
|
||
/**
|
||
* @description Pie chart data
|
||
* @type {Array}
|
||
* @default data = []
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Pie inside label configuration
|
||
* @type {Object}
|
||
*/
|
||
insideLabel: {
|
||
/**
|
||
* @description Whether to display inside label
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = '{percent}%'
|
||
* @example formatter = '${name}-{value}-{percent}%'
|
||
* @example formatter = (dataItem) => (dataItem.name)
|
||
*/
|
||
formatter: '{percent}%',
|
||
|
||
/**
|
||
* @description Label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 10,
|
||
fill: '#fff',
|
||
textAlign: 'center',
|
||
textBaseline: 'middle'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Pie Outside label configuration
|
||
* @type {Object}
|
||
*/
|
||
outsideLabel: {
|
||
/**
|
||
* @description Whether to display outside label
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = '{name}'
|
||
* @example formatter = '${name}-{value}-{percent}%'
|
||
* @example formatter = (dataItem) => (dataItem.name)
|
||
*/
|
||
formatter: '{name}',
|
||
|
||
/**
|
||
* @description Label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 11
|
||
},
|
||
|
||
/**
|
||
* @description Gap beteen label line bended place and pie
|
||
* @type {String|Number}
|
||
* @default labelLineBendGap = '20%'
|
||
* @example labelLineBendGap = '20%' | 20
|
||
*/
|
||
labelLineBendGap: '20%',
|
||
|
||
/**
|
||
* @description Label line end length
|
||
* @type {Number}
|
||
* @default labelLineEndLength = 50
|
||
*/
|
||
labelLineEndLength: 50,
|
||
|
||
/**
|
||
* @description Label line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
labelLineStyle: {
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Pie default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
pieStyle: {},
|
||
|
||
/**
|
||
* @description Percentage fractional precision
|
||
* @type {Number}
|
||
* @default percentToFixed = 0
|
||
*/
|
||
percentToFixed: 0,
|
||
|
||
/**
|
||
* @description Pie chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 10
|
||
*/
|
||
rLevel: 10,
|
||
|
||
/**
|
||
* @description Animation delay gap
|
||
* @type {Number}
|
||
* @default animationDelayGap = 60
|
||
*/
|
||
animationDelayGap: 60,
|
||
|
||
/**
|
||
* @description Pie animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Pie start animation curve
|
||
* @type {String}
|
||
* @default startAnimationCurve = 'easeOutBack'
|
||
*/
|
||
startAnimationCurve: 'easeOutBack',
|
||
|
||
/**
|
||
* @description Pie animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.pieConfig = pieConfig;
|
||
},{}],13:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.radarConfig = void 0;
|
||
var radarConfig = {
|
||
/**
|
||
* @description Whether to display this radar
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Legend name
|
||
* @type {String}
|
||
* @default name = ''
|
||
*/
|
||
name: '',
|
||
|
||
/**
|
||
* @description Radar chart data
|
||
* @type {Array}
|
||
* @default data = []
|
||
* @example data = [100, 200, 300]
|
||
*/
|
||
data: [],
|
||
|
||
/**
|
||
* @description Radar default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
radarStyle: {
|
||
lineWidth: 1
|
||
},
|
||
|
||
/**
|
||
* @description Radar point configuration
|
||
* @type {Object}
|
||
*/
|
||
point: {
|
||
/**
|
||
* @description Whether to display radar point
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Point radius
|
||
* @type {Number}
|
||
* @default radius = 2
|
||
*/
|
||
radius: 2,
|
||
|
||
/**
|
||
* @description Radar point default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#fff'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Radar label configuration
|
||
* @type {Object}
|
||
*/
|
||
label: {
|
||
/**
|
||
* @description Whether to display radar label
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Label position offset
|
||
* @type {Array}
|
||
* @default offset = [0, 0]
|
||
*/
|
||
offset: [0, 0],
|
||
|
||
/**
|
||
* @description Label gap between label and radar
|
||
* @type {Number}
|
||
* @default labelGap = 5
|
||
*/
|
||
labelGap: 5,
|
||
|
||
/**
|
||
* @description Label formatter
|
||
* @type {String|Function}
|
||
* @default formatter = null
|
||
* @example formatter = 'Score-{value}'
|
||
* @example formatter = (label) => (label)
|
||
*/
|
||
formatter: null,
|
||
|
||
/**
|
||
* @description Radar label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fontSize: 10
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Radar chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 10
|
||
*/
|
||
rLevel: 10,
|
||
|
||
/**
|
||
* @description Radar animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Radar animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrane: 50
|
||
};
|
||
exports.radarConfig = radarConfig;
|
||
},{}],14:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.radarAxisConfig = void 0;
|
||
var radarAxisConfig = {
|
||
/**
|
||
* @description Whether to display this radar axis
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Center point of radar axis
|
||
* @type {Array}
|
||
* @default center = ['50%','50%']
|
||
* @example center = ['50%','50%'] | [100, 100]
|
||
*/
|
||
center: ['50%', '50%'],
|
||
|
||
/**
|
||
* @description Radius of radar axis
|
||
* @type {String|Number}
|
||
* @default radius = '65%'
|
||
* @example radius = '65%' | 100
|
||
*/
|
||
radius: '65%',
|
||
|
||
/**
|
||
* @description Radar axis start angle
|
||
* @type {Number}
|
||
* @default startAngle = -Math.PI / 2
|
||
* @example startAngle = -Math.PI
|
||
*/
|
||
startAngle: -Math.PI / 2,
|
||
|
||
/**
|
||
* @description Radar axis split number
|
||
* @type {Number}
|
||
* @default splitNum = 5
|
||
*/
|
||
splitNum: 5,
|
||
|
||
/**
|
||
* @description Whether to enable polygon radar axis
|
||
* @type {Boolean}
|
||
* @default polygon = false
|
||
*/
|
||
polygon: false,
|
||
|
||
/**
|
||
* @description Axis label configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLabel: {
|
||
/**
|
||
* @description Whether to display axis label
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Label gap between label and radar axis
|
||
* @type {Number}
|
||
* @default labelGap = 15
|
||
*/
|
||
labelGap: 15,
|
||
|
||
/**
|
||
* @description Label color (Hex|rgb|rgba), will cover style.fill
|
||
* @type {Array}
|
||
* @default color = []
|
||
*/
|
||
color: [],
|
||
|
||
/**
|
||
* @description Axis label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#333'
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Axis line configuration
|
||
* @type {Object}
|
||
*/
|
||
axisLine: {
|
||
/**
|
||
* @description Whether to display axis line
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Line color (Hex|rgb|rgba), will cover style.stroke
|
||
* @type {Array}
|
||
* @default color = []
|
||
*/
|
||
color: [],
|
||
|
||
/**
|
||
* @description Axis label default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#999',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Split line configuration
|
||
* @type {Object}
|
||
*/
|
||
splitLine: {
|
||
/**
|
||
* @description Whether to display split line
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Line color (Hex|rgb|rgba), will cover style.stroke
|
||
* @type {Array}
|
||
* @default color = []
|
||
*/
|
||
color: [],
|
||
|
||
/**
|
||
* @description Split line default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
stroke: '#d4d4d4',
|
||
lineWidth: 1
|
||
}
|
||
},
|
||
|
||
/**
|
||
* @description Split area configuration
|
||
* @type {Object}
|
||
*/
|
||
splitArea: {
|
||
/**
|
||
* @description Whether to display split area
|
||
* @type {Boolean}
|
||
* @default show = false
|
||
*/
|
||
show: false,
|
||
|
||
/**
|
||
* @description Area color (Hex|rgb|rgba), will cover style.stroke
|
||
* @type {Array}
|
||
* @default color = []
|
||
*/
|
||
color: ['#f5f5f5', '#e6e6e6'],
|
||
|
||
/**
|
||
* @description Split area default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {}
|
||
},
|
||
|
||
/**
|
||
* @description Bar chart render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = -10
|
||
*/
|
||
rLevel: -10,
|
||
|
||
/**
|
||
* @description Radar axis animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Radar axis animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrane: 50
|
||
};
|
||
exports.radarAxisConfig = radarAxisConfig;
|
||
},{}],15:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.titleConfig = void 0;
|
||
var titleConfig = {
|
||
/**
|
||
* @description Whether to display title
|
||
* @type {Boolean}
|
||
* @default show = true
|
||
*/
|
||
show: true,
|
||
|
||
/**
|
||
* @description Title text
|
||
* @type {String}
|
||
* @default text = ''
|
||
*/
|
||
text: '',
|
||
|
||
/**
|
||
* @description Title offset
|
||
* @type {Array}
|
||
* @default offset = [0, -20]
|
||
*/
|
||
offset: [0, -20],
|
||
|
||
/**
|
||
* @description Title default style configuration
|
||
* @type {Object}
|
||
* @default style = {Configuration Of Class Style}
|
||
*/
|
||
style: {
|
||
fill: '#333',
|
||
fontSize: 17,
|
||
fontWeight: 'bold',
|
||
textAlign: 'center',
|
||
textBaseline: 'bottom'
|
||
},
|
||
|
||
/**
|
||
* @description Title render level
|
||
* Priority rendering high level
|
||
* @type {Number}
|
||
* @default rLevel = 20
|
||
*/
|
||
rLevel: 20,
|
||
|
||
/**
|
||
* @description Title animation curve
|
||
* @type {String}
|
||
* @default animationCurve = 'easeOutCubic'
|
||
*/
|
||
animationCurve: 'easeOutCubic',
|
||
|
||
/**
|
||
* @description Title animation frame
|
||
* @type {Number}
|
||
* @default animationFrame = 50
|
||
*/
|
||
animationFrame: 50
|
||
};
|
||
exports.titleConfig = titleConfig;
|
||
},{}],16:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.axis = axis;
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util = require("../util");
|
||
|
||
var _util2 = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
var axisConfig = {
|
||
xAxisConfig: _config.xAxisConfig,
|
||
yAxisConfig: _config.yAxisConfig
|
||
};
|
||
var min = Math.min,
|
||
max = Math.max,
|
||
abs = Math.abs,
|
||
pow = Math.pow;
|
||
|
||
function axis(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var xAxis = option.xAxis,
|
||
yAxis = option.yAxis,
|
||
series = option.series;
|
||
var allAxis = [];
|
||
|
||
if (xAxis && yAxis && series) {
|
||
allAxis = getAllAxis(xAxis, yAxis);
|
||
allAxis = mergeDefaultAxisConfig(allAxis);
|
||
allAxis = allAxis.filter(function (_ref) {
|
||
var show = _ref.show;
|
||
return show;
|
||
});
|
||
allAxis = mergeDefaultBoundaryGap(allAxis);
|
||
allAxis = calcAxisLabelData(allAxis, series);
|
||
allAxis = setAxisPosition(allAxis);
|
||
allAxis = calcAxisLinePosition(allAxis, chart);
|
||
allAxis = calcAxisTickPosition(allAxis, chart);
|
||
allAxis = calcAxisNamePosition(allAxis, chart);
|
||
allAxis = calcSplitLinePosition(allAxis, chart);
|
||
}
|
||
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: allAxis,
|
||
key: 'axisLine',
|
||
getGraphConfig: getLineConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: allAxis,
|
||
key: 'axisTick',
|
||
getGraphConfig: getTickConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: allAxis,
|
||
key: 'axisLabel',
|
||
getGraphConfig: getLabelConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: allAxis,
|
||
key: 'axisName',
|
||
getGraphConfig: getNameConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: allAxis,
|
||
key: 'splitLine',
|
||
getGraphConfig: getSplitLineConfig
|
||
});
|
||
chart.axisData = allAxis;
|
||
}
|
||
|
||
function getAllAxis(xAxis, yAxis) {
|
||
var allXAxis = [],
|
||
allYAxis = [];
|
||
|
||
if (xAxis instanceof Array) {
|
||
var _allXAxis;
|
||
|
||
(_allXAxis = allXAxis).push.apply(_allXAxis, (0, _toConsumableArray2["default"])(xAxis));
|
||
} else {
|
||
allXAxis.push(xAxis);
|
||
}
|
||
|
||
if (yAxis instanceof Array) {
|
||
var _allYAxis;
|
||
|
||
(_allYAxis = allYAxis).push.apply(_allYAxis, (0, _toConsumableArray2["default"])(yAxis));
|
||
} else {
|
||
allYAxis.push(yAxis);
|
||
}
|
||
|
||
allXAxis.splice(2);
|
||
allYAxis.splice(2);
|
||
allXAxis = allXAxis.map(function (axis, i) {
|
||
return _objectSpread({}, axis, {
|
||
index: i,
|
||
axis: 'x'
|
||
});
|
||
});
|
||
allYAxis = allYAxis.map(function (axis, i) {
|
||
return _objectSpread({}, axis, {
|
||
index: i,
|
||
axis: 'y'
|
||
});
|
||
});
|
||
return [].concat((0, _toConsumableArray2["default"])(allXAxis), (0, _toConsumableArray2["default"])(allYAxis));
|
||
}
|
||
|
||
function mergeDefaultAxisConfig(allAxis) {
|
||
var xAxis = allAxis.filter(function (_ref2) {
|
||
var axis = _ref2.axis;
|
||
return axis === 'x';
|
||
});
|
||
var yAxis = allAxis.filter(function (_ref3) {
|
||
var axis = _ref3.axis;
|
||
return axis === 'y';
|
||
});
|
||
xAxis = xAxis.map(function (axis) {
|
||
return (0, _util.deepMerge)((0, _util2.deepClone)(_config.xAxisConfig), axis);
|
||
});
|
||
yAxis = yAxis.map(function (axis) {
|
||
return (0, _util.deepMerge)((0, _util2.deepClone)(_config.yAxisConfig), axis);
|
||
});
|
||
return [].concat((0, _toConsumableArray2["default"])(xAxis), (0, _toConsumableArray2["default"])(yAxis));
|
||
}
|
||
|
||
function mergeDefaultBoundaryGap(allAxis) {
|
||
var valueAxis = allAxis.filter(function (_ref4) {
|
||
var data = _ref4.data;
|
||
return data === 'value';
|
||
});
|
||
var labelAxis = allAxis.filter(function (_ref5) {
|
||
var data = _ref5.data;
|
||
return data !== 'value';
|
||
});
|
||
valueAxis.forEach(function (axis) {
|
||
if (typeof axis.boundaryGap === 'boolean') return;
|
||
axis.boundaryGap = false;
|
||
});
|
||
labelAxis.forEach(function (axis) {
|
||
if (typeof axis.boundaryGap === 'boolean') return;
|
||
axis.boundaryGap = true;
|
||
});
|
||
return [].concat((0, _toConsumableArray2["default"])(valueAxis), (0, _toConsumableArray2["default"])(labelAxis));
|
||
}
|
||
|
||
function calcAxisLabelData(allAxis, series) {
|
||
var valueAxis = allAxis.filter(function (_ref6) {
|
||
var data = _ref6.data;
|
||
return data === 'value';
|
||
});
|
||
var labelAxis = allAxis.filter(function (_ref7) {
|
||
var data = _ref7.data;
|
||
return data instanceof Array;
|
||
});
|
||
valueAxis = calcValueAxisLabelData(valueAxis, series);
|
||
labelAxis = calcLabelAxisLabelData(labelAxis);
|
||
return [].concat((0, _toConsumableArray2["default"])(valueAxis), (0, _toConsumableArray2["default"])(labelAxis));
|
||
}
|
||
|
||
function calcValueAxisLabelData(valueAxis, series) {
|
||
return valueAxis.map(function (axis) {
|
||
var minMaxValue = getValueAxisMaxMinValue(axis, series);
|
||
|
||
var _getTrueMinMax = getTrueMinMax(axis, minMaxValue),
|
||
_getTrueMinMax2 = (0, _slicedToArray2["default"])(_getTrueMinMax, 2),
|
||
min = _getTrueMinMax2[0],
|
||
max = _getTrueMinMax2[1];
|
||
|
||
var interval = getValueInterval(min, max, axis);
|
||
var formatter = axis.axisLabel.formatter;
|
||
var label = [];
|
||
|
||
if (minMaxValue[0] === minMaxValue[1]) {
|
||
label = minMaxValue;
|
||
} else if (min < 0 && max > 0) {
|
||
label = getValueAxisLabelFromZero(min, max, interval);
|
||
} else {
|
||
label = getValueAxisLabelFromMin(min, max, interval);
|
||
}
|
||
|
||
label = label.map(function (l) {
|
||
return parseFloat(l.toFixed(2));
|
||
});
|
||
return _objectSpread({}, axis, {
|
||
maxValue: label.slice(-1)[0],
|
||
minValue: label[0],
|
||
label: getAfterFormatterLabel(label, formatter)
|
||
});
|
||
});
|
||
}
|
||
|
||
function getValueAxisMaxMinValue(axis, series) {
|
||
series = series.filter(function (_ref8) {
|
||
var show = _ref8.show,
|
||
type = _ref8.type;
|
||
if (show === false) return false;
|
||
if (type === 'pie') return false;
|
||
return true;
|
||
});
|
||
if (series.length === 0) return [0, 0];
|
||
var index = axis.index,
|
||
axisType = axis.axis;
|
||
series = mergeStackData(series);
|
||
var axisName = axisType + 'Axis';
|
||
var valueSeries = series.filter(function (s) {
|
||
return s[axisName] === index;
|
||
});
|
||
if (!valueSeries.length) valueSeries = series;
|
||
return getSeriesMinMaxValue(valueSeries);
|
||
}
|
||
|
||
function getSeriesMinMaxValue(series) {
|
||
if (!series) return;
|
||
var minValue = Math.min.apply(Math, (0, _toConsumableArray2["default"])(series.map(function (_ref9) {
|
||
var data = _ref9.data;
|
||
return Math.min.apply(Math, (0, _toConsumableArray2["default"])((0, _util.filterNonNumber)(data)));
|
||
})));
|
||
var maxValue = Math.max.apply(Math, (0, _toConsumableArray2["default"])(series.map(function (_ref10) {
|
||
var data = _ref10.data;
|
||
return Math.max.apply(Math, (0, _toConsumableArray2["default"])((0, _util.filterNonNumber)(data)));
|
||
})));
|
||
return [minValue, maxValue];
|
||
}
|
||
|
||
function mergeStackData(series) {
|
||
var seriesCloned = (0, _util2.deepClone)(series, true);
|
||
series.forEach(function (item, i) {
|
||
var data = (0, _util.mergeSameStackData)(item, series);
|
||
seriesCloned[i].data = data;
|
||
});
|
||
return seriesCloned;
|
||
}
|
||
|
||
function getTrueMinMax(_ref11, _ref12) {
|
||
var min = _ref11.min,
|
||
max = _ref11.max,
|
||
axis = _ref11.axis;
|
||
|
||
var _ref13 = (0, _slicedToArray2["default"])(_ref12, 2),
|
||
minValue = _ref13[0],
|
||
maxValue = _ref13[1];
|
||
|
||
var minType = (0, _typeof2["default"])(min),
|
||
maxType = (0, _typeof2["default"])(max);
|
||
|
||
if (!testMinMaxType(min)) {
|
||
min = axisConfig[axis + 'AxisConfig'].min;
|
||
minType = 'string';
|
||
}
|
||
|
||
if (!testMinMaxType(max)) {
|
||
max = axisConfig[axis + 'AxisConfig'].max;
|
||
maxType = 'string';
|
||
}
|
||
|
||
if (minType === 'string') {
|
||
min = parseInt(minValue - abs(minValue * parseFloat(min) / 100));
|
||
var lever = getValueLever(min);
|
||
min = parseFloat((min / lever - 0.1).toFixed(1)) * lever;
|
||
}
|
||
|
||
if (maxType === 'string') {
|
||
max = parseInt(maxValue + abs(maxValue * parseFloat(max) / 100));
|
||
|
||
var _lever = getValueLever(max);
|
||
|
||
max = parseFloat((max / _lever + 0.1).toFixed(1)) * _lever;
|
||
}
|
||
|
||
return [min, max];
|
||
}
|
||
|
||
function getValueLever(value) {
|
||
var valueString = abs(value).toString();
|
||
var valueLength = valueString.length;
|
||
var firstZeroIndex = valueString.replace(/0*$/g, '').indexOf('0');
|
||
var pow10Num = valueLength - 1;
|
||
if (firstZeroIndex !== -1) pow10Num -= firstZeroIndex;
|
||
return pow(10, pow10Num);
|
||
}
|
||
|
||
function testMinMaxType(val) {
|
||
var valType = (0, _typeof2["default"])(val);
|
||
var isValidString = valType === 'string' && /^\d+%$/.test(val);
|
||
var isValidNumber = valType === 'number';
|
||
return isValidString || isValidNumber;
|
||
}
|
||
|
||
function getValueAxisLabelFromZero(min, max, interval) {
|
||
var negative = [],
|
||
positive = [];
|
||
var currentNegative = 0,
|
||
currentPositive = 0;
|
||
|
||
do {
|
||
negative.push(currentNegative -= interval);
|
||
} while (currentNegative > min);
|
||
|
||
do {
|
||
positive.push(currentPositive += interval);
|
||
} while (currentPositive < max);
|
||
|
||
return [].concat((0, _toConsumableArray2["default"])(negative.reverse()), [0], (0, _toConsumableArray2["default"])(positive));
|
||
}
|
||
|
||
function getValueAxisLabelFromMin(min, max, interval) {
|
||
var label = [min],
|
||
currentValue = min;
|
||
|
||
do {
|
||
label.push(currentValue += interval);
|
||
} while (currentValue < max);
|
||
|
||
return label;
|
||
}
|
||
|
||
function getAfterFormatterLabel(label, formatter) {
|
||
if (!formatter) return label;
|
||
if (typeof formatter === 'string') label = label.map(function (l) {
|
||
return formatter.replace('{value}', l);
|
||
});
|
||
if (typeof formatter === 'function') label = label.map(function (value, index) {
|
||
return formatter({
|
||
value: value,
|
||
index: index
|
||
});
|
||
});
|
||
return label;
|
||
}
|
||
|
||
function calcLabelAxisLabelData(labelAxis) {
|
||
return labelAxis.map(function (axis) {
|
||
var data = axis.data,
|
||
formatter = axis.axisLabel.formatter;
|
||
return _objectSpread({}, axis, {
|
||
label: getAfterFormatterLabel(data, formatter)
|
||
});
|
||
});
|
||
}
|
||
|
||
function getValueInterval(min, max, axis) {
|
||
var interval = axis.interval,
|
||
minInterval = axis.minInterval,
|
||
maxInterval = axis.maxInterval,
|
||
splitNumber = axis.splitNumber,
|
||
axisType = axis.axis;
|
||
var config = axisConfig[axisType + 'AxisConfig'];
|
||
if (typeof interval !== 'number') interval = config.interval;
|
||
if (typeof minInterval !== 'number') minInterval = config.minInterval;
|
||
if (typeof maxInterval !== 'number') maxInterval = config.maxInterval;
|
||
if (typeof splitNumber !== 'number') splitNumber = config.splitNumber;
|
||
if (typeof interval === 'number') return interval;
|
||
var valueInterval = parseInt((max - min) / (splitNumber - 1));
|
||
if (valueInterval.toString().length > 1) valueInterval = parseInt(valueInterval.toString().replace(/\d$/, '0'));
|
||
if (valueInterval === 0) valueInterval = 1;
|
||
if (typeof minInterval === 'number' && valueInterval < minInterval) return minInterval;
|
||
if (typeof maxInterval === 'number' && valueInterval > maxInterval) return maxInterval;
|
||
return valueInterval;
|
||
}
|
||
|
||
function setAxisPosition(allAxis) {
|
||
var xAxis = allAxis.filter(function (_ref14) {
|
||
var axis = _ref14.axis;
|
||
return axis === 'x';
|
||
});
|
||
var yAxis = allAxis.filter(function (_ref15) {
|
||
var axis = _ref15.axis;
|
||
return axis === 'y';
|
||
});
|
||
if (xAxis[0] && !xAxis[0].position) xAxis[0].position = _config.xAxisConfig.position;
|
||
|
||
if (xAxis[1] && !xAxis[1].position) {
|
||
xAxis[1].position = xAxis[0].position === 'bottom' ? 'top' : 'bottom';
|
||
}
|
||
|
||
if (yAxis[0] && !yAxis[0].position) yAxis[0].position = _config.yAxisConfig.position;
|
||
|
||
if (yAxis[1] && !yAxis[1].position) {
|
||
yAxis[1].position = yAxis[0].position === 'left' ? 'right' : 'left';
|
||
}
|
||
|
||
return [].concat((0, _toConsumableArray2["default"])(xAxis), (0, _toConsumableArray2["default"])(yAxis));
|
||
}
|
||
|
||
function calcAxisLinePosition(allAxis, chart) {
|
||
var _chart$gridArea = chart.gridArea,
|
||
x = _chart$gridArea.x,
|
||
y = _chart$gridArea.y,
|
||
w = _chart$gridArea.w,
|
||
h = _chart$gridArea.h;
|
||
allAxis = allAxis.map(function (axis) {
|
||
var position = axis.position;
|
||
var linePosition = [];
|
||
|
||
if (position === 'left') {
|
||
linePosition = [[x, y], [x, y + h]].reverse();
|
||
} else if (position === 'right') {
|
||
linePosition = [[x + w, y], [x + w, y + h]].reverse();
|
||
} else if (position === 'top') {
|
||
linePosition = [[x, y], [x + w, y]];
|
||
} else if (position === 'bottom') {
|
||
linePosition = [[x, y + h], [x + w, y + h]];
|
||
}
|
||
|
||
return _objectSpread({}, axis, {
|
||
linePosition: linePosition
|
||
});
|
||
});
|
||
return allAxis;
|
||
}
|
||
|
||
function calcAxisTickPosition(allAxis, chart) {
|
||
return allAxis.map(function (axisItem) {
|
||
var axis = axisItem.axis,
|
||
linePosition = axisItem.linePosition,
|
||
position = axisItem.position,
|
||
label = axisItem.label,
|
||
boundaryGap = axisItem.boundaryGap;
|
||
if (typeof boundaryGap !== 'boolean') boundaryGap = axisConfig[axis + 'AxisConfig'].boundaryGap;
|
||
var labelNum = label.length;
|
||
|
||
var _linePosition = (0, _slicedToArray2["default"])(linePosition, 2),
|
||
_linePosition$ = (0, _slicedToArray2["default"])(_linePosition[0], 2),
|
||
startX = _linePosition$[0],
|
||
startY = _linePosition$[1],
|
||
_linePosition$2 = (0, _slicedToArray2["default"])(_linePosition[1], 2),
|
||
endX = _linePosition$2[0],
|
||
endY = _linePosition$2[1];
|
||
|
||
var gapLength = axis === 'x' ? endX - startX : endY - startY;
|
||
var gap = gapLength / (boundaryGap ? labelNum : labelNum - 1);
|
||
var tickPosition = new Array(labelNum).fill(0).map(function (foo, i) {
|
||
if (axis === 'x') {
|
||
return [startX + gap * (boundaryGap ? i + 0.5 : i), startY];
|
||
}
|
||
|
||
return [startX, startY + gap * (boundaryGap ? i + 0.5 : i)];
|
||
});
|
||
var tickLinePosition = getTickLinePosition(axis, boundaryGap, position, tickPosition, gap);
|
||
return _objectSpread({}, axisItem, {
|
||
tickPosition: tickPosition,
|
||
tickLinePosition: tickLinePosition,
|
||
tickGap: gap
|
||
});
|
||
});
|
||
}
|
||
|
||
function getTickLinePosition(axisType, boundaryGap, position, tickPosition, gap) {
|
||
var index = axisType === 'x' ? 1 : 0;
|
||
var plus = 5;
|
||
if (axisType === 'x' && position === 'top') plus = -5;
|
||
if (axisType === 'y' && position === 'left') plus = -5;
|
||
var tickLinePosition = tickPosition.map(function (lineStart) {
|
||
var lineEnd = (0, _util2.deepClone)(lineStart);
|
||
lineEnd[index] += plus;
|
||
return [(0, _util2.deepClone)(lineStart), lineEnd];
|
||
});
|
||
if (!boundaryGap) return tickLinePosition;
|
||
index = axisType === 'x' ? 0 : 1;
|
||
plus = gap / 2;
|
||
tickLinePosition.forEach(function (_ref16) {
|
||
var _ref17 = (0, _slicedToArray2["default"])(_ref16, 2),
|
||
lineStart = _ref17[0],
|
||
lineEnd = _ref17[1];
|
||
|
||
lineStart[index] += plus;
|
||
lineEnd[index] += plus;
|
||
});
|
||
return tickLinePosition;
|
||
}
|
||
|
||
function calcAxisNamePosition(allAxis, chart) {
|
||
return allAxis.map(function (axisItem) {
|
||
var nameGap = axisItem.nameGap,
|
||
nameLocation = axisItem.nameLocation,
|
||
position = axisItem.position,
|
||
linePosition = axisItem.linePosition;
|
||
|
||
var _linePosition2 = (0, _slicedToArray2["default"])(linePosition, 2),
|
||
lineStart = _linePosition2[0],
|
||
lineEnd = _linePosition2[1];
|
||
|
||
var namePosition = (0, _toConsumableArray2["default"])(lineStart);
|
||
if (nameLocation === 'end') namePosition = (0, _toConsumableArray2["default"])(lineEnd);
|
||
|
||
if (nameLocation === 'center') {
|
||
namePosition[0] = (lineStart[0] + lineEnd[0]) / 2;
|
||
namePosition[1] = (lineStart[1] + lineEnd[1]) / 2;
|
||
}
|
||
|
||
var index = 0;
|
||
if (position === 'top' && nameLocation === 'center') index = 1;
|
||
if (position === 'bottom' && nameLocation === 'center') index = 1;
|
||
if (position === 'left' && nameLocation !== 'center') index = 1;
|
||
if (position === 'right' && nameLocation !== 'center') index = 1;
|
||
var plus = nameGap;
|
||
if (position === 'top' && nameLocation !== 'end') plus *= -1;
|
||
if (position === 'left' && nameLocation !== 'start') plus *= -1;
|
||
if (position === 'bottom' && nameLocation === 'start') plus *= -1;
|
||
if (position === 'right' && nameLocation === 'end') plus *= -1;
|
||
namePosition[index] += plus;
|
||
return _objectSpread({}, axisItem, {
|
||
namePosition: namePosition
|
||
});
|
||
});
|
||
}
|
||
|
||
function calcSplitLinePosition(allAxis, chart) {
|
||
var _chart$gridArea2 = chart.gridArea,
|
||
w = _chart$gridArea2.w,
|
||
h = _chart$gridArea2.h;
|
||
return allAxis.map(function (axisItem) {
|
||
var tickLinePosition = axisItem.tickLinePosition,
|
||
position = axisItem.position,
|
||
boundaryGap = axisItem.boundaryGap;
|
||
var index = 0,
|
||
plus = w;
|
||
if (position === 'top' || position === 'bottom') index = 1;
|
||
if (position === 'top' || position === 'bottom') plus = h;
|
||
if (position === 'right' || position === 'bottom') plus *= -1;
|
||
var splitLinePosition = tickLinePosition.map(function (_ref18) {
|
||
var _ref19 = (0, _slicedToArray2["default"])(_ref18, 1),
|
||
startPoint = _ref19[0];
|
||
|
||
var endPoint = (0, _toConsumableArray2["default"])(startPoint);
|
||
endPoint[index] += plus;
|
||
return [(0, _toConsumableArray2["default"])(startPoint), endPoint];
|
||
});
|
||
if (!boundaryGap) splitLinePosition.shift();
|
||
return _objectSpread({}, axisItem, {
|
||
splitLinePosition: splitLinePosition
|
||
});
|
||
});
|
||
}
|
||
|
||
function getLineConfig(axisItem) {
|
||
var animationCurve = axisItem.animationCurve,
|
||
animationFrame = axisItem.animationFrame,
|
||
rLevel = axisItem.rLevel;
|
||
return [{
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: axisItem.axisLine.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getLineShape(axisItem),
|
||
style: getLineStyle(axisItem)
|
||
}];
|
||
}
|
||
|
||
function getLineShape(axisItem) {
|
||
var linePosition = axisItem.linePosition;
|
||
return {
|
||
points: linePosition
|
||
};
|
||
}
|
||
|
||
function getLineStyle(axisItem) {
|
||
return axisItem.axisLine.style;
|
||
}
|
||
|
||
function getTickConfig(axisItem) {
|
||
var animationCurve = axisItem.animationCurve,
|
||
animationFrame = axisItem.animationFrame,
|
||
rLevel = axisItem.rLevel;
|
||
var shapes = getTickShapes(axisItem);
|
||
var style = getTickStyle(axisItem);
|
||
return shapes.map(function (shape) {
|
||
return {
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: axisItem.axisTick.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getTickShapes(axisItem) {
|
||
var tickLinePosition = axisItem.tickLinePosition;
|
||
return tickLinePosition.map(function (points) {
|
||
return {
|
||
points: points
|
||
};
|
||
});
|
||
}
|
||
|
||
function getTickStyle(axisItem) {
|
||
return axisItem.axisTick.style;
|
||
}
|
||
|
||
function getLabelConfig(axisItem) {
|
||
var animationCurve = axisItem.animationCurve,
|
||
animationFrame = axisItem.animationFrame,
|
||
rLevel = axisItem.rLevel;
|
||
var shapes = getLabelShapes(axisItem);
|
||
var styles = getLabelStyle(axisItem, shapes);
|
||
return shapes.map(function (shape, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: axisItem.axisLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: styles[i],
|
||
setGraphCenter: function setGraphCenter() {
|
||
return void 0;
|
||
}
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelShapes(axisItem) {
|
||
var label = axisItem.label,
|
||
tickPosition = axisItem.tickPosition,
|
||
position = axisItem.position;
|
||
return tickPosition.map(function (point, i) {
|
||
return {
|
||
position: getLabelRealPosition(point, position),
|
||
content: label[i].toString()
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelRealPosition(points, position) {
|
||
var index = 0,
|
||
plus = 10;
|
||
if (position === 'top' || position === 'bottom') index = 1;
|
||
if (position === 'top' || position === 'left') plus = -10;
|
||
points = (0, _util2.deepClone)(points);
|
||
points[index] += plus;
|
||
return points;
|
||
}
|
||
|
||
function getLabelStyle(axisItem, shapes) {
|
||
var position = axisItem.position;
|
||
var style = axisItem.axisLabel.style;
|
||
var align = getAxisLabelRealAlign(position);
|
||
style = (0, _util.deepMerge)(align, style);
|
||
var styles = shapes.map(function (_ref20) {
|
||
var position = _ref20.position;
|
||
return _objectSpread({}, style, {
|
||
graphCenter: position
|
||
});
|
||
});
|
||
return styles;
|
||
}
|
||
|
||
function getAxisLabelRealAlign(position) {
|
||
if (position === 'left') return {
|
||
textAlign: 'right',
|
||
textBaseline: 'middle'
|
||
};
|
||
if (position === 'right') return {
|
||
textAlign: 'left',
|
||
textBaseline: 'middle'
|
||
};
|
||
if (position === 'top') return {
|
||
textAlign: 'center',
|
||
textBaseline: 'bottom'
|
||
};
|
||
if (position === 'bottom') return {
|
||
textAlign: 'center',
|
||
textBaseline: 'top'
|
||
};
|
||
}
|
||
|
||
function getNameConfig(axisItem) {
|
||
var animationCurve = axisItem.animationCurve,
|
||
animationFrame = axisItem.animationFrame,
|
||
rLevel = axisItem.rLevel;
|
||
return [{
|
||
name: 'text',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getNameShape(axisItem),
|
||
style: getNameStyle(axisItem)
|
||
}];
|
||
}
|
||
|
||
function getNameShape(axisItem) {
|
||
var name = axisItem.name,
|
||
namePosition = axisItem.namePosition;
|
||
return {
|
||
content: name,
|
||
position: namePosition
|
||
};
|
||
}
|
||
|
||
function getNameStyle(axisItem) {
|
||
var nameLocation = axisItem.nameLocation,
|
||
position = axisItem.position,
|
||
style = axisItem.nameTextStyle;
|
||
var align = getNameRealAlign(position, nameLocation);
|
||
return (0, _util.deepMerge)(align, style);
|
||
}
|
||
|
||
function getNameRealAlign(position, location) {
|
||
if (position === 'top' && location === 'start' || position === 'bottom' && location === 'start' || position === 'left' && location === 'center') return {
|
||
textAlign: 'right',
|
||
textBaseline: 'middle'
|
||
};
|
||
if (position === 'top' && location === 'end' || position === 'bottom' && location === 'end' || position === 'right' && location === 'center') return {
|
||
textAlign: 'left',
|
||
textBaseline: 'middle'
|
||
};
|
||
if (position === 'top' && location === 'center' || position === 'left' && location === 'end' || position === 'right' && location === 'end') return {
|
||
textAlign: 'center',
|
||
textBaseline: 'bottom'
|
||
};
|
||
if (position === 'bottom' && location === 'center' || position === 'left' && location === 'start' || position === 'right' && location === 'start') return {
|
||
textAlign: 'center',
|
||
textBaseline: 'top'
|
||
};
|
||
}
|
||
|
||
function getSplitLineConfig(axisItem) {
|
||
var animationCurve = axisItem.animationCurve,
|
||
animationFrame = axisItem.animationFrame,
|
||
rLevel = axisItem.rLevel;
|
||
var shapes = getSplitLineShapes(axisItem);
|
||
var style = getSplitLineStyle(axisItem);
|
||
return shapes.map(function (shape) {
|
||
return {
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: axisItem.splitLine.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getSplitLineShapes(axisItem) {
|
||
var splitLinePosition = axisItem.splitLinePosition;
|
||
return splitLinePosition.map(function (points) {
|
||
return {
|
||
points: points
|
||
};
|
||
});
|
||
}
|
||
|
||
function getSplitLineStyle(axisItem) {
|
||
return axisItem.splitLine.style;
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54}],17:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.bar = bar;
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function bar(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var xAxis = option.xAxis,
|
||
yAxis = option.yAxis,
|
||
series = option.series;
|
||
var bars = [];
|
||
|
||
if (xAxis && yAxis && series) {
|
||
bars = (0, _util2.initNeedSeries)(series, _config.barConfig, 'bar');
|
||
bars = setBarAxis(bars, chart);
|
||
bars = setBarPositionData(bars, chart);
|
||
bars = calcBarsPosition(bars, chart);
|
||
}
|
||
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: bars.slice(-1),
|
||
key: 'backgroundBar',
|
||
getGraphConfig: getBackgroundBarConfig
|
||
});
|
||
bars.reverse();
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: bars,
|
||
key: 'bar',
|
||
getGraphConfig: getBarConfig,
|
||
getStartGraphConfig: getStartBarConfig,
|
||
beforeUpdate: beforeUpdateBar
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: bars,
|
||
key: 'barLabel',
|
||
getGraphConfig: getLabelConfig
|
||
});
|
||
}
|
||
|
||
function setBarAxis(bars, chart) {
|
||
var axisData = chart.axisData;
|
||
bars.forEach(function (bar) {
|
||
var xAxisIndex = bar.xAxisIndex,
|
||
yAxisIndex = bar.yAxisIndex;
|
||
if (typeof xAxisIndex !== 'number') xAxisIndex = 0;
|
||
if (typeof yAxisIndex !== 'number') yAxisIndex = 0;
|
||
var xAxis = axisData.find(function (_ref) {
|
||
var axis = _ref.axis,
|
||
index = _ref.index;
|
||
return "".concat(axis).concat(index) === "x".concat(xAxisIndex);
|
||
});
|
||
var yAxis = axisData.find(function (_ref2) {
|
||
var axis = _ref2.axis,
|
||
index = _ref2.index;
|
||
return "".concat(axis).concat(index) === "y".concat(yAxisIndex);
|
||
});
|
||
var axis = [xAxis, yAxis];
|
||
var valueAxisIndex = axis.findIndex(function (_ref3) {
|
||
var data = _ref3.data;
|
||
return data === 'value';
|
||
});
|
||
bar.valueAxis = axis[valueAxisIndex];
|
||
bar.labelAxis = axis[1 - valueAxisIndex];
|
||
});
|
||
return bars;
|
||
}
|
||
|
||
function setBarPositionData(bars, chart) {
|
||
var labelBarGroup = groupBarByLabelAxis(bars);
|
||
labelBarGroup.forEach(function (group) {
|
||
setBarIndex(group);
|
||
setBarNum(group);
|
||
setBarCategoryWidth(group, chart);
|
||
setBarWidthAndGap(group);
|
||
setBarAllWidthAndGap(group);
|
||
});
|
||
return bars;
|
||
}
|
||
|
||
function setBarIndex(bars) {
|
||
var stacks = getBarStack(bars);
|
||
stacks = stacks.map(function (stack) {
|
||
return {
|
||
stack: stack,
|
||
index: -1
|
||
};
|
||
});
|
||
var currentIndex = 0;
|
||
bars.forEach(function (bar) {
|
||
var stack = bar.stack;
|
||
|
||
if (!stack) {
|
||
bar.barIndex = currentIndex;
|
||
currentIndex++;
|
||
} else {
|
||
var stackData = stacks.find(function (_ref4) {
|
||
var s = _ref4.stack;
|
||
return s === stack;
|
||
});
|
||
|
||
if (stackData.index === -1) {
|
||
stackData.index = currentIndex;
|
||
currentIndex++;
|
||
}
|
||
|
||
bar.barIndex = stackData.index;
|
||
}
|
||
});
|
||
}
|
||
|
||
function groupBarByLabelAxis(bars) {
|
||
var labelAxis = bars.map(function (_ref5) {
|
||
var _ref5$labelAxis = _ref5.labelAxis,
|
||
axis = _ref5$labelAxis.axis,
|
||
index = _ref5$labelAxis.index;
|
||
return axis + index;
|
||
});
|
||
labelAxis = (0, _toConsumableArray2["default"])(new Set(labelAxis));
|
||
return labelAxis.map(function (axisIndex) {
|
||
return bars.filter(function (_ref6) {
|
||
var _ref6$labelAxis = _ref6.labelAxis,
|
||
axis = _ref6$labelAxis.axis,
|
||
index = _ref6$labelAxis.index;
|
||
return axis + index === axisIndex;
|
||
});
|
||
});
|
||
}
|
||
|
||
function getBarStack(bars) {
|
||
var stacks = [];
|
||
bars.forEach(function (_ref7) {
|
||
var stack = _ref7.stack;
|
||
if (stack) stacks.push(stack);
|
||
});
|
||
return (0, _toConsumableArray2["default"])(new Set(stacks));
|
||
}
|
||
|
||
function setBarNum(bars) {
|
||
var barNum = (0, _toConsumableArray2["default"])(new Set(bars.map(function (_ref8) {
|
||
var barIndex = _ref8.barIndex;
|
||
return barIndex;
|
||
}))).length;
|
||
bars.forEach(function (bar) {
|
||
return bar.barNum = barNum;
|
||
});
|
||
}
|
||
|
||
function setBarCategoryWidth(bars) {
|
||
var lastBar = bars.slice(-1)[0];
|
||
var barCategoryGap = lastBar.barCategoryGap,
|
||
tickGap = lastBar.labelAxis.tickGap;
|
||
var barCategoryWidth = 0;
|
||
|
||
if (typeof barCategoryGap === 'number') {
|
||
barCategoryWidth = barCategoryGap;
|
||
} else {
|
||
barCategoryWidth = (1 - parseInt(barCategoryGap) / 100) * tickGap;
|
||
}
|
||
|
||
bars.forEach(function (bar) {
|
||
return bar.barCategoryWidth = barCategoryWidth;
|
||
});
|
||
}
|
||
|
||
function setBarWidthAndGap(bars) {
|
||
var _bars$slice$ = bars.slice(-1)[0],
|
||
barCategoryWidth = _bars$slice$.barCategoryWidth,
|
||
barWidth = _bars$slice$.barWidth,
|
||
barGap = _bars$slice$.barGap,
|
||
barNum = _bars$slice$.barNum;
|
||
var widthAndGap = [];
|
||
|
||
if (typeof barWidth === 'number' || barWidth !== 'auto') {
|
||
widthAndGap = getBarWidthAndGapWithPercentOrNumber(barCategoryWidth, barWidth, barGap, barNum);
|
||
} else if (barWidth === 'auto') {
|
||
widthAndGap = getBarWidthAndGapWidthAuto(barCategoryWidth, barWidth, barGap, barNum);
|
||
}
|
||
|
||
var _widthAndGap = widthAndGap,
|
||
_widthAndGap2 = (0, _slicedToArray2["default"])(_widthAndGap, 2),
|
||
width = _widthAndGap2[0],
|
||
gap = _widthAndGap2[1];
|
||
|
||
bars.forEach(function (bar) {
|
||
bar.barWidth = width;
|
||
bar.barGap = gap;
|
||
});
|
||
}
|
||
|
||
function getBarWidthAndGapWithPercentOrNumber(barCategoryWidth, barWidth, barGap) {
|
||
var width = 0,
|
||
gap = 0;
|
||
|
||
if (typeof barWidth === 'number') {
|
||
width = barWidth;
|
||
} else {
|
||
width = parseInt(barWidth) / 100 * barCategoryWidth;
|
||
}
|
||
|
||
if (typeof barGap === 'number') {
|
||
gap = barGap;
|
||
} else {
|
||
gap = parseInt(barGap) / 100 * width;
|
||
}
|
||
|
||
return [width, gap];
|
||
}
|
||
|
||
function getBarWidthAndGapWidthAuto(barCategoryWidth, barWidth, barGap, barNum) {
|
||
var width = 0,
|
||
gap = 0;
|
||
var barItemWidth = barCategoryWidth / barNum;
|
||
|
||
if (typeof barGap === 'number') {
|
||
gap = barGap;
|
||
width = barItemWidth - gap;
|
||
} else {
|
||
var percent = 10 + parseInt(barGap) / 10;
|
||
|
||
if (percent === 0) {
|
||
width = barItemWidth * 2;
|
||
gap = -width;
|
||
} else {
|
||
width = barItemWidth / percent * 10;
|
||
gap = barItemWidth - width;
|
||
}
|
||
}
|
||
|
||
return [width, gap];
|
||
}
|
||
|
||
function setBarAllWidthAndGap(bars) {
|
||
var _bars$slice$2 = bars.slice(-1)[0],
|
||
barGap = _bars$slice$2.barGap,
|
||
barWidth = _bars$slice$2.barWidth,
|
||
barNum = _bars$slice$2.barNum;
|
||
var barAllWidthAndGap = (barGap + barWidth) * barNum - barGap;
|
||
bars.forEach(function (bar) {
|
||
return bar.barAllWidthAndGap = barAllWidthAndGap;
|
||
});
|
||
}
|
||
|
||
function calcBarsPosition(bars, chart) {
|
||
bars = calcBarValueAxisCoordinate(bars);
|
||
bars = calcBarLabelAxisCoordinate(bars);
|
||
bars = eliminateNullBarLabelAxis(bars);
|
||
bars = keepSameNumBetweenBarAndData(bars);
|
||
return bars;
|
||
}
|
||
|
||
function calcBarLabelAxisCoordinate(bars) {
|
||
return bars.map(function (bar) {
|
||
var labelAxis = bar.labelAxis,
|
||
barAllWidthAndGap = bar.barAllWidthAndGap,
|
||
barGap = bar.barGap,
|
||
barWidth = bar.barWidth,
|
||
barIndex = bar.barIndex;
|
||
var tickGap = labelAxis.tickGap,
|
||
tickPosition = labelAxis.tickPosition,
|
||
axis = labelAxis.axis;
|
||
var coordinateIndex = axis === 'x' ? 0 : 1;
|
||
var barLabelAxisPos = tickPosition.map(function (tick, i) {
|
||
var barCategoryStartPos = tickPosition[i][coordinateIndex] - tickGap / 2;
|
||
var barItemsStartPos = barCategoryStartPos + (tickGap - barAllWidthAndGap) / 2;
|
||
return barItemsStartPos + (barIndex + 0.5) * barWidth + barIndex * barGap;
|
||
});
|
||
return _objectSpread({}, bar, {
|
||
barLabelAxisPos: barLabelAxisPos
|
||
});
|
||
});
|
||
}
|
||
|
||
function calcBarValueAxisCoordinate(bars) {
|
||
return bars.map(function (bar) {
|
||
var data = (0, _util2.mergeSameStackData)(bar, bars);
|
||
data = eliminateNonNumberData(bar, data);
|
||
var _bar$valueAxis = bar.valueAxis,
|
||
axis = _bar$valueAxis.axis,
|
||
minValue = _bar$valueAxis.minValue,
|
||
maxValue = _bar$valueAxis.maxValue,
|
||
linePosition = _bar$valueAxis.linePosition;
|
||
var startPos = getValuePos(minValue, maxValue, minValue < 0 ? 0 : minValue, linePosition, axis);
|
||
var endPos = data.map(function (v) {
|
||
return getValuePos(minValue, maxValue, v, linePosition, axis);
|
||
});
|
||
var barValueAxisPos = endPos.map(function (p) {
|
||
return [startPos, p];
|
||
});
|
||
return _objectSpread({}, bar, {
|
||
barValueAxisPos: barValueAxisPos
|
||
});
|
||
});
|
||
}
|
||
|
||
function eliminateNonNumberData(barItem, barData) {
|
||
var data = barItem.data;
|
||
return barData.map(function (v, i) {
|
||
return typeof data[i] === 'number' ? v : null;
|
||
}).filter(function (d) {
|
||
return d !== null;
|
||
});
|
||
}
|
||
|
||
function eliminateNullBarLabelAxis(bars) {
|
||
return bars.map(function (bar) {
|
||
var barLabelAxisPos = bar.barLabelAxisPos,
|
||
data = bar.data;
|
||
data.forEach(function (d, i) {
|
||
if (typeof d === 'number') return;
|
||
barLabelAxisPos[i] = null;
|
||
});
|
||
return _objectSpread({}, bar, {
|
||
barLabelAxisPos: barLabelAxisPos.filter(function (p) {
|
||
return p !== null;
|
||
})
|
||
});
|
||
});
|
||
}
|
||
|
||
function keepSameNumBetweenBarAndData(bars) {
|
||
bars.forEach(function (bar) {
|
||
var data = bar.data,
|
||
barLabelAxisPos = bar.barLabelAxisPos,
|
||
barValueAxisPos = bar.barValueAxisPos;
|
||
var dataNum = data.filter(function (d) {
|
||
return typeof d === 'number';
|
||
}).length;
|
||
var axisPosNum = barLabelAxisPos.length;
|
||
|
||
if (axisPosNum > dataNum) {
|
||
barLabelAxisPos.splice(dataNum);
|
||
barValueAxisPos.splice(dataNum);
|
||
}
|
||
});
|
||
return bars;
|
||
}
|
||
|
||
function getValuePos(min, max, value, linePosition, axis) {
|
||
if (typeof value !== 'number') return null;
|
||
var valueMinus = max - min;
|
||
var coordinateIndex = axis === 'x' ? 0 : 1;
|
||
var posMinus = linePosition[1][coordinateIndex] - linePosition[0][coordinateIndex];
|
||
var percent = (value - min) / valueMinus;
|
||
if (valueMinus === 0) percent = 0;
|
||
var pos = percent * posMinus;
|
||
return pos + linePosition[0][coordinateIndex];
|
||
}
|
||
|
||
function getBackgroundBarConfig(barItem) {
|
||
var animationCurve = barItem.animationCurve,
|
||
animationFrame = barItem.animationFrame,
|
||
rLevel = barItem.rLevel;
|
||
var shapes = getBackgroundBarShapes(barItem);
|
||
var style = getBackgroundBarStyle(barItem);
|
||
return shapes.map(function (shape) {
|
||
return {
|
||
name: 'rect',
|
||
index: rLevel,
|
||
visible: barItem.backgroundBar.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getBackgroundBarShapes(barItem) {
|
||
var labelAxis = barItem.labelAxis,
|
||
valueAxis = barItem.valueAxis;
|
||
var tickPosition = labelAxis.tickPosition;
|
||
var axis = valueAxis.axis,
|
||
linePosition = valueAxis.linePosition;
|
||
var width = getBackgroundBarWidth(barItem);
|
||
var haltWidth = width / 2;
|
||
var posIndex = axis === 'x' ? 0 : 1;
|
||
var centerPos = tickPosition.map(function (p) {
|
||
return p[1 - posIndex];
|
||
});
|
||
var _ref9 = [linePosition[0][posIndex], linePosition[1][posIndex]],
|
||
start = _ref9[0],
|
||
end = _ref9[1];
|
||
return centerPos.map(function (center) {
|
||
if (axis === 'x') {
|
||
return {
|
||
x: start,
|
||
y: center - haltWidth,
|
||
w: end - start,
|
||
h: width
|
||
};
|
||
} else {
|
||
return {
|
||
x: center - haltWidth,
|
||
y: end,
|
||
w: width,
|
||
h: start - end
|
||
};
|
||
}
|
||
});
|
||
}
|
||
|
||
function getBackgroundBarWidth(barItem) {
|
||
var barAllWidthAndGap = barItem.barAllWidthAndGap,
|
||
barCategoryWidth = barItem.barCategoryWidth,
|
||
backgroundBar = barItem.backgroundBar;
|
||
var width = backgroundBar.width;
|
||
if (typeof width === 'number') return width;
|
||
if (width === 'auto') return barAllWidthAndGap;
|
||
return parseInt(width) / 100 * barCategoryWidth;
|
||
}
|
||
|
||
function getBackgroundBarStyle(barItem) {
|
||
return barItem.backgroundBar.style;
|
||
}
|
||
|
||
function getBarConfig(barItem) {
|
||
var barLabelAxisPos = barItem.barLabelAxisPos,
|
||
animationCurve = barItem.animationCurve,
|
||
animationFrame = barItem.animationFrame,
|
||
rLevel = barItem.rLevel;
|
||
var name = getBarName(barItem);
|
||
return barLabelAxisPos.map(function (foo, i) {
|
||
return {
|
||
name: name,
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getBarShape(barItem, i),
|
||
style: getBarStyle(barItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getBarName(barItem) {
|
||
var shapeType = barItem.shapeType;
|
||
if (shapeType === 'leftEchelon' || shapeType === 'rightEchelon') return 'polyline';
|
||
return 'rect';
|
||
}
|
||
|
||
function getBarShape(barItem, i) {
|
||
var shapeType = barItem.shapeType;
|
||
|
||
if (shapeType === 'leftEchelon') {
|
||
return getLeftEchelonShape(barItem, i);
|
||
} else if (shapeType === 'rightEchelon') {
|
||
return getRightEchelonShape(barItem, i);
|
||
} else {
|
||
return getNormalBarShape(barItem, i);
|
||
}
|
||
}
|
||
|
||
function getLeftEchelonShape(barItem, i) {
|
||
var barValueAxisPos = barItem.barValueAxisPos,
|
||
barLabelAxisPos = barItem.barLabelAxisPos,
|
||
barWidth = barItem.barWidth,
|
||
echelonOffset = barItem.echelonOffset;
|
||
|
||
var _barValueAxisPos$i = (0, _slicedToArray2["default"])(barValueAxisPos[i], 2),
|
||
start = _barValueAxisPos$i[0],
|
||
end = _barValueAxisPos$i[1];
|
||
|
||
var labelAxisPos = barLabelAxisPos[i];
|
||
var halfWidth = barWidth / 2;
|
||
var valueAxis = barItem.valueAxis.axis;
|
||
var points = [];
|
||
|
||
if (valueAxis === 'x') {
|
||
points[0] = [end, labelAxisPos - halfWidth];
|
||
points[1] = [end, labelAxisPos + halfWidth];
|
||
points[2] = [start, labelAxisPos + halfWidth];
|
||
points[3] = [start + echelonOffset, labelAxisPos - halfWidth];
|
||
if (end - start < echelonOffset) points.splice(3, 1);
|
||
} else {
|
||
points[0] = [labelAxisPos - halfWidth, end];
|
||
points[1] = [labelAxisPos + halfWidth, end];
|
||
points[2] = [labelAxisPos + halfWidth, start];
|
||
points[3] = [labelAxisPos - halfWidth, start - echelonOffset];
|
||
if (start - end < echelonOffset) points.splice(3, 1);
|
||
}
|
||
|
||
return {
|
||
points: points,
|
||
close: true
|
||
};
|
||
}
|
||
|
||
function getRightEchelonShape(barItem, i) {
|
||
var barValueAxisPos = barItem.barValueAxisPos,
|
||
barLabelAxisPos = barItem.barLabelAxisPos,
|
||
barWidth = barItem.barWidth,
|
||
echelonOffset = barItem.echelonOffset;
|
||
|
||
var _barValueAxisPos$i2 = (0, _slicedToArray2["default"])(barValueAxisPos[i], 2),
|
||
start = _barValueAxisPos$i2[0],
|
||
end = _barValueAxisPos$i2[1];
|
||
|
||
var labelAxisPos = barLabelAxisPos[i];
|
||
var halfWidth = barWidth / 2;
|
||
var valueAxis = barItem.valueAxis.axis;
|
||
var points = [];
|
||
|
||
if (valueAxis === 'x') {
|
||
points[0] = [end, labelAxisPos + halfWidth];
|
||
points[1] = [end, labelAxisPos - halfWidth];
|
||
points[2] = [start, labelAxisPos - halfWidth];
|
||
points[3] = [start + echelonOffset, labelAxisPos + halfWidth];
|
||
if (end - start < echelonOffset) points.splice(2, 1);
|
||
} else {
|
||
points[0] = [labelAxisPos + halfWidth, end];
|
||
points[1] = [labelAxisPos - halfWidth, end];
|
||
points[2] = [labelAxisPos - halfWidth, start];
|
||
points[3] = [labelAxisPos + halfWidth, start - echelonOffset];
|
||
if (start - end < echelonOffset) points.splice(2, 1);
|
||
}
|
||
|
||
return {
|
||
points: points,
|
||
close: true
|
||
};
|
||
}
|
||
|
||
function getNormalBarShape(barItem, i) {
|
||
var barValueAxisPos = barItem.barValueAxisPos,
|
||
barLabelAxisPos = barItem.barLabelAxisPos,
|
||
barWidth = barItem.barWidth;
|
||
|
||
var _barValueAxisPos$i3 = (0, _slicedToArray2["default"])(barValueAxisPos[i], 2),
|
||
start = _barValueAxisPos$i3[0],
|
||
end = _barValueAxisPos$i3[1];
|
||
|
||
var labelAxisPos = barLabelAxisPos[i];
|
||
var valueAxis = barItem.valueAxis.axis;
|
||
var shape = {};
|
||
|
||
if (valueAxis === 'x') {
|
||
shape.x = start;
|
||
shape.y = labelAxisPos - barWidth / 2;
|
||
shape.w = end - start;
|
||
shape.h = barWidth;
|
||
} else {
|
||
shape.x = labelAxisPos - barWidth / 2;
|
||
shape.y = end;
|
||
shape.w = barWidth;
|
||
shape.h = start - end;
|
||
}
|
||
|
||
return shape;
|
||
}
|
||
|
||
function getBarStyle(barItem, i) {
|
||
var barStyle = barItem.barStyle,
|
||
gradient = barItem.gradient,
|
||
color = barItem.color,
|
||
independentColor = barItem.independentColor,
|
||
independentColors = barItem.independentColors;
|
||
var fillColor = [barStyle.fill || color];
|
||
var gradientColor = (0, _util2.deepMerge)(fillColor, gradient.color);
|
||
|
||
if (independentColor) {
|
||
var idtColor = independentColors[i % independentColors.length];
|
||
gradientColor = idtColor instanceof Array ? idtColor : [idtColor];
|
||
}
|
||
|
||
if (gradientColor.length === 1) gradientColor.push(gradientColor[0]);
|
||
var gradientParams = getGradientParams(barItem, i);
|
||
return (0, _util2.deepMerge)({
|
||
gradientColor: gradientColor,
|
||
gradientParams: gradientParams,
|
||
gradientType: 'linear',
|
||
gradientWith: 'fill'
|
||
}, barStyle);
|
||
}
|
||
|
||
function getGradientParams(barItem, i) {
|
||
var barValueAxisPos = barItem.barValueAxisPos,
|
||
barLabelAxisPos = barItem.barLabelAxisPos,
|
||
data = barItem.data;
|
||
var _barItem$valueAxis = barItem.valueAxis,
|
||
linePosition = _barItem$valueAxis.linePosition,
|
||
axis = _barItem$valueAxis.axis;
|
||
|
||
var _barValueAxisPos$i4 = (0, _slicedToArray2["default"])(barValueAxisPos[i], 2),
|
||
start = _barValueAxisPos$i4[0],
|
||
end = _barValueAxisPos$i4[1];
|
||
|
||
var labelAxisPos = barLabelAxisPos[i];
|
||
var value = data[i];
|
||
|
||
var _linePosition = (0, _slicedToArray2["default"])(linePosition, 2),
|
||
lineStart = _linePosition[0],
|
||
lineEnd = _linePosition[1];
|
||
|
||
var valueAxisIndex = axis === 'x' ? 0 : 1;
|
||
var endPos = end;
|
||
|
||
if (!barItem.gradient.local) {
|
||
endPos = value < 0 ? lineStart[valueAxisIndex] : lineEnd[valueAxisIndex];
|
||
}
|
||
|
||
if (axis === 'y') {
|
||
return [labelAxisPos, endPos, labelAxisPos, start];
|
||
} else {
|
||
return [endPos, labelAxisPos, start, labelAxisPos];
|
||
}
|
||
}
|
||
|
||
function getStartBarConfig(barItem) {
|
||
var configs = getBarConfig(barItem);
|
||
var shapeType = barItem.shapeType;
|
||
configs.forEach(function (config) {
|
||
var shape = config.shape;
|
||
|
||
if (shapeType === 'leftEchelon') {
|
||
shape = getStartLeftEchelonShape(shape, barItem);
|
||
} else if (shapeType === 'rightEchelon') {
|
||
shape = getStartRightEchelonShape(shape, barItem);
|
||
} else {
|
||
shape = getStartNormalBarShape(shape, barItem);
|
||
}
|
||
|
||
config.shape = shape;
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function getStartLeftEchelonShape(shape, barItem) {
|
||
var axis = barItem.valueAxis.axis;
|
||
shape = (0, _util.deepClone)(shape);
|
||
var _shape = shape,
|
||
points = _shape.points;
|
||
var index = axis === 'x' ? 0 : 1;
|
||
var start = points[2][index];
|
||
points.forEach(function (point) {
|
||
return point[index] = start;
|
||
});
|
||
return shape;
|
||
}
|
||
|
||
function getStartRightEchelonShape(shape, barItem) {
|
||
var axis = barItem.valueAxis.axis;
|
||
shape = (0, _util.deepClone)(shape);
|
||
var _shape2 = shape,
|
||
points = _shape2.points;
|
||
var index = axis === 'x' ? 0 : 1;
|
||
var start = points[2][index];
|
||
points.forEach(function (point) {
|
||
return point[index] = start;
|
||
});
|
||
return shape;
|
||
}
|
||
|
||
function getStartNormalBarShape(shape, barItem) {
|
||
var axis = barItem.valueAxis.axis;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
|
||
if (axis === 'x') {
|
||
w = 0;
|
||
} else {
|
||
y = y + h;
|
||
h = 0;
|
||
}
|
||
|
||
return {
|
||
x: x,
|
||
y: y,
|
||
w: w,
|
||
h: h
|
||
};
|
||
}
|
||
|
||
function beforeUpdateBar(graphs, barItem, i, updater) {
|
||
var render = updater.chart.render;
|
||
var name = getBarName(barItem);
|
||
|
||
if (graphs[i] && graphs[i][0].name !== name) {
|
||
graphs[i].forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
graphs[i] = null;
|
||
}
|
||
}
|
||
|
||
function getLabelConfig(barItem) {
|
||
var animationCurve = barItem.animationCurve,
|
||
animationFrame = barItem.animationFrame,
|
||
rLevel = barItem.rLevel;
|
||
var shapes = getLabelShapes(barItem);
|
||
var style = getLabelStyle(barItem);
|
||
return shapes.map(function (shape) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: barItem.label.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelShapes(barItem) {
|
||
var contents = getFormatterLabels(barItem);
|
||
var position = getLabelsPosition(barItem);
|
||
return position.map(function (pos, i) {
|
||
return {
|
||
position: pos,
|
||
content: contents[i]
|
||
};
|
||
});
|
||
}
|
||
|
||
function getFormatterLabels(barItem) {
|
||
var data = barItem.data,
|
||
label = barItem.label;
|
||
var formatter = label.formatter;
|
||
data = data.filter(function (d) {
|
||
return typeof d === 'number';
|
||
}).map(function (d) {
|
||
return d.toString();
|
||
});
|
||
if (!formatter) return data;
|
||
var type = (0, _typeof2["default"])(formatter);
|
||
if (type === 'string') return data.map(function (d) {
|
||
return formatter.replace('{value}', d);
|
||
});
|
||
if (type === 'function') return data.map(function (d, i) {
|
||
return formatter({
|
||
value: d,
|
||
index: i
|
||
});
|
||
});
|
||
return data;
|
||
}
|
||
|
||
function getLabelsPosition(barItem) {
|
||
var label = barItem.label,
|
||
barValueAxisPos = barItem.barValueAxisPos,
|
||
barLabelAxisPos = barItem.barLabelAxisPos;
|
||
var position = label.position,
|
||
offset = label.offset;
|
||
var axis = barItem.valueAxis.axis;
|
||
return barValueAxisPos.map(function (_ref10, i) {
|
||
var _ref11 = (0, _slicedToArray2["default"])(_ref10, 2),
|
||
start = _ref11[0],
|
||
end = _ref11[1];
|
||
|
||
var labelAxisPos = barLabelAxisPos[i];
|
||
var pos = [end, labelAxisPos];
|
||
|
||
if (position === 'bottom') {
|
||
pos = [start, labelAxisPos];
|
||
}
|
||
|
||
if (position === 'center') {
|
||
pos = [(start + end) / 2, labelAxisPos];
|
||
}
|
||
|
||
if (axis === 'y') pos.reverse();
|
||
return getOffsetedPoint(pos, offset);
|
||
});
|
||
}
|
||
|
||
function getOffsetedPoint(_ref12, _ref13) {
|
||
var _ref14 = (0, _slicedToArray2["default"])(_ref12, 2),
|
||
x = _ref14[0],
|
||
y = _ref14[1];
|
||
|
||
var _ref15 = (0, _slicedToArray2["default"])(_ref13, 2),
|
||
ox = _ref15[0],
|
||
oy = _ref15[1];
|
||
|
||
return [x + ox, y + oy];
|
||
}
|
||
|
||
function getLabelStyle(barItem) {
|
||
var color = barItem.color,
|
||
style = barItem.label.style,
|
||
gc = barItem.gradient.color;
|
||
if (gc.length) color = gc[0];
|
||
style = (0, _util2.deepMerge)({
|
||
fill: color
|
||
}, style);
|
||
return style;
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54}],18:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.gauge = gauge;
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _gauge = require("../config/gauge");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
var _color = require("@jiaminghi/color");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function gauge(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var series = option.series;
|
||
if (!series) series = [];
|
||
var gauges = (0, _util2.initNeedSeries)(series, _gauge.gaugeConfig, 'gauge');
|
||
gauges = calcGaugesCenter(gauges, chart);
|
||
gauges = calcGaugesRadius(gauges, chart);
|
||
gauges = calcGaugesDataRadiusAndLineWidth(gauges, chart);
|
||
gauges = calcGaugesDataAngles(gauges, chart);
|
||
gauges = calcGaugesDataGradient(gauges, chart);
|
||
gauges = calcGaugesAxisTickPosition(gauges, chart);
|
||
gauges = calcGaugesLabelPositionAndAlign(gauges, chart);
|
||
gauges = calcGaugesLabelData(gauges, chart);
|
||
gauges = calcGaugesDetailsPosition(gauges, chart);
|
||
gauges = calcGaugesDetailsContent(gauges, chart);
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugeAxisTick',
|
||
getGraphConfig: getAxisTickConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugeAxisLabel',
|
||
getGraphConfig: getAxisLabelConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugeBackgroundArc',
|
||
getGraphConfig: getBackgroundArcConfig,
|
||
getStartGraphConfig: getStartBackgroundArcConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugeArc',
|
||
getGraphConfig: getArcConfig,
|
||
getStartGraphConfig: getStartArcConfig,
|
||
beforeChange: beforeChangeArc
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugePointer',
|
||
getGraphConfig: getPointerConfig,
|
||
getStartGraphConfig: getStartPointerConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: gauges,
|
||
key: 'gaugeDetails',
|
||
getGraphConfig: getDetailsConfig
|
||
});
|
||
}
|
||
|
||
function calcGaugesCenter(gauges, chart) {
|
||
var area = chart.render.area;
|
||
gauges.forEach(function (gaugeItem) {
|
||
var center = gaugeItem.center;
|
||
center = center.map(function (pos, i) {
|
||
if (typeof pos === 'number') return pos;
|
||
return parseInt(pos) / 100 * area[i];
|
||
});
|
||
gaugeItem.center = center;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesRadius(gauges, chart) {
|
||
var area = chart.render.area;
|
||
var maxRadius = Math.min.apply(Math, (0, _toConsumableArray2["default"])(area)) / 2;
|
||
gauges.forEach(function (gaugeItem) {
|
||
var radius = gaugeItem.radius;
|
||
|
||
if (typeof radius !== 'number') {
|
||
radius = parseInt(radius) / 100 * maxRadius;
|
||
}
|
||
|
||
gaugeItem.radius = radius;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesDataRadiusAndLineWidth(gauges, chart) {
|
||
var area = chart.render.area;
|
||
var maxRadius = Math.min.apply(Math, (0, _toConsumableArray2["default"])(area)) / 2;
|
||
gauges.forEach(function (gaugeItem) {
|
||
var radius = gaugeItem.radius,
|
||
data = gaugeItem.data,
|
||
arcLineWidth = gaugeItem.arcLineWidth;
|
||
data.forEach(function (item) {
|
||
var arcRadius = item.radius,
|
||
lineWidth = item.lineWidth;
|
||
if (!arcRadius) arcRadius = radius;
|
||
if (typeof arcRadius !== 'number') arcRadius = parseInt(arcRadius) / 100 * maxRadius;
|
||
item.radius = arcRadius;
|
||
if (!lineWidth) lineWidth = arcLineWidth;
|
||
item.lineWidth = lineWidth;
|
||
});
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesDataAngles(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var startAngle = gaugeItem.startAngle,
|
||
endAngle = gaugeItem.endAngle,
|
||
data = gaugeItem.data,
|
||
min = gaugeItem.min,
|
||
max = gaugeItem.max;
|
||
var angleMinus = endAngle - startAngle;
|
||
var valueMinus = max - min;
|
||
data.forEach(function (item) {
|
||
var value = item.value;
|
||
var itemAngle = Math.abs((value - min) / valueMinus * angleMinus);
|
||
item.startAngle = startAngle;
|
||
item.endAngle = startAngle + itemAngle;
|
||
});
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesDataGradient(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var data = gaugeItem.data;
|
||
data.forEach(function (item) {
|
||
var color = item.color,
|
||
gradient = item.gradient;
|
||
if (!gradient || !gradient.length) gradient = color;
|
||
if (!(gradient instanceof Array)) gradient = [gradient];
|
||
item.gradient = gradient;
|
||
});
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesAxisTickPosition(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var startAngle = gaugeItem.startAngle,
|
||
endAngle = gaugeItem.endAngle,
|
||
splitNum = gaugeItem.splitNum,
|
||
center = gaugeItem.center,
|
||
radius = gaugeItem.radius,
|
||
arcLineWidth = gaugeItem.arcLineWidth,
|
||
axisTick = gaugeItem.axisTick;
|
||
var tickLength = axisTick.tickLength,
|
||
lineWidth = axisTick.style.lineWidth;
|
||
var angles = endAngle - startAngle;
|
||
var outerRadius = radius - arcLineWidth / 2;
|
||
var innerRadius = outerRadius - tickLength;
|
||
var angleGap = angles / (splitNum - 1);
|
||
var arcLength = 2 * Math.PI * radius * angles / (Math.PI * 2);
|
||
var offset = Math.ceil(lineWidth / 2) / arcLength * angles;
|
||
gaugeItem.tickAngles = [];
|
||
gaugeItem.tickInnerRadius = [];
|
||
gaugeItem.tickPosition = new Array(splitNum).fill(0).map(function (foo, i) {
|
||
var angle = startAngle + angleGap * i;
|
||
if (i === 0) angle += offset;
|
||
if (i === splitNum - 1) angle -= offset;
|
||
gaugeItem.tickAngles[i] = angle;
|
||
gaugeItem.tickInnerRadius[i] = innerRadius;
|
||
return [_util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([outerRadius, angle])), _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([innerRadius, angle]))];
|
||
});
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesLabelPositionAndAlign(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var center = gaugeItem.center,
|
||
tickInnerRadius = gaugeItem.tickInnerRadius,
|
||
tickAngles = gaugeItem.tickAngles,
|
||
labelGap = gaugeItem.axisLabel.labelGap;
|
||
var position = tickAngles.map(function (angle, i) {
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([tickInnerRadius[i] - labelGap, tickAngles[i]]));
|
||
});
|
||
var align = position.map(function (_ref) {
|
||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
|
||
x = _ref2[0],
|
||
y = _ref2[1];
|
||
|
||
return {
|
||
textAlign: x > center[0] ? 'right' : 'left',
|
||
textBaseline: y > center[1] ? 'bottom' : 'top'
|
||
};
|
||
});
|
||
gaugeItem.labelPosition = position;
|
||
gaugeItem.labelAlign = align;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesLabelData(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var axisLabel = gaugeItem.axisLabel,
|
||
min = gaugeItem.min,
|
||
max = gaugeItem.max,
|
||
splitNum = gaugeItem.splitNum;
|
||
var data = axisLabel.data,
|
||
formatter = axisLabel.formatter;
|
||
var valueGap = (max - min) / (splitNum - 1);
|
||
var value = new Array(splitNum).fill(0).map(function (foo, i) {
|
||
return parseInt(min + valueGap * i);
|
||
});
|
||
var formatterType = (0, _typeof2["default"])(formatter);
|
||
data = (0, _util2.deepMerge)(value, data).map(function (v, i) {
|
||
var label = v;
|
||
|
||
if (formatterType === 'string') {
|
||
label = formatter.replace('{value}', v);
|
||
}
|
||
|
||
if (formatterType === 'function') {
|
||
label = formatter({
|
||
value: v,
|
||
index: i
|
||
});
|
||
}
|
||
|
||
return label;
|
||
});
|
||
axisLabel.data = data;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesDetailsPosition(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var data = gaugeItem.data,
|
||
details = gaugeItem.details,
|
||
center = gaugeItem.center;
|
||
var position = details.position,
|
||
offset = details.offset;
|
||
var detailsPosition = data.map(function (_ref3) {
|
||
var startAngle = _ref3.startAngle,
|
||
endAngle = _ref3.endAngle,
|
||
radius = _ref3.radius;
|
||
var point = null;
|
||
|
||
if (position === 'center') {
|
||
point = center;
|
||
} else if (position === 'start') {
|
||
point = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([radius, startAngle]));
|
||
} else if (position === 'end') {
|
||
point = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([radius, endAngle]));
|
||
}
|
||
|
||
return getOffsetedPoint(point, offset);
|
||
});
|
||
gaugeItem.detailsPosition = detailsPosition;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function calcGaugesDetailsContent(gauges, chart) {
|
||
gauges.forEach(function (gaugeItem) {
|
||
var data = gaugeItem.data,
|
||
details = gaugeItem.details;
|
||
var formatter = details.formatter;
|
||
var formatterType = (0, _typeof2["default"])(formatter);
|
||
var contents = data.map(function (dataItem) {
|
||
var content = dataItem.value;
|
||
|
||
if (formatterType === 'string') {
|
||
content = formatter.replace('{value}', '{nt}');
|
||
content = content.replace('{name}', dataItem.name);
|
||
}
|
||
|
||
if (formatterType === 'function') content = formatter(dataItem);
|
||
return content.toString();
|
||
});
|
||
gaugeItem.detailsContent = contents;
|
||
});
|
||
return gauges;
|
||
}
|
||
|
||
function getOffsetedPoint(_ref4, _ref5) {
|
||
var _ref6 = (0, _slicedToArray2["default"])(_ref4, 2),
|
||
x = _ref6[0],
|
||
y = _ref6[1];
|
||
|
||
var _ref7 = (0, _slicedToArray2["default"])(_ref5, 2),
|
||
ox = _ref7[0],
|
||
oy = _ref7[1];
|
||
|
||
return [x + ox, y + oy];
|
||
}
|
||
|
||
function getAxisTickConfig(gaugeItem) {
|
||
var tickPosition = gaugeItem.tickPosition,
|
||
animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
rLevel = gaugeItem.rLevel;
|
||
return tickPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: gaugeItem.axisTick.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getAxisTickShape(gaugeItem, i),
|
||
style: getAxisTickStyle(gaugeItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getAxisTickShape(gaugeItem, i) {
|
||
var tickPosition = gaugeItem.tickPosition;
|
||
return {
|
||
points: tickPosition[i]
|
||
};
|
||
}
|
||
|
||
function getAxisTickStyle(gaugeItem, i) {
|
||
var style = gaugeItem.axisTick.style;
|
||
return style;
|
||
}
|
||
|
||
function getAxisLabelConfig(gaugeItem) {
|
||
var labelPosition = gaugeItem.labelPosition,
|
||
animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
rLevel = gaugeItem.rLevel;
|
||
return labelPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: gaugeItem.axisLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getAxisLabelShape(gaugeItem, i),
|
||
style: getAxisLabelStyle(gaugeItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getAxisLabelShape(gaugeItem, i) {
|
||
var labelPosition = gaugeItem.labelPosition,
|
||
data = gaugeItem.axisLabel.data;
|
||
return {
|
||
content: data[i].toString(),
|
||
position: labelPosition[i]
|
||
};
|
||
}
|
||
|
||
function getAxisLabelStyle(gaugeItem, i) {
|
||
var labelAlign = gaugeItem.labelAlign,
|
||
axisLabel = gaugeItem.axisLabel;
|
||
var style = axisLabel.style;
|
||
return (0, _util2.deepMerge)(_objectSpread({}, labelAlign[i]), style);
|
||
}
|
||
|
||
function getBackgroundArcConfig(gaugeItem) {
|
||
var animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
rLevel = gaugeItem.rLevel;
|
||
return [{
|
||
name: 'arc',
|
||
index: rLevel,
|
||
visible: gaugeItem.backgroundArc.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getGaugeBackgroundArcShape(gaugeItem),
|
||
style: getGaugeBackgroundArcStyle(gaugeItem)
|
||
}];
|
||
}
|
||
|
||
function getGaugeBackgroundArcShape(gaugeItem) {
|
||
var startAngle = gaugeItem.startAngle,
|
||
endAngle = gaugeItem.endAngle,
|
||
center = gaugeItem.center,
|
||
radius = gaugeItem.radius;
|
||
return {
|
||
rx: center[0],
|
||
ry: center[1],
|
||
r: radius,
|
||
startAngle: startAngle,
|
||
endAngle: endAngle
|
||
};
|
||
}
|
||
|
||
function getGaugeBackgroundArcStyle(gaugeItem) {
|
||
var backgroundArc = gaugeItem.backgroundArc,
|
||
arcLineWidth = gaugeItem.arcLineWidth;
|
||
var style = backgroundArc.style;
|
||
return (0, _util2.deepMerge)({
|
||
lineWidth: arcLineWidth
|
||
}, style);
|
||
}
|
||
|
||
function getStartBackgroundArcConfig(gaugeItem) {
|
||
var config = getBackgroundArcConfig(gaugeItem)[0];
|
||
|
||
var shape = _objectSpread({}, config.shape);
|
||
|
||
shape.endAngle = config.shape.startAngle;
|
||
config.shape = shape;
|
||
return [config];
|
||
}
|
||
|
||
function getArcConfig(gaugeItem) {
|
||
var data = gaugeItem.data,
|
||
animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
rLevel = gaugeItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'agArc',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getGaugeArcShape(gaugeItem, i),
|
||
style: getGaugeArcStyle(gaugeItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getGaugeArcShape(gaugeItem, i) {
|
||
var data = gaugeItem.data,
|
||
center = gaugeItem.center,
|
||
gradientEndAngle = gaugeItem.endAngle;
|
||
var _data$i = data[i],
|
||
radius = _data$i.radius,
|
||
startAngle = _data$i.startAngle,
|
||
endAngle = _data$i.endAngle,
|
||
localGradient = _data$i.localGradient;
|
||
if (localGradient) gradientEndAngle = endAngle;
|
||
return {
|
||
rx: center[0],
|
||
ry: center[1],
|
||
r: radius,
|
||
startAngle: startAngle,
|
||
endAngle: endAngle,
|
||
gradientEndAngle: gradientEndAngle
|
||
};
|
||
}
|
||
|
||
function getGaugeArcStyle(gaugeItem, i) {
|
||
var data = gaugeItem.data,
|
||
dataItemStyle = gaugeItem.dataItemStyle;
|
||
var _data$i2 = data[i],
|
||
lineWidth = _data$i2.lineWidth,
|
||
gradient = _data$i2.gradient;
|
||
gradient = gradient.map(function (c) {
|
||
return (0, _color.getRgbaValue)(c);
|
||
});
|
||
return (0, _util2.deepMerge)({
|
||
lineWidth: lineWidth,
|
||
gradient: gradient
|
||
}, dataItemStyle);
|
||
}
|
||
|
||
function getStartArcConfig(gaugeItem) {
|
||
var configs = getArcConfig(gaugeItem);
|
||
configs.map(function (config) {
|
||
var shape = _objectSpread({}, config.shape);
|
||
|
||
shape.endAngle = config.shape.startAngle;
|
||
config.shape = shape;
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function beforeChangeArc(graph, config) {
|
||
var graphGradient = graph.style.gradient;
|
||
var cacheNum = graphGradient.length;
|
||
var needNum = config.style.gradient.length;
|
||
|
||
if (cacheNum > needNum) {
|
||
graphGradient.splice(needNum);
|
||
} else {
|
||
var last = graphGradient.slice(-1)[0];
|
||
graphGradient.push.apply(graphGradient, (0, _toConsumableArray2["default"])(new Array(needNum - cacheNum).fill(0).map(function (foo) {
|
||
return (0, _toConsumableArray2["default"])(last);
|
||
})));
|
||
}
|
||
}
|
||
|
||
function getPointerConfig(gaugeItem) {
|
||
var animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
center = gaugeItem.center,
|
||
rLevel = gaugeItem.rLevel;
|
||
return [{
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: gaugeItem.pointer.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getPointerShape(gaugeItem),
|
||
style: getPointerStyle(gaugeItem),
|
||
setGraphCenter: function setGraphCenter(foo, graph) {
|
||
graph.style.graphCenter = center;
|
||
}
|
||
}];
|
||
}
|
||
|
||
function getPointerShape(gaugeItem) {
|
||
var center = gaugeItem.center;
|
||
return {
|
||
points: getPointerPoints(center),
|
||
close: true
|
||
};
|
||
}
|
||
|
||
function getPointerStyle(gaugeItem) {
|
||
var startAngle = gaugeItem.startAngle,
|
||
endAngle = gaugeItem.endAngle,
|
||
min = gaugeItem.min,
|
||
max = gaugeItem.max,
|
||
data = gaugeItem.data,
|
||
pointer = gaugeItem.pointer,
|
||
center = gaugeItem.center;
|
||
var valueIndex = pointer.valueIndex,
|
||
style = pointer.style;
|
||
var value = data[valueIndex] ? data[valueIndex].value : 0;
|
||
var angle = (value - min) / (max - min) * (endAngle - startAngle) + startAngle + Math.PI / 2;
|
||
return (0, _util2.deepMerge)({
|
||
rotate: (0, _util2.radianToAngle)(angle),
|
||
scale: [1, 1],
|
||
graphCenter: center
|
||
}, style);
|
||
}
|
||
|
||
function getPointerPoints(_ref8) {
|
||
var _ref9 = (0, _slicedToArray2["default"])(_ref8, 2),
|
||
x = _ref9[0],
|
||
y = _ref9[1];
|
||
|
||
var point1 = [x, y - 40];
|
||
var point2 = [x + 5, y];
|
||
var point3 = [x, y + 10];
|
||
var point4 = [x - 5, y];
|
||
return [point1, point2, point3, point4];
|
||
}
|
||
|
||
function getStartPointerConfig(gaugeItem) {
|
||
var startAngle = gaugeItem.startAngle;
|
||
var config = getPointerConfig(gaugeItem)[0];
|
||
config.style.rotate = (0, _util2.radianToAngle)(startAngle + Math.PI / 2);
|
||
return [config];
|
||
}
|
||
|
||
function getDetailsConfig(gaugeItem) {
|
||
var detailsPosition = gaugeItem.detailsPosition,
|
||
animationCurve = gaugeItem.animationCurve,
|
||
animationFrame = gaugeItem.animationFrame,
|
||
rLevel = gaugeItem.rLevel;
|
||
var visible = gaugeItem.details.show;
|
||
return detailsPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'numberText',
|
||
index: rLevel,
|
||
visible: visible,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getDetailsShape(gaugeItem, i),
|
||
style: getDetailsStyle(gaugeItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getDetailsShape(gaugeItem, i) {
|
||
var detailsPosition = gaugeItem.detailsPosition,
|
||
detailsContent = gaugeItem.detailsContent,
|
||
data = gaugeItem.data,
|
||
details = gaugeItem.details;
|
||
var position = detailsPosition[i];
|
||
var content = detailsContent[i];
|
||
var dataValue = data[i].value;
|
||
var toFixed = details.valueToFixed;
|
||
return {
|
||
number: [dataValue],
|
||
content: content,
|
||
position: position,
|
||
toFixed: toFixed
|
||
};
|
||
}
|
||
|
||
function getDetailsStyle(gaugeItem, i) {
|
||
var details = gaugeItem.details,
|
||
data = gaugeItem.data;
|
||
var style = details.style;
|
||
var color = data[i].color;
|
||
return (0, _util2.deepMerge)({
|
||
fill: color
|
||
}, style);
|
||
}
|
||
},{"../class/updater.class":3,"../config/gauge":7,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54,"@jiaminghi/color":56}],19:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.grid = grid;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function grid(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var grid = option.grid;
|
||
grid = (0, _util2.deepMerge)((0, _util.deepClone)(_config.gridConfig, true), grid || {});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: [grid],
|
||
key: 'grid',
|
||
getGraphConfig: getGridConfig
|
||
});
|
||
}
|
||
|
||
function getGridConfig(gridItem, updater) {
|
||
var animationCurve = gridItem.animationCurve,
|
||
animationFrame = gridItem.animationFrame,
|
||
rLevel = gridItem.rLevel;
|
||
var shape = getGridShape(gridItem, updater);
|
||
var style = getGridStyle(gridItem);
|
||
updater.chart.gridArea = _objectSpread({}, shape);
|
||
return [{
|
||
name: 'rect',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
}];
|
||
}
|
||
|
||
function getGridShape(gridItem, updater) {
|
||
var _updater$chart$render = (0, _slicedToArray2["default"])(updater.chart.render.area, 2),
|
||
w = _updater$chart$render[0],
|
||
h = _updater$chart$render[1];
|
||
|
||
var left = getNumberValue(gridItem.left, w);
|
||
var right = getNumberValue(gridItem.right, w);
|
||
var top = getNumberValue(gridItem.top, h);
|
||
var bottom = getNumberValue(gridItem.bottom, h);
|
||
var width = w - left - right;
|
||
var height = h - top - bottom;
|
||
return {
|
||
x: left,
|
||
y: top,
|
||
w: width,
|
||
h: height
|
||
};
|
||
}
|
||
|
||
function getNumberValue(val, all) {
|
||
if (typeof val === 'number') return val;
|
||
if (typeof val !== 'string') return 0;
|
||
return all * parseInt(val) / 100;
|
||
}
|
||
|
||
function getGridStyle(gridItem) {
|
||
var style = gridItem.style;
|
||
return style;
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@jiaminghi/c-render/lib/plugin/util":54}],20:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
Object.defineProperty(exports, "mergeColor", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _mergeColor.mergeColor;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "title", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _title.title;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "grid", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _grid.grid;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "axis", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _axis.axis;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "line", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _line.line;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "bar", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _bar.bar;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "pie", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _pie.pie;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "radarAxis", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _radarAxis.radarAxis;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "radar", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _radar.radar;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "gauge", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _gauge.gauge;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "legend", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _legend.legend;
|
||
}
|
||
});
|
||
|
||
var _mergeColor = require("./mergeColor");
|
||
|
||
var _title = require("./title");
|
||
|
||
var _grid = require("./grid");
|
||
|
||
var _axis = require("./axis");
|
||
|
||
var _line = require("./line");
|
||
|
||
var _bar = require("./bar");
|
||
|
||
var _pie = require("./pie");
|
||
|
||
var _radarAxis = require("./radarAxis");
|
||
|
||
var _radar = require("./radar");
|
||
|
||
var _gauge = require("./gauge");
|
||
|
||
var _legend = require("./legend");
|
||
},{"./axis":16,"./bar":17,"./gauge":18,"./grid":19,"./legend":21,"./line":22,"./mergeColor":23,"./pie":24,"./radar":25,"./radarAxis":26,"./title":27}],21:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.legend = legend;
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function legend(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var legend = option.legend;
|
||
|
||
if (legend) {
|
||
legend = (0, _util2.deepMerge)((0, _util.deepClone)(_config.legendConfig, true), legend);
|
||
legend = initLegendData(legend);
|
||
legend = filterInvalidData(legend, option, chart);
|
||
legend = calcLegendTextWidth(legend, chart);
|
||
legend = calcLegendPosition(legend, chart);
|
||
legend = [legend];
|
||
} else {
|
||
legend = [];
|
||
}
|
||
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: legend,
|
||
key: 'legendIcon',
|
||
getGraphConfig: getIconConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: legend,
|
||
key: 'legendText',
|
||
getGraphConfig: getTextConfig
|
||
});
|
||
}
|
||
|
||
function initLegendData(legend) {
|
||
var data = legend.data;
|
||
legend.data = data.map(function (item) {
|
||
var itemType = (0, _typeof2["default"])(item);
|
||
|
||
if (itemType === 'string') {
|
||
return {
|
||
name: item
|
||
};
|
||
} else if (itemType === 'object') {
|
||
return item;
|
||
}
|
||
|
||
return {
|
||
name: ''
|
||
};
|
||
});
|
||
return legend;
|
||
}
|
||
|
||
function filterInvalidData(legend, option, chart) {
|
||
var series = option.series;
|
||
var legendStatus = chart.legendStatus;
|
||
var data = legend.data.filter(function (item) {
|
||
var name = item.name;
|
||
var result = series.find(function (_ref) {
|
||
var sn = _ref.name;
|
||
return name === sn;
|
||
});
|
||
if (!result) return false;
|
||
if (!item.color) item.color = result.color;
|
||
if (!item.icon) item.icon = result.type;
|
||
return item;
|
||
});
|
||
if (!legendStatus || legendStatus.length !== legend.data.length) legendStatus = new Array(legend.data.length).fill(true);
|
||
data.forEach(function (item, i) {
|
||
return item.status = legendStatus[i];
|
||
});
|
||
legend.data = data;
|
||
chart.legendStatus = legendStatus;
|
||
return legend;
|
||
}
|
||
|
||
function calcLegendTextWidth(legend, chart) {
|
||
var ctx = chart.render.ctx;
|
||
var data = legend.data,
|
||
textStyle = legend.textStyle,
|
||
textUnselectedStyle = legend.textUnselectedStyle;
|
||
data.forEach(function (item) {
|
||
var status = item.status,
|
||
name = item.name;
|
||
item.textWidth = getTextWidth(ctx, name, status ? textStyle : textUnselectedStyle);
|
||
});
|
||
return legend;
|
||
}
|
||
|
||
function getTextWidth(ctx, text, style) {
|
||
ctx.font = getFontConfig(style);
|
||
return ctx.measureText(text).width;
|
||
}
|
||
|
||
function getFontConfig(style) {
|
||
var fontFamily = style.fontFamily,
|
||
fontSize = style.fontSize;
|
||
return "".concat(fontSize, "px ").concat(fontFamily);
|
||
}
|
||
|
||
function calcLegendPosition(legend, chart) {
|
||
var orient = legend.orient;
|
||
|
||
if (orient === 'vertical') {
|
||
calcVerticalPosition(legend, chart);
|
||
} else {
|
||
calcHorizontalPosition(legend, chart);
|
||
}
|
||
|
||
return legend;
|
||
}
|
||
|
||
function calcHorizontalPosition(legend, chart) {
|
||
var iconHeight = legend.iconHeight,
|
||
itemGap = legend.itemGap;
|
||
var lines = calcDefaultHorizontalPosition(legend, chart);
|
||
var xOffsets = lines.map(function (line) {
|
||
return getHorizontalXOffset(line, legend, chart);
|
||
});
|
||
var yOffset = getHorizontalYOffset(legend, chart);
|
||
var align = {
|
||
textAlign: 'left',
|
||
textBaseline: 'middle'
|
||
};
|
||
lines.forEach(function (line, i) {
|
||
return line.forEach(function (item) {
|
||
var iconPosition = item.iconPosition,
|
||
textPosition = item.textPosition;
|
||
var xOffset = xOffsets[i];
|
||
var realYOffset = yOffset + i * (itemGap + iconHeight);
|
||
item.iconPosition = mergeOffset(iconPosition, [xOffset, realYOffset]);
|
||
item.textPosition = mergeOffset(textPosition, [xOffset, realYOffset]);
|
||
item.align = align;
|
||
});
|
||
});
|
||
}
|
||
|
||
function calcDefaultHorizontalPosition(legend, chart) {
|
||
var data = legend.data,
|
||
iconWidth = legend.iconWidth;
|
||
var w = chart.render.area[0];
|
||
var startIndex = 0;
|
||
var lines = [[]];
|
||
data.forEach(function (item, i) {
|
||
var beforeWidth = getBeforeWidth(startIndex, i, legend);
|
||
var endXPos = beforeWidth + iconWidth + 5 + item.textWidth;
|
||
|
||
if (endXPos >= w) {
|
||
startIndex = i;
|
||
beforeWidth = getBeforeWidth(startIndex, i, legend);
|
||
lines.push([]);
|
||
}
|
||
|
||
item.iconPosition = [beforeWidth, 0];
|
||
item.textPosition = [beforeWidth + iconWidth + 5, 0];
|
||
lines.slice(-1)[0].push(item);
|
||
});
|
||
return lines;
|
||
}
|
||
|
||
function getBeforeWidth(startIndex, currentIndex, legend) {
|
||
var data = legend.data,
|
||
iconWidth = legend.iconWidth,
|
||
itemGap = legend.itemGap;
|
||
var beforeItem = data.slice(startIndex, currentIndex);
|
||
return (0, _util2.mulAdd)(beforeItem.map(function (_ref2) {
|
||
var textWidth = _ref2.textWidth;
|
||
return textWidth;
|
||
})) + (currentIndex - startIndex) * (itemGap + 5 + iconWidth);
|
||
}
|
||
|
||
function getHorizontalXOffset(data, legend, chart) {
|
||
var left = legend.left,
|
||
right = legend.right,
|
||
iconWidth = legend.iconWidth,
|
||
itemGap = legend.itemGap;
|
||
var w = chart.render.area[0];
|
||
var dataNum = data.length;
|
||
var allWidth = (0, _util2.mulAdd)(data.map(function (_ref3) {
|
||
var textWidth = _ref3.textWidth;
|
||
return textWidth;
|
||
})) + dataNum * (5 + iconWidth) + (dataNum - 1) * itemGap;
|
||
var horizontal = [left, right].findIndex(function (pos) {
|
||
return pos !== 'auto';
|
||
});
|
||
|
||
if (horizontal === -1) {
|
||
return (w - allWidth) / 2;
|
||
} else if (horizontal === 0) {
|
||
if (typeof left === 'number') return left;
|
||
return parseInt(left) / 100 * w;
|
||
} else {
|
||
if (typeof right !== 'number') right = parseInt(right) / 100 * w;
|
||
return w - (allWidth + right);
|
||
}
|
||
}
|
||
|
||
function getHorizontalYOffset(legend, chart) {
|
||
var top = legend.top,
|
||
bottom = legend.bottom,
|
||
iconHeight = legend.iconHeight;
|
||
var h = chart.render.area[1];
|
||
var vertical = [top, bottom].findIndex(function (pos) {
|
||
return pos !== 'auto';
|
||
});
|
||
var halfIconHeight = iconHeight / 2;
|
||
|
||
if (vertical === -1) {
|
||
var _chart$gridArea = chart.gridArea,
|
||
y = _chart$gridArea.y,
|
||
height = _chart$gridArea.h;
|
||
return y + height + 45 - halfIconHeight;
|
||
} else if (vertical === 0) {
|
||
if (typeof top === 'number') return top - halfIconHeight;
|
||
return parseInt(top) / 100 * h - halfIconHeight;
|
||
} else {
|
||
if (typeof bottom !== 'number') bottom = parseInt(bottom) / 100 * h;
|
||
return h - bottom - halfIconHeight;
|
||
}
|
||
}
|
||
|
||
function mergeOffset(_ref4, _ref5) {
|
||
var _ref6 = (0, _slicedToArray2["default"])(_ref4, 2),
|
||
x = _ref6[0],
|
||
y = _ref6[1];
|
||
|
||
var _ref7 = (0, _slicedToArray2["default"])(_ref5, 2),
|
||
ox = _ref7[0],
|
||
oy = _ref7[1];
|
||
|
||
return [x + ox, y + oy];
|
||
}
|
||
|
||
function calcVerticalPosition(legend, chart) {
|
||
var _getVerticalXOffset = getVerticalXOffset(legend, chart),
|
||
_getVerticalXOffset2 = (0, _slicedToArray2["default"])(_getVerticalXOffset, 2),
|
||
isRight = _getVerticalXOffset2[0],
|
||
xOffset = _getVerticalXOffset2[1];
|
||
|
||
var yOffset = getVerticalYOffset(legend, chart);
|
||
calcDefaultVerticalPosition(legend, isRight);
|
||
var align = {
|
||
textAlign: 'left',
|
||
textBaseline: 'middle'
|
||
};
|
||
legend.data.forEach(function (item) {
|
||
var textPosition = item.textPosition,
|
||
iconPosition = item.iconPosition;
|
||
item.textPosition = mergeOffset(textPosition, [xOffset, yOffset]);
|
||
item.iconPosition = mergeOffset(iconPosition, [xOffset, yOffset]);
|
||
item.align = align;
|
||
});
|
||
}
|
||
|
||
function getVerticalXOffset(legend, chart) {
|
||
var left = legend.left,
|
||
right = legend.right;
|
||
var w = chart.render.area[0];
|
||
var horizontal = [left, right].findIndex(function (pos) {
|
||
return pos !== 'auto';
|
||
});
|
||
|
||
if (horizontal === -1) {
|
||
return [true, w - 10];
|
||
} else {
|
||
var offset = [left, right][horizontal];
|
||
if (typeof offset !== 'number') offset = parseInt(offset) / 100 * w;
|
||
return [Boolean(horizontal), offset];
|
||
}
|
||
}
|
||
|
||
function getVerticalYOffset(legend, chart) {
|
||
var iconHeight = legend.iconHeight,
|
||
itemGap = legend.itemGap,
|
||
data = legend.data,
|
||
top = legend.top,
|
||
bottom = legend.bottom;
|
||
var h = chart.render.area[1];
|
||
var dataNum = data.length;
|
||
var allHeight = dataNum * iconHeight + (dataNum - 1) * itemGap;
|
||
var vertical = [top, bottom].findIndex(function (pos) {
|
||
return pos !== 'auto';
|
||
});
|
||
|
||
if (vertical === -1) {
|
||
return (h - allHeight) / 2;
|
||
} else {
|
||
var offset = [top, bottom][vertical];
|
||
if (typeof offset !== 'number') offset = parseInt(offset) / 100 * h;
|
||
if (vertical === 1) offset = h - offset - allHeight;
|
||
return offset;
|
||
}
|
||
}
|
||
|
||
function calcDefaultVerticalPosition(legend, isRight) {
|
||
var data = legend.data,
|
||
iconWidth = legend.iconWidth,
|
||
iconHeight = legend.iconHeight,
|
||
itemGap = legend.itemGap;
|
||
var halfIconHeight = iconHeight / 2;
|
||
data.forEach(function (item, i) {
|
||
var textWidth = item.textWidth;
|
||
var yPos = (iconHeight + itemGap) * i + halfIconHeight;
|
||
var iconXPos = isRight ? 0 - iconWidth : 0;
|
||
var textXpos = isRight ? iconXPos - 5 - textWidth : iconWidth + 5;
|
||
item.iconPosition = [iconXPos, yPos];
|
||
item.textPosition = [textXpos, yPos];
|
||
});
|
||
}
|
||
|
||
function getIconConfig(legendItem, updater) {
|
||
var data = legendItem.data,
|
||
selectAble = legendItem.selectAble,
|
||
animationCurve = legendItem.animationCurve,
|
||
animationFrame = legendItem.animationFrame,
|
||
rLevel = legendItem.rLevel;
|
||
return data.map(function (item, i) {
|
||
return (0, _defineProperty2["default"])({
|
||
name: item.icon === 'line' ? 'lineIcon' : 'rect',
|
||
index: rLevel,
|
||
visible: legendItem.show,
|
||
hover: selectAble,
|
||
click: selectAble,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getIconShape(legendItem, i),
|
||
style: getIconStyle(legendItem, i)
|
||
}, "click", createClickCallBack(legendItem, i, updater));
|
||
});
|
||
}
|
||
|
||
function getIconShape(legendItem, i) {
|
||
var data = legendItem.data,
|
||
iconWidth = legendItem.iconWidth,
|
||
iconHeight = legendItem.iconHeight;
|
||
|
||
var _data$i$iconPosition = (0, _slicedToArray2["default"])(data[i].iconPosition, 2),
|
||
x = _data$i$iconPosition[0],
|
||
y = _data$i$iconPosition[1];
|
||
|
||
var halfIconHeight = iconHeight / 2;
|
||
return {
|
||
x: x,
|
||
y: y - halfIconHeight,
|
||
w: iconWidth,
|
||
h: iconHeight
|
||
};
|
||
}
|
||
|
||
function getIconStyle(legendItem, i) {
|
||
var data = legendItem.data,
|
||
iconStyle = legendItem.iconStyle,
|
||
iconUnselectedStyle = legendItem.iconUnselectedStyle;
|
||
var _data$i = data[i],
|
||
status = _data$i.status,
|
||
color = _data$i.color;
|
||
var style = status ? iconStyle : iconUnselectedStyle;
|
||
return (0, _util2.deepMerge)({
|
||
fill: color
|
||
}, style);
|
||
}
|
||
|
||
function getTextConfig(legendItem, updater) {
|
||
var data = legendItem.data,
|
||
selectAble = legendItem.selectAble,
|
||
animationCurve = legendItem.animationCurve,
|
||
animationFrame = legendItem.animationFrame,
|
||
rLevel = legendItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: legendItem.show,
|
||
hover: selectAble,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
hoverRect: getTextHoverRect(legendItem, i),
|
||
shape: getTextShape(legendItem, i),
|
||
style: getTextStyle(legendItem, i),
|
||
click: createClickCallBack(legendItem, i, updater)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getTextShape(legendItem, i) {
|
||
var _legendItem$data$i = legendItem.data[i],
|
||
textPosition = _legendItem$data$i.textPosition,
|
||
name = _legendItem$data$i.name;
|
||
return {
|
||
content: name,
|
||
position: textPosition
|
||
};
|
||
}
|
||
|
||
function getTextStyle(legendItem, i) {
|
||
var textStyle = legendItem.textStyle,
|
||
textUnselectedStyle = legendItem.textUnselectedStyle;
|
||
var _legendItem$data$i2 = legendItem.data[i],
|
||
status = _legendItem$data$i2.status,
|
||
align = _legendItem$data$i2.align;
|
||
var style = status ? textStyle : textUnselectedStyle;
|
||
return (0, _util2.deepMerge)((0, _util.deepClone)(style, true), align);
|
||
}
|
||
|
||
function getTextHoverRect(legendItem, i) {
|
||
var textStyle = legendItem.textStyle,
|
||
textUnselectedStyle = legendItem.textUnselectedStyle;
|
||
|
||
var _legendItem$data$i3 = legendItem.data[i],
|
||
status = _legendItem$data$i3.status,
|
||
_legendItem$data$i3$t = (0, _slicedToArray2["default"])(_legendItem$data$i3.textPosition, 2),
|
||
x = _legendItem$data$i3$t[0],
|
||
y = _legendItem$data$i3$t[1],
|
||
textWidth = _legendItem$data$i3.textWidth;
|
||
|
||
var style = status ? textStyle : textUnselectedStyle;
|
||
var fontSize = style.fontSize;
|
||
return [x, y - fontSize / 2, textWidth, fontSize];
|
||
}
|
||
|
||
function createClickCallBack(legendItem, index, updater) {
|
||
var name = legendItem.data[index].name;
|
||
return function () {
|
||
var _updater$chart = updater.chart,
|
||
legendStatus = _updater$chart.legendStatus,
|
||
option = _updater$chart.option;
|
||
var status = !legendStatus[index];
|
||
var change = option.series.find(function (_ref9) {
|
||
var sn = _ref9.name;
|
||
return sn === name;
|
||
});
|
||
change.show = status;
|
||
legendStatus[index] = status;
|
||
updater.chart.setOption(option);
|
||
};
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54}],22:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.line = line;
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _bezierCurve = _interopRequireDefault(require("@jiaminghi/bezier-curve"));
|
||
|
||
var _util = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
var polylineToBezierCurve = _bezierCurve["default"].polylineToBezierCurve,
|
||
getBezierCurveLength = _bezierCurve["default"].getBezierCurveLength;
|
||
|
||
function line(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var xAxis = option.xAxis,
|
||
yAxis = option.yAxis,
|
||
series = option.series;
|
||
var lines = [];
|
||
|
||
if (xAxis && yAxis && series) {
|
||
lines = (0, _util.initNeedSeries)(series, _config.lineConfig, 'line');
|
||
lines = calcLinesPosition(lines, chart);
|
||
}
|
||
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: lines,
|
||
key: 'lineArea',
|
||
getGraphConfig: getLineAreaConfig,
|
||
getStartGraphConfig: getStartLineAreaConfig,
|
||
beforeUpdate: beforeUpdateLineAndArea,
|
||
beforeChange: beforeChangeLineAndArea
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: lines,
|
||
key: 'line',
|
||
getGraphConfig: getLineConfig,
|
||
getStartGraphConfig: getStartLineConfig,
|
||
beforeUpdate: beforeUpdateLineAndArea,
|
||
beforeChange: beforeChangeLineAndArea
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: lines,
|
||
key: 'linePoint',
|
||
getGraphConfig: getPointConfig,
|
||
getStartGraphConfig: getStartPointConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: lines,
|
||
key: 'lineLabel',
|
||
getGraphConfig: getLabelConfig
|
||
});
|
||
}
|
||
|
||
function calcLinesPosition(lines, chart) {
|
||
var axisData = chart.axisData;
|
||
return lines.map(function (lineItem) {
|
||
var lineData = (0, _util.mergeSameStackData)(lineItem, lines);
|
||
lineData = mergeNonNumber(lineItem, lineData);
|
||
var lineAxis = getLineAxis(lineItem, axisData);
|
||
var linePosition = getLinePosition(lineData, lineAxis);
|
||
var lineFillBottomPos = getLineFillBottomPos(lineAxis);
|
||
return _objectSpread({}, lineItem, {
|
||
linePosition: linePosition.filter(function (p) {
|
||
return p;
|
||
}),
|
||
lineFillBottomPos: lineFillBottomPos
|
||
});
|
||
});
|
||
}
|
||
|
||
function mergeNonNumber(lineItem, lineData) {
|
||
var data = lineItem.data;
|
||
return lineData.map(function (v, i) {
|
||
return typeof data[i] === 'number' ? v : null;
|
||
});
|
||
}
|
||
|
||
function getLineAxis(line, axisData) {
|
||
var xAxisIndex = line.xAxisIndex,
|
||
yAxisIndex = line.yAxisIndex;
|
||
var xAxis = axisData.find(function (_ref) {
|
||
var axis = _ref.axis,
|
||
index = _ref.index;
|
||
return axis === 'x' && index === xAxisIndex;
|
||
});
|
||
var yAxis = axisData.find(function (_ref2) {
|
||
var axis = _ref2.axis,
|
||
index = _ref2.index;
|
||
return axis === 'y' && index === yAxisIndex;
|
||
});
|
||
return [xAxis, yAxis];
|
||
}
|
||
|
||
function getLinePosition(lineData, lineAxis) {
|
||
var valueAxisIndex = lineAxis.findIndex(function (_ref3) {
|
||
var data = _ref3.data;
|
||
return data === 'value';
|
||
});
|
||
var valueAxis = lineAxis[valueAxisIndex];
|
||
var labelAxis = lineAxis[1 - valueAxisIndex];
|
||
var linePosition = valueAxis.linePosition,
|
||
axis = valueAxis.axis;
|
||
var tickPosition = labelAxis.tickPosition;
|
||
var tickNum = tickPosition.length;
|
||
var valueAxisPosIndex = axis === 'x' ? 0 : 1;
|
||
var valueAxisStartPos = linePosition[0][valueAxisPosIndex];
|
||
var valueAxisEndPos = linePosition[1][valueAxisPosIndex];
|
||
var valueAxisPosMinus = valueAxisEndPos - valueAxisStartPos;
|
||
var maxValue = valueAxis.maxValue,
|
||
minValue = valueAxis.minValue;
|
||
var valueMinus = maxValue - minValue;
|
||
var position = new Array(tickNum).fill(0).map(function (foo, i) {
|
||
var v = lineData[i];
|
||
if (typeof v !== 'number') return null;
|
||
var valuePercent = (v - minValue) / valueMinus;
|
||
if (valueMinus === 0) valuePercent = 0;
|
||
return valuePercent * valueAxisPosMinus + valueAxisStartPos;
|
||
});
|
||
return position.map(function (vPos, i) {
|
||
if (i >= tickNum || typeof vPos !== 'number') return null;
|
||
var pos = [vPos, tickPosition[i][1 - valueAxisPosIndex]];
|
||
if (valueAxisPosIndex === 0) return pos;
|
||
pos.reverse();
|
||
return pos;
|
||
});
|
||
}
|
||
|
||
function getLineFillBottomPos(lineAxis) {
|
||
var valueAxis = lineAxis.find(function (_ref4) {
|
||
var data = _ref4.data;
|
||
return data === 'value';
|
||
});
|
||
var axis = valueAxis.axis,
|
||
linePosition = valueAxis.linePosition,
|
||
minValue = valueAxis.minValue,
|
||
maxValue = valueAxis.maxValue;
|
||
var changeIndex = axis === 'x' ? 0 : 1;
|
||
var changeValue = linePosition[0][changeIndex];
|
||
|
||
if (minValue < 0 && maxValue > 0) {
|
||
var valueMinus = maxValue - minValue;
|
||
var posMinus = Math.abs(linePosition[0][changeIndex] - linePosition[1][changeIndex]);
|
||
var offset = Math.abs(minValue) / valueMinus * posMinus;
|
||
if (axis === 'y') offset *= -1;
|
||
changeValue += offset;
|
||
}
|
||
|
||
return {
|
||
changeIndex: changeIndex,
|
||
changeValue: changeValue
|
||
};
|
||
}
|
||
|
||
function getLineAreaConfig(lineItem) {
|
||
var animationCurve = lineItem.animationCurve,
|
||
animationFrame = lineItem.animationFrame,
|
||
lineFillBottomPos = lineItem.lineFillBottomPos,
|
||
rLevel = lineItem.rLevel;
|
||
return [{
|
||
name: getLineGraphName(lineItem),
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
visible: lineItem.lineArea.show,
|
||
lineFillBottomPos: lineFillBottomPos,
|
||
shape: getLineAndAreaShape(lineItem),
|
||
style: getLineAreaStyle(lineItem),
|
||
drawed: lineAreaDrawed
|
||
}];
|
||
}
|
||
|
||
function getLineAndAreaShape(lineItem) {
|
||
var linePosition = lineItem.linePosition;
|
||
return {
|
||
points: linePosition
|
||
};
|
||
}
|
||
|
||
function getLineAreaStyle(lineItem) {
|
||
var lineArea = lineItem.lineArea,
|
||
color = lineItem.color;
|
||
var gradient = lineArea.gradient,
|
||
style = lineArea.style;
|
||
var fillColor = [style.fill || color];
|
||
var gradientColor = (0, _util.deepMerge)(fillColor, gradient);
|
||
if (gradientColor.length === 1) gradientColor.push(gradientColor[0]);
|
||
var gradientParams = getGradientParams(lineItem);
|
||
style = _objectSpread({}, style, {
|
||
stroke: 'rgba(0, 0, 0, 0)'
|
||
});
|
||
return (0, _util.deepMerge)({
|
||
gradientColor: gradientColor,
|
||
gradientParams: gradientParams,
|
||
gradientType: 'linear',
|
||
gradientWith: 'fill'
|
||
}, style);
|
||
}
|
||
|
||
function getGradientParams(lineItem) {
|
||
var lineFillBottomPos = lineItem.lineFillBottomPos,
|
||
linePosition = lineItem.linePosition;
|
||
var changeIndex = lineFillBottomPos.changeIndex,
|
||
changeValue = lineFillBottomPos.changeValue;
|
||
var mainPos = linePosition.map(function (p) {
|
||
return p[changeIndex];
|
||
});
|
||
var maxPos = Math.max.apply(Math, (0, _toConsumableArray2["default"])(mainPos));
|
||
var minPos = Math.min.apply(Math, (0, _toConsumableArray2["default"])(mainPos));
|
||
var beginPos = maxPos;
|
||
if (changeIndex === 1) beginPos = minPos;
|
||
|
||
if (changeIndex === 1) {
|
||
return [0, beginPos, 0, changeValue];
|
||
} else {
|
||
return [beginPos, 0, changeValue, 0];
|
||
}
|
||
}
|
||
|
||
function lineAreaDrawed(_ref5, _ref6) {
|
||
var lineFillBottomPos = _ref5.lineFillBottomPos,
|
||
shape = _ref5.shape;
|
||
var ctx = _ref6.ctx;
|
||
var points = shape.points;
|
||
var changeIndex = lineFillBottomPos.changeIndex,
|
||
changeValue = lineFillBottomPos.changeValue;
|
||
var linePoint1 = (0, _toConsumableArray2["default"])(points[points.length - 1]);
|
||
var linePoint2 = (0, _toConsumableArray2["default"])(points[0]);
|
||
linePoint1[changeIndex] = changeValue;
|
||
linePoint2[changeIndex] = changeValue;
|
||
ctx.lineTo.apply(ctx, (0, _toConsumableArray2["default"])(linePoint1));
|
||
ctx.lineTo.apply(ctx, (0, _toConsumableArray2["default"])(linePoint2));
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
}
|
||
|
||
function getStartLineAreaConfig(lineItem) {
|
||
var config = getLineAreaConfig(lineItem)[0];
|
||
|
||
var style = _objectSpread({}, config.style);
|
||
|
||
style.opacity = 0;
|
||
config.style = style;
|
||
return [config];
|
||
}
|
||
|
||
function beforeUpdateLineAndArea(graphs, lineItem, i, updater) {
|
||
var cache = graphs[i];
|
||
if (!cache) return;
|
||
var currentName = getLineGraphName(lineItem);
|
||
var render = updater.chart.render;
|
||
var name = cache[0].name;
|
||
var delAll = currentName !== name;
|
||
if (!delAll) return;
|
||
cache.forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
graphs[i] = null;
|
||
}
|
||
|
||
function beforeChangeLineAndArea(graph, config) {
|
||
var points = config.shape.points;
|
||
var graphPoints = graph.shape.points;
|
||
var graphPointsNum = graphPoints.length;
|
||
var pointsNum = points.length;
|
||
|
||
if (pointsNum > graphPointsNum) {
|
||
var lastPoint = graphPoints.slice(-1)[0];
|
||
var newAddPoints = new Array(pointsNum - graphPointsNum).fill(0).map(function (foo) {
|
||
return (0, _toConsumableArray2["default"])(lastPoint);
|
||
});
|
||
graphPoints.push.apply(graphPoints, (0, _toConsumableArray2["default"])(newAddPoints));
|
||
} else if (pointsNum < graphPointsNum) {
|
||
graphPoints.splice(pointsNum);
|
||
}
|
||
}
|
||
|
||
function getLineConfig(lineItem) {
|
||
var animationCurve = lineItem.animationCurve,
|
||
animationFrame = lineItem.animationFrame,
|
||
rLevel = lineItem.rLevel;
|
||
return [{
|
||
name: getLineGraphName(lineItem),
|
||
index: rLevel + 1,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getLineAndAreaShape(lineItem),
|
||
style: getLineStyle(lineItem)
|
||
}];
|
||
}
|
||
|
||
function getLineGraphName(lineItem) {
|
||
var smooth = lineItem.smooth;
|
||
return smooth ? 'smoothline' : 'polyline';
|
||
}
|
||
|
||
function getLineStyle(lineItem) {
|
||
var lineStyle = lineItem.lineStyle,
|
||
color = lineItem.color,
|
||
smooth = lineItem.smooth,
|
||
linePosition = lineItem.linePosition;
|
||
var lineLength = getLineLength(linePosition, smooth);
|
||
return (0, _util.deepMerge)({
|
||
stroke: color,
|
||
lineDash: [lineLength, 0]
|
||
}, lineStyle);
|
||
}
|
||
|
||
function getLineLength(points) {
|
||
var smooth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
if (!smooth) return (0, _util.getPolylineLength)(points);
|
||
var curve = polylineToBezierCurve(points);
|
||
return getBezierCurveLength(curve);
|
||
}
|
||
|
||
function getStartLineConfig(lineItem) {
|
||
var lineDash = lineItem.lineStyle.lineDash;
|
||
var config = getLineConfig(lineItem)[0];
|
||
var realLineDash = config.style.lineDash;
|
||
|
||
if (lineDash) {
|
||
realLineDash = [0, 0];
|
||
} else {
|
||
realLineDash = (0, _toConsumableArray2["default"])(realLineDash).reverse();
|
||
}
|
||
|
||
config.style.lineDash = realLineDash;
|
||
return [config];
|
||
}
|
||
|
||
function getPointConfig(lineItem) {
|
||
var animationCurve = lineItem.animationCurve,
|
||
animationFrame = lineItem.animationFrame,
|
||
rLevel = lineItem.rLevel;
|
||
var shapes = getPointShapes(lineItem);
|
||
var style = getPointStyle(lineItem);
|
||
return shapes.map(function (shape) {
|
||
return {
|
||
name: 'circle',
|
||
index: rLevel + 2,
|
||
visible: lineItem.linePoint.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getPointShapes(lineItem) {
|
||
var linePosition = lineItem.linePosition,
|
||
radius = lineItem.linePoint.radius;
|
||
return linePosition.map(function (_ref7) {
|
||
var _ref8 = (0, _slicedToArray2["default"])(_ref7, 2),
|
||
rx = _ref8[0],
|
||
ry = _ref8[1];
|
||
|
||
return {
|
||
r: radius,
|
||
rx: rx,
|
||
ry: ry
|
||
};
|
||
});
|
||
}
|
||
|
||
function getPointStyle(lineItem) {
|
||
var color = lineItem.color,
|
||
style = lineItem.linePoint.style;
|
||
return (0, _util.deepMerge)({
|
||
stroke: color
|
||
}, style);
|
||
}
|
||
|
||
function getStartPointConfig(lineItem) {
|
||
var configs = getPointConfig(lineItem);
|
||
configs.forEach(function (config) {
|
||
config.shape.r = 0.1;
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function getLabelConfig(lineItem) {
|
||
var animationCurve = lineItem.animationCurve,
|
||
animationFrame = lineItem.animationFrame,
|
||
rLevel = lineItem.rLevel;
|
||
var shapes = getLabelShapes(lineItem);
|
||
var style = getLabelStyle(lineItem);
|
||
return shapes.map(function (shape, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel + 3,
|
||
visible: lineItem.label.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelShapes(lineItem) {
|
||
var contents = formatterLabel(lineItem);
|
||
var position = getLabelPosition(lineItem);
|
||
return contents.map(function (content, i) {
|
||
return {
|
||
content: content,
|
||
position: position[i]
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelPosition(lineItem) {
|
||
var linePosition = lineItem.linePosition,
|
||
lineFillBottomPos = lineItem.lineFillBottomPos,
|
||
label = lineItem.label;
|
||
var position = label.position,
|
||
offset = label.offset;
|
||
var changeIndex = lineFillBottomPos.changeIndex,
|
||
changeValue = lineFillBottomPos.changeValue;
|
||
return linePosition.map(function (pos) {
|
||
if (position === 'bottom') {
|
||
pos = (0, _toConsumableArray2["default"])(pos);
|
||
pos[changeIndex] = changeValue;
|
||
}
|
||
|
||
if (position === 'center') {
|
||
var bottom = (0, _toConsumableArray2["default"])(pos);
|
||
bottom[changeIndex] = changeValue;
|
||
pos = getCenterLabelPoint(pos, bottom);
|
||
}
|
||
|
||
return getOffsetedPoint(pos, offset);
|
||
});
|
||
}
|
||
|
||
function getOffsetedPoint(_ref9, _ref10) {
|
||
var _ref11 = (0, _slicedToArray2["default"])(_ref9, 2),
|
||
x = _ref11[0],
|
||
y = _ref11[1];
|
||
|
||
var _ref12 = (0, _slicedToArray2["default"])(_ref10, 2),
|
||
ox = _ref12[0],
|
||
oy = _ref12[1];
|
||
|
||
return [x + ox, y + oy];
|
||
}
|
||
|
||
function getCenterLabelPoint(_ref13, _ref14) {
|
||
var _ref15 = (0, _slicedToArray2["default"])(_ref13, 2),
|
||
ax = _ref15[0],
|
||
ay = _ref15[1];
|
||
|
||
var _ref16 = (0, _slicedToArray2["default"])(_ref14, 2),
|
||
bx = _ref16[0],
|
||
by = _ref16[1];
|
||
|
||
return [(ax + bx) / 2, (ay + by) / 2];
|
||
}
|
||
|
||
function formatterLabel(lineItem) {
|
||
var data = lineItem.data,
|
||
formatter = lineItem.label.formatter;
|
||
data = data.filter(function (d) {
|
||
return typeof d === 'number';
|
||
}).map(function (d) {
|
||
return d.toString();
|
||
});
|
||
if (!formatter) return data;
|
||
var type = (0, _typeof2["default"])(formatter);
|
||
if (type === 'string') return data.map(function (d) {
|
||
return formatter.replace('{value}', d);
|
||
});
|
||
if (type === 'function') return data.map(function (value, index) {
|
||
return formatter({
|
||
value: value,
|
||
index: index
|
||
});
|
||
});
|
||
return data;
|
||
}
|
||
|
||
function getLabelStyle(lineItem) {
|
||
var color = lineItem.color,
|
||
style = lineItem.label.style;
|
||
return (0, _util.deepMerge)({
|
||
fill: color
|
||
}, style);
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/bezier-curve":47}],23:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.mergeColor = mergeColor;
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function mergeColor(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var defaultColor = (0, _util.deepClone)(_config.colorConfig, true);
|
||
var color = option.color,
|
||
series = option.series;
|
||
if (!series) series = [];
|
||
if (!color) color = [];
|
||
option.color = color = (0, _util2.deepMerge)(defaultColor, color);
|
||
if (!series.length) return;
|
||
var colorNum = color.length;
|
||
series.forEach(function (item, i) {
|
||
if (item.color) return;
|
||
item.color = color[i % colorNum];
|
||
});
|
||
var pies = series.filter(function (_ref) {
|
||
var type = _ref.type;
|
||
return type === 'pie';
|
||
});
|
||
pies.forEach(function (pie) {
|
||
return pie.data.forEach(function (di, i) {
|
||
return di.color = color[i % colorNum];
|
||
});
|
||
});
|
||
var gauges = series.filter(function (_ref2) {
|
||
var type = _ref2.type;
|
||
return type === 'gauge';
|
||
});
|
||
gauges.forEach(function (gauge) {
|
||
return gauge.data.forEach(function (di, i) {
|
||
return di.color = color[i % colorNum];
|
||
});
|
||
});
|
||
var barWithIndependentColor = series.filter(function (_ref3) {
|
||
var type = _ref3.type,
|
||
independentColor = _ref3.independentColor;
|
||
return type === 'bar' && independentColor;
|
||
});
|
||
barWithIndependentColor.forEach(function (bar) {
|
||
if (bar.independentColors) return;
|
||
bar.independentColors = color;
|
||
});
|
||
}
|
||
},{"../config":9,"../util":30,"@jiaminghi/c-render/lib/plugin/util":54}],24:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.pie = pie;
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _pie = require("../config/pie");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function pie(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var series = option.series;
|
||
if (!series) series = [];
|
||
var pies = (0, _util2.initNeedSeries)(series, _pie.pieConfig, 'pie');
|
||
pies = calcPiesCenter(pies, chart);
|
||
pies = calcPiesRadius(pies, chart);
|
||
pies = calcRosePiesRadius(pies, chart);
|
||
pies = calcPiesPercent(pies);
|
||
pies = calcPiesAngle(pies, chart);
|
||
pies = calcPiesInsideLabelPos(pies);
|
||
pies = calcPiesEdgeCenterPos(pies);
|
||
pies = calcPiesOutSideLabelPos(pies);
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: pies,
|
||
key: 'pie',
|
||
getGraphConfig: getPieConfig,
|
||
getStartGraphConfig: getStartPieConfig,
|
||
beforeChange: beforeChangePie
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: pies,
|
||
key: 'pieInsideLabel',
|
||
getGraphConfig: getInsideLabelConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: pies,
|
||
key: 'pieOutsideLabelLine',
|
||
getGraphConfig: getOutsideLabelLineConfig,
|
||
getStartGraphConfig: getStartOutsideLabelLineConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: pies,
|
||
key: 'pieOutsideLabel',
|
||
getGraphConfig: getOutsideLabelConfig,
|
||
getStartGraphConfig: getStartOutsideLabelConfig
|
||
});
|
||
}
|
||
|
||
function calcPiesCenter(pies, chart) {
|
||
var area = chart.render.area;
|
||
pies.forEach(function (pie) {
|
||
var center = pie.center;
|
||
center = center.map(function (pos, i) {
|
||
if (typeof pos === 'number') return pos;
|
||
return parseInt(pos) / 100 * area[i];
|
||
});
|
||
pie.center = center;
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function calcPiesRadius(pies, chart) {
|
||
var maxRadius = Math.min.apply(Math, (0, _toConsumableArray2["default"])(chart.render.area)) / 2;
|
||
pies.forEach(function (pie) {
|
||
var radius = pie.radius,
|
||
data = pie.data;
|
||
radius = getNumberRadius(radius, maxRadius);
|
||
data.forEach(function (item) {
|
||
var itemRadius = item.radius;
|
||
if (!itemRadius) itemRadius = radius;
|
||
itemRadius = getNumberRadius(itemRadius, maxRadius);
|
||
item.radius = itemRadius;
|
||
});
|
||
pie.radius = radius;
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function getNumberRadius(radius, maxRadius) {
|
||
if (!(radius instanceof Array)) radius = [0, radius];
|
||
radius = radius.map(function (r) {
|
||
if (typeof r === 'number') return r;
|
||
return parseInt(r) / 100 * maxRadius;
|
||
});
|
||
return radius;
|
||
}
|
||
|
||
function calcRosePiesRadius(pies, chart) {
|
||
var rosePie = pies.filter(function (_ref) {
|
||
var roseType = _ref.roseType;
|
||
return roseType;
|
||
});
|
||
rosePie.forEach(function (pie) {
|
||
var radius = pie.radius,
|
||
data = pie.data,
|
||
roseSort = pie.roseSort;
|
||
var roseIncrement = getRoseIncrement(pie);
|
||
var dataCopy = (0, _toConsumableArray2["default"])(data);
|
||
data = sortData(data);
|
||
data.forEach(function (item, i) {
|
||
item.radius[1] = radius[1] - roseIncrement * i;
|
||
});
|
||
|
||
if (roseSort) {
|
||
data.reverse();
|
||
} else {
|
||
pie.data = dataCopy;
|
||
}
|
||
|
||
pie.roseIncrement = roseIncrement;
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function sortData(data) {
|
||
return data.sort(function (_ref2, _ref3) {
|
||
var a = _ref2.value;
|
||
var b = _ref3.value;
|
||
if (a === b) return 0;
|
||
if (a > b) return -1;
|
||
if (a < b) return 1;
|
||
});
|
||
}
|
||
|
||
function getRoseIncrement(pie) {
|
||
var radius = pie.radius,
|
||
roseIncrement = pie.roseIncrement;
|
||
if (typeof roseIncrement === 'number') return roseIncrement;
|
||
|
||
if (roseIncrement === 'auto') {
|
||
var data = pie.data;
|
||
var allRadius = data.reduce(function (all, _ref4) {
|
||
var radius = _ref4.radius;
|
||
return [].concat((0, _toConsumableArray2["default"])(all), (0, _toConsumableArray2["default"])(radius));
|
||
}, []);
|
||
var minRadius = Math.min.apply(Math, (0, _toConsumableArray2["default"])(allRadius));
|
||
var maxRadius = Math.max.apply(Math, (0, _toConsumableArray2["default"])(allRadius));
|
||
return (maxRadius - minRadius) * 0.6 / (data.length - 1 || 1);
|
||
}
|
||
|
||
return parseInt(roseIncrement) / 100 * radius[1];
|
||
}
|
||
|
||
function calcPiesPercent(pies) {
|
||
pies.forEach(function (pie) {
|
||
var data = pie.data,
|
||
percentToFixed = pie.percentToFixed;
|
||
var sum = getDataSum(data);
|
||
data.forEach(function (item) {
|
||
var value = item.value;
|
||
item.percent = toFixedNoCeil(value / sum * 100, percentToFixed);
|
||
});
|
||
var percentSumNoLast = (0, _util2.mulAdd)(data.slice(0, -1).map(function (_ref5) {
|
||
var percent = _ref5.percent;
|
||
return percent;
|
||
}));
|
||
data.slice(-1)[0].percent = toFixedNoCeil(100 - percentSumNoLast, percentToFixed);
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function toFixedNoCeil(number) {
|
||
var toFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
||
var stringNumber = number.toString();
|
||
var splitedNumber = stringNumber.split('.');
|
||
var decimal = splitedNumber[1] || '0';
|
||
var fixedDecimal = decimal.slice(0, toFixed);
|
||
splitedNumber[1] = fixedDecimal;
|
||
return parseFloat(splitedNumber.join('.'));
|
||
}
|
||
|
||
function getDataSum(data) {
|
||
return (0, _util2.mulAdd)(data.map(function (_ref6) {
|
||
var value = _ref6.value;
|
||
return value;
|
||
}));
|
||
}
|
||
|
||
function calcPiesAngle(pies) {
|
||
pies.forEach(function (pie) {
|
||
var start = pie.startAngle,
|
||
data = pie.data;
|
||
data.forEach(function (item, i) {
|
||
var _getDataAngle = getDataAngle(data, i),
|
||
_getDataAngle2 = (0, _slicedToArray2["default"])(_getDataAngle, 2),
|
||
startAngle = _getDataAngle2[0],
|
||
endAngle = _getDataAngle2[1];
|
||
|
||
item.startAngle = start + startAngle;
|
||
item.endAngle = start + endAngle;
|
||
});
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function getDataAngle(data, i) {
|
||
var fullAngle = Math.PI * 2;
|
||
var needAddData = data.slice(0, i + 1);
|
||
var percentSum = (0, _util2.mulAdd)(needAddData.map(function (_ref7) {
|
||
var percent = _ref7.percent;
|
||
return percent;
|
||
}));
|
||
var percent = data[i].percent;
|
||
var startPercent = percentSum - percent;
|
||
return [fullAngle * startPercent / 100, fullAngle * percentSum / 100];
|
||
}
|
||
|
||
function calcPiesInsideLabelPos(pies) {
|
||
pies.forEach(function (pieItem) {
|
||
var data = pieItem.data;
|
||
data.forEach(function (item) {
|
||
item.insideLabelPos = getPieInsideLabelPos(pieItem, item);
|
||
});
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function getPieInsideLabelPos(pieItem, dataItem) {
|
||
var center = pieItem.center;
|
||
|
||
var startAngle = dataItem.startAngle,
|
||
endAngle = dataItem.endAngle,
|
||
_dataItem$radius = (0, _slicedToArray2["default"])(dataItem.radius, 2),
|
||
ir = _dataItem$radius[0],
|
||
or = _dataItem$radius[1];
|
||
|
||
var radius = (ir + or) / 2;
|
||
var angle = (startAngle + endAngle) / 2;
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([radius, angle]));
|
||
}
|
||
|
||
function calcPiesEdgeCenterPos(pies) {
|
||
pies.forEach(function (pie) {
|
||
var data = pie.data,
|
||
center = pie.center;
|
||
data.forEach(function (item) {
|
||
var startAngle = item.startAngle,
|
||
endAngle = item.endAngle,
|
||
radius = item.radius;
|
||
var centerAngle = (startAngle + endAngle) / 2;
|
||
|
||
var pos = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([radius[1], centerAngle]));
|
||
|
||
item.edgeCenterPos = pos;
|
||
});
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function calcPiesOutSideLabelPos(pies) {
|
||
pies.forEach(function (pieItem) {
|
||
var leftPieDataItems = getLeftOrRightPieDataItems(pieItem);
|
||
var rightPieDataItems = getLeftOrRightPieDataItems(pieItem, false);
|
||
leftPieDataItems = sortPiesFromTopToBottom(leftPieDataItems);
|
||
rightPieDataItems = sortPiesFromTopToBottom(rightPieDataItems);
|
||
addLabelLineAndAlign(leftPieDataItems, pieItem);
|
||
addLabelLineAndAlign(rightPieDataItems, pieItem, false);
|
||
});
|
||
return pies;
|
||
}
|
||
|
||
function getLabelLineBendRadius(pieItem) {
|
||
var labelLineBendGap = pieItem.outsideLabel.labelLineBendGap;
|
||
var maxRadius = getPieMaxRadius(pieItem);
|
||
|
||
if (typeof labelLineBendGap !== 'number') {
|
||
labelLineBendGap = parseInt(labelLineBendGap) / 100 * maxRadius;
|
||
}
|
||
|
||
return labelLineBendGap + maxRadius;
|
||
}
|
||
|
||
function getPieMaxRadius(pieItem) {
|
||
var data = pieItem.data;
|
||
var radius = data.map(function (_ref8) {
|
||
var _ref8$radius = (0, _slicedToArray2["default"])(_ref8.radius, 2),
|
||
foo = _ref8$radius[0],
|
||
r = _ref8$radius[1];
|
||
|
||
return r;
|
||
});
|
||
return Math.max.apply(Math, (0, _toConsumableArray2["default"])(radius));
|
||
}
|
||
|
||
function getLeftOrRightPieDataItems(pieItem) {
|
||
var left = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||
var data = pieItem.data,
|
||
center = pieItem.center;
|
||
var centerXPos = center[0];
|
||
return data.filter(function (_ref9) {
|
||
var edgeCenterPos = _ref9.edgeCenterPos;
|
||
var xPos = edgeCenterPos[0];
|
||
if (left) return xPos <= centerXPos;
|
||
return xPos > centerXPos;
|
||
});
|
||
}
|
||
|
||
function sortPiesFromTopToBottom(dataItem) {
|
||
dataItem.sort(function (_ref10, _ref11) {
|
||
var _ref10$edgeCenterPos = (0, _slicedToArray2["default"])(_ref10.edgeCenterPos, 2),
|
||
t = _ref10$edgeCenterPos[0],
|
||
ay = _ref10$edgeCenterPos[1];
|
||
|
||
var _ref11$edgeCenterPos = (0, _slicedToArray2["default"])(_ref11.edgeCenterPos, 2),
|
||
tt = _ref11$edgeCenterPos[0],
|
||
by = _ref11$edgeCenterPos[1];
|
||
|
||
if (ay > by) return 1;
|
||
if (ay < by) return -1;
|
||
if (ay === by) return 0;
|
||
});
|
||
return dataItem;
|
||
}
|
||
|
||
function addLabelLineAndAlign(dataItem, pieItem) {
|
||
var left = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
||
var center = pieItem.center,
|
||
outsideLabel = pieItem.outsideLabel;
|
||
var radius = getLabelLineBendRadius(pieItem);
|
||
dataItem.forEach(function (item) {
|
||
var edgeCenterPos = item.edgeCenterPos,
|
||
startAngle = item.startAngle,
|
||
endAngle = item.endAngle;
|
||
var labelLineEndLength = outsideLabel.labelLineEndLength;
|
||
var angle = (startAngle + endAngle) / 2;
|
||
|
||
var bendPoint = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(center).concat([radius, angle]));
|
||
|
||
var endPoint = (0, _toConsumableArray2["default"])(bendPoint);
|
||
endPoint[0] += labelLineEndLength * (left ? -1 : 1);
|
||
item.labelLine = [edgeCenterPos, bendPoint, endPoint];
|
||
item.labelLineLength = (0, _util2.getPolylineLength)(item.labelLine);
|
||
item.align = {
|
||
textAlign: 'left',
|
||
textBaseline: 'middle'
|
||
};
|
||
if (left) item.align.textAlign = 'right';
|
||
});
|
||
}
|
||
|
||
function getPieConfig(pieItem) {
|
||
var data = pieItem.data,
|
||
animationCurve = pieItem.animationCurve,
|
||
animationFrame = pieItem.animationFrame,
|
||
rLevel = pieItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'pie',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getPieShape(pieItem, i),
|
||
style: getPieStyle(pieItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getStartPieConfig(pieItem) {
|
||
var animationDelayGap = pieItem.animationDelayGap,
|
||
startAnimationCurve = pieItem.startAnimationCurve;
|
||
var configs = getPieConfig(pieItem);
|
||
configs.forEach(function (config, i) {
|
||
config.animationCurve = startAnimationCurve;
|
||
config.animationDelay = i * animationDelayGap;
|
||
config.shape.or = config.shape.ir;
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function beforeChangePie(graph) {
|
||
graph.animationDelay = 0;
|
||
}
|
||
|
||
function getPieShape(pieItem, i) {
|
||
var center = pieItem.center,
|
||
data = pieItem.data;
|
||
var dataItem = data[i];
|
||
var radius = dataItem.radius,
|
||
startAngle = dataItem.startAngle,
|
||
endAngle = dataItem.endAngle;
|
||
return {
|
||
startAngle: startAngle,
|
||
endAngle: endAngle,
|
||
ir: radius[0],
|
||
or: radius[1],
|
||
rx: center[0],
|
||
ry: center[1]
|
||
};
|
||
}
|
||
|
||
function getPieStyle(pieItem, i) {
|
||
var pieStyle = pieItem.pieStyle,
|
||
data = pieItem.data;
|
||
var dataItem = data[i];
|
||
var color = dataItem.color;
|
||
return (0, _util2.deepMerge)({
|
||
fill: color
|
||
}, pieStyle);
|
||
}
|
||
|
||
function getInsideLabelConfig(pieItem) {
|
||
var animationCurve = pieItem.animationCurve,
|
||
animationFrame = pieItem.animationFrame,
|
||
data = pieItem.data,
|
||
rLevel = pieItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: pieItem.insideLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getInsideLabelShape(pieItem, i),
|
||
style: getInsideLabelStyle(pieItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getInsideLabelShape(pieItem, i) {
|
||
var insideLabel = pieItem.insideLabel,
|
||
data = pieItem.data;
|
||
var formatter = insideLabel.formatter;
|
||
var dataItem = data[i];
|
||
var formatterType = (0, _typeof2["default"])(formatter);
|
||
var label = '';
|
||
|
||
if (formatterType === 'string') {
|
||
label = formatter.replace('{name}', dataItem.name);
|
||
label = label.replace('{percent}', dataItem.percent);
|
||
label = label.replace('{value}', dataItem.value);
|
||
}
|
||
|
||
if (formatterType === 'function') {
|
||
label = formatter(dataItem);
|
||
}
|
||
|
||
return {
|
||
content: label,
|
||
position: dataItem.insideLabelPos
|
||
};
|
||
}
|
||
|
||
function getInsideLabelStyle(pieItem, i) {
|
||
var style = pieItem.insideLabel.style;
|
||
return style;
|
||
}
|
||
|
||
function getOutsideLabelLineConfig(pieItem) {
|
||
var animationCurve = pieItem.animationCurve,
|
||
animationFrame = pieItem.animationFrame,
|
||
data = pieItem.data,
|
||
rLevel = pieItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: pieItem.outsideLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getOutsideLabelLineShape(pieItem, i),
|
||
style: getOutsideLabelLineStyle(pieItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getStartOutsideLabelLineConfig(pieItem) {
|
||
var data = pieItem.data;
|
||
var configs = getOutsideLabelLineConfig(pieItem);
|
||
configs.forEach(function (config, i) {
|
||
config.style.lineDash = [0, data[i].labelLineLength];
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function getOutsideLabelLineShape(pieItem, i) {
|
||
var data = pieItem.data;
|
||
var dataItem = data[i];
|
||
return {
|
||
points: dataItem.labelLine
|
||
};
|
||
}
|
||
|
||
function getOutsideLabelLineStyle(pieItem, i) {
|
||
var outsideLabel = pieItem.outsideLabel,
|
||
data = pieItem.data;
|
||
var labelLineStyle = outsideLabel.labelLineStyle;
|
||
var color = data[i].color;
|
||
return (0, _util2.deepMerge)({
|
||
stroke: color,
|
||
lineDash: [data[i].labelLineLength, 0]
|
||
}, labelLineStyle);
|
||
}
|
||
|
||
function getOutsideLabelConfig(pieItem) {
|
||
var animationCurve = pieItem.animationCurve,
|
||
animationFrame = pieItem.animationFrame,
|
||
data = pieItem.data,
|
||
rLevel = pieItem.rLevel;
|
||
return data.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: pieItem.outsideLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getOutsideLabelShape(pieItem, i),
|
||
style: getOutsideLabelStyle(pieItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getStartOutsideLabelConfig(pieItem) {
|
||
var data = pieItem.data;
|
||
var configs = getOutsideLabelConfig(pieItem);
|
||
configs.forEach(function (config, i) {
|
||
config.shape.position = data[i].labelLine[1];
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function getOutsideLabelShape(pieItem, i) {
|
||
var outsideLabel = pieItem.outsideLabel,
|
||
data = pieItem.data;
|
||
var formatter = outsideLabel.formatter;
|
||
var _data$i = data[i],
|
||
labelLine = _data$i.labelLine,
|
||
name = _data$i.name,
|
||
percent = _data$i.percent,
|
||
value = _data$i.value;
|
||
var formatterType = (0, _typeof2["default"])(formatter);
|
||
var label = '';
|
||
|
||
if (formatterType === 'string') {
|
||
label = formatter.replace('{name}', name);
|
||
label = label.replace('{percent}', percent);
|
||
label = label.replace('{value}', value);
|
||
}
|
||
|
||
if (formatterType === 'function') {
|
||
label = formatter(data[i]);
|
||
}
|
||
|
||
return {
|
||
content: label,
|
||
position: labelLine[2]
|
||
};
|
||
}
|
||
|
||
function getOutsideLabelStyle(pieItem, i) {
|
||
var outsideLabel = pieItem.outsideLabel,
|
||
data = pieItem.data;
|
||
var _data$i2 = data[i],
|
||
color = _data$i2.color,
|
||
align = _data$i2.align;
|
||
var style = outsideLabel.style;
|
||
return (0, _util2.deepMerge)(_objectSpread({
|
||
fill: color
|
||
}, align), style);
|
||
}
|
||
},{"../class/updater.class":3,"../config/pie":12,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54}],25:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.radar = radar;
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _index = require("../config/index");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _color = require("@jiaminghi/color");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function radar(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var series = option.series;
|
||
if (!series) series = [];
|
||
var radars = (0, _util2.initNeedSeries)(series, _index.radarConfig, 'radar');
|
||
radars = calcRadarPosition(radars, chart);
|
||
radars = calcRadarLabelPosition(radars, chart);
|
||
radars = calcRadarLabelAlign(radars, chart);
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radars,
|
||
key: 'radar',
|
||
getGraphConfig: getRadarConfig,
|
||
getStartGraphConfig: getStartRadarConfig,
|
||
beforeChange: beforeChangeRadar
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radars,
|
||
key: 'radarPoint',
|
||
getGraphConfig: getPointConfig,
|
||
getStartGraphConfig: getStartPointConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radars,
|
||
key: 'radarLabel',
|
||
getGraphConfig: getLabelConfig
|
||
});
|
||
}
|
||
|
||
function calcRadarPosition(radars, chart) {
|
||
var radarAxis = chart.radarAxis;
|
||
if (!radarAxis) return [];
|
||
var indicator = radarAxis.indicator,
|
||
axisLineAngles = radarAxis.axisLineAngles,
|
||
radius = radarAxis.radius,
|
||
centerPos = radarAxis.centerPos;
|
||
radars.forEach(function (radarItem) {
|
||
var data = radarItem.data;
|
||
radarItem.dataRadius = [];
|
||
radarItem.radarPosition = indicator.map(function (_ref, i) {
|
||
var max = _ref.max,
|
||
min = _ref.min;
|
||
var v = data[i];
|
||
if (typeof max !== 'number') max = v;
|
||
if (typeof min !== 'number') min = 0;
|
||
if (typeof v !== 'number') v = min;
|
||
var dataRadius = (v - min) / (max - min) * radius;
|
||
radarItem.dataRadius[i] = dataRadius;
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([dataRadius, axisLineAngles[i]]));
|
||
});
|
||
});
|
||
return radars;
|
||
}
|
||
|
||
function calcRadarLabelPosition(radars, chart) {
|
||
var radarAxis = chart.radarAxis;
|
||
if (!radarAxis) return [];
|
||
var centerPos = radarAxis.centerPos,
|
||
axisLineAngles = radarAxis.axisLineAngles;
|
||
radars.forEach(function (radarItem) {
|
||
var dataRadius = radarItem.dataRadius,
|
||
label = radarItem.label;
|
||
var labelGap = label.labelGap;
|
||
radarItem.labelPosition = dataRadius.map(function (r, i) {
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([r + labelGap, axisLineAngles[i]]));
|
||
});
|
||
});
|
||
return radars;
|
||
}
|
||
|
||
function calcRadarLabelAlign(radars, chart) {
|
||
var radarAxis = chart.radarAxis;
|
||
if (!radarAxis) return [];
|
||
|
||
var _radarAxis$centerPos = (0, _slicedToArray2["default"])(radarAxis.centerPos, 2),
|
||
x = _radarAxis$centerPos[0],
|
||
y = _radarAxis$centerPos[1];
|
||
|
||
radars.forEach(function (radarItem) {
|
||
var labelPosition = radarItem.labelPosition;
|
||
var labelAlign = labelPosition.map(function (_ref2) {
|
||
var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2),
|
||
lx = _ref3[0],
|
||
ly = _ref3[1];
|
||
|
||
var textAlign = lx > x ? 'left' : 'right';
|
||
var textBaseline = ly > y ? 'top' : 'bottom';
|
||
return {
|
||
textAlign: textAlign,
|
||
textBaseline: textBaseline
|
||
};
|
||
});
|
||
radarItem.labelAlign = labelAlign;
|
||
});
|
||
return radars;
|
||
}
|
||
|
||
function getRadarConfig(radarItem) {
|
||
var animationCurve = radarItem.animationCurve,
|
||
animationFrame = radarItem.animationFrame,
|
||
rLevel = radarItem.rLevel;
|
||
return [{
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getRadarShape(radarItem),
|
||
style: getRadarStyle(radarItem)
|
||
}];
|
||
}
|
||
|
||
function getStartRadarConfig(radarItem, updater) {
|
||
var centerPos = updater.chart.radarAxis.centerPos;
|
||
var config = getRadarConfig(radarItem)[0];
|
||
var pointNum = config.shape.points.length;
|
||
var points = new Array(pointNum).fill(0).map(function (foo) {
|
||
return (0, _toConsumableArray2["default"])(centerPos);
|
||
});
|
||
config.shape.points = points;
|
||
return [config];
|
||
}
|
||
|
||
function getRadarShape(radarItem) {
|
||
var radarPosition = radarItem.radarPosition;
|
||
return {
|
||
points: radarPosition,
|
||
close: true
|
||
};
|
||
}
|
||
|
||
function getRadarStyle(radarItem) {
|
||
var radarStyle = radarItem.radarStyle,
|
||
color = radarItem.color;
|
||
var colorRgbaValue = (0, _color.getRgbaValue)(color);
|
||
colorRgbaValue[3] = 0.5;
|
||
var radarDefaultColor = {
|
||
stroke: color,
|
||
fill: (0, _color.getColorFromRgbValue)(colorRgbaValue)
|
||
};
|
||
return (0, _util2.deepMerge)(radarDefaultColor, radarStyle);
|
||
}
|
||
|
||
function beforeChangeRadar(graph, _ref4) {
|
||
var shape = _ref4.shape;
|
||
var graphPoints = graph.shape.points;
|
||
var graphPointsNum = graphPoints.length;
|
||
var pointsNum = shape.points.length;
|
||
|
||
if (pointsNum > graphPointsNum) {
|
||
var lastPoint = graphPoints.slice(-1)[0];
|
||
var newAddPoints = new Array(pointsNum - graphPointsNum).fill(0).map(function (foo) {
|
||
return (0, _toConsumableArray2["default"])(lastPoint);
|
||
});
|
||
graphPoints.push.apply(graphPoints, (0, _toConsumableArray2["default"])(newAddPoints));
|
||
} else if (pointsNum < graphPointsNum) {
|
||
graphPoints.splice(pointsNum);
|
||
}
|
||
}
|
||
|
||
function getPointConfig(radarItem) {
|
||
var radarPosition = radarItem.radarPosition,
|
||
animationCurve = radarItem.animationCurve,
|
||
animationFrame = radarItem.animationFrame,
|
||
rLevel = radarItem.rLevel;
|
||
return radarPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'circle',
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
visible: radarItem.point.show,
|
||
shape: getPointShape(radarItem, i),
|
||
style: getPointStyle(radarItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getStartPointConfig(radarItem) {
|
||
var configs = getPointConfig(radarItem);
|
||
configs.forEach(function (config) {
|
||
return config.shape.r = 0.01;
|
||
});
|
||
return configs;
|
||
}
|
||
|
||
function getPointShape(radarItem, i) {
|
||
var radarPosition = radarItem.radarPosition,
|
||
point = radarItem.point;
|
||
var radius = point.radius;
|
||
var position = radarPosition[i];
|
||
return {
|
||
rx: position[0],
|
||
ry: position[1],
|
||
r: radius
|
||
};
|
||
}
|
||
|
||
function getPointStyle(radarItem, i) {
|
||
var point = radarItem.point,
|
||
color = radarItem.color;
|
||
var style = point.style;
|
||
return (0, _util2.deepMerge)({
|
||
stroke: color
|
||
}, style);
|
||
}
|
||
|
||
function getLabelConfig(radarItem) {
|
||
var labelPosition = radarItem.labelPosition,
|
||
animationCurve = radarItem.animationCurve,
|
||
animationFrame = radarItem.animationFrame,
|
||
rLevel = radarItem.rLevel;
|
||
return labelPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: radarItem.label.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getLabelShape(radarItem, i),
|
||
style: getLabelStyle(radarItem, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getLabelShape(radarItem, i) {
|
||
var labelPosition = radarItem.labelPosition,
|
||
label = radarItem.label,
|
||
data = radarItem.data;
|
||
var offset = label.offset,
|
||
formatter = label.formatter;
|
||
var position = mergePointOffset(labelPosition[i], offset);
|
||
var labelText = data[i] ? data[i].toString() : '0';
|
||
var formatterType = (0, _typeof2["default"])(formatter);
|
||
if (formatterType === 'string') labelText = formatter.replace('{value}', labelText);
|
||
if (formatterType === 'function') labelText = formatter(labelText);
|
||
return {
|
||
content: labelText,
|
||
position: position
|
||
};
|
||
}
|
||
|
||
function mergePointOffset(_ref5, _ref6) {
|
||
var _ref7 = (0, _slicedToArray2["default"])(_ref5, 2),
|
||
x = _ref7[0],
|
||
y = _ref7[1];
|
||
|
||
var _ref8 = (0, _slicedToArray2["default"])(_ref6, 2),
|
||
ox = _ref8[0],
|
||
oy = _ref8[1];
|
||
|
||
return [x + ox, y + oy];
|
||
}
|
||
|
||
function getLabelStyle(radarItem, i) {
|
||
var label = radarItem.label,
|
||
color = radarItem.color,
|
||
labelAlign = radarItem.labelAlign;
|
||
var style = label.style;
|
||
|
||
var defaultColorAndAlign = _objectSpread({
|
||
fill: color
|
||
}, labelAlign[i]);
|
||
|
||
return (0, _util2.deepMerge)(defaultColorAndAlign, style);
|
||
}
|
||
},{"../class/updater.class":3,"../config/index":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54,"@jiaminghi/color":56}],26:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.radarAxis = radarAxis;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _index = require("../config/index");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
function radarAxis(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var radar = option.radar;
|
||
var radarAxis = [];
|
||
|
||
if (radar) {
|
||
radarAxis = mergeRadarAxisDefaultConfig(radar);
|
||
radarAxis = calcRadarAxisCenter(radarAxis, chart);
|
||
radarAxis = calcRadarAxisRingRadius(radarAxis, chart);
|
||
radarAxis = calcRadarAxisLinePosition(radarAxis);
|
||
radarAxis = calcRadarAxisAreaRadius(radarAxis);
|
||
radarAxis = calcRadarAxisLabelPosition(radarAxis);
|
||
radarAxis = [radarAxis];
|
||
}
|
||
|
||
var radarAxisForUpdate = radarAxis;
|
||
if (radarAxis.length && !radarAxis[0].show) radarAxisForUpdate = [];
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radarAxisForUpdate,
|
||
key: 'radarAxisSplitArea',
|
||
getGraphConfig: getSplitAreaConfig,
|
||
beforeUpdate: beforeUpdateSplitArea,
|
||
beforeChange: beforeChangeSplitArea
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radarAxisForUpdate,
|
||
key: 'radarAxisSplitLine',
|
||
getGraphConfig: getSplitLineConfig,
|
||
beforeUpdate: beforeUpdateSplitLine,
|
||
beforeChange: beforeChangeSplitLine
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radarAxisForUpdate,
|
||
key: 'radarAxisLine',
|
||
getGraphConfig: getAxisLineConfig
|
||
});
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: radarAxisForUpdate,
|
||
key: 'radarAxisLable',
|
||
getGraphConfig: getAxisLabelConfig
|
||
});
|
||
chart.radarAxis = radarAxis[0];
|
||
}
|
||
|
||
function mergeRadarAxisDefaultConfig(radar) {
|
||
return (0, _util2.deepMerge)((0, _util.deepClone)(_index.radarAxisConfig), radar);
|
||
}
|
||
|
||
function calcRadarAxisCenter(radarAxis, chart) {
|
||
var area = chart.render.area;
|
||
var center = radarAxis.center;
|
||
radarAxis.centerPos = center.map(function (v, i) {
|
||
if (typeof v === 'number') return v;
|
||
return parseInt(v) / 100 * area[i];
|
||
});
|
||
return radarAxis;
|
||
}
|
||
|
||
function calcRadarAxisRingRadius(radarAxis, chart) {
|
||
var area = chart.render.area;
|
||
var splitNum = radarAxis.splitNum,
|
||
radius = radarAxis.radius;
|
||
var maxRadius = Math.min.apply(Math, (0, _toConsumableArray2["default"])(area)) / 2;
|
||
if (typeof radius !== 'number') radius = parseInt(radius) / 100 * maxRadius;
|
||
var splitGap = radius / splitNum;
|
||
radarAxis.ringRadius = new Array(splitNum).fill(0).map(function (foo, i) {
|
||
return splitGap * (i + 1);
|
||
});
|
||
radarAxis.radius = radius;
|
||
return radarAxis;
|
||
}
|
||
|
||
function calcRadarAxisLinePosition(radarAxis) {
|
||
var indicator = radarAxis.indicator,
|
||
centerPos = radarAxis.centerPos,
|
||
radius = radarAxis.radius,
|
||
startAngle = radarAxis.startAngle;
|
||
var fullAngle = Math.PI * 2;
|
||
var indicatorNum = indicator.length;
|
||
var indicatorGap = fullAngle / indicatorNum;
|
||
var angles = new Array(indicatorNum).fill(0).map(function (foo, i) {
|
||
return indicatorGap * i + startAngle;
|
||
});
|
||
radarAxis.axisLineAngles = angles;
|
||
radarAxis.axisLinePosition = angles.map(function (g) {
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([radius, g]));
|
||
});
|
||
return radarAxis;
|
||
}
|
||
|
||
function calcRadarAxisAreaRadius(radarAxis) {
|
||
var ringRadius = radarAxis.ringRadius;
|
||
var subRadius = ringRadius[0] / 2;
|
||
radarAxis.areaRadius = ringRadius.map(function (r) {
|
||
return r - subRadius;
|
||
});
|
||
return radarAxis;
|
||
}
|
||
|
||
function calcRadarAxisLabelPosition(radarAxis) {
|
||
var axisLineAngles = radarAxis.axisLineAngles,
|
||
centerPos = radarAxis.centerPos,
|
||
radius = radarAxis.radius,
|
||
axisLabel = radarAxis.axisLabel;
|
||
radius += axisLabel.labelGap;
|
||
radarAxis.axisLabelPosition = axisLineAngles.map(function (angle) {
|
||
return _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([radius, angle]));
|
||
});
|
||
return radarAxis;
|
||
}
|
||
|
||
function getSplitAreaConfig(radarAxis) {
|
||
var areaRadius = radarAxis.areaRadius,
|
||
polygon = radarAxis.polygon,
|
||
animationCurve = radarAxis.animationCurve,
|
||
animationFrame = radarAxis.animationFrame,
|
||
rLevel = radarAxis.rLevel;
|
||
var name = polygon ? 'regPolygon' : 'ring';
|
||
return areaRadius.map(function (foo, i) {
|
||
return {
|
||
name: name,
|
||
index: rLevel,
|
||
visible: radarAxis.splitArea.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getSplitAreaShape(radarAxis, i),
|
||
style: getSplitAreaStyle(radarAxis, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getSplitAreaShape(radarAxis, i) {
|
||
var polygon = radarAxis.polygon,
|
||
areaRadius = radarAxis.areaRadius,
|
||
indicator = radarAxis.indicator,
|
||
centerPos = radarAxis.centerPos;
|
||
var indicatorNum = indicator.length;
|
||
var shape = {
|
||
rx: centerPos[0],
|
||
ry: centerPos[1],
|
||
r: areaRadius[i]
|
||
};
|
||
if (polygon) shape.side = indicatorNum;
|
||
return shape;
|
||
}
|
||
|
||
function getSplitAreaStyle(radarAxis, i) {
|
||
var splitArea = radarAxis.splitArea,
|
||
ringRadius = radarAxis.ringRadius,
|
||
axisLineAngles = radarAxis.axisLineAngles,
|
||
polygon = radarAxis.polygon,
|
||
centerPos = radarAxis.centerPos;
|
||
var color = splitArea.color,
|
||
style = splitArea.style;
|
||
style = _objectSpread({
|
||
fill: 'rgba(0, 0, 0, 0)'
|
||
}, style);
|
||
var lineWidth = ringRadius[0] - 0;
|
||
|
||
if (polygon) {
|
||
var point1 = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([ringRadius[0], axisLineAngles[0]]));
|
||
|
||
var point2 = _util.getCircleRadianPoint.apply(void 0, (0, _toConsumableArray2["default"])(centerPos).concat([ringRadius[0], axisLineAngles[1]]));
|
||
|
||
lineWidth = (0, _util2.getPointToLineDistance)(centerPos, point1, point2);
|
||
}
|
||
|
||
style = (0, _util2.deepMerge)((0, _util.deepClone)(style, true), {
|
||
lineWidth: lineWidth
|
||
});
|
||
if (!color.length) return style;
|
||
var colorNum = color.length;
|
||
return (0, _util2.deepMerge)(style, {
|
||
stroke: color[i % colorNum]
|
||
});
|
||
}
|
||
|
||
function beforeUpdateSplitArea(graphs, radarAxis, i, updater) {
|
||
var cache = graphs[i];
|
||
if (!cache) return;
|
||
var render = updater.chart.render;
|
||
var polygon = radarAxis.polygon;
|
||
var name = cache[0].name;
|
||
var currentName = polygon ? 'regPolygon' : 'ring';
|
||
var delAll = currentName !== name;
|
||
if (!delAll) return;
|
||
cache.forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
graphs[i] = null;
|
||
}
|
||
|
||
function beforeChangeSplitArea(graph, config) {
|
||
var side = config.shape.side;
|
||
if (typeof side !== 'number') return;
|
||
graph.shape.side = side;
|
||
}
|
||
|
||
function getSplitLineConfig(radarAxis) {
|
||
var ringRadius = radarAxis.ringRadius,
|
||
polygon = radarAxis.polygon,
|
||
animationCurve = radarAxis.animationCurve,
|
||
animationFrame = radarAxis.animationFrame,
|
||
rLevel = radarAxis.rLevel;
|
||
var name = polygon ? 'regPolygon' : 'ring';
|
||
return ringRadius.map(function (foo, i) {
|
||
return {
|
||
name: name,
|
||
index: rLevel,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
visible: radarAxis.splitLine.show,
|
||
shape: getSplitLineShape(radarAxis, i),
|
||
style: getSplitLineStyle(radarAxis, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getSplitLineShape(radarAxis, i) {
|
||
var ringRadius = radarAxis.ringRadius,
|
||
centerPos = radarAxis.centerPos,
|
||
indicator = radarAxis.indicator,
|
||
polygon = radarAxis.polygon;
|
||
var shape = {
|
||
rx: centerPos[0],
|
||
ry: centerPos[1],
|
||
r: ringRadius[i]
|
||
};
|
||
var indicatorNum = indicator.length;
|
||
if (polygon) shape.side = indicatorNum;
|
||
return shape;
|
||
}
|
||
|
||
function getSplitLineStyle(radarAxis, i) {
|
||
var splitLine = radarAxis.splitLine;
|
||
var color = splitLine.color,
|
||
style = splitLine.style;
|
||
style = _objectSpread({
|
||
fill: 'rgba(0, 0, 0, 0)'
|
||
}, style);
|
||
if (!color.length) return style;
|
||
var colorNum = color.length;
|
||
return (0, _util2.deepMerge)(style, {
|
||
stroke: color[i % colorNum]
|
||
});
|
||
}
|
||
|
||
function beforeUpdateSplitLine(graphs, radarAxis, i, updater) {
|
||
var cache = graphs[i];
|
||
if (!cache) return;
|
||
var render = updater.chart.render;
|
||
var polygon = radarAxis.polygon;
|
||
var name = cache[0].name;
|
||
var currenName = polygon ? 'regPolygon' : 'ring';
|
||
var delAll = currenName !== name;
|
||
if (!delAll) return;
|
||
cache.forEach(function (g) {
|
||
return render.delGraph(g);
|
||
});
|
||
graphs[i] = null;
|
||
}
|
||
|
||
function beforeChangeSplitLine(graph, config) {
|
||
var side = config.shape.side;
|
||
if (typeof side !== 'number') return;
|
||
graph.shape.side = side;
|
||
}
|
||
|
||
function getAxisLineConfig(radarAxis) {
|
||
var axisLinePosition = radarAxis.axisLinePosition,
|
||
animationCurve = radarAxis.animationCurve,
|
||
animationFrame = radarAxis.animationFrame,
|
||
rLevel = radarAxis.rLevel;
|
||
return axisLinePosition.map(function (foo, i) {
|
||
return {
|
||
name: 'polyline',
|
||
index: rLevel,
|
||
visible: radarAxis.axisLine.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getAxisLineShape(radarAxis, i),
|
||
style: getAxisLineStyle(radarAxis, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getAxisLineShape(radarAxis, i) {
|
||
var centerPos = radarAxis.centerPos,
|
||
axisLinePosition = radarAxis.axisLinePosition;
|
||
var points = [centerPos, axisLinePosition[i]];
|
||
return {
|
||
points: points
|
||
};
|
||
}
|
||
|
||
function getAxisLineStyle(radarAxis, i) {
|
||
var axisLine = radarAxis.axisLine;
|
||
var color = axisLine.color,
|
||
style = axisLine.style;
|
||
if (!color.length) return style;
|
||
var colorNum = color.length;
|
||
return (0, _util2.deepMerge)(style, {
|
||
stroke: color[i % colorNum]
|
||
});
|
||
}
|
||
|
||
function getAxisLabelConfig(radarAxis) {
|
||
var axisLabelPosition = radarAxis.axisLabelPosition,
|
||
animationCurve = radarAxis.animationCurve,
|
||
animationFrame = radarAxis.animationFrame,
|
||
rLevel = radarAxis.rLevel;
|
||
return axisLabelPosition.map(function (foo, i) {
|
||
return {
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: radarAxis.axisLabel.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: getAxisLableShape(radarAxis, i),
|
||
style: getAxisLableStyle(radarAxis, i)
|
||
};
|
||
});
|
||
}
|
||
|
||
function getAxisLableShape(radarAxis, i) {
|
||
var axisLabelPosition = radarAxis.axisLabelPosition,
|
||
indicator = radarAxis.indicator;
|
||
return {
|
||
content: indicator[i].name,
|
||
position: axisLabelPosition[i]
|
||
};
|
||
}
|
||
|
||
function getAxisLableStyle(radarAxis, i) {
|
||
var axisLabel = radarAxis.axisLabel,
|
||
_radarAxis$centerPos = (0, _slicedToArray2["default"])(radarAxis.centerPos, 2),
|
||
x = _radarAxis$centerPos[0],
|
||
y = _radarAxis$centerPos[1],
|
||
axisLabelPosition = radarAxis.axisLabelPosition;
|
||
|
||
var color = axisLabel.color,
|
||
style = axisLabel.style;
|
||
|
||
var _axisLabelPosition$i = (0, _slicedToArray2["default"])(axisLabelPosition[i], 2),
|
||
labelXpos = _axisLabelPosition$i[0],
|
||
labelYPos = _axisLabelPosition$i[1];
|
||
|
||
var textAlign = labelXpos > x ? 'left' : 'right';
|
||
var textBaseline = labelYPos > y ? 'top' : 'bottom';
|
||
style = (0, _util2.deepMerge)({
|
||
textAlign: textAlign,
|
||
textBaseline: textBaseline
|
||
}, style);
|
||
if (!color.length) return style;
|
||
var colorNum = color.length;
|
||
return (0, _util2.deepMerge)(style, {
|
||
fill: color[i % colorNum]
|
||
});
|
||
}
|
||
},{"../class/updater.class":3,"../config/index":9,"../util":30,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@jiaminghi/c-render/lib/plugin/util":54}],27:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.title = title;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _updater = require("../class/updater.class");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _config = require("../config");
|
||
|
||
var _util2 = require("../util");
|
||
|
||
function title(chart) {
|
||
var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
var title = [];
|
||
|
||
if (option.title) {
|
||
title[0] = (0, _util2.deepMerge)((0, _util.deepClone)(_config.titleConfig, true), option.title);
|
||
}
|
||
|
||
(0, _updater.doUpdate)({
|
||
chart: chart,
|
||
series: title,
|
||
key: 'title',
|
||
getGraphConfig: getTitleConfig
|
||
});
|
||
}
|
||
|
||
function getTitleConfig(titleItem, updater) {
|
||
var animationCurve = _config.titleConfig.animationCurve,
|
||
animationFrame = _config.titleConfig.animationFrame,
|
||
rLevel = _config.titleConfig.rLevel;
|
||
var shape = getTitleShape(titleItem, updater);
|
||
var style = getTitleStyle(titleItem);
|
||
return [{
|
||
name: 'text',
|
||
index: rLevel,
|
||
visible: titleItem.show,
|
||
animationCurve: animationCurve,
|
||
animationFrame: animationFrame,
|
||
shape: shape,
|
||
style: style
|
||
}];
|
||
}
|
||
|
||
function getTitleShape(titleItem, updater) {
|
||
var offset = titleItem.offset,
|
||
text = titleItem.text;
|
||
var _updater$chart$gridAr = updater.chart.gridArea,
|
||
x = _updater$chart$gridAr.x,
|
||
y = _updater$chart$gridAr.y,
|
||
w = _updater$chart$gridAr.w;
|
||
|
||
var _offset = (0, _slicedToArray2["default"])(offset, 2),
|
||
ox = _offset[0],
|
||
oy = _offset[1];
|
||
|
||
return {
|
||
content: text,
|
||
position: [x + w / 2 + ox, y + oy]
|
||
};
|
||
}
|
||
|
||
function getTitleStyle(titleItem) {
|
||
var style = titleItem.style;
|
||
return style;
|
||
}
|
||
},{"../class/updater.class":3,"../config":9,"../util":30,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@jiaminghi/c-render/lib/plugin/util":54}],28:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _cRender = require("@jiaminghi/c-render");
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
var _color = require("@jiaminghi/color");
|
||
|
||
var _index = require("../util/index");
|
||
|
||
var pie = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
ir: 0,
|
||
or: 0,
|
||
startAngle: 0,
|
||
endAngle: 0,
|
||
clockWise: true
|
||
},
|
||
validator: function validator(_ref) {
|
||
var shape = _ref.shape;
|
||
var keys = ['rx', 'ry', 'ir', 'or', 'startAngle', 'endAngle'];
|
||
|
||
if (keys.find(function (key) {
|
||
return typeof shape[key] !== 'number';
|
||
})) {
|
||
console.error('Pie shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref2, _ref3) {
|
||
var ctx = _ref2.ctx;
|
||
var shape = _ref3.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
ir = shape.ir,
|
||
or = shape.or,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
clockWise = shape.clockWise;
|
||
rx = parseInt(rx) + 0.5;
|
||
ry = parseInt(ry) + 0.5;
|
||
ctx.arc(rx, ry, ir > 0 ? ir : 0, startAngle, endAngle, !clockWise);
|
||
var connectPoint1 = (0, _util.getCircleRadianPoint)(rx, ry, or, endAngle).map(function (p) {
|
||
return parseInt(p) + 0.5;
|
||
});
|
||
var connectPoint2 = (0, _util.getCircleRadianPoint)(rx, ry, ir, startAngle).map(function (p) {
|
||
return parseInt(p) + 0.5;
|
||
});
|
||
ctx.lineTo.apply(ctx, (0, _toConsumableArray2["default"])(connectPoint1));
|
||
ctx.arc(rx, ry, or > 0 ? or : 0, endAngle, startAngle, clockWise);
|
||
ctx.lineTo.apply(ctx, (0, _toConsumableArray2["default"])(connectPoint2));
|
||
ctx.closePath();
|
||
ctx.stroke();
|
||
ctx.fill();
|
||
}
|
||
};
|
||
var agArc = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0,
|
||
startAngle: 0,
|
||
endAngle: 0,
|
||
gradientStartAngle: null,
|
||
gradientEndAngle: null
|
||
},
|
||
validator: function validator(_ref4) {
|
||
var shape = _ref4.shape;
|
||
var keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle'];
|
||
|
||
if (keys.find(function (key) {
|
||
return typeof shape[key] !== 'number';
|
||
})) {
|
||
console.error('AgArc shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref5, _ref6) {
|
||
var ctx = _ref5.ctx;
|
||
var shape = _ref6.shape,
|
||
style = _ref6.style;
|
||
var gradient = style.gradient;
|
||
gradient = gradient.map(function (cv) {
|
||
return (0, _color.getColorFromRgbValue)(cv);
|
||
});
|
||
|
||
if (gradient.length === 1) {
|
||
gradient = [gradient[0], gradient[0]];
|
||
}
|
||
|
||
var gradientArcNum = gradient.length - 1;
|
||
var gradientStartAngle = shape.gradientStartAngle,
|
||
gradientEndAngle = shape.gradientEndAngle,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
r = shape.r,
|
||
rx = shape.rx,
|
||
ry = shape.ry;
|
||
if (gradientStartAngle === null) gradientStartAngle = startAngle;
|
||
if (gradientEndAngle === null) gradientEndAngle = endAngle;
|
||
var angleGap = (gradientEndAngle - gradientStartAngle) / gradientArcNum;
|
||
if (angleGap === Math.PI * 2) angleGap = Math.PI * 2 - 0.001;
|
||
|
||
for (var i = 0; i < gradientArcNum; i++) {
|
||
ctx.beginPath();
|
||
var startPoint = (0, _util.getCircleRadianPoint)(rx, ry, r, startAngle + angleGap * i);
|
||
var endPoint = (0, _util.getCircleRadianPoint)(rx, ry, r, startAngle + angleGap * (i + 1));
|
||
var color = (0, _index.getLinearGradientColor)(ctx, startPoint, endPoint, [gradient[i], gradient[i + 1]]);
|
||
var arcStartAngle = startAngle + angleGap * i;
|
||
var arcEndAngle = startAngle + angleGap * (i + 1);
|
||
var doBreak = false;
|
||
|
||
if (arcEndAngle > endAngle) {
|
||
arcEndAngle = endAngle;
|
||
doBreak = true;
|
||
}
|
||
|
||
ctx.arc(rx, ry, r, arcStartAngle, arcEndAngle);
|
||
ctx.strokeStyle = color;
|
||
ctx.stroke();
|
||
if (doBreak) break;
|
||
}
|
||
}
|
||
};
|
||
var numberText = {
|
||
shape: {
|
||
number: [],
|
||
content: '',
|
||
position: [0, 0],
|
||
toFixed: 0
|
||
},
|
||
validator: function validator(_ref7) {
|
||
var shape = _ref7.shape;
|
||
var number = shape.number,
|
||
content = shape.content,
|
||
position = shape.position;
|
||
|
||
if (!(number instanceof Array) || typeof content !== 'string' || !(position instanceof Array)) {
|
||
console.error('NumberText shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref8, _ref9) {
|
||
var ctx = _ref8.ctx;
|
||
var shape = _ref9.shape;
|
||
ctx.beginPath();
|
||
var number = shape.number,
|
||
content = shape.content,
|
||
position = shape.position,
|
||
toFixed = shape.toFixed;
|
||
var textSegments = content.split('{nt}');
|
||
var lastSegmentIndex = textSegments.length - 1;
|
||
var textString = '';
|
||
textSegments.forEach(function (t, i) {
|
||
var currentNumber = number[i];
|
||
if (i === lastSegmentIndex) currentNumber = '';
|
||
if (typeof currentNumber === 'number') currentNumber = currentNumber.toFixed(toFixed);
|
||
textString += t + (currentNumber || '');
|
||
});
|
||
ctx.closePath();
|
||
ctx.strokeText.apply(ctx, [textString].concat((0, _toConsumableArray2["default"])(position)));
|
||
ctx.fillText.apply(ctx, [textString].concat((0, _toConsumableArray2["default"])(position)));
|
||
}
|
||
};
|
||
var lineIcon = {
|
||
shape: {
|
||
x: 0,
|
||
y: 0,
|
||
w: 0,
|
||
h: 0
|
||
},
|
||
validator: function validator(_ref10) {
|
||
var shape = _ref10.shape;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
|
||
if (typeof x !== 'number' || typeof y !== 'number' || typeof w !== 'number' || typeof h !== 'number') {
|
||
console.error('lineIcon shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref11, _ref12) {
|
||
var ctx = _ref11.ctx;
|
||
var shape = _ref12.shape;
|
||
ctx.beginPath();
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
var halfH = h / 2;
|
||
ctx.strokeStyle = ctx.fillStyle;
|
||
ctx.moveTo(x, y + halfH);
|
||
ctx.lineTo(x + w, y + halfH);
|
||
ctx.lineWidth = 1;
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
var radius = halfH - 5 * 2;
|
||
if (radius <= 0) radius = 3;
|
||
ctx.arc(x + w / 2, y + halfH, radius, 0, Math.PI * 2);
|
||
ctx.lineWidth = 5;
|
||
ctx.stroke();
|
||
ctx.fillStyle = '#fff';
|
||
ctx.fill();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref13) {
|
||
var shape = _ref13.shape;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
return (0, _util.checkPointIsInRect)(position, x, y, w, h);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref14) {
|
||
var shape = _ref14.shape,
|
||
style = _ref14.style;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
style.graphCenter = [x + w / 2, y + h / 2];
|
||
}
|
||
};
|
||
(0, _cRender.extendNewGraph)('pie', pie);
|
||
(0, _cRender.extendNewGraph)('agArc', agArc);
|
||
(0, _cRender.extendNewGraph)('numberText', numberText);
|
||
(0, _cRender.extendNewGraph)('lineIcon', lineIcon);
|
||
},{"../util/index":30,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@jiaminghi/c-render":52,"@jiaminghi/c-render/lib/plugin/util":54,"@jiaminghi/color":56}],29:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
Object.defineProperty(exports, "changeDefaultConfig", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _config.changeDefaultConfig;
|
||
}
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _charts = _interopRequireDefault(require("./class/charts.class"));
|
||
|
||
var _config = require("./config");
|
||
|
||
var _default = _charts["default"];
|
||
exports["default"] = _default;
|
||
},{"./class/charts.class":2,"./config":9,"@babel/runtime/helpers/interopRequireDefault":36}],30:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.filterNonNumber = filterNonNumber;
|
||
exports.deepMerge = deepMerge;
|
||
exports.mulAdd = mulAdd;
|
||
exports.mergeSameStackData = mergeSameStackData;
|
||
exports.getTwoPointDistance = getTwoPointDistance;
|
||
exports.getLinearGradientColor = getLinearGradientColor;
|
||
exports.getPolylineLength = getPolylineLength;
|
||
exports.getPointToLineDistance = getPointToLineDistance;
|
||
exports.initNeedSeries = initNeedSeries;
|
||
exports.radianToAngle = radianToAngle;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _util = require("@jiaminghi/c-render/lib/plugin/util");
|
||
|
||
function filterNonNumber(array) {
|
||
return array.filter(function (n) {
|
||
return typeof n === 'number';
|
||
});
|
||
}
|
||
|
||
function deepMerge(target, merged) {
|
||
for (var key in merged) {
|
||
if (target[key] && (0, _typeof2["default"])(target[key]) === 'object') {
|
||
deepMerge(target[key], merged[key]);
|
||
continue;
|
||
}
|
||
|
||
if ((0, _typeof2["default"])(merged[key]) === 'object') {
|
||
target[key] = (0, _util.deepClone)(merged[key], true);
|
||
continue;
|
||
}
|
||
|
||
target[key] = merged[key];
|
||
}
|
||
|
||
return target;
|
||
}
|
||
|
||
function mulAdd(nums) {
|
||
nums = filterNonNumber(nums);
|
||
return nums.reduce(function (all, num) {
|
||
return all + num;
|
||
}, 0);
|
||
}
|
||
|
||
function mergeSameStackData(item, series) {
|
||
var stack = item.stack;
|
||
if (!stack) return (0, _toConsumableArray2["default"])(item.data);
|
||
var stacks = series.filter(function (_ref) {
|
||
var s = _ref.stack;
|
||
return s === stack;
|
||
});
|
||
var index = stacks.findIndex(function (_ref2) {
|
||
var d = _ref2.data;
|
||
return d === item.data;
|
||
});
|
||
var datas = stacks.splice(0, index + 1).map(function (_ref3) {
|
||
var data = _ref3.data;
|
||
return data;
|
||
});
|
||
var dataLength = datas[0].length;
|
||
return new Array(dataLength).fill(0).map(function (foo, i) {
|
||
return mulAdd(datas.map(function (d) {
|
||
return d[i];
|
||
}));
|
||
});
|
||
}
|
||
|
||
function getTwoPointDistance(pointOne, pointTwo) {
|
||
var minusX = Math.abs(pointOne[0] - pointTwo[0]);
|
||
var minusY = Math.abs(pointOne[1] - pointTwo[1]);
|
||
return Math.sqrt(minusX * minusX + minusY * minusY);
|
||
}
|
||
|
||
function getLinearGradientColor(ctx, begin, end, color) {
|
||
if (!ctx || !begin || !end || !color.length) return;
|
||
var colors = color;
|
||
typeof colors === 'string' && (colors = [color, color]);
|
||
var linearGradientColor = ctx.createLinearGradient.apply(ctx, (0, _toConsumableArray2["default"])(begin).concat((0, _toConsumableArray2["default"])(end)));
|
||
var colorGap = 1 / (colors.length - 1);
|
||
colors.forEach(function (c, i) {
|
||
return linearGradientColor.addColorStop(colorGap * i, c);
|
||
});
|
||
return linearGradientColor;
|
||
}
|
||
|
||
function getPolylineLength(points) {
|
||
var lineSegments = new Array(points.length - 1).fill(0).map(function (foo, i) {
|
||
return [points[i], points[i + 1]];
|
||
});
|
||
var lengths = lineSegments.map(function (item) {
|
||
return getTwoPointDistance.apply(void 0, (0, _toConsumableArray2["default"])(item));
|
||
});
|
||
return mulAdd(lengths);
|
||
}
|
||
|
||
function getPointToLineDistance(point, linePointOne, linePointTwo) {
|
||
var a = getTwoPointDistance(point, linePointOne);
|
||
var b = getTwoPointDistance(point, linePointTwo);
|
||
var c = getTwoPointDistance(linePointOne, linePointTwo);
|
||
return 0.5 * Math.sqrt((a + b + c) * (a + b - c) * (a + c - b) * (b + c - a)) / c;
|
||
}
|
||
|
||
function initNeedSeries(series, config, type) {
|
||
series = series.filter(function (_ref4) {
|
||
var st = _ref4.type;
|
||
return st === type;
|
||
});
|
||
series = series.map(function (item) {
|
||
return deepMerge((0, _util.deepClone)(config, true), item);
|
||
});
|
||
return series.filter(function (_ref5) {
|
||
var show = _ref5.show;
|
||
return show;
|
||
});
|
||
}
|
||
|
||
function radianToAngle(radian) {
|
||
return radian / Math.PI * 180;
|
||
}
|
||
},{"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@jiaminghi/c-render/lib/plugin/util":54}],31:[function(require,module,exports){
|
||
function _arrayWithHoles(arr) {
|
||
if (Array.isArray(arr)) return arr;
|
||
}
|
||
|
||
module.exports = _arrayWithHoles;
|
||
},{}],32:[function(require,module,exports){
|
||
function _arrayWithoutHoles(arr) {
|
||
if (Array.isArray(arr)) {
|
||
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
|
||
arr2[i] = arr[i];
|
||
}
|
||
|
||
return arr2;
|
||
}
|
||
}
|
||
|
||
module.exports = _arrayWithoutHoles;
|
||
},{}],33:[function(require,module,exports){
|
||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
||
try {
|
||
var info = gen[key](arg);
|
||
var value = info.value;
|
||
} catch (error) {
|
||
reject(error);
|
||
return;
|
||
}
|
||
|
||
if (info.done) {
|
||
resolve(value);
|
||
} else {
|
||
Promise.resolve(value).then(_next, _throw);
|
||
}
|
||
}
|
||
|
||
function _asyncToGenerator(fn) {
|
||
return function () {
|
||
var self = this,
|
||
args = arguments;
|
||
return new Promise(function (resolve, reject) {
|
||
var gen = fn.apply(self, args);
|
||
|
||
function _next(value) {
|
||
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
||
}
|
||
|
||
function _throw(err) {
|
||
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
||
}
|
||
|
||
_next(undefined);
|
||
});
|
||
};
|
||
}
|
||
|
||
module.exports = _asyncToGenerator;
|
||
},{}],34:[function(require,module,exports){
|
||
function _classCallCheck(instance, Constructor) {
|
||
if (!(instance instanceof Constructor)) {
|
||
throw new TypeError("Cannot call a class as a function");
|
||
}
|
||
}
|
||
|
||
module.exports = _classCallCheck;
|
||
},{}],35:[function(require,module,exports){
|
||
function _defineProperty(obj, key, value) {
|
||
if (key in obj) {
|
||
Object.defineProperty(obj, key, {
|
||
value: value,
|
||
enumerable: true,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
} else {
|
||
obj[key] = value;
|
||
}
|
||
|
||
return obj;
|
||
}
|
||
|
||
module.exports = _defineProperty;
|
||
},{}],36:[function(require,module,exports){
|
||
function _interopRequireDefault(obj) {
|
||
return obj && obj.__esModule ? obj : {
|
||
"default": obj
|
||
};
|
||
}
|
||
|
||
module.exports = _interopRequireDefault;
|
||
},{}],37:[function(require,module,exports){
|
||
function _iterableToArray(iter) {
|
||
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
|
||
}
|
||
|
||
module.exports = _iterableToArray;
|
||
},{}],38:[function(require,module,exports){
|
||
function _iterableToArrayLimit(arr, i) {
|
||
var _arr = [];
|
||
var _n = true;
|
||
var _d = false;
|
||
var _e = undefined;
|
||
|
||
try {
|
||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
|
||
_arr.push(_s.value);
|
||
|
||
if (i && _arr.length === i) break;
|
||
}
|
||
} catch (err) {
|
||
_d = true;
|
||
_e = err;
|
||
} finally {
|
||
try {
|
||
if (!_n && _i["return"] != null) _i["return"]();
|
||
} finally {
|
||
if (_d) throw _e;
|
||
}
|
||
}
|
||
|
||
return _arr;
|
||
}
|
||
|
||
module.exports = _iterableToArrayLimit;
|
||
},{}],39:[function(require,module,exports){
|
||
function _nonIterableRest() {
|
||
throw new TypeError("Invalid attempt to destructure non-iterable instance");
|
||
}
|
||
|
||
module.exports = _nonIterableRest;
|
||
},{}],40:[function(require,module,exports){
|
||
function _nonIterableSpread() {
|
||
throw new TypeError("Invalid attempt to spread non-iterable instance");
|
||
}
|
||
|
||
module.exports = _nonIterableSpread;
|
||
},{}],41:[function(require,module,exports){
|
||
var arrayWithHoles = require("./arrayWithHoles");
|
||
|
||
var iterableToArrayLimit = require("./iterableToArrayLimit");
|
||
|
||
var nonIterableRest = require("./nonIterableRest");
|
||
|
||
function _slicedToArray(arr, i) {
|
||
return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest();
|
||
}
|
||
|
||
module.exports = _slicedToArray;
|
||
},{"./arrayWithHoles":31,"./iterableToArrayLimit":38,"./nonIterableRest":39}],42:[function(require,module,exports){
|
||
var arrayWithoutHoles = require("./arrayWithoutHoles");
|
||
|
||
var iterableToArray = require("./iterableToArray");
|
||
|
||
var nonIterableSpread = require("./nonIterableSpread");
|
||
|
||
function _toConsumableArray(arr) {
|
||
return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread();
|
||
}
|
||
|
||
module.exports = _toConsumableArray;
|
||
},{"./arrayWithoutHoles":32,"./iterableToArray":37,"./nonIterableSpread":40}],43:[function(require,module,exports){
|
||
function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
|
||
|
||
function _typeof(obj) {
|
||
if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
|
||
module.exports = _typeof = function _typeof(obj) {
|
||
return _typeof2(obj);
|
||
};
|
||
} else {
|
||
module.exports = _typeof = function _typeof(obj) {
|
||
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
|
||
};
|
||
}
|
||
|
||
return _typeof(obj);
|
||
}
|
||
|
||
module.exports = _typeof;
|
||
},{}],44:[function(require,module,exports){
|
||
module.exports = require("regenerator-runtime");
|
||
|
||
},{"regenerator-runtime":59}],45:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.bezierCurveToPolyline = bezierCurveToPolyline;
|
||
exports.getBezierCurveLength = getBezierCurveLength;
|
||
exports["default"] = void 0;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var sqrt = Math.sqrt,
|
||
pow = Math.pow,
|
||
ceil = Math.ceil,
|
||
abs = Math.abs; // Initialize the number of points per curve
|
||
|
||
var defaultSegmentPointsNum = 50;
|
||
/**
|
||
* @example data structure of bezierCurve
|
||
* bezierCurve = [
|
||
* // Starting point of the curve
|
||
* [10, 10],
|
||
* // BezierCurve segment data (controlPoint1, controlPoint2, endPoint)
|
||
* [
|
||
* [20, 20], [40, 20], [50, 10]
|
||
* ],
|
||
* ...
|
||
* ]
|
||
*/
|
||
|
||
/**
|
||
* @description Abstract the curve as a polyline consisting of N points
|
||
* @param {Array} bezierCurve bezierCurve data
|
||
* @param {Number} precision calculation accuracy. Recommended for 1-20. Default = 5
|
||
* @return {Object} Calculation results and related data
|
||
* @return {Array} Option.segmentPoints Point data that constitutes a polyline after calculation
|
||
* @return {Number} Option.cycles Number of iterations
|
||
* @return {Number} Option.rounds The number of recursions for the last iteration
|
||
*/
|
||
|
||
function abstractBezierCurveToPolyline(bezierCurve) {
|
||
var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
|
||
var segmentsNum = bezierCurve.length - 1;
|
||
var startPoint = bezierCurve[0];
|
||
var endPoint = bezierCurve[segmentsNum][2];
|
||
var segments = bezierCurve.slice(1);
|
||
var getSegmentTPointFuns = segments.map(function (seg, i) {
|
||
var beginPoint = i === 0 ? startPoint : segments[i - 1][2];
|
||
return createGetBezierCurveTPointFun.apply(void 0, [beginPoint].concat((0, _toConsumableArray2["default"])(seg)));
|
||
}); // Initialize the curve to a polyline
|
||
|
||
var segmentPointsNum = new Array(segmentsNum).fill(defaultSegmentPointsNum);
|
||
var segmentPoints = getSegmentPointsByNum(getSegmentTPointFuns, segmentPointsNum); // Calculate uniformly distributed points by iteratively
|
||
|
||
var result = calcUniformPointsByIteration(segmentPoints, getSegmentTPointFuns, segments, precision);
|
||
result.segmentPoints.push(endPoint);
|
||
return result;
|
||
}
|
||
/**
|
||
* @description Generate a method for obtaining corresponding point by t according to curve data
|
||
* @param {Array} beginPoint BezierCurve begin point. [x, y]
|
||
* @param {Array} controlPoint1 BezierCurve controlPoint1. [x, y]
|
||
* @param {Array} controlPoint2 BezierCurve controlPoint2. [x, y]
|
||
* @param {Array} endPoint BezierCurve end point. [x, y]
|
||
* @return {Function} Expected function
|
||
*/
|
||
|
||
|
||
function createGetBezierCurveTPointFun(beginPoint, controlPoint1, controlPoint2, endPoint) {
|
||
return function (t) {
|
||
var tSubed1 = 1 - t;
|
||
var tSubed1Pow3 = pow(tSubed1, 3);
|
||
var tSubed1Pow2 = pow(tSubed1, 2);
|
||
var tPow3 = pow(t, 3);
|
||
var tPow2 = pow(t, 2);
|
||
return [beginPoint[0] * tSubed1Pow3 + 3 * controlPoint1[0] * t * tSubed1Pow2 + 3 * controlPoint2[0] * tPow2 * tSubed1 + endPoint[0] * tPow3, beginPoint[1] * tSubed1Pow3 + 3 * controlPoint1[1] * t * tSubed1Pow2 + 3 * controlPoint2[1] * tPow2 * tSubed1 + endPoint[1] * tPow3];
|
||
};
|
||
}
|
||
/**
|
||
* @description Get the distance between two points
|
||
* @param {Array} point1 BezierCurve begin point. [x, y]
|
||
* @param {Array} point2 BezierCurve controlPoint1. [x, y]
|
||
* @return {Number} Expected distance
|
||
*/
|
||
|
||
|
||
function getTwoPointDistance(_ref, _ref2) {
|
||
var _ref3 = (0, _slicedToArray2["default"])(_ref, 2),
|
||
ax = _ref3[0],
|
||
ay = _ref3[1];
|
||
|
||
var _ref4 = (0, _slicedToArray2["default"])(_ref2, 2),
|
||
bx = _ref4[0],
|
||
by = _ref4[1];
|
||
|
||
return sqrt(pow(ax - bx, 2) + pow(ay - by, 2));
|
||
}
|
||
/**
|
||
* @description Get the sum of the array of numbers
|
||
* @param {Array} nums An array of numbers
|
||
* @return {Number} Expected sum
|
||
*/
|
||
|
||
|
||
function getNumsSum(nums) {
|
||
return nums.reduce(function (sum, num) {
|
||
return sum + num;
|
||
}, 0);
|
||
}
|
||
/**
|
||
* @description Get the distance of multiple sets of points
|
||
* @param {Array} segmentPoints Multiple sets of point data
|
||
* @return {Array} Distance of multiple sets of point data
|
||
*/
|
||
|
||
|
||
function getSegmentPointsDistance(segmentPoints) {
|
||
return segmentPoints.map(function (points, i) {
|
||
return new Array(points.length - 1).fill(0).map(function (temp, j) {
|
||
return getTwoPointDistance(points[j], points[j + 1]);
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the distance of multiple sets of points
|
||
* @param {Array} segmentPoints Multiple sets of point data
|
||
* @return {Array} Distance of multiple sets of point data
|
||
*/
|
||
|
||
|
||
function getSegmentPointsByNum(getSegmentTPointFuns, segmentPointsNum) {
|
||
return getSegmentTPointFuns.map(function (getSegmentTPointFun, i) {
|
||
var tGap = 1 / segmentPointsNum[i];
|
||
return new Array(segmentPointsNum[i]).fill('').map(function (foo, j) {
|
||
return getSegmentTPointFun(j * tGap);
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the sum of deviations between line segment and the average length
|
||
* @param {Array} segmentPointsDistance Segment length of polyline
|
||
* @param {Number} avgLength Average length of the line segment
|
||
* @return {Number} Deviations
|
||
*/
|
||
|
||
|
||
function getAllDeviations(segmentPointsDistance, avgLength) {
|
||
return segmentPointsDistance.map(function (seg) {
|
||
return seg.map(function (s) {
|
||
return abs(s - avgLength);
|
||
});
|
||
}).map(function (seg) {
|
||
return getNumsSum(seg);
|
||
}).reduce(function (total, v) {
|
||
return total + v;
|
||
}, 0);
|
||
}
|
||
/**
|
||
* @description Calculate uniformly distributed points by iteratively
|
||
* @param {Array} segmentPoints Multiple setd of points that make up a polyline
|
||
* @param {Array} getSegmentTPointFuns Functions of get a point on the curve with t
|
||
* @param {Array} segments BezierCurve data
|
||
* @param {Number} precision Calculation accuracy
|
||
* @return {Object} Calculation results and related data
|
||
* @return {Array} Option.segmentPoints Point data that constitutes a polyline after calculation
|
||
* @return {Number} Option.cycles Number of iterations
|
||
* @return {Number} Option.rounds The number of recursions for the last iteration
|
||
*/
|
||
|
||
|
||
function calcUniformPointsByIteration(segmentPoints, getSegmentTPointFuns, segments, precision) {
|
||
// The number of loops for the current iteration
|
||
var rounds = 4; // Number of iterations
|
||
|
||
var cycles = 1;
|
||
|
||
var _loop = function _loop() {
|
||
// Recalculate the number of points per curve based on the last iteration data
|
||
var totalPointsNum = segmentPoints.reduce(function (total, seg) {
|
||
return total + seg.length;
|
||
}, 0); // Add last points of segment to calc exact segment length
|
||
|
||
segmentPoints.forEach(function (seg, i) {
|
||
return seg.push(segments[i][2]);
|
||
});
|
||
var segmentPointsDistance = getSegmentPointsDistance(segmentPoints);
|
||
var lineSegmentNum = segmentPointsDistance.reduce(function (total, seg) {
|
||
return total + seg.length;
|
||
}, 0);
|
||
var segmentlength = segmentPointsDistance.map(function (seg) {
|
||
return getNumsSum(seg);
|
||
});
|
||
var totalLength = getNumsSum(segmentlength);
|
||
var avgLength = totalLength / lineSegmentNum; // Check if precision is reached
|
||
|
||
var allDeviations = getAllDeviations(segmentPointsDistance, avgLength);
|
||
if (allDeviations <= precision) return "break";
|
||
totalPointsNum = ceil(avgLength / precision * totalPointsNum * 1.1);
|
||
var segmentPointsNum = segmentlength.map(function (length) {
|
||
return ceil(length / totalLength * totalPointsNum);
|
||
}); // Calculate the points after redistribution
|
||
|
||
segmentPoints = getSegmentPointsByNum(getSegmentTPointFuns, segmentPointsNum);
|
||
totalPointsNum = segmentPoints.reduce(function (total, seg) {
|
||
return total + seg.length;
|
||
}, 0);
|
||
var segmentPointsForLength = JSON.parse(JSON.stringify(segmentPoints));
|
||
segmentPointsForLength.forEach(function (seg, i) {
|
||
return seg.push(segments[i][2]);
|
||
});
|
||
segmentPointsDistance = getSegmentPointsDistance(segmentPointsForLength);
|
||
lineSegmentNum = segmentPointsDistance.reduce(function (total, seg) {
|
||
return total + seg.length;
|
||
}, 0);
|
||
segmentlength = segmentPointsDistance.map(function (seg) {
|
||
return getNumsSum(seg);
|
||
});
|
||
totalLength = getNumsSum(segmentlength);
|
||
avgLength = totalLength / lineSegmentNum;
|
||
var stepSize = 1 / totalPointsNum / 10; // Recursively for each segment of the polyline
|
||
|
||
getSegmentTPointFuns.forEach(function (getSegmentTPointFun, i) {
|
||
var currentSegmentPointsNum = segmentPointsNum[i];
|
||
var t = new Array(currentSegmentPointsNum).fill('').map(function (foo, j) {
|
||
return j / segmentPointsNum[i];
|
||
}); // Repeated recursive offset
|
||
|
||
for (var r = 0; r < rounds; r++) {
|
||
var distance = getSegmentPointsDistance([segmentPoints[i]])[0];
|
||
var deviations = distance.map(function (d) {
|
||
return d - avgLength;
|
||
});
|
||
var offset = 0;
|
||
|
||
for (var j = 0; j < currentSegmentPointsNum; j++) {
|
||
if (j === 0) return;
|
||
offset += deviations[j - 1];
|
||
t[j] -= stepSize * offset;
|
||
if (t[j] > 1) t[j] = 1;
|
||
if (t[j] < 0) t[j] = 0;
|
||
segmentPoints[i][j] = getSegmentTPointFun(t[j]);
|
||
}
|
||
}
|
||
});
|
||
rounds *= 4;
|
||
cycles++;
|
||
};
|
||
|
||
do {
|
||
var _ret = _loop();
|
||
|
||
if (_ret === "break") break;
|
||
} while (rounds <= 1025);
|
||
|
||
segmentPoints = segmentPoints.reduce(function (all, seg) {
|
||
return all.concat(seg);
|
||
}, []);
|
||
return {
|
||
segmentPoints: segmentPoints,
|
||
cycles: cycles,
|
||
rounds: rounds
|
||
};
|
||
}
|
||
/**
|
||
* @description Get the polyline corresponding to the Bezier curve
|
||
* @param {Array} bezierCurve BezierCurve data
|
||
* @param {Number} precision Calculation accuracy. Recommended for 1-20. Default = 5
|
||
* @return {Array|Boolean} Point data that constitutes a polyline after calculation (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function bezierCurveToPolyline(bezierCurve) {
|
||
var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
|
||
|
||
if (!bezierCurve) {
|
||
console.error('bezierCurveToPolyline: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
if (!(bezierCurve instanceof Array)) {
|
||
console.error('bezierCurveToPolyline: Parameter bezierCurve must be an array!');
|
||
return false;
|
||
}
|
||
|
||
if (typeof precision !== 'number') {
|
||
console.error('bezierCurveToPolyline: Parameter precision must be a number!');
|
||
return false;
|
||
}
|
||
|
||
var _abstractBezierCurveT = abstractBezierCurveToPolyline(bezierCurve, precision),
|
||
segmentPoints = _abstractBezierCurveT.segmentPoints;
|
||
|
||
return segmentPoints;
|
||
}
|
||
/**
|
||
* @description Get the bezier curve length
|
||
* @param {Array} bezierCurve bezierCurve data
|
||
* @param {Number} precision calculation accuracy. Recommended for 5-10. Default = 5
|
||
* @return {Number|Boolean} BezierCurve length (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function getBezierCurveLength(bezierCurve) {
|
||
var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
|
||
|
||
if (!bezierCurve) {
|
||
console.error('getBezierCurveLength: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
if (!(bezierCurve instanceof Array)) {
|
||
console.error('getBezierCurveLength: Parameter bezierCurve must be an array!');
|
||
return false;
|
||
}
|
||
|
||
if (typeof precision !== 'number') {
|
||
console.error('getBezierCurveLength: Parameter precision must be a number!');
|
||
return false;
|
||
}
|
||
|
||
var _abstractBezierCurveT2 = abstractBezierCurveToPolyline(bezierCurve, precision),
|
||
segmentPoints = _abstractBezierCurveT2.segmentPoints; // Calculate the total length of the points that make up the polyline
|
||
|
||
|
||
var pointsDistance = getSegmentPointsDistance([segmentPoints])[0];
|
||
var length = getNumsSum(pointsDistance);
|
||
return length;
|
||
}
|
||
|
||
var _default = bezierCurveToPolyline;
|
||
exports["default"] = _default;
|
||
},{"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42}],46:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
/**
|
||
* @description Abstract the polyline formed by N points into a set of bezier curve
|
||
* @param {Array} polyline A set of points that make up a polyline
|
||
* @param {Boolean} close Closed curve
|
||
* @param {Number} offsetA Smoothness
|
||
* @param {Number} offsetB Smoothness
|
||
* @return {Array|Boolean} A set of bezier curve (Invalid input will return false)
|
||
*/
|
||
function polylineToBezierCurve(polyline) {
|
||
var close = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
var offsetA = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.25;
|
||
var offsetB = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.25;
|
||
|
||
if (!(polyline instanceof Array)) {
|
||
console.error('polylineToBezierCurve: Parameter polyline must be an array!');
|
||
return false;
|
||
}
|
||
|
||
if (polyline.length <= 2) {
|
||
console.error('polylineToBezierCurve: Converting to a curve requires at least 3 points!');
|
||
return false;
|
||
}
|
||
|
||
var startPoint = polyline[0];
|
||
var bezierCurveLineNum = polyline.length - 1;
|
||
var bezierCurvePoints = new Array(bezierCurveLineNum).fill(0).map(function (foo, i) {
|
||
return [].concat((0, _toConsumableArray2["default"])(getBezierCurveLineControlPoints(polyline, i, close, offsetA, offsetB)), [polyline[i + 1]]);
|
||
});
|
||
if (close) closeBezierCurve(bezierCurvePoints, startPoint);
|
||
bezierCurvePoints.unshift(polyline[0]);
|
||
return bezierCurvePoints;
|
||
}
|
||
/**
|
||
* @description Get the control points of the Bezier curve
|
||
* @param {Array} polyline A set of points that make up a polyline
|
||
* @param {Number} index The index of which get controls points's point in polyline
|
||
* @param {Boolean} close Closed curve
|
||
* @param {Number} offsetA Smoothness
|
||
* @param {Number} offsetB Smoothness
|
||
* @return {Array} Control points
|
||
*/
|
||
|
||
|
||
function getBezierCurveLineControlPoints(polyline, index) {
|
||
var close = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
var offsetA = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.25;
|
||
var offsetB = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0.25;
|
||
var pointNum = polyline.length;
|
||
if (pointNum < 3 || index >= pointNum) return;
|
||
var beforePointIndex = index - 1;
|
||
if (beforePointIndex < 0) beforePointIndex = close ? pointNum + beforePointIndex : 0;
|
||
var afterPointIndex = index + 1;
|
||
if (afterPointIndex >= pointNum) afterPointIndex = close ? afterPointIndex - pointNum : pointNum - 1;
|
||
var afterNextPointIndex = index + 2;
|
||
if (afterNextPointIndex >= pointNum) afterNextPointIndex = close ? afterNextPointIndex - pointNum : pointNum - 1;
|
||
var pointBefore = polyline[beforePointIndex];
|
||
var pointMiddle = polyline[index];
|
||
var pointAfter = polyline[afterPointIndex];
|
||
var pointAfterNext = polyline[afterNextPointIndex];
|
||
return [[pointMiddle[0] + offsetA * (pointAfter[0] - pointBefore[0]), pointMiddle[1] + offsetA * (pointAfter[1] - pointBefore[1])], [pointAfter[0] - offsetB * (pointAfterNext[0] - pointMiddle[0]), pointAfter[1] - offsetB * (pointAfterNext[1] - pointMiddle[1])]];
|
||
}
|
||
/**
|
||
* @description Get the last curve of the closure
|
||
* @param {Array} bezierCurve A set of sub-curve
|
||
* @param {Array} startPoint Start point
|
||
* @return {Array} The last curve for closure
|
||
*/
|
||
|
||
|
||
function closeBezierCurve(bezierCurve, startPoint) {
|
||
var firstSubCurve = bezierCurve[0];
|
||
var lastSubCurve = bezierCurve.slice(-1)[0];
|
||
bezierCurve.push([getSymmetryPoint(lastSubCurve[1], lastSubCurve[2]), getSymmetryPoint(firstSubCurve[0], startPoint), startPoint]);
|
||
return bezierCurve;
|
||
}
|
||
/**
|
||
* @description Get the symmetry point
|
||
* @param {Array} point Symmetric point
|
||
* @param {Array} centerPoint Symmetric center
|
||
* @return {Array} Symmetric point
|
||
*/
|
||
|
||
|
||
function getSymmetryPoint(point, centerPoint) {
|
||
var _point = (0, _slicedToArray2["default"])(point, 2),
|
||
px = _point[0],
|
||
py = _point[1];
|
||
|
||
var _centerPoint = (0, _slicedToArray2["default"])(centerPoint, 2),
|
||
cx = _centerPoint[0],
|
||
cy = _centerPoint[1];
|
||
|
||
var minusX = cx - px;
|
||
var minusY = cy - py;
|
||
return [cx + minusX, cy + minusY];
|
||
}
|
||
|
||
var _default = polylineToBezierCurve;
|
||
exports["default"] = _default;
|
||
},{"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42}],47:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
Object.defineProperty(exports, "bezierCurveToPolyline", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _bezierCurveToPolyline.bezierCurveToPolyline;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "getBezierCurveLength", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _bezierCurveToPolyline.getBezierCurveLength;
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "polylineToBezierCurve", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _polylineToBezierCurve["default"];
|
||
}
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _bezierCurveToPolyline = require("./core/bezierCurveToPolyline");
|
||
|
||
var _polylineToBezierCurve = _interopRequireDefault(require("./core/polylineToBezierCurve"));
|
||
|
||
var _default = {
|
||
bezierCurveToPolyline: _bezierCurveToPolyline.bezierCurveToPolyline,
|
||
getBezierCurveLength: _bezierCurveToPolyline.getBezierCurveLength,
|
||
polylineToBezierCurve: _polylineToBezierCurve["default"]
|
||
};
|
||
exports["default"] = _default;
|
||
},{"./core/bezierCurveToPolyline":45,"./core/polylineToBezierCurve":46,"@babel/runtime/helpers/interopRequireDefault":36}],48:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
||
|
||
var _color = _interopRequireDefault(require("@jiaminghi/color"));
|
||
|
||
var _bezierCurve = _interopRequireDefault(require("@jiaminghi/bezier-curve"));
|
||
|
||
var _util = require("../plugin/util");
|
||
|
||
var _graphs = _interopRequireDefault(require("../config/graphs"));
|
||
|
||
var _graph = _interopRequireDefault(require("./graph.class"));
|
||
|
||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
||
|
||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
||
|
||
/**
|
||
* @description Class of CRender
|
||
* @param {Object} canvas Canvas DOM
|
||
* @return {CRender} Instance of CRender
|
||
*/
|
||
var CRender = function CRender(canvas) {
|
||
(0, _classCallCheck2["default"])(this, CRender);
|
||
|
||
if (!canvas) {
|
||
console.error('CRender Missing parameters!');
|
||
return;
|
||
}
|
||
|
||
var ctx = canvas.getContext('2d');
|
||
var clientWidth = canvas.clientWidth,
|
||
clientHeight = canvas.clientHeight;
|
||
var area = [clientWidth, clientHeight];
|
||
canvas.setAttribute('width', clientWidth);
|
||
canvas.setAttribute('height', clientHeight);
|
||
/**
|
||
* @description Context of the canvas
|
||
* @type {Object}
|
||
* @example ctx = canvas.getContext('2d')
|
||
*/
|
||
|
||
this.ctx = ctx;
|
||
/**
|
||
* @description Width and height of the canvas
|
||
* @type {Array}
|
||
* @example area = [300,100]
|
||
*/
|
||
|
||
this.area = area;
|
||
/**
|
||
* @description Whether render is in animation rendering
|
||
* @type {Boolean}
|
||
* @example animationStatus = true|false
|
||
*/
|
||
|
||
this.animationStatus = false;
|
||
/**
|
||
* @description Added graph
|
||
* @type {[Graph]}
|
||
* @example graphs = [Graph, Graph, ...]
|
||
*/
|
||
|
||
this.graphs = [];
|
||
/**
|
||
* @description Color plugin
|
||
* @type {Object}
|
||
* @link https://github.com/jiaming743/color
|
||
*/
|
||
|
||
this.color = _color["default"];
|
||
/**
|
||
* @description Bezier Curve plugin
|
||
* @type {Object}
|
||
* @link https://github.com/jiaming743/BezierCurve
|
||
*/
|
||
|
||
this.bezierCurve = _bezierCurve["default"]; // bind event handler
|
||
|
||
canvas.addEventListener('mousedown', mouseDown.bind(this));
|
||
canvas.addEventListener('mousemove', mouseMove.bind(this));
|
||
canvas.addEventListener('mouseup', mouseUp.bind(this));
|
||
};
|
||
/**
|
||
* @description Clear canvas drawing area
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
exports["default"] = CRender;
|
||
|
||
CRender.prototype.clearArea = function () {
|
||
var _this$ctx;
|
||
|
||
var area = this.area;
|
||
|
||
(_this$ctx = this.ctx).clearRect.apply(_this$ctx, [0, 0].concat((0, _toConsumableArray2["default"])(area)));
|
||
};
|
||
/**
|
||
* @description Add graph to render
|
||
* @param {Object} config Graph configuration
|
||
* @return {Graph} Graph instance
|
||
*/
|
||
|
||
|
||
CRender.prototype.add = function () {
|
||
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||
var name = config.name;
|
||
|
||
if (!name) {
|
||
console.error('add Missing parameters!');
|
||
return;
|
||
}
|
||
|
||
var graphConfig = _graphs["default"].get(name);
|
||
|
||
if (!graphConfig) {
|
||
console.warn('No corresponding graph configuration found!');
|
||
return;
|
||
}
|
||
|
||
var graph = new _graph["default"](graphConfig, config);
|
||
if (!graph.validator(graph)) return;
|
||
graph.render = this;
|
||
this.graphs.push(graph);
|
||
this.sortGraphsByIndex();
|
||
this.drawAllGraph();
|
||
return graph;
|
||
};
|
||
/**
|
||
* @description Sort the graph by index
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
CRender.prototype.sortGraphsByIndex = function () {
|
||
var graphs = this.graphs;
|
||
graphs.sort(function (a, b) {
|
||
if (a.index > b.index) return 1;
|
||
if (a.index === b.index) return 0;
|
||
if (a.index < b.index) return -1;
|
||
});
|
||
};
|
||
/**
|
||
* @description Delete graph in render
|
||
* @param {Graph} graph The graph to be deleted
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
CRender.prototype.delGraph = function (graph) {
|
||
if (typeof graph.delProcessor !== 'function') return;
|
||
graph.delProcessor(this);
|
||
this.graphs = this.graphs.filter(function (graph) {
|
||
return graph;
|
||
});
|
||
this.drawAllGraph();
|
||
};
|
||
/**
|
||
* @description Delete all graph in render
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
CRender.prototype.delAllGraph = function () {
|
||
var _this = this;
|
||
|
||
this.graphs.forEach(function (graph) {
|
||
return graph.delProcessor(_this);
|
||
});
|
||
this.graphs = this.graphs.filter(function (graph) {
|
||
return graph;
|
||
});
|
||
this.drawAllGraph();
|
||
};
|
||
/**
|
||
* @description Draw all the graphs in the render
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
CRender.prototype.drawAllGraph = function () {
|
||
var _this2 = this;
|
||
|
||
this.clearArea();
|
||
this.graphs.filter(function (graph) {
|
||
return graph && graph.visible;
|
||
}).forEach(function (graph) {
|
||
return graph.drawProcessor(_this2, graph);
|
||
});
|
||
};
|
||
/**
|
||
* @description Animate the graph whose animation queue is not empty
|
||
* and the animationPause is equal to false
|
||
* @return {Promise} Animation Promise
|
||
*/
|
||
|
||
|
||
CRender.prototype.launchAnimation = function () {
|
||
var _this3 = this;
|
||
|
||
var animationStatus = this.animationStatus;
|
||
if (animationStatus) return;
|
||
this.animationStatus = true;
|
||
return new Promise(function (resolve) {
|
||
animation.call(_this3, function () {
|
||
_this3.animationStatus = false;
|
||
resolve();
|
||
}, Date.now());
|
||
});
|
||
};
|
||
/**
|
||
* @description Try to animate every graph
|
||
* @param {Function} callback Callback in animation end
|
||
* @param {Number} timeStamp Time stamp of animation start
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function animation(callback, timeStamp) {
|
||
var graphs = this.graphs;
|
||
|
||
if (!animationAble(graphs)) {
|
||
callback();
|
||
return;
|
||
}
|
||
|
||
graphs.forEach(function (graph) {
|
||
return graph.turnNextAnimationFrame(timeStamp);
|
||
});
|
||
this.drawAllGraph();
|
||
requestAnimationFrame(animation.bind(this, callback, timeStamp));
|
||
}
|
||
/**
|
||
* @description Find if there are graph that can be animated
|
||
* @param {[Graph]} graphs
|
||
* @return {Boolean}
|
||
*/
|
||
|
||
|
||
function animationAble(graphs) {
|
||
return graphs.find(function (graph) {
|
||
return !graph.animationPause && graph.animationFrameState.length;
|
||
});
|
||
}
|
||
/**
|
||
* @description Handler of CRender mousedown event
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function mouseDown(e) {
|
||
var graphs = this.graphs;
|
||
var hoverGraph = graphs.find(function (graph) {
|
||
return graph.status === 'hover';
|
||
});
|
||
if (!hoverGraph) return;
|
||
hoverGraph.status = 'active';
|
||
}
|
||
/**
|
||
* @description Handler of CRender mousemove event
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function mouseMove(e) {
|
||
var offsetX = e.offsetX,
|
||
offsetY = e.offsetY;
|
||
var position = [offsetX, offsetY];
|
||
var graphs = this.graphs;
|
||
var activeGraph = graphs.find(function (graph) {
|
||
return graph.status === 'active' || graph.status === 'drag';
|
||
});
|
||
|
||
if (activeGraph) {
|
||
if (!activeGraph.drag) return;
|
||
|
||
if (typeof activeGraph.move !== 'function') {
|
||
console.error('No move method is provided, cannot be dragged!');
|
||
return;
|
||
}
|
||
|
||
activeGraph.moveProcessor(e);
|
||
activeGraph.status = 'drag';
|
||
return;
|
||
}
|
||
|
||
var hoverGraph = graphs.find(function (graph) {
|
||
return graph.status === 'hover';
|
||
});
|
||
var hoverAbleGraphs = graphs.filter(function (graph) {
|
||
return graph.hover && (typeof graph.hoverCheck === 'function' || graph.hoverRect);
|
||
});
|
||
var hoveredGraph = hoverAbleGraphs.find(function (graph) {
|
||
return graph.hoverCheckProcessor(position, graph);
|
||
});
|
||
|
||
if (hoveredGraph) {
|
||
document.body.style.cursor = hoveredGraph.style.hoverCursor;
|
||
} else {
|
||
document.body.style.cursor = 'default';
|
||
}
|
||
|
||
var hoverGraphMouseOuterIsFun = false,
|
||
hoveredGraphMouseEnterIsFun = false;
|
||
if (hoverGraph) hoverGraphMouseOuterIsFun = typeof hoverGraph.mouseOuter === 'function';
|
||
if (hoveredGraph) hoveredGraphMouseEnterIsFun = typeof hoveredGraph.mouseEnter === 'function';
|
||
if (!hoveredGraph && !hoverGraph) return;
|
||
|
||
if (!hoveredGraph && hoverGraph) {
|
||
if (hoverGraphMouseOuterIsFun) hoverGraph.mouseOuter(e, hoverGraph);
|
||
hoverGraph.status = 'static';
|
||
return;
|
||
}
|
||
|
||
if (hoveredGraph && hoveredGraph === hoverGraph) return;
|
||
|
||
if (hoveredGraph && !hoverGraph) {
|
||
if (hoveredGraphMouseEnterIsFun) hoveredGraph.mouseEnter(e, hoveredGraph);
|
||
hoveredGraph.status = 'hover';
|
||
return;
|
||
}
|
||
|
||
if (hoveredGraph && hoverGraph && hoveredGraph !== hoverGraph) {
|
||
if (hoverGraphMouseOuterIsFun) hoverGraph.mouseOuter(e, hoverGraph);
|
||
hoverGraph.status = 'static';
|
||
if (hoveredGraphMouseEnterIsFun) hoveredGraph.mouseEnter(e, hoveredGraph);
|
||
hoveredGraph.status = 'hover';
|
||
}
|
||
}
|
||
/**
|
||
* @description Handler of CRender mouseup event
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function mouseUp(e) {
|
||
var graphs = this.graphs;
|
||
var activeGraph = graphs.find(function (graph) {
|
||
return graph.status === 'active';
|
||
});
|
||
var dragGraph = graphs.find(function (graph) {
|
||
return graph.status === 'drag';
|
||
});
|
||
if (activeGraph && typeof activeGraph.click === 'function') activeGraph.click(e, activeGraph);
|
||
graphs.forEach(function (graph) {
|
||
return graph && (graph.status = 'static');
|
||
});
|
||
if (activeGraph) activeGraph.status = 'hover';
|
||
if (dragGraph) dragGraph.status = 'hover';
|
||
}
|
||
/**
|
||
* @description Clone Graph
|
||
* @param {Graph} graph The target to be cloned
|
||
* @return {Graph} Cloned graph
|
||
*/
|
||
|
||
|
||
CRender.prototype.clone = function (graph) {
|
||
var style = graph.style.getStyle();
|
||
|
||
var clonedGraph = _objectSpread({}, graph, {
|
||
style: style
|
||
});
|
||
|
||
delete clonedGraph.render;
|
||
clonedGraph = (0, _util.deepClone)(clonedGraph, true);
|
||
return this.add(clonedGraph);
|
||
};
|
||
},{"../config/graphs":51,"../plugin/util":54,"./graph.class":49,"@babel/runtime/helpers/classCallCheck":34,"@babel/runtime/helpers/defineProperty":35,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@jiaminghi/bezier-curve":47,"@jiaminghi/color":56}],49:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
||
|
||
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
||
|
||
var _style = _interopRequireDefault(require("./style.class"));
|
||
|
||
var _transition = _interopRequireDefault(require("@jiaminghi/transition"));
|
||
|
||
var _util = require("../plugin/util");
|
||
|
||
/**
|
||
* @description Class Graph
|
||
* @param {Object} graph Graph default configuration
|
||
* @param {Object} config Graph config
|
||
* @return {Graph} Instance of Graph
|
||
*/
|
||
var Graph = function Graph(graph, config) {
|
||
(0, _classCallCheck2["default"])(this, Graph);
|
||
config = (0, _util.deepClone)(config, true);
|
||
var defaultConfig = {
|
||
/**
|
||
* @description Weather to render graph
|
||
* @type {Boolean}
|
||
* @default visible = true
|
||
*/
|
||
visible: true,
|
||
|
||
/**
|
||
* @description Whether to enable drag
|
||
* @type {Boolean}
|
||
* @default drag = false
|
||
*/
|
||
drag: false,
|
||
|
||
/**
|
||
* @description Whether to enable hover
|
||
* @type {Boolean}
|
||
* @default hover = false
|
||
*/
|
||
hover: false,
|
||
|
||
/**
|
||
* @description Graph rendering index
|
||
* Give priority to index high graph in rendering
|
||
* @type {Number}
|
||
* @example index = 1
|
||
*/
|
||
index: 1,
|
||
|
||
/**
|
||
* @description Animation delay time(ms)
|
||
* @type {Number}
|
||
* @default animationDelay = 0
|
||
*/
|
||
animationDelay: 0,
|
||
|
||
/**
|
||
* @description Number of animation frames
|
||
* @type {Number}
|
||
* @default animationFrame = 30
|
||
*/
|
||
animationFrame: 30,
|
||
|
||
/**
|
||
* @description Animation dynamic curve (Supported by transition)
|
||
* @type {String}
|
||
* @default animationCurve = 'linear'
|
||
* @link https://github.com/jiaming743/Transition
|
||
*/
|
||
animationCurve: 'linear',
|
||
|
||
/**
|
||
* @description Weather to pause graph animation
|
||
* @type {Boolean}
|
||
* @default animationPause = false
|
||
*/
|
||
animationPause: false,
|
||
|
||
/**
|
||
* @description Rectangular hover detection zone
|
||
* Use this method for hover detection first
|
||
* @type {Null|Array}
|
||
* @default hoverRect = null
|
||
* @example hoverRect = [0, 0, 100, 100] // [Rect start x, y, Rect width, height]
|
||
*/
|
||
hoverRect: null,
|
||
|
||
/**
|
||
* @description Mouse enter event handler
|
||
* @type {Function|Null}
|
||
* @default mouseEnter = null
|
||
*/
|
||
mouseEnter: null,
|
||
|
||
/**
|
||
* @description Mouse outer event handler
|
||
* @type {Function|Null}
|
||
* @default mouseOuter = null
|
||
*/
|
||
mouseOuter: null,
|
||
|
||
/**
|
||
* @description Mouse click event handler
|
||
* @type {Function|Null}
|
||
* @default click = null
|
||
*/
|
||
click: null
|
||
};
|
||
var configAbleNot = {
|
||
status: 'static',
|
||
animationRoot: [],
|
||
animationKeys: [],
|
||
animationFrameState: [],
|
||
cache: {}
|
||
};
|
||
if (!config.shape) config.shape = {};
|
||
if (!config.style) config.style = {};
|
||
var shape = Object.assign({}, graph.shape, config.shape);
|
||
Object.assign(defaultConfig, config, configAbleNot);
|
||
Object.assign(this, graph, defaultConfig);
|
||
this.shape = shape;
|
||
this.style = new _style["default"](config.style);
|
||
this.addedProcessor();
|
||
};
|
||
/**
|
||
* @description Processor of added
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
exports["default"] = Graph;
|
||
|
||
Graph.prototype.addedProcessor = function () {
|
||
if (typeof this.setGraphCenter === 'function') this.setGraphCenter(null, this); // The life cycle 'added"
|
||
|
||
if (typeof this.added === 'function') this.added(this);
|
||
};
|
||
/**
|
||
* @description Processor of draw
|
||
* @param {CRender} render Instance of CRender
|
||
* @param {Graph} graph Instance of Graph
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.drawProcessor = function (render, graph) {
|
||
var ctx = render.ctx;
|
||
graph.style.initStyle(ctx);
|
||
if (typeof this.beforeDraw === 'function') this.beforeDraw(this, render);
|
||
graph.draw(render, graph);
|
||
if (typeof this.drawed === 'function') this.drawed(this, render);
|
||
graph.style.restoreTransform(ctx);
|
||
};
|
||
/**
|
||
* @description Processor of hover check
|
||
* @param {Array} position Mouse Position
|
||
* @param {Graph} graph Instance of Graph
|
||
* @return {Boolean} Result of hover check
|
||
*/
|
||
|
||
|
||
Graph.prototype.hoverCheckProcessor = function (position, _ref) {
|
||
var hoverRect = _ref.hoverRect,
|
||
style = _ref.style,
|
||
hoverCheck = _ref.hoverCheck;
|
||
var graphCenter = style.graphCenter,
|
||
rotate = style.rotate,
|
||
scale = style.scale,
|
||
translate = style.translate;
|
||
|
||
if (graphCenter) {
|
||
if (rotate) position = (0, _util.getRotatePointPos)(-rotate, position, graphCenter);
|
||
if (scale) position = (0, _util.getScalePointPos)(scale.map(function (s) {
|
||
return 1 / s;
|
||
}), position, graphCenter);
|
||
if (translate) position = (0, _util.getTranslatePointPos)(translate.map(function (v) {
|
||
return v * -1;
|
||
}), position);
|
||
}
|
||
|
||
if (hoverRect) return _util.checkPointIsInRect.apply(void 0, [position].concat((0, _toConsumableArray2["default"])(hoverRect)));
|
||
return hoverCheck(position, this);
|
||
};
|
||
/**
|
||
* @description Processor of move
|
||
* @param {Event} e Mouse movement event
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.moveProcessor = function (e) {
|
||
this.move(e, this);
|
||
if (typeof this.beforeMove === 'function') this.beforeMove(e, this);
|
||
if (typeof this.setGraphCenter === 'function') this.setGraphCenter(e, this);
|
||
if (typeof this.moved === 'function') this.moved(e, this);
|
||
};
|
||
/**
|
||
* @description Update graph state
|
||
* @param {String} attrName Updated attribute name
|
||
* @param {Any} change Updated value
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.attr = function (attrName) {
|
||
var change = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
|
||
if (!attrName || change === undefined) return false;
|
||
var isObject = (0, _typeof2["default"])(this[attrName]) === 'object';
|
||
if (isObject) change = (0, _util.deepClone)(change, true);
|
||
var render = this.render;
|
||
|
||
if (attrName === 'style') {
|
||
this.style.update(change);
|
||
} else if (isObject) {
|
||
Object.assign(this[attrName], change);
|
||
} else {
|
||
this[attrName] = change;
|
||
}
|
||
|
||
if (attrName === 'index') render.sortGraphsByIndex();
|
||
render.drawAllGraph();
|
||
};
|
||
/**
|
||
* @description Update graphics state (with animation)
|
||
* Only shape and style attributes are supported
|
||
* @param {String} attrName Updated attribute name
|
||
* @param {Any} change Updated value
|
||
* @param {Boolean} wait Whether to store the animation waiting
|
||
* for the next animation request
|
||
* @return {Promise} Animation Promise
|
||
*/
|
||
|
||
|
||
Graph.prototype.animation =
|
||
/*#__PURE__*/
|
||
function () {
|
||
var _ref2 = (0, _asyncToGenerator2["default"])(
|
||
/*#__PURE__*/
|
||
_regenerator["default"].mark(function _callee2(attrName, change) {
|
||
var wait,
|
||
changeRoot,
|
||
changeKeys,
|
||
beforeState,
|
||
animationFrame,
|
||
animationCurve,
|
||
animationDelay,
|
||
animationFrameState,
|
||
render,
|
||
_args2 = arguments;
|
||
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
||
while (1) {
|
||
switch (_context2.prev = _context2.next) {
|
||
case 0:
|
||
wait = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : false;
|
||
|
||
if (!(attrName !== 'shape' && attrName !== 'style')) {
|
||
_context2.next = 4;
|
||
break;
|
||
}
|
||
|
||
console.error('Only supported shape and style animation!');
|
||
return _context2.abrupt("return");
|
||
|
||
case 4:
|
||
change = (0, _util.deepClone)(change, true);
|
||
if (attrName === 'style') this.style.colorProcessor(change);
|
||
changeRoot = this[attrName];
|
||
changeKeys = Object.keys(change);
|
||
beforeState = {};
|
||
changeKeys.forEach(function (key) {
|
||
return beforeState[key] = changeRoot[key];
|
||
});
|
||
animationFrame = this.animationFrame, animationCurve = this.animationCurve, animationDelay = this.animationDelay;
|
||
animationFrameState = (0, _transition["default"])(animationCurve, beforeState, change, animationFrame, true);
|
||
this.animationRoot.push(changeRoot);
|
||
this.animationKeys.push(changeKeys);
|
||
this.animationFrameState.push(animationFrameState);
|
||
|
||
if (!wait) {
|
||
_context2.next = 17;
|
||
break;
|
||
}
|
||
|
||
return _context2.abrupt("return");
|
||
|
||
case 17:
|
||
if (!(animationDelay > 0)) {
|
||
_context2.next = 20;
|
||
break;
|
||
}
|
||
|
||
_context2.next = 20;
|
||
return delay(animationDelay);
|
||
|
||
case 20:
|
||
render = this.render;
|
||
return _context2.abrupt("return", new Promise(
|
||
/*#__PURE__*/
|
||
function () {
|
||
var _ref3 = (0, _asyncToGenerator2["default"])(
|
||
/*#__PURE__*/
|
||
_regenerator["default"].mark(function _callee(resolve) {
|
||
return _regenerator["default"].wrap(function _callee$(_context) {
|
||
while (1) {
|
||
switch (_context.prev = _context.next) {
|
||
case 0:
|
||
_context.next = 2;
|
||
return render.launchAnimation();
|
||
|
||
case 2:
|
||
resolve();
|
||
|
||
case 3:
|
||
case "end":
|
||
return _context.stop();
|
||
}
|
||
}
|
||
}, _callee);
|
||
}));
|
||
|
||
return function (_x3) {
|
||
return _ref3.apply(this, arguments);
|
||
};
|
||
}()));
|
||
|
||
case 22:
|
||
case "end":
|
||
return _context2.stop();
|
||
}
|
||
}
|
||
}, _callee2, this);
|
||
}));
|
||
|
||
return function (_x, _x2) {
|
||
return _ref2.apply(this, arguments);
|
||
};
|
||
}();
|
||
/**
|
||
* @description Extract the next frame of data from the animation queue
|
||
* and update the graph state
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.turnNextAnimationFrame = function (timeStamp) {
|
||
var animationDelay = this.animationDelay,
|
||
animationRoot = this.animationRoot,
|
||
animationKeys = this.animationKeys,
|
||
animationFrameState = this.animationFrameState,
|
||
animationPause = this.animationPause;
|
||
if (animationPause) return;
|
||
if (Date.now() - timeStamp < animationDelay) return;
|
||
animationRoot.forEach(function (root, i) {
|
||
animationKeys[i].forEach(function (key) {
|
||
root[key] = animationFrameState[i][0][key];
|
||
});
|
||
});
|
||
animationFrameState.forEach(function (stateItem, i) {
|
||
stateItem.shift();
|
||
var noFrame = stateItem.length === 0;
|
||
if (noFrame) animationRoot[i] = null;
|
||
if (noFrame) animationKeys[i] = null;
|
||
});
|
||
this.animationFrameState = animationFrameState.filter(function (state) {
|
||
return state.length;
|
||
});
|
||
this.animationRoot = animationRoot.filter(function (root) {
|
||
return root;
|
||
});
|
||
this.animationKeys = animationKeys.filter(function (keys) {
|
||
return keys;
|
||
});
|
||
};
|
||
/**
|
||
* @description Skip to the last frame of animation
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.animationEnd = function () {
|
||
var animationFrameState = this.animationFrameState,
|
||
animationKeys = this.animationKeys,
|
||
animationRoot = this.animationRoot,
|
||
render = this.render;
|
||
animationRoot.forEach(function (root, i) {
|
||
var currentKeys = animationKeys[i];
|
||
var lastState = animationFrameState[i].pop();
|
||
currentKeys.forEach(function (key) {
|
||
return root[key] = lastState[key];
|
||
});
|
||
});
|
||
this.animationFrameState = [];
|
||
this.animationKeys = [];
|
||
this.animationRoot = [];
|
||
return render.drawAllGraph();
|
||
};
|
||
/**
|
||
* @description Pause animation behavior
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.pauseAnimation = function () {
|
||
this.attr('animationPause', true);
|
||
};
|
||
/**
|
||
* @description Try animation behavior
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.playAnimation = function () {
|
||
var render = this.render;
|
||
this.attr('animationPause', false);
|
||
return new Promise(
|
||
/*#__PURE__*/
|
||
function () {
|
||
var _ref4 = (0, _asyncToGenerator2["default"])(
|
||
/*#__PURE__*/
|
||
_regenerator["default"].mark(function _callee3(resolve) {
|
||
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
||
while (1) {
|
||
switch (_context3.prev = _context3.next) {
|
||
case 0:
|
||
_context3.next = 2;
|
||
return render.launchAnimation();
|
||
|
||
case 2:
|
||
resolve();
|
||
|
||
case 3:
|
||
case "end":
|
||
return _context3.stop();
|
||
}
|
||
}
|
||
}, _callee3);
|
||
}));
|
||
|
||
return function (_x4) {
|
||
return _ref4.apply(this, arguments);
|
||
};
|
||
}());
|
||
};
|
||
/**
|
||
* @description Processor of delete
|
||
* @param {CRender} render Instance of CRender
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Graph.prototype.delProcessor = function (render) {
|
||
var _this = this;
|
||
|
||
var graphs = render.graphs;
|
||
var index = graphs.findIndex(function (graph) {
|
||
return graph === _this;
|
||
});
|
||
if (index === -1) return;
|
||
if (typeof this.beforeDelete === 'function') this.beforeDelete(this);
|
||
graphs.splice(index, 1, null);
|
||
if (typeof this.deleted === 'function') this.deleted(this);
|
||
};
|
||
/**
|
||
* @description Return a timed release Promise
|
||
* @param {Number} time Release time
|
||
* @return {Promise} A timed release Promise
|
||
*/
|
||
|
||
|
||
function delay(time) {
|
||
return new Promise(function (resolve) {
|
||
setTimeout(resolve, time);
|
||
});
|
||
}
|
||
},{"../plugin/util":54,"./style.class":50,"@babel/runtime/helpers/asyncToGenerator":33,"@babel/runtime/helpers/classCallCheck":34,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43,"@babel/runtime/regenerator":44,"@jiaminghi/transition":58}],50:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
||
|
||
var _color = require("@jiaminghi/color");
|
||
|
||
var _util = require("../plugin/util");
|
||
|
||
/**
|
||
* @description Class Style
|
||
* @param {Object} style Style configuration
|
||
* @return {Style} Instance of Style
|
||
*/
|
||
var Style = function Style(style) {
|
||
(0, _classCallCheck2["default"])(this, Style);
|
||
this.colorProcessor(style);
|
||
var defaultStyle = {
|
||
/**
|
||
* @description Rgba value of graph fill color
|
||
* @type {Array}
|
||
* @default fill = [0, 0, 0, 1]
|
||
*/
|
||
fill: [0, 0, 0, 1],
|
||
|
||
/**
|
||
* @description Rgba value of graph stroke color
|
||
* @type {Array}
|
||
* @default stroke = [0, 0, 0, 1]
|
||
*/
|
||
stroke: [0, 0, 0, 0],
|
||
|
||
/**
|
||
* @description Opacity of graph
|
||
* @type {Number}
|
||
* @default opacity = 1
|
||
*/
|
||
opacity: 1,
|
||
|
||
/**
|
||
* @description LineCap of Ctx
|
||
* @type {String}
|
||
* @default lineCap = null
|
||
* @example lineCap = 'butt'|'round'|'square'
|
||
*/
|
||
lineCap: null,
|
||
|
||
/**
|
||
* @description Linejoin of Ctx
|
||
* @type {String}
|
||
* @default lineJoin = null
|
||
* @example lineJoin = 'round'|'bevel'|'miter'
|
||
*/
|
||
lineJoin: null,
|
||
|
||
/**
|
||
* @description LineDash of Ctx
|
||
* @type {Array}
|
||
* @default lineDash = null
|
||
* @example lineDash = [10, 10]
|
||
*/
|
||
lineDash: null,
|
||
|
||
/**
|
||
* @description LineDashOffset of Ctx
|
||
* @type {Number}
|
||
* @default lineDashOffset = null
|
||
* @example lineDashOffset = 10
|
||
*/
|
||
lineDashOffset: null,
|
||
|
||
/**
|
||
* @description ShadowBlur of Ctx
|
||
* @type {Number}
|
||
* @default shadowBlur = 0
|
||
*/
|
||
shadowBlur: 0,
|
||
|
||
/**
|
||
* @description Rgba value of graph shadow color
|
||
* @type {Array}
|
||
* @default shadowColor = [0, 0, 0, 0]
|
||
*/
|
||
shadowColor: [0, 0, 0, 0],
|
||
|
||
/**
|
||
* @description ShadowOffsetX of Ctx
|
||
* @type {Number}
|
||
* @default shadowOffsetX = 0
|
||
*/
|
||
shadowOffsetX: 0,
|
||
|
||
/**
|
||
* @description ShadowOffsetY of Ctx
|
||
* @type {Number}
|
||
* @default shadowOffsetY = 0
|
||
*/
|
||
shadowOffsetY: 0,
|
||
|
||
/**
|
||
* @description LineWidth of Ctx
|
||
* @type {Number}
|
||
* @default lineWidth = 0
|
||
*/
|
||
lineWidth: 0,
|
||
|
||
/**
|
||
* @description Center point of the graph
|
||
* @type {Array}
|
||
* @default graphCenter = null
|
||
* @example graphCenter = [10, 10]
|
||
*/
|
||
graphCenter: null,
|
||
|
||
/**
|
||
* @description Graph scale
|
||
* @type {Array}
|
||
* @default scale = null
|
||
* @example scale = [1.5, 1.5]
|
||
*/
|
||
scale: null,
|
||
|
||
/**
|
||
* @description Graph rotation degree
|
||
* @type {Number}
|
||
* @default rotate = null
|
||
* @example rotate = 10
|
||
*/
|
||
rotate: null,
|
||
|
||
/**
|
||
* @description Graph translate distance
|
||
* @type {Array}
|
||
* @default translate = null
|
||
* @example translate = [10, 10]
|
||
*/
|
||
translate: null,
|
||
|
||
/**
|
||
* @description Cursor status when hover
|
||
* @type {String}
|
||
* @default hoverCursor = 'pointer'
|
||
* @example hoverCursor = 'default'|'pointer'|'auto'|'crosshair'|'move'|'wait'|...
|
||
*/
|
||
hoverCursor: 'pointer',
|
||
|
||
/**
|
||
* @description Font style of Ctx
|
||
* @type {String}
|
||
* @default fontStyle = 'normal'
|
||
* @example fontStyle = 'normal'|'italic'|'oblique'
|
||
*/
|
||
fontStyle: 'normal',
|
||
|
||
/**
|
||
* @description Font varient of Ctx
|
||
* @type {String}
|
||
* @default fontVarient = 'normal'
|
||
* @example fontVarient = 'normal'|'small-caps'
|
||
*/
|
||
fontVarient: 'normal',
|
||
|
||
/**
|
||
* @description Font weight of Ctx
|
||
* @type {String|Number}
|
||
* @default fontWeight = 'normal'
|
||
* @example fontWeight = 'normal'|'bold'|'bolder'|'lighter'|Number
|
||
*/
|
||
fontWeight: 'normal',
|
||
|
||
/**
|
||
* @description Font size of Ctx
|
||
* @type {Number}
|
||
* @default fontSize = 10
|
||
*/
|
||
fontSize: 10,
|
||
|
||
/**
|
||
* @description Font family of Ctx
|
||
* @type {String}
|
||
* @default fontFamily = 'Arial'
|
||
*/
|
||
fontFamily: 'Arial',
|
||
|
||
/**
|
||
* @description TextAlign of Ctx
|
||
* @type {String}
|
||
* @default textAlign = 'center'
|
||
* @example textAlign = 'start'|'end'|'left'|'right'|'center'
|
||
*/
|
||
textAlign: 'center',
|
||
|
||
/**
|
||
* @description TextBaseline of Ctx
|
||
* @type {String}
|
||
* @default textBaseline = 'middle'
|
||
* @example textBaseline = 'top'|'bottom'|'middle'|'alphabetic'|'hanging'
|
||
*/
|
||
textBaseline: 'middle',
|
||
|
||
/**
|
||
* @description The color used to create the gradient
|
||
* @type {Array}
|
||
* @default gradientColor = null
|
||
* @example gradientColor = ['#000', '#111', '#222']
|
||
*/
|
||
gradientColor: null,
|
||
|
||
/**
|
||
* @description Gradient type
|
||
* @type {String}
|
||
* @default gradientType = 'linear'
|
||
* @example gradientType = 'linear' | 'radial'
|
||
*/
|
||
gradientType: 'linear',
|
||
|
||
/**
|
||
* @description Gradient params
|
||
* @type {Array}
|
||
* @default gradientParams = null
|
||
* @example gradientParams = [x0, y0, x1, y1] (Linear Gradient)
|
||
* @example gradientParams = [x0, y0, r0, x1, y1, r1] (Radial Gradient)
|
||
*/
|
||
gradientParams: null,
|
||
|
||
/**
|
||
* @description When to use gradients
|
||
* @type {String}
|
||
* @default gradientWith = 'stroke'
|
||
* @example gradientWith = 'stroke' | 'fill'
|
||
*/
|
||
gradientWith: 'stroke',
|
||
|
||
/**
|
||
* @description Gradient color stops
|
||
* @type {String}
|
||
* @default gradientStops = 'auto'
|
||
* @example gradientStops = 'auto' | [0, .2, .3, 1]
|
||
*/
|
||
gradientStops: 'auto',
|
||
|
||
/**
|
||
* @description Extended color that supports animation transition
|
||
* @type {Array|Object}
|
||
* @default colors = null
|
||
* @example colors = ['#000', '#111', '#222', 'red' ]
|
||
* @example colors = { a: '#000', b: '#111' }
|
||
*/
|
||
colors: null
|
||
};
|
||
Object.assign(this, defaultStyle, style);
|
||
};
|
||
/**
|
||
* @description Set colors to rgba value
|
||
* @param {Object} style style config
|
||
* @param {Boolean} reverse Whether to perform reverse operation
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
exports["default"] = Style;
|
||
|
||
Style.prototype.colorProcessor = function (style) {
|
||
var reverse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
var processor = reverse ? _color.getColorFromRgbValue : _color.getRgbaValue;
|
||
var colorProcessorKeys = ['fill', 'stroke', 'shadowColor'];
|
||
var allKeys = Object.keys(style);
|
||
var colorKeys = allKeys.filter(function (key) {
|
||
return colorProcessorKeys.find(function (k) {
|
||
return k === key;
|
||
});
|
||
});
|
||
colorKeys.forEach(function (key) {
|
||
return style[key] = processor(style[key]);
|
||
});
|
||
var gradientColor = style.gradientColor,
|
||
colors = style.colors;
|
||
if (gradientColor) style.gradientColor = gradientColor.map(function (c) {
|
||
return processor(c);
|
||
});
|
||
|
||
if (colors) {
|
||
var colorsKeys = Object.keys(colors);
|
||
colorsKeys.forEach(function (key) {
|
||
return colors[key] = processor(colors[key]);
|
||
});
|
||
}
|
||
};
|
||
/**
|
||
* @description Init graph style
|
||
* @param {Object} ctx Context of canvas
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Style.prototype.initStyle = function (ctx) {
|
||
initTransform(ctx, this);
|
||
initGraphStyle(ctx, this);
|
||
initGradient(ctx, this);
|
||
};
|
||
/**
|
||
* @description Init canvas transform
|
||
* @param {Object} ctx Context of canvas
|
||
* @param {Style} style Instance of Style
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function initTransform(ctx, style) {
|
||
ctx.save();
|
||
var graphCenter = style.graphCenter,
|
||
rotate = style.rotate,
|
||
scale = style.scale,
|
||
translate = style.translate;
|
||
if (!(graphCenter instanceof Array)) return;
|
||
ctx.translate.apply(ctx, (0, _toConsumableArray2["default"])(graphCenter));
|
||
if (rotate) ctx.rotate(rotate * Math.PI / 180);
|
||
if (scale instanceof Array) ctx.scale.apply(ctx, (0, _toConsumableArray2["default"])(scale));
|
||
if (translate) ctx.translate.apply(ctx, (0, _toConsumableArray2["default"])(translate));
|
||
ctx.translate(-graphCenter[0], -graphCenter[1]);
|
||
}
|
||
|
||
var autoSetStyleKeys = ['lineCap', 'lineJoin', 'lineDashOffset', 'shadowOffsetX', 'shadowOffsetY', 'lineWidth', 'textAlign', 'textBaseline'];
|
||
/**
|
||
* @description Set the style of canvas ctx
|
||
* @param {Object} ctx Context of canvas
|
||
* @param {Style} style Instance of Style
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
function initGraphStyle(ctx, style) {
|
||
var fill = style.fill,
|
||
stroke = style.stroke,
|
||
shadowColor = style.shadowColor,
|
||
opacity = style.opacity;
|
||
autoSetStyleKeys.forEach(function (key) {
|
||
if (key || typeof key === 'number') ctx[key] = style[key];
|
||
});
|
||
fill = (0, _toConsumableArray2["default"])(fill);
|
||
stroke = (0, _toConsumableArray2["default"])(stroke);
|
||
shadowColor = (0, _toConsumableArray2["default"])(shadowColor);
|
||
fill[3] *= opacity;
|
||
stroke[3] *= opacity;
|
||
shadowColor[3] *= opacity;
|
||
ctx.fillStyle = (0, _color.getColorFromRgbValue)(fill);
|
||
ctx.strokeStyle = (0, _color.getColorFromRgbValue)(stroke);
|
||
ctx.shadowColor = (0, _color.getColorFromRgbValue)(shadowColor);
|
||
var lineDash = style.lineDash,
|
||
shadowBlur = style.shadowBlur;
|
||
|
||
if (lineDash) {
|
||
lineDash = lineDash.map(function (v) {
|
||
return v >= 0 ? v : 0;
|
||
});
|
||
ctx.setLineDash(lineDash);
|
||
}
|
||
|
||
if (typeof shadowBlur === 'number') ctx.shadowBlur = shadowBlur > 0 ? shadowBlur : 0.001;
|
||
var fontStyle = style.fontStyle,
|
||
fontVarient = style.fontVarient,
|
||
fontWeight = style.fontWeight,
|
||
fontSize = style.fontSize,
|
||
fontFamily = style.fontFamily;
|
||
ctx.font = fontStyle + ' ' + fontVarient + ' ' + fontWeight + ' ' + fontSize + 'px' + ' ' + fontFamily;
|
||
}
|
||
/**
|
||
* @description Set the gradient color of canvas ctx
|
||
* @param {Object} ctx Context of canvas
|
||
* @param {Style} style Instance of Style
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function initGradient(ctx, style) {
|
||
if (!gradientValidator(style)) return;
|
||
var gradientColor = style.gradientColor,
|
||
gradientParams = style.gradientParams,
|
||
gradientType = style.gradientType,
|
||
gradientWith = style.gradientWith,
|
||
gradientStops = style.gradientStops,
|
||
opacity = style.opacity;
|
||
gradientColor = gradientColor.map(function (color) {
|
||
var colorOpacity = color[3] * opacity;
|
||
var clonedColor = (0, _toConsumableArray2["default"])(color);
|
||
clonedColor[3] = colorOpacity;
|
||
return clonedColor;
|
||
});
|
||
gradientColor = gradientColor.map(function (c) {
|
||
return (0, _color.getColorFromRgbValue)(c);
|
||
});
|
||
if (gradientStops === 'auto') gradientStops = getAutoColorStops(gradientColor);
|
||
var gradient = ctx["create".concat(gradientType.slice(0, 1).toUpperCase() + gradientType.slice(1), "Gradient")].apply(ctx, (0, _toConsumableArray2["default"])(gradientParams));
|
||
gradientStops.forEach(function (stop, i) {
|
||
return gradient.addColorStop(stop, gradientColor[i]);
|
||
});
|
||
ctx["".concat(gradientWith, "Style")] = gradient;
|
||
}
|
||
/**
|
||
* @description Check if the gradient configuration is legal
|
||
* @param {Style} style Instance of Style
|
||
* @return {Boolean} Check Result
|
||
*/
|
||
|
||
|
||
function gradientValidator(style) {
|
||
var gradientColor = style.gradientColor,
|
||
gradientParams = style.gradientParams,
|
||
gradientType = style.gradientType,
|
||
gradientWith = style.gradientWith,
|
||
gradientStops = style.gradientStops;
|
||
if (!gradientColor || !gradientParams) return false;
|
||
|
||
if (gradientColor.length === 1) {
|
||
console.warn('The gradient needs to provide at least two colors');
|
||
return false;
|
||
}
|
||
|
||
if (gradientType !== 'linear' && gradientType !== 'radial') {
|
||
console.warn('GradientType only supports linear or radial, current value is ' + gradientType);
|
||
return false;
|
||
}
|
||
|
||
var gradientParamsLength = gradientParams.length;
|
||
|
||
if (gradientType === 'linear' && gradientParamsLength !== 4 || gradientType === 'radial' && gradientParamsLength !== 6) {
|
||
console.warn('The expected length of gradientParams is ' + (gradientType === 'linear' ? '4' : '6'));
|
||
return false;
|
||
}
|
||
|
||
if (gradientWith !== 'fill' && gradientWith !== 'stroke') {
|
||
console.warn('GradientWith only supports fill or stroke, current value is ' + gradientWith);
|
||
return false;
|
||
}
|
||
|
||
if (gradientStops !== 'auto' && !(gradientStops instanceof Array)) {
|
||
console.warn("gradientStops only supports 'auto' or Number Array ([0, .5, 1]), current value is " + gradientStops);
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
/**
|
||
* @description Get a uniform gradient color stop
|
||
* @param {Array} color Gradient color
|
||
* @return {Array} Gradient color stop
|
||
*/
|
||
|
||
|
||
function getAutoColorStops(color) {
|
||
var stopGap = 1 / (color.length - 1);
|
||
return color.map(function (foo, i) {
|
||
return stopGap * i;
|
||
});
|
||
}
|
||
/**
|
||
* @description Restore canvas ctx transform
|
||
* @param {Object} ctx Context of canvas
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Style.prototype.restoreTransform = function (ctx) {
|
||
ctx.restore();
|
||
};
|
||
/**
|
||
* @description Update style data
|
||
* @param {Object} change Changed data
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
Style.prototype.update = function (change) {
|
||
this.colorProcessor(change);
|
||
Object.assign(this, change);
|
||
};
|
||
/**
|
||
* @description Get the current style configuration
|
||
* @return {Object} Style configuration
|
||
*/
|
||
|
||
|
||
Style.prototype.getStyle = function () {
|
||
var clonedStyle = (0, _util.deepClone)(this, true);
|
||
this.colorProcessor(clonedStyle, true);
|
||
return clonedStyle;
|
||
};
|
||
},{"../plugin/util":54,"@babel/runtime/helpers/classCallCheck":34,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42,"@jiaminghi/color":56}],51:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.extendNewGraph = extendNewGraph;
|
||
exports["default"] = exports.text = exports.bezierCurve = exports.smoothline = exports.polyline = exports.regPolygon = exports.sector = exports.arc = exports.ring = exports.rect = exports.ellipse = exports.circle = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _bezierCurve2 = _interopRequireDefault(require("@jiaminghi/bezier-curve"));
|
||
|
||
var _util = require("../plugin/util");
|
||
|
||
var _canvas = require("../plugin/canvas");
|
||
|
||
var polylineToBezierCurve = _bezierCurve2["default"].polylineToBezierCurve,
|
||
bezierCurveToPolyline = _bezierCurve2["default"].bezierCurveToPolyline;
|
||
var circle = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0
|
||
},
|
||
validator: function validator(_ref) {
|
||
var shape = _ref.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
|
||
if (typeof rx !== 'number' || typeof ry !== 'number' || typeof r !== 'number') {
|
||
console.error('Circle shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref2, _ref3) {
|
||
var ctx = _ref2.ctx;
|
||
var shape = _ref3.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
ctx.arc(rx, ry, r > 0 ? r : 0.01, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref4) {
|
||
var shape = _ref4.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
return (0, _util.checkPointIsInCircle)(position, rx, ry, r);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref5) {
|
||
var shape = _ref5.shape,
|
||
style = _ref5.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref6, _ref7) {
|
||
var movementX = _ref6.movementX,
|
||
movementY = _ref6.movementY;
|
||
var shape = _ref7.shape;
|
||
this.attr('shape', {
|
||
rx: shape.rx + movementX,
|
||
ry: shape.ry + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.circle = circle;
|
||
var ellipse = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
hr: 0,
|
||
vr: 0
|
||
},
|
||
validator: function validator(_ref8) {
|
||
var shape = _ref8.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
hr = shape.hr,
|
||
vr = shape.vr;
|
||
|
||
if (typeof rx !== 'number' || typeof ry !== 'number' || typeof hr !== 'number' || typeof vr !== 'number') {
|
||
console.error('Ellipse shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref9, _ref10) {
|
||
var ctx = _ref9.ctx;
|
||
var shape = _ref10.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
hr = shape.hr,
|
||
vr = shape.vr;
|
||
ctx.ellipse(rx, ry, hr > 0 ? hr : 0.01, vr > 0 ? vr : 0.01, 0, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref11) {
|
||
var shape = _ref11.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
hr = shape.hr,
|
||
vr = shape.vr;
|
||
var a = Math.max(hr, vr);
|
||
var b = Math.min(hr, vr);
|
||
var c = Math.sqrt(a * a - b * b);
|
||
var leftFocusPoint = [rx - c, ry];
|
||
var rightFocusPoint = [rx + c, ry];
|
||
var distance = (0, _util.getTwoPointDistance)(position, leftFocusPoint) + (0, _util.getTwoPointDistance)(position, rightFocusPoint);
|
||
return distance <= 2 * a;
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref12) {
|
||
var shape = _ref12.shape,
|
||
style = _ref12.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref13, _ref14) {
|
||
var movementX = _ref13.movementX,
|
||
movementY = _ref13.movementY;
|
||
var shape = _ref14.shape;
|
||
this.attr('shape', {
|
||
rx: shape.rx + movementX,
|
||
ry: shape.ry + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.ellipse = ellipse;
|
||
var rect = {
|
||
shape: {
|
||
x: 0,
|
||
y: 0,
|
||
w: 0,
|
||
h: 0
|
||
},
|
||
validator: function validator(_ref15) {
|
||
var shape = _ref15.shape;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
|
||
if (typeof x !== 'number' || typeof y !== 'number' || typeof w !== 'number' || typeof h !== 'number') {
|
||
console.error('Rect shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref16, _ref17) {
|
||
var ctx = _ref16.ctx;
|
||
var shape = _ref17.shape;
|
||
ctx.beginPath();
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
ctx.rect(x, y, w, h);
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref18) {
|
||
var shape = _ref18.shape;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
return (0, _util.checkPointIsInRect)(position, x, y, w, h);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref19) {
|
||
var shape = _ref19.shape,
|
||
style = _ref19.style;
|
||
var x = shape.x,
|
||
y = shape.y,
|
||
w = shape.w,
|
||
h = shape.h;
|
||
style.graphCenter = [x + w / 2, y + h / 2];
|
||
},
|
||
move: function move(_ref20, _ref21) {
|
||
var movementX = _ref20.movementX,
|
||
movementY = _ref20.movementY;
|
||
var shape = _ref21.shape;
|
||
this.attr('shape', {
|
||
x: shape.x + movementX,
|
||
y: shape.y + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.rect = rect;
|
||
var ring = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0
|
||
},
|
||
validator: function validator(_ref22) {
|
||
var shape = _ref22.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
|
||
if (typeof rx !== 'number' || typeof ry !== 'number' || typeof r !== 'number') {
|
||
console.error('Ring shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref23, _ref24) {
|
||
var ctx = _ref23.ctx;
|
||
var shape = _ref24.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
ctx.arc(rx, ry, r > 0 ? r : 0.01, 0, Math.PI * 2);
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref25) {
|
||
var shape = _ref25.shape,
|
||
style = _ref25.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r;
|
||
var lineWidth = style.lineWidth;
|
||
var halfLineWidth = lineWidth / 2;
|
||
var minDistance = r - halfLineWidth;
|
||
var maxDistance = r + halfLineWidth;
|
||
var distance = (0, _util.getTwoPointDistance)(position, [rx, ry]);
|
||
return distance >= minDistance && distance <= maxDistance;
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref26) {
|
||
var shape = _ref26.shape,
|
||
style = _ref26.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref27, _ref28) {
|
||
var movementX = _ref27.movementX,
|
||
movementY = _ref27.movementY;
|
||
var shape = _ref28.shape;
|
||
this.attr('shape', {
|
||
rx: shape.rx + movementX,
|
||
ry: shape.ry + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.ring = ring;
|
||
var arc = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0,
|
||
startAngle: 0,
|
||
endAngle: 0,
|
||
clockWise: true
|
||
},
|
||
validator: function validator(_ref29) {
|
||
var shape = _ref29.shape;
|
||
var keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle'];
|
||
|
||
if (keys.find(function (key) {
|
||
return typeof shape[key] !== 'number';
|
||
})) {
|
||
console.error('Arc shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref30, _ref31) {
|
||
var ctx = _ref30.ctx;
|
||
var shape = _ref31.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
clockWise = shape.clockWise;
|
||
ctx.arc(rx, ry, r > 0 ? r : 0.001, startAngle, endAngle, !clockWise);
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref32) {
|
||
var shape = _ref32.shape,
|
||
style = _ref32.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
clockWise = shape.clockWise;
|
||
var lineWidth = style.lineWidth;
|
||
var halfLineWidth = lineWidth / 2;
|
||
var insideRadius = r - halfLineWidth;
|
||
var outsideRadius = r + halfLineWidth;
|
||
return !(0, _util.checkPointIsInSector)(position, rx, ry, insideRadius, startAngle, endAngle, clockWise) && (0, _util.checkPointIsInSector)(position, rx, ry, outsideRadius, startAngle, endAngle, clockWise);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref33) {
|
||
var shape = _ref33.shape,
|
||
style = _ref33.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref34, _ref35) {
|
||
var movementX = _ref34.movementX,
|
||
movementY = _ref34.movementY;
|
||
var shape = _ref35.shape;
|
||
this.attr('shape', {
|
||
rx: shape.rx + movementX,
|
||
ry: shape.ry + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.arc = arc;
|
||
var sector = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0,
|
||
startAngle: 0,
|
||
endAngle: 0,
|
||
clockWise: true
|
||
},
|
||
validator: function validator(_ref36) {
|
||
var shape = _ref36.shape;
|
||
var keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle'];
|
||
|
||
if (keys.find(function (key) {
|
||
return typeof shape[key] !== 'number';
|
||
})) {
|
||
console.error('Sector shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref37, _ref38) {
|
||
var ctx = _ref37.ctx;
|
||
var shape = _ref38.shape;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
clockWise = shape.clockWise;
|
||
ctx.arc(rx, ry, r > 0 ? r : 0.01, startAngle, endAngle, !clockWise);
|
||
ctx.lineTo(rx, ry);
|
||
ctx.closePath();
|
||
ctx.stroke();
|
||
ctx.fill();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref39) {
|
||
var shape = _ref39.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r,
|
||
startAngle = shape.startAngle,
|
||
endAngle = shape.endAngle,
|
||
clockWise = shape.clockWise;
|
||
return (0, _util.checkPointIsInSector)(position, rx, ry, r, startAngle, endAngle, clockWise);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref40) {
|
||
var shape = _ref40.shape,
|
||
style = _ref40.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref41, _ref42) {
|
||
var movementX = _ref41.movementX,
|
||
movementY = _ref41.movementY;
|
||
var shape = _ref42.shape;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
this.attr('shape', {
|
||
rx: rx + movementX,
|
||
ry: ry + movementY
|
||
});
|
||
}
|
||
};
|
||
exports.sector = sector;
|
||
var regPolygon = {
|
||
shape: {
|
||
rx: 0,
|
||
ry: 0,
|
||
r: 0,
|
||
side: 0
|
||
},
|
||
validator: function validator(_ref43) {
|
||
var shape = _ref43.shape;
|
||
var side = shape.side;
|
||
var keys = ['rx', 'ry', 'r', 'side'];
|
||
|
||
if (keys.find(function (key) {
|
||
return typeof shape[key] !== 'number';
|
||
})) {
|
||
console.error('RegPolygon shape configuration is abnormal!');
|
||
return false;
|
||
}
|
||
|
||
if (side < 3) {
|
||
console.error('RegPolygon at least trigon!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref44, _ref45) {
|
||
var ctx = _ref44.ctx;
|
||
var shape = _ref45.shape,
|
||
cache = _ref45.cache;
|
||
ctx.beginPath();
|
||
var rx = shape.rx,
|
||
ry = shape.ry,
|
||
r = shape.r,
|
||
side = shape.side;
|
||
|
||
if (!cache.points || cache.rx !== rx || cache.ry !== ry || cache.r !== r || cache.side !== side) {
|
||
var _points = (0, _util.getRegularPolygonPoints)(rx, ry, r, side);
|
||
|
||
Object.assign(cache, {
|
||
points: _points,
|
||
rx: rx,
|
||
ry: ry,
|
||
r: r,
|
||
side: side
|
||
});
|
||
}
|
||
|
||
var points = cache.points;
|
||
(0, _canvas.drawPolylinePath)(ctx, points);
|
||
ctx.closePath();
|
||
ctx.stroke();
|
||
ctx.fill();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref46) {
|
||
var cache = _ref46.cache;
|
||
var points = cache.points;
|
||
return (0, _util.checkPointIsInPolygon)(position, points);
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref47) {
|
||
var shape = _ref47.shape,
|
||
style = _ref47.style;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
style.graphCenter = [rx, ry];
|
||
},
|
||
move: function move(_ref48, _ref49) {
|
||
var movementX = _ref48.movementX,
|
||
movementY = _ref48.movementY;
|
||
var shape = _ref49.shape,
|
||
cache = _ref49.cache;
|
||
var rx = shape.rx,
|
||
ry = shape.ry;
|
||
cache.rx += movementX;
|
||
cache.ry += movementY;
|
||
this.attr('shape', {
|
||
rx: rx + movementX,
|
||
ry: ry + movementY
|
||
});
|
||
cache.points = cache.points.map(function (_ref50) {
|
||
var _ref51 = (0, _slicedToArray2["default"])(_ref50, 2),
|
||
x = _ref51[0],
|
||
y = _ref51[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
}
|
||
};
|
||
exports.regPolygon = regPolygon;
|
||
var polyline = {
|
||
shape: {
|
||
points: [],
|
||
close: false
|
||
},
|
||
validator: function validator(_ref52) {
|
||
var shape = _ref52.shape;
|
||
var points = shape.points;
|
||
|
||
if (!(points instanceof Array)) {
|
||
console.error('Polyline points should be an array!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref53, _ref54) {
|
||
var ctx = _ref53.ctx;
|
||
var shape = _ref54.shape,
|
||
lineWidth = _ref54.style.lineWidth;
|
||
ctx.beginPath();
|
||
var points = shape.points,
|
||
close = shape.close;
|
||
if (lineWidth === 1) points = (0, _util.eliminateBlur)(points);
|
||
(0, _canvas.drawPolylinePath)(ctx, points);
|
||
|
||
if (close) {
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
} else {
|
||
ctx.stroke();
|
||
}
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref55) {
|
||
var shape = _ref55.shape,
|
||
style = _ref55.style;
|
||
var points = shape.points,
|
||
close = shape.close;
|
||
var lineWidth = style.lineWidth;
|
||
|
||
if (close) {
|
||
return (0, _util.checkPointIsInPolygon)(position, points);
|
||
} else {
|
||
return (0, _util.checkPointIsNearPolyline)(position, points, lineWidth);
|
||
}
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref56) {
|
||
var shape = _ref56.shape,
|
||
style = _ref56.style;
|
||
var points = shape.points;
|
||
style.graphCenter = points[0];
|
||
},
|
||
move: function move(_ref57, _ref58) {
|
||
var movementX = _ref57.movementX,
|
||
movementY = _ref57.movementY;
|
||
var shape = _ref58.shape;
|
||
var points = shape.points;
|
||
var moveAfterPoints = points.map(function (_ref59) {
|
||
var _ref60 = (0, _slicedToArray2["default"])(_ref59, 2),
|
||
x = _ref60[0],
|
||
y = _ref60[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
this.attr('shape', {
|
||
points: moveAfterPoints
|
||
});
|
||
}
|
||
};
|
||
exports.polyline = polyline;
|
||
var smoothline = {
|
||
shape: {
|
||
points: [],
|
||
close: false
|
||
},
|
||
validator: function validator(_ref61) {
|
||
var shape = _ref61.shape;
|
||
var points = shape.points;
|
||
|
||
if (!(points instanceof Array)) {
|
||
console.error('Smoothline points should be an array!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref62, _ref63) {
|
||
var ctx = _ref62.ctx;
|
||
var shape = _ref63.shape,
|
||
cache = _ref63.cache;
|
||
var points = shape.points,
|
||
close = shape.close;
|
||
|
||
if (!cache.points || cache.points.toString() !== points.toString()) {
|
||
var _bezierCurve = polylineToBezierCurve(points, close);
|
||
|
||
var hoverPoints = bezierCurveToPolyline(_bezierCurve);
|
||
Object.assign(cache, {
|
||
points: (0, _util.deepClone)(points, true),
|
||
bezierCurve: _bezierCurve,
|
||
hoverPoints: hoverPoints
|
||
});
|
||
}
|
||
|
||
var bezierCurve = cache.bezierCurve;
|
||
ctx.beginPath();
|
||
(0, _canvas.drawBezierCurvePath)(ctx, bezierCurve.slice(1), bezierCurve[0]);
|
||
|
||
if (close) {
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
} else {
|
||
ctx.stroke();
|
||
}
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref64) {
|
||
var cache = _ref64.cache,
|
||
shape = _ref64.shape,
|
||
style = _ref64.style;
|
||
var hoverPoints = cache.hoverPoints;
|
||
var close = shape.close;
|
||
var lineWidth = style.lineWidth;
|
||
|
||
if (close) {
|
||
return (0, _util.checkPointIsInPolygon)(position, hoverPoints);
|
||
} else {
|
||
return (0, _util.checkPointIsNearPolyline)(position, hoverPoints, lineWidth);
|
||
}
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref65) {
|
||
var shape = _ref65.shape,
|
||
style = _ref65.style;
|
||
var points = shape.points;
|
||
style.graphCenter = points[0];
|
||
},
|
||
move: function move(_ref66, _ref67) {
|
||
var movementX = _ref66.movementX,
|
||
movementY = _ref66.movementY;
|
||
var shape = _ref67.shape,
|
||
cache = _ref67.cache;
|
||
var points = shape.points;
|
||
var moveAfterPoints = points.map(function (_ref68) {
|
||
var _ref69 = (0, _slicedToArray2["default"])(_ref68, 2),
|
||
x = _ref69[0],
|
||
y = _ref69[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
cache.points = moveAfterPoints;
|
||
|
||
var _cache$bezierCurve$ = (0, _slicedToArray2["default"])(cache.bezierCurve[0], 2),
|
||
fx = _cache$bezierCurve$[0],
|
||
fy = _cache$bezierCurve$[1];
|
||
|
||
var curves = cache.bezierCurve.slice(1);
|
||
cache.bezierCurve = [[fx + movementX, fy + movementY]].concat((0, _toConsumableArray2["default"])(curves.map(function (curve) {
|
||
return curve.map(function (_ref70) {
|
||
var _ref71 = (0, _slicedToArray2["default"])(_ref70, 2),
|
||
x = _ref71[0],
|
||
y = _ref71[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
})));
|
||
cache.hoverPoints = cache.hoverPoints.map(function (_ref72) {
|
||
var _ref73 = (0, _slicedToArray2["default"])(_ref72, 2),
|
||
x = _ref73[0],
|
||
y = _ref73[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
this.attr('shape', {
|
||
points: moveAfterPoints
|
||
});
|
||
}
|
||
};
|
||
exports.smoothline = smoothline;
|
||
var bezierCurve = {
|
||
shape: {
|
||
points: [],
|
||
close: false
|
||
},
|
||
validator: function validator(_ref74) {
|
||
var shape = _ref74.shape;
|
||
var points = shape.points;
|
||
|
||
if (!(points instanceof Array)) {
|
||
console.error('BezierCurve points should be an array!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref75, _ref76) {
|
||
var ctx = _ref75.ctx;
|
||
var shape = _ref76.shape,
|
||
cache = _ref76.cache;
|
||
var points = shape.points,
|
||
close = shape.close;
|
||
|
||
if (!cache.points || cache.points.toString() !== points.toString()) {
|
||
var hoverPoints = bezierCurveToPolyline(points, 20);
|
||
Object.assign(cache, {
|
||
points: (0, _util.deepClone)(points, true),
|
||
hoverPoints: hoverPoints
|
||
});
|
||
}
|
||
|
||
ctx.beginPath();
|
||
(0, _canvas.drawBezierCurvePath)(ctx, points.slice(1), points[0]);
|
||
|
||
if (close) {
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
} else {
|
||
ctx.stroke();
|
||
}
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref77) {
|
||
var cache = _ref77.cache,
|
||
shape = _ref77.shape,
|
||
style = _ref77.style;
|
||
var hoverPoints = cache.hoverPoints;
|
||
var close = shape.close;
|
||
var lineWidth = style.lineWidth;
|
||
|
||
if (close) {
|
||
return (0, _util.checkPointIsInPolygon)(position, hoverPoints);
|
||
} else {
|
||
return (0, _util.checkPointIsNearPolyline)(position, hoverPoints, lineWidth);
|
||
}
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref78) {
|
||
var shape = _ref78.shape,
|
||
style = _ref78.style;
|
||
var points = shape.points;
|
||
style.graphCenter = points[0];
|
||
},
|
||
move: function move(_ref79, _ref80) {
|
||
var movementX = _ref79.movementX,
|
||
movementY = _ref79.movementY;
|
||
var shape = _ref80.shape,
|
||
cache = _ref80.cache;
|
||
var points = shape.points;
|
||
|
||
var _points$ = (0, _slicedToArray2["default"])(points[0], 2),
|
||
fx = _points$[0],
|
||
fy = _points$[1];
|
||
|
||
var curves = points.slice(1);
|
||
var bezierCurve = [[fx + movementX, fy + movementY]].concat((0, _toConsumableArray2["default"])(curves.map(function (curve) {
|
||
return curve.map(function (_ref81) {
|
||
var _ref82 = (0, _slicedToArray2["default"])(_ref81, 2),
|
||
x = _ref82[0],
|
||
y = _ref82[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
})));
|
||
cache.points = bezierCurve;
|
||
cache.hoverPoints = cache.hoverPoints.map(function (_ref83) {
|
||
var _ref84 = (0, _slicedToArray2["default"])(_ref83, 2),
|
||
x = _ref84[0],
|
||
y = _ref84[1];
|
||
|
||
return [x + movementX, y + movementY];
|
||
});
|
||
this.attr('shape', {
|
||
points: bezierCurve
|
||
});
|
||
}
|
||
};
|
||
exports.bezierCurve = bezierCurve;
|
||
var text = {
|
||
shape: {
|
||
content: '',
|
||
position: [],
|
||
maxWidth: undefined,
|
||
rowGap: 0
|
||
},
|
||
validator: function validator(_ref85) {
|
||
var shape = _ref85.shape;
|
||
var content = shape.content,
|
||
position = shape.position,
|
||
rowGap = shape.rowGap;
|
||
|
||
if (typeof content !== 'string') {
|
||
console.error('Text content should be a string!');
|
||
return false;
|
||
}
|
||
|
||
if (!(position instanceof Array)) {
|
||
console.error('Text position should be an array!');
|
||
return false;
|
||
}
|
||
|
||
if (typeof rowGap !== 'number') {
|
||
console.error('Text rowGap should be a number!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
},
|
||
draw: function draw(_ref86, _ref87) {
|
||
var ctx = _ref86.ctx;
|
||
var shape = _ref87.shape;
|
||
var content = shape.content,
|
||
position = shape.position,
|
||
maxWidth = shape.maxWidth,
|
||
rowGap = shape.rowGap;
|
||
var textBaseline = ctx.textBaseline,
|
||
font = ctx.font;
|
||
var fontSize = parseInt(font.replace(/\D/g, ''));
|
||
|
||
var _position = position,
|
||
_position2 = (0, _slicedToArray2["default"])(_position, 2),
|
||
x = _position2[0],
|
||
y = _position2[1];
|
||
|
||
content = content.split('\n');
|
||
var rowNum = content.length;
|
||
var lineHeight = fontSize + rowGap;
|
||
var allHeight = rowNum * lineHeight - rowGap;
|
||
var offset = 0;
|
||
|
||
if (textBaseline === 'middle') {
|
||
offset = allHeight / 2;
|
||
y += fontSize / 2;
|
||
}
|
||
|
||
if (textBaseline === 'bottom') {
|
||
offset = allHeight;
|
||
y += fontSize;
|
||
}
|
||
|
||
position = new Array(rowNum).fill(0).map(function (foo, i) {
|
||
return [x, y + i * lineHeight - offset];
|
||
});
|
||
ctx.beginPath();
|
||
content.forEach(function (text, i) {
|
||
ctx.fillText.apply(ctx, [text].concat((0, _toConsumableArray2["default"])(position[i]), [maxWidth]));
|
||
ctx.strokeText.apply(ctx, [text].concat((0, _toConsumableArray2["default"])(position[i]), [maxWidth]));
|
||
});
|
||
ctx.closePath();
|
||
},
|
||
hoverCheck: function hoverCheck(position, _ref88) {
|
||
var shape = _ref88.shape,
|
||
style = _ref88.style;
|
||
return false;
|
||
},
|
||
setGraphCenter: function setGraphCenter(e, _ref89) {
|
||
var shape = _ref89.shape,
|
||
style = _ref89.style;
|
||
var position = shape.position;
|
||
style.graphCenter = (0, _toConsumableArray2["default"])(position);
|
||
},
|
||
move: function move(_ref90, _ref91) {
|
||
var movementX = _ref90.movementX,
|
||
movementY = _ref90.movementY;
|
||
var shape = _ref91.shape;
|
||
|
||
var _shape$position = (0, _slicedToArray2["default"])(shape.position, 2),
|
||
x = _shape$position[0],
|
||
y = _shape$position[1];
|
||
|
||
this.attr('shape', {
|
||
position: [x + movementX, y + movementY]
|
||
});
|
||
}
|
||
};
|
||
exports.text = text;
|
||
var graphs = new Map([['circle', circle], ['ellipse', ellipse], ['rect', rect], ['ring', ring], ['arc', arc], ['sector', sector], ['regPolygon', regPolygon], ['polyline', polyline], ['smoothline', smoothline], ['bezierCurve', bezierCurve], ['text', text]]);
|
||
var _default = graphs;
|
||
/**
|
||
* @description Extend new graph
|
||
* @param {String} name Name of Graph
|
||
* @param {Object} config Configuration of Graph
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
exports["default"] = _default;
|
||
|
||
function extendNewGraph(name, config) {
|
||
if (!name || !config) {
|
||
console.error('ExtendNewGraph Missing Parameters!');
|
||
return;
|
||
}
|
||
|
||
if (!config.shape) {
|
||
console.error('Required attribute of shape to extendNewGraph!');
|
||
return;
|
||
}
|
||
|
||
if (!config.validator) {
|
||
console.error('Required function of validator to extendNewGraph!');
|
||
return;
|
||
}
|
||
|
||
if (!config.draw) {
|
||
console.error('Required function of draw to extendNewGraph!');
|
||
return;
|
||
}
|
||
|
||
graphs.set(name, config);
|
||
}
|
||
},{"../plugin/canvas":53,"../plugin/util":54,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@jiaminghi/bezier-curve":47}],52:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
Object.defineProperty(exports, "CRender", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _crender["default"];
|
||
}
|
||
});
|
||
Object.defineProperty(exports, "extendNewGraph", {
|
||
enumerable: true,
|
||
get: function get() {
|
||
return _graphs.extendNewGraph;
|
||
}
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _crender = _interopRequireDefault(require("./class/crender.class"));
|
||
|
||
var _graphs = require("./config/graphs");
|
||
|
||
var _default = _crender["default"];
|
||
exports["default"] = _default;
|
||
},{"./class/crender.class":48,"./config/graphs":51,"@babel/runtime/helpers/interopRequireDefault":36}],53:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.drawPolylinePath = drawPolylinePath;
|
||
exports.drawBezierCurvePath = drawBezierCurvePath;
|
||
exports["default"] = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
/**
|
||
* @description Draw a polyline path
|
||
* @param {Object} ctx Canvas 2d context
|
||
* @param {Array} points The points that makes up a polyline
|
||
* @param {Boolean} beginPath Whether to execute beginPath
|
||
* @param {Boolean} closePath Whether to execute closePath
|
||
* @return {Undefined} Void
|
||
*/
|
||
function drawPolylinePath(ctx, points) {
|
||
var beginPath = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
var closePath = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
||
if (!ctx || points.length < 2) return false;
|
||
if (beginPath) ctx.beginPath();
|
||
points.forEach(function (point, i) {
|
||
return point && (i === 0 ? ctx.moveTo.apply(ctx, (0, _toConsumableArray2["default"])(point)) : ctx.lineTo.apply(ctx, (0, _toConsumableArray2["default"])(point)));
|
||
});
|
||
if (closePath) ctx.closePath();
|
||
}
|
||
/**
|
||
* @description Draw a bezier curve path
|
||
* @param {Object} ctx Canvas 2d context
|
||
* @param {Array} points The points that makes up a bezier curve
|
||
* @param {Array} moveTo The point need to excute moveTo
|
||
* @param {Boolean} beginPath Whether to execute beginPath
|
||
* @param {Boolean} closePath Whether to execute closePath
|
||
* @return {Undefined} Void
|
||
*/
|
||
|
||
|
||
function drawBezierCurvePath(ctx, points) {
|
||
var moveTo = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
var beginPath = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
||
var closePath = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
||
if (!ctx || !points) return false;
|
||
if (beginPath) ctx.beginPath();
|
||
if (moveTo) ctx.moveTo.apply(ctx, (0, _toConsumableArray2["default"])(moveTo));
|
||
points.forEach(function (item) {
|
||
return item && ctx.bezierCurveTo.apply(ctx, (0, _toConsumableArray2["default"])(item[0]).concat((0, _toConsumableArray2["default"])(item[1]), (0, _toConsumableArray2["default"])(item[2])));
|
||
});
|
||
if (closePath) ctx.closePath();
|
||
}
|
||
|
||
var _default = {
|
||
drawPolylinePath: drawPolylinePath,
|
||
drawBezierCurvePath: drawBezierCurvePath
|
||
};
|
||
exports["default"] = _default;
|
||
},{"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42}],54:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.deepClone = deepClone;
|
||
exports.eliminateBlur = eliminateBlur;
|
||
exports.checkPointIsInCircle = checkPointIsInCircle;
|
||
exports.getTwoPointDistance = getTwoPointDistance;
|
||
exports.checkPointIsInPolygon = checkPointIsInPolygon;
|
||
exports.checkPointIsInSector = checkPointIsInSector;
|
||
exports.checkPointIsNearPolyline = checkPointIsNearPolyline;
|
||
exports.checkPointIsInRect = checkPointIsInRect;
|
||
exports.getRotatePointPos = getRotatePointPos;
|
||
exports.getScalePointPos = getScalePointPos;
|
||
exports.getTranslatePointPos = getTranslatePointPos;
|
||
exports.getDistanceBetweenPointAndLine = getDistanceBetweenPointAndLine;
|
||
exports.getCircleRadianPoint = getCircleRadianPoint;
|
||
exports.getRegularPolygonPoints = getRegularPolygonPoints;
|
||
exports["default"] = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var abs = Math.abs,
|
||
sqrt = Math.sqrt,
|
||
sin = Math.sin,
|
||
cos = Math.cos,
|
||
max = Math.max,
|
||
min = Math.min,
|
||
PI = Math.PI;
|
||
/**
|
||
* @description Clone an object or array
|
||
* @param {Object|Array} object Cloned object
|
||
* @param {Boolean} recursion Whether to use recursive cloning
|
||
* @return {Object|Array} Clone object
|
||
*/
|
||
|
||
function deepClone(object) {
|
||
var recursion = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
if (!object) return object;
|
||
var parse = JSON.parse,
|
||
stringify = JSON.stringify;
|
||
if (!recursion) return parse(stringify(object));
|
||
var clonedObj = object instanceof Array ? [] : {};
|
||
|
||
if (object && (0, _typeof2["default"])(object) === 'object') {
|
||
for (var key in object) {
|
||
if (object.hasOwnProperty(key)) {
|
||
if (object[key] && (0, _typeof2["default"])(object[key]) === 'object') {
|
||
clonedObj[key] = deepClone(object[key], true);
|
||
} else {
|
||
clonedObj[key] = object[key];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return clonedObj;
|
||
}
|
||
/**
|
||
* @description Eliminate line blur due to 1px line width
|
||
* @param {Array} points Line points
|
||
* @return {Array} Line points after processed
|
||
*/
|
||
|
||
|
||
function eliminateBlur(points) {
|
||
return points.map(function (_ref) {
|
||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
|
||
x = _ref2[0],
|
||
y = _ref2[1];
|
||
|
||
return [parseInt(x) + 0.5, parseInt(y) + 0.5];
|
||
});
|
||
}
|
||
/**
|
||
* @description Check if the point is inside the circle
|
||
* @param {Array} point Postion of point
|
||
* @param {Number} rx Circle x coordinate
|
||
* @param {Number} ry Circle y coordinate
|
||
* @param {Number} r Circle radius
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function checkPointIsInCircle(point, rx, ry, r) {
|
||
return getTwoPointDistance(point, [rx, ry]) <= r;
|
||
}
|
||
/**
|
||
* @description Get the distance between two points
|
||
* @param {Array} point1 point1
|
||
* @param {Array} point2 point2
|
||
* @return {Number} Distance between two points
|
||
*/
|
||
|
||
|
||
function getTwoPointDistance(_ref3, _ref4) {
|
||
var _ref5 = (0, _slicedToArray2["default"])(_ref3, 2),
|
||
xa = _ref5[0],
|
||
ya = _ref5[1];
|
||
|
||
var _ref6 = (0, _slicedToArray2["default"])(_ref4, 2),
|
||
xb = _ref6[0],
|
||
yb = _ref6[1];
|
||
|
||
var minusX = abs(xa - xb);
|
||
var minusY = abs(ya - yb);
|
||
return sqrt(minusX * minusX + minusY * minusY);
|
||
}
|
||
/**
|
||
* @description Check if the point is inside the polygon
|
||
* @param {Array} point Postion of point
|
||
* @param {Array} points The points that makes up a polyline
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function checkPointIsInPolygon(point, polygon) {
|
||
var counter = 0;
|
||
|
||
var _point = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point[0],
|
||
y = _point[1];
|
||
|
||
var pointNum = polygon.length;
|
||
|
||
for (var i = 1, p1 = polygon[0]; i <= pointNum; i++) {
|
||
var p2 = polygon[i % pointNum];
|
||
|
||
if (x > min(p1[0], p2[0]) && x <= max(p1[0], p2[0])) {
|
||
if (y <= max(p1[1], p2[1])) {
|
||
if (p1[0] !== p2[0]) {
|
||
var xinters = (x - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
|
||
|
||
if (p1[1] === p2[1] || y <= xinters) {
|
||
counter++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
p1 = p2;
|
||
}
|
||
|
||
return counter % 2 === 1;
|
||
}
|
||
/**
|
||
* @description Check if the point is inside the sector
|
||
* @param {Array} point Postion of point
|
||
* @param {Number} rx Sector x coordinate
|
||
* @param {Number} ry Sector y coordinate
|
||
* @param {Number} r Sector radius
|
||
* @param {Number} startAngle Sector start angle
|
||
* @param {Number} endAngle Sector end angle
|
||
* @param {Boolean} clockWise Whether the sector angle is clockwise
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function checkPointIsInSector(point, rx, ry, r, startAngle, endAngle, clockWise) {
|
||
if (!point) return false;
|
||
if (getTwoPointDistance(point, [rx, ry]) > r) return false;
|
||
|
||
if (!clockWise) {
|
||
var _deepClone = deepClone([endAngle, startAngle]);
|
||
|
||
var _deepClone2 = (0, _slicedToArray2["default"])(_deepClone, 2);
|
||
|
||
startAngle = _deepClone2[0];
|
||
endAngle = _deepClone2[1];
|
||
}
|
||
|
||
var reverseBE = startAngle > endAngle;
|
||
|
||
if (reverseBE) {
|
||
var _ref7 = [endAngle, startAngle];
|
||
startAngle = _ref7[0];
|
||
endAngle = _ref7[1];
|
||
}
|
||
|
||
var minus = endAngle - startAngle;
|
||
if (minus >= PI * 2) return true;
|
||
|
||
var _point2 = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point2[0],
|
||
y = _point2[1];
|
||
|
||
var _getCircleRadianPoint = getCircleRadianPoint(rx, ry, r, startAngle),
|
||
_getCircleRadianPoint2 = (0, _slicedToArray2["default"])(_getCircleRadianPoint, 2),
|
||
bx = _getCircleRadianPoint2[0],
|
||
by = _getCircleRadianPoint2[1];
|
||
|
||
var _getCircleRadianPoint3 = getCircleRadianPoint(rx, ry, r, endAngle),
|
||
_getCircleRadianPoint4 = (0, _slicedToArray2["default"])(_getCircleRadianPoint3, 2),
|
||
ex = _getCircleRadianPoint4[0],
|
||
ey = _getCircleRadianPoint4[1];
|
||
|
||
var vPoint = [x - rx, y - ry];
|
||
var vBArm = [bx - rx, by - ry];
|
||
var vEArm = [ex - rx, ey - ry];
|
||
var reverse = minus > PI;
|
||
|
||
if (reverse) {
|
||
var _deepClone3 = deepClone([vEArm, vBArm]);
|
||
|
||
var _deepClone4 = (0, _slicedToArray2["default"])(_deepClone3, 2);
|
||
|
||
vBArm = _deepClone4[0];
|
||
vEArm = _deepClone4[1];
|
||
}
|
||
|
||
var inSector = isClockWise(vBArm, vPoint) && !isClockWise(vEArm, vPoint);
|
||
if (reverse) inSector = !inSector;
|
||
if (reverseBE) inSector = !inSector;
|
||
return inSector;
|
||
}
|
||
/**
|
||
* @description Determine if the point is in the clockwise direction of the vector
|
||
* @param {Array} vArm Vector
|
||
* @param {Array} vPoint Point
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function isClockWise(vArm, vPoint) {
|
||
var _vArm = (0, _slicedToArray2["default"])(vArm, 2),
|
||
ax = _vArm[0],
|
||
ay = _vArm[1];
|
||
|
||
var _vPoint = (0, _slicedToArray2["default"])(vPoint, 2),
|
||
px = _vPoint[0],
|
||
py = _vPoint[1];
|
||
|
||
return -ay * px + ax * py > 0;
|
||
}
|
||
/**
|
||
* @description Check if the point is inside the polyline
|
||
* @param {Array} point Postion of point
|
||
* @param {Array} polyline The points that makes up a polyline
|
||
* @param {Number} lineWidth Polyline linewidth
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function checkPointIsNearPolyline(point, polyline, lineWidth) {
|
||
var halfLineWidth = lineWidth / 2;
|
||
var moveUpPolyline = polyline.map(function (_ref8) {
|
||
var _ref9 = (0, _slicedToArray2["default"])(_ref8, 2),
|
||
x = _ref9[0],
|
||
y = _ref9[1];
|
||
|
||
return [x, y - halfLineWidth];
|
||
});
|
||
var moveDownPolyline = polyline.map(function (_ref10) {
|
||
var _ref11 = (0, _slicedToArray2["default"])(_ref10, 2),
|
||
x = _ref11[0],
|
||
y = _ref11[1];
|
||
|
||
return [x, y + halfLineWidth];
|
||
});
|
||
var polygon = [].concat((0, _toConsumableArray2["default"])(moveUpPolyline), (0, _toConsumableArray2["default"])(moveDownPolyline.reverse()));
|
||
return checkPointIsInPolygon(point, polygon);
|
||
}
|
||
/**
|
||
* @description Check if the point is inside the rect
|
||
* @param {Array} point Postion of point
|
||
* @param {Number} x Rect start x coordinate
|
||
* @param {Number} y Rect start y coordinate
|
||
* @param {Number} width Rect width
|
||
* @param {Number} height Rect height
|
||
* @return {Boolean} Result of check
|
||
*/
|
||
|
||
|
||
function checkPointIsInRect(_ref12, x, y, width, height) {
|
||
var _ref13 = (0, _slicedToArray2["default"])(_ref12, 2),
|
||
px = _ref13[0],
|
||
py = _ref13[1];
|
||
|
||
if (px < x) return false;
|
||
if (py < y) return false;
|
||
if (px > x + width) return false;
|
||
if (py > y + height) return false;
|
||
return true;
|
||
}
|
||
/**
|
||
* @description Get the coordinates of the rotated point
|
||
* @param {Number} rotate Degree of rotation
|
||
* @param {Array} point Postion of point
|
||
* @param {Array} origin Rotation center
|
||
* @param {Array} origin Rotation center
|
||
* @return {Number} Coordinates after rotation
|
||
*/
|
||
|
||
|
||
function getRotatePointPos() {
|
||
var rotate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
||
var point = arguments.length > 1 ? arguments[1] : undefined;
|
||
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
||
if (!point) return false;
|
||
if (rotate % 360 === 0) return point;
|
||
|
||
var _point3 = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point3[0],
|
||
y = _point3[1];
|
||
|
||
var _origin = (0, _slicedToArray2["default"])(origin, 2),
|
||
ox = _origin[0],
|
||
oy = _origin[1];
|
||
|
||
rotate *= PI / 180;
|
||
return [(x - ox) * cos(rotate) - (y - oy) * sin(rotate) + ox, (x - ox) * sin(rotate) + (y - oy) * cos(rotate) + oy];
|
||
}
|
||
/**
|
||
* @description Get the coordinates of the scaled point
|
||
* @param {Array} scale Scale factor
|
||
* @param {Array} point Postion of point
|
||
* @param {Array} origin Scale center
|
||
* @return {Number} Coordinates after scale
|
||
*/
|
||
|
||
|
||
function getScalePointPos() {
|
||
var scale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [1, 1];
|
||
var point = arguments.length > 1 ? arguments[1] : undefined;
|
||
var origin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [0, 0];
|
||
if (!point) return false;
|
||
if (scale === 1) return point;
|
||
|
||
var _point4 = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point4[0],
|
||
y = _point4[1];
|
||
|
||
var _origin2 = (0, _slicedToArray2["default"])(origin, 2),
|
||
ox = _origin2[0],
|
||
oy = _origin2[1];
|
||
|
||
var _scale = (0, _slicedToArray2["default"])(scale, 2),
|
||
xs = _scale[0],
|
||
ys = _scale[1];
|
||
|
||
var relativePosX = x - ox;
|
||
var relativePosY = y - oy;
|
||
return [relativePosX * xs + ox, relativePosY * ys + oy];
|
||
}
|
||
/**
|
||
* @description Get the coordinates of the scaled point
|
||
* @param {Array} translate Translation distance
|
||
* @param {Array} point Postion of point
|
||
* @return {Number} Coordinates after translation
|
||
*/
|
||
|
||
|
||
function getTranslatePointPos(translate, point) {
|
||
if (!translate || !point) return false;
|
||
|
||
var _point5 = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point5[0],
|
||
y = _point5[1];
|
||
|
||
var _translate = (0, _slicedToArray2["default"])(translate, 2),
|
||
tx = _translate[0],
|
||
ty = _translate[1];
|
||
|
||
return [x + tx, y + ty];
|
||
}
|
||
/**
|
||
* @description Get the distance from the point to the line
|
||
* @param {Array} point Postion of point
|
||
* @param {Array} lineBegin Line start position
|
||
* @param {Array} lineEnd Line end position
|
||
* @return {Number} Distance between point and line
|
||
*/
|
||
|
||
|
||
function getDistanceBetweenPointAndLine(point, lineBegin, lineEnd) {
|
||
if (!point || !lineBegin || !lineEnd) return false;
|
||
|
||
var _point6 = (0, _slicedToArray2["default"])(point, 2),
|
||
x = _point6[0],
|
||
y = _point6[1];
|
||
|
||
var _lineBegin = (0, _slicedToArray2["default"])(lineBegin, 2),
|
||
x1 = _lineBegin[0],
|
||
y1 = _lineBegin[1];
|
||
|
||
var _lineEnd = (0, _slicedToArray2["default"])(lineEnd, 2),
|
||
x2 = _lineEnd[0],
|
||
y2 = _lineEnd[1];
|
||
|
||
var a = y2 - y1;
|
||
var b = x1 - x2;
|
||
var c = y1 * (x2 - x1) - x1 * (y2 - y1);
|
||
var molecule = abs(a * x + b * y + c);
|
||
var denominator = sqrt(a * a + b * b);
|
||
return molecule / denominator;
|
||
}
|
||
/**
|
||
* @description Get the coordinates of the specified radian on the circle
|
||
* @param {Number} x Circle x coordinate
|
||
* @param {Number} y Circle y coordinate
|
||
* @param {Number} radius Circle radius
|
||
* @param {Number} radian Specfied radian
|
||
* @return {Array} Postion of point
|
||
*/
|
||
|
||
|
||
function getCircleRadianPoint(x, y, radius, radian) {
|
||
return [x + cos(radian) * radius, y + sin(radian) * radius];
|
||
}
|
||
/**
|
||
* @description Get the points that make up a regular polygon
|
||
* @param {Number} x X coordinate of the polygon inscribed circle
|
||
* @param {Number} y Y coordinate of the polygon inscribed circle
|
||
* @param {Number} r Radius of the polygon inscribed circle
|
||
* @param {Number} side Side number
|
||
* @param {Number} minus Radian offset
|
||
* @return {Array} Points that make up a regular polygon
|
||
*/
|
||
|
||
|
||
function getRegularPolygonPoints(rx, ry, r, side) {
|
||
var minus = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : PI * -0.5;
|
||
var radianGap = PI * 2 / side;
|
||
var radians = new Array(side).fill('').map(function (t, i) {
|
||
return i * radianGap + minus;
|
||
});
|
||
return radians.map(function (radian) {
|
||
return getCircleRadianPoint(rx, ry, r, radian);
|
||
});
|
||
}
|
||
|
||
var _default = {
|
||
deepClone: deepClone,
|
||
eliminateBlur: eliminateBlur,
|
||
checkPointIsInCircle: checkPointIsInCircle,
|
||
checkPointIsInPolygon: checkPointIsInPolygon,
|
||
checkPointIsInSector: checkPointIsInSector,
|
||
checkPointIsNearPolyline: checkPointIsNearPolyline,
|
||
getTwoPointDistance: getTwoPointDistance,
|
||
getRotatePointPos: getRotatePointPos,
|
||
getScalePointPos: getScalePointPos,
|
||
getTranslatePointPos: getTranslatePointPos,
|
||
getCircleRadianPoint: getCircleRadianPoint,
|
||
getRegularPolygonPoints: getRegularPolygonPoints,
|
||
getDistanceBetweenPointAndLine: getDistanceBetweenPointAndLine
|
||
};
|
||
exports["default"] = _default;
|
||
},{"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/toConsumableArray":42,"@babel/runtime/helpers/typeof":43}],55:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = void 0;
|
||
|
||
var _default = new Map([['transparent', 'rgba(0,0,0,0)'], ['black', '#000000'], ['silver', '#C0C0C0'], ['gray', '#808080'], ['white', '#FFFFFF'], ['maroon', '#800000'], ['red', '#FF0000'], ['purple', '#800080'], ['fuchsia', '#FF00FF'], ['green', '#008000'], ['lime', '#00FF00'], ['olive', '#808000'], ['yellow', '#FFFF00'], ['navy', '#000080'], ['blue', '#0000FF'], ['teal', '#008080'], ['aqua', '#00FFFF'], ['aliceblue', '#f0f8ff'], ['antiquewhite', '#faebd7'], ['aquamarine', '#7fffd4'], ['azure', '#f0ffff'], ['beige', '#f5f5dc'], ['bisque', '#ffe4c4'], ['blanchedalmond', '#ffebcd'], ['blueviolet', '#8a2be2'], ['brown', '#a52a2a'], ['burlywood', '#deb887'], ['cadetblue', '#5f9ea0'], ['chartreuse', '#7fff00'], ['chocolate', '#d2691e'], ['coral', '#ff7f50'], ['cornflowerblue', '#6495ed'], ['cornsilk', '#fff8dc'], ['crimson', '#dc143c'], ['cyan', '#00ffff'], ['darkblue', '#00008b'], ['darkcyan', '#008b8b'], ['darkgoldenrod', '#b8860b'], ['darkgray', '#a9a9a9'], ['darkgreen', '#006400'], ['darkgrey', '#a9a9a9'], ['darkkhaki', '#bdb76b'], ['darkmagenta', '#8b008b'], ['darkolivegreen', '#556b2f'], ['darkorange', '#ff8c00'], ['darkorchid', '#9932cc'], ['darkred', '#8b0000'], ['darksalmon', '#e9967a'], ['darkseagreen', '#8fbc8f'], ['darkslateblue', '#483d8b'], ['darkslategray', '#2f4f4f'], ['darkslategrey', '#2f4f4f'], ['darkturquoise', '#00ced1'], ['darkviolet', '#9400d3'], ['deeppink', '#ff1493'], ['deepskyblue', '#00bfff'], ['dimgray', '#696969'], ['dimgrey', '#696969'], ['dodgerblue', '#1e90ff'], ['firebrick', '#b22222'], ['floralwhite', '#fffaf0'], ['forestgreen', '#228b22'], ['gainsboro', '#dcdcdc'], ['ghostwhite', '#f8f8ff'], ['gold', '#ffd700'], ['goldenrod', '#daa520'], ['greenyellow', '#adff2f'], ['grey', '#808080'], ['honeydew', '#f0fff0'], ['hotpink', '#ff69b4'], ['indianred', '#cd5c5c'], ['indigo', '#4b0082'], ['ivory', '#fffff0'], ['khaki', '#f0e68c'], ['lavender', '#e6e6fa'], ['lavenderblush', '#fff0f5'], ['lawngreen', '#7cfc00'], ['lemonchiffon', '#fffacd'], ['lightblue', '#add8e6'], ['lightcoral', '#f08080'], ['lightcyan', '#e0ffff'], ['lightgoldenrodyellow', '#fafad2'], ['lightgray', '#d3d3d3'], ['lightgreen', '#90ee90'], ['lightgrey', '#d3d3d3'], ['lightpink', '#ffb6c1'], ['lightsalmon', '#ffa07a'], ['lightseagreen', '#20b2aa'], ['lightskyblue', '#87cefa'], ['lightslategray', '#778899'], ['lightslategrey', '#778899'], ['lightsteelblue', '#b0c4de'], ['lightyellow', '#ffffe0'], ['limegreen', '#32cd32'], ['linen', '#faf0e6'], ['magenta', '#ff00ff'], ['mediumaquamarine', '#66cdaa'], ['mediumblue', '#0000cd'], ['mediumorchid', '#ba55d3'], ['mediumpurple', '#9370db'], ['mediumseagreen', '#3cb371'], ['mediumslateblue', '#7b68ee'], ['mediumspringgreen', '#00fa9a'], ['mediumturquoise', '#48d1cc'], ['mediumvioletred', '#c71585'], ['midnightblue', '#191970'], ['mintcream', '#f5fffa'], ['mistyrose', '#ffe4e1'], ['moccasin', '#ffe4b5'], ['navajowhite', '#ffdead'], ['oldlace', '#fdf5e6'], ['olivedrab', '#6b8e23'], ['orange', '#ffa500'], ['orangered', '#ff4500'], ['orchid', '#da70d6'], ['palegoldenrod', '#eee8aa'], ['palegreen', '#98fb98'], ['paleturquoise', '#afeeee'], ['palevioletred', '#db7093'], ['papayawhip', '#ffefd5'], ['peachpuff', '#ffdab9'], ['peru', '#cd853f'], ['pink', '#ffc0cb'], ['plum', '#dda0dd'], ['powderblue', '#b0e0e6'], ['rosybrown', '#bc8f8f'], ['royalblue', '#4169e1'], ['saddlebrown', '#8b4513'], ['salmon', '#fa8072'], ['sandybrown', '#f4a460'], ['seagreen', '#2e8b57'], ['seashell', '#fff5ee'], ['sienna', '#a0522d'], ['skyblue', '#87ceeb'], ['slateblue', '#6a5acd'], ['slategray', '#708090'], ['slategrey', '#708090'], ['snow', '#fffafa'], ['springgreen', '#00ff7f'], ['steelblue', '#4682b4'], ['tan', '#d2b48c'], ['thistle', '#d8bfd8'], ['tomato', '#ff6347'], ['turquoise', '#40e0d0'], ['violet', '#ee82ee'], ['wheat', '#f5deb3'], ['whitesmoke', '#f5f5f5'], ['yellowgreen', '#9acd32']]);
|
||
|
||
exports["default"] = _default;
|
||
},{}],56:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.getRgbValue = getRgbValue;
|
||
exports.getRgbaValue = getRgbaValue;
|
||
exports.getOpacity = getOpacity;
|
||
exports.toRgb = toRgb;
|
||
exports.toHex = toHex;
|
||
exports.getColorFromRgbValue = getColorFromRgbValue;
|
||
exports.darken = darken;
|
||
exports.lighten = lighten;
|
||
exports.fade = fade;
|
||
exports["default"] = void 0;
|
||
|
||
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
||
|
||
var _keywords = _interopRequireDefault(require("./config/keywords"));
|
||
|
||
var hexReg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
|
||
var rgbReg = /^(rgb|rgba|RGB|RGBA)/;
|
||
var rgbaReg = /^(rgba|RGBA)/;
|
||
/**
|
||
* @description Color validator
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {String|Boolean} Valid color Or false
|
||
*/
|
||
|
||
function validator(color) {
|
||
var isHex = hexReg.test(color);
|
||
var isRgb = rgbReg.test(color);
|
||
if (isHex || isRgb) return color;
|
||
color = getColorByKeyword(color);
|
||
|
||
if (!color) {
|
||
console.error('Color: Invalid color!');
|
||
return false;
|
||
}
|
||
|
||
return color;
|
||
}
|
||
/**
|
||
* @description Get color by keyword
|
||
* @param {String} keyword Color keyword like red, green and etc.
|
||
* @return {String|Boolean} Hex or rgba color (Invalid keyword will return false)
|
||
*/
|
||
|
||
|
||
function getColorByKeyword(keyword) {
|
||
if (!keyword) {
|
||
console.error('getColorByKeywords: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
if (!_keywords["default"].has(keyword)) return false;
|
||
return _keywords["default"].get(keyword);
|
||
}
|
||
/**
|
||
* @description Get the Rgb value of the color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {Array<Number>|Boolean} Rgb value of the color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function getRgbValue(color) {
|
||
if (!color) {
|
||
console.error('getRgbValue: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
color = validator(color);
|
||
if (!color) return false;
|
||
var isHex = hexReg.test(color);
|
||
var isRgb = rgbReg.test(color);
|
||
var lowerColor = color.toLowerCase();
|
||
if (isHex) return getRgbValueFromHex(lowerColor);
|
||
if (isRgb) return getRgbValueFromRgb(lowerColor);
|
||
}
|
||
/**
|
||
* @description Get the rgb value of the hex color
|
||
* @param {String} color Hex color
|
||
* @return {Array<Number>} Rgb value of the color
|
||
*/
|
||
|
||
|
||
function getRgbValueFromHex(color) {
|
||
color = color.replace('#', '');
|
||
if (color.length === 3) color = Array.from(color).map(function (hexNum) {
|
||
return hexNum + hexNum;
|
||
}).join('');
|
||
color = color.split('');
|
||
return new Array(3).fill(0).map(function (t, i) {
|
||
return parseInt("0x".concat(color[i * 2]).concat(color[i * 2 + 1]));
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the rgb value of the rgb/rgba color
|
||
* @param {String} color Hex color
|
||
* @return {Array} Rgb value of the color
|
||
*/
|
||
|
||
|
||
function getRgbValueFromRgb(color) {
|
||
return color.replace(/rgb\(|rgba\(|\)/g, '').split(',').slice(0, 3).map(function (n) {
|
||
return parseInt(n);
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the Rgba value of the color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {Array<Number>|Boolean} Rgba value of the color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function getRgbaValue(color) {
|
||
if (!color) {
|
||
console.error('getRgbaValue: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var colorValue = getRgbValue(color);
|
||
if (!colorValue) return false;
|
||
colorValue.push(getOpacity(color));
|
||
return colorValue;
|
||
}
|
||
/**
|
||
* @description Get the opacity of color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {Number|Boolean} Color opacity (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function getOpacity(color) {
|
||
if (!color) {
|
||
console.error('getOpacity: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
color = validator(color);
|
||
if (!color) return false;
|
||
var isRgba = rgbaReg.test(color);
|
||
if (!isRgba) return 1;
|
||
color = color.toLowerCase();
|
||
return Number(color.split(',').slice(-1)[0].replace(/[)|\s]/g, ''));
|
||
}
|
||
/**
|
||
* @description Convert color to Rgb|Rgba color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @param {Number} opacity The opacity of color
|
||
* @return {String|Boolean} Rgb|Rgba color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function toRgb(color, opacity) {
|
||
if (!color) {
|
||
console.error('toRgb: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var rgbValue = getRgbValue(color);
|
||
if (!rgbValue) return false;
|
||
var addOpacity = typeof opacity === 'number';
|
||
if (addOpacity) return 'rgba(' + rgbValue.join(',') + ",".concat(opacity, ")");
|
||
return 'rgb(' + rgbValue.join(',') + ')';
|
||
}
|
||
/**
|
||
* @description Convert color to Hex color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {String|Boolean} Hex color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function toHex(color) {
|
||
if (!color) {
|
||
console.error('toHex: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
if (hexReg.test(color)) return color;
|
||
color = getRgbValue(color);
|
||
if (!color) return false;
|
||
return '#' + color.map(function (n) {
|
||
return Number(n).toString(16);
|
||
}).map(function (n) {
|
||
return n === '0' ? '00' : n;
|
||
}).join('');
|
||
}
|
||
/**
|
||
* @description Get Color from Rgb|Rgba value
|
||
* @param {Array<Number>} value Rgb|Rgba color value
|
||
* @return {String|Boolean} Rgb|Rgba color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function getColorFromRgbValue(value) {
|
||
if (!value) {
|
||
console.error('getColorFromRgbValue: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var valueLength = value.length;
|
||
|
||
if (valueLength !== 3 && valueLength !== 4) {
|
||
console.error('getColorFromRgbValue: Value is illegal!');
|
||
return false;
|
||
}
|
||
|
||
var color = valueLength === 3 ? 'rgb(' : 'rgba(';
|
||
color += value.join(',') + ')';
|
||
return color;
|
||
}
|
||
/**
|
||
* @description Deepen color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {Number} Percent of Deepen (1-100)
|
||
* @return {String|Boolean} Rgba color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function darken(color) {
|
||
var percent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
||
|
||
if (!color) {
|
||
console.error('darken: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var rgbaValue = getRgbaValue(color);
|
||
if (!rgbaValue) return false;
|
||
rgbaValue = rgbaValue.map(function (v, i) {
|
||
return i === 3 ? v : v - Math.ceil(2.55 * percent);
|
||
}).map(function (v) {
|
||
return v < 0 ? 0 : v;
|
||
});
|
||
return getColorFromRgbValue(rgbaValue);
|
||
}
|
||
/**
|
||
* @description Brighten color
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @return {Number} Percent of brighten (1-100)
|
||
* @return {String|Boolean} Rgba color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function lighten(color) {
|
||
var percent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
||
|
||
if (!color) {
|
||
console.error('lighten: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var rgbaValue = getRgbaValue(color);
|
||
if (!rgbaValue) return false;
|
||
rgbaValue = rgbaValue.map(function (v, i) {
|
||
return i === 3 ? v : v + Math.ceil(2.55 * percent);
|
||
}).map(function (v) {
|
||
return v > 255 ? 255 : v;
|
||
});
|
||
return getColorFromRgbValue(rgbaValue);
|
||
}
|
||
/**
|
||
* @description Adjust color opacity
|
||
* @param {String} color Hex|Rgb|Rgba color or color keyword
|
||
* @param {Number} Percent of opacity
|
||
* @return {String|Boolean} Rgba color (Invalid input will return false)
|
||
*/
|
||
|
||
|
||
function fade(color) {
|
||
var percent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
|
||
|
||
if (!color) {
|
||
console.error('fade: Missing parameters!');
|
||
return false;
|
||
}
|
||
|
||
var rgbValue = getRgbValue(color);
|
||
if (!rgbValue) return false;
|
||
var rgbaValue = [].concat((0, _toConsumableArray2["default"])(rgbValue), [percent / 100]);
|
||
return getColorFromRgbValue(rgbaValue);
|
||
}
|
||
|
||
var _default = {
|
||
fade: fade,
|
||
toHex: toHex,
|
||
toRgb: toRgb,
|
||
darken: darken,
|
||
lighten: lighten,
|
||
getOpacity: getOpacity,
|
||
getRgbValue: getRgbValue,
|
||
getRgbaValue: getRgbaValue,
|
||
getColorFromRgbValue: getColorFromRgbValue
|
||
};
|
||
exports["default"] = _default;
|
||
},{"./config/keywords":55,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/toConsumableArray":42}],57:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports["default"] = exports.easeInOutBounce = exports.easeOutBounce = exports.easeInBounce = exports.easeInOutElastic = exports.easeOutElastic = exports.easeInElastic = exports.easeInOutBack = exports.easeOutBack = exports.easeInBack = exports.easeInOutQuint = exports.easeOutQuint = exports.easeInQuint = exports.easeInOutQuart = exports.easeOutQuart = exports.easeInQuart = exports.easeInOutCubic = exports.easeOutCubic = exports.easeInCubic = exports.easeInOutQuad = exports.easeOutQuad = exports.easeInQuad = exports.easeInOutSine = exports.easeOutSine = exports.easeInSine = exports.linear = void 0;
|
||
var linear = [[[0, 1], '', [0.33, 0.67]], [[1, 0], [0.67, 0.33]]];
|
||
/**
|
||
* @description Sine
|
||
*/
|
||
|
||
exports.linear = linear;
|
||
var easeInSine = [[[0, 1]], [[0.538, 0.564], [0.169, 0.912], [0.880, 0.196]], [[1, 0]]];
|
||
exports.easeInSine = easeInSine;
|
||
var easeOutSine = [[[0, 1]], [[0.444, 0.448], [0.169, 0.736], [0.718, 0.16]], [[1, 0]]];
|
||
exports.easeOutSine = easeOutSine;
|
||
var easeInOutSine = [[[0, 1]], [[0.5, 0.5], [0.2, 1], [0.8, 0]], [[1, 0]]];
|
||
/**
|
||
* @description Quad
|
||
*/
|
||
|
||
exports.easeInOutSine = easeInOutSine;
|
||
var easeInQuad = [[[0, 1]], [[0.550, 0.584], [0.231, 0.904], [0.868, 0.264]], [[1, 0]]];
|
||
exports.easeInQuad = easeInQuad;
|
||
var easeOutQuad = [[[0, 1]], [[0.413, 0.428], [0.065, 0.816], [0.760, 0.04]], [[1, 0]]];
|
||
exports.easeOutQuad = easeOutQuad;
|
||
var easeInOutQuad = [[[0, 1]], [[0.5, 0.5], [0.3, 0.9], [0.7, 0.1]], [[1, 0]]];
|
||
/**
|
||
* @description Cubic
|
||
*/
|
||
|
||
exports.easeInOutQuad = easeInOutQuad;
|
||
var easeInCubic = [[[0, 1]], [[0.679, 0.688], [0.366, 0.992], [0.992, 0.384]], [[1, 0]]];
|
||
exports.easeInCubic = easeInCubic;
|
||
var easeOutCubic = [[[0, 1]], [[0.321, 0.312], [0.008, 0.616], [0.634, 0.008]], [[1, 0]]];
|
||
exports.easeOutCubic = easeOutCubic;
|
||
var easeInOutCubic = [[[0, 1]], [[0.5, 0.5], [0.3, 1], [0.7, 0]], [[1, 0]]];
|
||
/**
|
||
* @description Quart
|
||
*/
|
||
|
||
exports.easeInOutCubic = easeInOutCubic;
|
||
var easeInQuart = [[[0, 1]], [[0.812, 0.74], [0.611, 0.988], [1.013, 0.492]], [[1, 0]]];
|
||
exports.easeInQuart = easeInQuart;
|
||
var easeOutQuart = [[[0, 1]], [[0.152, 0.244], [0.001, 0.448], [0.285, -0.02]], [[1, 0]]];
|
||
exports.easeOutQuart = easeOutQuart;
|
||
var easeInOutQuart = [[[0, 1]], [[0.5, 0.5], [0.4, 1], [0.6, 0]], [[1, 0]]];
|
||
/**
|
||
* @description Quint
|
||
*/
|
||
|
||
exports.easeInOutQuart = easeInOutQuart;
|
||
var easeInQuint = [[[0, 1]], [[0.857, 0.856], [0.714, 1], [1, 0.712]], [[1, 0]]];
|
||
exports.easeInQuint = easeInQuint;
|
||
var easeOutQuint = [[[0, 1]], [[0.108, 0.2], [0.001, 0.4], [0.214, -0.012]], [[1, 0]]];
|
||
exports.easeOutQuint = easeOutQuint;
|
||
var easeInOutQuint = [[[0, 1]], [[0.5, 0.5], [0.5, 1], [0.5, 0]], [[1, 0]]];
|
||
/**
|
||
* @description Back
|
||
*/
|
||
|
||
exports.easeInOutQuint = easeInOutQuint;
|
||
var easeInBack = [[[0, 1]], [[0.667, 0.896], [0.380, 1.184], [0.955, 0.616]], [[1, 0]]];
|
||
exports.easeInBack = easeInBack;
|
||
var easeOutBack = [[[0, 1]], [[0.335, 0.028], [0.061, 0.22], [0.631, -0.18]], [[1, 0]]];
|
||
exports.easeOutBack = easeOutBack;
|
||
var easeInOutBack = [[[0, 1]], [[0.5, 0.5], [0.4, 1.4], [0.6, -0.4]], [[1, 0]]];
|
||
/**
|
||
* @description Elastic
|
||
*/
|
||
|
||
exports.easeInOutBack = easeInOutBack;
|
||
var easeInElastic = [[[0, 1]], [[0.474, 0.964], [0.382, 0.988], [0.557, 0.952]], [[0.619, 1.076], [0.565, 1.088], [0.669, 1.08]], [[0.770, 0.916], [0.712, 0.924], [0.847, 0.904]], [[0.911, 1.304], [0.872, 1.316], [0.961, 1.34]], [[1, 0]]];
|
||
exports.easeInElastic = easeInElastic;
|
||
var easeOutElastic = [[[0, 1]], [[0.073, -0.32], [0.034, -0.328], [0.104, -0.344]], [[0.191, 0.092], [0.110, 0.06], [0.256, 0.08]], [[0.310, -0.076], [0.260, -0.068], [0.357, -0.076]], [[0.432, 0.032], [0.362, 0.028], [0.683, -0.004]], [[1, 0]]];
|
||
exports.easeOutElastic = easeOutElastic;
|
||
var easeInOutElastic = [[[0, 1]], [[0.210, 0.94], [0.167, 0.884], [0.252, 0.98]], [[0.299, 1.104], [0.256, 1.092], [0.347, 1.108]], [[0.5, 0.496], [0.451, 0.672], [0.548, 0.324]], [[0.696, -0.108], [0.652, -0.112], [0.741, -0.124]], [[0.805, 0.064], [0.756, 0.012], [0.866, 0.096]], [[1, 0]]];
|
||
/**
|
||
* @description Bounce
|
||
*/
|
||
|
||
exports.easeInOutElastic = easeInOutElastic;
|
||
var easeInBounce = [[[0, 1]], [[0.148, 1], [0.075, 0.868], [0.193, 0.848]], [[0.326, 1], [0.276, 0.836], [0.405, 0.712]], [[0.600, 1], [0.511, 0.708], [0.671, 0.348]], [[1, 0]]];
|
||
exports.easeInBounce = easeInBounce;
|
||
var easeOutBounce = [[[0, 1]], [[0.357, 0.004], [0.270, 0.592], [0.376, 0.252]], [[0.604, -0.004], [0.548, 0.312], [0.669, 0.184]], [[0.820, 0], [0.749, 0.184], [0.905, 0.132]], [[1, 0]]];
|
||
exports.easeOutBounce = easeOutBounce;
|
||
var easeInOutBounce = [[[0, 1]], [[0.102, 1], [0.050, 0.864], [0.117, 0.86]], [[0.216, 0.996], [0.208, 0.844], [0.227, 0.808]], [[0.347, 0.996], [0.343, 0.8], [0.480, 0.292]], [[0.635, 0.004], [0.511, 0.676], [0.656, 0.208]], [[0.787, 0], [0.760, 0.2], [0.795, 0.144]], [[0.905, -0.004], [0.899, 0.164], [0.944, 0.144]], [[1, 0]]];
|
||
exports.easeInOutBounce = easeInOutBounce;
|
||
|
||
var _default = new Map([['linear', linear], ['easeInSine', easeInSine], ['easeOutSine', easeOutSine], ['easeInOutSine', easeInOutSine], ['easeInQuad', easeInQuad], ['easeOutQuad', easeOutQuad], ['easeInOutQuad', easeInOutQuad], ['easeInCubic', easeInCubic], ['easeOutCubic', easeOutCubic], ['easeInOutCubic', easeInOutCubic], ['easeInQuart', easeInQuart], ['easeOutQuart', easeOutQuart], ['easeInOutQuart', easeInOutQuart], ['easeInQuint', easeInQuint], ['easeOutQuint', easeOutQuint], ['easeInOutQuint', easeInOutQuint], ['easeInBack', easeInBack], ['easeOutBack', easeOutBack], ['easeInOutBack', easeInOutBack], ['easeInElastic', easeInElastic], ['easeOutElastic', easeOutElastic], ['easeInOutElastic', easeInOutElastic], ['easeInBounce', easeInBounce], ['easeOutBounce', easeOutBounce], ['easeInOutBounce', easeInOutBounce]]);
|
||
|
||
exports["default"] = _default;
|
||
},{}],58:[function(require,module,exports){
|
||
"use strict";
|
||
|
||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.transition = transition;
|
||
exports.injectNewCurve = injectNewCurve;
|
||
exports["default"] = void 0;
|
||
|
||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
||
|
||
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
||
|
||
var _curves = _interopRequireDefault(require("./config/curves"));
|
||
|
||
var defaultTransitionBC = 'linear';
|
||
/**
|
||
* @description Get the N-frame animation state by the start and end state
|
||
* of the animation and the easing curve
|
||
* @param {String|Array} tBC Easing curve name or data
|
||
* @param {Number|Array|Object} startState Animation start state
|
||
* @param {Number|Array|Object} endState Animation end state
|
||
* @param {Number} frameNum Number of Animation frames
|
||
* @param {Boolean} deep Whether to use recursive mode
|
||
* @return {Array|Boolean} State of each frame of the animation (Invalid input will return false)
|
||
*/
|
||
|
||
function transition(tBC) {
|
||
var startState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||
var endState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||
var frameNum = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 30;
|
||
var deep = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
||
if (!checkParams.apply(void 0, arguments)) return false;
|
||
|
||
try {
|
||
// Get the transition bezier curve
|
||
var bezierCurve = getBezierCurve(tBC); // Get the progress of each frame state
|
||
|
||
var frameStateProgress = getFrameStateProgress(bezierCurve, frameNum); // If the recursion mode is not enabled or the state type is Number, the shallow state calculation is performed directly.
|
||
|
||
if (!deep || typeof endState === 'number') return getTransitionState(startState, endState, frameStateProgress);
|
||
return recursionTransitionState(startState, endState, frameStateProgress);
|
||
} catch (_unused) {
|
||
console.warn('Transition parameter may be abnormal!');
|
||
return [endState];
|
||
}
|
||
}
|
||
/**
|
||
* @description Check if the parameters are legal
|
||
* @param {String} tBC Name of transition bezier curve
|
||
* @param {Any} startState Transition start state
|
||
* @param {Any} endState Transition end state
|
||
* @param {Number} frameNum Number of transition frames
|
||
* @return {Boolean} Is the parameter legal
|
||
*/
|
||
|
||
|
||
function checkParams(tBC) {
|
||
var startState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||
var endState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
||
var frameNum = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 30;
|
||
|
||
if (!tBC || startState === false || endState === false || !frameNum) {
|
||
console.error('transition: Missing Parameters!');
|
||
return false;
|
||
}
|
||
|
||
if ((0, _typeof2["default"])(startState) !== (0, _typeof2["default"])(endState)) {
|
||
console.error('transition: Inconsistent Status Types!');
|
||
return false;
|
||
}
|
||
|
||
var stateType = (0, _typeof2["default"])(endState);
|
||
|
||
if (stateType === 'string' || stateType === 'boolean' || !tBC.length) {
|
||
console.error('transition: Unsupported Data Type of State!');
|
||
return false;
|
||
}
|
||
|
||
if (!_curves["default"].has(tBC) && !(tBC instanceof Array)) {
|
||
console.warn('transition: Transition curve not found, default curve will be used!');
|
||
}
|
||
|
||
return true;
|
||
}
|
||
/**
|
||
* @description Get the transition bezier curve
|
||
* @param {String} tBC Name of transition bezier curve
|
||
* @return {Array} Bezier curve data
|
||
*/
|
||
|
||
|
||
function getBezierCurve(tBC) {
|
||
var bezierCurve = '';
|
||
|
||
if (_curves["default"].has(tBC)) {
|
||
bezierCurve = _curves["default"].get(tBC);
|
||
} else if (tBC instanceof Array) {
|
||
bezierCurve = tBC;
|
||
} else {
|
||
bezierCurve = _curves["default"].get(defaultTransitionBC);
|
||
}
|
||
|
||
return bezierCurve;
|
||
}
|
||
/**
|
||
* @description Get the progress of each frame state
|
||
* @param {Array} bezierCurve Transition bezier curve
|
||
* @param {Number} frameNum Number of transition frames
|
||
* @return {Array} Progress of each frame state
|
||
*/
|
||
|
||
|
||
function getFrameStateProgress(bezierCurve, frameNum) {
|
||
var tMinus = 1 / (frameNum - 1);
|
||
var tState = new Array(frameNum).fill(0).map(function (t, i) {
|
||
return i * tMinus;
|
||
});
|
||
var frameState = tState.map(function (t) {
|
||
return getFrameStateFromT(bezierCurve, t);
|
||
});
|
||
return frameState;
|
||
}
|
||
/**
|
||
* @description Get the progress of the corresponding frame according to t
|
||
* @param {Array} bezierCurve Transition bezier curve
|
||
* @param {Number} t Current frame t
|
||
* @return {Number} Progress of current frame
|
||
*/
|
||
|
||
|
||
function getFrameStateFromT(bezierCurve, t) {
|
||
var tBezierCurvePoint = getBezierCurvePointFromT(bezierCurve, t);
|
||
var bezierCurvePointT = getBezierCurvePointTFromReT(tBezierCurvePoint, t);
|
||
return getBezierCurveTState(tBezierCurvePoint, bezierCurvePointT);
|
||
}
|
||
/**
|
||
* @description Get the corresponding sub-curve according to t
|
||
* @param {Array} bezierCurve Transition bezier curve
|
||
* @param {Number} t Current frame t
|
||
* @return {Array} Sub-curve of t
|
||
*/
|
||
|
||
|
||
function getBezierCurvePointFromT(bezierCurve, t) {
|
||
var lastIndex = bezierCurve.length - 1;
|
||
var begin = '',
|
||
end = '';
|
||
bezierCurve.findIndex(function (item, i) {
|
||
if (i === lastIndex) return;
|
||
begin = item;
|
||
end = bezierCurve[i + 1];
|
||
var currentMainPointX = begin[0][0];
|
||
var nextMainPointX = end[0][0];
|
||
return t >= currentMainPointX && t < nextMainPointX;
|
||
});
|
||
var p0 = begin[0];
|
||
var p1 = begin[2] || begin[0];
|
||
var p2 = end[1] || end[0];
|
||
var p3 = end[0];
|
||
return [p0, p1, p2, p3];
|
||
}
|
||
/**
|
||
* @description Get local t based on t and sub-curve
|
||
* @param {Array} bezierCurve Sub-curve
|
||
* @param {Number} t Current frame t
|
||
* @return {Number} local t of sub-curve
|
||
*/
|
||
|
||
|
||
function getBezierCurvePointTFromReT(bezierCurve, t) {
|
||
var reBeginX = bezierCurve[0][0];
|
||
var reEndX = bezierCurve[3][0];
|
||
var xMinus = reEndX - reBeginX;
|
||
var tMinus = t - reBeginX;
|
||
return tMinus / xMinus;
|
||
}
|
||
/**
|
||
* @description Get the curve progress of t
|
||
* @param {Array} bezierCurve Sub-curve
|
||
* @param {Number} t Current frame t
|
||
* @return {Number} Progress of current frame
|
||
*/
|
||
|
||
|
||
function getBezierCurveTState(_ref, t) {
|
||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 4),
|
||
_ref2$ = (0, _slicedToArray2["default"])(_ref2[0], 2),
|
||
p0 = _ref2$[1],
|
||
_ref2$2 = (0, _slicedToArray2["default"])(_ref2[1], 2),
|
||
p1 = _ref2$2[1],
|
||
_ref2$3 = (0, _slicedToArray2["default"])(_ref2[2], 2),
|
||
p2 = _ref2$3[1],
|
||
_ref2$4 = (0, _slicedToArray2["default"])(_ref2[3], 2),
|
||
p3 = _ref2$4[1];
|
||
|
||
var pow = Math.pow;
|
||
var tMinus = 1 - t;
|
||
var result1 = p0 * pow(tMinus, 3);
|
||
var result2 = 3 * p1 * t * pow(tMinus, 2);
|
||
var result3 = 3 * p2 * pow(t, 2) * tMinus;
|
||
var result4 = p3 * pow(t, 3);
|
||
return 1 - (result1 + result2 + result3 + result4);
|
||
}
|
||
/**
|
||
* @description Get transition state according to frame progress
|
||
* @param {Any} startState Transition start state
|
||
* @param {Any} endState Transition end state
|
||
* @param {Array} frameState Frame state progress
|
||
* @return {Array} Transition frame state
|
||
*/
|
||
|
||
|
||
function getTransitionState(begin, end, frameState) {
|
||
var stateType = 'object';
|
||
if (typeof begin === 'number') stateType = 'number';
|
||
if (begin instanceof Array) stateType = 'array';
|
||
if (stateType === 'number') return getNumberTransitionState(begin, end, frameState);
|
||
if (stateType === 'array') return getArrayTransitionState(begin, end, frameState);
|
||
if (stateType === 'object') return getObjectTransitionState(begin, end, frameState);
|
||
return frameState.map(function (t) {
|
||
return end;
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the transition data of the number type
|
||
* @param {Number} startState Transition start state
|
||
* @param {Number} endState Transition end state
|
||
* @param {Array} frameState Frame state progress
|
||
* @return {Array} Transition frame state
|
||
*/
|
||
|
||
|
||
function getNumberTransitionState(begin, end, frameState) {
|
||
var minus = end - begin;
|
||
return frameState.map(function (s) {
|
||
return begin + minus * s;
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the transition data of the array type
|
||
* @param {Array} startState Transition start state
|
||
* @param {Array} endState Transition end state
|
||
* @param {Array} frameState Frame state progress
|
||
* @return {Array} Transition frame state
|
||
*/
|
||
|
||
|
||
function getArrayTransitionState(begin, end, frameState) {
|
||
var minus = end.map(function (v, i) {
|
||
if (typeof v !== 'number') return false;
|
||
return v - begin[i];
|
||
});
|
||
return frameState.map(function (s) {
|
||
return minus.map(function (v, i) {
|
||
if (v === false) return end[i];
|
||
return begin[i] + v * s;
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the transition data of the object type
|
||
* @param {Object} startState Transition start state
|
||
* @param {Object} endState Transition end state
|
||
* @param {Array} frameState Frame state progress
|
||
* @return {Array} Transition frame state
|
||
*/
|
||
|
||
|
||
function getObjectTransitionState(begin, end, frameState) {
|
||
var keys = Object.keys(end);
|
||
var beginValue = keys.map(function (k) {
|
||
return begin[k];
|
||
});
|
||
var endValue = keys.map(function (k) {
|
||
return end[k];
|
||
});
|
||
var arrayState = getArrayTransitionState(beginValue, endValue, frameState);
|
||
return arrayState.map(function (item) {
|
||
var frameData = {};
|
||
item.forEach(function (v, i) {
|
||
return frameData[keys[i]] = v;
|
||
});
|
||
return frameData;
|
||
});
|
||
}
|
||
/**
|
||
* @description Get the transition state data by recursion
|
||
* @param {Array|Object} startState Transition start state
|
||
* @param {Array|Object} endState Transition end state
|
||
* @param {Array} frameState Frame state progress
|
||
* @return {Array} Transition frame state
|
||
*/
|
||
|
||
|
||
function recursionTransitionState(begin, end, frameState) {
|
||
var state = getTransitionState(begin, end, frameState);
|
||
|
||
var _loop = function _loop(key) {
|
||
var bTemp = begin[key];
|
||
var eTemp = end[key];
|
||
if ((0, _typeof2["default"])(eTemp) !== 'object') return "continue";
|
||
var data = recursionTransitionState(bTemp, eTemp, frameState);
|
||
state.forEach(function (fs, i) {
|
||
return fs[key] = data[i];
|
||
});
|
||
};
|
||
|
||
for (var key in end) {
|
||
var _ret = _loop(key);
|
||
|
||
if (_ret === "continue") continue;
|
||
}
|
||
|
||
return state;
|
||
}
|
||
/**
|
||
* @description Inject new curve into curves as config
|
||
* @param {Any} key The key of curve
|
||
* @param {Array} curve Bezier curve data
|
||
* @return {Undefined} No return
|
||
*/
|
||
|
||
|
||
function injectNewCurve(key, curve) {
|
||
if (!key || !curve) {
|
||
console.error('InjectNewCurve Missing Parameters!');
|
||
return;
|
||
}
|
||
|
||
_curves["default"].set(key, curve);
|
||
}
|
||
|
||
var _default = transition;
|
||
exports["default"] = _default;
|
||
},{"./config/curves":57,"@babel/runtime/helpers/interopRequireDefault":36,"@babel/runtime/helpers/slicedToArray":41,"@babel/runtime/helpers/typeof":43}],59:[function(require,module,exports){
|
||
/**
|
||
* Copyright (c) 2014-present, Facebook, Inc.
|
||
*
|
||
* This source code is licensed under the MIT license found in the
|
||
* LICENSE file in the root directory of this source tree.
|
||
*/
|
||
|
||
var runtime = (function (exports) {
|
||
"use strict";
|
||
|
||
var Op = Object.prototype;
|
||
var hasOwn = Op.hasOwnProperty;
|
||
var undefined; // More compressible than void 0.
|
||
var $Symbol = typeof Symbol === "function" ? Symbol : {};
|
||
var iteratorSymbol = $Symbol.iterator || "@@iterator";
|
||
var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
|
||
var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
|
||
|
||
function wrap(innerFn, outerFn, self, tryLocsList) {
|
||
// If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
|
||
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
|
||
var generator = Object.create(protoGenerator.prototype);
|
||
var context = new Context(tryLocsList || []);
|
||
|
||
// The ._invoke method unifies the implementations of the .next,
|
||
// .throw, and .return methods.
|
||
generator._invoke = makeInvokeMethod(innerFn, self, context);
|
||
|
||
return generator;
|
||
}
|
||
exports.wrap = wrap;
|
||
|
||
// Try/catch helper to minimize deoptimizations. Returns a completion
|
||
// record like context.tryEntries[i].completion. This interface could
|
||
// have been (and was previously) designed to take a closure to be
|
||
// invoked without arguments, but in all the cases we care about we
|
||
// already have an existing method we want to call, so there's no need
|
||
// to create a new function object. We can even get away with assuming
|
||
// the method takes exactly one argument, since that happens to be true
|
||
// in every case, so we don't have to touch the arguments object. The
|
||
// only additional allocation required is the completion record, which
|
||
// has a stable shape and so hopefully should be cheap to allocate.
|
||
function tryCatch(fn, obj, arg) {
|
||
try {
|
||
return { type: "normal", arg: fn.call(obj, arg) };
|
||
} catch (err) {
|
||
return { type: "throw", arg: err };
|
||
}
|
||
}
|
||
|
||
var GenStateSuspendedStart = "suspendedStart";
|
||
var GenStateSuspendedYield = "suspendedYield";
|
||
var GenStateExecuting = "executing";
|
||
var GenStateCompleted = "completed";
|
||
|
||
// Returning this object from the innerFn has the same effect as
|
||
// breaking out of the dispatch switch statement.
|
||
var ContinueSentinel = {};
|
||
|
||
// Dummy constructor functions that we use as the .constructor and
|
||
// .constructor.prototype properties for functions that return Generator
|
||
// objects. For full spec compliance, you may wish to configure your
|
||
// minifier not to mangle the names of these two functions.
|
||
function Generator() {}
|
||
function GeneratorFunction() {}
|
||
function GeneratorFunctionPrototype() {}
|
||
|
||
// This is a polyfill for %IteratorPrototype% for environments that
|
||
// don't natively support it.
|
||
var IteratorPrototype = {};
|
||
IteratorPrototype[iteratorSymbol] = function () {
|
||
return this;
|
||
};
|
||
|
||
var getProto = Object.getPrototypeOf;
|
||
var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
|
||
if (NativeIteratorPrototype &&
|
||
NativeIteratorPrototype !== Op &&
|
||
hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
|
||
// This environment has a native %IteratorPrototype%; use it instead
|
||
// of the polyfill.
|
||
IteratorPrototype = NativeIteratorPrototype;
|
||
}
|
||
|
||
var Gp = GeneratorFunctionPrototype.prototype =
|
||
Generator.prototype = Object.create(IteratorPrototype);
|
||
GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
|
||
GeneratorFunctionPrototype.constructor = GeneratorFunction;
|
||
GeneratorFunctionPrototype[toStringTagSymbol] =
|
||
GeneratorFunction.displayName = "GeneratorFunction";
|
||
|
||
// Helper for defining the .next, .throw, and .return methods of the
|
||
// Iterator interface in terms of a single ._invoke method.
|
||
function defineIteratorMethods(prototype) {
|
||
["next", "throw", "return"].forEach(function(method) {
|
||
prototype[method] = function(arg) {
|
||
return this._invoke(method, arg);
|
||
};
|
||
});
|
||
}
|
||
|
||
exports.isGeneratorFunction = function(genFun) {
|
||
var ctor = typeof genFun === "function" && genFun.constructor;
|
||
return ctor
|
||
? ctor === GeneratorFunction ||
|
||
// For the native GeneratorFunction constructor, the best we can
|
||
// do is to check its .name property.
|
||
(ctor.displayName || ctor.name) === "GeneratorFunction"
|
||
: false;
|
||
};
|
||
|
||
exports.mark = function(genFun) {
|
||
if (Object.setPrototypeOf) {
|
||
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
|
||
} else {
|
||
genFun.__proto__ = GeneratorFunctionPrototype;
|
||
if (!(toStringTagSymbol in genFun)) {
|
||
genFun[toStringTagSymbol] = "GeneratorFunction";
|
||
}
|
||
}
|
||
genFun.prototype = Object.create(Gp);
|
||
return genFun;
|
||
};
|
||
|
||
// Within the body of any async function, `await x` is transformed to
|
||
// `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
|
||
// `hasOwn.call(value, "__await")` to determine if the yielded value is
|
||
// meant to be awaited.
|
||
exports.awrap = function(arg) {
|
||
return { __await: arg };
|
||
};
|
||
|
||
function AsyncIterator(generator) {
|
||
function invoke(method, arg, resolve, reject) {
|
||
var record = tryCatch(generator[method], generator, arg);
|
||
if (record.type === "throw") {
|
||
reject(record.arg);
|
||
} else {
|
||
var result = record.arg;
|
||
var value = result.value;
|
||
if (value &&
|
||
typeof value === "object" &&
|
||
hasOwn.call(value, "__await")) {
|
||
return Promise.resolve(value.__await).then(function(value) {
|
||
invoke("next", value, resolve, reject);
|
||
}, function(err) {
|
||
invoke("throw", err, resolve, reject);
|
||
});
|
||
}
|
||
|
||
return Promise.resolve(value).then(function(unwrapped) {
|
||
// When a yielded Promise is resolved, its final value becomes
|
||
// the .value of the Promise<{value,done}> result for the
|
||
// current iteration.
|
||
result.value = unwrapped;
|
||
resolve(result);
|
||
}, function(error) {
|
||
// If a rejected Promise was yielded, throw the rejection back
|
||
// into the async generator function so it can be handled there.
|
||
return invoke("throw", error, resolve, reject);
|
||
});
|
||
}
|
||
}
|
||
|
||
var previousPromise;
|
||
|
||
function enqueue(method, arg) {
|
||
function callInvokeWithMethodAndArg() {
|
||
return new Promise(function(resolve, reject) {
|
||
invoke(method, arg, resolve, reject);
|
||
});
|
||
}
|
||
|
||
return previousPromise =
|
||
// If enqueue has been called before, then we want to wait until
|
||
// all previous Promises have been resolved before calling invoke,
|
||
// so that results are always delivered in the correct order. If
|
||
// enqueue has not been called before, then it is important to
|
||
// call invoke immediately, without waiting on a callback to fire,
|
||
// so that the async generator function has the opportunity to do
|
||
// any necessary setup in a predictable way. This predictability
|
||
// is why the Promise constructor synchronously invokes its
|
||
// executor callback, and why async functions synchronously
|
||
// execute code before the first await. Since we implement simple
|
||
// async functions in terms of async generators, it is especially
|
||
// important to get this right, even though it requires care.
|
||
previousPromise ? previousPromise.then(
|
||
callInvokeWithMethodAndArg,
|
||
// Avoid propagating failures to Promises returned by later
|
||
// invocations of the iterator.
|
||
callInvokeWithMethodAndArg
|
||
) : callInvokeWithMethodAndArg();
|
||
}
|
||
|
||
// Define the unified helper method that is used to implement .next,
|
||
// .throw, and .return (see defineIteratorMethods).
|
||
this._invoke = enqueue;
|
||
}
|
||
|
||
defineIteratorMethods(AsyncIterator.prototype);
|
||
AsyncIterator.prototype[asyncIteratorSymbol] = function () {
|
||
return this;
|
||
};
|
||
exports.AsyncIterator = AsyncIterator;
|
||
|
||
// Note that simple async functions are implemented on top of
|
||
// AsyncIterator objects; they just return a Promise for the value of
|
||
// the final result produced by the iterator.
|
||
exports.async = function(innerFn, outerFn, self, tryLocsList) {
|
||
var iter = new AsyncIterator(
|
||
wrap(innerFn, outerFn, self, tryLocsList)
|
||
);
|
||
|
||
return exports.isGeneratorFunction(outerFn)
|
||
? iter // If outerFn is a generator, return the full iterator.
|
||
: iter.next().then(function(result) {
|
||
return result.done ? result.value : iter.next();
|
||
});
|
||
};
|
||
|
||
function makeInvokeMethod(innerFn, self, context) {
|
||
var state = GenStateSuspendedStart;
|
||
|
||
return function invoke(method, arg) {
|
||
if (state === GenStateExecuting) {
|
||
throw new Error("Generator is already running");
|
||
}
|
||
|
||
if (state === GenStateCompleted) {
|
||
if (method === "throw") {
|
||
throw arg;
|
||
}
|
||
|
||
// Be forgiving, per 25.3.3.3.3 of the spec:
|
||
// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
|
||
return doneResult();
|
||
}
|
||
|
||
context.method = method;
|
||
context.arg = arg;
|
||
|
||
while (true) {
|
||
var delegate = context.delegate;
|
||
if (delegate) {
|
||
var delegateResult = maybeInvokeDelegate(delegate, context);
|
||
if (delegateResult) {
|
||
if (delegateResult === ContinueSentinel) continue;
|
||
return delegateResult;
|
||
}
|
||
}
|
||
|
||
if (context.method === "next") {
|
||
// Setting context._sent for legacy support of Babel's
|
||
// function.sent implementation.
|
||
context.sent = context._sent = context.arg;
|
||
|
||
} else if (context.method === "throw") {
|
||
if (state === GenStateSuspendedStart) {
|
||
state = GenStateCompleted;
|
||
throw context.arg;
|
||
}
|
||
|
||
context.dispatchException(context.arg);
|
||
|
||
} else if (context.method === "return") {
|
||
context.abrupt("return", context.arg);
|
||
}
|
||
|
||
state = GenStateExecuting;
|
||
|
||
var record = tryCatch(innerFn, self, context);
|
||
if (record.type === "normal") {
|
||
// If an exception is thrown from innerFn, we leave state ===
|
||
// GenStateExecuting and loop back for another invocation.
|
||
state = context.done
|
||
? GenStateCompleted
|
||
: GenStateSuspendedYield;
|
||
|
||
if (record.arg === ContinueSentinel) {
|
||
continue;
|
||
}
|
||
|
||
return {
|
||
value: record.arg,
|
||
done: context.done
|
||
};
|
||
|
||
} else if (record.type === "throw") {
|
||
state = GenStateCompleted;
|
||
// Dispatch the exception by looping back around to the
|
||
// context.dispatchException(context.arg) call above.
|
||
context.method = "throw";
|
||
context.arg = record.arg;
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
// Call delegate.iterator[context.method](context.arg) and handle the
|
||
// result, either by returning a { value, done } result from the
|
||
// delegate iterator, or by modifying context.method and context.arg,
|
||
// setting context.delegate to null, and returning the ContinueSentinel.
|
||
function maybeInvokeDelegate(delegate, context) {
|
||
var method = delegate.iterator[context.method];
|
||
if (method === undefined) {
|
||
// A .throw or .return when the delegate iterator has no .throw
|
||
// method always terminates the yield* loop.
|
||
context.delegate = null;
|
||
|
||
if (context.method === "throw") {
|
||
// Note: ["return"] must be used for ES3 parsing compatibility.
|
||
if (delegate.iterator["return"]) {
|
||
// If the delegate iterator has a return method, give it a
|
||
// chance to clean up.
|
||
context.method = "return";
|
||
context.arg = undefined;
|
||
maybeInvokeDelegate(delegate, context);
|
||
|
||
if (context.method === "throw") {
|
||
// If maybeInvokeDelegate(context) changed context.method from
|
||
// "return" to "throw", let that override the TypeError below.
|
||
return ContinueSentinel;
|
||
}
|
||
}
|
||
|
||
context.method = "throw";
|
||
context.arg = new TypeError(
|
||
"The iterator does not provide a 'throw' method");
|
||
}
|
||
|
||
return ContinueSentinel;
|
||
}
|
||
|
||
var record = tryCatch(method, delegate.iterator, context.arg);
|
||
|
||
if (record.type === "throw") {
|
||
context.method = "throw";
|
||
context.arg = record.arg;
|
||
context.delegate = null;
|
||
return ContinueSentinel;
|
||
}
|
||
|
||
var info = record.arg;
|
||
|
||
if (! info) {
|
||
context.method = "throw";
|
||
context.arg = new TypeError("iterator result is not an object");
|
||
context.delegate = null;
|
||
return ContinueSentinel;
|
||
}
|
||
|
||
if (info.done) {
|
||
// Assign the result of the finished delegate to the temporary
|
||
// variable specified by delegate.resultName (see delegateYield).
|
||
context[delegate.resultName] = info.value;
|
||
|
||
// Resume execution at the desired location (see delegateYield).
|
||
context.next = delegate.nextLoc;
|
||
|
||
// If context.method was "throw" but the delegate handled the
|
||
// exception, let the outer generator proceed normally. If
|
||
// context.method was "next", forget context.arg since it has been
|
||
// "consumed" by the delegate iterator. If context.method was
|
||
// "return", allow the original .return call to continue in the
|
||
// outer generator.
|
||
if (context.method !== "return") {
|
||
context.method = "next";
|
||
context.arg = undefined;
|
||
}
|
||
|
||
} else {
|
||
// Re-yield the result returned by the delegate method.
|
||
return info;
|
||
}
|
||
|
||
// The delegate iterator is finished, so forget it and continue with
|
||
// the outer generator.
|
||
context.delegate = null;
|
||
return ContinueSentinel;
|
||
}
|
||
|
||
// Define Generator.prototype.{next,throw,return} in terms of the
|
||
// unified ._invoke helper method.
|
||
defineIteratorMethods(Gp);
|
||
|
||
Gp[toStringTagSymbol] = "Generator";
|
||
|
||
// A Generator should always return itself as the iterator object when the
|
||
// @@iterator function is called on it. Some browsers' implementations of the
|
||
// iterator prototype chain incorrectly implement this, causing the Generator
|
||
// object to not be returned from this call. This ensures that doesn't happen.
|
||
// See https://github.com/facebook/regenerator/issues/274 for more details.
|
||
Gp[iteratorSymbol] = function() {
|
||
return this;
|
||
};
|
||
|
||
Gp.toString = function() {
|
||
return "[object Generator]";
|
||
};
|
||
|
||
function pushTryEntry(locs) {
|
||
var entry = { tryLoc: locs[0] };
|
||
|
||
if (1 in locs) {
|
||
entry.catchLoc = locs[1];
|
||
}
|
||
|
||
if (2 in locs) {
|
||
entry.finallyLoc = locs[2];
|
||
entry.afterLoc = locs[3];
|
||
}
|
||
|
||
this.tryEntries.push(entry);
|
||
}
|
||
|
||
function resetTryEntry(entry) {
|
||
var record = entry.completion || {};
|
||
record.type = "normal";
|
||
delete record.arg;
|
||
entry.completion = record;
|
||
}
|
||
|
||
function Context(tryLocsList) {
|
||
// The root entry object (effectively a try statement without a catch
|
||
// or a finally block) gives us a place to store values thrown from
|
||
// locations where there is no enclosing try statement.
|
||
this.tryEntries = [{ tryLoc: "root" }];
|
||
tryLocsList.forEach(pushTryEntry, this);
|
||
this.reset(true);
|
||
}
|
||
|
||
exports.keys = function(object) {
|
||
var keys = [];
|
||
for (var key in object) {
|
||
keys.push(key);
|
||
}
|
||
keys.reverse();
|
||
|
||
// Rather than returning an object with a next method, we keep
|
||
// things simple and return the next function itself.
|
||
return function next() {
|
||
while (keys.length) {
|
||
var key = keys.pop();
|
||
if (key in object) {
|
||
next.value = key;
|
||
next.done = false;
|
||
return next;
|
||
}
|
||
}
|
||
|
||
// To avoid creating an additional object, we just hang the .value
|
||
// and .done properties off the next function object itself. This
|
||
// also ensures that the minifier will not anonymize the function.
|
||
next.done = true;
|
||
return next;
|
||
};
|
||
};
|
||
|
||
function values(iterable) {
|
||
if (iterable) {
|
||
var iteratorMethod = iterable[iteratorSymbol];
|
||
if (iteratorMethod) {
|
||
return iteratorMethod.call(iterable);
|
||
}
|
||
|
||
if (typeof iterable.next === "function") {
|
||
return iterable;
|
||
}
|
||
|
||
if (!isNaN(iterable.length)) {
|
||
var i = -1, next = function next() {
|
||
while (++i < iterable.length) {
|
||
if (hasOwn.call(iterable, i)) {
|
||
next.value = iterable[i];
|
||
next.done = false;
|
||
return next;
|
||
}
|
||
}
|
||
|
||
next.value = undefined;
|
||
next.done = true;
|
||
|
||
return next;
|
||
};
|
||
|
||
return next.next = next;
|
||
}
|
||
}
|
||
|
||
// Return an iterator with no values.
|
||
return { next: doneResult };
|
||
}
|
||
exports.values = values;
|
||
|
||
function doneResult() {
|
||
return { value: undefined, done: true };
|
||
}
|
||
|
||
Context.prototype = {
|
||
constructor: Context,
|
||
|
||
reset: function(skipTempReset) {
|
||
this.prev = 0;
|
||
this.next = 0;
|
||
// Resetting context._sent for legacy support of Babel's
|
||
// function.sent implementation.
|
||
this.sent = this._sent = undefined;
|
||
this.done = false;
|
||
this.delegate = null;
|
||
|
||
this.method = "next";
|
||
this.arg = undefined;
|
||
|
||
this.tryEntries.forEach(resetTryEntry);
|
||
|
||
if (!skipTempReset) {
|
||
for (var name in this) {
|
||
// Not sure about the optimal order of these conditions:
|
||
if (name.charAt(0) === "t" &&
|
||
hasOwn.call(this, name) &&
|
||
!isNaN(+name.slice(1))) {
|
||
this[name] = undefined;
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
stop: function() {
|
||
this.done = true;
|
||
|
||
var rootEntry = this.tryEntries[0];
|
||
var rootRecord = rootEntry.completion;
|
||
if (rootRecord.type === "throw") {
|
||
throw rootRecord.arg;
|
||
}
|
||
|
||
return this.rval;
|
||
},
|
||
|
||
dispatchException: function(exception) {
|
||
if (this.done) {
|
||
throw exception;
|
||
}
|
||
|
||
var context = this;
|
||
function handle(loc, caught) {
|
||
record.type = "throw";
|
||
record.arg = exception;
|
||
context.next = loc;
|
||
|
||
if (caught) {
|
||
// If the dispatched exception was caught by a catch block,
|
||
// then let that catch block handle the exception normally.
|
||
context.method = "next";
|
||
context.arg = undefined;
|
||
}
|
||
|
||
return !! caught;
|
||
}
|
||
|
||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||
var entry = this.tryEntries[i];
|
||
var record = entry.completion;
|
||
|
||
if (entry.tryLoc === "root") {
|
||
// Exception thrown outside of any try block that could handle
|
||
// it, so set the completion value of the entire function to
|
||
// throw the exception.
|
||
return handle("end");
|
||
}
|
||
|
||
if (entry.tryLoc <= this.prev) {
|
||
var hasCatch = hasOwn.call(entry, "catchLoc");
|
||
var hasFinally = hasOwn.call(entry, "finallyLoc");
|
||
|
||
if (hasCatch && hasFinally) {
|
||
if (this.prev < entry.catchLoc) {
|
||
return handle(entry.catchLoc, true);
|
||
} else if (this.prev < entry.finallyLoc) {
|
||
return handle(entry.finallyLoc);
|
||
}
|
||
|
||
} else if (hasCatch) {
|
||
if (this.prev < entry.catchLoc) {
|
||
return handle(entry.catchLoc, true);
|
||
}
|
||
|
||
} else if (hasFinally) {
|
||
if (this.prev < entry.finallyLoc) {
|
||
return handle(entry.finallyLoc);
|
||
}
|
||
|
||
} else {
|
||
throw new Error("try statement without catch or finally");
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
abrupt: function(type, arg) {
|
||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||
var entry = this.tryEntries[i];
|
||
if (entry.tryLoc <= this.prev &&
|
||
hasOwn.call(entry, "finallyLoc") &&
|
||
this.prev < entry.finallyLoc) {
|
||
var finallyEntry = entry;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (finallyEntry &&
|
||
(type === "break" ||
|
||
type === "continue") &&
|
||
finallyEntry.tryLoc <= arg &&
|
||
arg <= finallyEntry.finallyLoc) {
|
||
// Ignore the finally entry if control is not jumping to a
|
||
// location outside the try/catch block.
|
||
finallyEntry = null;
|
||
}
|
||
|
||
var record = finallyEntry ? finallyEntry.completion : {};
|
||
record.type = type;
|
||
record.arg = arg;
|
||
|
||
if (finallyEntry) {
|
||
this.method = "next";
|
||
this.next = finallyEntry.finallyLoc;
|
||
return ContinueSentinel;
|
||
}
|
||
|
||
return this.complete(record);
|
||
},
|
||
|
||
complete: function(record, afterLoc) {
|
||
if (record.type === "throw") {
|
||
throw record.arg;
|
||
}
|
||
|
||
if (record.type === "break" ||
|
||
record.type === "continue") {
|
||
this.next = record.arg;
|
||
} else if (record.type === "return") {
|
||
this.rval = this.arg = record.arg;
|
||
this.method = "return";
|
||
this.next = "end";
|
||
} else if (record.type === "normal" && afterLoc) {
|
||
this.next = afterLoc;
|
||
}
|
||
|
||
return ContinueSentinel;
|
||
},
|
||
|
||
finish: function(finallyLoc) {
|
||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||
var entry = this.tryEntries[i];
|
||
if (entry.finallyLoc === finallyLoc) {
|
||
this.complete(entry.completion, entry.afterLoc);
|
||
resetTryEntry(entry);
|
||
return ContinueSentinel;
|
||
}
|
||
}
|
||
},
|
||
|
||
"catch": function(tryLoc) {
|
||
for (var i = this.tryEntries.length - 1; i >= 0; --i) {
|
||
var entry = this.tryEntries[i];
|
||
if (entry.tryLoc === tryLoc) {
|
||
var record = entry.completion;
|
||
if (record.type === "throw") {
|
||
var thrown = record.arg;
|
||
resetTryEntry(entry);
|
||
}
|
||
return thrown;
|
||
}
|
||
}
|
||
|
||
// The context.catch method must only be called with a location
|
||
// argument that corresponds to a known catch block.
|
||
throw new Error("illegal catch attempt");
|
||
},
|
||
|
||
delegateYield: function(iterable, resultName, nextLoc) {
|
||
this.delegate = {
|
||
iterator: values(iterable),
|
||
resultName: resultName,
|
||
nextLoc: nextLoc
|
||
};
|
||
|
||
if (this.method === "next") {
|
||
// Deliberately forget the last sent value so that we don't
|
||
// accidentally pass it on to the delegate.
|
||
this.arg = undefined;
|
||
}
|
||
|
||
return ContinueSentinel;
|
||
}
|
||
};
|
||
|
||
// Regardless of whether this script is executing as a CommonJS module
|
||
// or not, return the runtime object so that we can declare the variable
|
||
// regeneratorRuntime in the outer scope, which allows this module to be
|
||
// injected easily by `bin/regenerator --include-runtime script.js`.
|
||
return exports;
|
||
|
||
}(
|
||
// If this script is executing as a CommonJS module, use module.exports
|
||
// as the regeneratorRuntime namespace. Otherwise create a new empty
|
||
// object. Either way, the resulting object will be used to initialize
|
||
// the regeneratorRuntime variable at the top of this file.
|
||
typeof module === "object" ? module.exports : {}
|
||
));
|
||
|
||
try {
|
||
regeneratorRuntime = runtime;
|
||
} catch (accidentalStrictMode) {
|
||
// This module should not be running in strict mode, so the above
|
||
// assignment should always work unless something is misconfigured. Just
|
||
// in case runtime.js accidentally runs in strict mode, we can escape
|
||
// strict mode using a global Function call. This could conceivably fail
|
||
// if a Content Security Policy forbids using Function, but in that case
|
||
// the proper solution is to fix the accidental strict mode problem. If
|
||
// you've misconfigured your bundler to force strict mode and applied a
|
||
// CSP to forbid Function, and you're not willing to fix either of those
|
||
// problems, please detail your unique predicament in a GitHub issue.
|
||
Function("r", "regeneratorRuntime = r")(runtime);
|
||
}
|
||
|
||
},{}]},{},[1])
|
||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJidWlsZC9lbnRyeS5qcyIsImxpYi9jbGFzcy9jaGFydHMuY2xhc3MuanMiLCJsaWIvY2xhc3MvdXBkYXRlci5jbGFzcy5qcyIsImxpYi9jb25maWcvYXhpcy5qcyIsImxpYi9jb25maWcvYmFyLmpzIiwibGliL2NvbmZpZy9jb2xvci5qcyIsImxpYi9jb25maWcvZ2F1Z2UuanMiLCJsaWIvY29uZmlnL2dyaWQuanMiLCJsaWIvY29uZmlnL2luZGV4LmpzIiwibGliL2NvbmZpZy9sZWdlbmQuanMiLCJsaWIvY29uZmlnL2xpbmUuanMiLCJsaWIvY29uZmlnL3BpZS5qcyIsImxpYi9jb25maWcvcmFkYXIuanMiLCJsaWIvY29uZmlnL3JhZGFyQXhpcy5qcyIsImxpYi9jb25maWcvdGl0bGUuanMiLCJsaWIvY29yZS9heGlzLmpzIiwibGliL2NvcmUvYmFyLmpzIiwibGliL2NvcmUvZ2F1Z2UuanMiLCJsaWIvY29yZS9ncmlkLmpzIiwibGliL2NvcmUvaW5kZXguanMiLCJsaWIvY29yZS9sZWdlbmQuanMiLCJsaWIvY29yZS9saW5lLmpzIiwibGliL2NvcmUvbWVyZ2VDb2xvci5qcyIsImxpYi9jb3JlL3BpZS5qcyIsImxpYi9jb3JlL3JhZGFyLmpzIiwibGliL2NvcmUvcmFkYXJBeGlzLmpzIiwibGliL2NvcmUvdGl0bGUuanMiLCJsaWIvZXh0ZW5kL2luZGV4LmpzIiwibGliL2luZGV4LmpzIiwibGliL3V0aWwvaW5kZXguanMiLCJub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9hcnJheVdpdGhIb2xlcy5qcyIsIm5vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL2FycmF5V2l0aG91dEhvbGVzLmpzIiwibm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvYXN5bmNUb0dlbmVyYXRvci5qcyIsIm5vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL2NsYXNzQ2FsbENoZWNrLmpzIiwibm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvZGVmaW5lUHJvcGVydHkuanMiLCJub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHQuanMiLCJub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pdGVyYWJsZVRvQXJyYXkuanMiLCJub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pdGVyYWJsZVRvQXJyYXlMaW1pdC5qcyIsIm5vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL25vbkl0ZXJhYmxlUmVzdC5qcyIsIm5vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL25vbkl0ZXJhYmxlU3ByZWFkLmpzIiwibm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheS5qcyIsIm5vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5LmpzIiwibm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mLmpzIiwibm9kZV9tb2R1bGVzL0BiYWJlbC9ydW50aW1lL3JlZ2VuZXJhdG9yL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL0BqaWFtaW5naGkvYmV6aWVyLWN1cnZlL2xpYi9jb3JlL2JlemllckN1cnZlVG9Qb2x5bGluZS5qcyIsIm5vZGVfbW9kdWxlcy9AamlhbWluZ2hpL2Jlemllci1jdXJ2ZS9saWIvY29yZS9wb2x5bGluZVRvQmV6aWVyQ3VydmUuanMiLCJub2RlX21vZHVsZXMvQGppYW1pbmdoaS9iZXppZXItY3VydmUvbGliL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL0BqaWFtaW5naGkvYy1yZW5kZXIvbGliL2NsYXNzL2NyZW5kZXIuY2xhc3MuanMiLCJub2RlX21vZHVsZXMvQGppYW1pbmdoaS9jLXJlbmRlci9saWIvY2xhc3MvZ3JhcGguY2xhc3MuanMiLCJub2RlX21vZHVsZXMvQGppYW1pbmdoaS9jLXJlbmRlci9saWIvY2xhc3Mvc3R5bGUuY2xhc3MuanMiLCJub2RlX21vZHVsZXMvQGppYW1pbmdoaS9jLXJlbmRlci9saWIvY29uZmlnL2dyYXBocy5qcyIsIm5vZGVfbW9kdWxlcy9AamlhbWluZ2hpL2MtcmVuZGVyL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9AamlhbWluZ2hpL2MtcmVuZGVyL2xpYi9wbHVnaW4vY2FudmFzLmpzIiwibm9kZV9tb2R1bGVzL0BqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsLmpzIiwibm9kZV9tb2R1bGVzL0BqaWFtaW5naGkvY29sb3IvbGliL2NvbmZpZy9rZXl3b3Jkcy5qcyIsIm5vZGVfbW9kdWxlcy9AamlhbWluZ2hpL2NvbG9yL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9AamlhbWluZ2hpL3RyYW5zaXRpb24vbGliL2NvbmZpZy9jdXJ2ZXMuanMiLCJub2RlX21vZHVsZXMvQGppYW1pbmdoaS90cmFuc2l0aW9uL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWdlbmVyYXRvci1ydW50aW1lL3J1bnRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN2NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDck5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdHdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzl5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVtQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDelNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5VUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4ZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3ZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcDRCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcmNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCJ2YXIgQ2hhcnRzID0gcmVxdWlyZSgnLi4vbGliL2luZGV4Jylcblxud2luZG93LkNoYXJ0cyA9IENoYXJ0cyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBfY2xhc3NDYWxsQ2hlY2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9jbGFzc0NhbGxDaGVja1wiKSk7XG5cbnJlcXVpcmUoXCIuLi9leHRlbmQvaW5kZXhcIik7XG5cbnZhciBfY1JlbmRlciA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXJcIikpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiQGppYW1pbmdoaS9jLXJlbmRlci9saWIvcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfY29yZSA9IHJlcXVpcmUoXCIuLi9jb3JlXCIpO1xuXG52YXIgQ2hhcnRzID0gZnVuY3Rpb24gQ2hhcnRzKGRvbSkge1xuICAoMCwgX2NsYXNzQ2FsbENoZWNrMltcImRlZmF1bHRcIl0pKHRoaXMsIENoYXJ0cyk7XG5cbiAgaWYgKCFkb20pIHtcbiAgICBjb25zb2xlLmVycm9yKCdDaGFydHMgTWlzc2luZyBwYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBjbGllbnRXaWR0aCA9IGRvbS5jbGllbnRXaWR0aCxcbiAgICAgIGNsaWVudEhlaWdodCA9IGRvbS5jbGllbnRIZWlnaHQ7XG4gIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgY2FudmFzLnNldEF0dHJpYnV0ZSgnd2lkdGgnLCBjbGllbnRXaWR0aCk7XG4gIGNhbnZhcy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIGNsaWVudEhlaWdodCk7XG4gIGRvbS5hcHBlbmRDaGlsZChjYW52YXMpO1xuICB2YXIgYXR0cmlidXRlID0ge1xuICAgIGNvbnRhaW5lcjogZG9tLFxuICAgIGNhbnZhczogY2FudmFzLFxuICAgIHJlbmRlcjogbmV3IF9jUmVuZGVyW1wiZGVmYXVsdFwiXShjYW52YXMpLFxuICAgIG9wdGlvbjogbnVsbFxuICB9O1xuICBPYmplY3QuYXNzaWduKHRoaXMsIGF0dHJpYnV0ZSk7XG59O1xuLyoqXG4gKiBAZGVzY3JpcHRpb24gU2V0IGNoYXJ0IG9wdGlvblxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbiBDaGFydCBvcHRpb25cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gYW5pbWF0aW9uRW5kIEV4ZWN1dGUgYW5pbWF0aW9uRW5kXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IE5vIHJldHVyblxuICovXG5cblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBDaGFydHM7XG5cbkNoYXJ0cy5wcm90b3R5cGUuc2V0T3B0aW9uID0gZnVuY3Rpb24gKG9wdGlvbikge1xuICB2YXIgYW5pbWF0aW9uRW5kID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTtcblxuICBpZiAoIW9wdGlvbiB8fCAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShvcHRpb24pICE9PSAnb2JqZWN0Jykge1xuICAgIGNvbnNvbGUuZXJyb3IoJ3NldE9wdGlvbiBNaXNzaW5nIHBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGFuaW1hdGlvbkVuZCkgdGhpcy5yZW5kZXIuZ3JhcGhzLmZvckVhY2goZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLmFuaW1hdGlvbkVuZCgpO1xuICB9KTtcbiAgdmFyIG9wdGlvbkNsb25lZCA9ICgwLCBfdXRpbC5kZWVwQ2xvbmUpKG9wdGlvbiwgdHJ1ZSk7XG4gICgwLCBfY29yZS5tZXJnZUNvbG9yKSh0aGlzLCBvcHRpb25DbG9uZWQpO1xuICAoMCwgX2NvcmUuZ3JpZCkodGhpcywgb3B0aW9uQ2xvbmVkKTtcbiAgKDAsIF9jb3JlLmF4aXMpKHRoaXMsIG9wdGlvbkNsb25lZCk7XG4gICgwLCBfY29yZS5yYWRhckF4aXMpKHRoaXMsIG9wdGlvbkNsb25lZCk7XG4gICgwLCBfY29yZS50aXRsZSkodGhpcywgb3B0aW9uQ2xvbmVkKTtcbiAgKDAsIF9jb3JlLmJhcikodGhpcywgb3B0aW9uQ2xvbmVkKTtcbiAgKDAsIF9jb3JlLmxpbmUpKHRoaXMsIG9wdGlvbkNsb25lZCk7XG4gICgwLCBfY29yZS5waWUpKHRoaXMsIG9wdGlvbkNsb25lZCk7XG4gICgwLCBfY29yZS5yYWRhcikodGhpcywgb3B0aW9uQ2xvbmVkKTtcbiAgKDAsIF9jb3JlLmdhdWdlKSh0aGlzLCBvcHRpb25DbG9uZWQpO1xuICAoMCwgX2NvcmUubGVnZW5kKSh0aGlzLCBvcHRpb25DbG9uZWQpO1xuICB0aGlzLm9wdGlvbiA9IG9wdGlvbjtcbiAgdGhpcy5yZW5kZXIubGF1bmNoQW5pbWF0aW9uKCk7IC8vIGNvbnNvbGUud2Fybih0aGlzKVxufTtcbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlc2l6ZSBjaGFydFxuICogQHJldHVybiB7VW5kZWZpbmVkfSBObyByZXR1cm5cbiAqL1xuXG5cbkNoYXJ0cy5wcm90b3R5cGUucmVzaXplID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY29udGFpbmVyID0gdGhpcy5jb250YWluZXIsXG4gICAgICBjYW52YXMgPSB0aGlzLmNhbnZhcyxcbiAgICAgIHJlbmRlciA9IHRoaXMucmVuZGVyLFxuICAgICAgb3B0aW9uID0gdGhpcy5vcHRpb247XG4gIHZhciBjbGllbnRXaWR0aCA9IGNvbnRhaW5lci5jbGllbnRXaWR0aCxcbiAgICAgIGNsaWVudEhlaWdodCA9IGNvbnRhaW5lci5jbGllbnRIZWlnaHQ7XG4gIGNhbnZhcy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgY2xpZW50V2lkdGgpO1xuICBjYW52YXMuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBjbGllbnRIZWlnaHQpO1xuICByZW5kZXIuYXJlYSA9IFtjbGllbnRXaWR0aCwgY2xpZW50SGVpZ2h0XTtcbiAgdGhpcy5zZXRPcHRpb24ob3B0aW9uKTtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kb1VwZGF0ZSA9IGRvVXBkYXRlO1xuZXhwb3J0cy5VcGRhdGVyID0gdm9pZCAwO1xuXG52YXIgX3RvQ29uc3VtYWJsZUFycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdG9Db25zdW1hYmxlQXJyYXlcIikpO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBfY2xhc3NDYWxsQ2hlY2syID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9jbGFzc0NhbGxDaGVja1wiKSk7XG5cbnZhciBVcGRhdGVyID0gZnVuY3Rpb24gVXBkYXRlcihjb25maWcsIHNlcmllcykge1xuICAoMCwgX2NsYXNzQ2FsbENoZWNrMltcImRlZmF1bHRcIl0pKHRoaXMsIFVwZGF0ZXIpO1xuICB2YXIgY2hhcnQgPSBjb25maWcuY2hhcnQsXG4gICAgICBrZXkgPSBjb25maWcua2V5LFxuICAgICAgZ2V0R3JhcGhDb25maWcgPSBjb25maWcuZ2V0R3JhcGhDb25maWc7XG5cbiAgaWYgKHR5cGVvZiBnZXRHcmFwaENvbmZpZyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNvbnNvbGUud2FybignVXBkYXRlciBuZWVkIGZ1bmN0aW9uIGdldEdyYXBoQ29uZmlnIScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghY2hhcnRba2V5XSkgdGhpcy5ncmFwaHMgPSBjaGFydFtrZXldID0gW107XG4gIE9iamVjdC5hc3NpZ24odGhpcywgY29uZmlnKTtcbiAgdGhpcy51cGRhdGUoc2VyaWVzKTtcbn07XG5cbmV4cG9ydHMuVXBkYXRlciA9IFVwZGF0ZXI7XG5cblVwZGF0ZXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChzZXJpZXMpIHtcbiAgdmFyIF90aGlzID0gdGhpcztcblxuICB2YXIgZ3JhcGhzID0gdGhpcy5ncmFwaHMsXG4gICAgICBiZWZvcmVVcGRhdGUgPSB0aGlzLmJlZm9yZVVwZGF0ZTtcbiAgZGVsUmVkdW5kYW5jZUdyYXBoKHRoaXMsIHNlcmllcyk7XG4gIGlmICghc2VyaWVzLmxlbmd0aCkgcmV0dXJuO1xuICB2YXIgYmVmb3JlVXBkYXRlVHlwZSA9ICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKGJlZm9yZVVwZGF0ZSk7XG4gIHNlcmllcy5mb3JFYWNoKGZ1bmN0aW9uIChzZXJpZXNJdGVtLCBpKSB7XG4gICAgaWYgKGJlZm9yZVVwZGF0ZVR5cGUgPT09ICdmdW5jdGlvbicpIGJlZm9yZVVwZGF0ZShncmFwaHMsIHNlcmllc0l0ZW0sIGksIF90aGlzKTtcbiAgICB2YXIgY2FjaGUgPSBncmFwaHNbaV07XG5cbiAgICBpZiAoY2FjaGUpIHtcbiAgICAgIGNoYW5nZUdyYXBocyhjYWNoZSwgc2VyaWVzSXRlbSwgaSwgX3RoaXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhZGRHcmFwaHMoZ3JhcGhzLCBzZXJpZXNJdGVtLCBpLCBfdGhpcyk7XG4gICAgfVxuICB9KTtcbn07XG5cbmZ1bmN0aW9uIGRlbFJlZHVuZGFuY2VHcmFwaCh1cGRhdGVyLCBzZXJpZXMpIHtcbiAgdmFyIGdyYXBocyA9IHVwZGF0ZXIuZ3JhcGhzLFxuICAgICAgcmVuZGVyID0gdXBkYXRlci5jaGFydC5yZW5kZXI7XG4gIHZhciBjYWNoZUdyYXBoTnVtID0gZ3JhcGhzLmxlbmd0aDtcbiAgdmFyIG5lZWRHcmFwaE51bSA9IHNlcmllcy5sZW5ndGg7XG5cbiAgaWYgKGNhY2hlR3JhcGhOdW0gPiBuZWVkR3JhcGhOdW0pIHtcbiAgICB2YXIgbmVlZERlbEdyYXBocyA9IGdyYXBocy5zcGxpY2UobmVlZEdyYXBoTnVtKTtcbiAgICBuZWVkRGVsR3JhcGhzLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgIHJldHVybiBpdGVtLmZvckVhY2goZnVuY3Rpb24gKGcpIHtcbiAgICAgICAgcmV0dXJuIHJlbmRlci5kZWxHcmFwaChnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNoYW5nZUdyYXBocyhjYWNoZSwgc2VyaWVzSXRlbSwgaSwgdXBkYXRlcikge1xuICB2YXIgZ2V0R3JhcGhDb25maWcgPSB1cGRhdGVyLmdldEdyYXBoQ29uZmlnLFxuICAgICAgcmVuZGVyID0gdXBkYXRlci5jaGFydC5yZW5kZXIsXG4gICAgICBiZWZvcmVDaGFuZ2UgPSB1cGRhdGVyLmJlZm9yZUNoYW5nZTtcbiAgdmFyIGNvbmZpZ3MgPSBnZXRHcmFwaENvbmZpZyhzZXJpZXNJdGVtLCB1cGRhdGVyKTtcbiAgYmFsYW5jZUdyYXBoc051bShjYWNoZSwgY29uZmlncywgcmVuZGVyKTtcbiAgY2FjaGUuZm9yRWFjaChmdW5jdGlvbiAoZ3JhcGgsIGopIHtcbiAgICB2YXIgY29uZmlnID0gY29uZmlnc1tqXTtcbiAgICBpZiAodHlwZW9mIGJlZm9yZUNoYW5nZSA9PT0gJ2Z1bmN0aW9uJykgYmVmb3JlQ2hhbmdlKGdyYXBoLCBjb25maWcpO1xuICAgIHVwZGF0ZUdyYXBoQ29uZmlnQnlLZXkoZ3JhcGgsIGNvbmZpZyk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBiYWxhbmNlR3JhcGhzTnVtKGdyYXBocywgZ3JhcGhDb25maWcsIHJlbmRlcikge1xuICB2YXIgY2FjaGVHcmFwaE51bSA9IGdyYXBocy5sZW5ndGg7XG4gIHZhciBuZWVkR3JhcGhOdW0gPSBncmFwaENvbmZpZy5sZW5ndGg7XG5cbiAgaWYgKG5lZWRHcmFwaE51bSA+IGNhY2hlR3JhcGhOdW0pIHtcbiAgICB2YXIgbGFzdENhY2hlR3JhcGggPSBncmFwaHMuc2xpY2UoLTEpWzBdO1xuICAgIHZhciBuZWVkQWRkR3JhcGhOdW0gPSBuZWVkR3JhcGhOdW0gLSBjYWNoZUdyYXBoTnVtO1xuICAgIHZhciBuZWVkQWRkR3JhcGhzID0gbmV3IEFycmF5KG5lZWRBZGRHcmFwaE51bSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbykge1xuICAgICAgcmV0dXJuIHJlbmRlci5jbG9uZShsYXN0Q2FjaGVHcmFwaCk7XG4gICAgfSk7XG4gICAgZ3JhcGhzLnB1c2guYXBwbHkoZ3JhcGhzLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKG5lZWRBZGRHcmFwaHMpKTtcbiAgfSBlbHNlIGlmIChuZWVkR3JhcGhOdW0gPCBjYWNoZUdyYXBoTnVtKSB7XG4gICAgdmFyIG5lZWREZWxDYWNoZSA9IGdyYXBocy5zcGxpY2UobmVlZEdyYXBoTnVtKTtcbiAgICBuZWVkRGVsQ2FjaGUuZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgICAgcmV0dXJuIHJlbmRlci5kZWxHcmFwaChnKTtcbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhZGRHcmFwaHMoZ3JhcGhzLCBzZXJpZXNJdGVtLCBpLCB1cGRhdGVyKSB7XG4gIHZhciBnZXRHcmFwaENvbmZpZyA9IHVwZGF0ZXIuZ2V0R3JhcGhDb25maWcsXG4gICAgICBnZXRTdGFydEdyYXBoQ29uZmlnID0gdXBkYXRlci5nZXRTdGFydEdyYXBoQ29uZmlnLFxuICAgICAgY2hhcnQgPSB1cGRhdGVyLmNoYXJ0O1xuICB2YXIgcmVuZGVyID0gY2hhcnQucmVuZGVyO1xuICB2YXIgc3RhcnRDb25maWdzID0gbnVsbDtcbiAgaWYgKHR5cGVvZiBnZXRTdGFydEdyYXBoQ29uZmlnID09PSAnZnVuY3Rpb24nKSBzdGFydENvbmZpZ3MgPSBnZXRTdGFydEdyYXBoQ29uZmlnKHNlcmllc0l0ZW0sIHVwZGF0ZXIpO1xuICB2YXIgY29uZmlncyA9IGdldEdyYXBoQ29uZmlnKHNlcmllc0l0ZW0sIHVwZGF0ZXIpO1xuICBpZiAoIWNvbmZpZ3MubGVuZ3RoKSByZXR1cm47XG5cbiAgaWYgKHN0YXJ0Q29uZmlncykge1xuICAgIGdyYXBoc1tpXSA9IHN0YXJ0Q29uZmlncy5tYXAoZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHJlbmRlci5hZGQoY29uZmlnKTtcbiAgICB9KTtcbiAgICBncmFwaHNbaV0uZm9yRWFjaChmdW5jdGlvbiAoZ3JhcGgsIGkpIHtcbiAgICAgIHZhciBjb25maWcgPSBjb25maWdzW2ldO1xuICAgICAgdXBkYXRlR3JhcGhDb25maWdCeUtleShncmFwaCwgY29uZmlnKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBncmFwaHNbaV0gPSBjb25maWdzLm1hcChmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICByZXR1cm4gcmVuZGVyLmFkZChjb25maWcpO1xuICAgIH0pO1xuICB9XG5cbiAgdmFyIGFmdGVyQWRkR3JhcGggPSB1cGRhdGVyLmFmdGVyQWRkR3JhcGg7XG4gIGlmICh0eXBlb2YgYWZ0ZXJBZGRHcmFwaCA9PT0gJ2Z1bmN0aW9uJykgYWZ0ZXJBZGRHcmFwaChncmFwaHNbaV0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVHcmFwaENvbmZpZ0J5S2V5KGdyYXBoLCBjb25maWcpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhjb25maWcpO1xuICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIGlmIChrZXkgPT09ICdzaGFwZScgfHwga2V5ID09PSAnc3R5bGUnKSB7XG4gICAgICBncmFwaC5hbmltYXRpb24oa2V5LCBjb25maWdba2V5XSwgdHJ1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdyYXBoW2tleV0gPSBjb25maWdba2V5XTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkb1VwZGF0ZSgpIHtcbiAgdmFyIF9yZWYgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9LFxuICAgICAgY2hhcnQgPSBfcmVmLmNoYXJ0LFxuICAgICAgc2VyaWVzID0gX3JlZi5zZXJpZXMsXG4gICAgICBrZXkgPSBfcmVmLmtleSxcbiAgICAgIGdldEdyYXBoQ29uZmlnID0gX3JlZi5nZXRHcmFwaENvbmZpZyxcbiAgICAgIGdldFN0YXJ0R3JhcGhDb25maWcgPSBfcmVmLmdldFN0YXJ0R3JhcGhDb25maWcsXG4gICAgICBiZWZvcmVDaGFuZ2UgPSBfcmVmLmJlZm9yZUNoYW5nZSxcbiAgICAgIGJlZm9yZVVwZGF0ZSA9IF9yZWYuYmVmb3JlVXBkYXRlLFxuICAgICAgYWZ0ZXJBZGRHcmFwaCA9IF9yZWYuYWZ0ZXJBZGRHcmFwaDtcblxuICBpZiAoY2hhcnRba2V5XSkge1xuICAgIGNoYXJ0W2tleV0udXBkYXRlKHNlcmllcyk7XG4gIH0gZWxzZSB7XG4gICAgY2hhcnRba2V5XSA9IG5ldyBVcGRhdGVyKHtcbiAgICAgIGNoYXJ0OiBjaGFydCxcbiAgICAgIGtleToga2V5LFxuICAgICAgZ2V0R3JhcGhDb25maWc6IGdldEdyYXBoQ29uZmlnLFxuICAgICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRHcmFwaENvbmZpZyxcbiAgICAgIGJlZm9yZUNoYW5nZTogYmVmb3JlQ2hhbmdlLFxuICAgICAgYmVmb3JlVXBkYXRlOiBiZWZvcmVVcGRhdGUsXG4gICAgICBhZnRlckFkZEdyYXBoOiBhZnRlckFkZEdyYXBoXG4gICAgfSwgc2VyaWVzKTtcbiAgfVxufSIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy55QXhpc0NvbmZpZyA9IGV4cG9ydHMueEF4aXNDb25maWcgPSB2b2lkIDA7XG52YXIgeEF4aXNDb25maWcgPSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBuYW1lXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IG5hbWUgPSAnJ1xuICAgKi9cbiAgbmFtZTogJycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgdGhpcyBheGlzXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgKi9cbiAgc2hvdzogdHJ1ZSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgcG9zaXRpb24gPSAnYm90dG9tJ1xuICAgKiBAZXhhbXBsZSBwb3NpdGlvbiA9ICdib3R0b20nIHwgJ3RvcCdcbiAgICovXG4gIHBvc2l0aW9uOiAnYm90dG9tJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE5hbWUgZ2FwXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IG5hbWVHYXAgPSAxNVxuICAgKi9cbiAgbmFtZUdhcDogMTUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBOYW1lIGxvY2F0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IG5hbWVMb2NhdGlvbiA9ICdlbmQnXG4gICAqIEBleGFtcGxlIG5hbWVMb2NhdGlvbiA9ICdlbmQnIHwgJ2NlbnRlcicgfCAnc3RhcnQnXG4gICAqL1xuICBuYW1lTG9jYXRpb246ICdlbmQnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTmFtZSBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICovXG4gIG5hbWVUZXh0U3R5bGU6IHtcbiAgICBmaWxsOiAnIzMzMycsXG4gICAgZm9udFNpemU6IDEwXG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIG1pbiB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICogQGRlZmF1bHQgbWluID0gJzIwJSdcbiAgICogQGV4YW1wbGUgbWluID0gJzIwJScgfCAwXG4gICAqL1xuICBtaW46ICcyMCUnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBtYXggdmFsdWVcbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IG1heCA9ICcyMCUnXG4gICAqIEBleGFtcGxlIG1heCA9ICcyMCUnIHwgMFxuICAgKi9cbiAgbWF4OiAnMjAlJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgdmFsdWUgaW50ZXJ2YWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgaW50ZXJ2YWwgPSBudWxsXG4gICAqIEBleGFtcGxlIGludGVydmFsID0gMTAwXG4gICAqL1xuICBpbnRlcnZhbDogbnVsbCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1pbiBpbnRlcnZhbFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBtaW5JbnRlcnZhbCA9IG51bGxcbiAgICogQGV4YW1wbGUgbWluSW50ZXJ2YWwgPSAxXG4gICAqL1xuICBtaW5JbnRlcnZhbDogbnVsbCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1heCBpbnRlcnZhbFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBtYXhJbnRlcnZhbCA9IG51bGxcbiAgICogQGV4YW1wbGUgbWF4SW50ZXJ2YWwgPSAxMDBcbiAgICovXG4gIG1heEludGVydmFsOiBudWxsLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQm91bmRhcnkgZ2FwXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCBib3VuZGFyeUdhcCA9IG51bGxcbiAgICogQGV4YW1wbGUgYm91bmRhcnlHYXAgPSB0cnVlXG4gICAqL1xuICBib3VuZGFyeUdhcDogbnVsbCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgc3BsaXQgbnVtYmVyXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHNwbGl0TnVtYmVyID0gNVxuICAgKi9cbiAgc3BsaXROdW1iZXI6IDUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIGxpbmUgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgYXhpc0xpbmU6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGF4aXMgbGluZVxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBBeGlzIGxpbmUgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBzdHJva2U6ICcjMzMzJyxcbiAgICAgIGxpbmVXaWR0aDogMVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgdGljayBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBheGlzVGljazoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgYXhpcyB0aWNrXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgdGljayBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIHN0cm9rZTogJyMzMzMnLFxuICAgICAgbGluZVdpZHRoOiAxXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBheGlzTGFiZWw6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGF4aXMgbGFiZWxcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgICAqL1xuICAgIHNob3c6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBmb3JtYXR0ZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfEZ1bmN0aW9ufVxuICAgICAqIEBkZWZhdWx0IGZvcm1hdHRlciA9IG51bGxcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAne3ZhbHVlfeS7tidcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAoZGF0YUl0ZW0pID0+IChkYXRhSXRlbS52YWx1ZSlcbiAgICAgKi9cbiAgICBmb3JtYXR0ZXI6IG51bGwsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIGZpbGw6ICcjMzMzJyxcbiAgICAgIGZvbnRTaXplOiAxMCxcbiAgICAgIHJvdGF0ZTogMFxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgc3BsaXQgbGluZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzcGxpdExpbmU6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGF4aXMgc3BsaXQgbGluZVxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSBmYWxzZVxuICAgICAqL1xuICAgIHNob3c6IGZhbHNlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgc3BsaXQgbGluZSBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIHN0cm9rZTogJyNkNGQ0ZDQnLFxuICAgICAgbGluZVdpZHRoOiAxXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gWCBheGlzIHJlbmRlciBsZXZlbFxuICAgKiBQcmlvcml0eSByZW5kZXJpbmcgaGlnaCBsZXZlbFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCByTGV2ZWwgPSAtMjBcbiAgICovXG4gIHJMZXZlbDogLTIwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gWCBheGlzIGFuaW1hdGlvbiBjdXJ2ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25DdXJ2ZSA9ICdlYXNlT3V0Q3ViaWMnXG4gICAqL1xuICBhbmltYXRpb25DdXJ2ZTogJ2Vhc2VPdXRDdWJpYycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBYIGF4aXMgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMueEF4aXNDb25maWcgPSB4QXhpc0NvbmZpZztcbnZhciB5QXhpc0NvbmZpZyA9IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIG5hbWVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgbmFtZSA9ICcnXG4gICAqL1xuICBuYW1lOiAnJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSB0aGlzIGF4aXNcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAqL1xuICBzaG93OiB0cnVlLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBwb3NpdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBwb3NpdGlvbiA9ICdsZWZ0J1xuICAgKiBAZXhhbXBsZSBwb3NpdGlvbiA9ICdsZWZ0JyB8ICdyaWdodCdcbiAgICovXG4gIHBvc2l0aW9uOiAnbGVmdCcsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBOYW1lIGdhcFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBuYW1lR2FwID0gMTVcbiAgICovXG4gIG5hbWVHYXA6IDE1LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTmFtZSBsb2NhdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lTG9jYXRpb24gPSAnZW5kJ1xuICAgKiBAZXhhbXBsZSBuYW1lTG9jYXRpb24gPSAnZW5kJyB8ICdjZW50ZXInIHwgJ3N0YXJ0J1xuICAgKi9cbiAgbmFtZUxvY2F0aW9uOiAnZW5kJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIG5hbWUgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBuYW1lVGV4dFN0eWxlOiB7XG4gICAgZmlsbDogJyMzMzMnLFxuICAgIGZvbnRTaXplOiAxMFxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBtaW4gdmFsdWVcbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IG1pbiA9ICcyMCUnXG4gICAqIEBleGFtcGxlIG1pbiA9ICcyMCUnIHwgMFxuICAgKi9cbiAgbWluOiAnMjAlJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgbWF4IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBtYXggPSAnMjAlJ1xuICAgKiBAZXhhbXBsZSBtYXggPSAnMjAlJyB8IDBcbiAgICovXG4gIG1heDogJzIwJScsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIHZhbHVlIGludGVydmFsXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGludGVydmFsID0gbnVsbFxuICAgKiBAZXhhbXBsZSBpbnRlcnZhbCA9IDEwMFxuICAgKi9cbiAgaW50ZXJ2YWw6IG51bGwsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNaW4gaW50ZXJ2YWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgbWluSW50ZXJ2YWwgPSBudWxsXG4gICAqIEBleGFtcGxlIG1pbkludGVydmFsID0gMVxuICAgKi9cbiAgbWluSW50ZXJ2YWw6IG51bGwsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBNYXggaW50ZXJ2YWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgbWF4SW50ZXJ2YWwgPSBudWxsXG4gICAqIEBleGFtcGxlIG1heEludGVydmFsID0gMTAwXG4gICAqL1xuICBtYXhJbnRlcnZhbDogbnVsbCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJvdW5kYXJ5IGdhcFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgYm91bmRhcnlHYXAgPSBudWxsXG4gICAqIEBleGFtcGxlIGJvdW5kYXJ5R2FwID0gdHJ1ZVxuICAgKi9cbiAgYm91bmRhcnlHYXA6IG51bGwsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIHNwbGl0IG51bWJlclxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBzcGxpdE51bWJlciA9IDVcbiAgICovXG4gIHNwbGl0TnVtYmVyOiA1LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsaW5lIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGF4aXNMaW5lOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBheGlzIGxpbmVcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgICAqL1xuICAgIHNob3c6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsaW5lIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgc3Ryb2tlOiAnIzMzMycsXG4gICAgICBsaW5lV2lkdGg6IDFcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIHRpY2sgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgYXhpc1RpY2s6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGF4aXMgdGlja1xuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBBeGlzIHRpY2sgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBzdHJva2U6ICcjMzMzJyxcbiAgICAgIGxpbmVXaWR0aDogMVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGFiZWwgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgYXhpc0xhYmVsOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBheGlzIGxhYmVsXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGFiZWwgZm9ybWF0dGVyXG4gICAgICogQHR5cGUge1N0cmluZ3xGdW5jdGlvbn1cbiAgICAgKiBAZGVmYXVsdCBmb3JtYXR0ZXIgPSBudWxsXG4gICAgICogQGV4YW1wbGUgZm9ybWF0dGVyID0gJ3t2YWx1ZX3ku7YnXG4gICAgICogQGV4YW1wbGUgZm9ybWF0dGVyID0gKGRhdGFJdGVtKSA9PiAoZGF0YUl0ZW0udmFsdWUpXG4gICAgICovXG4gICAgZm9ybWF0dGVyOiBudWxsLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGFiZWwgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBmaWxsOiAnIzMzMycsXG4gICAgICBmb250U2l6ZTogMTAsXG4gICAgICByb3RhdGU6IDBcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIHNwbGl0IGxpbmUgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3BsaXRMaW5lOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBheGlzIHNwbGl0IGxpbmVcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgICAqL1xuICAgIHNob3c6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBzcGxpdCBsaW5lIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgc3Ryb2tlOiAnI2Q0ZDRkNCcsXG4gICAgICBsaW5lV2lkdGg6IDFcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBZIGF4aXMgcmVuZGVyIGxldmVsXG4gICAqIFByaW9yaXR5IHJlbmRlcmluZyBoaWdoIGxldmVsXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHJMZXZlbCA9IC0yMFxuICAgKi9cbiAgckxldmVsOiAtMjAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBZIGF4aXMgYW5pbWF0aW9uIGN1cnZlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkN1cnZlID0gJ2Vhc2VPdXRDdWJpYydcbiAgICovXG4gIGFuaW1hdGlvbkN1cnZlOiAnZWFzZU91dEN1YmljJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFkgYXhpcyBhbmltYXRpb24gZnJhbWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgYW5pbWF0aW9uRnJhbWUgPSA1MFxuICAgKi9cbiAgYW5pbWF0aW9uRnJhbWU6IDUwXG59O1xuZXhwb3J0cy55QXhpc0NvbmZpZyA9IHlBeGlzQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5iYXJDb25maWcgPSB2b2lkIDA7XG52YXIgYmFyQ29uZmlnID0ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSB0aGlzIGJhciBjaGFydFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lID0gJydcbiAgICovXG4gIG5hbWU6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGF0YSBzdGFja2luZ1xuICAgKiBUaGUgZGF0YSB2YWx1ZSBvZiB0aGUgc2VyaWVzIGVsZW1lbnQgb2YgdGhlIHNhbWUgc3RhY2tcbiAgICogd2lsbCBiZSBzdXBlcmltcG9zZWQgKHRoZSBsYXR0ZXIgdmFsdWUgd2lsbCBiZSBzdXBlcmltcG9zZWQgb24gdGhlIHByZXZpb3VzIHZhbHVlKVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBzdGFjayA9ICcnXG4gICAqL1xuICBzdGFjazogJycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYXIgc2hhcGUgdHlwZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBzaGFwZVR5cGUgPSAnbm9ybWFsJ1xuICAgKiBAZXhhbXBsZSBzaGFwZVR5cGUgPSAnbm9ybWFsJyB8ICdsZWZ0RWNoZWxvbicgfCAncmlnaHRFY2hlbG9uJ1xuICAgKi9cbiAgc2hhcGVUeXBlOiAnbm9ybWFsJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEVjaGVsb24gYmFyIHNoYXJwbmVzcyBvZmZzZXRcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgZWNoZWxvbk9mZnNldCA9IDEwXG4gICAqL1xuICBlY2hlbG9uT2Zmc2V0OiAxMCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciB3aWR0aFxuICAgKiBUaGlzIHByb3BlcnR5IHNob3VsZCBiZSBzZXQgb24gdGhlIGxhc3QgJ2Jhcicgc2VyaWVzXG4gICAqIGluIHRoaXMgY29vcmRpbmF0ZSBzeXN0ZW0gdG8gdGFrZSBlZmZlY3QgYW5kIHdpbGwgYmUgaW4gZWZmZWN0XG4gICAqIGZvciBhbGwgJ2Jhcicgc2VyaWVzIGluIHRoaXMgY29vcmRpbmF0ZSBzeXN0ZW1cbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGJhcldpZHRoID0gJ2F1dG8nXG4gICAqIEBleGFtcGxlIGJhcldpZHRoID0gJ2F1dG8nIHwgJzEwJScgfCAyMFxuICAgKi9cbiAgYmFyV2lkdGg6ICdhdXRvJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciBnYXBcbiAgICogVGhpcyBwcm9wZXJ0eSBzaG91bGQgYmUgc2V0IG9uIHRoZSBsYXN0ICdiYXInIHNlcmllc1xuICAgKiBpbiB0aGlzIGNvb3JkaW5hdGUgc3lzdGVtIHRvIHRha2UgZWZmZWN0IGFuZCB3aWxsIGJlIGluIGVmZmVjdFxuICAgKiBmb3IgYWxsICdiYXInIHNlcmllcyBpbiB0aGlzIGNvb3JkaW5hdGUgc3lzdGVtXG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBiYXJHYXAgPSAnMzAlJ1xuICAgKiBAZXhhbXBsZSBiYXJHYXAgPSAnMzAlJyB8IDMwXG4gICAqL1xuICBiYXJHYXA6ICczMCUnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQmFyIGNhdGVnb3J5IGdhcFxuICAgKiBUaGlzIHByb3BlcnR5IHNob3VsZCBiZSBzZXQgb24gdGhlIGxhc3QgJ2Jhcicgc2VyaWVzXG4gICAqIGluIHRoaXMgY29vcmRpbmF0ZSBzeXN0ZW0gdG8gdGFrZSBlZmZlY3QgYW5kIHdpbGwgYmUgaW4gZWZmZWN0XG4gICAqIGZvciBhbGwgJ2Jhcicgc2VyaWVzIGluIHRoaXMgY29vcmRpbmF0ZSBzeXN0ZW1cbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGJhckNhdGVnb3J5R2FwID0gJzIwJSdcbiAgICogQGV4YW1wbGUgYmFyQ2F0ZWdvcnlHYXAgPSAnMjAlJyB8IDIwXG4gICAqL1xuICBiYXJDYXRlZ29yeUdhcDogJzIwJScsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYXIgeCBheGlzIGluZGV4XG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHhBeGlzSW5kZXggPSAwXG4gICAqIEBleGFtcGxlIHhBeGlzSW5kZXggPSAwIHwgMVxuICAgKi9cbiAgeEF4aXNJbmRleDogMCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciB5IGF4aXMgaW5kZXhcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgeUF4aXNJbmRleCA9IDBcbiAgICogQGV4YW1wbGUgeUF4aXNJbmRleCA9IDAgfCAxXG4gICAqL1xuICB5QXhpc0luZGV4OiAwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQmFyIGNoYXJ0IGRhdGFcbiAgICogQHR5cGUge0FycmF5fVxuICAgKiBAZGVmYXVsdCBkYXRhID0gW11cbiAgICogQGV4YW1wbGUgZGF0YSA9IFsxMDAsIDIwMCwgMzAwXVxuICAgKi9cbiAgZGF0YTogW10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYWNrZ3JvdW5kIGJhciBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBiYWNrZ3JvdW5kQmFyOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBiYWNrZ3JvdW5kIGJhclxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSBmYWxzZVxuICAgICAqL1xuICAgIHNob3c6IGZhbHNlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEJhY2tncm91bmQgYmFyIHdpZHRoXG4gICAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAgICogQGRlZmF1bHQgd2lkdGggPSAnYXV0bydcbiAgICAgKiBAZXhhbXBsZSB3aWR0aCA9ICdhdXRvJyB8ICczMCUnIHwgMzBcbiAgICAgKi9cbiAgICB3aWR0aDogJ2F1dG8nLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEJhY2tncm91bmQgYmFyIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgZmlsbDogJ3JnYmEoMjAwLCAyMDAsIDIwMCwgLjQpJ1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciBsYWJlbCBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBsYWJlbDoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgYmFyIGxhYmVsXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IGZhbHNlXG4gICAgICovXG4gICAgc2hvdzogZmFsc2UsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQmFyIGxhYmVsIHBvc2l0aW9uXG4gICAgICogQHR5cGUge1N0cmluZ31cbiAgICAgKiBAZGVmYXVsdCBwb3NpdGlvbiA9ICd0b3AnXG4gICAgICogQGV4YW1wbGUgcG9zaXRpb24gPSAndG9wJyB8ICdjZW50ZXInIHwgJ2JvdHRvbSdcbiAgICAgKi9cbiAgICBwb3NpdGlvbjogJ3RvcCcsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQmFyIGxhYmVsIG9mZnNldFxuICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgKiBAZGVmYXVsdCBvZmZzZXQgPSBbMCwgLTEwXVxuICAgICAqL1xuICAgIG9mZnNldDogWzAsIC0xMF0sXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQmFyIGxhYmVsIGZvcm1hdHRlclxuICAgICAqIEB0eXBlIHtTdHJpbmd8RnVuY3Rpb259XG4gICAgICogQGRlZmF1bHQgZm9ybWF0dGVyID0gbnVsbFxuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9ICd7dmFsdWV95Lu2J1xuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9IChkYXRhSXRlbSkgPT4gKGRhdGFJdGVtLnZhbHVlKVxuICAgICAqL1xuICAgIGZvcm1hdHRlcjogbnVsbCxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBCYXIgbGFiZWwgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBmb250U2l6ZTogMTBcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYXIgZ3JhZGllbnQgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgZ3JhZGllbnQ6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gR3JhZGllbnQgY29sb3IgKEhleHxyZ2J8cmdiYSlcbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICogQGRlZmF1bHQgY29sb3IgPSBbXVxuICAgICAqL1xuICAgIGNvbG9yOiBbXSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMb2NhbCBncmFkaWVudFxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IGxvY2FsID0gdHJ1ZVxuICAgICAqL1xuICAgIGxvY2FsOiB0cnVlXG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYXIgc3R5bGUgZGVmYXVsdCBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBiYXJTdHlsZToge30sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbmRlcGVuZGVudCBjb2xvciBtb2RlXG4gICAqIFdoZW4gc2V0IHRvIHRydWUsIGluZGVwZW5kZW50IGNvbG9yIG1vZGUgaXMgZW5hYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgaW5kZXBlbmRlbnRDb2xvciA9IGZhbHNlXG4gICAqL1xuICBpbmRlcGVuZGVudENvbG9yOiBmYWxzZSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEluZGVwZW5kZW50IGNvbG9yc1xuICAgKiBPbmx5IGVmZmVjdGl2ZSB3aGVuIGluZGVwZW5kZW50IGNvbG9yIG1vZGUgaXMgZW5hYmxlZFxuICAgKiBEZWZhdWx0IHZhbHVlIGlzIHRoZSBzYW1lIGFzIHRoZSBjb2xvciBpbiB0aGUgcm9vdCBjb25maWd1cmF0aW9uXG4gICAqIFR3by1kaW1lbnNpb25hbCBjb2xvciBhcnJheSBjYW4gcHJvZHVjZSBncmFkaWVudCBjb2xvcnNcbiAgICogQHR5cGUge0FycmF5fVxuICAgKiBAZXhhbXBsZSBpbmRlcGVuZGVudENvbG9yID0gWycjZmZmJywgJyMwMDAnXVxuICAgKiBAZXhhbXBsZSBpbmRlcGVuZGVudENvbG9yID0gW1snI2ZmZicsICcjMDAwJ10sICcjMDAwJ11cbiAgICovXG4gIGluZGVwZW5kZW50Q29sb3JzOiBbXSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciBjaGFydCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gMFxuICAgKi9cbiAgckxldmVsOiAwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQmFyIGFuaW1hdGlvbiBjdXJ2ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25DdXJ2ZSA9ICdlYXNlT3V0Q3ViaWMnXG4gICAqL1xuICBhbmltYXRpb25DdXJ2ZTogJ2Vhc2VPdXRDdWJpYycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCYXIgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMuYmFyQ29uZmlnID0gYmFyQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5jb2xvckNvbmZpZyA9IHZvaWQgMDtcbnZhciBjb2xvckNvbmZpZyA9IFsnIzM3YTJkYScsICcjMzJjNWU5JywgJyM2N2UwZTMnLCAnIzlmZTZiOCcsICcjZmZkYjVjJywgJyNmZjlmN2YnLCAnI2ZiNzI5MycsICcjZTA2MmFlJywgJyNlNjkwZDEnLCAnI2U3YmNmMycsICcjOWQ5NmY1JywgJyM4Mzc4ZWEnLCAnIzk2YmZmZiddO1xuZXhwb3J0cy5jb2xvckNvbmZpZyA9IGNvbG9yQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5nYXVnZUNvbmZpZyA9IHZvaWQgMDtcbnZhciBnYXVnZUNvbmZpZyA9IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgdGhpcyBnYXVnZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lID0gJydcbiAgICovXG4gIG5hbWU6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmFkaXVzIG9mIGdhdWdlXG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCByYWRpdXMgPSAnNjAlJ1xuICAgKiBAZXhhbXBsZSByYWRpdXMgPSAnNjAlJyB8IDEwMFxuICAgKi9cbiAgcmFkaXVzOiAnNjAlJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENlbnRlciBwb2ludCBvZiBnYXVnZVxuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqIEBkZWZhdWx0IGNlbnRlciA9IFsnNTAlJywnNTAlJ11cbiAgICogQGV4YW1wbGUgY2VudGVyID0gWyc1MCUnLCc1MCUnXSB8IFsxMDAsIDEwMF1cbiAgICovXG4gIGNlbnRlcjogWyc1MCUnLCAnNTAlJ10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHYXVnZSBzdGFydCBhbmdsZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBzdGFydEFuZ2xlID0gLShNYXRoLlBJIC8gNCkgKiA1XG4gICAqIEBleGFtcGxlIHN0YXJ0QW5nbGUgPSAtTWF0aC5QSVxuICAgKi9cbiAgc3RhcnRBbmdsZTogLShNYXRoLlBJIC8gNCkgKiA1LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2F1Z2UgZW5kIGFuZ2xlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGVuZEFuZ2xlID0gTWF0aC5QSSAvIDRcbiAgICogQGV4YW1wbGUgZW5kQW5nbGUgPSAwXG4gICAqL1xuICBlbmRBbmdsZTogTWF0aC5QSSAvIDQsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHYXVnZSBtaW4gdmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgbWluID0gMFxuICAgKi9cbiAgbWluOiAwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2F1Z2UgbWF4IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IG1heCA9IDEwMFxuICAgKi9cbiAgbWF4OiAxMDAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHYXVnZSBzcGxpdCBudW1iZXJcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgc3BsaXROdW0gPSA1XG4gICAqL1xuICBzcGxpdE51bTogNSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdhdWdlIGFyYyBsaW5lIHdpZHRoXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFyY0xpbmVXaWR0aCA9IDE1XG4gICAqL1xuICBhcmNMaW5lV2lkdGg6IDE1LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2F1Z2UgY2hhcnQgZGF0YVxuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqIEBkZWZhdWx0IGRhdGEgPSBbXVxuICAgKi9cbiAgZGF0YTogW10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEYXRhIGl0ZW0gYXJjIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVmYXVsdCBkYXRhSXRlbVN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBkYXRhSXRlbVN0eWxlOiB7fSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgdGljayBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBheGlzVGljazoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgYXhpcyB0aWNrXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgdGljayBsZW5ndGhcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAqIEBkZWZhdWx0IHRpY2tMZW5ndGggPSA2XG4gICAgICovXG4gICAgdGlja0xlbmd0aDogNixcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBBeGlzIHRpY2sgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBzdHJva2U6ICcjOTk5JyxcbiAgICAgIGxpbmVXaWR0aDogMVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGFiZWwgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgYXhpc0xhYmVsOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBheGlzIGxhYmVsXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGFiZWwgZGF0YSAoQ2FuIGJlIGNhbGN1bGF0ZWQgYXV0b21hdGljYWxseSlcbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICogQGRlZmF1bHQgZGF0YSA9IFtOdW1iZXIuLi5dXG4gICAgICovXG4gICAgZGF0YTogW10sXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBmb3JtYXR0ZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfEZ1bmN0aW9ufVxuICAgICAqIEBkZWZhdWx0IGZvcm1hdHRlciA9IG51bGxcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAne3ZhbHVlfSUnXG4gICAgICogQGV4YW1wbGUgZm9ybWF0dGVyID0gKGxhYmVsSXRlbSkgPT4gKGxhYmVsSXRlbS52YWx1ZSlcbiAgICAgKi9cbiAgICBmb3JtYXR0ZXI6IG51bGwsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBnYXAgYmV0d2VlbiBsYWJlbCBhbmQgYXhpcyB0aWNrXG4gICAgICogQHR5cGUge1N0cmluZ3xGdW5jdGlvbn1cbiAgICAgKiBAZGVmYXVsdCBsYWJlbEdhcCA9IDVcbiAgICAgKi9cbiAgICBsYWJlbEdhcDogNSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBBeGlzIGxhYmVsIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge31cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdhdWdlIHBvaW50ZXIgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgcG9pbnRlcjoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgcG9pbnRlclxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBQb2ludGVyIHZhbHVlIGluZGV4IG9mIGRhdGFcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAqIEBkZWZhdWx0IHZhbHVlSW5kZXggPSAwIChwb2ludGVyLnZhbHVlID0gZGF0YVswXS52YWx1ZSlcbiAgICAgKi9cbiAgICB2YWx1ZUluZGV4OiAwLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFBvaW50ZXIgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBzY2FsZTogWzEsIDFdLFxuICAgICAgZmlsbDogJyNmYjcyOTMnXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGF0YSBpdGVtIGFyYyBkZXRhaWwgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgZGV0YWlsczoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgZGV0YWlsc1xuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSBmYWxzZVxuICAgICAqL1xuICAgIHNob3c6IGZhbHNlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIERldGFpbHMgZm9ybWF0dGVyXG4gICAgICogQHR5cGUge1N0cmluZ3xGdW5jdGlvbn1cbiAgICAgKiBAZGVmYXVsdCBmb3JtYXR0ZXIgPSBudWxsXG4gICAgICogQGV4YW1wbGUgZm9ybWF0dGVyID0gJ3t2YWx1ZX0lJ1xuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9ICd7bmFtZX0lJ1xuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9IChkYXRhSXRlbSkgPT4gKGRhdGFJdGVtLnZhbHVlKVxuICAgICAqL1xuICAgIGZvcm1hdHRlcjogbnVsbCxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBEZXRhaWxzIHBvc2l0aW9uIG9mZnNldFxuICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgKiBAZGVmYXVsdCBvZmZzZXQgPSBbMCwgMF1cbiAgICAgKiBAZXhhbXBsZSBvZmZzZXQgPSBbMTAsIDEwXVxuICAgICAqL1xuICAgIG9mZnNldDogWzAsIDBdLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFZhbHVlIGZyYWN0aW9uYWwgcHJlY2lzaW9uXG4gICAgICogQHR5cGUge051bWJlcn1cbiAgICAgKiBAZGVmYXVsdCB2YWx1ZVRvRml4ZWQgPSAwXG4gICAgICovXG4gICAgdmFsdWVUb0ZpeGVkOiAwLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIERldGFpbHMgcG9zaXRpb25cbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgICAqIEBkZWZhdWx0IHBvc2l0aW9uID0gJ2NlbnRlcidcbiAgICAgKiBAZXhhbXBsZSBwb3NpdGlvbiA9ICdzdGFydCcgfCAnY2VudGVyJyB8ICdlbmQnXG4gICAgICovXG4gICAgcG9zaXRpb246ICdjZW50ZXInLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIERldGFpbHMgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBmb250U2l6ZTogMjAsXG4gICAgICBmb250V2VpZ2h0OiAnYm9sZCcsXG4gICAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdhdWdlIGJhY2tncm91bmQgYXJjIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGJhY2tncm91bmRBcmM6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGJhY2tncm91bmQgYXJjXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEJhY2tncm91bmQgYXJjIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgc3Ryb2tlOiAnI2UwZTBlMCdcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHYXVnZSBjaGFydCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gMTBcbiAgICovXG4gIHJMZXZlbDogMTAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHYXVnZSBhbmltYXRpb24gY3VydmVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYW5pbWF0aW9uQ3VydmUgPSAnZWFzZU91dEN1YmljJ1xuICAgKi9cbiAgYW5pbWF0aW9uQ3VydmU6ICdlYXNlT3V0Q3ViaWMnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2F1Z2UgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMuZ2F1Z2VDb25maWcgPSBnYXVnZUNvbmZpZzsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZ3JpZENvbmZpZyA9IHZvaWQgMDtcbnZhciBncmlkQ29uZmlnID0ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgbGVmdCBtYXJnaW5cbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGxlZnQgPSAnMTAlJ1xuICAgKiBAZXhhbXBsZSBsZWZ0ID0gJzEwJScgfCAxMFxuICAgKi9cbiAgbGVmdDogJzEwJScsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHcmlkIHJpZ2h0IG1hcmdpblxuICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICogQGRlZmF1bHQgcmlnaHQgPSAnMTAlJ1xuICAgKiBAZXhhbXBsZSByaWdodCA9ICcxMCUnIHwgMTBcbiAgICovXG4gIHJpZ2h0OiAnMTAlJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgdG9wIG1hcmdpblxuICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICogQGRlZmF1bHQgdG9wID0gNjBcbiAgICogQGV4YW1wbGUgdG9wID0gJzEwJScgfCA2MFxuICAgKi9cbiAgdG9wOiA2MCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgYm90dG9tIG1hcmdpblxuICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICogQGRlZmF1bHQgYm90dG9tID0gNjBcbiAgICogQGV4YW1wbGUgYm90dG9tID0gJzEwJScgfCA2MFxuICAgKi9cbiAgYm90dG9tOiA2MCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBzdHlsZToge1xuICAgIGZpbGw6ICdyZ2JhKDAsIDAsIDAsIDApJ1xuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR3JpZCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gLTMwXG4gICAqL1xuICByTGV2ZWw6IC0zMCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgYW5pbWF0aW9uIGN1cnZlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkN1cnZlID0gJ2Vhc2VPdXRDdWJpYydcbiAgICovXG4gIGFuaW1hdGlvbkN1cnZlOiAnZWFzZU91dEN1YmljJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdyaWQgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiAzMFxufTtcbmV4cG9ydHMuZ3JpZENvbmZpZyA9IGdyaWRDb25maWc7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmNoYW5nZURlZmF1bHRDb25maWcgPSBjaGFuZ2VEZWZhdWx0Q29uZmlnO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiY29sb3JDb25maWdcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX2NvbG9yLmNvbG9yQ29uZmlnO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImdyaWRDb25maWdcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX2dyaWQuZ3JpZENvbmZpZztcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ4QXhpc0NvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfYXhpcy54QXhpc0NvbmZpZztcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ5QXhpc0NvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfYXhpcy55QXhpc0NvbmZpZztcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJ0aXRsZUNvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfdGl0bGUudGl0bGVDb25maWc7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibGluZUNvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfbGluZS5saW5lQ29uZmlnO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImJhckNvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfYmFyLmJhckNvbmZpZztcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJwaWVDb25maWdcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX3BpZS5waWVDb25maWc7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwicmFkYXJBeGlzQ29uZmlnXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9yYWRhckF4aXMucmFkYXJBeGlzQ29uZmlnO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInJhZGFyQ29uZmlnXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9yYWRhci5yYWRhckNvbmZpZztcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJnYXVnZUNvbmZpZ1wiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfZ2F1Z2UuZ2F1Z2VDb25maWc7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibGVnZW5kQ29uZmlnXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9sZWdlbmQubGVnZW5kQ29uZmlnO1xuICB9XG59KTtcbmV4cG9ydHMua2V5cyA9IHZvaWQgMDtcblxudmFyIF9jb2xvciA9IHJlcXVpcmUoXCIuL2NvbG9yXCIpO1xuXG52YXIgX2dyaWQgPSByZXF1aXJlKFwiLi9ncmlkXCIpO1xuXG52YXIgX2F4aXMgPSByZXF1aXJlKFwiLi9heGlzXCIpO1xuXG52YXIgX3RpdGxlID0gcmVxdWlyZShcIi4vdGl0bGVcIik7XG5cbnZhciBfbGluZSA9IHJlcXVpcmUoXCIuL2xpbmVcIik7XG5cbnZhciBfYmFyID0gcmVxdWlyZShcIi4vYmFyXCIpO1xuXG52YXIgX3BpZSA9IHJlcXVpcmUoXCIuL3BpZVwiKTtcblxudmFyIF9yYWRhckF4aXMgPSByZXF1aXJlKFwiLi9yYWRhckF4aXNcIik7XG5cbnZhciBfcmFkYXIgPSByZXF1aXJlKFwiLi9yYWRhclwiKTtcblxudmFyIF9nYXVnZSA9IHJlcXVpcmUoXCIuL2dhdWdlXCIpO1xuXG52YXIgX2xlZ2VuZCA9IHJlcXVpcmUoXCIuL2xlZ2VuZFwiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIi4uL3V0aWxcIik7XG5cbnZhciBhbGxDb25maWcgPSB7XG4gIGNvbG9yQ29uZmlnOiBfY29sb3IuY29sb3JDb25maWcsXG4gIGdyaWRDb25maWc6IF9ncmlkLmdyaWRDb25maWcsXG4gIHhBeGlzQ29uZmlnOiBfYXhpcy54QXhpc0NvbmZpZyxcbiAgeUF4aXNDb25maWc6IF9heGlzLnlBeGlzQ29uZmlnLFxuICB0aXRsZUNvbmZpZzogX3RpdGxlLnRpdGxlQ29uZmlnLFxuICBsaW5lQ29uZmlnOiBfbGluZS5saW5lQ29uZmlnLFxuICBiYXJDb25maWc6IF9iYXIuYmFyQ29uZmlnLFxuICBwaWVDb25maWc6IF9waWUucGllQ29uZmlnLFxuICByYWRhckF4aXNDb25maWc6IF9yYWRhckF4aXMucmFkYXJBeGlzQ29uZmlnLFxuICByYWRhckNvbmZpZzogX3JhZGFyLnJhZGFyQ29uZmlnLFxuICBnYXVnZUNvbmZpZzogX2dhdWdlLmdhdWdlQ29uZmlnLFxuICBsZWdlbmRDb25maWc6IF9sZWdlbmQubGVnZW5kQ29uZmlnXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ2hhbmdlIGRlZmF1bHQgY29uZmlndXJhdGlvblxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5ICAgICAgICAgIENvbmZpZ3VyYXRpb24ga2V5XG4gICAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBjb25maWcgWW91ciBjb25maWdcbiAgICogQHJldHVybiB7VW5kZWZpbmVkfSBObyByZXR1cm5cbiAgICovXG5cbn07XG5cbmZ1bmN0aW9uIGNoYW5nZURlZmF1bHRDb25maWcoa2V5LCBjb25maWcpIHtcbiAgaWYgKCFhbGxDb25maWdbXCJcIi5jb25jYXQoa2V5LCBcIkNvbmZpZ1wiKV0pIHtcbiAgICBjb25zb2xlLndhcm4oJ0NoYW5nZSBkZWZhdWx0IGNvbmZpZyBFcnJvciAtIEludmFsaWQga2V5IScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gICgwLCBfdXRpbC5kZWVwTWVyZ2UpKGFsbENvbmZpZ1tcIlwiLmNvbmNhdChrZXksIFwiQ29uZmlnXCIpXSwgY29uZmlnKTtcbn1cblxudmFyIGtleXMgPSBbJ2NvbG9yJywgJ3RpdGxlJywgJ2xlZ2VuZCcsICd4QXhpcycsICd5QXhpcycsICdncmlkJywgJ3JhZGFyQXhpcycsICdsaW5lJywgJ2JhcicsICdwaWUnLCAncmFkYXInLCAnZ2F1Z2UnXTtcbmV4cG9ydHMua2V5cyA9IGtleXM7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmxlZ2VuZENvbmZpZyA9IHZvaWQgMDtcbnZhciBsZWdlbmRDb25maWcgPSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IGxlZ2VuZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgb3JpZW50XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IG9yaWVudCA9ICdob3Jpem9udGFsJ1xuICAgKiBAZXhhbXBsZSBvcmllbnQgPSAnaG9yaXpvbnRhbCcgfCAndmVydGljYWwnXG4gICAqL1xuICBvcmllbnQ6ICdob3Jpem9udGFsJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExlZ2VuZCBsZWZ0XG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBsZWZ0ID0gJ2F1dG8nXG4gICAqIEBleGFtcGxlIGxlZnQgPSAnYXV0bycgfCAnMTAlJyB8IDEwXG4gICAqL1xuICBsZWZ0OiAnYXV0bycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgcmlnaHRcbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHJpZ2h0ID0gJ2F1dG8nXG4gICAqIEBleGFtcGxlIHJpZ2h0ID0gJ2F1dG8nIHwgJzEwJScgfCAxMFxuICAgKi9cbiAgcmlnaHQ6ICdhdXRvJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExlZ2VuZCB0b3BcbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHRvcCA9ICdhdXRvJ1xuICAgKiBAZXhhbXBsZSB0b3AgPSAnYXV0bycgfCAnMTAlJyB8IDEwXG4gICAqL1xuICB0b3A6ICdhdXRvJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExlZ2VuZCBib3R0b21cbiAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGJvdHRvbSA9ICdhdXRvJ1xuICAgKiBAZXhhbXBsZSBib3R0b20gPSAnYXV0bycgfCAnMTAlJyB8IDEwXG4gICAqL1xuICBib3R0b206ICdhdXRvJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExlZ2VuZCBpdGVtIGdhcFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBpdGVtR2FwID0gMTBcbiAgICovXG4gIGl0ZW1HYXA6IDEwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSWNvbiB3aWR0aFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBpY29uV2lkdGggPSAyNVxuICAgKi9cbiAgaWNvbldpZHRoOiAyNSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEljb24gaGVpZ2h0XG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGljb25IZWlnaHQgPSAxMFxuICAgKi9cbiAgaWNvbkhlaWdodDogMTAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIGxlZ2VuZCBpcyBvcHRpb25hbFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2VsZWN0QWJsZSA9IHRydWVcbiAgICovXG4gIHNlbGVjdEFibGU6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgZGF0YVxuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqIEBkZWZhdWx0IGRhdGEgPSBbXVxuICAgKi9cbiAgZGF0YTogW10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgdGV4dCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICovXG4gIHRleHRTdHlsZToge1xuICAgIGZvbnRGYW1pbHk6ICdBcmlhbCcsXG4gICAgZm9udFNpemU6IDEzLFxuICAgIGZpbGw6ICcjMDAwJ1xuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGVnZW5kIGljb24gZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBpY29uU3R5bGU6IHt9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGVnZW5kIHRleHQgdW5zZWxlY3RlZCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICovXG4gIHRleHRVbnNlbGVjdGVkU3R5bGU6IHtcbiAgICBmb250RmFtaWx5OiAnQXJpYWwnLFxuICAgIGZvbnRTaXplOiAxMyxcbiAgICBmaWxsOiAnIzk5OSdcbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIExlZ2VuZCBpY29uIHVuc2VsZWN0ZWQgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBpY29uVW5zZWxlY3RlZFN0eWxlOiB7XG4gICAgZmlsbDogJyM5OTknXG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgcmVuZGVyIGxldmVsXG4gICAqIFByaW9yaXR5IHJlbmRlcmluZyBoaWdoIGxldmVsXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHJMZXZlbCA9IDIwXG4gICAqL1xuICByTGV2ZWw6IDIwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGVnZW5kIGFuaW1hdGlvbiBjdXJ2ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25DdXJ2ZSA9ICdlYXNlT3V0Q3ViaWMnXG4gICAqL1xuICBhbmltYXRpb25DdXJ2ZTogJ2Vhc2VPdXRDdWJpYycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMubGVnZW5kQ29uZmlnID0gbGVnZW5kQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5saW5lQ29uZmlnID0gdm9pZCAwO1xudmFyIGxpbmVDb25maWcgPSB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IHRoaXMgbGluZSBjaGFydFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lID0gJydcbiAgICovXG4gIG5hbWU6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGF0YSBzdGFja2luZ1xuICAgKiBUaGUgZGF0YSB2YWx1ZSBvZiB0aGUgc2VyaWVzIGVsZW1lbnQgb2YgdGhlIHNhbWUgc3RhY2tcbiAgICogd2lsbCBiZSBzdXBlcmltcG9zZWQgKHRoZSBsYXR0ZXIgdmFsdWUgd2lsbCBiZSBzdXBlcmltcG9zZWQgb24gdGhlIHByZXZpb3VzIHZhbHVlKVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBzdGFjayA9ICcnXG4gICAqL1xuICBzdGFjazogJycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTbW9vdGggbGluZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc21vb3RoID0gZmFsc2VcbiAgICovXG4gIHNtb290aDogZmFsc2UsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIHggYXhpcyBpbmRleFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCB4QXhpc0luZGV4ID0gMFxuICAgKiBAZXhhbXBsZSB4QXhpc0luZGV4ID0gMCB8IDFcbiAgICovXG4gIHhBeGlzSW5kZXg6IDAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIHkgYXhpcyBpbmRleFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCB5QXhpc0luZGV4ID0gMFxuICAgKiBAZXhhbXBsZSB5QXhpc0luZGV4ID0gMCB8IDFcbiAgICovXG4gIHlBeGlzSW5kZXg6IDAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIGNoYXJ0IGRhdGFcbiAgICogQHR5cGUge0FycmF5fVxuICAgKiBAZGVmYXVsdCBkYXRhID0gW11cbiAgICogQGV4YW1wbGUgZGF0YSA9IFsxMDAsIDIwMCwgMzAwXVxuICAgKi9cbiAgZGF0YTogW10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgKi9cbiAgbGluZVN0eWxlOiB7XG4gICAgbGluZVdpZHRoOiAxXG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIHBvaW50IGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGxpbmVQb2ludDoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgbGluZSBwb2ludFxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIHBvaW50IHJhZGl1c1xuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQGRlZmF1bHQgcmFkaXVzID0gMlxuICAgICAqL1xuICAgIHJhZGl1czogMixcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIHBvaW50IGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgZmlsbDogJyNmZmYnLFxuICAgICAgbGluZVdpZHRoOiAxXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGluZSBhcmVhIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGxpbmVBcmVhOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBsaW5lIGFyZWFcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gZmFsc2VcbiAgICAgKi9cbiAgICBzaG93OiBmYWxzZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIGFyZWEgZ3JhZGllbnQgY29sb3IgKEhleHxyZ2J8cmdiYSlcbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICogQGRlZmF1bHQgZ3JhZGllbnQgPSBbXVxuICAgICAqL1xuICAgIGdyYWRpZW50OiBbXSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIGFyZWEgc3R5bGUgZGVmYXVsdCBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBvcGFjaXR5OiAwLjVcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIGxhYmVsIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGxhYmVsOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBsaW5lIGxhYmVsXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IGZhbHNlXG4gICAgICovXG4gICAgc2hvdzogZmFsc2UsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gTGluZSBsYWJlbCBwb3NpdGlvblxuICAgICAqIEB0eXBlIHtTdHJpbmd9XG4gICAgICogQGRlZmF1bHQgcG9zaXRpb24gPSAndG9wJ1xuICAgICAqIEBleGFtcGxlIHBvc2l0aW9uID0gJ3RvcCcgfCAnY2VudGVyJyB8ICdib3R0b20nXG4gICAgICovXG4gICAgcG9zaXRpb246ICd0b3AnLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExpbmUgbGFiZWwgb2Zmc2V0XG4gICAgICogQHR5cGUge0FycmF5fVxuICAgICAqIEBkZWZhdWx0IG9mZnNldCA9IFswLCAtMTBdXG4gICAgICovXG4gICAgb2Zmc2V0OiBbMCwgLTEwXSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIGxhYmVsIGZvcm1hdHRlclxuICAgICAqIEB0eXBlIHtTdHJpbmd8RnVuY3Rpb259XG4gICAgICogQGRlZmF1bHQgZm9ybWF0dGVyID0gbnVsbFxuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9ICd7dmFsdWV95Lu2J1xuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9IChkYXRhSXRlbSkgPT4gKGRhdGFJdGVtLnZhbHVlKVxuICAgICAqL1xuICAgIGZvcm1hdHRlcjogbnVsbCxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lIGxhYmVsIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgZm9udFNpemU6IDEwXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTGluZSBjaGFydCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gMTBcbiAgICovXG4gIHJMZXZlbDogMTAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIGFuaW1hdGlvbiBjdXJ2ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25DdXJ2ZSA9ICdlYXNlT3V0Q3ViaWMnXG4gICAqL1xuICBhbmltYXRpb25DdXJ2ZTogJ2Vhc2VPdXRDdWJpYycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMaW5lIGFuaW1hdGlvbiBmcmFtZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25GcmFtZSA9IDUwXG4gICAqL1xuICBhbmltYXRpb25GcmFtZTogNTBcbn07XG5leHBvcnRzLmxpbmVDb25maWcgPSBsaW5lQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5waWVDb25maWcgPSB2b2lkIDA7XG52YXIgcGllQ29uZmlnID0ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSB0aGlzIHBpZSBjaGFydFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lID0gJydcbiAgICovXG4gIG5hbWU6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmFkaXVzIG9mIHBpZVxuICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICogQGRlZmF1bHQgcmFkaXVzID0gJzUwJSdcbiAgICogQGV4YW1wbGUgcmFkaXVzID0gJzUwJScgfCAxMDBcbiAgICovXG4gIHJhZGl1czogJzUwJScsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDZW50ZXIgcG9pbnQgb2YgcGllXG4gICAqIEB0eXBlIHtBcnJheX1cbiAgICogQGRlZmF1bHQgY2VudGVyID0gWyc1MCUnLCc1MCUnXVxuICAgKiBAZXhhbXBsZSBjZW50ZXIgPSBbJzUwJScsJzUwJSddIHwgWzEwMCwgMTAwXVxuICAgKi9cbiAgY2VudGVyOiBbJzUwJScsICc1MCUnXSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBpZSBjaGFydCBzdGFydCBhbmdsZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBzdGFydEFuZ2xlID0gLU1hdGguUEkgLyAyXG4gICAqIEBleGFtcGxlIHN0YXJ0QW5nbGUgPSAtTWF0aC5QSVxuICAgKi9cbiAgc3RhcnRBbmdsZTogLU1hdGguUEkgLyAyLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBlbmFibGUgcm9zZSB0eXBlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCByb3NlVHlwZSA9IGZhbHNlXG4gICAqL1xuICByb3NlVHlwZTogZmFsc2UsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBdXRvbWF0aWMgc29ydGluZyBpbiByb3NlIHR5cGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IHJvc2VTb3J0ID0gdHJ1ZVxuICAgKi9cbiAgcm9zZVNvcnQ6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSb3NlIHJhZGl1cyBpbmNyZWFzaW5nXG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCByb3NlSW5jcmVtZW50ID0gJ2F1dG8nXG4gICAqIEBleGFtcGxlIHJvc2VJbmNyZW1lbnQgPSAnYXV0bycgfCAnMTAlJyB8IDEwXG4gICAqL1xuICByb3NlSW5jcmVtZW50OiAnYXV0bycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgY2hhcnQgZGF0YVxuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqIEBkZWZhdWx0IGRhdGEgPSBbXVxuICAgKi9cbiAgZGF0YTogW10sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgaW5zaWRlIGxhYmVsIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGluc2lkZUxhYmVsOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSBpbnNpZGUgbGFiZWxcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gZmFsc2VcbiAgICAgKi9cbiAgICBzaG93OiBmYWxzZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMYWJlbCBmb3JtYXR0ZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfEZ1bmN0aW9ufVxuICAgICAqIEBkZWZhdWx0IGZvcm1hdHRlciA9ICd7cGVyY2VudH0lJ1xuICAgICAqIEBleGFtcGxlIGZvcm1hdHRlciA9ICcke25hbWV9LXt2YWx1ZX0te3BlcmNlbnR9JSdcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAoZGF0YUl0ZW0pID0+IChkYXRhSXRlbS5uYW1lKVxuICAgICAqL1xuICAgIGZvcm1hdHRlcjogJ3twZXJjZW50fSUnLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExhYmVsIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgZm9udFNpemU6IDEwLFxuICAgICAgZmlsbDogJyNmZmYnLFxuICAgICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICAgIHRleHRCYXNlbGluZTogJ21pZGRsZSdcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgT3V0c2lkZSBsYWJlbCBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBvdXRzaWRlTGFiZWw6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IG91dHNpZGUgbGFiZWxcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gZmFsc2VcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExhYmVsIGZvcm1hdHRlclxuICAgICAqIEB0eXBlIHtTdHJpbmd8RnVuY3Rpb259XG4gICAgICogQGRlZmF1bHQgZm9ybWF0dGVyID0gJ3tuYW1lfSdcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAnJHtuYW1lfS17dmFsdWV9LXtwZXJjZW50fSUnXG4gICAgICogQGV4YW1wbGUgZm9ybWF0dGVyID0gKGRhdGFJdGVtKSA9PiAoZGF0YUl0ZW0ubmFtZSlcbiAgICAgKi9cbiAgICBmb3JtYXR0ZXI6ICd7bmFtZX0nLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExhYmVsIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgZm9udFNpemU6IDExXG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBHYXAgYmV0ZWVuIGxhYmVsIGxpbmUgYmVuZGVkIHBsYWNlIGFuZCBwaWVcbiAgICAgKiBAdHlwZSB7U3RyaW5nfE51bWJlcn1cbiAgICAgKiBAZGVmYXVsdCBsYWJlbExpbmVCZW5kR2FwID0gJzIwJSdcbiAgICAgKiBAZXhhbXBsZSBsYWJlbExpbmVCZW5kR2FwID0gJzIwJScgfCAyMFxuICAgICAqL1xuICAgIGxhYmVsTGluZUJlbmRHYXA6ICcyMCUnLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExhYmVsIGxpbmUgZW5kIGxlbmd0aFxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQGRlZmF1bHQgbGFiZWxMaW5lRW5kTGVuZ3RoID0gNTBcbiAgICAgKi9cbiAgICBsYWJlbExpbmVFbmRMZW5ndGg6IDUwLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExhYmVsIGxpbmUgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIGxhYmVsTGluZVN0eWxlOiB7XG4gICAgICBsaW5lV2lkdGg6IDFcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAqL1xuICBwaWVTdHlsZToge30sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQZXJjZW50YWdlIGZyYWN0aW9uYWwgcHJlY2lzaW9uXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHBlcmNlbnRUb0ZpeGVkID0gMFxuICAgKi9cbiAgcGVyY2VudFRvRml4ZWQ6IDAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgY2hhcnQgcmVuZGVyIGxldmVsXG4gICAqIFByaW9yaXR5IHJlbmRlcmluZyBoaWdoIGxldmVsXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHJMZXZlbCA9IDEwXG4gICAqL1xuICByTGV2ZWw6IDEwLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQW5pbWF0aW9uIGRlbGF5IGdhcFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVmYXVsdCBhbmltYXRpb25EZWxheUdhcCA9IDYwXG4gICAqL1xuICBhbmltYXRpb25EZWxheUdhcDogNjAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgYW5pbWF0aW9uIGN1cnZlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkN1cnZlID0gJ2Vhc2VPdXRDdWJpYydcbiAgICovXG4gIGFuaW1hdGlvbkN1cnZlOiAnZWFzZU91dEN1YmljJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBpZSBzdGFydCBhbmltYXRpb24gY3VydmVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgc3RhcnRBbmltYXRpb25DdXJ2ZSA9ICdlYXNlT3V0QmFjaydcbiAgICovXG4gIHN0YXJ0QW5pbWF0aW9uQ3VydmU6ICdlYXNlT3V0QmFjaycsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQaWUgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMucGllQ29uZmlnID0gcGllQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5yYWRhckNvbmZpZyA9IHZvaWQgMDtcbnZhciByYWRhckNvbmZpZyA9IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgdGhpcyByYWRhclxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICovXG4gIHNob3c6IHRydWUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMZWdlbmQgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBuYW1lID0gJydcbiAgICovXG4gIG5hbWU6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmFkYXIgY2hhcnQgZGF0YVxuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqIEBkZWZhdWx0IGRhdGEgPSBbXVxuICAgKiBAZXhhbXBsZSBkYXRhID0gWzEwMCwgMjAwLCAzMDBdXG4gICAqL1xuICBkYXRhOiBbXSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgKi9cbiAgcmFkYXJTdHlsZToge1xuICAgIGxpbmVXaWR0aDogMVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmFkYXIgcG9pbnQgY29uZmlndXJhdGlvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgcG9pbnQ6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IHJhZGFyIHBvaW50XG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFBvaW50IHJhZGl1c1xuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQGRlZmF1bHQgcmFkaXVzID0gMlxuICAgICAqL1xuICAgIHJhZGl1czogMixcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBSYWRhciBwb2ludCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIGZpbGw6ICcjZmZmJ1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGxhYmVsIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGxhYmVsOiB7XG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZGlzcGxheSByYWRhciBsYWJlbFxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMYWJlbCBwb3NpdGlvbiBvZmZzZXRcbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICogQGRlZmF1bHQgb2Zmc2V0ID0gWzAsIDBdXG4gICAgICovXG4gICAgb2Zmc2V0OiBbMCwgMF0sXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gTGFiZWwgZ2FwIGJldHdlZW4gbGFiZWwgYW5kIHJhZGFyXG4gICAgICogQHR5cGUge051bWJlcn1cbiAgICAgKiBAZGVmYXVsdCBsYWJlbEdhcCA9IDVcbiAgICAgKi9cbiAgICBsYWJlbEdhcDogNSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMYWJlbCBmb3JtYXR0ZXJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfEZ1bmN0aW9ufVxuICAgICAqIEBkZWZhdWx0IGZvcm1hdHRlciA9IG51bGxcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAnU2NvcmUte3ZhbHVlfSdcbiAgICAgKiBAZXhhbXBsZSBmb3JtYXR0ZXIgPSAobGFiZWwpID0+IChsYWJlbClcbiAgICAgKi9cbiAgICBmb3JtYXR0ZXI6IG51bGwsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gUmFkYXIgbGFiZWwgZGVmYXVsdCBzdHlsZSBjb25maWd1cmF0aW9uXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKiBAZGVmYXVsdCBzdHlsZSA9IHtDb25maWd1cmF0aW9uIE9mIENsYXNzIFN0eWxlfVxuICAgICAqL1xuICAgIHN0eWxlOiB7XG4gICAgICBmb250U2l6ZTogMTBcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSYWRhciBjaGFydCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gMTBcbiAgICovXG4gIHJMZXZlbDogMTAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSYWRhciBhbmltYXRpb24gY3VydmVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYW5pbWF0aW9uQ3VydmUgPSAnZWFzZU91dEN1YmljJ1xuICAgKi9cbiAgYW5pbWF0aW9uQ3VydmU6ICdlYXNlT3V0Q3ViaWMnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmFkYXIgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW5lOiA1MFxufTtcbmV4cG9ydHMucmFkYXJDb25maWcgPSByYWRhckNvbmZpZzsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMucmFkYXJBeGlzQ29uZmlnID0gdm9pZCAwO1xudmFyIHJhZGFyQXhpc0NvbmZpZyA9IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgdGhpcyByYWRhciBheGlzXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgKi9cbiAgc2hvdzogdHJ1ZSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENlbnRlciBwb2ludCBvZiByYWRhciBheGlzXG4gICAqIEB0eXBlIHtBcnJheX1cbiAgICogQGRlZmF1bHQgY2VudGVyID0gWyc1MCUnLCc1MCUnXVxuICAgKiBAZXhhbXBsZSBjZW50ZXIgPSBbJzUwJScsJzUwJSddIHwgWzEwMCwgMTAwXVxuICAgKi9cbiAgY2VudGVyOiBbJzUwJScsICc1MCUnXSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGl1cyBvZiByYWRhciBheGlzXG4gICAqIEB0eXBlIHtTdHJpbmd8TnVtYmVyfVxuICAgKiBAZGVmYXVsdCByYWRpdXMgPSAnNjUlJ1xuICAgKiBAZXhhbXBsZSByYWRpdXMgPSAnNjUlJyB8IDEwMFxuICAgKi9cbiAgcmFkaXVzOiAnNjUlJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGF4aXMgc3RhcnQgYW5nbGVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgc3RhcnRBbmdsZSA9IC1NYXRoLlBJIC8gMlxuICAgKiBAZXhhbXBsZSBzdGFydEFuZ2xlID0gLU1hdGguUElcbiAgICovXG4gIHN0YXJ0QW5nbGU6IC1NYXRoLlBJIC8gMixcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGF4aXMgc3BsaXQgbnVtYmVyXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IHNwbGl0TnVtID0gNVxuICAgKi9cbiAgc3BsaXROdW06IDUsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGVuYWJsZSBwb2x5Z29uIHJhZGFyIGF4aXNcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IHBvbHlnb24gPSBmYWxzZVxuICAgKi9cbiAgcG9seWdvbjogZmFsc2UsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBeGlzIGxhYmVsIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIGF4aXNMYWJlbDoge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgYXhpcyBsYWJlbFxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAgICovXG4gICAgc2hvdzogdHJ1ZSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMYWJlbCBnYXAgYmV0d2VlbiBsYWJlbCBhbmQgcmFkYXIgYXhpc1xuICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICogQGRlZmF1bHQgbGFiZWxHYXAgPSAxNVxuICAgICAqL1xuICAgIGxhYmVsR2FwOiAxNSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBMYWJlbCBjb2xvciAoSGV4fHJnYnxyZ2JhKSwgd2lsbCBjb3ZlciBzdHlsZS5maWxsXG4gICAgICogQHR5cGUge0FycmF5fVxuICAgICAqIEBkZWZhdWx0IGNvbG9yID0gW11cbiAgICAgKi9cbiAgICBjb2xvcjogW10sXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIGZpbGw6ICcjMzMzJ1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEF4aXMgbGluZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBheGlzTGluZToge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgYXhpcyBsaW5lXG4gICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICogQGRlZmF1bHQgc2hvdyA9IHRydWVcbiAgICAgKi9cbiAgICBzaG93OiB0cnVlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIExpbmUgY29sb3IgKEhleHxyZ2J8cmdiYSksIHdpbGwgY292ZXIgc3R5bGUuc3Ryb2tlXG4gICAgICogQHR5cGUge0FycmF5fVxuICAgICAqIEBkZWZhdWx0IGNvbG9yID0gW11cbiAgICAgKi9cbiAgICBjb2xvcjogW10sXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gQXhpcyBsYWJlbCBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZWZhdWx0IHN0eWxlID0ge0NvbmZpZ3VyYXRpb24gT2YgQ2xhc3MgU3R5bGV9XG4gICAgICovXG4gICAgc3R5bGU6IHtcbiAgICAgIHN0cm9rZTogJyM5OTknLFxuICAgICAgbGluZVdpZHRoOiAxXG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU3BsaXQgbGluZSBjb25maWd1cmF0aW9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzcGxpdExpbmU6IHtcbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gV2hldGhlciB0byBkaXNwbGF5IHNwbGl0IGxpbmVcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgKiBAZGVmYXVsdCBzaG93ID0gdHJ1ZVxuICAgICAqL1xuICAgIHNob3c6IHRydWUsXG5cbiAgICAvKipcbiAgICAgKiBAZGVzY3JpcHRpb24gTGluZSBjb2xvciAoSGV4fHJnYnxyZ2JhKSwgd2lsbCBjb3ZlciBzdHlsZS5zdHJva2VcbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICogQGRlZmF1bHQgY29sb3IgPSBbXVxuICAgICAqL1xuICAgIGNvbG9yOiBbXSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBTcGxpdCBsaW5lIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge1xuICAgICAgc3Ryb2tlOiAnI2Q0ZDRkNCcsXG4gICAgICBsaW5lV2lkdGg6IDFcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTcGxpdCBhcmVhIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHNwbGl0QXJlYToge1xuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgc3BsaXQgYXJlYVxuICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAqIEBkZWZhdWx0IHNob3cgPSBmYWxzZVxuICAgICAqL1xuICAgIHNob3c6IGZhbHNlLFxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIEFyZWEgY29sb3IgKEhleHxyZ2J8cmdiYSksIHdpbGwgY292ZXIgc3R5bGUuc3Ryb2tlXG4gICAgICogQHR5cGUge0FycmF5fVxuICAgICAqIEBkZWZhdWx0IGNvbG9yID0gW11cbiAgICAgKi9cbiAgICBjb2xvcjogWycjZjVmNWY1JywgJyNlNmU2ZTYnXSxcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBTcGxpdCBhcmVhIGRlZmF1bHQgc3R5bGUgY29uZmlndXJhdGlvblxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICAgKi9cbiAgICBzdHlsZToge31cbiAgfSxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJhciBjaGFydCByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gLTEwXG4gICAqL1xuICByTGV2ZWw6IC0xMCxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGF4aXMgYW5pbWF0aW9uIGN1cnZlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkN1cnZlID0gJ2Vhc2VPdXRDdWJpYydcbiAgICovXG4gIGFuaW1hdGlvbkN1cnZlOiAnZWFzZU91dEN1YmljJyxcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJhZGFyIGF4aXMgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW5lOiA1MFxufTtcbmV4cG9ydHMucmFkYXJBeGlzQ29uZmlnID0gcmFkYXJBeGlzQ29uZmlnOyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy50aXRsZUNvbmZpZyA9IHZvaWQgMDtcbnZhciB0aXRsZUNvbmZpZyA9IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGRpc3BsYXkgdGl0bGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IHNob3cgPSB0cnVlXG4gICAqL1xuICBzaG93OiB0cnVlLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGl0bGUgdGV4dFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCB0ZXh0ID0gJydcbiAgICovXG4gIHRleHQ6ICcnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGl0bGUgb2Zmc2V0XG4gICAqIEB0eXBlIHtBcnJheX1cbiAgICogQGRlZmF1bHQgb2Zmc2V0ID0gWzAsIC0yMF1cbiAgICovXG4gIG9mZnNldDogWzAsIC0yMF0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaXRsZSBkZWZhdWx0IHN0eWxlIGNvbmZpZ3VyYXRpb25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlZmF1bHQgc3R5bGUgPSB7Q29uZmlndXJhdGlvbiBPZiBDbGFzcyBTdHlsZX1cbiAgICovXG4gIHN0eWxlOiB7XG4gICAgZmlsbDogJyMzMzMnLFxuICAgIGZvbnRTaXplOiAxNyxcbiAgICBmb250V2VpZ2h0OiAnYm9sZCcsXG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICB0ZXh0QmFzZWxpbmU6ICdib3R0b20nXG4gIH0sXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaXRsZSByZW5kZXIgbGV2ZWxcbiAgICogUHJpb3JpdHkgcmVuZGVyaW5nIGhpZ2ggbGV2ZWxcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgckxldmVsID0gMjBcbiAgICovXG4gIHJMZXZlbDogMjAsXG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaXRsZSBhbmltYXRpb24gY3VydmVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYW5pbWF0aW9uQ3VydmUgPSAnZWFzZU91dEN1YmljJ1xuICAgKi9cbiAgYW5pbWF0aW9uQ3VydmU6ICdlYXNlT3V0Q3ViaWMnLFxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGl0bGUgYW5pbWF0aW9uIGZyYW1lXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IGFuaW1hdGlvbkZyYW1lID0gNTBcbiAgICovXG4gIGFuaW1hdGlvbkZyYW1lOiA1MFxufTtcbmV4cG9ydHMudGl0bGVDb25maWcgPSB0aXRsZUNvbmZpZzsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmF4aXMgPSBheGlzO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX2RlZmluZVByb3BlcnR5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvZGVmaW5lUHJvcGVydHlcIikpO1xuXG52YXIgX3RvQ29uc3VtYWJsZUFycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdG9Db25zdW1hYmxlQXJyYXlcIikpO1xuXG52YXIgX3VwZGF0ZXIgPSByZXF1aXJlKFwiLi4vY2xhc3MvdXBkYXRlci5jbGFzc1wiKTtcblxudmFyIF9jb25maWcgPSByZXF1aXJlKFwiLi4vY29uZmlnXCIpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiLi4vdXRpbFwiKTtcblxudmFyIF91dGlsMiA9IHJlcXVpcmUoXCJAamlhbWluZ2hpL2MtcmVuZGVyL2xpYi9wbHVnaW4vdXRpbFwiKTtcblxuZnVuY3Rpb24gb3duS2V5cyhvYmplY3QsIGVudW1lcmFibGVPbmx5KSB7IHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTsgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHsgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7IGlmIChlbnVtZXJhYmxlT25seSkgc3ltYm9scyA9IHN5bWJvbHMuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHsgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBzeW0pLmVudW1lcmFibGU7IH0pOyBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7IH0gcmV0dXJuIGtleXM7IH1cblxuZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307IGlmIChpICUgMikgeyBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7ICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTsgfSk7IH0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpIHsgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzb3VyY2UpKTsgfSBlbHNlIHsgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsgfSk7IH0gfSByZXR1cm4gdGFyZ2V0OyB9XG5cbnZhciBheGlzQ29uZmlnID0ge1xuICB4QXhpc0NvbmZpZzogX2NvbmZpZy54QXhpc0NvbmZpZyxcbiAgeUF4aXNDb25maWc6IF9jb25maWcueUF4aXNDb25maWdcbn07XG52YXIgbWluID0gTWF0aC5taW4sXG4gICAgbWF4ID0gTWF0aC5tYXgsXG4gICAgYWJzID0gTWF0aC5hYnMsXG4gICAgcG93ID0gTWF0aC5wb3c7XG5cbmZ1bmN0aW9uIGF4aXMoY2hhcnQpIHtcbiAgdmFyIG9wdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG4gIHZhciB4QXhpcyA9IG9wdGlvbi54QXhpcyxcbiAgICAgIHlBeGlzID0gb3B0aW9uLnlBeGlzLFxuICAgICAgc2VyaWVzID0gb3B0aW9uLnNlcmllcztcbiAgdmFyIGFsbEF4aXMgPSBbXTtcblxuICBpZiAoeEF4aXMgJiYgeUF4aXMgJiYgc2VyaWVzKSB7XG4gICAgYWxsQXhpcyA9IGdldEFsbEF4aXMoeEF4aXMsIHlBeGlzKTtcbiAgICBhbGxBeGlzID0gbWVyZ2VEZWZhdWx0QXhpc0NvbmZpZyhhbGxBeGlzKTtcbiAgICBhbGxBeGlzID0gYWxsQXhpcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWYpIHtcbiAgICAgIHZhciBzaG93ID0gX3JlZi5zaG93O1xuICAgICAgcmV0dXJuIHNob3c7XG4gICAgfSk7XG4gICAgYWxsQXhpcyA9IG1lcmdlRGVmYXVsdEJvdW5kYXJ5R2FwKGFsbEF4aXMpO1xuICAgIGFsbEF4aXMgPSBjYWxjQXhpc0xhYmVsRGF0YShhbGxBeGlzLCBzZXJpZXMpO1xuICAgIGFsbEF4aXMgPSBzZXRBeGlzUG9zaXRpb24oYWxsQXhpcyk7XG4gICAgYWxsQXhpcyA9IGNhbGNBeGlzTGluZVBvc2l0aW9uKGFsbEF4aXMsIGNoYXJ0KTtcbiAgICBhbGxBeGlzID0gY2FsY0F4aXNUaWNrUG9zaXRpb24oYWxsQXhpcywgY2hhcnQpO1xuICAgIGFsbEF4aXMgPSBjYWxjQXhpc05hbWVQb3NpdGlvbihhbGxBeGlzLCBjaGFydCk7XG4gICAgYWxsQXhpcyA9IGNhbGNTcGxpdExpbmVQb3NpdGlvbihhbGxBeGlzLCBjaGFydCk7XG4gIH1cblxuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiBhbGxBeGlzLFxuICAgIGtleTogJ2F4aXNMaW5lJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0TGluZUNvbmZpZ1xuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogYWxsQXhpcyxcbiAgICBrZXk6ICdheGlzVGljaycsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFRpY2tDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGFsbEF4aXMsXG4gICAga2V5OiAnYXhpc0xhYmVsJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0TGFiZWxDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGFsbEF4aXMsXG4gICAga2V5OiAnYXhpc05hbWUnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXROYW1lQ29uZmlnXG4gIH0pO1xuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiBhbGxBeGlzLFxuICAgIGtleTogJ3NwbGl0TGluZScsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFNwbGl0TGluZUNvbmZpZ1xuICB9KTtcbiAgY2hhcnQuYXhpc0RhdGEgPSBhbGxBeGlzO1xufVxuXG5mdW5jdGlvbiBnZXRBbGxBeGlzKHhBeGlzLCB5QXhpcykge1xuICB2YXIgYWxsWEF4aXMgPSBbXSxcbiAgICAgIGFsbFlBeGlzID0gW107XG5cbiAgaWYgKHhBeGlzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICB2YXIgX2FsbFhBeGlzO1xuXG4gICAgKF9hbGxYQXhpcyA9IGFsbFhBeGlzKS5wdXNoLmFwcGx5KF9hbGxYQXhpcywgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh4QXhpcykpO1xuICB9IGVsc2Uge1xuICAgIGFsbFhBeGlzLnB1c2goeEF4aXMpO1xuICB9XG5cbiAgaWYgKHlBeGlzIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICB2YXIgX2FsbFlBeGlzO1xuXG4gICAgKF9hbGxZQXhpcyA9IGFsbFlBeGlzKS5wdXNoLmFwcGx5KF9hbGxZQXhpcywgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh5QXhpcykpO1xuICB9IGVsc2Uge1xuICAgIGFsbFlBeGlzLnB1c2goeUF4aXMpO1xuICB9XG5cbiAgYWxsWEF4aXMuc3BsaWNlKDIpO1xuICBhbGxZQXhpcy5zcGxpY2UoMik7XG4gIGFsbFhBeGlzID0gYWxsWEF4aXMubWFwKGZ1bmN0aW9uIChheGlzLCBpKSB7XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQoe30sIGF4aXMsIHtcbiAgICAgIGluZGV4OiBpLFxuICAgICAgYXhpczogJ3gnXG4gICAgfSk7XG4gIH0pO1xuICBhbGxZQXhpcyA9IGFsbFlBeGlzLm1hcChmdW5jdGlvbiAoYXhpcywgaSkge1xuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBheGlzLCB7XG4gICAgICBpbmRleDogaSxcbiAgICAgIGF4aXM6ICd5J1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIFtdLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGFsbFhBeGlzKSwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhbGxZQXhpcykpO1xufVxuXG5mdW5jdGlvbiBtZXJnZURlZmF1bHRBeGlzQ29uZmlnKGFsbEF4aXMpIHtcbiAgdmFyIHhBeGlzID0gYWxsQXhpcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWYyKSB7XG4gICAgdmFyIGF4aXMgPSBfcmVmMi5heGlzO1xuICAgIHJldHVybiBheGlzID09PSAneCc7XG4gIH0pO1xuICB2YXIgeUF4aXMgPSBhbGxBeGlzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjMpIHtcbiAgICB2YXIgYXhpcyA9IF9yZWYzLmF4aXM7XG4gICAgcmV0dXJuIGF4aXMgPT09ICd5JztcbiAgfSk7XG4gIHhBeGlzID0geEF4aXMubWFwKGZ1bmN0aW9uIChheGlzKSB7XG4gICAgcmV0dXJuICgwLCBfdXRpbC5kZWVwTWVyZ2UpKCgwLCBfdXRpbDIuZGVlcENsb25lKShfY29uZmlnLnhBeGlzQ29uZmlnKSwgYXhpcyk7XG4gIH0pO1xuICB5QXhpcyA9IHlBeGlzLm1hcChmdW5jdGlvbiAoYXhpcykge1xuICAgIHJldHVybiAoMCwgX3V0aWwuZGVlcE1lcmdlKSgoMCwgX3V0aWwyLmRlZXBDbG9uZSkoX2NvbmZpZy55QXhpc0NvbmZpZyksIGF4aXMpO1xuICB9KTtcbiAgcmV0dXJuIFtdLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHhBeGlzKSwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh5QXhpcykpO1xufVxuXG5mdW5jdGlvbiBtZXJnZURlZmF1bHRCb3VuZGFyeUdhcChhbGxBeGlzKSB7XG4gIHZhciB2YWx1ZUF4aXMgPSBhbGxBeGlzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjQpIHtcbiAgICB2YXIgZGF0YSA9IF9yZWY0LmRhdGE7XG4gICAgcmV0dXJuIGRhdGEgPT09ICd2YWx1ZSc7XG4gIH0pO1xuICB2YXIgbGFiZWxBeGlzID0gYWxsQXhpcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWY1KSB7XG4gICAgdmFyIGRhdGEgPSBfcmVmNS5kYXRhO1xuICAgIHJldHVybiBkYXRhICE9PSAndmFsdWUnO1xuICB9KTtcbiAgdmFsdWVBeGlzLmZvckVhY2goZnVuY3Rpb24gKGF4aXMpIHtcbiAgICBpZiAodHlwZW9mIGF4aXMuYm91bmRhcnlHYXAgPT09ICdib29sZWFuJykgcmV0dXJuO1xuICAgIGF4aXMuYm91bmRhcnlHYXAgPSBmYWxzZTtcbiAgfSk7XG4gIGxhYmVsQXhpcy5mb3JFYWNoKGZ1bmN0aW9uIChheGlzKSB7XG4gICAgaWYgKHR5cGVvZiBheGlzLmJvdW5kYXJ5R2FwID09PSAnYm9vbGVhbicpIHJldHVybjtcbiAgICBheGlzLmJvdW5kYXJ5R2FwID0gdHJ1ZTtcbiAgfSk7XG4gIHJldHVybiBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh2YWx1ZUF4aXMpLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGxhYmVsQXhpcykpO1xufVxuXG5mdW5jdGlvbiBjYWxjQXhpc0xhYmVsRGF0YShhbGxBeGlzLCBzZXJpZXMpIHtcbiAgdmFyIHZhbHVlQXhpcyA9IGFsbEF4aXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmNikge1xuICAgIHZhciBkYXRhID0gX3JlZjYuZGF0YTtcbiAgICByZXR1cm4gZGF0YSA9PT0gJ3ZhbHVlJztcbiAgfSk7XG4gIHZhciBsYWJlbEF4aXMgPSBhbGxBeGlzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjcpIHtcbiAgICB2YXIgZGF0YSA9IF9yZWY3LmRhdGE7XG4gICAgcmV0dXJuIGRhdGEgaW5zdGFuY2VvZiBBcnJheTtcbiAgfSk7XG4gIHZhbHVlQXhpcyA9IGNhbGNWYWx1ZUF4aXNMYWJlbERhdGEodmFsdWVBeGlzLCBzZXJpZXMpO1xuICBsYWJlbEF4aXMgPSBjYWxjTGFiZWxBeGlzTGFiZWxEYXRhKGxhYmVsQXhpcyk7XG4gIHJldHVybiBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh2YWx1ZUF4aXMpLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGxhYmVsQXhpcykpO1xufVxuXG5mdW5jdGlvbiBjYWxjVmFsdWVBeGlzTGFiZWxEYXRhKHZhbHVlQXhpcywgc2VyaWVzKSB7XG4gIHJldHVybiB2YWx1ZUF4aXMubWFwKGZ1bmN0aW9uIChheGlzKSB7XG4gICAgdmFyIG1pbk1heFZhbHVlID0gZ2V0VmFsdWVBeGlzTWF4TWluVmFsdWUoYXhpcywgc2VyaWVzKTtcblxuICAgIHZhciBfZ2V0VHJ1ZU1pbk1heCA9IGdldFRydWVNaW5NYXgoYXhpcywgbWluTWF4VmFsdWUpLFxuICAgICAgICBfZ2V0VHJ1ZU1pbk1heDIgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX2dldFRydWVNaW5NYXgsIDIpLFxuICAgICAgICBtaW4gPSBfZ2V0VHJ1ZU1pbk1heDJbMF0sXG4gICAgICAgIG1heCA9IF9nZXRUcnVlTWluTWF4MlsxXTtcblxuICAgIHZhciBpbnRlcnZhbCA9IGdldFZhbHVlSW50ZXJ2YWwobWluLCBtYXgsIGF4aXMpO1xuICAgIHZhciBmb3JtYXR0ZXIgPSBheGlzLmF4aXNMYWJlbC5mb3JtYXR0ZXI7XG4gICAgdmFyIGxhYmVsID0gW107XG5cbiAgICBpZiAobWluTWF4VmFsdWVbMF0gPT09IG1pbk1heFZhbHVlWzFdKSB7XG4gICAgICBsYWJlbCA9IG1pbk1heFZhbHVlO1xuICAgIH0gZWxzZSBpZiAobWluIDwgMCAmJiBtYXggPiAwKSB7XG4gICAgICBsYWJlbCA9IGdldFZhbHVlQXhpc0xhYmVsRnJvbVplcm8obWluLCBtYXgsIGludGVydmFsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGFiZWwgPSBnZXRWYWx1ZUF4aXNMYWJlbEZyb21NaW4obWluLCBtYXgsIGludGVydmFsKTtcbiAgICB9XG5cbiAgICBsYWJlbCA9IGxhYmVsLm1hcChmdW5jdGlvbiAobCkge1xuICAgICAgcmV0dXJuIHBhcnNlRmxvYXQobC50b0ZpeGVkKDIpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gX29iamVjdFNwcmVhZCh7fSwgYXhpcywge1xuICAgICAgbWF4VmFsdWU6IGxhYmVsLnNsaWNlKC0xKVswXSxcbiAgICAgIG1pblZhbHVlOiBsYWJlbFswXSxcbiAgICAgIGxhYmVsOiBnZXRBZnRlckZvcm1hdHRlckxhYmVsKGxhYmVsLCBmb3JtYXR0ZXIpXG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRWYWx1ZUF4aXNNYXhNaW5WYWx1ZShheGlzLCBzZXJpZXMpIHtcbiAgc2VyaWVzID0gc2VyaWVzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjgpIHtcbiAgICB2YXIgc2hvdyA9IF9yZWY4LnNob3csXG4gICAgICAgIHR5cGUgPSBfcmVmOC50eXBlO1xuICAgIGlmIChzaG93ID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICh0eXBlID09PSAncGllJykgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbiAgaWYgKHNlcmllcy5sZW5ndGggPT09IDApIHJldHVybiBbMCwgMF07XG4gIHZhciBpbmRleCA9IGF4aXMuaW5kZXgsXG4gICAgICBheGlzVHlwZSA9IGF4aXMuYXhpcztcbiAgc2VyaWVzID0gbWVyZ2VTdGFja0RhdGEoc2VyaWVzKTtcbiAgdmFyIGF4aXNOYW1lID0gYXhpc1R5cGUgKyAnQXhpcyc7XG4gIHZhciB2YWx1ZVNlcmllcyA9IHNlcmllcy5maWx0ZXIoZnVuY3Rpb24gKHMpIHtcbiAgICByZXR1cm4gc1theGlzTmFtZV0gPT09IGluZGV4O1xuICB9KTtcbiAgaWYgKCF2YWx1ZVNlcmllcy5sZW5ndGgpIHZhbHVlU2VyaWVzID0gc2VyaWVzO1xuICByZXR1cm4gZ2V0U2VyaWVzTWluTWF4VmFsdWUodmFsdWVTZXJpZXMpO1xufVxuXG5mdW5jdGlvbiBnZXRTZXJpZXNNaW5NYXhWYWx1ZShzZXJpZXMpIHtcbiAgaWYgKCFzZXJpZXMpIHJldHVybjtcbiAgdmFyIG1pblZhbHVlID0gTWF0aC5taW4uYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShzZXJpZXMubWFwKGZ1bmN0aW9uIChfcmVmOSkge1xuICAgIHZhciBkYXRhID0gX3JlZjkuZGF0YTtcbiAgICByZXR1cm4gTWF0aC5taW4uYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSgoMCwgX3V0aWwuZmlsdGVyTm9uTnVtYmVyKShkYXRhKSkpO1xuICB9KSkpO1xuICB2YXIgbWF4VmFsdWUgPSBNYXRoLm1heC5hcHBseShNYXRoLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHNlcmllcy5tYXAoZnVuY3Rpb24gKF9yZWYxMCkge1xuICAgIHZhciBkYXRhID0gX3JlZjEwLmRhdGE7XG4gICAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoKDAsIF91dGlsLmZpbHRlck5vbk51bWJlcikoZGF0YSkpKTtcbiAgfSkpKTtcbiAgcmV0dXJuIFttaW5WYWx1ZSwgbWF4VmFsdWVdO1xufVxuXG5mdW5jdGlvbiBtZXJnZVN0YWNrRGF0YShzZXJpZXMpIHtcbiAgdmFyIHNlcmllc0Nsb25lZCA9ICgwLCBfdXRpbDIuZGVlcENsb25lKShzZXJpZXMsIHRydWUpO1xuICBzZXJpZXMuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgIHZhciBkYXRhID0gKDAsIF91dGlsLm1lcmdlU2FtZVN0YWNrRGF0YSkoaXRlbSwgc2VyaWVzKTtcbiAgICBzZXJpZXNDbG9uZWRbaV0uZGF0YSA9IGRhdGE7XG4gIH0pO1xuICByZXR1cm4gc2VyaWVzQ2xvbmVkO1xufVxuXG5mdW5jdGlvbiBnZXRUcnVlTWluTWF4KF9yZWYxMSwgX3JlZjEyKSB7XG4gIHZhciBtaW4gPSBfcmVmMTEubWluLFxuICAgICAgbWF4ID0gX3JlZjExLm1heCxcbiAgICAgIGF4aXMgPSBfcmVmMTEuYXhpcztcblxuICB2YXIgX3JlZjEzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxMiwgMiksXG4gICAgICBtaW5WYWx1ZSA9IF9yZWYxM1swXSxcbiAgICAgIG1heFZhbHVlID0gX3JlZjEzWzFdO1xuXG4gIHZhciBtaW5UeXBlID0gKDAsIF90eXBlb2YyW1wiZGVmYXVsdFwiXSkobWluKSxcbiAgICAgIG1heFR5cGUgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShtYXgpO1xuXG4gIGlmICghdGVzdE1pbk1heFR5cGUobWluKSkge1xuICAgIG1pbiA9IGF4aXNDb25maWdbYXhpcyArICdBeGlzQ29uZmlnJ10ubWluO1xuICAgIG1pblR5cGUgPSAnc3RyaW5nJztcbiAgfVxuXG4gIGlmICghdGVzdE1pbk1heFR5cGUobWF4KSkge1xuICAgIG1heCA9IGF4aXNDb25maWdbYXhpcyArICdBeGlzQ29uZmlnJ10ubWF4O1xuICAgIG1heFR5cGUgPSAnc3RyaW5nJztcbiAgfVxuXG4gIGlmIChtaW5UeXBlID09PSAnc3RyaW5nJykge1xuICAgIG1pbiA9IHBhcnNlSW50KG1pblZhbHVlIC0gYWJzKG1pblZhbHVlICogcGFyc2VGbG9hdChtaW4pIC8gMTAwKSk7XG4gICAgdmFyIGxldmVyID0gZ2V0VmFsdWVMZXZlcihtaW4pO1xuICAgIG1pbiA9IHBhcnNlRmxvYXQoKG1pbiAvIGxldmVyIC0gMC4xKS50b0ZpeGVkKDEpKSAqIGxldmVyO1xuICB9XG5cbiAgaWYgKG1heFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgbWF4ID0gcGFyc2VJbnQobWF4VmFsdWUgKyBhYnMobWF4VmFsdWUgKiBwYXJzZUZsb2F0KG1heCkgLyAxMDApKTtcblxuICAgIHZhciBfbGV2ZXIgPSBnZXRWYWx1ZUxldmVyKG1heCk7XG5cbiAgICBtYXggPSBwYXJzZUZsb2F0KChtYXggLyBfbGV2ZXIgKyAwLjEpLnRvRml4ZWQoMSkpICogX2xldmVyO1xuICB9XG5cbiAgcmV0dXJuIFttaW4sIG1heF07XG59XG5cbmZ1bmN0aW9uIGdldFZhbHVlTGV2ZXIodmFsdWUpIHtcbiAgdmFyIHZhbHVlU3RyaW5nID0gYWJzKHZhbHVlKS50b1N0cmluZygpO1xuICB2YXIgdmFsdWVMZW5ndGggPSB2YWx1ZVN0cmluZy5sZW5ndGg7XG4gIHZhciBmaXJzdFplcm9JbmRleCA9IHZhbHVlU3RyaW5nLnJlcGxhY2UoLzAqJC9nLCAnJykuaW5kZXhPZignMCcpO1xuICB2YXIgcG93MTBOdW0gPSB2YWx1ZUxlbmd0aCAtIDE7XG4gIGlmIChmaXJzdFplcm9JbmRleCAhPT0gLTEpIHBvdzEwTnVtIC09IGZpcnN0WmVyb0luZGV4O1xuICByZXR1cm4gcG93KDEwLCBwb3cxME51bSk7XG59XG5cbmZ1bmN0aW9uIHRlc3RNaW5NYXhUeXBlKHZhbCkge1xuICB2YXIgdmFsVHlwZSA9ICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKHZhbCk7XG4gIHZhciBpc1ZhbGlkU3RyaW5nID0gdmFsVHlwZSA9PT0gJ3N0cmluZycgJiYgL15cXGQrJSQvLnRlc3QodmFsKTtcbiAgdmFyIGlzVmFsaWROdW1iZXIgPSB2YWxUeXBlID09PSAnbnVtYmVyJztcbiAgcmV0dXJuIGlzVmFsaWRTdHJpbmcgfHwgaXNWYWxpZE51bWJlcjtcbn1cblxuZnVuY3Rpb24gZ2V0VmFsdWVBeGlzTGFiZWxGcm9tWmVybyhtaW4sIG1heCwgaW50ZXJ2YWwpIHtcbiAgdmFyIG5lZ2F0aXZlID0gW10sXG4gICAgICBwb3NpdGl2ZSA9IFtdO1xuICB2YXIgY3VycmVudE5lZ2F0aXZlID0gMCxcbiAgICAgIGN1cnJlbnRQb3NpdGl2ZSA9IDA7XG5cbiAgZG8ge1xuICAgIG5lZ2F0aXZlLnB1c2goY3VycmVudE5lZ2F0aXZlIC09IGludGVydmFsKTtcbiAgfSB3aGlsZSAoY3VycmVudE5lZ2F0aXZlID4gbWluKTtcblxuICBkbyB7XG4gICAgcG9zaXRpdmUucHVzaChjdXJyZW50UG9zaXRpdmUgKz0gaW50ZXJ2YWwpO1xuICB9IHdoaWxlIChjdXJyZW50UG9zaXRpdmUgPCBtYXgpO1xuXG4gIHJldHVybiBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShuZWdhdGl2ZS5yZXZlcnNlKCkpLCBbMF0sICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9zaXRpdmUpKTtcbn1cblxuZnVuY3Rpb24gZ2V0VmFsdWVBeGlzTGFiZWxGcm9tTWluKG1pbiwgbWF4LCBpbnRlcnZhbCkge1xuICB2YXIgbGFiZWwgPSBbbWluXSxcbiAgICAgIGN1cnJlbnRWYWx1ZSA9IG1pbjtcblxuICBkbyB7XG4gICAgbGFiZWwucHVzaChjdXJyZW50VmFsdWUgKz0gaW50ZXJ2YWwpO1xuICB9IHdoaWxlIChjdXJyZW50VmFsdWUgPCBtYXgpO1xuXG4gIHJldHVybiBsYWJlbDtcbn1cblxuZnVuY3Rpb24gZ2V0QWZ0ZXJGb3JtYXR0ZXJMYWJlbChsYWJlbCwgZm9ybWF0dGVyKSB7XG4gIGlmICghZm9ybWF0dGVyKSByZXR1cm4gbGFiZWw7XG4gIGlmICh0eXBlb2YgZm9ybWF0dGVyID09PSAnc3RyaW5nJykgbGFiZWwgPSBsYWJlbC5tYXAoZnVuY3Rpb24gKGwpIHtcbiAgICByZXR1cm4gZm9ybWF0dGVyLnJlcGxhY2UoJ3t2YWx1ZX0nLCBsKTtcbiAgfSk7XG4gIGlmICh0eXBlb2YgZm9ybWF0dGVyID09PSAnZnVuY3Rpb24nKSBsYWJlbCA9IGxhYmVsLm1hcChmdW5jdGlvbiAodmFsdWUsIGluZGV4KSB7XG4gICAgcmV0dXJuIGZvcm1hdHRlcih7XG4gICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICBpbmRleDogaW5kZXhcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBsYWJlbDtcbn1cblxuZnVuY3Rpb24gY2FsY0xhYmVsQXhpc0xhYmVsRGF0YShsYWJlbEF4aXMpIHtcbiAgcmV0dXJuIGxhYmVsQXhpcy5tYXAoZnVuY3Rpb24gKGF4aXMpIHtcbiAgICB2YXIgZGF0YSA9IGF4aXMuZGF0YSxcbiAgICAgICAgZm9ybWF0dGVyID0gYXhpcy5heGlzTGFiZWwuZm9ybWF0dGVyO1xuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBheGlzLCB7XG4gICAgICBsYWJlbDogZ2V0QWZ0ZXJGb3JtYXR0ZXJMYWJlbChkYXRhLCBmb3JtYXR0ZXIpXG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRWYWx1ZUludGVydmFsKG1pbiwgbWF4LCBheGlzKSB7XG4gIHZhciBpbnRlcnZhbCA9IGF4aXMuaW50ZXJ2YWwsXG4gICAgICBtaW5JbnRlcnZhbCA9IGF4aXMubWluSW50ZXJ2YWwsXG4gICAgICBtYXhJbnRlcnZhbCA9IGF4aXMubWF4SW50ZXJ2YWwsXG4gICAgICBzcGxpdE51bWJlciA9IGF4aXMuc3BsaXROdW1iZXIsXG4gICAgICBheGlzVHlwZSA9IGF4aXMuYXhpcztcbiAgdmFyIGNvbmZpZyA9IGF4aXNDb25maWdbYXhpc1R5cGUgKyAnQXhpc0NvbmZpZyddO1xuICBpZiAodHlwZW9mIGludGVydmFsICE9PSAnbnVtYmVyJykgaW50ZXJ2YWwgPSBjb25maWcuaW50ZXJ2YWw7XG4gIGlmICh0eXBlb2YgbWluSW50ZXJ2YWwgIT09ICdudW1iZXInKSBtaW5JbnRlcnZhbCA9IGNvbmZpZy5taW5JbnRlcnZhbDtcbiAgaWYgKHR5cGVvZiBtYXhJbnRlcnZhbCAhPT0gJ251bWJlcicpIG1heEludGVydmFsID0gY29uZmlnLm1heEludGVydmFsO1xuICBpZiAodHlwZW9mIHNwbGl0TnVtYmVyICE9PSAnbnVtYmVyJykgc3BsaXROdW1iZXIgPSBjb25maWcuc3BsaXROdW1iZXI7XG4gIGlmICh0eXBlb2YgaW50ZXJ2YWwgPT09ICdudW1iZXInKSByZXR1cm4gaW50ZXJ2YWw7XG4gIHZhciB2YWx1ZUludGVydmFsID0gcGFyc2VJbnQoKG1heCAtIG1pbikgLyAoc3BsaXROdW1iZXIgLSAxKSk7XG4gIGlmICh2YWx1ZUludGVydmFsLnRvU3RyaW5nKCkubGVuZ3RoID4gMSkgdmFsdWVJbnRlcnZhbCA9IHBhcnNlSW50KHZhbHVlSW50ZXJ2YWwudG9TdHJpbmcoKS5yZXBsYWNlKC9cXGQkLywgJzAnKSk7XG4gIGlmICh2YWx1ZUludGVydmFsID09PSAwKSB2YWx1ZUludGVydmFsID0gMTtcbiAgaWYgKHR5cGVvZiBtaW5JbnRlcnZhbCA9PT0gJ251bWJlcicgJiYgdmFsdWVJbnRlcnZhbCA8IG1pbkludGVydmFsKSByZXR1cm4gbWluSW50ZXJ2YWw7XG4gIGlmICh0eXBlb2YgbWF4SW50ZXJ2YWwgPT09ICdudW1iZXInICYmIHZhbHVlSW50ZXJ2YWwgPiBtYXhJbnRlcnZhbCkgcmV0dXJuIG1heEludGVydmFsO1xuICByZXR1cm4gdmFsdWVJbnRlcnZhbDtcbn1cblxuZnVuY3Rpb24gc2V0QXhpc1Bvc2l0aW9uKGFsbEF4aXMpIHtcbiAgdmFyIHhBeGlzID0gYWxsQXhpcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWYxNCkge1xuICAgIHZhciBheGlzID0gX3JlZjE0LmF4aXM7XG4gICAgcmV0dXJuIGF4aXMgPT09ICd4JztcbiAgfSk7XG4gIHZhciB5QXhpcyA9IGFsbEF4aXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmMTUpIHtcbiAgICB2YXIgYXhpcyA9IF9yZWYxNS5heGlzO1xuICAgIHJldHVybiBheGlzID09PSAneSc7XG4gIH0pO1xuICBpZiAoeEF4aXNbMF0gJiYgIXhBeGlzWzBdLnBvc2l0aW9uKSB4QXhpc1swXS5wb3NpdGlvbiA9IF9jb25maWcueEF4aXNDb25maWcucG9zaXRpb247XG5cbiAgaWYgKHhBeGlzWzFdICYmICF4QXhpc1sxXS5wb3NpdGlvbikge1xuICAgIHhBeGlzWzFdLnBvc2l0aW9uID0geEF4aXNbMF0ucG9zaXRpb24gPT09ICdib3R0b20nID8gJ3RvcCcgOiAnYm90dG9tJztcbiAgfVxuXG4gIGlmICh5QXhpc1swXSAmJiAheUF4aXNbMF0ucG9zaXRpb24pIHlBeGlzWzBdLnBvc2l0aW9uID0gX2NvbmZpZy55QXhpc0NvbmZpZy5wb3NpdGlvbjtcblxuICBpZiAoeUF4aXNbMV0gJiYgIXlBeGlzWzFdLnBvc2l0aW9uKSB7XG4gICAgeUF4aXNbMV0ucG9zaXRpb24gPSB5QXhpc1swXS5wb3NpdGlvbiA9PT0gJ2xlZnQnID8gJ3JpZ2h0JyA6ICdsZWZ0JztcbiAgfVxuXG4gIHJldHVybiBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKSh4QXhpcyksICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoeUF4aXMpKTtcbn1cblxuZnVuY3Rpb24gY2FsY0F4aXNMaW5lUG9zaXRpb24oYWxsQXhpcywgY2hhcnQpIHtcbiAgdmFyIF9jaGFydCRncmlkQXJlYSA9IGNoYXJ0LmdyaWRBcmVhLFxuICAgICAgeCA9IF9jaGFydCRncmlkQXJlYS54LFxuICAgICAgeSA9IF9jaGFydCRncmlkQXJlYS55LFxuICAgICAgdyA9IF9jaGFydCRncmlkQXJlYS53LFxuICAgICAgaCA9IF9jaGFydCRncmlkQXJlYS5oO1xuICBhbGxBeGlzID0gYWxsQXhpcy5tYXAoZnVuY3Rpb24gKGF4aXMpIHtcbiAgICB2YXIgcG9zaXRpb24gPSBheGlzLnBvc2l0aW9uO1xuICAgIHZhciBsaW5lUG9zaXRpb24gPSBbXTtcblxuICAgIGlmIChwb3NpdGlvbiA9PT0gJ2xlZnQnKSB7XG4gICAgICBsaW5lUG9zaXRpb24gPSBbW3gsIHldLCBbeCwgeSArIGhdXS5yZXZlcnNlKCk7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgbGluZVBvc2l0aW9uID0gW1t4ICsgdywgeV0sIFt4ICsgdywgeSArIGhdXS5yZXZlcnNlKCk7XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcpIHtcbiAgICAgIGxpbmVQb3NpdGlvbiA9IFtbeCwgeV0sIFt4ICsgdywgeV1dO1xuICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdib3R0b20nKSB7XG4gICAgICBsaW5lUG9zaXRpb24gPSBbW3gsIHkgKyBoXSwgW3ggKyB3LCB5ICsgaF1dO1xuICAgIH1cblxuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBheGlzLCB7XG4gICAgICBsaW5lUG9zaXRpb246IGxpbmVQb3NpdGlvblxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGFsbEF4aXM7XG59XG5cbmZ1bmN0aW9uIGNhbGNBeGlzVGlja1Bvc2l0aW9uKGFsbEF4aXMsIGNoYXJ0KSB7XG4gIHJldHVybiBhbGxBeGlzLm1hcChmdW5jdGlvbiAoYXhpc0l0ZW0pIHtcbiAgICB2YXIgYXhpcyA9IGF4aXNJdGVtLmF4aXMsXG4gICAgICAgIGxpbmVQb3NpdGlvbiA9IGF4aXNJdGVtLmxpbmVQb3NpdGlvbixcbiAgICAgICAgcG9zaXRpb24gPSBheGlzSXRlbS5wb3NpdGlvbixcbiAgICAgICAgbGFiZWwgPSBheGlzSXRlbS5sYWJlbCxcbiAgICAgICAgYm91bmRhcnlHYXAgPSBheGlzSXRlbS5ib3VuZGFyeUdhcDtcbiAgICBpZiAodHlwZW9mIGJvdW5kYXJ5R2FwICE9PSAnYm9vbGVhbicpIGJvdW5kYXJ5R2FwID0gYXhpc0NvbmZpZ1theGlzICsgJ0F4aXNDb25maWcnXS5ib3VuZGFyeUdhcDtcbiAgICB2YXIgbGFiZWxOdW0gPSBsYWJlbC5sZW5ndGg7XG5cbiAgICB2YXIgX2xpbmVQb3NpdGlvbiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShsaW5lUG9zaXRpb24sIDIpLFxuICAgICAgICBfbGluZVBvc2l0aW9uJCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfbGluZVBvc2l0aW9uWzBdLCAyKSxcbiAgICAgICAgc3RhcnRYID0gX2xpbmVQb3NpdGlvbiRbMF0sXG4gICAgICAgIHN0YXJ0WSA9IF9saW5lUG9zaXRpb24kWzFdLFxuICAgICAgICBfbGluZVBvc2l0aW9uJDIgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX2xpbmVQb3NpdGlvblsxXSwgMiksXG4gICAgICAgIGVuZFggPSBfbGluZVBvc2l0aW9uJDJbMF0sXG4gICAgICAgIGVuZFkgPSBfbGluZVBvc2l0aW9uJDJbMV07XG5cbiAgICB2YXIgZ2FwTGVuZ3RoID0gYXhpcyA9PT0gJ3gnID8gZW5kWCAtIHN0YXJ0WCA6IGVuZFkgLSBzdGFydFk7XG4gICAgdmFyIGdhcCA9IGdhcExlbmd0aCAvIChib3VuZGFyeUdhcCA/IGxhYmVsTnVtIDogbGFiZWxOdW0gLSAxKTtcbiAgICB2YXIgdGlja1Bvc2l0aW9uID0gbmV3IEFycmF5KGxhYmVsTnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgICBpZiAoYXhpcyA9PT0gJ3gnKSB7XG4gICAgICAgIHJldHVybiBbc3RhcnRYICsgZ2FwICogKGJvdW5kYXJ5R2FwID8gaSArIDAuNSA6IGkpLCBzdGFydFldO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gW3N0YXJ0WCwgc3RhcnRZICsgZ2FwICogKGJvdW5kYXJ5R2FwID8gaSArIDAuNSA6IGkpXTtcbiAgICB9KTtcbiAgICB2YXIgdGlja0xpbmVQb3NpdGlvbiA9IGdldFRpY2tMaW5lUG9zaXRpb24oYXhpcywgYm91bmRhcnlHYXAsIHBvc2l0aW9uLCB0aWNrUG9zaXRpb24sIGdhcCk7XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQoe30sIGF4aXNJdGVtLCB7XG4gICAgICB0aWNrUG9zaXRpb246IHRpY2tQb3NpdGlvbixcbiAgICAgIHRpY2tMaW5lUG9zaXRpb246IHRpY2tMaW5lUG9zaXRpb24sXG4gICAgICB0aWNrR2FwOiBnYXBcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFRpY2tMaW5lUG9zaXRpb24oYXhpc1R5cGUsIGJvdW5kYXJ5R2FwLCBwb3NpdGlvbiwgdGlja1Bvc2l0aW9uLCBnYXApIHtcbiAgdmFyIGluZGV4ID0gYXhpc1R5cGUgPT09ICd4JyA/IDEgOiAwO1xuICB2YXIgcGx1cyA9IDU7XG4gIGlmIChheGlzVHlwZSA9PT0gJ3gnICYmIHBvc2l0aW9uID09PSAndG9wJykgcGx1cyA9IC01O1xuICBpZiAoYXhpc1R5cGUgPT09ICd5JyAmJiBwb3NpdGlvbiA9PT0gJ2xlZnQnKSBwbHVzID0gLTU7XG4gIHZhciB0aWNrTGluZVBvc2l0aW9uID0gdGlja1Bvc2l0aW9uLm1hcChmdW5jdGlvbiAobGluZVN0YXJ0KSB7XG4gICAgdmFyIGxpbmVFbmQgPSAoMCwgX3V0aWwyLmRlZXBDbG9uZSkobGluZVN0YXJ0KTtcbiAgICBsaW5lRW5kW2luZGV4XSArPSBwbHVzO1xuICAgIHJldHVybiBbKDAsIF91dGlsMi5kZWVwQ2xvbmUpKGxpbmVTdGFydCksIGxpbmVFbmRdO1xuICB9KTtcbiAgaWYgKCFib3VuZGFyeUdhcCkgcmV0dXJuIHRpY2tMaW5lUG9zaXRpb247XG4gIGluZGV4ID0gYXhpc1R5cGUgPT09ICd4JyA/IDAgOiAxO1xuICBwbHVzID0gZ2FwIC8gMjtcbiAgdGlja0xpbmVQb3NpdGlvbi5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmMTYpIHtcbiAgICB2YXIgX3JlZjE3ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxNiwgMiksXG4gICAgICAgIGxpbmVTdGFydCA9IF9yZWYxN1swXSxcbiAgICAgICAgbGluZUVuZCA9IF9yZWYxN1sxXTtcblxuICAgIGxpbmVTdGFydFtpbmRleF0gKz0gcGx1cztcbiAgICBsaW5lRW5kW2luZGV4XSArPSBwbHVzO1xuICB9KTtcbiAgcmV0dXJuIHRpY2tMaW5lUG9zaXRpb247XG59XG5cbmZ1bmN0aW9uIGNhbGNBeGlzTmFtZVBvc2l0aW9uKGFsbEF4aXMsIGNoYXJ0KSB7XG4gIHJldHVybiBhbGxBeGlzLm1hcChmdW5jdGlvbiAoYXhpc0l0ZW0pIHtcbiAgICB2YXIgbmFtZUdhcCA9IGF4aXNJdGVtLm5hbWVHYXAsXG4gICAgICAgIG5hbWVMb2NhdGlvbiA9IGF4aXNJdGVtLm5hbWVMb2NhdGlvbixcbiAgICAgICAgcG9zaXRpb24gPSBheGlzSXRlbS5wb3NpdGlvbixcbiAgICAgICAgbGluZVBvc2l0aW9uID0gYXhpc0l0ZW0ubGluZVBvc2l0aW9uO1xuXG4gICAgdmFyIF9saW5lUG9zaXRpb24yID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGxpbmVQb3NpdGlvbiwgMiksXG4gICAgICAgIGxpbmVTdGFydCA9IF9saW5lUG9zaXRpb24yWzBdLFxuICAgICAgICBsaW5lRW5kID0gX2xpbmVQb3NpdGlvbjJbMV07XG5cbiAgICB2YXIgbmFtZVBvc2l0aW9uID0gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShsaW5lU3RhcnQpO1xuICAgIGlmIChuYW1lTG9jYXRpb24gPT09ICdlbmQnKSBuYW1lUG9zaXRpb24gPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGxpbmVFbmQpO1xuXG4gICAgaWYgKG5hbWVMb2NhdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIG5hbWVQb3NpdGlvblswXSA9IChsaW5lU3RhcnRbMF0gKyBsaW5lRW5kWzBdKSAvIDI7XG4gICAgICBuYW1lUG9zaXRpb25bMV0gPSAobGluZVN0YXJ0WzFdICsgbGluZUVuZFsxXSkgLyAyO1xuICAgIH1cblxuICAgIHZhciBpbmRleCA9IDA7XG4gICAgaWYgKHBvc2l0aW9uID09PSAndG9wJyAmJiBuYW1lTG9jYXRpb24gPT09ICdjZW50ZXInKSBpbmRleCA9IDE7XG4gICAgaWYgKHBvc2l0aW9uID09PSAnYm90dG9tJyAmJiBuYW1lTG9jYXRpb24gPT09ICdjZW50ZXInKSBpbmRleCA9IDE7XG4gICAgaWYgKHBvc2l0aW9uID09PSAnbGVmdCcgJiYgbmFtZUxvY2F0aW9uICE9PSAnY2VudGVyJykgaW5kZXggPSAxO1xuICAgIGlmIChwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiBuYW1lTG9jYXRpb24gIT09ICdjZW50ZXInKSBpbmRleCA9IDE7XG4gICAgdmFyIHBsdXMgPSBuYW1lR2FwO1xuICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcgJiYgbmFtZUxvY2F0aW9uICE9PSAnZW5kJykgcGx1cyAqPSAtMTtcbiAgICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JyAmJiBuYW1lTG9jYXRpb24gIT09ICdzdGFydCcpIHBsdXMgKj0gLTE7XG4gICAgaWYgKHBvc2l0aW9uID09PSAnYm90dG9tJyAmJiBuYW1lTG9jYXRpb24gPT09ICdzdGFydCcpIHBsdXMgKj0gLTE7XG4gICAgaWYgKHBvc2l0aW9uID09PSAncmlnaHQnICYmIG5hbWVMb2NhdGlvbiA9PT0gJ2VuZCcpIHBsdXMgKj0gLTE7XG4gICAgbmFtZVBvc2l0aW9uW2luZGV4XSArPSBwbHVzO1xuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBheGlzSXRlbSwge1xuICAgICAgbmFtZVBvc2l0aW9uOiBuYW1lUG9zaXRpb25cbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNTcGxpdExpbmVQb3NpdGlvbihhbGxBeGlzLCBjaGFydCkge1xuICB2YXIgX2NoYXJ0JGdyaWRBcmVhMiA9IGNoYXJ0LmdyaWRBcmVhLFxuICAgICAgdyA9IF9jaGFydCRncmlkQXJlYTIudyxcbiAgICAgIGggPSBfY2hhcnQkZ3JpZEFyZWEyLmg7XG4gIHJldHVybiBhbGxBeGlzLm1hcChmdW5jdGlvbiAoYXhpc0l0ZW0pIHtcbiAgICB2YXIgdGlja0xpbmVQb3NpdGlvbiA9IGF4aXNJdGVtLnRpY2tMaW5lUG9zaXRpb24sXG4gICAgICAgIHBvc2l0aW9uID0gYXhpc0l0ZW0ucG9zaXRpb24sXG4gICAgICAgIGJvdW5kYXJ5R2FwID0gYXhpc0l0ZW0uYm91bmRhcnlHYXA7XG4gICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgcGx1cyA9IHc7XG4gICAgaWYgKHBvc2l0aW9uID09PSAndG9wJyB8fCBwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIGluZGV4ID0gMTtcbiAgICBpZiAocG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJykgcGx1cyA9IGg7XG4gICAgaWYgKHBvc2l0aW9uID09PSAncmlnaHQnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJykgcGx1cyAqPSAtMTtcbiAgICB2YXIgc3BsaXRMaW5lUG9zaXRpb24gPSB0aWNrTGluZVBvc2l0aW9uLm1hcChmdW5jdGlvbiAoX3JlZjE4KSB7XG4gICAgICB2YXIgX3JlZjE5ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxOCwgMSksXG4gICAgICAgICAgc3RhcnRQb2ludCA9IF9yZWYxOVswXTtcblxuICAgICAgdmFyIGVuZFBvaW50ID0gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShzdGFydFBvaW50KTtcbiAgICAgIGVuZFBvaW50W2luZGV4XSArPSBwbHVzO1xuICAgICAgcmV0dXJuIFsoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHN0YXJ0UG9pbnQpLCBlbmRQb2ludF07XG4gICAgfSk7XG4gICAgaWYgKCFib3VuZGFyeUdhcCkgc3BsaXRMaW5lUG9zaXRpb24uc2hpZnQoKTtcbiAgICByZXR1cm4gX29iamVjdFNwcmVhZCh7fSwgYXhpc0l0ZW0sIHtcbiAgICAgIHNwbGl0TGluZVBvc2l0aW9uOiBzcGxpdExpbmVQb3NpdGlvblxuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0TGluZUNvbmZpZyhheGlzSXRlbSkge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBheGlzSXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gYXhpc0l0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBheGlzSXRlbS5yTGV2ZWw7XG4gIHJldHVybiBbe1xuICAgIG5hbWU6ICdwb2x5bGluZScsXG4gICAgaW5kZXg6IHJMZXZlbCxcbiAgICB2aXNpYmxlOiBheGlzSXRlbS5heGlzTGluZS5zaG93LFxuICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgc2hhcGU6IGdldExpbmVTaGFwZShheGlzSXRlbSksXG4gICAgc3R5bGU6IGdldExpbmVTdHlsZShheGlzSXRlbSlcbiAgfV07XG59XG5cbmZ1bmN0aW9uIGdldExpbmVTaGFwZShheGlzSXRlbSkge1xuICB2YXIgbGluZVBvc2l0aW9uID0gYXhpc0l0ZW0ubGluZVBvc2l0aW9uO1xuICByZXR1cm4ge1xuICAgIHBvaW50czogbGluZVBvc2l0aW9uXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldExpbmVTdHlsZShheGlzSXRlbSkge1xuICByZXR1cm4gYXhpc0l0ZW0uYXhpc0xpbmUuc3R5bGU7XG59XG5cbmZ1bmN0aW9uIGdldFRpY2tDb25maWcoYXhpc0l0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gYXhpc0l0ZW0uYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZSA9IGF4aXNJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gYXhpc0l0ZW0uckxldmVsO1xuICB2YXIgc2hhcGVzID0gZ2V0VGlja1NoYXBlcyhheGlzSXRlbSk7XG4gIHZhciBzdHlsZSA9IGdldFRpY2tTdHlsZShheGlzSXRlbSk7XG4gIHJldHVybiBzaGFwZXMubWFwKGZ1bmN0aW9uIChzaGFwZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAncG9seWxpbmUnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IGF4aXNJdGVtLmF4aXNUaWNrLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogc2hhcGUsXG4gICAgICBzdHlsZTogc3R5bGVcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0VGlja1NoYXBlcyhheGlzSXRlbSkge1xuICB2YXIgdGlja0xpbmVQb3NpdGlvbiA9IGF4aXNJdGVtLnRpY2tMaW5lUG9zaXRpb247XG4gIHJldHVybiB0aWNrTGluZVBvc2l0aW9uLm1hcChmdW5jdGlvbiAocG9pbnRzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHBvaW50czogcG9pbnRzXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFRpY2tTdHlsZShheGlzSXRlbSkge1xuICByZXR1cm4gYXhpc0l0ZW0uYXhpc1RpY2suc3R5bGU7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsQ29uZmlnKGF4aXNJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGF4aXNJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBheGlzSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGF4aXNJdGVtLnJMZXZlbDtcbiAgdmFyIHNoYXBlcyA9IGdldExhYmVsU2hhcGVzKGF4aXNJdGVtKTtcbiAgdmFyIHN0eWxlcyA9IGdldExhYmVsU3R5bGUoYXhpc0l0ZW0sIHNoYXBlcyk7XG4gIHJldHVybiBzaGFwZXMubWFwKGZ1bmN0aW9uIChzaGFwZSwgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAndGV4dCcsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogYXhpc0l0ZW0uYXhpc0xhYmVsLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogc2hhcGUsXG4gICAgICBzdHlsZTogc3R5bGVzW2ldLFxuICAgICAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKCkge1xuICAgICAgICByZXR1cm4gdm9pZCAwO1xuICAgICAgfVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRMYWJlbFNoYXBlcyhheGlzSXRlbSkge1xuICB2YXIgbGFiZWwgPSBheGlzSXRlbS5sYWJlbCxcbiAgICAgIHRpY2tQb3NpdGlvbiA9IGF4aXNJdGVtLnRpY2tQb3NpdGlvbixcbiAgICAgIHBvc2l0aW9uID0gYXhpc0l0ZW0ucG9zaXRpb247XG4gIHJldHVybiB0aWNrUG9zaXRpb24ubWFwKGZ1bmN0aW9uIChwb2ludCwgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBwb3NpdGlvbjogZ2V0TGFiZWxSZWFsUG9zaXRpb24ocG9pbnQsIHBvc2l0aW9uKSxcbiAgICAgIGNvbnRlbnQ6IGxhYmVsW2ldLnRvU3RyaW5nKClcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0TGFiZWxSZWFsUG9zaXRpb24ocG9pbnRzLCBwb3NpdGlvbikge1xuICB2YXIgaW5kZXggPSAwLFxuICAgICAgcGx1cyA9IDEwO1xuICBpZiAocG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnYm90dG9tJykgaW5kZXggPSAxO1xuICBpZiAocG9zaXRpb24gPT09ICd0b3AnIHx8IHBvc2l0aW9uID09PSAnbGVmdCcpIHBsdXMgPSAtMTA7XG4gIHBvaW50cyA9ICgwLCBfdXRpbDIuZGVlcENsb25lKShwb2ludHMpO1xuICBwb2ludHNbaW5kZXhdICs9IHBsdXM7XG4gIHJldHVybiBwb2ludHM7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsU3R5bGUoYXhpc0l0ZW0sIHNoYXBlcykge1xuICB2YXIgcG9zaXRpb24gPSBheGlzSXRlbS5wb3NpdGlvbjtcbiAgdmFyIHN0eWxlID0gYXhpc0l0ZW0uYXhpc0xhYmVsLnN0eWxlO1xuICB2YXIgYWxpZ24gPSBnZXRBeGlzTGFiZWxSZWFsQWxpZ24ocG9zaXRpb24pO1xuICBzdHlsZSA9ICgwLCBfdXRpbC5kZWVwTWVyZ2UpKGFsaWduLCBzdHlsZSk7XG4gIHZhciBzdHlsZXMgPSBzaGFwZXMubWFwKGZ1bmN0aW9uIChfcmVmMjApIHtcbiAgICB2YXIgcG9zaXRpb24gPSBfcmVmMjAucG9zaXRpb247XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQoe30sIHN0eWxlLCB7XG4gICAgICBncmFwaENlbnRlcjogcG9zaXRpb25cbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBzdHlsZXM7XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMYWJlbFJlYWxBbGlnbihwb3NpdGlvbikge1xuICBpZiAocG9zaXRpb24gPT09ICdsZWZ0JykgcmV0dXJuIHtcbiAgICB0ZXh0QWxpZ246ICdyaWdodCcsXG4gICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICB9O1xuICBpZiAocG9zaXRpb24gPT09ICdyaWdodCcpIHJldHVybiB7XG4gICAgdGV4dEFsaWduOiAnbGVmdCcsXG4gICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICB9O1xuICBpZiAocG9zaXRpb24gPT09ICd0b3AnKSByZXR1cm4ge1xuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gICAgdGV4dEJhc2VsaW5lOiAnYm90dG9tJ1xuICB9O1xuICBpZiAocG9zaXRpb24gPT09ICdib3R0b20nKSByZXR1cm4ge1xuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gICAgdGV4dEJhc2VsaW5lOiAndG9wJ1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXROYW1lQ29uZmlnKGF4aXNJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGF4aXNJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBheGlzSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGF4aXNJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIFt7XG4gICAgbmFtZTogJ3RleHQnLFxuICAgIGluZGV4OiByTGV2ZWwsXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICBzaGFwZTogZ2V0TmFtZVNoYXBlKGF4aXNJdGVtKSxcbiAgICBzdHlsZTogZ2V0TmFtZVN0eWxlKGF4aXNJdGVtKVxuICB9XTtcbn1cblxuZnVuY3Rpb24gZ2V0TmFtZVNoYXBlKGF4aXNJdGVtKSB7XG4gIHZhciBuYW1lID0gYXhpc0l0ZW0ubmFtZSxcbiAgICAgIG5hbWVQb3NpdGlvbiA9IGF4aXNJdGVtLm5hbWVQb3NpdGlvbjtcbiAgcmV0dXJuIHtcbiAgICBjb250ZW50OiBuYW1lLFxuICAgIHBvc2l0aW9uOiBuYW1lUG9zaXRpb25cbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0TmFtZVN0eWxlKGF4aXNJdGVtKSB7XG4gIHZhciBuYW1lTG9jYXRpb24gPSBheGlzSXRlbS5uYW1lTG9jYXRpb24sXG4gICAgICBwb3NpdGlvbiA9IGF4aXNJdGVtLnBvc2l0aW9uLFxuICAgICAgc3R5bGUgPSBheGlzSXRlbS5uYW1lVGV4dFN0eWxlO1xuICB2YXIgYWxpZ24gPSBnZXROYW1lUmVhbEFsaWduKHBvc2l0aW9uLCBuYW1lTG9jYXRpb24pO1xuICByZXR1cm4gKDAsIF91dGlsLmRlZXBNZXJnZSkoYWxpZ24sIHN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0TmFtZVJlYWxBbGlnbihwb3NpdGlvbiwgbG9jYXRpb24pIHtcbiAgaWYgKHBvc2l0aW9uID09PSAndG9wJyAmJiBsb2NhdGlvbiA9PT0gJ3N0YXJ0JyB8fCBwb3NpdGlvbiA9PT0gJ2JvdHRvbScgJiYgbG9jYXRpb24gPT09ICdzdGFydCcgfHwgcG9zaXRpb24gPT09ICdsZWZ0JyAmJiBsb2NhdGlvbiA9PT0gJ2NlbnRlcicpIHJldHVybiB7XG4gICAgdGV4dEFsaWduOiAncmlnaHQnLFxuICAgIHRleHRCYXNlbGluZTogJ21pZGRsZSdcbiAgfTtcbiAgaWYgKHBvc2l0aW9uID09PSAndG9wJyAmJiBsb2NhdGlvbiA9PT0gJ2VuZCcgfHwgcG9zaXRpb24gPT09ICdib3R0b20nICYmIGxvY2F0aW9uID09PSAnZW5kJyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiBsb2NhdGlvbiA9PT0gJ2NlbnRlcicpIHJldHVybiB7XG4gICAgdGV4dEFsaWduOiAnbGVmdCcsXG4gICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICB9O1xuICBpZiAocG9zaXRpb24gPT09ICd0b3AnICYmIGxvY2F0aW9uID09PSAnY2VudGVyJyB8fCBwb3NpdGlvbiA9PT0gJ2xlZnQnICYmIGxvY2F0aW9uID09PSAnZW5kJyB8fCBwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiBsb2NhdGlvbiA9PT0gJ2VuZCcpIHJldHVybiB7XG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICB0ZXh0QmFzZWxpbmU6ICdib3R0b20nXG4gIH07XG4gIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScgJiYgbG9jYXRpb24gPT09ICdjZW50ZXInIHx8IHBvc2l0aW9uID09PSAnbGVmdCcgJiYgbG9jYXRpb24gPT09ICdzdGFydCcgfHwgcG9zaXRpb24gPT09ICdyaWdodCcgJiYgbG9jYXRpb24gPT09ICdzdGFydCcpIHJldHVybiB7XG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICB0ZXh0QmFzZWxpbmU6ICd0b3AnXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNwbGl0TGluZUNvbmZpZyhheGlzSXRlbSkge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBheGlzSXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gYXhpc0l0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBheGlzSXRlbS5yTGV2ZWw7XG4gIHZhciBzaGFwZXMgPSBnZXRTcGxpdExpbmVTaGFwZXMoYXhpc0l0ZW0pO1xuICB2YXIgc3R5bGUgPSBnZXRTcGxpdExpbmVTdHlsZShheGlzSXRlbSk7XG4gIHJldHVybiBzaGFwZXMubWFwKGZ1bmN0aW9uIChzaGFwZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAncG9seWxpbmUnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IGF4aXNJdGVtLnNwbGl0TGluZS5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IHNoYXBlLFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFNwbGl0TGluZVNoYXBlcyhheGlzSXRlbSkge1xuICB2YXIgc3BsaXRMaW5lUG9zaXRpb24gPSBheGlzSXRlbS5zcGxpdExpbmVQb3NpdGlvbjtcbiAgcmV0dXJuIHNwbGl0TGluZVBvc2l0aW9uLm1hcChmdW5jdGlvbiAocG9pbnRzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHBvaW50czogcG9pbnRzXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFNwbGl0TGluZVN0eWxlKGF4aXNJdGVtKSB7XG4gIHJldHVybiBheGlzSXRlbS5zcGxpdExpbmUuc3R5bGU7XG59IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5iYXIgPSBiYXI7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF9kZWZpbmVQcm9wZXJ0eTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2RlZmluZVByb3BlcnR5XCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX2NvbmZpZyA9IHJlcXVpcmUoXCIuLi9jb25maWdcIik7XG5cbnZhciBfdXRpbCA9IHJlcXVpcmUoXCJAamlhbWluZ2hpL2MtcmVuZGVyL2xpYi9wbHVnaW4vdXRpbFwiKTtcblxudmFyIF91dGlsMiA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuXG5mdW5jdGlvbiBvd25LZXlzKG9iamVjdCwgZW51bWVyYWJsZU9ubHkpIHsgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpOyBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykgeyB2YXIgc3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqZWN0KTsgaWYgKGVudW1lcmFibGVPbmx5KSBzeW1ib2xzID0gc3ltYm9scy5maWx0ZXIoZnVuY3Rpb24gKHN5bSkgeyByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHN5bSkuZW51bWVyYWJsZTsgfSk7IGtleXMucHVzaC5hcHBseShrZXlzLCBzeW1ib2xzKTsgfSByZXR1cm4ga2V5czsgfVxuXG5mdW5jdGlvbiBfb2JqZWN0U3ByZWFkKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldICE9IG51bGwgPyBhcmd1bWVudHNbaV0gOiB7fTsgaWYgKGkgJSAyKSB7IG93bktleXMoc291cmNlLCB0cnVlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgKDAsIF9kZWZpbmVQcm9wZXJ0eTJbXCJkZWZhdWx0XCJdKSh0YXJnZXQsIGtleSwgc291cmNlW2tleV0pOyB9KTsgfSBlbHNlIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycykgeyBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKHNvdXJjZSkpOyB9IGVsc2UgeyBvd25LZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIGtleSkpOyB9KTsgfSB9IHJldHVybiB0YXJnZXQ7IH1cblxuZnVuY3Rpb24gYmFyKGNoYXJ0KSB7XG4gIHZhciBvcHRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuICB2YXIgeEF4aXMgPSBvcHRpb24ueEF4aXMsXG4gICAgICB5QXhpcyA9IG9wdGlvbi55QXhpcyxcbiAgICAgIHNlcmllcyA9IG9wdGlvbi5zZXJpZXM7XG4gIHZhciBiYXJzID0gW107XG5cbiAgaWYgKHhBeGlzICYmIHlBeGlzICYmIHNlcmllcykge1xuICAgIGJhcnMgPSAoMCwgX3V0aWwyLmluaXROZWVkU2VyaWVzKShzZXJpZXMsIF9jb25maWcuYmFyQ29uZmlnLCAnYmFyJyk7XG4gICAgYmFycyA9IHNldEJhckF4aXMoYmFycywgY2hhcnQpO1xuICAgIGJhcnMgPSBzZXRCYXJQb3NpdGlvbkRhdGEoYmFycywgY2hhcnQpO1xuICAgIGJhcnMgPSBjYWxjQmFyc1Bvc2l0aW9uKGJhcnMsIGNoYXJ0KTtcbiAgfVxuXG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGJhcnMuc2xpY2UoLTEpLFxuICAgIGtleTogJ2JhY2tncm91bmRCYXInLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRCYWNrZ3JvdW5kQmFyQ29uZmlnXG4gIH0pO1xuICBiYXJzLnJldmVyc2UoKTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogYmFycyxcbiAgICBrZXk6ICdiYXInLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRCYXJDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRCYXJDb25maWcsXG4gICAgYmVmb3JlVXBkYXRlOiBiZWZvcmVVcGRhdGVCYXJcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGJhcnMsXG4gICAga2V5OiAnYmFyTGFiZWwnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRMYWJlbENvbmZpZ1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0QmFyQXhpcyhiYXJzLCBjaGFydCkge1xuICB2YXIgYXhpc0RhdGEgPSBjaGFydC5heGlzRGF0YTtcbiAgYmFycy5mb3JFYWNoKGZ1bmN0aW9uIChiYXIpIHtcbiAgICB2YXIgeEF4aXNJbmRleCA9IGJhci54QXhpc0luZGV4LFxuICAgICAgICB5QXhpc0luZGV4ID0gYmFyLnlBeGlzSW5kZXg7XG4gICAgaWYgKHR5cGVvZiB4QXhpc0luZGV4ICE9PSAnbnVtYmVyJykgeEF4aXNJbmRleCA9IDA7XG4gICAgaWYgKHR5cGVvZiB5QXhpc0luZGV4ICE9PSAnbnVtYmVyJykgeUF4aXNJbmRleCA9IDA7XG4gICAgdmFyIHhBeGlzID0gYXhpc0RhdGEuZmluZChmdW5jdGlvbiAoX3JlZikge1xuICAgICAgdmFyIGF4aXMgPSBfcmVmLmF4aXMsXG4gICAgICAgICAgaW5kZXggPSBfcmVmLmluZGV4O1xuICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KGF4aXMpLmNvbmNhdChpbmRleCkgPT09IFwieFwiLmNvbmNhdCh4QXhpc0luZGV4KTtcbiAgICB9KTtcbiAgICB2YXIgeUF4aXMgPSBheGlzRGF0YS5maW5kKGZ1bmN0aW9uIChfcmVmMikge1xuICAgICAgdmFyIGF4aXMgPSBfcmVmMi5heGlzLFxuICAgICAgICAgIGluZGV4ID0gX3JlZjIuaW5kZXg7XG4gICAgICByZXR1cm4gXCJcIi5jb25jYXQoYXhpcykuY29uY2F0KGluZGV4KSA9PT0gXCJ5XCIuY29uY2F0KHlBeGlzSW5kZXgpO1xuICAgIH0pO1xuICAgIHZhciBheGlzID0gW3hBeGlzLCB5QXhpc107XG4gICAgdmFyIHZhbHVlQXhpc0luZGV4ID0gYXhpcy5maW5kSW5kZXgoZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgICB2YXIgZGF0YSA9IF9yZWYzLmRhdGE7XG4gICAgICByZXR1cm4gZGF0YSA9PT0gJ3ZhbHVlJztcbiAgICB9KTtcbiAgICBiYXIudmFsdWVBeGlzID0gYXhpc1t2YWx1ZUF4aXNJbmRleF07XG4gICAgYmFyLmxhYmVsQXhpcyA9IGF4aXNbMSAtIHZhbHVlQXhpc0luZGV4XTtcbiAgfSk7XG4gIHJldHVybiBiYXJzO1xufVxuXG5mdW5jdGlvbiBzZXRCYXJQb3NpdGlvbkRhdGEoYmFycywgY2hhcnQpIHtcbiAgdmFyIGxhYmVsQmFyR3JvdXAgPSBncm91cEJhckJ5TGFiZWxBeGlzKGJhcnMpO1xuICBsYWJlbEJhckdyb3VwLmZvckVhY2goZnVuY3Rpb24gKGdyb3VwKSB7XG4gICAgc2V0QmFySW5kZXgoZ3JvdXApO1xuICAgIHNldEJhck51bShncm91cCk7XG4gICAgc2V0QmFyQ2F0ZWdvcnlXaWR0aChncm91cCwgY2hhcnQpO1xuICAgIHNldEJhcldpZHRoQW5kR2FwKGdyb3VwKTtcbiAgICBzZXRCYXJBbGxXaWR0aEFuZEdhcChncm91cCk7XG4gIH0pO1xuICByZXR1cm4gYmFycztcbn1cblxuZnVuY3Rpb24gc2V0QmFySW5kZXgoYmFycykge1xuICB2YXIgc3RhY2tzID0gZ2V0QmFyU3RhY2soYmFycyk7XG4gIHN0YWNrcyA9IHN0YWNrcy5tYXAoZnVuY3Rpb24gKHN0YWNrKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YWNrOiBzdGFjayxcbiAgICAgIGluZGV4OiAtMVxuICAgIH07XG4gIH0pO1xuICB2YXIgY3VycmVudEluZGV4ID0gMDtcbiAgYmFycy5mb3JFYWNoKGZ1bmN0aW9uIChiYXIpIHtcbiAgICB2YXIgc3RhY2sgPSBiYXIuc3RhY2s7XG5cbiAgICBpZiAoIXN0YWNrKSB7XG4gICAgICBiYXIuYmFySW5kZXggPSBjdXJyZW50SW5kZXg7XG4gICAgICBjdXJyZW50SW5kZXgrKztcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHN0YWNrRGF0YSA9IHN0YWNrcy5maW5kKGZ1bmN0aW9uIChfcmVmNCkge1xuICAgICAgICB2YXIgcyA9IF9yZWY0LnN0YWNrO1xuICAgICAgICByZXR1cm4gcyA9PT0gc3RhY2s7XG4gICAgICB9KTtcblxuICAgICAgaWYgKHN0YWNrRGF0YS5pbmRleCA9PT0gLTEpIHtcbiAgICAgICAgc3RhY2tEYXRhLmluZGV4ID0gY3VycmVudEluZGV4O1xuICAgICAgICBjdXJyZW50SW5kZXgrKztcbiAgICAgIH1cblxuICAgICAgYmFyLmJhckluZGV4ID0gc3RhY2tEYXRhLmluZGV4O1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdyb3VwQmFyQnlMYWJlbEF4aXMoYmFycykge1xuICB2YXIgbGFiZWxBeGlzID0gYmFycy5tYXAoZnVuY3Rpb24gKF9yZWY1KSB7XG4gICAgdmFyIF9yZWY1JGxhYmVsQXhpcyA9IF9yZWY1LmxhYmVsQXhpcyxcbiAgICAgICAgYXhpcyA9IF9yZWY1JGxhYmVsQXhpcy5heGlzLFxuICAgICAgICBpbmRleCA9IF9yZWY1JGxhYmVsQXhpcy5pbmRleDtcbiAgICByZXR1cm4gYXhpcyArIGluZGV4O1xuICB9KTtcbiAgbGFiZWxBeGlzID0gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShuZXcgU2V0KGxhYmVsQXhpcykpO1xuICByZXR1cm4gbGFiZWxBeGlzLm1hcChmdW5jdGlvbiAoYXhpc0luZGV4KSB7XG4gICAgcmV0dXJuIGJhcnMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmNikge1xuICAgICAgdmFyIF9yZWY2JGxhYmVsQXhpcyA9IF9yZWY2LmxhYmVsQXhpcyxcbiAgICAgICAgICBheGlzID0gX3JlZjYkbGFiZWxBeGlzLmF4aXMsXG4gICAgICAgICAgaW5kZXggPSBfcmVmNiRsYWJlbEF4aXMuaW5kZXg7XG4gICAgICByZXR1cm4gYXhpcyArIGluZGV4ID09PSBheGlzSW5kZXg7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRCYXJTdGFjayhiYXJzKSB7XG4gIHZhciBzdGFja3MgPSBbXTtcbiAgYmFycy5mb3JFYWNoKGZ1bmN0aW9uIChfcmVmNykge1xuICAgIHZhciBzdGFjayA9IF9yZWY3LnN0YWNrO1xuICAgIGlmIChzdGFjaykgc3RhY2tzLnB1c2goc3RhY2spO1xuICB9KTtcbiAgcmV0dXJuICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobmV3IFNldChzdGFja3MpKTtcbn1cblxuZnVuY3Rpb24gc2V0QmFyTnVtKGJhcnMpIHtcbiAgdmFyIGJhck51bSA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobmV3IFNldChiYXJzLm1hcChmdW5jdGlvbiAoX3JlZjgpIHtcbiAgICB2YXIgYmFySW5kZXggPSBfcmVmOC5iYXJJbmRleDtcbiAgICByZXR1cm4gYmFySW5kZXg7XG4gIH0pKSkubGVuZ3RoO1xuICBiYXJzLmZvckVhY2goZnVuY3Rpb24gKGJhcikge1xuICAgIHJldHVybiBiYXIuYmFyTnVtID0gYmFyTnVtO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0QmFyQ2F0ZWdvcnlXaWR0aChiYXJzKSB7XG4gIHZhciBsYXN0QmFyID0gYmFycy5zbGljZSgtMSlbMF07XG4gIHZhciBiYXJDYXRlZ29yeUdhcCA9IGxhc3RCYXIuYmFyQ2F0ZWdvcnlHYXAsXG4gICAgICB0aWNrR2FwID0gbGFzdEJhci5sYWJlbEF4aXMudGlja0dhcDtcbiAgdmFyIGJhckNhdGVnb3J5V2lkdGggPSAwO1xuXG4gIGlmICh0eXBlb2YgYmFyQ2F0ZWdvcnlHYXAgPT09ICdudW1iZXInKSB7XG4gICAgYmFyQ2F0ZWdvcnlXaWR0aCA9IGJhckNhdGVnb3J5R2FwO1xuICB9IGVsc2Uge1xuICAgIGJhckNhdGVnb3J5V2lkdGggPSAoMSAtIHBhcnNlSW50KGJhckNhdGVnb3J5R2FwKSAvIDEwMCkgKiB0aWNrR2FwO1xuICB9XG5cbiAgYmFycy5mb3JFYWNoKGZ1bmN0aW9uIChiYXIpIHtcbiAgICByZXR1cm4gYmFyLmJhckNhdGVnb3J5V2lkdGggPSBiYXJDYXRlZ29yeVdpZHRoO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0QmFyV2lkdGhBbmRHYXAoYmFycykge1xuICB2YXIgX2JhcnMkc2xpY2UkID0gYmFycy5zbGljZSgtMSlbMF0sXG4gICAgICBiYXJDYXRlZ29yeVdpZHRoID0gX2JhcnMkc2xpY2UkLmJhckNhdGVnb3J5V2lkdGgsXG4gICAgICBiYXJXaWR0aCA9IF9iYXJzJHNsaWNlJC5iYXJXaWR0aCxcbiAgICAgIGJhckdhcCA9IF9iYXJzJHNsaWNlJC5iYXJHYXAsXG4gICAgICBiYXJOdW0gPSBfYmFycyRzbGljZSQuYmFyTnVtO1xuICB2YXIgd2lkdGhBbmRHYXAgPSBbXTtcblxuICBpZiAodHlwZW9mIGJhcldpZHRoID09PSAnbnVtYmVyJyB8fCBiYXJXaWR0aCAhPT0gJ2F1dG8nKSB7XG4gICAgd2lkdGhBbmRHYXAgPSBnZXRCYXJXaWR0aEFuZEdhcFdpdGhQZXJjZW50T3JOdW1iZXIoYmFyQ2F0ZWdvcnlXaWR0aCwgYmFyV2lkdGgsIGJhckdhcCwgYmFyTnVtKTtcbiAgfSBlbHNlIGlmIChiYXJXaWR0aCA9PT0gJ2F1dG8nKSB7XG4gICAgd2lkdGhBbmRHYXAgPSBnZXRCYXJXaWR0aEFuZEdhcFdpZHRoQXV0byhiYXJDYXRlZ29yeVdpZHRoLCBiYXJXaWR0aCwgYmFyR2FwLCBiYXJOdW0pO1xuICB9XG5cbiAgdmFyIF93aWR0aEFuZEdhcCA9IHdpZHRoQW5kR2FwLFxuICAgICAgX3dpZHRoQW5kR2FwMiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfd2lkdGhBbmRHYXAsIDIpLFxuICAgICAgd2lkdGggPSBfd2lkdGhBbmRHYXAyWzBdLFxuICAgICAgZ2FwID0gX3dpZHRoQW5kR2FwMlsxXTtcblxuICBiYXJzLmZvckVhY2goZnVuY3Rpb24gKGJhcikge1xuICAgIGJhci5iYXJXaWR0aCA9IHdpZHRoO1xuICAgIGJhci5iYXJHYXAgPSBnYXA7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRCYXJXaWR0aEFuZEdhcFdpdGhQZXJjZW50T3JOdW1iZXIoYmFyQ2F0ZWdvcnlXaWR0aCwgYmFyV2lkdGgsIGJhckdhcCkge1xuICB2YXIgd2lkdGggPSAwLFxuICAgICAgZ2FwID0gMDtcblxuICBpZiAodHlwZW9mIGJhcldpZHRoID09PSAnbnVtYmVyJykge1xuICAgIHdpZHRoID0gYmFyV2lkdGg7XG4gIH0gZWxzZSB7XG4gICAgd2lkdGggPSBwYXJzZUludChiYXJXaWR0aCkgLyAxMDAgKiBiYXJDYXRlZ29yeVdpZHRoO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBiYXJHYXAgPT09ICdudW1iZXInKSB7XG4gICAgZ2FwID0gYmFyR2FwO1xuICB9IGVsc2Uge1xuICAgIGdhcCA9IHBhcnNlSW50KGJhckdhcCkgLyAxMDAgKiB3aWR0aDtcbiAgfVxuXG4gIHJldHVybiBbd2lkdGgsIGdhcF07XG59XG5cbmZ1bmN0aW9uIGdldEJhcldpZHRoQW5kR2FwV2lkdGhBdXRvKGJhckNhdGVnb3J5V2lkdGgsIGJhcldpZHRoLCBiYXJHYXAsIGJhck51bSkge1xuICB2YXIgd2lkdGggPSAwLFxuICAgICAgZ2FwID0gMDtcbiAgdmFyIGJhckl0ZW1XaWR0aCA9IGJhckNhdGVnb3J5V2lkdGggLyBiYXJOdW07XG5cbiAgaWYgKHR5cGVvZiBiYXJHYXAgPT09ICdudW1iZXInKSB7XG4gICAgZ2FwID0gYmFyR2FwO1xuICAgIHdpZHRoID0gYmFySXRlbVdpZHRoIC0gZ2FwO1xuICB9IGVsc2Uge1xuICAgIHZhciBwZXJjZW50ID0gMTAgKyBwYXJzZUludChiYXJHYXApIC8gMTA7XG5cbiAgICBpZiAocGVyY2VudCA9PT0gMCkge1xuICAgICAgd2lkdGggPSBiYXJJdGVtV2lkdGggKiAyO1xuICAgICAgZ2FwID0gLXdpZHRoO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aWR0aCA9IGJhckl0ZW1XaWR0aCAvIHBlcmNlbnQgKiAxMDtcbiAgICAgIGdhcCA9IGJhckl0ZW1XaWR0aCAtIHdpZHRoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBbd2lkdGgsIGdhcF07XG59XG5cbmZ1bmN0aW9uIHNldEJhckFsbFdpZHRoQW5kR2FwKGJhcnMpIHtcbiAgdmFyIF9iYXJzJHNsaWNlJDIgPSBiYXJzLnNsaWNlKC0xKVswXSxcbiAgICAgIGJhckdhcCA9IF9iYXJzJHNsaWNlJDIuYmFyR2FwLFxuICAgICAgYmFyV2lkdGggPSBfYmFycyRzbGljZSQyLmJhcldpZHRoLFxuICAgICAgYmFyTnVtID0gX2JhcnMkc2xpY2UkMi5iYXJOdW07XG4gIHZhciBiYXJBbGxXaWR0aEFuZEdhcCA9IChiYXJHYXAgKyBiYXJXaWR0aCkgKiBiYXJOdW0gLSBiYXJHYXA7XG4gIGJhcnMuZm9yRWFjaChmdW5jdGlvbiAoYmFyKSB7XG4gICAgcmV0dXJuIGJhci5iYXJBbGxXaWR0aEFuZEdhcCA9IGJhckFsbFdpZHRoQW5kR2FwO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY2FsY0JhcnNQb3NpdGlvbihiYXJzLCBjaGFydCkge1xuICBiYXJzID0gY2FsY0JhclZhbHVlQXhpc0Nvb3JkaW5hdGUoYmFycyk7XG4gIGJhcnMgPSBjYWxjQmFyTGFiZWxBeGlzQ29vcmRpbmF0ZShiYXJzKTtcbiAgYmFycyA9IGVsaW1pbmF0ZU51bGxCYXJMYWJlbEF4aXMoYmFycyk7XG4gIGJhcnMgPSBrZWVwU2FtZU51bUJldHdlZW5CYXJBbmREYXRhKGJhcnMpO1xuICByZXR1cm4gYmFycztcbn1cblxuZnVuY3Rpb24gY2FsY0JhckxhYmVsQXhpc0Nvb3JkaW5hdGUoYmFycykge1xuICByZXR1cm4gYmFycy5tYXAoZnVuY3Rpb24gKGJhcikge1xuICAgIHZhciBsYWJlbEF4aXMgPSBiYXIubGFiZWxBeGlzLFxuICAgICAgICBiYXJBbGxXaWR0aEFuZEdhcCA9IGJhci5iYXJBbGxXaWR0aEFuZEdhcCxcbiAgICAgICAgYmFyR2FwID0gYmFyLmJhckdhcCxcbiAgICAgICAgYmFyV2lkdGggPSBiYXIuYmFyV2lkdGgsXG4gICAgICAgIGJhckluZGV4ID0gYmFyLmJhckluZGV4O1xuICAgIHZhciB0aWNrR2FwID0gbGFiZWxBeGlzLnRpY2tHYXAsXG4gICAgICAgIHRpY2tQb3NpdGlvbiA9IGxhYmVsQXhpcy50aWNrUG9zaXRpb24sXG4gICAgICAgIGF4aXMgPSBsYWJlbEF4aXMuYXhpcztcbiAgICB2YXIgY29vcmRpbmF0ZUluZGV4ID0gYXhpcyA9PT0gJ3gnID8gMCA6IDE7XG4gICAgdmFyIGJhckxhYmVsQXhpc1BvcyA9IHRpY2tQb3NpdGlvbi5tYXAoZnVuY3Rpb24gKHRpY2ssIGkpIHtcbiAgICAgIHZhciBiYXJDYXRlZ29yeVN0YXJ0UG9zID0gdGlja1Bvc2l0aW9uW2ldW2Nvb3JkaW5hdGVJbmRleF0gLSB0aWNrR2FwIC8gMjtcbiAgICAgIHZhciBiYXJJdGVtc1N0YXJ0UG9zID0gYmFyQ2F0ZWdvcnlTdGFydFBvcyArICh0aWNrR2FwIC0gYmFyQWxsV2lkdGhBbmRHYXApIC8gMjtcbiAgICAgIHJldHVybiBiYXJJdGVtc1N0YXJ0UG9zICsgKGJhckluZGV4ICsgMC41KSAqIGJhcldpZHRoICsgYmFySW5kZXggKiBiYXJHYXA7XG4gICAgfSk7XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQoe30sIGJhciwge1xuICAgICAgYmFyTGFiZWxBeGlzUG9zOiBiYXJMYWJlbEF4aXNQb3NcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNCYXJWYWx1ZUF4aXNDb29yZGluYXRlKGJhcnMpIHtcbiAgcmV0dXJuIGJhcnMubWFwKGZ1bmN0aW9uIChiYXIpIHtcbiAgICB2YXIgZGF0YSA9ICgwLCBfdXRpbDIubWVyZ2VTYW1lU3RhY2tEYXRhKShiYXIsIGJhcnMpO1xuICAgIGRhdGEgPSBlbGltaW5hdGVOb25OdW1iZXJEYXRhKGJhciwgZGF0YSk7XG4gICAgdmFyIF9iYXIkdmFsdWVBeGlzID0gYmFyLnZhbHVlQXhpcyxcbiAgICAgICAgYXhpcyA9IF9iYXIkdmFsdWVBeGlzLmF4aXMsXG4gICAgICAgIG1pblZhbHVlID0gX2JhciR2YWx1ZUF4aXMubWluVmFsdWUsXG4gICAgICAgIG1heFZhbHVlID0gX2JhciR2YWx1ZUF4aXMubWF4VmFsdWUsXG4gICAgICAgIGxpbmVQb3NpdGlvbiA9IF9iYXIkdmFsdWVBeGlzLmxpbmVQb3NpdGlvbjtcbiAgICB2YXIgc3RhcnRQb3MgPSBnZXRWYWx1ZVBvcyhtaW5WYWx1ZSwgbWF4VmFsdWUsIG1pblZhbHVlIDwgMCA/IDAgOiBtaW5WYWx1ZSwgbGluZVBvc2l0aW9uLCBheGlzKTtcbiAgICB2YXIgZW5kUG9zID0gZGF0YS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICAgIHJldHVybiBnZXRWYWx1ZVBvcyhtaW5WYWx1ZSwgbWF4VmFsdWUsIHYsIGxpbmVQb3NpdGlvbiwgYXhpcyk7XG4gICAgfSk7XG4gICAgdmFyIGJhclZhbHVlQXhpc1BvcyA9IGVuZFBvcy5tYXAoZnVuY3Rpb24gKHApIHtcbiAgICAgIHJldHVybiBbc3RhcnRQb3MsIHBdO1xuICAgIH0pO1xuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBiYXIsIHtcbiAgICAgIGJhclZhbHVlQXhpc1BvczogYmFyVmFsdWVBeGlzUG9zXG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlbGltaW5hdGVOb25OdW1iZXJEYXRhKGJhckl0ZW0sIGJhckRhdGEpIHtcbiAgdmFyIGRhdGEgPSBiYXJJdGVtLmRhdGE7XG4gIHJldHVybiBiYXJEYXRhLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgIHJldHVybiB0eXBlb2YgZGF0YVtpXSA9PT0gJ251bWJlcicgPyB2IDogbnVsbDtcbiAgfSkuZmlsdGVyKGZ1bmN0aW9uIChkKSB7XG4gICAgcmV0dXJuIGQgIT09IG51bGw7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlbGltaW5hdGVOdWxsQmFyTGFiZWxBeGlzKGJhcnMpIHtcbiAgcmV0dXJuIGJhcnMubWFwKGZ1bmN0aW9uIChiYXIpIHtcbiAgICB2YXIgYmFyTGFiZWxBeGlzUG9zID0gYmFyLmJhckxhYmVsQXhpc1BvcyxcbiAgICAgICAgZGF0YSA9IGJhci5kYXRhO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoZCwgaSkge1xuICAgICAgaWYgKHR5cGVvZiBkID09PSAnbnVtYmVyJykgcmV0dXJuO1xuICAgICAgYmFyTGFiZWxBeGlzUG9zW2ldID0gbnVsbDtcbiAgICB9KTtcbiAgICByZXR1cm4gX29iamVjdFNwcmVhZCh7fSwgYmFyLCB7XG4gICAgICBiYXJMYWJlbEF4aXNQb3M6IGJhckxhYmVsQXhpc1Bvcy5maWx0ZXIoZnVuY3Rpb24gKHApIHtcbiAgICAgICAgcmV0dXJuIHAgIT09IG51bGw7XG4gICAgICB9KVxuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24ga2VlcFNhbWVOdW1CZXR3ZWVuQmFyQW5kRGF0YShiYXJzKSB7XG4gIGJhcnMuZm9yRWFjaChmdW5jdGlvbiAoYmFyKSB7XG4gICAgdmFyIGRhdGEgPSBiYXIuZGF0YSxcbiAgICAgICAgYmFyTGFiZWxBeGlzUG9zID0gYmFyLmJhckxhYmVsQXhpc1BvcyxcbiAgICAgICAgYmFyVmFsdWVBeGlzUG9zID0gYmFyLmJhclZhbHVlQXhpc1BvcztcbiAgICB2YXIgZGF0YU51bSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uIChkKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIGQgPT09ICdudW1iZXInO1xuICAgIH0pLmxlbmd0aDtcbiAgICB2YXIgYXhpc1Bvc051bSA9IGJhckxhYmVsQXhpc1Bvcy5sZW5ndGg7XG5cbiAgICBpZiAoYXhpc1Bvc051bSA+IGRhdGFOdW0pIHtcbiAgICAgIGJhckxhYmVsQXhpc1Bvcy5zcGxpY2UoZGF0YU51bSk7XG4gICAgICBiYXJWYWx1ZUF4aXNQb3Muc3BsaWNlKGRhdGFOdW0pO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBiYXJzO1xufVxuXG5mdW5jdGlvbiBnZXRWYWx1ZVBvcyhtaW4sIG1heCwgdmFsdWUsIGxpbmVQb3NpdGlvbiwgYXhpcykge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJykgcmV0dXJuIG51bGw7XG4gIHZhciB2YWx1ZU1pbnVzID0gbWF4IC0gbWluO1xuICB2YXIgY29vcmRpbmF0ZUluZGV4ID0gYXhpcyA9PT0gJ3gnID8gMCA6IDE7XG4gIHZhciBwb3NNaW51cyA9IGxpbmVQb3NpdGlvblsxXVtjb29yZGluYXRlSW5kZXhdIC0gbGluZVBvc2l0aW9uWzBdW2Nvb3JkaW5hdGVJbmRleF07XG4gIHZhciBwZXJjZW50ID0gKHZhbHVlIC0gbWluKSAvIHZhbHVlTWludXM7XG4gIGlmICh2YWx1ZU1pbnVzID09PSAwKSBwZXJjZW50ID0gMDtcbiAgdmFyIHBvcyA9IHBlcmNlbnQgKiBwb3NNaW51cztcbiAgcmV0dXJuIHBvcyArIGxpbmVQb3NpdGlvblswXVtjb29yZGluYXRlSW5kZXhdO1xufVxuXG5mdW5jdGlvbiBnZXRCYWNrZ3JvdW5kQmFyQ29uZmlnKGJhckl0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gYmFySXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gYmFySXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGJhckl0ZW0uckxldmVsO1xuICB2YXIgc2hhcGVzID0gZ2V0QmFja2dyb3VuZEJhclNoYXBlcyhiYXJJdGVtKTtcbiAgdmFyIHN0eWxlID0gZ2V0QmFja2dyb3VuZEJhclN0eWxlKGJhckl0ZW0pO1xuICByZXR1cm4gc2hhcGVzLm1hcChmdW5jdGlvbiAoc2hhcGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ3JlY3QnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IGJhckl0ZW0uYmFja2dyb3VuZEJhci5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IHNoYXBlLFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEJhY2tncm91bmRCYXJTaGFwZXMoYmFySXRlbSkge1xuICB2YXIgbGFiZWxBeGlzID0gYmFySXRlbS5sYWJlbEF4aXMsXG4gICAgICB2YWx1ZUF4aXMgPSBiYXJJdGVtLnZhbHVlQXhpcztcbiAgdmFyIHRpY2tQb3NpdGlvbiA9IGxhYmVsQXhpcy50aWNrUG9zaXRpb247XG4gIHZhciBheGlzID0gdmFsdWVBeGlzLmF4aXMsXG4gICAgICBsaW5lUG9zaXRpb24gPSB2YWx1ZUF4aXMubGluZVBvc2l0aW9uO1xuICB2YXIgd2lkdGggPSBnZXRCYWNrZ3JvdW5kQmFyV2lkdGgoYmFySXRlbSk7XG4gIHZhciBoYWx0V2lkdGggPSB3aWR0aCAvIDI7XG4gIHZhciBwb3NJbmRleCA9IGF4aXMgPT09ICd4JyA/IDAgOiAxO1xuICB2YXIgY2VudGVyUG9zID0gdGlja1Bvc2l0aW9uLm1hcChmdW5jdGlvbiAocCkge1xuICAgIHJldHVybiBwWzEgLSBwb3NJbmRleF07XG4gIH0pO1xuICB2YXIgX3JlZjkgPSBbbGluZVBvc2l0aW9uWzBdW3Bvc0luZGV4XSwgbGluZVBvc2l0aW9uWzFdW3Bvc0luZGV4XV0sXG4gICAgICBzdGFydCA9IF9yZWY5WzBdLFxuICAgICAgZW5kID0gX3JlZjlbMV07XG4gIHJldHVybiBjZW50ZXJQb3MubWFwKGZ1bmN0aW9uIChjZW50ZXIpIHtcbiAgICBpZiAoYXhpcyA9PT0gJ3gnKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB4OiBzdGFydCxcbiAgICAgICAgeTogY2VudGVyIC0gaGFsdFdpZHRoLFxuICAgICAgICB3OiBlbmQgLSBzdGFydCxcbiAgICAgICAgaDogd2lkdGhcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IGNlbnRlciAtIGhhbHRXaWR0aCxcbiAgICAgICAgeTogZW5kLFxuICAgICAgICB3OiB3aWR0aCxcbiAgICAgICAgaDogc3RhcnQgLSBlbmRcbiAgICAgIH07XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0QmFja2dyb3VuZEJhcldpZHRoKGJhckl0ZW0pIHtcbiAgdmFyIGJhckFsbFdpZHRoQW5kR2FwID0gYmFySXRlbS5iYXJBbGxXaWR0aEFuZEdhcCxcbiAgICAgIGJhckNhdGVnb3J5V2lkdGggPSBiYXJJdGVtLmJhckNhdGVnb3J5V2lkdGgsXG4gICAgICBiYWNrZ3JvdW5kQmFyID0gYmFySXRlbS5iYWNrZ3JvdW5kQmFyO1xuICB2YXIgd2lkdGggPSBiYWNrZ3JvdW5kQmFyLndpZHRoO1xuICBpZiAodHlwZW9mIHdpZHRoID09PSAnbnVtYmVyJykgcmV0dXJuIHdpZHRoO1xuICBpZiAod2lkdGggPT09ICdhdXRvJykgcmV0dXJuIGJhckFsbFdpZHRoQW5kR2FwO1xuICByZXR1cm4gcGFyc2VJbnQod2lkdGgpIC8gMTAwICogYmFyQ2F0ZWdvcnlXaWR0aDtcbn1cblxuZnVuY3Rpb24gZ2V0QmFja2dyb3VuZEJhclN0eWxlKGJhckl0ZW0pIHtcbiAgcmV0dXJuIGJhckl0ZW0uYmFja2dyb3VuZEJhci5zdHlsZTtcbn1cblxuZnVuY3Rpb24gZ2V0QmFyQ29uZmlnKGJhckl0ZW0pIHtcbiAgdmFyIGJhckxhYmVsQXhpc1BvcyA9IGJhckl0ZW0uYmFyTGFiZWxBeGlzUG9zLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSBiYXJJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBiYXJJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gYmFySXRlbS5yTGV2ZWw7XG4gIHZhciBuYW1lID0gZ2V0QmFyTmFtZShiYXJJdGVtKTtcbiAgcmV0dXJuIGJhckxhYmVsQXhpc1Bvcy5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICAgIHNoYXBlOiBnZXRCYXJTaGFwZShiYXJJdGVtLCBpKSxcbiAgICAgIHN0eWxlOiBnZXRCYXJTdHlsZShiYXJJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRCYXJOYW1lKGJhckl0ZW0pIHtcbiAgdmFyIHNoYXBlVHlwZSA9IGJhckl0ZW0uc2hhcGVUeXBlO1xuICBpZiAoc2hhcGVUeXBlID09PSAnbGVmdEVjaGVsb24nIHx8IHNoYXBlVHlwZSA9PT0gJ3JpZ2h0RWNoZWxvbicpIHJldHVybiAncG9seWxpbmUnO1xuICByZXR1cm4gJ3JlY3QnO1xufVxuXG5mdW5jdGlvbiBnZXRCYXJTaGFwZShiYXJJdGVtLCBpKSB7XG4gIHZhciBzaGFwZVR5cGUgPSBiYXJJdGVtLnNoYXBlVHlwZTtcblxuICBpZiAoc2hhcGVUeXBlID09PSAnbGVmdEVjaGVsb24nKSB7XG4gICAgcmV0dXJuIGdldExlZnRFY2hlbG9uU2hhcGUoYmFySXRlbSwgaSk7XG4gIH0gZWxzZSBpZiAoc2hhcGVUeXBlID09PSAncmlnaHRFY2hlbG9uJykge1xuICAgIHJldHVybiBnZXRSaWdodEVjaGVsb25TaGFwZShiYXJJdGVtLCBpKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZ2V0Tm9ybWFsQmFyU2hhcGUoYmFySXRlbSwgaSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0TGVmdEVjaGVsb25TaGFwZShiYXJJdGVtLCBpKSB7XG4gIHZhciBiYXJWYWx1ZUF4aXNQb3MgPSBiYXJJdGVtLmJhclZhbHVlQXhpc1BvcyxcbiAgICAgIGJhckxhYmVsQXhpc1BvcyA9IGJhckl0ZW0uYmFyTGFiZWxBeGlzUG9zLFxuICAgICAgYmFyV2lkdGggPSBiYXJJdGVtLmJhcldpZHRoLFxuICAgICAgZWNoZWxvbk9mZnNldCA9IGJhckl0ZW0uZWNoZWxvbk9mZnNldDtcblxuICB2YXIgX2JhclZhbHVlQXhpc1BvcyRpID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGJhclZhbHVlQXhpc1Bvc1tpXSwgMiksXG4gICAgICBzdGFydCA9IF9iYXJWYWx1ZUF4aXNQb3MkaVswXSxcbiAgICAgIGVuZCA9IF9iYXJWYWx1ZUF4aXNQb3MkaVsxXTtcblxuICB2YXIgbGFiZWxBeGlzUG9zID0gYmFyTGFiZWxBeGlzUG9zW2ldO1xuICB2YXIgaGFsZldpZHRoID0gYmFyV2lkdGggLyAyO1xuICB2YXIgdmFsdWVBeGlzID0gYmFySXRlbS52YWx1ZUF4aXMuYXhpcztcbiAgdmFyIHBvaW50cyA9IFtdO1xuXG4gIGlmICh2YWx1ZUF4aXMgPT09ICd4Jykge1xuICAgIHBvaW50c1swXSA9IFtlbmQsIGxhYmVsQXhpc1BvcyAtIGhhbGZXaWR0aF07XG4gICAgcG9pbnRzWzFdID0gW2VuZCwgbGFiZWxBeGlzUG9zICsgaGFsZldpZHRoXTtcbiAgICBwb2ludHNbMl0gPSBbc3RhcnQsIGxhYmVsQXhpc1BvcyArIGhhbGZXaWR0aF07XG4gICAgcG9pbnRzWzNdID0gW3N0YXJ0ICsgZWNoZWxvbk9mZnNldCwgbGFiZWxBeGlzUG9zIC0gaGFsZldpZHRoXTtcbiAgICBpZiAoZW5kIC0gc3RhcnQgPCBlY2hlbG9uT2Zmc2V0KSBwb2ludHMuc3BsaWNlKDMsIDEpO1xuICB9IGVsc2Uge1xuICAgIHBvaW50c1swXSA9IFtsYWJlbEF4aXNQb3MgLSBoYWxmV2lkdGgsIGVuZF07XG4gICAgcG9pbnRzWzFdID0gW2xhYmVsQXhpc1BvcyArIGhhbGZXaWR0aCwgZW5kXTtcbiAgICBwb2ludHNbMl0gPSBbbGFiZWxBeGlzUG9zICsgaGFsZldpZHRoLCBzdGFydF07XG4gICAgcG9pbnRzWzNdID0gW2xhYmVsQXhpc1BvcyAtIGhhbGZXaWR0aCwgc3RhcnQgLSBlY2hlbG9uT2Zmc2V0XTtcbiAgICBpZiAoc3RhcnQgLSBlbmQgPCBlY2hlbG9uT2Zmc2V0KSBwb2ludHMuc3BsaWNlKDMsIDEpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwb2ludHM6IHBvaW50cyxcbiAgICBjbG9zZTogdHJ1ZVxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRSaWdodEVjaGVsb25TaGFwZShiYXJJdGVtLCBpKSB7XG4gIHZhciBiYXJWYWx1ZUF4aXNQb3MgPSBiYXJJdGVtLmJhclZhbHVlQXhpc1BvcyxcbiAgICAgIGJhckxhYmVsQXhpc1BvcyA9IGJhckl0ZW0uYmFyTGFiZWxBeGlzUG9zLFxuICAgICAgYmFyV2lkdGggPSBiYXJJdGVtLmJhcldpZHRoLFxuICAgICAgZWNoZWxvbk9mZnNldCA9IGJhckl0ZW0uZWNoZWxvbk9mZnNldDtcblxuICB2YXIgX2JhclZhbHVlQXhpc1BvcyRpMiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShiYXJWYWx1ZUF4aXNQb3NbaV0sIDIpLFxuICAgICAgc3RhcnQgPSBfYmFyVmFsdWVBeGlzUG9zJGkyWzBdLFxuICAgICAgZW5kID0gX2JhclZhbHVlQXhpc1BvcyRpMlsxXTtcblxuICB2YXIgbGFiZWxBeGlzUG9zID0gYmFyTGFiZWxBeGlzUG9zW2ldO1xuICB2YXIgaGFsZldpZHRoID0gYmFyV2lkdGggLyAyO1xuICB2YXIgdmFsdWVBeGlzID0gYmFySXRlbS52YWx1ZUF4aXMuYXhpcztcbiAgdmFyIHBvaW50cyA9IFtdO1xuXG4gIGlmICh2YWx1ZUF4aXMgPT09ICd4Jykge1xuICAgIHBvaW50c1swXSA9IFtlbmQsIGxhYmVsQXhpc1BvcyArIGhhbGZXaWR0aF07XG4gICAgcG9pbnRzWzFdID0gW2VuZCwgbGFiZWxBeGlzUG9zIC0gaGFsZldpZHRoXTtcbiAgICBwb2ludHNbMl0gPSBbc3RhcnQsIGxhYmVsQXhpc1BvcyAtIGhhbGZXaWR0aF07XG4gICAgcG9pbnRzWzNdID0gW3N0YXJ0ICsgZWNoZWxvbk9mZnNldCwgbGFiZWxBeGlzUG9zICsgaGFsZldpZHRoXTtcbiAgICBpZiAoZW5kIC0gc3RhcnQgPCBlY2hlbG9uT2Zmc2V0KSBwb2ludHMuc3BsaWNlKDIsIDEpO1xuICB9IGVsc2Uge1xuICAgIHBvaW50c1swXSA9IFtsYWJlbEF4aXNQb3MgKyBoYWxmV2lkdGgsIGVuZF07XG4gICAgcG9pbnRzWzFdID0gW2xhYmVsQXhpc1BvcyAtIGhhbGZXaWR0aCwgZW5kXTtcbiAgICBwb2ludHNbMl0gPSBbbGFiZWxBeGlzUG9zIC0gaGFsZldpZHRoLCBzdGFydF07XG4gICAgcG9pbnRzWzNdID0gW2xhYmVsQXhpc1BvcyArIGhhbGZXaWR0aCwgc3RhcnQgLSBlY2hlbG9uT2Zmc2V0XTtcbiAgICBpZiAoc3RhcnQgLSBlbmQgPCBlY2hlbG9uT2Zmc2V0KSBwb2ludHMuc3BsaWNlKDIsIDEpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwb2ludHM6IHBvaW50cyxcbiAgICBjbG9zZTogdHJ1ZVxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXROb3JtYWxCYXJTaGFwZShiYXJJdGVtLCBpKSB7XG4gIHZhciBiYXJWYWx1ZUF4aXNQb3MgPSBiYXJJdGVtLmJhclZhbHVlQXhpc1BvcyxcbiAgICAgIGJhckxhYmVsQXhpc1BvcyA9IGJhckl0ZW0uYmFyTGFiZWxBeGlzUG9zLFxuICAgICAgYmFyV2lkdGggPSBiYXJJdGVtLmJhcldpZHRoO1xuXG4gIHZhciBfYmFyVmFsdWVBeGlzUG9zJGkzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGJhclZhbHVlQXhpc1Bvc1tpXSwgMiksXG4gICAgICBzdGFydCA9IF9iYXJWYWx1ZUF4aXNQb3MkaTNbMF0sXG4gICAgICBlbmQgPSBfYmFyVmFsdWVBeGlzUG9zJGkzWzFdO1xuXG4gIHZhciBsYWJlbEF4aXNQb3MgPSBiYXJMYWJlbEF4aXNQb3NbaV07XG4gIHZhciB2YWx1ZUF4aXMgPSBiYXJJdGVtLnZhbHVlQXhpcy5heGlzO1xuICB2YXIgc2hhcGUgPSB7fTtcblxuICBpZiAodmFsdWVBeGlzID09PSAneCcpIHtcbiAgICBzaGFwZS54ID0gc3RhcnQ7XG4gICAgc2hhcGUueSA9IGxhYmVsQXhpc1BvcyAtIGJhcldpZHRoIC8gMjtcbiAgICBzaGFwZS53ID0gZW5kIC0gc3RhcnQ7XG4gICAgc2hhcGUuaCA9IGJhcldpZHRoO1xuICB9IGVsc2Uge1xuICAgIHNoYXBlLnggPSBsYWJlbEF4aXNQb3MgLSBiYXJXaWR0aCAvIDI7XG4gICAgc2hhcGUueSA9IGVuZDtcbiAgICBzaGFwZS53ID0gYmFyV2lkdGg7XG4gICAgc2hhcGUuaCA9IHN0YXJ0IC0gZW5kO1xuICB9XG5cbiAgcmV0dXJuIHNoYXBlO1xufVxuXG5mdW5jdGlvbiBnZXRCYXJTdHlsZShiYXJJdGVtLCBpKSB7XG4gIHZhciBiYXJTdHlsZSA9IGJhckl0ZW0uYmFyU3R5bGUsXG4gICAgICBncmFkaWVudCA9IGJhckl0ZW0uZ3JhZGllbnQsXG4gICAgICBjb2xvciA9IGJhckl0ZW0uY29sb3IsXG4gICAgICBpbmRlcGVuZGVudENvbG9yID0gYmFySXRlbS5pbmRlcGVuZGVudENvbG9yLFxuICAgICAgaW5kZXBlbmRlbnRDb2xvcnMgPSBiYXJJdGVtLmluZGVwZW5kZW50Q29sb3JzO1xuICB2YXIgZmlsbENvbG9yID0gW2JhclN0eWxlLmZpbGwgfHwgY29sb3JdO1xuICB2YXIgZ3JhZGllbnRDb2xvciA9ICgwLCBfdXRpbDIuZGVlcE1lcmdlKShmaWxsQ29sb3IsIGdyYWRpZW50LmNvbG9yKTtcblxuICBpZiAoaW5kZXBlbmRlbnRDb2xvcikge1xuICAgIHZhciBpZHRDb2xvciA9IGluZGVwZW5kZW50Q29sb3JzW2kgJSBpbmRlcGVuZGVudENvbG9ycy5sZW5ndGhdO1xuICAgIGdyYWRpZW50Q29sb3IgPSBpZHRDb2xvciBpbnN0YW5jZW9mIEFycmF5ID8gaWR0Q29sb3IgOiBbaWR0Q29sb3JdO1xuICB9XG5cbiAgaWYgKGdyYWRpZW50Q29sb3IubGVuZ3RoID09PSAxKSBncmFkaWVudENvbG9yLnB1c2goZ3JhZGllbnRDb2xvclswXSk7XG4gIHZhciBncmFkaWVudFBhcmFtcyA9IGdldEdyYWRpZW50UGFyYW1zKGJhckl0ZW0sIGkpO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBncmFkaWVudENvbG9yOiBncmFkaWVudENvbG9yLFxuICAgIGdyYWRpZW50UGFyYW1zOiBncmFkaWVudFBhcmFtcyxcbiAgICBncmFkaWVudFR5cGU6ICdsaW5lYXInLFxuICAgIGdyYWRpZW50V2l0aDogJ2ZpbGwnXG4gIH0sIGJhclN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0R3JhZGllbnRQYXJhbXMoYmFySXRlbSwgaSkge1xuICB2YXIgYmFyVmFsdWVBeGlzUG9zID0gYmFySXRlbS5iYXJWYWx1ZUF4aXNQb3MsXG4gICAgICBiYXJMYWJlbEF4aXNQb3MgPSBiYXJJdGVtLmJhckxhYmVsQXhpc1BvcyxcbiAgICAgIGRhdGEgPSBiYXJJdGVtLmRhdGE7XG4gIHZhciBfYmFySXRlbSR2YWx1ZUF4aXMgPSBiYXJJdGVtLnZhbHVlQXhpcyxcbiAgICAgIGxpbmVQb3NpdGlvbiA9IF9iYXJJdGVtJHZhbHVlQXhpcy5saW5lUG9zaXRpb24sXG4gICAgICBheGlzID0gX2Jhckl0ZW0kdmFsdWVBeGlzLmF4aXM7XG5cbiAgdmFyIF9iYXJWYWx1ZUF4aXNQb3MkaTQgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoYmFyVmFsdWVBeGlzUG9zW2ldLCAyKSxcbiAgICAgIHN0YXJ0ID0gX2JhclZhbHVlQXhpc1BvcyRpNFswXSxcbiAgICAgIGVuZCA9IF9iYXJWYWx1ZUF4aXNQb3MkaTRbMV07XG5cbiAgdmFyIGxhYmVsQXhpc1BvcyA9IGJhckxhYmVsQXhpc1Bvc1tpXTtcbiAgdmFyIHZhbHVlID0gZGF0YVtpXTtcblxuICB2YXIgX2xpbmVQb3NpdGlvbiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShsaW5lUG9zaXRpb24sIDIpLFxuICAgICAgbGluZVN0YXJ0ID0gX2xpbmVQb3NpdGlvblswXSxcbiAgICAgIGxpbmVFbmQgPSBfbGluZVBvc2l0aW9uWzFdO1xuXG4gIHZhciB2YWx1ZUF4aXNJbmRleCA9IGF4aXMgPT09ICd4JyA/IDAgOiAxO1xuICB2YXIgZW5kUG9zID0gZW5kO1xuXG4gIGlmICghYmFySXRlbS5ncmFkaWVudC5sb2NhbCkge1xuICAgIGVuZFBvcyA9IHZhbHVlIDwgMCA/IGxpbmVTdGFydFt2YWx1ZUF4aXNJbmRleF0gOiBsaW5lRW5kW3ZhbHVlQXhpc0luZGV4XTtcbiAgfVxuXG4gIGlmIChheGlzID09PSAneScpIHtcbiAgICByZXR1cm4gW2xhYmVsQXhpc1BvcywgZW5kUG9zLCBsYWJlbEF4aXNQb3MsIHN0YXJ0XTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gW2VuZFBvcywgbGFiZWxBeGlzUG9zLCBzdGFydCwgbGFiZWxBeGlzUG9zXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTdGFydEJhckNvbmZpZyhiYXJJdGVtKSB7XG4gIHZhciBjb25maWdzID0gZ2V0QmFyQ29uZmlnKGJhckl0ZW0pO1xuICB2YXIgc2hhcGVUeXBlID0gYmFySXRlbS5zaGFwZVR5cGU7XG4gIGNvbmZpZ3MuZm9yRWFjaChmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgdmFyIHNoYXBlID0gY29uZmlnLnNoYXBlO1xuXG4gICAgaWYgKHNoYXBlVHlwZSA9PT0gJ2xlZnRFY2hlbG9uJykge1xuICAgICAgc2hhcGUgPSBnZXRTdGFydExlZnRFY2hlbG9uU2hhcGUoc2hhcGUsIGJhckl0ZW0pO1xuICAgIH0gZWxzZSBpZiAoc2hhcGVUeXBlID09PSAncmlnaHRFY2hlbG9uJykge1xuICAgICAgc2hhcGUgPSBnZXRTdGFydFJpZ2h0RWNoZWxvblNoYXBlKHNoYXBlLCBiYXJJdGVtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2hhcGUgPSBnZXRTdGFydE5vcm1hbEJhclNoYXBlKHNoYXBlLCBiYXJJdGVtKTtcbiAgICB9XG5cbiAgICBjb25maWcuc2hhcGUgPSBzaGFwZTtcbiAgfSk7XG4gIHJldHVybiBjb25maWdzO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydExlZnRFY2hlbG9uU2hhcGUoc2hhcGUsIGJhckl0ZW0pIHtcbiAgdmFyIGF4aXMgPSBiYXJJdGVtLnZhbHVlQXhpcy5heGlzO1xuICBzaGFwZSA9ICgwLCBfdXRpbC5kZWVwQ2xvbmUpKHNoYXBlKTtcbiAgdmFyIF9zaGFwZSA9IHNoYXBlLFxuICAgICAgcG9pbnRzID0gX3NoYXBlLnBvaW50cztcbiAgdmFyIGluZGV4ID0gYXhpcyA9PT0gJ3gnID8gMCA6IDE7XG4gIHZhciBzdGFydCA9IHBvaW50c1syXVtpbmRleF07XG4gIHBvaW50cy5mb3JFYWNoKGZ1bmN0aW9uIChwb2ludCkge1xuICAgIHJldHVybiBwb2ludFtpbmRleF0gPSBzdGFydDtcbiAgfSk7XG4gIHJldHVybiBzaGFwZTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRSaWdodEVjaGVsb25TaGFwZShzaGFwZSwgYmFySXRlbSkge1xuICB2YXIgYXhpcyA9IGJhckl0ZW0udmFsdWVBeGlzLmF4aXM7XG4gIHNoYXBlID0gKDAsIF91dGlsLmRlZXBDbG9uZSkoc2hhcGUpO1xuICB2YXIgX3NoYXBlMiA9IHNoYXBlLFxuICAgICAgcG9pbnRzID0gX3NoYXBlMi5wb2ludHM7XG4gIHZhciBpbmRleCA9IGF4aXMgPT09ICd4JyA/IDAgOiAxO1xuICB2YXIgc3RhcnQgPSBwb2ludHNbMl1baW5kZXhdO1xuICBwb2ludHMuZm9yRWFjaChmdW5jdGlvbiAocG9pbnQpIHtcbiAgICByZXR1cm4gcG9pbnRbaW5kZXhdID0gc3RhcnQ7XG4gIH0pO1xuICByZXR1cm4gc2hhcGU7XG59XG5cbmZ1bmN0aW9uIGdldFN0YXJ0Tm9ybWFsQmFyU2hhcGUoc2hhcGUsIGJhckl0ZW0pIHtcbiAgdmFyIGF4aXMgPSBiYXJJdGVtLnZhbHVlQXhpcy5heGlzO1xuICB2YXIgeCA9IHNoYXBlLngsXG4gICAgICB5ID0gc2hhcGUueSxcbiAgICAgIHcgPSBzaGFwZS53LFxuICAgICAgaCA9IHNoYXBlLmg7XG5cbiAgaWYgKGF4aXMgPT09ICd4Jykge1xuICAgIHcgPSAwO1xuICB9IGVsc2Uge1xuICAgIHkgPSB5ICsgaDtcbiAgICBoID0gMDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgeDogeCxcbiAgICB5OiB5LFxuICAgIHc6IHcsXG4gICAgaDogaFxuICB9O1xufVxuXG5mdW5jdGlvbiBiZWZvcmVVcGRhdGVCYXIoZ3JhcGhzLCBiYXJJdGVtLCBpLCB1cGRhdGVyKSB7XG4gIHZhciByZW5kZXIgPSB1cGRhdGVyLmNoYXJ0LnJlbmRlcjtcbiAgdmFyIG5hbWUgPSBnZXRCYXJOYW1lKGJhckl0ZW0pO1xuXG4gIGlmIChncmFwaHNbaV0gJiYgZ3JhcGhzW2ldWzBdLm5hbWUgIT09IG5hbWUpIHtcbiAgICBncmFwaHNbaV0uZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgICAgcmV0dXJuIHJlbmRlci5kZWxHcmFwaChnKTtcbiAgICB9KTtcbiAgICBncmFwaHNbaV0gPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsQ29uZmlnKGJhckl0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gYmFySXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gYmFySXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGJhckl0ZW0uckxldmVsO1xuICB2YXIgc2hhcGVzID0gZ2V0TGFiZWxTaGFwZXMoYmFySXRlbSk7XG4gIHZhciBzdHlsZSA9IGdldExhYmVsU3R5bGUoYmFySXRlbSk7XG4gIHJldHVybiBzaGFwZXMubWFwKGZ1bmN0aW9uIChzaGFwZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAndGV4dCcsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogYmFySXRlbS5sYWJlbC5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IHNoYXBlLFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsU2hhcGVzKGJhckl0ZW0pIHtcbiAgdmFyIGNvbnRlbnRzID0gZ2V0Rm9ybWF0dGVyTGFiZWxzKGJhckl0ZW0pO1xuICB2YXIgcG9zaXRpb24gPSBnZXRMYWJlbHNQb3NpdGlvbihiYXJJdGVtKTtcbiAgcmV0dXJuIHBvc2l0aW9uLm1hcChmdW5jdGlvbiAocG9zLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHBvc2l0aW9uOiBwb3MsXG4gICAgICBjb250ZW50OiBjb250ZW50c1tpXVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRGb3JtYXR0ZXJMYWJlbHMoYmFySXRlbSkge1xuICB2YXIgZGF0YSA9IGJhckl0ZW0uZGF0YSxcbiAgICAgIGxhYmVsID0gYmFySXRlbS5sYWJlbDtcbiAgdmFyIGZvcm1hdHRlciA9IGxhYmVsLmZvcm1hdHRlcjtcbiAgZGF0YSA9IGRhdGEuZmlsdGVyKGZ1bmN0aW9uIChkKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBkID09PSAnbnVtYmVyJztcbiAgfSkubWFwKGZ1bmN0aW9uIChkKSB7XG4gICAgcmV0dXJuIGQudG9TdHJpbmcoKTtcbiAgfSk7XG4gIGlmICghZm9ybWF0dGVyKSByZXR1cm4gZGF0YTtcbiAgdmFyIHR5cGUgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShmb3JtYXR0ZXIpO1xuICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHJldHVybiBkYXRhLm1hcChmdW5jdGlvbiAoZCkge1xuICAgIHJldHVybiBmb3JtYXR0ZXIucmVwbGFjZSgne3ZhbHVlfScsIGQpO1xuICB9KTtcbiAgaWYgKHR5cGUgPT09ICdmdW5jdGlvbicpIHJldHVybiBkYXRhLm1hcChmdW5jdGlvbiAoZCwgaSkge1xuICAgIHJldHVybiBmb3JtYXR0ZXIoe1xuICAgICAgdmFsdWU6IGQsXG4gICAgICBpbmRleDogaVxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsc1Bvc2l0aW9uKGJhckl0ZW0pIHtcbiAgdmFyIGxhYmVsID0gYmFySXRlbS5sYWJlbCxcbiAgICAgIGJhclZhbHVlQXhpc1BvcyA9IGJhckl0ZW0uYmFyVmFsdWVBeGlzUG9zLFxuICAgICAgYmFyTGFiZWxBeGlzUG9zID0gYmFySXRlbS5iYXJMYWJlbEF4aXNQb3M7XG4gIHZhciBwb3NpdGlvbiA9IGxhYmVsLnBvc2l0aW9uLFxuICAgICAgb2Zmc2V0ID0gbGFiZWwub2Zmc2V0O1xuICB2YXIgYXhpcyA9IGJhckl0ZW0udmFsdWVBeGlzLmF4aXM7XG4gIHJldHVybiBiYXJWYWx1ZUF4aXNQb3MubWFwKGZ1bmN0aW9uIChfcmVmMTAsIGkpIHtcbiAgICB2YXIgX3JlZjExID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxMCwgMiksXG4gICAgICAgIHN0YXJ0ID0gX3JlZjExWzBdLFxuICAgICAgICBlbmQgPSBfcmVmMTFbMV07XG5cbiAgICB2YXIgbGFiZWxBeGlzUG9zID0gYmFyTGFiZWxBeGlzUG9zW2ldO1xuICAgIHZhciBwb3MgPSBbZW5kLCBsYWJlbEF4aXNQb3NdO1xuXG4gICAgaWYgKHBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgcG9zID0gW3N0YXJ0LCBsYWJlbEF4aXNQb3NdO1xuICAgIH1cblxuICAgIGlmIChwb3NpdGlvbiA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHBvcyA9IFsoc3RhcnQgKyBlbmQpIC8gMiwgbGFiZWxBeGlzUG9zXTtcbiAgICB9XG5cbiAgICBpZiAoYXhpcyA9PT0gJ3knKSBwb3MucmV2ZXJzZSgpO1xuICAgIHJldHVybiBnZXRPZmZzZXRlZFBvaW50KHBvcywgb2Zmc2V0KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldE9mZnNldGVkUG9pbnQoX3JlZjEyLCBfcmVmMTMpIHtcbiAgdmFyIF9yZWYxNCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMTIsIDIpLFxuICAgICAgeCA9IF9yZWYxNFswXSxcbiAgICAgIHkgPSBfcmVmMTRbMV07XG5cbiAgdmFyIF9yZWYxNSA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMTMsIDIpLFxuICAgICAgb3ggPSBfcmVmMTVbMF0sXG4gICAgICBveSA9IF9yZWYxNVsxXTtcblxuICByZXR1cm4gW3ggKyBveCwgeSArIG95XTtcbn1cblxuZnVuY3Rpb24gZ2V0TGFiZWxTdHlsZShiYXJJdGVtKSB7XG4gIHZhciBjb2xvciA9IGJhckl0ZW0uY29sb3IsXG4gICAgICBzdHlsZSA9IGJhckl0ZW0ubGFiZWwuc3R5bGUsXG4gICAgICBnYyA9IGJhckl0ZW0uZ3JhZGllbnQuY29sb3I7XG4gIGlmIChnYy5sZW5ndGgpIGNvbG9yID0gZ2NbMF07XG4gIHN0eWxlID0gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBmaWxsOiBjb2xvclxuICB9LCBzdHlsZSk7XG4gIHJldHVybiBzdHlsZTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmdhdWdlID0gZ2F1Z2U7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX2dhdWdlID0gcmVxdWlyZShcIi4uL2NvbmZpZy9nYXVnZVwiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG52YXIgX3V0aWwyID0gcmVxdWlyZShcIi4uL3V0aWxcIik7XG5cbnZhciBfY29sb3IgPSByZXF1aXJlKFwiQGppYW1pbmdoaS9jb2xvclwiKTtcblxuZnVuY3Rpb24gb3duS2V5cyhvYmplY3QsIGVudW1lcmFibGVPbmx5KSB7IHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTsgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHsgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7IGlmIChlbnVtZXJhYmxlT25seSkgc3ltYm9scyA9IHN5bWJvbHMuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHsgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBzeW0pLmVudW1lcmFibGU7IH0pOyBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7IH0gcmV0dXJuIGtleXM7IH1cblxuZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307IGlmIChpICUgMikgeyBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7ICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTsgfSk7IH0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpIHsgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzb3VyY2UpKTsgfSBlbHNlIHsgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsgfSk7IH0gfSByZXR1cm4gdGFyZ2V0OyB9XG5cbmZ1bmN0aW9uIGdhdWdlKGNoYXJ0KSB7XG4gIHZhciBvcHRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuICB2YXIgc2VyaWVzID0gb3B0aW9uLnNlcmllcztcbiAgaWYgKCFzZXJpZXMpIHNlcmllcyA9IFtdO1xuICB2YXIgZ2F1Z2VzID0gKDAsIF91dGlsMi5pbml0TmVlZFNlcmllcykoc2VyaWVzLCBfZ2F1Z2UuZ2F1Z2VDb25maWcsICdnYXVnZScpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzQ2VudGVyKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzUmFkaXVzKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzRGF0YVJhZGl1c0FuZExpbmVXaWR0aChnYXVnZXMsIGNoYXJ0KTtcbiAgZ2F1Z2VzID0gY2FsY0dhdWdlc0RhdGFBbmdsZXMoZ2F1Z2VzLCBjaGFydCk7XG4gIGdhdWdlcyA9IGNhbGNHYXVnZXNEYXRhR3JhZGllbnQoZ2F1Z2VzLCBjaGFydCk7XG4gIGdhdWdlcyA9IGNhbGNHYXVnZXNBeGlzVGlja1Bvc2l0aW9uKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzTGFiZWxQb3NpdGlvbkFuZEFsaWduKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzTGFiZWxEYXRhKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzRGV0YWlsc1Bvc2l0aW9uKGdhdWdlcywgY2hhcnQpO1xuICBnYXVnZXMgPSBjYWxjR2F1Z2VzRGV0YWlsc0NvbnRlbnQoZ2F1Z2VzLCBjaGFydCk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGdhdWdlcyxcbiAgICBrZXk6ICdnYXVnZUF4aXNUaWNrJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0QXhpc1RpY2tDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGdhdWdlcyxcbiAgICBrZXk6ICdnYXVnZUF4aXNMYWJlbCcsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldEF4aXNMYWJlbENvbmZpZ1xuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogZ2F1Z2VzLFxuICAgIGtleTogJ2dhdWdlQmFja2dyb3VuZEFyYycsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldEJhY2tncm91bmRBcmNDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRCYWNrZ3JvdW5kQXJjQ29uZmlnXG4gIH0pO1xuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiBnYXVnZXMsXG4gICAga2V5OiAnZ2F1Z2VBcmMnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRBcmNDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRBcmNDb25maWcsXG4gICAgYmVmb3JlQ2hhbmdlOiBiZWZvcmVDaGFuZ2VBcmNcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGdhdWdlcyxcbiAgICBrZXk6ICdnYXVnZVBvaW50ZXInLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRQb2ludGVyQ29uZmlnLFxuICAgIGdldFN0YXJ0R3JhcGhDb25maWc6IGdldFN0YXJ0UG9pbnRlckNvbmZpZ1xuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogZ2F1Z2VzLFxuICAgIGtleTogJ2dhdWdlRGV0YWlscycsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldERldGFpbHNDb25maWdcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNHYXVnZXNDZW50ZXIoZ2F1Z2VzLCBjaGFydCkge1xuICB2YXIgYXJlYSA9IGNoYXJ0LnJlbmRlci5hcmVhO1xuICBnYXVnZXMuZm9yRWFjaChmdW5jdGlvbiAoZ2F1Z2VJdGVtKSB7XG4gICAgdmFyIGNlbnRlciA9IGdhdWdlSXRlbS5jZW50ZXI7XG4gICAgY2VudGVyID0gY2VudGVyLm1hcChmdW5jdGlvbiAocG9zLCBpKSB7XG4gICAgICBpZiAodHlwZW9mIHBvcyA9PT0gJ251bWJlcicpIHJldHVybiBwb3M7XG4gICAgICByZXR1cm4gcGFyc2VJbnQocG9zKSAvIDEwMCAqIGFyZWFbaV07XG4gICAgfSk7XG4gICAgZ2F1Z2VJdGVtLmNlbnRlciA9IGNlbnRlcjtcbiAgfSk7XG4gIHJldHVybiBnYXVnZXM7XG59XG5cbmZ1bmN0aW9uIGNhbGNHYXVnZXNSYWRpdXMoZ2F1Z2VzLCBjaGFydCkge1xuICB2YXIgYXJlYSA9IGNoYXJ0LnJlbmRlci5hcmVhO1xuICB2YXIgbWF4UmFkaXVzID0gTWF0aC5taW4uYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhcmVhKSkgLyAyO1xuICBnYXVnZXMuZm9yRWFjaChmdW5jdGlvbiAoZ2F1Z2VJdGVtKSB7XG4gICAgdmFyIHJhZGl1cyA9IGdhdWdlSXRlbS5yYWRpdXM7XG5cbiAgICBpZiAodHlwZW9mIHJhZGl1cyAhPT0gJ251bWJlcicpIHtcbiAgICAgIHJhZGl1cyA9IHBhcnNlSW50KHJhZGl1cykgLyAxMDAgKiBtYXhSYWRpdXM7XG4gICAgfVxuXG4gICAgZ2F1Z2VJdGVtLnJhZGl1cyA9IHJhZGl1cztcbiAgfSk7XG4gIHJldHVybiBnYXVnZXM7XG59XG5cbmZ1bmN0aW9uIGNhbGNHYXVnZXNEYXRhUmFkaXVzQW5kTGluZVdpZHRoKGdhdWdlcywgY2hhcnQpIHtcbiAgdmFyIGFyZWEgPSBjaGFydC5yZW5kZXIuYXJlYTtcbiAgdmFyIG1heFJhZGl1cyA9IE1hdGgubWluLmFwcGx5KE1hdGgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoYXJlYSkpIC8gMjtcbiAgZ2F1Z2VzLmZvckVhY2goZnVuY3Rpb24gKGdhdWdlSXRlbSkge1xuICAgIHZhciByYWRpdXMgPSBnYXVnZUl0ZW0ucmFkaXVzLFxuICAgICAgICBkYXRhID0gZ2F1Z2VJdGVtLmRhdGEsXG4gICAgICAgIGFyY0xpbmVXaWR0aCA9IGdhdWdlSXRlbS5hcmNMaW5lV2lkdGg7XG4gICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICB2YXIgYXJjUmFkaXVzID0gaXRlbS5yYWRpdXMsXG4gICAgICAgICAgbGluZVdpZHRoID0gaXRlbS5saW5lV2lkdGg7XG4gICAgICBpZiAoIWFyY1JhZGl1cykgYXJjUmFkaXVzID0gcmFkaXVzO1xuICAgICAgaWYgKHR5cGVvZiBhcmNSYWRpdXMgIT09ICdudW1iZXInKSBhcmNSYWRpdXMgPSBwYXJzZUludChhcmNSYWRpdXMpIC8gMTAwICogbWF4UmFkaXVzO1xuICAgICAgaXRlbS5yYWRpdXMgPSBhcmNSYWRpdXM7XG4gICAgICBpZiAoIWxpbmVXaWR0aCkgbGluZVdpZHRoID0gYXJjTGluZVdpZHRoO1xuICAgICAgaXRlbS5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gZ2F1Z2VzO1xufVxuXG5mdW5jdGlvbiBjYWxjR2F1Z2VzRGF0YUFuZ2xlcyhnYXVnZXMsIGNoYXJ0KSB7XG4gIGdhdWdlcy5mb3JFYWNoKGZ1bmN0aW9uIChnYXVnZUl0ZW0pIHtcbiAgICB2YXIgc3RhcnRBbmdsZSA9IGdhdWdlSXRlbS5zdGFydEFuZ2xlLFxuICAgICAgICBlbmRBbmdsZSA9IGdhdWdlSXRlbS5lbmRBbmdsZSxcbiAgICAgICAgZGF0YSA9IGdhdWdlSXRlbS5kYXRhLFxuICAgICAgICBtaW4gPSBnYXVnZUl0ZW0ubWluLFxuICAgICAgICBtYXggPSBnYXVnZUl0ZW0ubWF4O1xuICAgIHZhciBhbmdsZU1pbnVzID0gZW5kQW5nbGUgLSBzdGFydEFuZ2xlO1xuICAgIHZhciB2YWx1ZU1pbnVzID0gbWF4IC0gbWluO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIHZhbHVlID0gaXRlbS52YWx1ZTtcbiAgICAgIHZhciBpdGVtQW5nbGUgPSBNYXRoLmFicygodmFsdWUgLSBtaW4pIC8gdmFsdWVNaW51cyAqIGFuZ2xlTWludXMpO1xuICAgICAgaXRlbS5zdGFydEFuZ2xlID0gc3RhcnRBbmdsZTtcbiAgICAgIGl0ZW0uZW5kQW5nbGUgPSBzdGFydEFuZ2xlICsgaXRlbUFuZ2xlO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gY2FsY0dhdWdlc0RhdGFHcmFkaWVudChnYXVnZXMsIGNoYXJ0KSB7XG4gIGdhdWdlcy5mb3JFYWNoKGZ1bmN0aW9uIChnYXVnZUl0ZW0pIHtcbiAgICB2YXIgZGF0YSA9IGdhdWdlSXRlbS5kYXRhO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIGNvbG9yID0gaXRlbS5jb2xvcixcbiAgICAgICAgICBncmFkaWVudCA9IGl0ZW0uZ3JhZGllbnQ7XG4gICAgICBpZiAoIWdyYWRpZW50IHx8ICFncmFkaWVudC5sZW5ndGgpIGdyYWRpZW50ID0gY29sb3I7XG4gICAgICBpZiAoIShncmFkaWVudCBpbnN0YW5jZW9mIEFycmF5KSkgZ3JhZGllbnQgPSBbZ3JhZGllbnRdO1xuICAgICAgaXRlbS5ncmFkaWVudCA9IGdyYWRpZW50O1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gY2FsY0dhdWdlc0F4aXNUaWNrUG9zaXRpb24oZ2F1Z2VzLCBjaGFydCkge1xuICBnYXVnZXMuZm9yRWFjaChmdW5jdGlvbiAoZ2F1Z2VJdGVtKSB7XG4gICAgdmFyIHN0YXJ0QW5nbGUgPSBnYXVnZUl0ZW0uc3RhcnRBbmdsZSxcbiAgICAgICAgZW5kQW5nbGUgPSBnYXVnZUl0ZW0uZW5kQW5nbGUsXG4gICAgICAgIHNwbGl0TnVtID0gZ2F1Z2VJdGVtLnNwbGl0TnVtLFxuICAgICAgICBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyLFxuICAgICAgICByYWRpdXMgPSBnYXVnZUl0ZW0ucmFkaXVzLFxuICAgICAgICBhcmNMaW5lV2lkdGggPSBnYXVnZUl0ZW0uYXJjTGluZVdpZHRoLFxuICAgICAgICBheGlzVGljayA9IGdhdWdlSXRlbS5heGlzVGljaztcbiAgICB2YXIgdGlja0xlbmd0aCA9IGF4aXNUaWNrLnRpY2tMZW5ndGgsXG4gICAgICAgIGxpbmVXaWR0aCA9IGF4aXNUaWNrLnN0eWxlLmxpbmVXaWR0aDtcbiAgICB2YXIgYW5nbGVzID0gZW5kQW5nbGUgLSBzdGFydEFuZ2xlO1xuICAgIHZhciBvdXRlclJhZGl1cyA9IHJhZGl1cyAtIGFyY0xpbmVXaWR0aCAvIDI7XG4gICAgdmFyIGlubmVyUmFkaXVzID0gb3V0ZXJSYWRpdXMgLSB0aWNrTGVuZ3RoO1xuICAgIHZhciBhbmdsZUdhcCA9IGFuZ2xlcyAvIChzcGxpdE51bSAtIDEpO1xuICAgIHZhciBhcmNMZW5ndGggPSAyICogTWF0aC5QSSAqIHJhZGl1cyAqIGFuZ2xlcyAvIChNYXRoLlBJICogMik7XG4gICAgdmFyIG9mZnNldCA9IE1hdGguY2VpbChsaW5lV2lkdGggLyAyKSAvIGFyY0xlbmd0aCAqIGFuZ2xlcztcbiAgICBnYXVnZUl0ZW0udGlja0FuZ2xlcyA9IFtdO1xuICAgIGdhdWdlSXRlbS50aWNrSW5uZXJSYWRpdXMgPSBbXTtcbiAgICBnYXVnZUl0ZW0udGlja1Bvc2l0aW9uID0gbmV3IEFycmF5KHNwbGl0TnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgICB2YXIgYW5nbGUgPSBzdGFydEFuZ2xlICsgYW5nbGVHYXAgKiBpO1xuICAgICAgaWYgKGkgPT09IDApIGFuZ2xlICs9IG9mZnNldDtcbiAgICAgIGlmIChpID09PSBzcGxpdE51bSAtIDEpIGFuZ2xlIC09IG9mZnNldDtcbiAgICAgIGdhdWdlSXRlbS50aWNrQW5nbGVzW2ldID0gYW5nbGU7XG4gICAgICBnYXVnZUl0ZW0udGlja0lubmVyUmFkaXVzW2ldID0gaW5uZXJSYWRpdXM7XG4gICAgICByZXR1cm4gW191dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXIpLmNvbmNhdChbb3V0ZXJSYWRpdXMsIGFuZ2xlXSkpLCBfdXRpbC5nZXRDaXJjbGVSYWRpYW5Qb2ludC5hcHBseSh2b2lkIDAsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY2VudGVyKS5jb25jYXQoW2lubmVyUmFkaXVzLCBhbmdsZV0pKV07XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gZ2F1Z2VzO1xufVxuXG5mdW5jdGlvbiBjYWxjR2F1Z2VzTGFiZWxQb3NpdGlvbkFuZEFsaWduKGdhdWdlcywgY2hhcnQpIHtcbiAgZ2F1Z2VzLmZvckVhY2goZnVuY3Rpb24gKGdhdWdlSXRlbSkge1xuICAgIHZhciBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyLFxuICAgICAgICB0aWNrSW5uZXJSYWRpdXMgPSBnYXVnZUl0ZW0udGlja0lubmVyUmFkaXVzLFxuICAgICAgICB0aWNrQW5nbGVzID0gZ2F1Z2VJdGVtLnRpY2tBbmdsZXMsXG4gICAgICAgIGxhYmVsR2FwID0gZ2F1Z2VJdGVtLmF4aXNMYWJlbC5sYWJlbEdhcDtcbiAgICB2YXIgcG9zaXRpb24gPSB0aWNrQW5nbGVzLm1hcChmdW5jdGlvbiAoYW5nbGUsIGkpIHtcbiAgICAgIHJldHVybiBfdXRpbC5nZXRDaXJjbGVSYWRpYW5Qb2ludC5hcHBseSh2b2lkIDAsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY2VudGVyKS5jb25jYXQoW3RpY2tJbm5lclJhZGl1c1tpXSAtIGxhYmVsR2FwLCB0aWNrQW5nbGVzW2ldXSkpO1xuICAgIH0pO1xuICAgIHZhciBhbGlnbiA9IHBvc2l0aW9uLm1hcChmdW5jdGlvbiAoX3JlZikge1xuICAgICAgdmFyIF9yZWYyID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYsIDIpLFxuICAgICAgICAgIHggPSBfcmVmMlswXSxcbiAgICAgICAgICB5ID0gX3JlZjJbMV07XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRleHRBbGlnbjogeCA+IGNlbnRlclswXSA/ICdyaWdodCcgOiAnbGVmdCcsXG4gICAgICAgIHRleHRCYXNlbGluZTogeSA+IGNlbnRlclsxXSA/ICdib3R0b20nIDogJ3RvcCdcbiAgICAgIH07XG4gICAgfSk7XG4gICAgZ2F1Z2VJdGVtLmxhYmVsUG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgICBnYXVnZUl0ZW0ubGFiZWxBbGlnbiA9IGFsaWduO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gY2FsY0dhdWdlc0xhYmVsRGF0YShnYXVnZXMsIGNoYXJ0KSB7XG4gIGdhdWdlcy5mb3JFYWNoKGZ1bmN0aW9uIChnYXVnZUl0ZW0pIHtcbiAgICB2YXIgYXhpc0xhYmVsID0gZ2F1Z2VJdGVtLmF4aXNMYWJlbCxcbiAgICAgICAgbWluID0gZ2F1Z2VJdGVtLm1pbixcbiAgICAgICAgbWF4ID0gZ2F1Z2VJdGVtLm1heCxcbiAgICAgICAgc3BsaXROdW0gPSBnYXVnZUl0ZW0uc3BsaXROdW07XG4gICAgdmFyIGRhdGEgPSBheGlzTGFiZWwuZGF0YSxcbiAgICAgICAgZm9ybWF0dGVyID0gYXhpc0xhYmVsLmZvcm1hdHRlcjtcbiAgICB2YXIgdmFsdWVHYXAgPSAobWF4IC0gbWluKSAvIChzcGxpdE51bSAtIDEpO1xuICAgIHZhciB2YWx1ZSA9IG5ldyBBcnJheShzcGxpdE51bSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KG1pbiArIHZhbHVlR2FwICogaSk7XG4gICAgfSk7XG4gICAgdmFyIGZvcm1hdHRlclR5cGUgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShmb3JtYXR0ZXIpO1xuICAgIGRhdGEgPSAoMCwgX3V0aWwyLmRlZXBNZXJnZSkodmFsdWUsIGRhdGEpLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgICAgdmFyIGxhYmVsID0gdjtcblxuICAgICAgaWYgKGZvcm1hdHRlclR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxhYmVsID0gZm9ybWF0dGVyLnJlcGxhY2UoJ3t2YWx1ZX0nLCB2KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGZvcm1hdHRlclR5cGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgbGFiZWwgPSBmb3JtYXR0ZXIoe1xuICAgICAgICAgIHZhbHVlOiB2LFxuICAgICAgICAgIGluZGV4OiBpXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbGFiZWw7XG4gICAgfSk7XG4gICAgYXhpc0xhYmVsLmRhdGEgPSBkYXRhO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gY2FsY0dhdWdlc0RldGFpbHNQb3NpdGlvbihnYXVnZXMsIGNoYXJ0KSB7XG4gIGdhdWdlcy5mb3JFYWNoKGZ1bmN0aW9uIChnYXVnZUl0ZW0pIHtcbiAgICB2YXIgZGF0YSA9IGdhdWdlSXRlbS5kYXRhLFxuICAgICAgICBkZXRhaWxzID0gZ2F1Z2VJdGVtLmRldGFpbHMsXG4gICAgICAgIGNlbnRlciA9IGdhdWdlSXRlbS5jZW50ZXI7XG4gICAgdmFyIHBvc2l0aW9uID0gZGV0YWlscy5wb3NpdGlvbixcbiAgICAgICAgb2Zmc2V0ID0gZGV0YWlscy5vZmZzZXQ7XG4gICAgdmFyIGRldGFpbHNQb3NpdGlvbiA9IGRhdGEubWFwKGZ1bmN0aW9uIChfcmVmMykge1xuICAgICAgdmFyIHN0YXJ0QW5nbGUgPSBfcmVmMy5zdGFydEFuZ2xlLFxuICAgICAgICAgIGVuZEFuZ2xlID0gX3JlZjMuZW5kQW5nbGUsXG4gICAgICAgICAgcmFkaXVzID0gX3JlZjMucmFkaXVzO1xuICAgICAgdmFyIHBvaW50ID0gbnVsbDtcblxuICAgICAgaWYgKHBvc2l0aW9uID09PSAnY2VudGVyJykge1xuICAgICAgICBwb2ludCA9IGNlbnRlcjtcbiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdzdGFydCcpIHtcbiAgICAgICAgcG9pbnQgPSBfdXRpbC5nZXRDaXJjbGVSYWRpYW5Qb2ludC5hcHBseSh2b2lkIDAsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY2VudGVyKS5jb25jYXQoW3JhZGl1cywgc3RhcnRBbmdsZV0pKTtcbiAgICAgIH0gZWxzZSBpZiAocG9zaXRpb24gPT09ICdlbmQnKSB7XG4gICAgICAgIHBvaW50ID0gX3V0aWwuZ2V0Q2lyY2xlUmFkaWFuUG9pbnQuYXBwbHkodm9pZCAwLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNlbnRlcikuY29uY2F0KFtyYWRpdXMsIGVuZEFuZ2xlXSkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZ2V0T2Zmc2V0ZWRQb2ludChwb2ludCwgb2Zmc2V0KTtcbiAgICB9KTtcbiAgICBnYXVnZUl0ZW0uZGV0YWlsc1Bvc2l0aW9uID0gZGV0YWlsc1Bvc2l0aW9uO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gY2FsY0dhdWdlc0RldGFpbHNDb250ZW50KGdhdWdlcywgY2hhcnQpIHtcbiAgZ2F1Z2VzLmZvckVhY2goZnVuY3Rpb24gKGdhdWdlSXRlbSkge1xuICAgIHZhciBkYXRhID0gZ2F1Z2VJdGVtLmRhdGEsXG4gICAgICAgIGRldGFpbHMgPSBnYXVnZUl0ZW0uZGV0YWlscztcbiAgICB2YXIgZm9ybWF0dGVyID0gZGV0YWlscy5mb3JtYXR0ZXI7XG4gICAgdmFyIGZvcm1hdHRlclR5cGUgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShmb3JtYXR0ZXIpO1xuICAgIHZhciBjb250ZW50cyA9IGRhdGEubWFwKGZ1bmN0aW9uIChkYXRhSXRlbSkge1xuICAgICAgdmFyIGNvbnRlbnQgPSBkYXRhSXRlbS52YWx1ZTtcblxuICAgICAgaWYgKGZvcm1hdHRlclR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnRlbnQgPSBmb3JtYXR0ZXIucmVwbGFjZSgne3ZhbHVlfScsICd7bnR9Jyk7XG4gICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnJlcGxhY2UoJ3tuYW1lfScsIGRhdGFJdGVtLm5hbWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0dGVyVHlwZSA9PT0gJ2Z1bmN0aW9uJykgY29udGVudCA9IGZvcm1hdHRlcihkYXRhSXRlbSk7XG4gICAgICByZXR1cm4gY29udGVudC50b1N0cmluZygpO1xuICAgIH0pO1xuICAgIGdhdWdlSXRlbS5kZXRhaWxzQ29udGVudCA9IGNvbnRlbnRzO1xuICB9KTtcbiAgcmV0dXJuIGdhdWdlcztcbn1cblxuZnVuY3Rpb24gZ2V0T2Zmc2V0ZWRQb2ludChfcmVmNCwgX3JlZjUpIHtcbiAgdmFyIF9yZWY2ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY0LCAyKSxcbiAgICAgIHggPSBfcmVmNlswXSxcbiAgICAgIHkgPSBfcmVmNlsxXTtcblxuICB2YXIgX3JlZjcgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjUsIDIpLFxuICAgICAgb3ggPSBfcmVmN1swXSxcbiAgICAgIG95ID0gX3JlZjdbMV07XG5cbiAgcmV0dXJuIFt4ICsgb3gsIHkgKyBveV07XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNUaWNrQ29uZmlnKGdhdWdlSXRlbSkge1xuICB2YXIgdGlja1Bvc2l0aW9uID0gZ2F1Z2VJdGVtLnRpY2tQb3NpdGlvbixcbiAgICAgIGFuaW1hdGlvbkN1cnZlID0gZ2F1Z2VJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBnYXVnZUl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBnYXVnZUl0ZW0uckxldmVsO1xuICByZXR1cm4gdGlja1Bvc2l0aW9uLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdwb2x5bGluZScsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogZ2F1Z2VJdGVtLmF4aXNUaWNrLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0QXhpc1RpY2tTaGFwZShnYXVnZUl0ZW0sIGkpLFxuICAgICAgc3R5bGU6IGdldEF4aXNUaWNrU3R5bGUoZ2F1Z2VJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRBeGlzVGlja1NoYXBlKGdhdWdlSXRlbSwgaSkge1xuICB2YXIgdGlja1Bvc2l0aW9uID0gZ2F1Z2VJdGVtLnRpY2tQb3NpdGlvbjtcbiAgcmV0dXJuIHtcbiAgICBwb2ludHM6IHRpY2tQb3NpdGlvbltpXVxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRBeGlzVGlja1N0eWxlKGdhdWdlSXRlbSwgaSkge1xuICB2YXIgc3R5bGUgPSBnYXVnZUl0ZW0uYXhpc1RpY2suc3R5bGU7XG4gIHJldHVybiBzdHlsZTtcbn1cblxuZnVuY3Rpb24gZ2V0QXhpc0xhYmVsQ29uZmlnKGdhdWdlSXRlbSkge1xuICB2YXIgbGFiZWxQb3NpdGlvbiA9IGdhdWdlSXRlbS5sYWJlbFBvc2l0aW9uLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSBnYXVnZUl0ZW0uYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZSA9IGdhdWdlSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGdhdWdlSXRlbS5yTGV2ZWw7XG4gIHJldHVybiBsYWJlbFBvc2l0aW9uLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICd0ZXh0JyxcbiAgICAgIGluZGV4OiByTGV2ZWwsXG4gICAgICB2aXNpYmxlOiBnYXVnZUl0ZW0uYXhpc0xhYmVsLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0QXhpc0xhYmVsU2hhcGUoZ2F1Z2VJdGVtLCBpKSxcbiAgICAgIHN0eWxlOiBnZXRBeGlzTGFiZWxTdHlsZShnYXVnZUl0ZW0sIGkpXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMYWJlbFNoYXBlKGdhdWdlSXRlbSwgaSkge1xuICB2YXIgbGFiZWxQb3NpdGlvbiA9IGdhdWdlSXRlbS5sYWJlbFBvc2l0aW9uLFxuICAgICAgZGF0YSA9IGdhdWdlSXRlbS5heGlzTGFiZWwuZGF0YTtcbiAgcmV0dXJuIHtcbiAgICBjb250ZW50OiBkYXRhW2ldLnRvU3RyaW5nKCksXG4gICAgcG9zaXRpb246IGxhYmVsUG9zaXRpb25baV1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0QXhpc0xhYmVsU3R5bGUoZ2F1Z2VJdGVtLCBpKSB7XG4gIHZhciBsYWJlbEFsaWduID0gZ2F1Z2VJdGVtLmxhYmVsQWxpZ24sXG4gICAgICBheGlzTGFiZWwgPSBnYXVnZUl0ZW0uYXhpc0xhYmVsO1xuICB2YXIgc3R5bGUgPSBheGlzTGFiZWwuc3R5bGU7XG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoX29iamVjdFNwcmVhZCh7fSwgbGFiZWxBbGlnbltpXSksIHN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0QmFja2dyb3VuZEFyY0NvbmZpZyhnYXVnZUl0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gZ2F1Z2VJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBnYXVnZUl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBnYXVnZUl0ZW0uckxldmVsO1xuICByZXR1cm4gW3tcbiAgICBuYW1lOiAnYXJjJyxcbiAgICBpbmRleDogckxldmVsLFxuICAgIHZpc2libGU6IGdhdWdlSXRlbS5iYWNrZ3JvdW5kQXJjLnNob3csXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICBzaGFwZTogZ2V0R2F1Z2VCYWNrZ3JvdW5kQXJjU2hhcGUoZ2F1Z2VJdGVtKSxcbiAgICBzdHlsZTogZ2V0R2F1Z2VCYWNrZ3JvdW5kQXJjU3R5bGUoZ2F1Z2VJdGVtKVxuICB9XTtcbn1cblxuZnVuY3Rpb24gZ2V0R2F1Z2VCYWNrZ3JvdW5kQXJjU2hhcGUoZ2F1Z2VJdGVtKSB7XG4gIHZhciBzdGFydEFuZ2xlID0gZ2F1Z2VJdGVtLnN0YXJ0QW5nbGUsXG4gICAgICBlbmRBbmdsZSA9IGdhdWdlSXRlbS5lbmRBbmdsZSxcbiAgICAgIGNlbnRlciA9IGdhdWdlSXRlbS5jZW50ZXIsXG4gICAgICByYWRpdXMgPSBnYXVnZUl0ZW0ucmFkaXVzO1xuICByZXR1cm4ge1xuICAgIHJ4OiBjZW50ZXJbMF0sXG4gICAgcnk6IGNlbnRlclsxXSxcbiAgICByOiByYWRpdXMsXG4gICAgc3RhcnRBbmdsZTogc3RhcnRBbmdsZSxcbiAgICBlbmRBbmdsZTogZW5kQW5nbGVcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0R2F1Z2VCYWNrZ3JvdW5kQXJjU3R5bGUoZ2F1Z2VJdGVtKSB7XG4gIHZhciBiYWNrZ3JvdW5kQXJjID0gZ2F1Z2VJdGVtLmJhY2tncm91bmRBcmMsXG4gICAgICBhcmNMaW5lV2lkdGggPSBnYXVnZUl0ZW0uYXJjTGluZVdpZHRoO1xuICB2YXIgc3R5bGUgPSBiYWNrZ3JvdW5kQXJjLnN0eWxlO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBsaW5lV2lkdGg6IGFyY0xpbmVXaWR0aFxuICB9LCBzdHlsZSk7XG59XG5cbmZ1bmN0aW9uIGdldFN0YXJ0QmFja2dyb3VuZEFyY0NvbmZpZyhnYXVnZUl0ZW0pIHtcbiAgdmFyIGNvbmZpZyA9IGdldEJhY2tncm91bmRBcmNDb25maWcoZ2F1Z2VJdGVtKVswXTtcblxuICB2YXIgc2hhcGUgPSBfb2JqZWN0U3ByZWFkKHt9LCBjb25maWcuc2hhcGUpO1xuXG4gIHNoYXBlLmVuZEFuZ2xlID0gY29uZmlnLnNoYXBlLnN0YXJ0QW5nbGU7XG4gIGNvbmZpZy5zaGFwZSA9IHNoYXBlO1xuICByZXR1cm4gW2NvbmZpZ107XG59XG5cbmZ1bmN0aW9uIGdldEFyY0NvbmZpZyhnYXVnZUl0ZW0pIHtcbiAgdmFyIGRhdGEgPSBnYXVnZUl0ZW0uZGF0YSxcbiAgICAgIGFuaW1hdGlvbkN1cnZlID0gZ2F1Z2VJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBnYXVnZUl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBnYXVnZUl0ZW0uckxldmVsO1xuICByZXR1cm4gZGF0YS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnYWdBcmMnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICAgIHNoYXBlOiBnZXRHYXVnZUFyY1NoYXBlKGdhdWdlSXRlbSwgaSksXG4gICAgICBzdHlsZTogZ2V0R2F1Z2VBcmNTdHlsZShnYXVnZUl0ZW0sIGkpXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEdhdWdlQXJjU2hhcGUoZ2F1Z2VJdGVtLCBpKSB7XG4gIHZhciBkYXRhID0gZ2F1Z2VJdGVtLmRhdGEsXG4gICAgICBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyLFxuICAgICAgZ3JhZGllbnRFbmRBbmdsZSA9IGdhdWdlSXRlbS5lbmRBbmdsZTtcbiAgdmFyIF9kYXRhJGkgPSBkYXRhW2ldLFxuICAgICAgcmFkaXVzID0gX2RhdGEkaS5yYWRpdXMsXG4gICAgICBzdGFydEFuZ2xlID0gX2RhdGEkaS5zdGFydEFuZ2xlLFxuICAgICAgZW5kQW5nbGUgPSBfZGF0YSRpLmVuZEFuZ2xlLFxuICAgICAgbG9jYWxHcmFkaWVudCA9IF9kYXRhJGkubG9jYWxHcmFkaWVudDtcbiAgaWYgKGxvY2FsR3JhZGllbnQpIGdyYWRpZW50RW5kQW5nbGUgPSBlbmRBbmdsZTtcbiAgcmV0dXJuIHtcbiAgICByeDogY2VudGVyWzBdLFxuICAgIHJ5OiBjZW50ZXJbMV0sXG4gICAgcjogcmFkaXVzLFxuICAgIHN0YXJ0QW5nbGU6IHN0YXJ0QW5nbGUsXG4gICAgZW5kQW5nbGU6IGVuZEFuZ2xlLFxuICAgIGdyYWRpZW50RW5kQW5nbGU6IGdyYWRpZW50RW5kQW5nbGVcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0R2F1Z2VBcmNTdHlsZShnYXVnZUl0ZW0sIGkpIHtcbiAgdmFyIGRhdGEgPSBnYXVnZUl0ZW0uZGF0YSxcbiAgICAgIGRhdGFJdGVtU3R5bGUgPSBnYXVnZUl0ZW0uZGF0YUl0ZW1TdHlsZTtcbiAgdmFyIF9kYXRhJGkyID0gZGF0YVtpXSxcbiAgICAgIGxpbmVXaWR0aCA9IF9kYXRhJGkyLmxpbmVXaWR0aCxcbiAgICAgIGdyYWRpZW50ID0gX2RhdGEkaTIuZ3JhZGllbnQ7XG4gIGdyYWRpZW50ID0gZ3JhZGllbnQubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuICgwLCBfY29sb3IuZ2V0UmdiYVZhbHVlKShjKTtcbiAgfSk7XG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoe1xuICAgIGxpbmVXaWR0aDogbGluZVdpZHRoLFxuICAgIGdyYWRpZW50OiBncmFkaWVudFxuICB9LCBkYXRhSXRlbVN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRBcmNDb25maWcoZ2F1Z2VJdGVtKSB7XG4gIHZhciBjb25maWdzID0gZ2V0QXJjQ29uZmlnKGdhdWdlSXRlbSk7XG4gIGNvbmZpZ3MubWFwKGZ1bmN0aW9uIChjb25maWcpIHtcbiAgICB2YXIgc2hhcGUgPSBfb2JqZWN0U3ByZWFkKHt9LCBjb25maWcuc2hhcGUpO1xuXG4gICAgc2hhcGUuZW5kQW5nbGUgPSBjb25maWcuc2hhcGUuc3RhcnRBbmdsZTtcbiAgICBjb25maWcuc2hhcGUgPSBzaGFwZTtcbiAgfSk7XG4gIHJldHVybiBjb25maWdzO1xufVxuXG5mdW5jdGlvbiBiZWZvcmVDaGFuZ2VBcmMoZ3JhcGgsIGNvbmZpZykge1xuICB2YXIgZ3JhcGhHcmFkaWVudCA9IGdyYXBoLnN0eWxlLmdyYWRpZW50O1xuICB2YXIgY2FjaGVOdW0gPSBncmFwaEdyYWRpZW50Lmxlbmd0aDtcbiAgdmFyIG5lZWROdW0gPSBjb25maWcuc3R5bGUuZ3JhZGllbnQubGVuZ3RoO1xuXG4gIGlmIChjYWNoZU51bSA+IG5lZWROdW0pIHtcbiAgICBncmFwaEdyYWRpZW50LnNwbGljZShuZWVkTnVtKTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgbGFzdCA9IGdyYXBoR3JhZGllbnQuc2xpY2UoLTEpWzBdO1xuICAgIGdyYXBoR3JhZGllbnQucHVzaC5hcHBseShncmFwaEdyYWRpZW50LCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKG5ldyBBcnJheShuZWVkTnVtIC0gY2FjaGVOdW0pLmZpbGwoMCkubWFwKGZ1bmN0aW9uIChmb28pIHtcbiAgICAgIHJldHVybiAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGxhc3QpO1xuICAgIH0pKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0UG9pbnRlckNvbmZpZyhnYXVnZUl0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gZ2F1Z2VJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBnYXVnZUl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyLFxuICAgICAgckxldmVsID0gZ2F1Z2VJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIFt7XG4gICAgbmFtZTogJ3BvbHlsaW5lJyxcbiAgICBpbmRleDogckxldmVsLFxuICAgIHZpc2libGU6IGdhdWdlSXRlbS5wb2ludGVyLnNob3csXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICBzaGFwZTogZ2V0UG9pbnRlclNoYXBlKGdhdWdlSXRlbSksXG4gICAgc3R5bGU6IGdldFBvaW50ZXJTdHlsZShnYXVnZUl0ZW0pLFxuICAgIHNldEdyYXBoQ2VudGVyOiBmdW5jdGlvbiBzZXRHcmFwaENlbnRlcihmb28sIGdyYXBoKSB7XG4gICAgICBncmFwaC5zdHlsZS5ncmFwaENlbnRlciA9IGNlbnRlcjtcbiAgICB9XG4gIH1dO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludGVyU2hhcGUoZ2F1Z2VJdGVtKSB7XG4gIHZhciBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyO1xuICByZXR1cm4ge1xuICAgIHBvaW50czogZ2V0UG9pbnRlclBvaW50cyhjZW50ZXIpLFxuICAgIGNsb3NlOiB0cnVlXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFBvaW50ZXJTdHlsZShnYXVnZUl0ZW0pIHtcbiAgdmFyIHN0YXJ0QW5nbGUgPSBnYXVnZUl0ZW0uc3RhcnRBbmdsZSxcbiAgICAgIGVuZEFuZ2xlID0gZ2F1Z2VJdGVtLmVuZEFuZ2xlLFxuICAgICAgbWluID0gZ2F1Z2VJdGVtLm1pbixcbiAgICAgIG1heCA9IGdhdWdlSXRlbS5tYXgsXG4gICAgICBkYXRhID0gZ2F1Z2VJdGVtLmRhdGEsXG4gICAgICBwb2ludGVyID0gZ2F1Z2VJdGVtLnBvaW50ZXIsXG4gICAgICBjZW50ZXIgPSBnYXVnZUl0ZW0uY2VudGVyO1xuICB2YXIgdmFsdWVJbmRleCA9IHBvaW50ZXIudmFsdWVJbmRleCxcbiAgICAgIHN0eWxlID0gcG9pbnRlci5zdHlsZTtcbiAgdmFyIHZhbHVlID0gZGF0YVt2YWx1ZUluZGV4XSA/IGRhdGFbdmFsdWVJbmRleF0udmFsdWUgOiAwO1xuICB2YXIgYW5nbGUgPSAodmFsdWUgLSBtaW4pIC8gKG1heCAtIG1pbikgKiAoZW5kQW5nbGUgLSBzdGFydEFuZ2xlKSArIHN0YXJ0QW5nbGUgKyBNYXRoLlBJIC8gMjtcbiAgcmV0dXJuICgwLCBfdXRpbDIuZGVlcE1lcmdlKSh7XG4gICAgcm90YXRlOiAoMCwgX3V0aWwyLnJhZGlhblRvQW5nbGUpKGFuZ2xlKSxcbiAgICBzY2FsZTogWzEsIDFdLFxuICAgIGdyYXBoQ2VudGVyOiBjZW50ZXJcbiAgfSwgc3R5bGUpO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludGVyUG9pbnRzKF9yZWY4KSB7XG4gIHZhciBfcmVmOSA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmOCwgMiksXG4gICAgICB4ID0gX3JlZjlbMF0sXG4gICAgICB5ID0gX3JlZjlbMV07XG5cbiAgdmFyIHBvaW50MSA9IFt4LCB5IC0gNDBdO1xuICB2YXIgcG9pbnQyID0gW3ggKyA1LCB5XTtcbiAgdmFyIHBvaW50MyA9IFt4LCB5ICsgMTBdO1xuICB2YXIgcG9pbnQ0ID0gW3ggLSA1LCB5XTtcbiAgcmV0dXJuIFtwb2ludDEsIHBvaW50MiwgcG9pbnQzLCBwb2ludDRdO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydFBvaW50ZXJDb25maWcoZ2F1Z2VJdGVtKSB7XG4gIHZhciBzdGFydEFuZ2xlID0gZ2F1Z2VJdGVtLnN0YXJ0QW5nbGU7XG4gIHZhciBjb25maWcgPSBnZXRQb2ludGVyQ29uZmlnKGdhdWdlSXRlbSlbMF07XG4gIGNvbmZpZy5zdHlsZS5yb3RhdGUgPSAoMCwgX3V0aWwyLnJhZGlhblRvQW5nbGUpKHN0YXJ0QW5nbGUgKyBNYXRoLlBJIC8gMik7XG4gIHJldHVybiBbY29uZmlnXTtcbn1cblxuZnVuY3Rpb24gZ2V0RGV0YWlsc0NvbmZpZyhnYXVnZUl0ZW0pIHtcbiAgdmFyIGRldGFpbHNQb3NpdGlvbiA9IGdhdWdlSXRlbS5kZXRhaWxzUG9zaXRpb24sXG4gICAgICBhbmltYXRpb25DdXJ2ZSA9IGdhdWdlSXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gZ2F1Z2VJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gZ2F1Z2VJdGVtLnJMZXZlbDtcbiAgdmFyIHZpc2libGUgPSBnYXVnZUl0ZW0uZGV0YWlscy5zaG93O1xuICByZXR1cm4gZGV0YWlsc1Bvc2l0aW9uLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdudW1iZXJUZXh0JyxcbiAgICAgIGluZGV4OiByTGV2ZWwsXG4gICAgICB2aXNpYmxlOiB2aXNpYmxlLFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IGdldERldGFpbHNTaGFwZShnYXVnZUl0ZW0sIGkpLFxuICAgICAgc3R5bGU6IGdldERldGFpbHNTdHlsZShnYXVnZUl0ZW0sIGkpXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldERldGFpbHNTaGFwZShnYXVnZUl0ZW0sIGkpIHtcbiAgdmFyIGRldGFpbHNQb3NpdGlvbiA9IGdhdWdlSXRlbS5kZXRhaWxzUG9zaXRpb24sXG4gICAgICBkZXRhaWxzQ29udGVudCA9IGdhdWdlSXRlbS5kZXRhaWxzQ29udGVudCxcbiAgICAgIGRhdGEgPSBnYXVnZUl0ZW0uZGF0YSxcbiAgICAgIGRldGFpbHMgPSBnYXVnZUl0ZW0uZGV0YWlscztcbiAgdmFyIHBvc2l0aW9uID0gZGV0YWlsc1Bvc2l0aW9uW2ldO1xuICB2YXIgY29udGVudCA9IGRldGFpbHNDb250ZW50W2ldO1xuICB2YXIgZGF0YVZhbHVlID0gZGF0YVtpXS52YWx1ZTtcbiAgdmFyIHRvRml4ZWQgPSBkZXRhaWxzLnZhbHVlVG9GaXhlZDtcbiAgcmV0dXJuIHtcbiAgICBudW1iZXI6IFtkYXRhVmFsdWVdLFxuICAgIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgcG9zaXRpb246IHBvc2l0aW9uLFxuICAgIHRvRml4ZWQ6IHRvRml4ZWRcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0RGV0YWlsc1N0eWxlKGdhdWdlSXRlbSwgaSkge1xuICB2YXIgZGV0YWlscyA9IGdhdWdlSXRlbS5kZXRhaWxzLFxuICAgICAgZGF0YSA9IGdhdWdlSXRlbS5kYXRhO1xuICB2YXIgc3R5bGUgPSBkZXRhaWxzLnN0eWxlO1xuICB2YXIgY29sb3IgPSBkYXRhW2ldLmNvbG9yO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBmaWxsOiBjb2xvclxuICB9LCBzdHlsZSk7XG59IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5ncmlkID0gZ3JpZDtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiQGppYW1pbmdoaS9jLXJlbmRlci9saWIvcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfY29uZmlnID0gcmVxdWlyZShcIi4uL2NvbmZpZ1wiKTtcblxudmFyIF91dGlsMiA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuXG5mdW5jdGlvbiBvd25LZXlzKG9iamVjdCwgZW51bWVyYWJsZU9ubHkpIHsgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpOyBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykgeyB2YXIgc3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqZWN0KTsgaWYgKGVudW1lcmFibGVPbmx5KSBzeW1ib2xzID0gc3ltYm9scy5maWx0ZXIoZnVuY3Rpb24gKHN5bSkgeyByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHN5bSkuZW51bWVyYWJsZTsgfSk7IGtleXMucHVzaC5hcHBseShrZXlzLCBzeW1ib2xzKTsgfSByZXR1cm4ga2V5czsgfVxuXG5mdW5jdGlvbiBfb2JqZWN0U3ByZWFkKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldICE9IG51bGwgPyBhcmd1bWVudHNbaV0gOiB7fTsgaWYgKGkgJSAyKSB7IG93bktleXMoc291cmNlLCB0cnVlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgKDAsIF9kZWZpbmVQcm9wZXJ0eTJbXCJkZWZhdWx0XCJdKSh0YXJnZXQsIGtleSwgc291cmNlW2tleV0pOyB9KTsgfSBlbHNlIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycykgeyBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKHNvdXJjZSkpOyB9IGVsc2UgeyBvd25LZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIGtleSkpOyB9KTsgfSB9IHJldHVybiB0YXJnZXQ7IH1cblxuZnVuY3Rpb24gZ3JpZChjaGFydCkge1xuICB2YXIgb3B0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcbiAgdmFyIGdyaWQgPSBvcHRpb24uZ3JpZDtcbiAgZ3JpZCA9ICgwLCBfdXRpbDIuZGVlcE1lcmdlKSgoMCwgX3V0aWwuZGVlcENsb25lKShfY29uZmlnLmdyaWRDb25maWcsIHRydWUpLCBncmlkIHx8IHt9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogW2dyaWRdLFxuICAgIGtleTogJ2dyaWQnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRHcmlkQ29uZmlnXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRHcmlkQ29uZmlnKGdyaWRJdGVtLCB1cGRhdGVyKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGdyaWRJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBncmlkSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGdyaWRJdGVtLnJMZXZlbDtcbiAgdmFyIHNoYXBlID0gZ2V0R3JpZFNoYXBlKGdyaWRJdGVtLCB1cGRhdGVyKTtcbiAgdmFyIHN0eWxlID0gZ2V0R3JpZFN0eWxlKGdyaWRJdGVtKTtcbiAgdXBkYXRlci5jaGFydC5ncmlkQXJlYSA9IF9vYmplY3RTcHJlYWQoe30sIHNoYXBlKTtcbiAgcmV0dXJuIFt7XG4gICAgbmFtZTogJ3JlY3QnLFxuICAgIGluZGV4OiByTGV2ZWwsXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICBzaGFwZTogc2hhcGUsXG4gICAgc3R5bGU6IHN0eWxlXG4gIH1dO1xufVxuXG5mdW5jdGlvbiBnZXRHcmlkU2hhcGUoZ3JpZEl0ZW0sIHVwZGF0ZXIpIHtcbiAgdmFyIF91cGRhdGVyJGNoYXJ0JHJlbmRlciA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKSh1cGRhdGVyLmNoYXJ0LnJlbmRlci5hcmVhLCAyKSxcbiAgICAgIHcgPSBfdXBkYXRlciRjaGFydCRyZW5kZXJbMF0sXG4gICAgICBoID0gX3VwZGF0ZXIkY2hhcnQkcmVuZGVyWzFdO1xuXG4gIHZhciBsZWZ0ID0gZ2V0TnVtYmVyVmFsdWUoZ3JpZEl0ZW0ubGVmdCwgdyk7XG4gIHZhciByaWdodCA9IGdldE51bWJlclZhbHVlKGdyaWRJdGVtLnJpZ2h0LCB3KTtcbiAgdmFyIHRvcCA9IGdldE51bWJlclZhbHVlKGdyaWRJdGVtLnRvcCwgaCk7XG4gIHZhciBib3R0b20gPSBnZXROdW1iZXJWYWx1ZShncmlkSXRlbS5ib3R0b20sIGgpO1xuICB2YXIgd2lkdGggPSB3IC0gbGVmdCAtIHJpZ2h0O1xuICB2YXIgaGVpZ2h0ID0gaCAtIHRvcCAtIGJvdHRvbTtcbiAgcmV0dXJuIHtcbiAgICB4OiBsZWZ0LFxuICAgIHk6IHRvcCxcbiAgICB3OiB3aWR0aCxcbiAgICBoOiBoZWlnaHRcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0TnVtYmVyVmFsdWUodmFsLCBhbGwpIHtcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSByZXR1cm4gdmFsO1xuICBpZiAodHlwZW9mIHZhbCAhPT0gJ3N0cmluZycpIHJldHVybiAwO1xuICByZXR1cm4gYWxsICogcGFyc2VJbnQodmFsKSAvIDEwMDtcbn1cblxuZnVuY3Rpb24gZ2V0R3JpZFN0eWxlKGdyaWRJdGVtKSB7XG4gIHZhciBzdHlsZSA9IGdyaWRJdGVtLnN0eWxlO1xuICByZXR1cm4gc3R5bGU7XG59IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJtZXJnZUNvbG9yXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9tZXJnZUNvbG9yLm1lcmdlQ29sb3I7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwidGl0bGVcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX3RpdGxlLnRpdGxlO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImdyaWRcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX2dyaWQuZ3JpZDtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJheGlzXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9heGlzLmF4aXM7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibGluZVwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfbGluZS5saW5lO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImJhclwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfYmFyLmJhcjtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJwaWVcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX3BpZS5waWU7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwicmFkYXJBeGlzXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9yYWRhckF4aXMucmFkYXJBeGlzO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcInJhZGFyXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9yYWRhci5yYWRhcjtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJnYXVnZVwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfZ2F1Z2UuZ2F1Z2U7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwibGVnZW5kXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9sZWdlbmQubGVnZW5kO1xuICB9XG59KTtcblxudmFyIF9tZXJnZUNvbG9yID0gcmVxdWlyZShcIi4vbWVyZ2VDb2xvclwiKTtcblxudmFyIF90aXRsZSA9IHJlcXVpcmUoXCIuL3RpdGxlXCIpO1xuXG52YXIgX2dyaWQgPSByZXF1aXJlKFwiLi9ncmlkXCIpO1xuXG52YXIgX2F4aXMgPSByZXF1aXJlKFwiLi9heGlzXCIpO1xuXG52YXIgX2xpbmUgPSByZXF1aXJlKFwiLi9saW5lXCIpO1xuXG52YXIgX2JhciA9IHJlcXVpcmUoXCIuL2JhclwiKTtcblxudmFyIF9waWUgPSByZXF1aXJlKFwiLi9waWVcIik7XG5cbnZhciBfcmFkYXJBeGlzID0gcmVxdWlyZShcIi4vcmFkYXJBeGlzXCIpO1xuXG52YXIgX3JhZGFyID0gcmVxdWlyZShcIi4vcmFkYXJcIik7XG5cbnZhciBfZ2F1Z2UgPSByZXF1aXJlKFwiLi9nYXVnZVwiKTtcblxudmFyIF9sZWdlbmQgPSByZXF1aXJlKFwiLi9sZWdlbmRcIik7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5sZWdlbmQgPSBsZWdlbmQ7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiQGppYW1pbmdoaS9jLXJlbmRlci9saWIvcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfY29uZmlnID0gcmVxdWlyZShcIi4uL2NvbmZpZ1wiKTtcblxudmFyIF91dGlsMiA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuXG5mdW5jdGlvbiBsZWdlbmQoY2hhcnQpIHtcbiAgdmFyIG9wdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG4gIHZhciBsZWdlbmQgPSBvcHRpb24ubGVnZW5kO1xuXG4gIGlmIChsZWdlbmQpIHtcbiAgICBsZWdlbmQgPSAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoKDAsIF91dGlsLmRlZXBDbG9uZSkoX2NvbmZpZy5sZWdlbmRDb25maWcsIHRydWUpLCBsZWdlbmQpO1xuICAgIGxlZ2VuZCA9IGluaXRMZWdlbmREYXRhKGxlZ2VuZCk7XG4gICAgbGVnZW5kID0gZmlsdGVySW52YWxpZERhdGEobGVnZW5kLCBvcHRpb24sIGNoYXJ0KTtcbiAgICBsZWdlbmQgPSBjYWxjTGVnZW5kVGV4dFdpZHRoKGxlZ2VuZCwgY2hhcnQpO1xuICAgIGxlZ2VuZCA9IGNhbGNMZWdlbmRQb3NpdGlvbihsZWdlbmQsIGNoYXJ0KTtcbiAgICBsZWdlbmQgPSBbbGVnZW5kXTtcbiAgfSBlbHNlIHtcbiAgICBsZWdlbmQgPSBbXTtcbiAgfVxuXG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGxlZ2VuZCxcbiAgICBrZXk6ICdsZWdlbmRJY29uJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0SWNvbkNvbmZpZ1xuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogbGVnZW5kLFxuICAgIGtleTogJ2xlZ2VuZFRleHQnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRUZXh0Q29uZmlnXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBpbml0TGVnZW5kRGF0YShsZWdlbmQpIHtcbiAgdmFyIGRhdGEgPSBsZWdlbmQuZGF0YTtcbiAgbGVnZW5kLmRhdGEgPSBkYXRhLm1hcChmdW5jdGlvbiAoaXRlbSkge1xuICAgIHZhciBpdGVtVHlwZSA9ICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKGl0ZW0pO1xuXG4gICAgaWYgKGl0ZW1UeXBlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogaXRlbVxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGl0ZW1UeXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICcnXG4gICAgfTtcbiAgfSk7XG4gIHJldHVybiBsZWdlbmQ7XG59XG5cbmZ1bmN0aW9uIGZpbHRlckludmFsaWREYXRhKGxlZ2VuZCwgb3B0aW9uLCBjaGFydCkge1xuICB2YXIgc2VyaWVzID0gb3B0aW9uLnNlcmllcztcbiAgdmFyIGxlZ2VuZFN0YXR1cyA9IGNoYXJ0LmxlZ2VuZFN0YXR1cztcbiAgdmFyIGRhdGEgPSBsZWdlbmQuZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICB2YXIgbmFtZSA9IGl0ZW0ubmFtZTtcbiAgICB2YXIgcmVzdWx0ID0gc2VyaWVzLmZpbmQoZnVuY3Rpb24gKF9yZWYpIHtcbiAgICAgIHZhciBzbiA9IF9yZWYubmFtZTtcbiAgICAgIHJldHVybiBuYW1lID09PSBzbjtcbiAgICB9KTtcbiAgICBpZiAoIXJlc3VsdCkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghaXRlbS5jb2xvcikgaXRlbS5jb2xvciA9IHJlc3VsdC5jb2xvcjtcbiAgICBpZiAoIWl0ZW0uaWNvbikgaXRlbS5pY29uID0gcmVzdWx0LnR5cGU7XG4gICAgcmV0dXJuIGl0ZW07XG4gIH0pO1xuICBpZiAoIWxlZ2VuZFN0YXR1cyB8fCBsZWdlbmRTdGF0dXMubGVuZ3RoICE9PSBsZWdlbmQuZGF0YS5sZW5ndGgpIGxlZ2VuZFN0YXR1cyA9IG5ldyBBcnJheShsZWdlbmQuZGF0YS5sZW5ndGgpLmZpbGwodHJ1ZSk7XG4gIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgIHJldHVybiBpdGVtLnN0YXR1cyA9IGxlZ2VuZFN0YXR1c1tpXTtcbiAgfSk7XG4gIGxlZ2VuZC5kYXRhID0gZGF0YTtcbiAgY2hhcnQubGVnZW5kU3RhdHVzID0gbGVnZW5kU3RhdHVzO1xuICByZXR1cm4gbGVnZW5kO1xufVxuXG5mdW5jdGlvbiBjYWxjTGVnZW5kVGV4dFdpZHRoKGxlZ2VuZCwgY2hhcnQpIHtcbiAgdmFyIGN0eCA9IGNoYXJ0LnJlbmRlci5jdHg7XG4gIHZhciBkYXRhID0gbGVnZW5kLmRhdGEsXG4gICAgICB0ZXh0U3R5bGUgPSBsZWdlbmQudGV4dFN0eWxlLFxuICAgICAgdGV4dFVuc2VsZWN0ZWRTdHlsZSA9IGxlZ2VuZC50ZXh0VW5zZWxlY3RlZFN0eWxlO1xuICBkYXRhLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICB2YXIgc3RhdHVzID0gaXRlbS5zdGF0dXMsXG4gICAgICAgIG5hbWUgPSBpdGVtLm5hbWU7XG4gICAgaXRlbS50ZXh0V2lkdGggPSBnZXRUZXh0V2lkdGgoY3R4LCBuYW1lLCBzdGF0dXMgPyB0ZXh0U3R5bGUgOiB0ZXh0VW5zZWxlY3RlZFN0eWxlKTtcbiAgfSk7XG4gIHJldHVybiBsZWdlbmQ7XG59XG5cbmZ1bmN0aW9uIGdldFRleHRXaWR0aChjdHgsIHRleHQsIHN0eWxlKSB7XG4gIGN0eC5mb250ID0gZ2V0Rm9udENvbmZpZyhzdHlsZSk7XG4gIHJldHVybiBjdHgubWVhc3VyZVRleHQodGV4dCkud2lkdGg7XG59XG5cbmZ1bmN0aW9uIGdldEZvbnRDb25maWcoc3R5bGUpIHtcbiAgdmFyIGZvbnRGYW1pbHkgPSBzdHlsZS5mb250RmFtaWx5LFxuICAgICAgZm9udFNpemUgPSBzdHlsZS5mb250U2l6ZTtcbiAgcmV0dXJuIFwiXCIuY29uY2F0KGZvbnRTaXplLCBcInB4IFwiKS5jb25jYXQoZm9udEZhbWlseSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNMZWdlbmRQb3NpdGlvbihsZWdlbmQsIGNoYXJ0KSB7XG4gIHZhciBvcmllbnQgPSBsZWdlbmQub3JpZW50O1xuXG4gIGlmIChvcmllbnQgPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICBjYWxjVmVydGljYWxQb3NpdGlvbihsZWdlbmQsIGNoYXJ0KTtcbiAgfSBlbHNlIHtcbiAgICBjYWxjSG9yaXpvbnRhbFBvc2l0aW9uKGxlZ2VuZCwgY2hhcnQpO1xuICB9XG5cbiAgcmV0dXJuIGxlZ2VuZDtcbn1cblxuZnVuY3Rpb24gY2FsY0hvcml6b250YWxQb3NpdGlvbihsZWdlbmQsIGNoYXJ0KSB7XG4gIHZhciBpY29uSGVpZ2h0ID0gbGVnZW5kLmljb25IZWlnaHQsXG4gICAgICBpdGVtR2FwID0gbGVnZW5kLml0ZW1HYXA7XG4gIHZhciBsaW5lcyA9IGNhbGNEZWZhdWx0SG9yaXpvbnRhbFBvc2l0aW9uKGxlZ2VuZCwgY2hhcnQpO1xuICB2YXIgeE9mZnNldHMgPSBsaW5lcy5tYXAoZnVuY3Rpb24gKGxpbmUpIHtcbiAgICByZXR1cm4gZ2V0SG9yaXpvbnRhbFhPZmZzZXQobGluZSwgbGVnZW5kLCBjaGFydCk7XG4gIH0pO1xuICB2YXIgeU9mZnNldCA9IGdldEhvcml6b250YWxZT2Zmc2V0KGxlZ2VuZCwgY2hhcnQpO1xuICB2YXIgYWxpZ24gPSB7XG4gICAgdGV4dEFsaWduOiAnbGVmdCcsXG4gICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICB9O1xuICBsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5lLCBpKSB7XG4gICAgcmV0dXJuIGxpbmUuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIGljb25Qb3NpdGlvbiA9IGl0ZW0uaWNvblBvc2l0aW9uLFxuICAgICAgICAgIHRleHRQb3NpdGlvbiA9IGl0ZW0udGV4dFBvc2l0aW9uO1xuICAgICAgdmFyIHhPZmZzZXQgPSB4T2Zmc2V0c1tpXTtcbiAgICAgIHZhciByZWFsWU9mZnNldCA9IHlPZmZzZXQgKyBpICogKGl0ZW1HYXAgKyBpY29uSGVpZ2h0KTtcbiAgICAgIGl0ZW0uaWNvblBvc2l0aW9uID0gbWVyZ2VPZmZzZXQoaWNvblBvc2l0aW9uLCBbeE9mZnNldCwgcmVhbFlPZmZzZXRdKTtcbiAgICAgIGl0ZW0udGV4dFBvc2l0aW9uID0gbWVyZ2VPZmZzZXQodGV4dFBvc2l0aW9uLCBbeE9mZnNldCwgcmVhbFlPZmZzZXRdKTtcbiAgICAgIGl0ZW0uYWxpZ24gPSBhbGlnbjtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNEZWZhdWx0SG9yaXpvbnRhbFBvc2l0aW9uKGxlZ2VuZCwgY2hhcnQpIHtcbiAgdmFyIGRhdGEgPSBsZWdlbmQuZGF0YSxcbiAgICAgIGljb25XaWR0aCA9IGxlZ2VuZC5pY29uV2lkdGg7XG4gIHZhciB3ID0gY2hhcnQucmVuZGVyLmFyZWFbMF07XG4gIHZhciBzdGFydEluZGV4ID0gMDtcbiAgdmFyIGxpbmVzID0gW1tdXTtcbiAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtLCBpKSB7XG4gICAgdmFyIGJlZm9yZVdpZHRoID0gZ2V0QmVmb3JlV2lkdGgoc3RhcnRJbmRleCwgaSwgbGVnZW5kKTtcbiAgICB2YXIgZW5kWFBvcyA9IGJlZm9yZVdpZHRoICsgaWNvbldpZHRoICsgNSArIGl0ZW0udGV4dFdpZHRoO1xuXG4gICAgaWYgKGVuZFhQb3MgPj0gdykge1xuICAgICAgc3RhcnRJbmRleCA9IGk7XG4gICAgICBiZWZvcmVXaWR0aCA9IGdldEJlZm9yZVdpZHRoKHN0YXJ0SW5kZXgsIGksIGxlZ2VuZCk7XG4gICAgICBsaW5lcy5wdXNoKFtdKTtcbiAgICB9XG5cbiAgICBpdGVtLmljb25Qb3NpdGlvbiA9IFtiZWZvcmVXaWR0aCwgMF07XG4gICAgaXRlbS50ZXh0UG9zaXRpb24gPSBbYmVmb3JlV2lkdGggKyBpY29uV2lkdGggKyA1LCAwXTtcbiAgICBsaW5lcy5zbGljZSgtMSlbMF0ucHVzaChpdGVtKTtcbiAgfSk7XG4gIHJldHVybiBsaW5lcztcbn1cblxuZnVuY3Rpb24gZ2V0QmVmb3JlV2lkdGgoc3RhcnRJbmRleCwgY3VycmVudEluZGV4LCBsZWdlbmQpIHtcbiAgdmFyIGRhdGEgPSBsZWdlbmQuZGF0YSxcbiAgICAgIGljb25XaWR0aCA9IGxlZ2VuZC5pY29uV2lkdGgsXG4gICAgICBpdGVtR2FwID0gbGVnZW5kLml0ZW1HYXA7XG4gIHZhciBiZWZvcmVJdGVtID0gZGF0YS5zbGljZShzdGFydEluZGV4LCBjdXJyZW50SW5kZXgpO1xuICByZXR1cm4gKDAsIF91dGlsMi5tdWxBZGQpKGJlZm9yZUl0ZW0ubWFwKGZ1bmN0aW9uIChfcmVmMikge1xuICAgIHZhciB0ZXh0V2lkdGggPSBfcmVmMi50ZXh0V2lkdGg7XG4gICAgcmV0dXJuIHRleHRXaWR0aDtcbiAgfSkpICsgKGN1cnJlbnRJbmRleCAtIHN0YXJ0SW5kZXgpICogKGl0ZW1HYXAgKyA1ICsgaWNvbldpZHRoKTtcbn1cblxuZnVuY3Rpb24gZ2V0SG9yaXpvbnRhbFhPZmZzZXQoZGF0YSwgbGVnZW5kLCBjaGFydCkge1xuICB2YXIgbGVmdCA9IGxlZ2VuZC5sZWZ0LFxuICAgICAgcmlnaHQgPSBsZWdlbmQucmlnaHQsXG4gICAgICBpY29uV2lkdGggPSBsZWdlbmQuaWNvbldpZHRoLFxuICAgICAgaXRlbUdhcCA9IGxlZ2VuZC5pdGVtR2FwO1xuICB2YXIgdyA9IGNoYXJ0LnJlbmRlci5hcmVhWzBdO1xuICB2YXIgZGF0YU51bSA9IGRhdGEubGVuZ3RoO1xuICB2YXIgYWxsV2lkdGggPSAoMCwgX3V0aWwyLm11bEFkZCkoZGF0YS5tYXAoZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgdmFyIHRleHRXaWR0aCA9IF9yZWYzLnRleHRXaWR0aDtcbiAgICByZXR1cm4gdGV4dFdpZHRoO1xuICB9KSkgKyBkYXRhTnVtICogKDUgKyBpY29uV2lkdGgpICsgKGRhdGFOdW0gLSAxKSAqIGl0ZW1HYXA7XG4gIHZhciBob3Jpem9udGFsID0gW2xlZnQsIHJpZ2h0XS5maW5kSW5kZXgoZnVuY3Rpb24gKHBvcykge1xuICAgIHJldHVybiBwb3MgIT09ICdhdXRvJztcbiAgfSk7XG5cbiAgaWYgKGhvcml6b250YWwgPT09IC0xKSB7XG4gICAgcmV0dXJuICh3IC0gYWxsV2lkdGgpIC8gMjtcbiAgfSBlbHNlIGlmIChob3Jpem9udGFsID09PSAwKSB7XG4gICAgaWYgKHR5cGVvZiBsZWZ0ID09PSAnbnVtYmVyJykgcmV0dXJuIGxlZnQ7XG4gICAgcmV0dXJuIHBhcnNlSW50KGxlZnQpIC8gMTAwICogdztcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIHJpZ2h0ICE9PSAnbnVtYmVyJykgcmlnaHQgPSBwYXJzZUludChyaWdodCkgLyAxMDAgKiB3O1xuICAgIHJldHVybiB3IC0gKGFsbFdpZHRoICsgcmlnaHQpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEhvcml6b250YWxZT2Zmc2V0KGxlZ2VuZCwgY2hhcnQpIHtcbiAgdmFyIHRvcCA9IGxlZ2VuZC50b3AsXG4gICAgICBib3R0b20gPSBsZWdlbmQuYm90dG9tLFxuICAgICAgaWNvbkhlaWdodCA9IGxlZ2VuZC5pY29uSGVpZ2h0O1xuICB2YXIgaCA9IGNoYXJ0LnJlbmRlci5hcmVhWzFdO1xuICB2YXIgdmVydGljYWwgPSBbdG9wLCBib3R0b21dLmZpbmRJbmRleChmdW5jdGlvbiAocG9zKSB7XG4gICAgcmV0dXJuIHBvcyAhPT0gJ2F1dG8nO1xuICB9KTtcbiAgdmFyIGhhbGZJY29uSGVpZ2h0ID0gaWNvbkhlaWdodCAvIDI7XG5cbiAgaWYgKHZlcnRpY2FsID09PSAtMSkge1xuICAgIHZhciBfY2hhcnQkZ3JpZEFyZWEgPSBjaGFydC5ncmlkQXJlYSxcbiAgICAgICAgeSA9IF9jaGFydCRncmlkQXJlYS55LFxuICAgICAgICBoZWlnaHQgPSBfY2hhcnQkZ3JpZEFyZWEuaDtcbiAgICByZXR1cm4geSArIGhlaWdodCArIDQ1IC0gaGFsZkljb25IZWlnaHQ7XG4gIH0gZWxzZSBpZiAodmVydGljYWwgPT09IDApIHtcbiAgICBpZiAodHlwZW9mIHRvcCA9PT0gJ251bWJlcicpIHJldHVybiB0b3AgLSBoYWxmSWNvbkhlaWdodDtcbiAgICByZXR1cm4gcGFyc2VJbnQodG9wKSAvIDEwMCAqIGggLSBoYWxmSWNvbkhlaWdodDtcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIGJvdHRvbSAhPT0gJ251bWJlcicpIGJvdHRvbSA9IHBhcnNlSW50KGJvdHRvbSkgLyAxMDAgKiBoO1xuICAgIHJldHVybiBoIC0gYm90dG9tIC0gaGFsZkljb25IZWlnaHQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWVyZ2VPZmZzZXQoX3JlZjQsIF9yZWY1KSB7XG4gIHZhciBfcmVmNiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmNCwgMiksXG4gICAgICB4ID0gX3JlZjZbMF0sXG4gICAgICB5ID0gX3JlZjZbMV07XG5cbiAgdmFyIF9yZWY3ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY1LCAyKSxcbiAgICAgIG94ID0gX3JlZjdbMF0sXG4gICAgICBveSA9IF9yZWY3WzFdO1xuXG4gIHJldHVybiBbeCArIG94LCB5ICsgb3ldO1xufVxuXG5mdW5jdGlvbiBjYWxjVmVydGljYWxQb3NpdGlvbihsZWdlbmQsIGNoYXJ0KSB7XG4gIHZhciBfZ2V0VmVydGljYWxYT2Zmc2V0ID0gZ2V0VmVydGljYWxYT2Zmc2V0KGxlZ2VuZCwgY2hhcnQpLFxuICAgICAgX2dldFZlcnRpY2FsWE9mZnNldDIgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX2dldFZlcnRpY2FsWE9mZnNldCwgMiksXG4gICAgICBpc1JpZ2h0ID0gX2dldFZlcnRpY2FsWE9mZnNldDJbMF0sXG4gICAgICB4T2Zmc2V0ID0gX2dldFZlcnRpY2FsWE9mZnNldDJbMV07XG5cbiAgdmFyIHlPZmZzZXQgPSBnZXRWZXJ0aWNhbFlPZmZzZXQobGVnZW5kLCBjaGFydCk7XG4gIGNhbGNEZWZhdWx0VmVydGljYWxQb3NpdGlvbihsZWdlbmQsIGlzUmlnaHQpO1xuICB2YXIgYWxpZ24gPSB7XG4gICAgdGV4dEFsaWduOiAnbGVmdCcsXG4gICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICB9O1xuICBsZWdlbmQuZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgdmFyIHRleHRQb3NpdGlvbiA9IGl0ZW0udGV4dFBvc2l0aW9uLFxuICAgICAgICBpY29uUG9zaXRpb24gPSBpdGVtLmljb25Qb3NpdGlvbjtcbiAgICBpdGVtLnRleHRQb3NpdGlvbiA9IG1lcmdlT2Zmc2V0KHRleHRQb3NpdGlvbiwgW3hPZmZzZXQsIHlPZmZzZXRdKTtcbiAgICBpdGVtLmljb25Qb3NpdGlvbiA9IG1lcmdlT2Zmc2V0KGljb25Qb3NpdGlvbiwgW3hPZmZzZXQsIHlPZmZzZXRdKTtcbiAgICBpdGVtLmFsaWduID0gYWxpZ247XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRWZXJ0aWNhbFhPZmZzZXQobGVnZW5kLCBjaGFydCkge1xuICB2YXIgbGVmdCA9IGxlZ2VuZC5sZWZ0LFxuICAgICAgcmlnaHQgPSBsZWdlbmQucmlnaHQ7XG4gIHZhciB3ID0gY2hhcnQucmVuZGVyLmFyZWFbMF07XG4gIHZhciBob3Jpem9udGFsID0gW2xlZnQsIHJpZ2h0XS5maW5kSW5kZXgoZnVuY3Rpb24gKHBvcykge1xuICAgIHJldHVybiBwb3MgIT09ICdhdXRvJztcbiAgfSk7XG5cbiAgaWYgKGhvcml6b250YWwgPT09IC0xKSB7XG4gICAgcmV0dXJuIFt0cnVlLCB3IC0gMTBdO1xuICB9IGVsc2Uge1xuICAgIHZhciBvZmZzZXQgPSBbbGVmdCwgcmlnaHRdW2hvcml6b250YWxdO1xuICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJykgb2Zmc2V0ID0gcGFyc2VJbnQob2Zmc2V0KSAvIDEwMCAqIHc7XG4gICAgcmV0dXJuIFtCb29sZWFuKGhvcml6b250YWwpLCBvZmZzZXRdO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldFZlcnRpY2FsWU9mZnNldChsZWdlbmQsIGNoYXJ0KSB7XG4gIHZhciBpY29uSGVpZ2h0ID0gbGVnZW5kLmljb25IZWlnaHQsXG4gICAgICBpdGVtR2FwID0gbGVnZW5kLml0ZW1HYXAsXG4gICAgICBkYXRhID0gbGVnZW5kLmRhdGEsXG4gICAgICB0b3AgPSBsZWdlbmQudG9wLFxuICAgICAgYm90dG9tID0gbGVnZW5kLmJvdHRvbTtcbiAgdmFyIGggPSBjaGFydC5yZW5kZXIuYXJlYVsxXTtcbiAgdmFyIGRhdGFOdW0gPSBkYXRhLmxlbmd0aDtcbiAgdmFyIGFsbEhlaWdodCA9IGRhdGFOdW0gKiBpY29uSGVpZ2h0ICsgKGRhdGFOdW0gLSAxKSAqIGl0ZW1HYXA7XG4gIHZhciB2ZXJ0aWNhbCA9IFt0b3AsIGJvdHRvbV0uZmluZEluZGV4KGZ1bmN0aW9uIChwb3MpIHtcbiAgICByZXR1cm4gcG9zICE9PSAnYXV0byc7XG4gIH0pO1xuXG4gIGlmICh2ZXJ0aWNhbCA9PT0gLTEpIHtcbiAgICByZXR1cm4gKGggLSBhbGxIZWlnaHQpIC8gMjtcbiAgfSBlbHNlIHtcbiAgICB2YXIgb2Zmc2V0ID0gW3RvcCwgYm90dG9tXVt2ZXJ0aWNhbF07XG4gICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInKSBvZmZzZXQgPSBwYXJzZUludChvZmZzZXQpIC8gMTAwICogaDtcbiAgICBpZiAodmVydGljYWwgPT09IDEpIG9mZnNldCA9IGggLSBvZmZzZXQgLSBhbGxIZWlnaHQ7XG4gICAgcmV0dXJuIG9mZnNldDtcbiAgfVxufVxuXG5mdW5jdGlvbiBjYWxjRGVmYXVsdFZlcnRpY2FsUG9zaXRpb24obGVnZW5kLCBpc1JpZ2h0KSB7XG4gIHZhciBkYXRhID0gbGVnZW5kLmRhdGEsXG4gICAgICBpY29uV2lkdGggPSBsZWdlbmQuaWNvbldpZHRoLFxuICAgICAgaWNvbkhlaWdodCA9IGxlZ2VuZC5pY29uSGVpZ2h0LFxuICAgICAgaXRlbUdhcCA9IGxlZ2VuZC5pdGVtR2FwO1xuICB2YXIgaGFsZkljb25IZWlnaHQgPSBpY29uSGVpZ2h0IC8gMjtcbiAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtLCBpKSB7XG4gICAgdmFyIHRleHRXaWR0aCA9IGl0ZW0udGV4dFdpZHRoO1xuICAgIHZhciB5UG9zID0gKGljb25IZWlnaHQgKyBpdGVtR2FwKSAqIGkgKyBoYWxmSWNvbkhlaWdodDtcbiAgICB2YXIgaWNvblhQb3MgPSBpc1JpZ2h0ID8gMCAtIGljb25XaWR0aCA6IDA7XG4gICAgdmFyIHRleHRYcG9zID0gaXNSaWdodCA/IGljb25YUG9zIC0gNSAtIHRleHRXaWR0aCA6IGljb25XaWR0aCArIDU7XG4gICAgaXRlbS5pY29uUG9zaXRpb24gPSBbaWNvblhQb3MsIHlQb3NdO1xuICAgIGl0ZW0udGV4dFBvc2l0aW9uID0gW3RleHRYcG9zLCB5UG9zXTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEljb25Db25maWcobGVnZW5kSXRlbSwgdXBkYXRlcikge1xuICB2YXIgZGF0YSA9IGxlZ2VuZEl0ZW0uZGF0YSxcbiAgICAgIHNlbGVjdEFibGUgPSBsZWdlbmRJdGVtLnNlbGVjdEFibGUsXG4gICAgICBhbmltYXRpb25DdXJ2ZSA9IGxlZ2VuZEl0ZW0uYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZSA9IGxlZ2VuZEl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBsZWdlbmRJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uIChpdGVtLCBpKSB7XG4gICAgcmV0dXJuICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkoe1xuICAgICAgbmFtZTogaXRlbS5pY29uID09PSAnbGluZScgPyAnbGluZUljb24nIDogJ3JlY3QnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IGxlZ2VuZEl0ZW0uc2hvdyxcbiAgICAgIGhvdmVyOiBzZWxlY3RBYmxlLFxuICAgICAgY2xpY2s6IHNlbGVjdEFibGUsXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0SWNvblNoYXBlKGxlZ2VuZEl0ZW0sIGkpLFxuICAgICAgc3R5bGU6IGdldEljb25TdHlsZShsZWdlbmRJdGVtLCBpKVxuICAgIH0sIFwiY2xpY2tcIiwgY3JlYXRlQ2xpY2tDYWxsQmFjayhsZWdlbmRJdGVtLCBpLCB1cGRhdGVyKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRJY29uU2hhcGUobGVnZW5kSXRlbSwgaSkge1xuICB2YXIgZGF0YSA9IGxlZ2VuZEl0ZW0uZGF0YSxcbiAgICAgIGljb25XaWR0aCA9IGxlZ2VuZEl0ZW0uaWNvbldpZHRoLFxuICAgICAgaWNvbkhlaWdodCA9IGxlZ2VuZEl0ZW0uaWNvbkhlaWdodDtcblxuICB2YXIgX2RhdGEkaSRpY29uUG9zaXRpb24gPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoZGF0YVtpXS5pY29uUG9zaXRpb24sIDIpLFxuICAgICAgeCA9IF9kYXRhJGkkaWNvblBvc2l0aW9uWzBdLFxuICAgICAgeSA9IF9kYXRhJGkkaWNvblBvc2l0aW9uWzFdO1xuXG4gIHZhciBoYWxmSWNvbkhlaWdodCA9IGljb25IZWlnaHQgLyAyO1xuICByZXR1cm4ge1xuICAgIHg6IHgsXG4gICAgeTogeSAtIGhhbGZJY29uSGVpZ2h0LFxuICAgIHc6IGljb25XaWR0aCxcbiAgICBoOiBpY29uSGVpZ2h0XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldEljb25TdHlsZShsZWdlbmRJdGVtLCBpKSB7XG4gIHZhciBkYXRhID0gbGVnZW5kSXRlbS5kYXRhLFxuICAgICAgaWNvblN0eWxlID0gbGVnZW5kSXRlbS5pY29uU3R5bGUsXG4gICAgICBpY29uVW5zZWxlY3RlZFN0eWxlID0gbGVnZW5kSXRlbS5pY29uVW5zZWxlY3RlZFN0eWxlO1xuICB2YXIgX2RhdGEkaSA9IGRhdGFbaV0sXG4gICAgICBzdGF0dXMgPSBfZGF0YSRpLnN0YXR1cyxcbiAgICAgIGNvbG9yID0gX2RhdGEkaS5jb2xvcjtcbiAgdmFyIHN0eWxlID0gc3RhdHVzID8gaWNvblN0eWxlIDogaWNvblVuc2VsZWN0ZWRTdHlsZTtcbiAgcmV0dXJuICgwLCBfdXRpbDIuZGVlcE1lcmdlKSh7XG4gICAgZmlsbDogY29sb3JcbiAgfSwgc3R5bGUpO1xufVxuXG5mdW5jdGlvbiBnZXRUZXh0Q29uZmlnKGxlZ2VuZEl0ZW0sIHVwZGF0ZXIpIHtcbiAgdmFyIGRhdGEgPSBsZWdlbmRJdGVtLmRhdGEsXG4gICAgICBzZWxlY3RBYmxlID0gbGVnZW5kSXRlbS5zZWxlY3RBYmxlLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSBsZWdlbmRJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBsZWdlbmRJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gbGVnZW5kSXRlbS5yTGV2ZWw7XG4gIHJldHVybiBkYXRhLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICd0ZXh0JyxcbiAgICAgIGluZGV4OiByTGV2ZWwsXG4gICAgICB2aXNpYmxlOiBsZWdlbmRJdGVtLnNob3csXG4gICAgICBob3Zlcjogc2VsZWN0QWJsZSxcbiAgICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICAgIGhvdmVyUmVjdDogZ2V0VGV4dEhvdmVyUmVjdChsZWdlbmRJdGVtLCBpKSxcbiAgICAgIHNoYXBlOiBnZXRUZXh0U2hhcGUobGVnZW5kSXRlbSwgaSksXG4gICAgICBzdHlsZTogZ2V0VGV4dFN0eWxlKGxlZ2VuZEl0ZW0sIGkpLFxuICAgICAgY2xpY2s6IGNyZWF0ZUNsaWNrQ2FsbEJhY2sobGVnZW5kSXRlbSwgaSwgdXBkYXRlcilcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0VGV4dFNoYXBlKGxlZ2VuZEl0ZW0sIGkpIHtcbiAgdmFyIF9sZWdlbmRJdGVtJGRhdGEkaSA9IGxlZ2VuZEl0ZW0uZGF0YVtpXSxcbiAgICAgIHRleHRQb3NpdGlvbiA9IF9sZWdlbmRJdGVtJGRhdGEkaS50ZXh0UG9zaXRpb24sXG4gICAgICBuYW1lID0gX2xlZ2VuZEl0ZW0kZGF0YSRpLm5hbWU7XG4gIHJldHVybiB7XG4gICAgY29udGVudDogbmFtZSxcbiAgICBwb3NpdGlvbjogdGV4dFBvc2l0aW9uXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFRleHRTdHlsZShsZWdlbmRJdGVtLCBpKSB7XG4gIHZhciB0ZXh0U3R5bGUgPSBsZWdlbmRJdGVtLnRleHRTdHlsZSxcbiAgICAgIHRleHRVbnNlbGVjdGVkU3R5bGUgPSBsZWdlbmRJdGVtLnRleHRVbnNlbGVjdGVkU3R5bGU7XG4gIHZhciBfbGVnZW5kSXRlbSRkYXRhJGkyID0gbGVnZW5kSXRlbS5kYXRhW2ldLFxuICAgICAgc3RhdHVzID0gX2xlZ2VuZEl0ZW0kZGF0YSRpMi5zdGF0dXMsXG4gICAgICBhbGlnbiA9IF9sZWdlbmRJdGVtJGRhdGEkaTIuYWxpZ247XG4gIHZhciBzdHlsZSA9IHN0YXR1cyA/IHRleHRTdHlsZSA6IHRleHRVbnNlbGVjdGVkU3R5bGU7XG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoKDAsIF91dGlsLmRlZXBDbG9uZSkoc3R5bGUsIHRydWUpLCBhbGlnbik7XG59XG5cbmZ1bmN0aW9uIGdldFRleHRIb3ZlclJlY3QobGVnZW5kSXRlbSwgaSkge1xuICB2YXIgdGV4dFN0eWxlID0gbGVnZW5kSXRlbS50ZXh0U3R5bGUsXG4gICAgICB0ZXh0VW5zZWxlY3RlZFN0eWxlID0gbGVnZW5kSXRlbS50ZXh0VW5zZWxlY3RlZFN0eWxlO1xuXG4gIHZhciBfbGVnZW5kSXRlbSRkYXRhJGkzID0gbGVnZW5kSXRlbS5kYXRhW2ldLFxuICAgICAgc3RhdHVzID0gX2xlZ2VuZEl0ZW0kZGF0YSRpMy5zdGF0dXMsXG4gICAgICBfbGVnZW5kSXRlbSRkYXRhJGkzJHQgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX2xlZ2VuZEl0ZW0kZGF0YSRpMy50ZXh0UG9zaXRpb24sIDIpLFxuICAgICAgeCA9IF9sZWdlbmRJdGVtJGRhdGEkaTMkdFswXSxcbiAgICAgIHkgPSBfbGVnZW5kSXRlbSRkYXRhJGkzJHRbMV0sXG4gICAgICB0ZXh0V2lkdGggPSBfbGVnZW5kSXRlbSRkYXRhJGkzLnRleHRXaWR0aDtcblxuICB2YXIgc3R5bGUgPSBzdGF0dXMgPyB0ZXh0U3R5bGUgOiB0ZXh0VW5zZWxlY3RlZFN0eWxlO1xuICB2YXIgZm9udFNpemUgPSBzdHlsZS5mb250U2l6ZTtcbiAgcmV0dXJuIFt4LCB5IC0gZm9udFNpemUgLyAyLCB0ZXh0V2lkdGgsIGZvbnRTaXplXTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2xpY2tDYWxsQmFjayhsZWdlbmRJdGVtLCBpbmRleCwgdXBkYXRlcikge1xuICB2YXIgbmFtZSA9IGxlZ2VuZEl0ZW0uZGF0YVtpbmRleF0ubmFtZTtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgX3VwZGF0ZXIkY2hhcnQgPSB1cGRhdGVyLmNoYXJ0LFxuICAgICAgICBsZWdlbmRTdGF0dXMgPSBfdXBkYXRlciRjaGFydC5sZWdlbmRTdGF0dXMsXG4gICAgICAgIG9wdGlvbiA9IF91cGRhdGVyJGNoYXJ0Lm9wdGlvbjtcbiAgICB2YXIgc3RhdHVzID0gIWxlZ2VuZFN0YXR1c1tpbmRleF07XG4gICAgdmFyIGNoYW5nZSA9IG9wdGlvbi5zZXJpZXMuZmluZChmdW5jdGlvbiAoX3JlZjkpIHtcbiAgICAgIHZhciBzbiA9IF9yZWY5Lm5hbWU7XG4gICAgICByZXR1cm4gc24gPT09IG5hbWU7XG4gICAgfSk7XG4gICAgY2hhbmdlLnNob3cgPSBzdGF0dXM7XG4gICAgbGVnZW5kU3RhdHVzW2luZGV4XSA9IHN0YXR1cztcbiAgICB1cGRhdGVyLmNoYXJ0LnNldE9wdGlvbihvcHRpb24pO1xuICB9O1xufSIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMubGluZSA9IGxpbmU7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX2NvbmZpZyA9IHJlcXVpcmUoXCIuLi9jb25maWdcIik7XG5cbnZhciBfYmV6aWVyQ3VydmUgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAamlhbWluZ2hpL2Jlemllci1jdXJ2ZVwiKSk7XG5cbnZhciBfdXRpbCA9IHJlcXVpcmUoXCIuLi91dGlsXCIpO1xuXG5mdW5jdGlvbiBvd25LZXlzKG9iamVjdCwgZW51bWVyYWJsZU9ubHkpIHsgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpOyBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykgeyB2YXIgc3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqZWN0KTsgaWYgKGVudW1lcmFibGVPbmx5KSBzeW1ib2xzID0gc3ltYm9scy5maWx0ZXIoZnVuY3Rpb24gKHN5bSkgeyByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHN5bSkuZW51bWVyYWJsZTsgfSk7IGtleXMucHVzaC5hcHBseShrZXlzLCBzeW1ib2xzKTsgfSByZXR1cm4ga2V5czsgfVxuXG5mdW5jdGlvbiBfb2JqZWN0U3ByZWFkKHRhcmdldCkgeyBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgeyB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldICE9IG51bGwgPyBhcmd1bWVudHNbaV0gOiB7fTsgaWYgKGkgJSAyKSB7IG93bktleXMoc291cmNlLCB0cnVlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgKDAsIF9kZWZpbmVQcm9wZXJ0eTJbXCJkZWZhdWx0XCJdKSh0YXJnZXQsIGtleSwgc291cmNlW2tleV0pOyB9KTsgfSBlbHNlIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycykgeyBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKHNvdXJjZSkpOyB9IGVsc2UgeyBvd25LZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIGtleSkpOyB9KTsgfSB9IHJldHVybiB0YXJnZXQ7IH1cblxudmFyIHBvbHlsaW5lVG9CZXppZXJDdXJ2ZSA9IF9iZXppZXJDdXJ2ZVtcImRlZmF1bHRcIl0ucG9seWxpbmVUb0JlemllckN1cnZlLFxuICAgIGdldEJlemllckN1cnZlTGVuZ3RoID0gX2JlemllckN1cnZlW1wiZGVmYXVsdFwiXS5nZXRCZXppZXJDdXJ2ZUxlbmd0aDtcblxuZnVuY3Rpb24gbGluZShjaGFydCkge1xuICB2YXIgb3B0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcbiAgdmFyIHhBeGlzID0gb3B0aW9uLnhBeGlzLFxuICAgICAgeUF4aXMgPSBvcHRpb24ueUF4aXMsXG4gICAgICBzZXJpZXMgPSBvcHRpb24uc2VyaWVzO1xuICB2YXIgbGluZXMgPSBbXTtcblxuICBpZiAoeEF4aXMgJiYgeUF4aXMgJiYgc2VyaWVzKSB7XG4gICAgbGluZXMgPSAoMCwgX3V0aWwuaW5pdE5lZWRTZXJpZXMpKHNlcmllcywgX2NvbmZpZy5saW5lQ29uZmlnLCAnbGluZScpO1xuICAgIGxpbmVzID0gY2FsY0xpbmVzUG9zaXRpb24obGluZXMsIGNoYXJ0KTtcbiAgfVxuXG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGxpbmVzLFxuICAgIGtleTogJ2xpbmVBcmVhJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0TGluZUFyZWFDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRMaW5lQXJlYUNvbmZpZyxcbiAgICBiZWZvcmVVcGRhdGU6IGJlZm9yZVVwZGF0ZUxpbmVBbmRBcmVhLFxuICAgIGJlZm9yZUNoYW5nZTogYmVmb3JlQ2hhbmdlTGluZUFuZEFyZWFcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGxpbmVzLFxuICAgIGtleTogJ2xpbmUnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRMaW5lQ29uZmlnLFxuICAgIGdldFN0YXJ0R3JhcGhDb25maWc6IGdldFN0YXJ0TGluZUNvbmZpZyxcbiAgICBiZWZvcmVVcGRhdGU6IGJlZm9yZVVwZGF0ZUxpbmVBbmRBcmVhLFxuICAgIGJlZm9yZUNoYW5nZTogYmVmb3JlQ2hhbmdlTGluZUFuZEFyZWFcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGxpbmVzLFxuICAgIGtleTogJ2xpbmVQb2ludCcsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFBvaW50Q29uZmlnLFxuICAgIGdldFN0YXJ0R3JhcGhDb25maWc6IGdldFN0YXJ0UG9pbnRDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IGxpbmVzLFxuICAgIGtleTogJ2xpbmVMYWJlbCcsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldExhYmVsQ29uZmlnXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjYWxjTGluZXNQb3NpdGlvbihsaW5lcywgY2hhcnQpIHtcbiAgdmFyIGF4aXNEYXRhID0gY2hhcnQuYXhpc0RhdGE7XG4gIHJldHVybiBsaW5lcy5tYXAoZnVuY3Rpb24gKGxpbmVJdGVtKSB7XG4gICAgdmFyIGxpbmVEYXRhID0gKDAsIF91dGlsLm1lcmdlU2FtZVN0YWNrRGF0YSkobGluZUl0ZW0sIGxpbmVzKTtcbiAgICBsaW5lRGF0YSA9IG1lcmdlTm9uTnVtYmVyKGxpbmVJdGVtLCBsaW5lRGF0YSk7XG4gICAgdmFyIGxpbmVBeGlzID0gZ2V0TGluZUF4aXMobGluZUl0ZW0sIGF4aXNEYXRhKTtcbiAgICB2YXIgbGluZVBvc2l0aW9uID0gZ2V0TGluZVBvc2l0aW9uKGxpbmVEYXRhLCBsaW5lQXhpcyk7XG4gICAgdmFyIGxpbmVGaWxsQm90dG9tUG9zID0gZ2V0TGluZUZpbGxCb3R0b21Qb3MobGluZUF4aXMpO1xuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkKHt9LCBsaW5lSXRlbSwge1xuICAgICAgbGluZVBvc2l0aW9uOiBsaW5lUG9zaXRpb24uZmlsdGVyKGZ1bmN0aW9uIChwKSB7XG4gICAgICAgIHJldHVybiBwO1xuICAgICAgfSksXG4gICAgICBsaW5lRmlsbEJvdHRvbVBvczogbGluZUZpbGxCb3R0b21Qb3NcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG1lcmdlTm9uTnVtYmVyKGxpbmVJdGVtLCBsaW5lRGF0YSkge1xuICB2YXIgZGF0YSA9IGxpbmVJdGVtLmRhdGE7XG4gIHJldHVybiBsaW5lRGF0YS5tYXAoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICByZXR1cm4gdHlwZW9mIGRhdGFbaV0gPT09ICdudW1iZXInID8gdiA6IG51bGw7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRMaW5lQXhpcyhsaW5lLCBheGlzRGF0YSkge1xuICB2YXIgeEF4aXNJbmRleCA9IGxpbmUueEF4aXNJbmRleCxcbiAgICAgIHlBeGlzSW5kZXggPSBsaW5lLnlBeGlzSW5kZXg7XG4gIHZhciB4QXhpcyA9IGF4aXNEYXRhLmZpbmQoZnVuY3Rpb24gKF9yZWYpIHtcbiAgICB2YXIgYXhpcyA9IF9yZWYuYXhpcyxcbiAgICAgICAgaW5kZXggPSBfcmVmLmluZGV4O1xuICAgIHJldHVybiBheGlzID09PSAneCcgJiYgaW5kZXggPT09IHhBeGlzSW5kZXg7XG4gIH0pO1xuICB2YXIgeUF4aXMgPSBheGlzRGF0YS5maW5kKGZ1bmN0aW9uIChfcmVmMikge1xuICAgIHZhciBheGlzID0gX3JlZjIuYXhpcyxcbiAgICAgICAgaW5kZXggPSBfcmVmMi5pbmRleDtcbiAgICByZXR1cm4gYXhpcyA9PT0gJ3knICYmIGluZGV4ID09PSB5QXhpc0luZGV4O1xuICB9KTtcbiAgcmV0dXJuIFt4QXhpcywgeUF4aXNdO1xufVxuXG5mdW5jdGlvbiBnZXRMaW5lUG9zaXRpb24obGluZURhdGEsIGxpbmVBeGlzKSB7XG4gIHZhciB2YWx1ZUF4aXNJbmRleCA9IGxpbmVBeGlzLmZpbmRJbmRleChmdW5jdGlvbiAoX3JlZjMpIHtcbiAgICB2YXIgZGF0YSA9IF9yZWYzLmRhdGE7XG4gICAgcmV0dXJuIGRhdGEgPT09ICd2YWx1ZSc7XG4gIH0pO1xuICB2YXIgdmFsdWVBeGlzID0gbGluZUF4aXNbdmFsdWVBeGlzSW5kZXhdO1xuICB2YXIgbGFiZWxBeGlzID0gbGluZUF4aXNbMSAtIHZhbHVlQXhpc0luZGV4XTtcbiAgdmFyIGxpbmVQb3NpdGlvbiA9IHZhbHVlQXhpcy5saW5lUG9zaXRpb24sXG4gICAgICBheGlzID0gdmFsdWVBeGlzLmF4aXM7XG4gIHZhciB0aWNrUG9zaXRpb24gPSBsYWJlbEF4aXMudGlja1Bvc2l0aW9uO1xuICB2YXIgdGlja051bSA9IHRpY2tQb3NpdGlvbi5sZW5ndGg7XG4gIHZhciB2YWx1ZUF4aXNQb3NJbmRleCA9IGF4aXMgPT09ICd4JyA/IDAgOiAxO1xuICB2YXIgdmFsdWVBeGlzU3RhcnRQb3MgPSBsaW5lUG9zaXRpb25bMF1bdmFsdWVBeGlzUG9zSW5kZXhdO1xuICB2YXIgdmFsdWVBeGlzRW5kUG9zID0gbGluZVBvc2l0aW9uWzFdW3ZhbHVlQXhpc1Bvc0luZGV4XTtcbiAgdmFyIHZhbHVlQXhpc1Bvc01pbnVzID0gdmFsdWVBeGlzRW5kUG9zIC0gdmFsdWVBeGlzU3RhcnRQb3M7XG4gIHZhciBtYXhWYWx1ZSA9IHZhbHVlQXhpcy5tYXhWYWx1ZSxcbiAgICAgIG1pblZhbHVlID0gdmFsdWVBeGlzLm1pblZhbHVlO1xuICB2YXIgdmFsdWVNaW51cyA9IG1heFZhbHVlIC0gbWluVmFsdWU7XG4gIHZhciBwb3NpdGlvbiA9IG5ldyBBcnJheSh0aWNrTnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgdmFyIHYgPSBsaW5lRGF0YVtpXTtcbiAgICBpZiAodHlwZW9mIHYgIT09ICdudW1iZXInKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgdmFsdWVQZXJjZW50ID0gKHYgLSBtaW5WYWx1ZSkgLyB2YWx1ZU1pbnVzO1xuICAgIGlmICh2YWx1ZU1pbnVzID09PSAwKSB2YWx1ZVBlcmNlbnQgPSAwO1xuICAgIHJldHVybiB2YWx1ZVBlcmNlbnQgKiB2YWx1ZUF4aXNQb3NNaW51cyArIHZhbHVlQXhpc1N0YXJ0UG9zO1xuICB9KTtcbiAgcmV0dXJuIHBvc2l0aW9uLm1hcChmdW5jdGlvbiAodlBvcywgaSkge1xuICAgIGlmIChpID49IHRpY2tOdW0gfHwgdHlwZW9mIHZQb3MgIT09ICdudW1iZXInKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgcG9zID0gW3ZQb3MsIHRpY2tQb3NpdGlvbltpXVsxIC0gdmFsdWVBeGlzUG9zSW5kZXhdXTtcbiAgICBpZiAodmFsdWVBeGlzUG9zSW5kZXggPT09IDApIHJldHVybiBwb3M7XG4gICAgcG9zLnJldmVyc2UoKTtcbiAgICByZXR1cm4gcG9zO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0TGluZUZpbGxCb3R0b21Qb3MobGluZUF4aXMpIHtcbiAgdmFyIHZhbHVlQXhpcyA9IGxpbmVBeGlzLmZpbmQoZnVuY3Rpb24gKF9yZWY0KSB7XG4gICAgdmFyIGRhdGEgPSBfcmVmNC5kYXRhO1xuICAgIHJldHVybiBkYXRhID09PSAndmFsdWUnO1xuICB9KTtcbiAgdmFyIGF4aXMgPSB2YWx1ZUF4aXMuYXhpcyxcbiAgICAgIGxpbmVQb3NpdGlvbiA9IHZhbHVlQXhpcy5saW5lUG9zaXRpb24sXG4gICAgICBtaW5WYWx1ZSA9IHZhbHVlQXhpcy5taW5WYWx1ZSxcbiAgICAgIG1heFZhbHVlID0gdmFsdWVBeGlzLm1heFZhbHVlO1xuICB2YXIgY2hhbmdlSW5kZXggPSBheGlzID09PSAneCcgPyAwIDogMTtcbiAgdmFyIGNoYW5nZVZhbHVlID0gbGluZVBvc2l0aW9uWzBdW2NoYW5nZUluZGV4XTtcblxuICBpZiAobWluVmFsdWUgPCAwICYmIG1heFZhbHVlID4gMCkge1xuICAgIHZhciB2YWx1ZU1pbnVzID0gbWF4VmFsdWUgLSBtaW5WYWx1ZTtcbiAgICB2YXIgcG9zTWludXMgPSBNYXRoLmFicyhsaW5lUG9zaXRpb25bMF1bY2hhbmdlSW5kZXhdIC0gbGluZVBvc2l0aW9uWzFdW2NoYW5nZUluZGV4XSk7XG4gICAgdmFyIG9mZnNldCA9IE1hdGguYWJzKG1pblZhbHVlKSAvIHZhbHVlTWludXMgKiBwb3NNaW51cztcbiAgICBpZiAoYXhpcyA9PT0gJ3knKSBvZmZzZXQgKj0gLTE7XG4gICAgY2hhbmdlVmFsdWUgKz0gb2Zmc2V0O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjaGFuZ2VJbmRleDogY2hhbmdlSW5kZXgsXG4gICAgY2hhbmdlVmFsdWU6IGNoYW5nZVZhbHVlXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldExpbmVBcmVhQ29uZmlnKGxpbmVJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGxpbmVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBsaW5lSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIGxpbmVGaWxsQm90dG9tUG9zID0gbGluZUl0ZW0ubGluZUZpbGxCb3R0b21Qb3MsXG4gICAgICByTGV2ZWwgPSBsaW5lSXRlbS5yTGV2ZWw7XG4gIHJldHVybiBbe1xuICAgIG5hbWU6IGdldExpbmVHcmFwaE5hbWUobGluZUl0ZW0pLFxuICAgIGluZGV4OiByTGV2ZWwsXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICB2aXNpYmxlOiBsaW5lSXRlbS5saW5lQXJlYS5zaG93LFxuICAgIGxpbmVGaWxsQm90dG9tUG9zOiBsaW5lRmlsbEJvdHRvbVBvcyxcbiAgICBzaGFwZTogZ2V0TGluZUFuZEFyZWFTaGFwZShsaW5lSXRlbSksXG4gICAgc3R5bGU6IGdldExpbmVBcmVhU3R5bGUobGluZUl0ZW0pLFxuICAgIGRyYXdlZDogbGluZUFyZWFEcmF3ZWRcbiAgfV07XG59XG5cbmZ1bmN0aW9uIGdldExpbmVBbmRBcmVhU2hhcGUobGluZUl0ZW0pIHtcbiAgdmFyIGxpbmVQb3NpdGlvbiA9IGxpbmVJdGVtLmxpbmVQb3NpdGlvbjtcbiAgcmV0dXJuIHtcbiAgICBwb2ludHM6IGxpbmVQb3NpdGlvblxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRMaW5lQXJlYVN0eWxlKGxpbmVJdGVtKSB7XG4gIHZhciBsaW5lQXJlYSA9IGxpbmVJdGVtLmxpbmVBcmVhLFxuICAgICAgY29sb3IgPSBsaW5lSXRlbS5jb2xvcjtcbiAgdmFyIGdyYWRpZW50ID0gbGluZUFyZWEuZ3JhZGllbnQsXG4gICAgICBzdHlsZSA9IGxpbmVBcmVhLnN0eWxlO1xuICB2YXIgZmlsbENvbG9yID0gW3N0eWxlLmZpbGwgfHwgY29sb3JdO1xuICB2YXIgZ3JhZGllbnRDb2xvciA9ICgwLCBfdXRpbC5kZWVwTWVyZ2UpKGZpbGxDb2xvciwgZ3JhZGllbnQpO1xuICBpZiAoZ3JhZGllbnRDb2xvci5sZW5ndGggPT09IDEpIGdyYWRpZW50Q29sb3IucHVzaChncmFkaWVudENvbG9yWzBdKTtcbiAgdmFyIGdyYWRpZW50UGFyYW1zID0gZ2V0R3JhZGllbnRQYXJhbXMobGluZUl0ZW0pO1xuICBzdHlsZSA9IF9vYmplY3RTcHJlYWQoe30sIHN0eWxlLCB7XG4gICAgc3Ryb2tlOiAncmdiYSgwLCAwLCAwLCAwKSdcbiAgfSk7XG4gIHJldHVybiAoMCwgX3V0aWwuZGVlcE1lcmdlKSh7XG4gICAgZ3JhZGllbnRDb2xvcjogZ3JhZGllbnRDb2xvcixcbiAgICBncmFkaWVudFBhcmFtczogZ3JhZGllbnRQYXJhbXMsXG4gICAgZ3JhZGllbnRUeXBlOiAnbGluZWFyJyxcbiAgICBncmFkaWVudFdpdGg6ICdmaWxsJ1xuICB9LCBzdHlsZSk7XG59XG5cbmZ1bmN0aW9uIGdldEdyYWRpZW50UGFyYW1zKGxpbmVJdGVtKSB7XG4gIHZhciBsaW5lRmlsbEJvdHRvbVBvcyA9IGxpbmVJdGVtLmxpbmVGaWxsQm90dG9tUG9zLFxuICAgICAgbGluZVBvc2l0aW9uID0gbGluZUl0ZW0ubGluZVBvc2l0aW9uO1xuICB2YXIgY2hhbmdlSW5kZXggPSBsaW5lRmlsbEJvdHRvbVBvcy5jaGFuZ2VJbmRleCxcbiAgICAgIGNoYW5nZVZhbHVlID0gbGluZUZpbGxCb3R0b21Qb3MuY2hhbmdlVmFsdWU7XG4gIHZhciBtYWluUG9zID0gbGluZVBvc2l0aW9uLm1hcChmdW5jdGlvbiAocCkge1xuICAgIHJldHVybiBwW2NoYW5nZUluZGV4XTtcbiAgfSk7XG4gIHZhciBtYXhQb3MgPSBNYXRoLm1heC5hcHBseShNYXRoLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKG1haW5Qb3MpKTtcbiAgdmFyIG1pblBvcyA9IE1hdGgubWluLmFwcGx5KE1hdGgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobWFpblBvcykpO1xuICB2YXIgYmVnaW5Qb3MgPSBtYXhQb3M7XG4gIGlmIChjaGFuZ2VJbmRleCA9PT0gMSkgYmVnaW5Qb3MgPSBtaW5Qb3M7XG5cbiAgaWYgKGNoYW5nZUluZGV4ID09PSAxKSB7XG4gICAgcmV0dXJuIFswLCBiZWdpblBvcywgMCwgY2hhbmdlVmFsdWVdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbYmVnaW5Qb3MsIDAsIGNoYW5nZVZhbHVlLCAwXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBsaW5lQXJlYURyYXdlZChfcmVmNSwgX3JlZjYpIHtcbiAgdmFyIGxpbmVGaWxsQm90dG9tUG9zID0gX3JlZjUubGluZUZpbGxCb3R0b21Qb3MsXG4gICAgICBzaGFwZSA9IF9yZWY1LnNoYXBlO1xuICB2YXIgY3R4ID0gX3JlZjYuY3R4O1xuICB2YXIgcG9pbnRzID0gc2hhcGUucG9pbnRzO1xuICB2YXIgY2hhbmdlSW5kZXggPSBsaW5lRmlsbEJvdHRvbVBvcy5jaGFuZ2VJbmRleCxcbiAgICAgIGNoYW5nZVZhbHVlID0gbGluZUZpbGxCb3R0b21Qb3MuY2hhbmdlVmFsdWU7XG4gIHZhciBsaW5lUG9pbnQxID0gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShwb2ludHNbcG9pbnRzLmxlbmd0aCAtIDFdKTtcbiAgdmFyIGxpbmVQb2ludDIgPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHBvaW50c1swXSk7XG4gIGxpbmVQb2ludDFbY2hhbmdlSW5kZXhdID0gY2hhbmdlVmFsdWU7XG4gIGxpbmVQb2ludDJbY2hhbmdlSW5kZXhdID0gY2hhbmdlVmFsdWU7XG4gIGN0eC5saW5lVG8uYXBwbHkoY3R4LCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGxpbmVQb2ludDEpKTtcbiAgY3R4LmxpbmVUby5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobGluZVBvaW50MikpO1xuICBjdHguY2xvc2VQYXRoKCk7XG4gIGN0eC5maWxsKCk7XG59XG5cbmZ1bmN0aW9uIGdldFN0YXJ0TGluZUFyZWFDb25maWcobGluZUl0ZW0pIHtcbiAgdmFyIGNvbmZpZyA9IGdldExpbmVBcmVhQ29uZmlnKGxpbmVJdGVtKVswXTtcblxuICB2YXIgc3R5bGUgPSBfb2JqZWN0U3ByZWFkKHt9LCBjb25maWcuc3R5bGUpO1xuXG4gIHN0eWxlLm9wYWNpdHkgPSAwO1xuICBjb25maWcuc3R5bGUgPSBzdHlsZTtcbiAgcmV0dXJuIFtjb25maWddO1xufVxuXG5mdW5jdGlvbiBiZWZvcmVVcGRhdGVMaW5lQW5kQXJlYShncmFwaHMsIGxpbmVJdGVtLCBpLCB1cGRhdGVyKSB7XG4gIHZhciBjYWNoZSA9IGdyYXBoc1tpXTtcbiAgaWYgKCFjYWNoZSkgcmV0dXJuO1xuICB2YXIgY3VycmVudE5hbWUgPSBnZXRMaW5lR3JhcGhOYW1lKGxpbmVJdGVtKTtcbiAgdmFyIHJlbmRlciA9IHVwZGF0ZXIuY2hhcnQucmVuZGVyO1xuICB2YXIgbmFtZSA9IGNhY2hlWzBdLm5hbWU7XG4gIHZhciBkZWxBbGwgPSBjdXJyZW50TmFtZSAhPT0gbmFtZTtcbiAgaWYgKCFkZWxBbGwpIHJldHVybjtcbiAgY2FjaGUuZm9yRWFjaChmdW5jdGlvbiAoZykge1xuICAgIHJldHVybiByZW5kZXIuZGVsR3JhcGgoZyk7XG4gIH0pO1xuICBncmFwaHNbaV0gPSBudWxsO1xufVxuXG5mdW5jdGlvbiBiZWZvcmVDaGFuZ2VMaW5lQW5kQXJlYShncmFwaCwgY29uZmlnKSB7XG4gIHZhciBwb2ludHMgPSBjb25maWcuc2hhcGUucG9pbnRzO1xuICB2YXIgZ3JhcGhQb2ludHMgPSBncmFwaC5zaGFwZS5wb2ludHM7XG4gIHZhciBncmFwaFBvaW50c051bSA9IGdyYXBoUG9pbnRzLmxlbmd0aDtcbiAgdmFyIHBvaW50c051bSA9IHBvaW50cy5sZW5ndGg7XG5cbiAgaWYgKHBvaW50c051bSA+IGdyYXBoUG9pbnRzTnVtKSB7XG4gICAgdmFyIGxhc3RQb2ludCA9IGdyYXBoUG9pbnRzLnNsaWNlKC0xKVswXTtcbiAgICB2YXIgbmV3QWRkUG9pbnRzID0gbmV3IEFycmF5KHBvaW50c051bSAtIGdyYXBoUG9pbnRzTnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vKSB7XG4gICAgICByZXR1cm4gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShsYXN0UG9pbnQpO1xuICAgIH0pO1xuICAgIGdyYXBoUG9pbnRzLnB1c2guYXBwbHkoZ3JhcGhQb2ludHMsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobmV3QWRkUG9pbnRzKSk7XG4gIH0gZWxzZSBpZiAocG9pbnRzTnVtIDwgZ3JhcGhQb2ludHNOdW0pIHtcbiAgICBncmFwaFBvaW50cy5zcGxpY2UocG9pbnRzTnVtKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRMaW5lQ29uZmlnKGxpbmVJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGxpbmVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBsaW5lSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGxpbmVJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIFt7XG4gICAgbmFtZTogZ2V0TGluZUdyYXBoTmFtZShsaW5lSXRlbSksXG4gICAgaW5kZXg6IHJMZXZlbCArIDEsXG4gICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICBzaGFwZTogZ2V0TGluZUFuZEFyZWFTaGFwZShsaW5lSXRlbSksXG4gICAgc3R5bGU6IGdldExpbmVTdHlsZShsaW5lSXRlbSlcbiAgfV07XG59XG5cbmZ1bmN0aW9uIGdldExpbmVHcmFwaE5hbWUobGluZUl0ZW0pIHtcbiAgdmFyIHNtb290aCA9IGxpbmVJdGVtLnNtb290aDtcbiAgcmV0dXJuIHNtb290aCA/ICdzbW9vdGhsaW5lJyA6ICdwb2x5bGluZSc7XG59XG5cbmZ1bmN0aW9uIGdldExpbmVTdHlsZShsaW5lSXRlbSkge1xuICB2YXIgbGluZVN0eWxlID0gbGluZUl0ZW0ubGluZVN0eWxlLFxuICAgICAgY29sb3IgPSBsaW5lSXRlbS5jb2xvcixcbiAgICAgIHNtb290aCA9IGxpbmVJdGVtLnNtb290aCxcbiAgICAgIGxpbmVQb3NpdGlvbiA9IGxpbmVJdGVtLmxpbmVQb3NpdGlvbjtcbiAgdmFyIGxpbmVMZW5ndGggPSBnZXRMaW5lTGVuZ3RoKGxpbmVQb3NpdGlvbiwgc21vb3RoKTtcbiAgcmV0dXJuICgwLCBfdXRpbC5kZWVwTWVyZ2UpKHtcbiAgICBzdHJva2U6IGNvbG9yLFxuICAgIGxpbmVEYXNoOiBbbGluZUxlbmd0aCwgMF1cbiAgfSwgbGluZVN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0TGluZUxlbmd0aChwb2ludHMpIHtcbiAgdmFyIHNtb290aCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7XG4gIGlmICghc21vb3RoKSByZXR1cm4gKDAsIF91dGlsLmdldFBvbHlsaW5lTGVuZ3RoKShwb2ludHMpO1xuICB2YXIgY3VydmUgPSBwb2x5bGluZVRvQmV6aWVyQ3VydmUocG9pbnRzKTtcbiAgcmV0dXJuIGdldEJlemllckN1cnZlTGVuZ3RoKGN1cnZlKTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRMaW5lQ29uZmlnKGxpbmVJdGVtKSB7XG4gIHZhciBsaW5lRGFzaCA9IGxpbmVJdGVtLmxpbmVTdHlsZS5saW5lRGFzaDtcbiAgdmFyIGNvbmZpZyA9IGdldExpbmVDb25maWcobGluZUl0ZW0pWzBdO1xuICB2YXIgcmVhbExpbmVEYXNoID0gY29uZmlnLnN0eWxlLmxpbmVEYXNoO1xuXG4gIGlmIChsaW5lRGFzaCkge1xuICAgIHJlYWxMaW5lRGFzaCA9IFswLCAwXTtcbiAgfSBlbHNlIHtcbiAgICByZWFsTGluZURhc2ggPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHJlYWxMaW5lRGFzaCkucmV2ZXJzZSgpO1xuICB9XG5cbiAgY29uZmlnLnN0eWxlLmxpbmVEYXNoID0gcmVhbExpbmVEYXNoO1xuICByZXR1cm4gW2NvbmZpZ107XG59XG5cbmZ1bmN0aW9uIGdldFBvaW50Q29uZmlnKGxpbmVJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IGxpbmVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBsaW5lSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IGxpbmVJdGVtLnJMZXZlbDtcbiAgdmFyIHNoYXBlcyA9IGdldFBvaW50U2hhcGVzKGxpbmVJdGVtKTtcbiAgdmFyIHN0eWxlID0gZ2V0UG9pbnRTdHlsZShsaW5lSXRlbSk7XG4gIHJldHVybiBzaGFwZXMubWFwKGZ1bmN0aW9uIChzaGFwZSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnY2lyY2xlJyxcbiAgICAgIGluZGV4OiByTGV2ZWwgKyAyLFxuICAgICAgdmlzaWJsZTogbGluZUl0ZW0ubGluZVBvaW50LnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogc2hhcGUsXG4gICAgICBzdHlsZTogc3R5bGVcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0UG9pbnRTaGFwZXMobGluZUl0ZW0pIHtcbiAgdmFyIGxpbmVQb3NpdGlvbiA9IGxpbmVJdGVtLmxpbmVQb3NpdGlvbixcbiAgICAgIHJhZGl1cyA9IGxpbmVJdGVtLmxpbmVQb2ludC5yYWRpdXM7XG4gIHJldHVybiBsaW5lUG9zaXRpb24ubWFwKGZ1bmN0aW9uIChfcmVmNykge1xuICAgIHZhciBfcmVmOCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmNywgMiksXG4gICAgICAgIHJ4ID0gX3JlZjhbMF0sXG4gICAgICAgIHJ5ID0gX3JlZjhbMV07XG5cbiAgICByZXR1cm4ge1xuICAgICAgcjogcmFkaXVzLFxuICAgICAgcng6IHJ4LFxuICAgICAgcnk6IHJ5XG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFBvaW50U3R5bGUobGluZUl0ZW0pIHtcbiAgdmFyIGNvbG9yID0gbGluZUl0ZW0uY29sb3IsXG4gICAgICBzdHlsZSA9IGxpbmVJdGVtLmxpbmVQb2ludC5zdHlsZTtcbiAgcmV0dXJuICgwLCBfdXRpbC5kZWVwTWVyZ2UpKHtcbiAgICBzdHJva2U6IGNvbG9yXG4gIH0sIHN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRQb2ludENvbmZpZyhsaW5lSXRlbSkge1xuICB2YXIgY29uZmlncyA9IGdldFBvaW50Q29uZmlnKGxpbmVJdGVtKTtcbiAgY29uZmlncy5mb3JFYWNoKGZ1bmN0aW9uIChjb25maWcpIHtcbiAgICBjb25maWcuc2hhcGUuciA9IDAuMTtcbiAgfSk7XG4gIHJldHVybiBjb25maWdzO1xufVxuXG5mdW5jdGlvbiBnZXRMYWJlbENvbmZpZyhsaW5lSXRlbSkge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBsaW5lSXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gbGluZUl0ZW0uYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSBsaW5lSXRlbS5yTGV2ZWw7XG4gIHZhciBzaGFwZXMgPSBnZXRMYWJlbFNoYXBlcyhsaW5lSXRlbSk7XG4gIHZhciBzdHlsZSA9IGdldExhYmVsU3R5bGUobGluZUl0ZW0pO1xuICByZXR1cm4gc2hhcGVzLm1hcChmdW5jdGlvbiAoc2hhcGUsIGkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ3RleHQnLFxuICAgICAgaW5kZXg6IHJMZXZlbCArIDMsXG4gICAgICB2aXNpYmxlOiBsaW5lSXRlbS5sYWJlbC5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IHNoYXBlLFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsU2hhcGVzKGxpbmVJdGVtKSB7XG4gIHZhciBjb250ZW50cyA9IGZvcm1hdHRlckxhYmVsKGxpbmVJdGVtKTtcbiAgdmFyIHBvc2l0aW9uID0gZ2V0TGFiZWxQb3NpdGlvbihsaW5lSXRlbSk7XG4gIHJldHVybiBjb250ZW50cy5tYXAoZnVuY3Rpb24gKGNvbnRlbnQsIGkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogY29udGVudCxcbiAgICAgIHBvc2l0aW9uOiBwb3NpdGlvbltpXVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRMYWJlbFBvc2l0aW9uKGxpbmVJdGVtKSB7XG4gIHZhciBsaW5lUG9zaXRpb24gPSBsaW5lSXRlbS5saW5lUG9zaXRpb24sXG4gICAgICBsaW5lRmlsbEJvdHRvbVBvcyA9IGxpbmVJdGVtLmxpbmVGaWxsQm90dG9tUG9zLFxuICAgICAgbGFiZWwgPSBsaW5lSXRlbS5sYWJlbDtcbiAgdmFyIHBvc2l0aW9uID0gbGFiZWwucG9zaXRpb24sXG4gICAgICBvZmZzZXQgPSBsYWJlbC5vZmZzZXQ7XG4gIHZhciBjaGFuZ2VJbmRleCA9IGxpbmVGaWxsQm90dG9tUG9zLmNoYW5nZUluZGV4LFxuICAgICAgY2hhbmdlVmFsdWUgPSBsaW5lRmlsbEJvdHRvbVBvcy5jaGFuZ2VWYWx1ZTtcbiAgcmV0dXJuIGxpbmVQb3NpdGlvbi5tYXAoZnVuY3Rpb24gKHBvcykge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIHBvcyA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9zKTtcbiAgICAgIHBvc1tjaGFuZ2VJbmRleF0gPSBjaGFuZ2VWYWx1ZTtcbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPT09ICdjZW50ZXInKSB7XG4gICAgICB2YXIgYm90dG9tID0gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShwb3MpO1xuICAgICAgYm90dG9tW2NoYW5nZUluZGV4XSA9IGNoYW5nZVZhbHVlO1xuICAgICAgcG9zID0gZ2V0Q2VudGVyTGFiZWxQb2ludChwb3MsIGJvdHRvbSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldE9mZnNldGVkUG9pbnQocG9zLCBvZmZzZXQpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0T2Zmc2V0ZWRQb2ludChfcmVmOSwgX3JlZjEwKSB7XG4gIHZhciBfcmVmMTEgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjksIDIpLFxuICAgICAgeCA9IF9yZWYxMVswXSxcbiAgICAgIHkgPSBfcmVmMTFbMV07XG5cbiAgdmFyIF9yZWYxMiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMTAsIDIpLFxuICAgICAgb3ggPSBfcmVmMTJbMF0sXG4gICAgICBveSA9IF9yZWYxMlsxXTtcblxuICByZXR1cm4gW3ggKyBveCwgeSArIG95XTtcbn1cblxuZnVuY3Rpb24gZ2V0Q2VudGVyTGFiZWxQb2ludChfcmVmMTMsIF9yZWYxNCkge1xuICB2YXIgX3JlZjE1ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxMywgMiksXG4gICAgICBheCA9IF9yZWYxNVswXSxcbiAgICAgIGF5ID0gX3JlZjE1WzFdO1xuXG4gIHZhciBfcmVmMTYgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjE0LCAyKSxcbiAgICAgIGJ4ID0gX3JlZjE2WzBdLFxuICAgICAgYnkgPSBfcmVmMTZbMV07XG5cbiAgcmV0dXJuIFsoYXggKyBieCkgLyAyLCAoYXkgKyBieSkgLyAyXTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0dGVyTGFiZWwobGluZUl0ZW0pIHtcbiAgdmFyIGRhdGEgPSBsaW5lSXRlbS5kYXRhLFxuICAgICAgZm9ybWF0dGVyID0gbGluZUl0ZW0ubGFiZWwuZm9ybWF0dGVyO1xuICBkYXRhID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24gKGQpIHtcbiAgICByZXR1cm4gdHlwZW9mIGQgPT09ICdudW1iZXInO1xuICB9KS5tYXAoZnVuY3Rpb24gKGQpIHtcbiAgICByZXR1cm4gZC50b1N0cmluZygpO1xuICB9KTtcbiAgaWYgKCFmb3JtYXR0ZXIpIHJldHVybiBkYXRhO1xuICB2YXIgdHlwZSA9ICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKGZvcm1hdHRlcik7XG4gIGlmICh0eXBlID09PSAnc3RyaW5nJykgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uIChkKSB7XG4gICAgcmV0dXJuIGZvcm1hdHRlci5yZXBsYWNlKCd7dmFsdWV9JywgZCk7XG4gIH0pO1xuICBpZiAodHlwZSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uICh2YWx1ZSwgaW5kZXgpIHtcbiAgICByZXR1cm4gZm9ybWF0dGVyKHtcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIGluZGV4OiBpbmRleFxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsU3R5bGUobGluZUl0ZW0pIHtcbiAgdmFyIGNvbG9yID0gbGluZUl0ZW0uY29sb3IsXG4gICAgICBzdHlsZSA9IGxpbmVJdGVtLmxhYmVsLnN0eWxlO1xuICByZXR1cm4gKDAsIF91dGlsLmRlZXBNZXJnZSkoe1xuICAgIGZpbGw6IGNvbG9yXG4gIH0sIHN0eWxlKTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMubWVyZ2VDb2xvciA9IG1lcmdlQ29sb3I7XG5cbnZhciBfY29uZmlnID0gcmVxdWlyZShcIi4uL2NvbmZpZ1wiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG52YXIgX3V0aWwyID0gcmVxdWlyZShcIi4uL3V0aWxcIik7XG5cbmZ1bmN0aW9uIG1lcmdlQ29sb3IoY2hhcnQpIHtcbiAgdmFyIG9wdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG4gIHZhciBkZWZhdWx0Q29sb3IgPSAoMCwgX3V0aWwuZGVlcENsb25lKShfY29uZmlnLmNvbG9yQ29uZmlnLCB0cnVlKTtcbiAgdmFyIGNvbG9yID0gb3B0aW9uLmNvbG9yLFxuICAgICAgc2VyaWVzID0gb3B0aW9uLnNlcmllcztcbiAgaWYgKCFzZXJpZXMpIHNlcmllcyA9IFtdO1xuICBpZiAoIWNvbG9yKSBjb2xvciA9IFtdO1xuICBvcHRpb24uY29sb3IgPSBjb2xvciA9ICgwLCBfdXRpbDIuZGVlcE1lcmdlKShkZWZhdWx0Q29sb3IsIGNvbG9yKTtcbiAgaWYgKCFzZXJpZXMubGVuZ3RoKSByZXR1cm47XG4gIHZhciBjb2xvck51bSA9IGNvbG9yLmxlbmd0aDtcbiAgc2VyaWVzLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0sIGkpIHtcbiAgICBpZiAoaXRlbS5jb2xvcikgcmV0dXJuO1xuICAgIGl0ZW0uY29sb3IgPSBjb2xvcltpICUgY29sb3JOdW1dO1xuICB9KTtcbiAgdmFyIHBpZXMgPSBzZXJpZXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmKSB7XG4gICAgdmFyIHR5cGUgPSBfcmVmLnR5cGU7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdwaWUnO1xuICB9KTtcbiAgcGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwaWUpIHtcbiAgICByZXR1cm4gcGllLmRhdGEuZm9yRWFjaChmdW5jdGlvbiAoZGksIGkpIHtcbiAgICAgIHJldHVybiBkaS5jb2xvciA9IGNvbG9yW2kgJSBjb2xvck51bV07XG4gICAgfSk7XG4gIH0pO1xuICB2YXIgZ2F1Z2VzID0gc2VyaWVzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjIpIHtcbiAgICB2YXIgdHlwZSA9IF9yZWYyLnR5cGU7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdnYXVnZSc7XG4gIH0pO1xuICBnYXVnZXMuZm9yRWFjaChmdW5jdGlvbiAoZ2F1Z2UpIHtcbiAgICByZXR1cm4gZ2F1Z2UuZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChkaSwgaSkge1xuICAgICAgcmV0dXJuIGRpLmNvbG9yID0gY29sb3JbaSAlIGNvbG9yTnVtXTtcbiAgICB9KTtcbiAgfSk7XG4gIHZhciBiYXJXaXRoSW5kZXBlbmRlbnRDb2xvciA9IHNlcmllcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgdmFyIHR5cGUgPSBfcmVmMy50eXBlLFxuICAgICAgICBpbmRlcGVuZGVudENvbG9yID0gX3JlZjMuaW5kZXBlbmRlbnRDb2xvcjtcbiAgICByZXR1cm4gdHlwZSA9PT0gJ2JhcicgJiYgaW5kZXBlbmRlbnRDb2xvcjtcbiAgfSk7XG4gIGJhcldpdGhJbmRlcGVuZGVudENvbG9yLmZvckVhY2goZnVuY3Rpb24gKGJhcikge1xuICAgIGlmIChiYXIuaW5kZXBlbmRlbnRDb2xvcnMpIHJldHVybjtcbiAgICBiYXIuaW5kZXBlbmRlbnRDb2xvcnMgPSBjb2xvcjtcbiAgfSk7XG59IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5waWUgPSBwaWU7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX3BpZSA9IHJlcXVpcmUoXCIuLi9jb25maWcvcGllXCIpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiQGppYW1pbmdoaS9jLXJlbmRlci9saWIvcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfdXRpbDIgPSByZXF1aXJlKFwiLi4vdXRpbFwiKTtcblxuZnVuY3Rpb24gb3duS2V5cyhvYmplY3QsIGVudW1lcmFibGVPbmx5KSB7IHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTsgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHsgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7IGlmIChlbnVtZXJhYmxlT25seSkgc3ltYm9scyA9IHN5bWJvbHMuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHsgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBzeW0pLmVudW1lcmFibGU7IH0pOyBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7IH0gcmV0dXJuIGtleXM7IH1cblxuZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307IGlmIChpICUgMikgeyBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7ICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTsgfSk7IH0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpIHsgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzb3VyY2UpKTsgfSBlbHNlIHsgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsgfSk7IH0gfSByZXR1cm4gdGFyZ2V0OyB9XG5cbmZ1bmN0aW9uIHBpZShjaGFydCkge1xuICB2YXIgb3B0aW9uID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcbiAgdmFyIHNlcmllcyA9IG9wdGlvbi5zZXJpZXM7XG4gIGlmICghc2VyaWVzKSBzZXJpZXMgPSBbXTtcbiAgdmFyIHBpZXMgPSAoMCwgX3V0aWwyLmluaXROZWVkU2VyaWVzKShzZXJpZXMsIF9waWUucGllQ29uZmlnLCAncGllJyk7XG4gIHBpZXMgPSBjYWxjUGllc0NlbnRlcihwaWVzLCBjaGFydCk7XG4gIHBpZXMgPSBjYWxjUGllc1JhZGl1cyhwaWVzLCBjaGFydCk7XG4gIHBpZXMgPSBjYWxjUm9zZVBpZXNSYWRpdXMocGllcywgY2hhcnQpO1xuICBwaWVzID0gY2FsY1BpZXNQZXJjZW50KHBpZXMpO1xuICBwaWVzID0gY2FsY1BpZXNBbmdsZShwaWVzLCBjaGFydCk7XG4gIHBpZXMgPSBjYWxjUGllc0luc2lkZUxhYmVsUG9zKHBpZXMpO1xuICBwaWVzID0gY2FsY1BpZXNFZGdlQ2VudGVyUG9zKHBpZXMpO1xuICBwaWVzID0gY2FsY1BpZXNPdXRTaWRlTGFiZWxQb3MocGllcyk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IHBpZXMsXG4gICAga2V5OiAncGllJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0UGllQ29uZmlnLFxuICAgIGdldFN0YXJ0R3JhcGhDb25maWc6IGdldFN0YXJ0UGllQ29uZmlnLFxuICAgIGJlZm9yZUNoYW5nZTogYmVmb3JlQ2hhbmdlUGllXG4gIH0pO1xuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiBwaWVzLFxuICAgIGtleTogJ3BpZUluc2lkZUxhYmVsJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0SW5zaWRlTGFiZWxDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IHBpZXMsXG4gICAga2V5OiAncGllT3V0c2lkZUxhYmVsTGluZScsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldE91dHNpZGVMYWJlbExpbmVDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRPdXRzaWRlTGFiZWxMaW5lQ29uZmlnXG4gIH0pO1xuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiBwaWVzLFxuICAgIGtleTogJ3BpZU91dHNpZGVMYWJlbCcsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldE91dHNpZGVMYWJlbENvbmZpZyxcbiAgICBnZXRTdGFydEdyYXBoQ29uZmlnOiBnZXRTdGFydE91dHNpZGVMYWJlbENvbmZpZ1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY2FsY1BpZXNDZW50ZXIocGllcywgY2hhcnQpIHtcbiAgdmFyIGFyZWEgPSBjaGFydC5yZW5kZXIuYXJlYTtcbiAgcGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwaWUpIHtcbiAgICB2YXIgY2VudGVyID0gcGllLmNlbnRlcjtcbiAgICBjZW50ZXIgPSBjZW50ZXIubWFwKGZ1bmN0aW9uIChwb3MsIGkpIHtcbiAgICAgIGlmICh0eXBlb2YgcG9zID09PSAnbnVtYmVyJykgcmV0dXJuIHBvcztcbiAgICAgIHJldHVybiBwYXJzZUludChwb3MpIC8gMTAwICogYXJlYVtpXTtcbiAgICB9KTtcbiAgICBwaWUuY2VudGVyID0gY2VudGVyO1xuICB9KTtcbiAgcmV0dXJuIHBpZXM7XG59XG5cbmZ1bmN0aW9uIGNhbGNQaWVzUmFkaXVzKHBpZXMsIGNoYXJ0KSB7XG4gIHZhciBtYXhSYWRpdXMgPSBNYXRoLm1pbi5hcHBseShNYXRoLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNoYXJ0LnJlbmRlci5hcmVhKSkgLyAyO1xuICBwaWVzLmZvckVhY2goZnVuY3Rpb24gKHBpZSkge1xuICAgIHZhciByYWRpdXMgPSBwaWUucmFkaXVzLFxuICAgICAgICBkYXRhID0gcGllLmRhdGE7XG4gICAgcmFkaXVzID0gZ2V0TnVtYmVyUmFkaXVzKHJhZGl1cywgbWF4UmFkaXVzKTtcbiAgICBkYXRhLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgIHZhciBpdGVtUmFkaXVzID0gaXRlbS5yYWRpdXM7XG4gICAgICBpZiAoIWl0ZW1SYWRpdXMpIGl0ZW1SYWRpdXMgPSByYWRpdXM7XG4gICAgICBpdGVtUmFkaXVzID0gZ2V0TnVtYmVyUmFkaXVzKGl0ZW1SYWRpdXMsIG1heFJhZGl1cyk7XG4gICAgICBpdGVtLnJhZGl1cyA9IGl0ZW1SYWRpdXM7XG4gICAgfSk7XG4gICAgcGllLnJhZGl1cyA9IHJhZGl1cztcbiAgfSk7XG4gIHJldHVybiBwaWVzO1xufVxuXG5mdW5jdGlvbiBnZXROdW1iZXJSYWRpdXMocmFkaXVzLCBtYXhSYWRpdXMpIHtcbiAgaWYgKCEocmFkaXVzIGluc3RhbmNlb2YgQXJyYXkpKSByYWRpdXMgPSBbMCwgcmFkaXVzXTtcbiAgcmFkaXVzID0gcmFkaXVzLm1hcChmdW5jdGlvbiAocikge1xuICAgIGlmICh0eXBlb2YgciA9PT0gJ251bWJlcicpIHJldHVybiByO1xuICAgIHJldHVybiBwYXJzZUludChyKSAvIDEwMCAqIG1heFJhZGl1cztcbiAgfSk7XG4gIHJldHVybiByYWRpdXM7XG59XG5cbmZ1bmN0aW9uIGNhbGNSb3NlUGllc1JhZGl1cyhwaWVzLCBjaGFydCkge1xuICB2YXIgcm9zZVBpZSA9IHBpZXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmKSB7XG4gICAgdmFyIHJvc2VUeXBlID0gX3JlZi5yb3NlVHlwZTtcbiAgICByZXR1cm4gcm9zZVR5cGU7XG4gIH0pO1xuICByb3NlUGllLmZvckVhY2goZnVuY3Rpb24gKHBpZSkge1xuICAgIHZhciByYWRpdXMgPSBwaWUucmFkaXVzLFxuICAgICAgICBkYXRhID0gcGllLmRhdGEsXG4gICAgICAgIHJvc2VTb3J0ID0gcGllLnJvc2VTb3J0O1xuICAgIHZhciByb3NlSW5jcmVtZW50ID0gZ2V0Um9zZUluY3JlbWVudChwaWUpO1xuICAgIHZhciBkYXRhQ29weSA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoZGF0YSk7XG4gICAgZGF0YSA9IHNvcnREYXRhKGRhdGEpO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgICAgaXRlbS5yYWRpdXNbMV0gPSByYWRpdXNbMV0gLSByb3NlSW5jcmVtZW50ICogaTtcbiAgICB9KTtcblxuICAgIGlmIChyb3NlU29ydCkge1xuICAgICAgZGF0YS5yZXZlcnNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBpZS5kYXRhID0gZGF0YUNvcHk7XG4gICAgfVxuXG4gICAgcGllLnJvc2VJbmNyZW1lbnQgPSByb3NlSW5jcmVtZW50O1xuICB9KTtcbiAgcmV0dXJuIHBpZXM7XG59XG5cbmZ1bmN0aW9uIHNvcnREYXRhKGRhdGEpIHtcbiAgcmV0dXJuIGRhdGEuc29ydChmdW5jdGlvbiAoX3JlZjIsIF9yZWYzKSB7XG4gICAgdmFyIGEgPSBfcmVmMi52YWx1ZTtcbiAgICB2YXIgYiA9IF9yZWYzLnZhbHVlO1xuICAgIGlmIChhID09PSBiKSByZXR1cm4gMDtcbiAgICBpZiAoYSA+IGIpIHJldHVybiAtMTtcbiAgICBpZiAoYSA8IGIpIHJldHVybiAxO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0Um9zZUluY3JlbWVudChwaWUpIHtcbiAgdmFyIHJhZGl1cyA9IHBpZS5yYWRpdXMsXG4gICAgICByb3NlSW5jcmVtZW50ID0gcGllLnJvc2VJbmNyZW1lbnQ7XG4gIGlmICh0eXBlb2Ygcm9zZUluY3JlbWVudCA9PT0gJ251bWJlcicpIHJldHVybiByb3NlSW5jcmVtZW50O1xuXG4gIGlmIChyb3NlSW5jcmVtZW50ID09PSAnYXV0bycpIHtcbiAgICB2YXIgZGF0YSA9IHBpZS5kYXRhO1xuICAgIHZhciBhbGxSYWRpdXMgPSBkYXRhLnJlZHVjZShmdW5jdGlvbiAoYWxsLCBfcmVmNCkge1xuICAgICAgdmFyIHJhZGl1cyA9IF9yZWY0LnJhZGl1cztcbiAgICAgIHJldHVybiBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhbGwpLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHJhZGl1cykpO1xuICAgIH0sIFtdKTtcbiAgICB2YXIgbWluUmFkaXVzID0gTWF0aC5taW4uYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhbGxSYWRpdXMpKTtcbiAgICB2YXIgbWF4UmFkaXVzID0gTWF0aC5tYXguYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhbGxSYWRpdXMpKTtcbiAgICByZXR1cm4gKG1heFJhZGl1cyAtIG1pblJhZGl1cykgKiAwLjYgLyAoZGF0YS5sZW5ndGggLSAxIHx8IDEpO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlSW50KHJvc2VJbmNyZW1lbnQpIC8gMTAwICogcmFkaXVzWzFdO1xufVxuXG5mdW5jdGlvbiBjYWxjUGllc1BlcmNlbnQocGllcykge1xuICBwaWVzLmZvckVhY2goZnVuY3Rpb24gKHBpZSkge1xuICAgIHZhciBkYXRhID0gcGllLmRhdGEsXG4gICAgICAgIHBlcmNlbnRUb0ZpeGVkID0gcGllLnBlcmNlbnRUb0ZpeGVkO1xuICAgIHZhciBzdW0gPSBnZXREYXRhU3VtKGRhdGEpO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIHZhbHVlID0gaXRlbS52YWx1ZTtcbiAgICAgIGl0ZW0ucGVyY2VudCA9IHRvRml4ZWROb0NlaWwodmFsdWUgLyBzdW0gKiAxMDAsIHBlcmNlbnRUb0ZpeGVkKTtcbiAgICB9KTtcbiAgICB2YXIgcGVyY2VudFN1bU5vTGFzdCA9ICgwLCBfdXRpbDIubXVsQWRkKShkYXRhLnNsaWNlKDAsIC0xKS5tYXAoZnVuY3Rpb24gKF9yZWY1KSB7XG4gICAgICB2YXIgcGVyY2VudCA9IF9yZWY1LnBlcmNlbnQ7XG4gICAgICByZXR1cm4gcGVyY2VudDtcbiAgICB9KSk7XG4gICAgZGF0YS5zbGljZSgtMSlbMF0ucGVyY2VudCA9IHRvRml4ZWROb0NlaWwoMTAwIC0gcGVyY2VudFN1bU5vTGFzdCwgcGVyY2VudFRvRml4ZWQpO1xuICB9KTtcbiAgcmV0dXJuIHBpZXM7XG59XG5cbmZ1bmN0aW9uIHRvRml4ZWROb0NlaWwobnVtYmVyKSB7XG4gIHZhciB0b0ZpeGVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAwO1xuICB2YXIgc3RyaW5nTnVtYmVyID0gbnVtYmVyLnRvU3RyaW5nKCk7XG4gIHZhciBzcGxpdGVkTnVtYmVyID0gc3RyaW5nTnVtYmVyLnNwbGl0KCcuJyk7XG4gIHZhciBkZWNpbWFsID0gc3BsaXRlZE51bWJlclsxXSB8fCAnMCc7XG4gIHZhciBmaXhlZERlY2ltYWwgPSBkZWNpbWFsLnNsaWNlKDAsIHRvRml4ZWQpO1xuICBzcGxpdGVkTnVtYmVyWzFdID0gZml4ZWREZWNpbWFsO1xuICByZXR1cm4gcGFyc2VGbG9hdChzcGxpdGVkTnVtYmVyLmpvaW4oJy4nKSk7XG59XG5cbmZ1bmN0aW9uIGdldERhdGFTdW0oZGF0YSkge1xuICByZXR1cm4gKDAsIF91dGlsMi5tdWxBZGQpKGRhdGEubWFwKGZ1bmN0aW9uIChfcmVmNikge1xuICAgIHZhciB2YWx1ZSA9IF9yZWY2LnZhbHVlO1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBjYWxjUGllc0FuZ2xlKHBpZXMpIHtcbiAgcGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwaWUpIHtcbiAgICB2YXIgc3RhcnQgPSBwaWUuc3RhcnRBbmdsZSxcbiAgICAgICAgZGF0YSA9IHBpZS5kYXRhO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSwgaSkge1xuICAgICAgdmFyIF9nZXREYXRhQW5nbGUgPSBnZXREYXRhQW5nbGUoZGF0YSwgaSksXG4gICAgICAgICAgX2dldERhdGFBbmdsZTIgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX2dldERhdGFBbmdsZSwgMiksXG4gICAgICAgICAgc3RhcnRBbmdsZSA9IF9nZXREYXRhQW5nbGUyWzBdLFxuICAgICAgICAgIGVuZEFuZ2xlID0gX2dldERhdGFBbmdsZTJbMV07XG5cbiAgICAgIGl0ZW0uc3RhcnRBbmdsZSA9IHN0YXJ0ICsgc3RhcnRBbmdsZTtcbiAgICAgIGl0ZW0uZW5kQW5nbGUgPSBzdGFydCArIGVuZEFuZ2xlO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIHBpZXM7XG59XG5cbmZ1bmN0aW9uIGdldERhdGFBbmdsZShkYXRhLCBpKSB7XG4gIHZhciBmdWxsQW5nbGUgPSBNYXRoLlBJICogMjtcbiAgdmFyIG5lZWRBZGREYXRhID0gZGF0YS5zbGljZSgwLCBpICsgMSk7XG4gIHZhciBwZXJjZW50U3VtID0gKDAsIF91dGlsMi5tdWxBZGQpKG5lZWRBZGREYXRhLm1hcChmdW5jdGlvbiAoX3JlZjcpIHtcbiAgICB2YXIgcGVyY2VudCA9IF9yZWY3LnBlcmNlbnQ7XG4gICAgcmV0dXJuIHBlcmNlbnQ7XG4gIH0pKTtcbiAgdmFyIHBlcmNlbnQgPSBkYXRhW2ldLnBlcmNlbnQ7XG4gIHZhciBzdGFydFBlcmNlbnQgPSBwZXJjZW50U3VtIC0gcGVyY2VudDtcbiAgcmV0dXJuIFtmdWxsQW5nbGUgKiBzdGFydFBlcmNlbnQgLyAxMDAsIGZ1bGxBbmdsZSAqIHBlcmNlbnRTdW0gLyAxMDBdO1xufVxuXG5mdW5jdGlvbiBjYWxjUGllc0luc2lkZUxhYmVsUG9zKHBpZXMpIHtcbiAgcGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwaWVJdGVtKSB7XG4gICAgdmFyIGRhdGEgPSBwaWVJdGVtLmRhdGE7XG4gICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICBpdGVtLmluc2lkZUxhYmVsUG9zID0gZ2V0UGllSW5zaWRlTGFiZWxQb3MocGllSXRlbSwgaXRlbSk7XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gcGllcztcbn1cblxuZnVuY3Rpb24gZ2V0UGllSW5zaWRlTGFiZWxQb3MocGllSXRlbSwgZGF0YUl0ZW0pIHtcbiAgdmFyIGNlbnRlciA9IHBpZUl0ZW0uY2VudGVyO1xuXG4gIHZhciBzdGFydEFuZ2xlID0gZGF0YUl0ZW0uc3RhcnRBbmdsZSxcbiAgICAgIGVuZEFuZ2xlID0gZGF0YUl0ZW0uZW5kQW5nbGUsXG4gICAgICBfZGF0YUl0ZW0kcmFkaXVzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGRhdGFJdGVtLnJhZGl1cywgMiksXG4gICAgICBpciA9IF9kYXRhSXRlbSRyYWRpdXNbMF0sXG4gICAgICBvciA9IF9kYXRhSXRlbSRyYWRpdXNbMV07XG5cbiAgdmFyIHJhZGl1cyA9IChpciArIG9yKSAvIDI7XG4gIHZhciBhbmdsZSA9IChzdGFydEFuZ2xlICsgZW5kQW5nbGUpIC8gMjtcbiAgcmV0dXJuIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXIpLmNvbmNhdChbcmFkaXVzLCBhbmdsZV0pKTtcbn1cblxuZnVuY3Rpb24gY2FsY1BpZXNFZGdlQ2VudGVyUG9zKHBpZXMpIHtcbiAgcGllcy5mb3JFYWNoKGZ1bmN0aW9uIChwaWUpIHtcbiAgICB2YXIgZGF0YSA9IHBpZS5kYXRhLFxuICAgICAgICBjZW50ZXIgPSBwaWUuY2VudGVyO1xuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgdmFyIHN0YXJ0QW5nbGUgPSBpdGVtLnN0YXJ0QW5nbGUsXG4gICAgICAgICAgZW5kQW5nbGUgPSBpdGVtLmVuZEFuZ2xlLFxuICAgICAgICAgIHJhZGl1cyA9IGl0ZW0ucmFkaXVzO1xuICAgICAgdmFyIGNlbnRlckFuZ2xlID0gKHN0YXJ0QW5nbGUgKyBlbmRBbmdsZSkgLyAyO1xuXG4gICAgICB2YXIgcG9zID0gX3V0aWwuZ2V0Q2lyY2xlUmFkaWFuUG9pbnQuYXBwbHkodm9pZCAwLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNlbnRlcikuY29uY2F0KFtyYWRpdXNbMV0sIGNlbnRlckFuZ2xlXSkpO1xuXG4gICAgICBpdGVtLmVkZ2VDZW50ZXJQb3MgPSBwb3M7XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gcGllcztcbn1cblxuZnVuY3Rpb24gY2FsY1BpZXNPdXRTaWRlTGFiZWxQb3MocGllcykge1xuICBwaWVzLmZvckVhY2goZnVuY3Rpb24gKHBpZUl0ZW0pIHtcbiAgICB2YXIgbGVmdFBpZURhdGFJdGVtcyA9IGdldExlZnRPclJpZ2h0UGllRGF0YUl0ZW1zKHBpZUl0ZW0pO1xuICAgIHZhciByaWdodFBpZURhdGFJdGVtcyA9IGdldExlZnRPclJpZ2h0UGllRGF0YUl0ZW1zKHBpZUl0ZW0sIGZhbHNlKTtcbiAgICBsZWZ0UGllRGF0YUl0ZW1zID0gc29ydFBpZXNGcm9tVG9wVG9Cb3R0b20obGVmdFBpZURhdGFJdGVtcyk7XG4gICAgcmlnaHRQaWVEYXRhSXRlbXMgPSBzb3J0UGllc0Zyb21Ub3BUb0JvdHRvbShyaWdodFBpZURhdGFJdGVtcyk7XG4gICAgYWRkTGFiZWxMaW5lQW5kQWxpZ24obGVmdFBpZURhdGFJdGVtcywgcGllSXRlbSk7XG4gICAgYWRkTGFiZWxMaW5lQW5kQWxpZ24ocmlnaHRQaWVEYXRhSXRlbXMsIHBpZUl0ZW0sIGZhbHNlKTtcbiAgfSk7XG4gIHJldHVybiBwaWVzO1xufVxuXG5mdW5jdGlvbiBnZXRMYWJlbExpbmVCZW5kUmFkaXVzKHBpZUl0ZW0pIHtcbiAgdmFyIGxhYmVsTGluZUJlbmRHYXAgPSBwaWVJdGVtLm91dHNpZGVMYWJlbC5sYWJlbExpbmVCZW5kR2FwO1xuICB2YXIgbWF4UmFkaXVzID0gZ2V0UGllTWF4UmFkaXVzKHBpZUl0ZW0pO1xuXG4gIGlmICh0eXBlb2YgbGFiZWxMaW5lQmVuZEdhcCAhPT0gJ251bWJlcicpIHtcbiAgICBsYWJlbExpbmVCZW5kR2FwID0gcGFyc2VJbnQobGFiZWxMaW5lQmVuZEdhcCkgLyAxMDAgKiBtYXhSYWRpdXM7XG4gIH1cblxuICByZXR1cm4gbGFiZWxMaW5lQmVuZEdhcCArIG1heFJhZGl1cztcbn1cblxuZnVuY3Rpb24gZ2V0UGllTWF4UmFkaXVzKHBpZUl0ZW0pIHtcbiAgdmFyIGRhdGEgPSBwaWVJdGVtLmRhdGE7XG4gIHZhciByYWRpdXMgPSBkYXRhLm1hcChmdW5jdGlvbiAoX3JlZjgpIHtcbiAgICB2YXIgX3JlZjgkcmFkaXVzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY4LnJhZGl1cywgMiksXG4gICAgICAgIGZvbyA9IF9yZWY4JHJhZGl1c1swXSxcbiAgICAgICAgciA9IF9yZWY4JHJhZGl1c1sxXTtcblxuICAgIHJldHVybiByO1xuICB9KTtcbiAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocmFkaXVzKSk7XG59XG5cbmZ1bmN0aW9uIGdldExlZnRPclJpZ2h0UGllRGF0YUl0ZW1zKHBpZUl0ZW0pIHtcbiAgdmFyIGxlZnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRydWU7XG4gIHZhciBkYXRhID0gcGllSXRlbS5kYXRhLFxuICAgICAgY2VudGVyID0gcGllSXRlbS5jZW50ZXI7XG4gIHZhciBjZW50ZXJYUG9zID0gY2VudGVyWzBdO1xuICByZXR1cm4gZGF0YS5maWx0ZXIoZnVuY3Rpb24gKF9yZWY5KSB7XG4gICAgdmFyIGVkZ2VDZW50ZXJQb3MgPSBfcmVmOS5lZGdlQ2VudGVyUG9zO1xuICAgIHZhciB4UG9zID0gZWRnZUNlbnRlclBvc1swXTtcbiAgICBpZiAobGVmdCkgcmV0dXJuIHhQb3MgPD0gY2VudGVyWFBvcztcbiAgICByZXR1cm4geFBvcyA+IGNlbnRlclhQb3M7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzb3J0UGllc0Zyb21Ub3BUb0JvdHRvbShkYXRhSXRlbSkge1xuICBkYXRhSXRlbS5zb3J0KGZ1bmN0aW9uIChfcmVmMTAsIF9yZWYxMSkge1xuICAgIHZhciBfcmVmMTAkZWRnZUNlbnRlclBvcyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMTAuZWRnZUNlbnRlclBvcywgMiksXG4gICAgICAgIHQgPSBfcmVmMTAkZWRnZUNlbnRlclBvc1swXSxcbiAgICAgICAgYXkgPSBfcmVmMTAkZWRnZUNlbnRlclBvc1sxXTtcblxuICAgIHZhciBfcmVmMTEkZWRnZUNlbnRlclBvcyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMTEuZWRnZUNlbnRlclBvcywgMiksXG4gICAgICAgIHR0ID0gX3JlZjExJGVkZ2VDZW50ZXJQb3NbMF0sXG4gICAgICAgIGJ5ID0gX3JlZjExJGVkZ2VDZW50ZXJQb3NbMV07XG5cbiAgICBpZiAoYXkgPiBieSkgcmV0dXJuIDE7XG4gICAgaWYgKGF5IDwgYnkpIHJldHVybiAtMTtcbiAgICBpZiAoYXkgPT09IGJ5KSByZXR1cm4gMDtcbiAgfSk7XG4gIHJldHVybiBkYXRhSXRlbTtcbn1cblxuZnVuY3Rpb24gYWRkTGFiZWxMaW5lQW5kQWxpZ24oZGF0YUl0ZW0sIHBpZUl0ZW0pIHtcbiAgdmFyIGxlZnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHRydWU7XG4gIHZhciBjZW50ZXIgPSBwaWVJdGVtLmNlbnRlcixcbiAgICAgIG91dHNpZGVMYWJlbCA9IHBpZUl0ZW0ub3V0c2lkZUxhYmVsO1xuICB2YXIgcmFkaXVzID0gZ2V0TGFiZWxMaW5lQmVuZFJhZGl1cyhwaWVJdGVtKTtcbiAgZGF0YUl0ZW0uZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgIHZhciBlZGdlQ2VudGVyUG9zID0gaXRlbS5lZGdlQ2VudGVyUG9zLFxuICAgICAgICBzdGFydEFuZ2xlID0gaXRlbS5zdGFydEFuZ2xlLFxuICAgICAgICBlbmRBbmdsZSA9IGl0ZW0uZW5kQW5nbGU7XG4gICAgdmFyIGxhYmVsTGluZUVuZExlbmd0aCA9IG91dHNpZGVMYWJlbC5sYWJlbExpbmVFbmRMZW5ndGg7XG4gICAgdmFyIGFuZ2xlID0gKHN0YXJ0QW5nbGUgKyBlbmRBbmdsZSkgLyAyO1xuXG4gICAgdmFyIGJlbmRQb2ludCA9IF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXIpLmNvbmNhdChbcmFkaXVzLCBhbmdsZV0pKTtcblxuICAgIHZhciBlbmRQb2ludCA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoYmVuZFBvaW50KTtcbiAgICBlbmRQb2ludFswXSArPSBsYWJlbExpbmVFbmRMZW5ndGggKiAobGVmdCA/IC0xIDogMSk7XG4gICAgaXRlbS5sYWJlbExpbmUgPSBbZWRnZUNlbnRlclBvcywgYmVuZFBvaW50LCBlbmRQb2ludF07XG4gICAgaXRlbS5sYWJlbExpbmVMZW5ndGggPSAoMCwgX3V0aWwyLmdldFBvbHlsaW5lTGVuZ3RoKShpdGVtLmxhYmVsTGluZSk7XG4gICAgaXRlbS5hbGlnbiA9IHtcbiAgICAgIHRleHRBbGlnbjogJ2xlZnQnLFxuICAgICAgdGV4dEJhc2VsaW5lOiAnbWlkZGxlJ1xuICAgIH07XG4gICAgaWYgKGxlZnQpIGl0ZW0uYWxpZ24udGV4dEFsaWduID0gJ3JpZ2h0JztcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFBpZUNvbmZpZyhwaWVJdGVtKSB7XG4gIHZhciBkYXRhID0gcGllSXRlbS5kYXRhLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSBwaWVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBwaWVJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gcGllSXRlbS5yTGV2ZWw7XG4gIHJldHVybiBkYXRhLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdwaWUnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICAgIHNoYXBlOiBnZXRQaWVTaGFwZShwaWVJdGVtLCBpKSxcbiAgICAgIHN0eWxlOiBnZXRQaWVTdHlsZShwaWVJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydFBpZUNvbmZpZyhwaWVJdGVtKSB7XG4gIHZhciBhbmltYXRpb25EZWxheUdhcCA9IHBpZUl0ZW0uYW5pbWF0aW9uRGVsYXlHYXAsXG4gICAgICBzdGFydEFuaW1hdGlvbkN1cnZlID0gcGllSXRlbS5zdGFydEFuaW1hdGlvbkN1cnZlO1xuICB2YXIgY29uZmlncyA9IGdldFBpZUNvbmZpZyhwaWVJdGVtKTtcbiAgY29uZmlncy5mb3JFYWNoKGZ1bmN0aW9uIChjb25maWcsIGkpIHtcbiAgICBjb25maWcuYW5pbWF0aW9uQ3VydmUgPSBzdGFydEFuaW1hdGlvbkN1cnZlO1xuICAgIGNvbmZpZy5hbmltYXRpb25EZWxheSA9IGkgKiBhbmltYXRpb25EZWxheUdhcDtcbiAgICBjb25maWcuc2hhcGUub3IgPSBjb25maWcuc2hhcGUuaXI7XG4gIH0pO1xuICByZXR1cm4gY29uZmlncztcbn1cblxuZnVuY3Rpb24gYmVmb3JlQ2hhbmdlUGllKGdyYXBoKSB7XG4gIGdyYXBoLmFuaW1hdGlvbkRlbGF5ID0gMDtcbn1cblxuZnVuY3Rpb24gZ2V0UGllU2hhcGUocGllSXRlbSwgaSkge1xuICB2YXIgY2VudGVyID0gcGllSXRlbS5jZW50ZXIsXG4gICAgICBkYXRhID0gcGllSXRlbS5kYXRhO1xuICB2YXIgZGF0YUl0ZW0gPSBkYXRhW2ldO1xuICB2YXIgcmFkaXVzID0gZGF0YUl0ZW0ucmFkaXVzLFxuICAgICAgc3RhcnRBbmdsZSA9IGRhdGFJdGVtLnN0YXJ0QW5nbGUsXG4gICAgICBlbmRBbmdsZSA9IGRhdGFJdGVtLmVuZEFuZ2xlO1xuICByZXR1cm4ge1xuICAgIHN0YXJ0QW5nbGU6IHN0YXJ0QW5nbGUsXG4gICAgZW5kQW5nbGU6IGVuZEFuZ2xlLFxuICAgIGlyOiByYWRpdXNbMF0sXG4gICAgb3I6IHJhZGl1c1sxXSxcbiAgICByeDogY2VudGVyWzBdLFxuICAgIHJ5OiBjZW50ZXJbMV1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGllU3R5bGUocGllSXRlbSwgaSkge1xuICB2YXIgcGllU3R5bGUgPSBwaWVJdGVtLnBpZVN0eWxlLFxuICAgICAgZGF0YSA9IHBpZUl0ZW0uZGF0YTtcbiAgdmFyIGRhdGFJdGVtID0gZGF0YVtpXTtcbiAgdmFyIGNvbG9yID0gZGF0YUl0ZW0uY29sb3I7XG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoe1xuICAgIGZpbGw6IGNvbG9yXG4gIH0sIHBpZVN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0SW5zaWRlTGFiZWxDb25maWcocGllSXRlbSkge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBwaWVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBwaWVJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgZGF0YSA9IHBpZUl0ZW0uZGF0YSxcbiAgICAgIHJMZXZlbCA9IHBpZUl0ZW0uckxldmVsO1xuICByZXR1cm4gZGF0YS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAndGV4dCcsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogcGllSXRlbS5pbnNpZGVMYWJlbC5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IGdldEluc2lkZUxhYmVsU2hhcGUocGllSXRlbSwgaSksXG4gICAgICBzdHlsZTogZ2V0SW5zaWRlTGFiZWxTdHlsZShwaWVJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRJbnNpZGVMYWJlbFNoYXBlKHBpZUl0ZW0sIGkpIHtcbiAgdmFyIGluc2lkZUxhYmVsID0gcGllSXRlbS5pbnNpZGVMYWJlbCxcbiAgICAgIGRhdGEgPSBwaWVJdGVtLmRhdGE7XG4gIHZhciBmb3JtYXR0ZXIgPSBpbnNpZGVMYWJlbC5mb3JtYXR0ZXI7XG4gIHZhciBkYXRhSXRlbSA9IGRhdGFbaV07XG4gIHZhciBmb3JtYXR0ZXJUeXBlID0gKDAsIF90eXBlb2YyW1wiZGVmYXVsdFwiXSkoZm9ybWF0dGVyKTtcbiAgdmFyIGxhYmVsID0gJyc7XG5cbiAgaWYgKGZvcm1hdHRlclR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgbGFiZWwgPSBmb3JtYXR0ZXIucmVwbGFjZSgne25hbWV9JywgZGF0YUl0ZW0ubmFtZSk7XG4gICAgbGFiZWwgPSBsYWJlbC5yZXBsYWNlKCd7cGVyY2VudH0nLCBkYXRhSXRlbS5wZXJjZW50KTtcbiAgICBsYWJlbCA9IGxhYmVsLnJlcGxhY2UoJ3t2YWx1ZX0nLCBkYXRhSXRlbS52YWx1ZSk7XG4gIH1cblxuICBpZiAoZm9ybWF0dGVyVHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGxhYmVsID0gZm9ybWF0dGVyKGRhdGFJdGVtKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY29udGVudDogbGFiZWwsXG4gICAgcG9zaXRpb246IGRhdGFJdGVtLmluc2lkZUxhYmVsUG9zXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldEluc2lkZUxhYmVsU3R5bGUocGllSXRlbSwgaSkge1xuICB2YXIgc3R5bGUgPSBwaWVJdGVtLmluc2lkZUxhYmVsLnN0eWxlO1xuICByZXR1cm4gc3R5bGU7XG59XG5cbmZ1bmN0aW9uIGdldE91dHNpZGVMYWJlbExpbmVDb25maWcocGllSXRlbSkge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBwaWVJdGVtLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBwaWVJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgZGF0YSA9IHBpZUl0ZW0uZGF0YSxcbiAgICAgIHJMZXZlbCA9IHBpZUl0ZW0uckxldmVsO1xuICByZXR1cm4gZGF0YS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAncG9seWxpbmUnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IHBpZUl0ZW0ub3V0c2lkZUxhYmVsLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0T3V0c2lkZUxhYmVsTGluZVNoYXBlKHBpZUl0ZW0sIGkpLFxuICAgICAgc3R5bGU6IGdldE91dHNpZGVMYWJlbExpbmVTdHlsZShwaWVJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydE91dHNpZGVMYWJlbExpbmVDb25maWcocGllSXRlbSkge1xuICB2YXIgZGF0YSA9IHBpZUl0ZW0uZGF0YTtcbiAgdmFyIGNvbmZpZ3MgPSBnZXRPdXRzaWRlTGFiZWxMaW5lQ29uZmlnKHBpZUl0ZW0pO1xuICBjb25maWdzLmZvckVhY2goZnVuY3Rpb24gKGNvbmZpZywgaSkge1xuICAgIGNvbmZpZy5zdHlsZS5saW5lRGFzaCA9IFswLCBkYXRhW2ldLmxhYmVsTGluZUxlbmd0aF07XG4gIH0pO1xuICByZXR1cm4gY29uZmlncztcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZUxhYmVsTGluZVNoYXBlKHBpZUl0ZW0sIGkpIHtcbiAgdmFyIGRhdGEgPSBwaWVJdGVtLmRhdGE7XG4gIHZhciBkYXRhSXRlbSA9IGRhdGFbaV07XG4gIHJldHVybiB7XG4gICAgcG9pbnRzOiBkYXRhSXRlbS5sYWJlbExpbmVcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZUxhYmVsTGluZVN0eWxlKHBpZUl0ZW0sIGkpIHtcbiAgdmFyIG91dHNpZGVMYWJlbCA9IHBpZUl0ZW0ub3V0c2lkZUxhYmVsLFxuICAgICAgZGF0YSA9IHBpZUl0ZW0uZGF0YTtcbiAgdmFyIGxhYmVsTGluZVN0eWxlID0gb3V0c2lkZUxhYmVsLmxhYmVsTGluZVN0eWxlO1xuICB2YXIgY29sb3IgPSBkYXRhW2ldLmNvbG9yO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBzdHJva2U6IGNvbG9yLFxuICAgIGxpbmVEYXNoOiBbZGF0YVtpXS5sYWJlbExpbmVMZW5ndGgsIDBdXG4gIH0sIGxhYmVsTGluZVN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZUxhYmVsQ29uZmlnKHBpZUl0ZW0pIHtcbiAgdmFyIGFuaW1hdGlvbkN1cnZlID0gcGllSXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gcGllSXRlbS5hbmltYXRpb25GcmFtZSxcbiAgICAgIGRhdGEgPSBwaWVJdGVtLmRhdGEsXG4gICAgICByTGV2ZWwgPSBwaWVJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uIChmb28sIGkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ3RleHQnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IHBpZUl0ZW0ub3V0c2lkZUxhYmVsLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0T3V0c2lkZUxhYmVsU2hhcGUocGllSXRlbSwgaSksXG4gICAgICBzdHlsZTogZ2V0T3V0c2lkZUxhYmVsU3R5bGUocGllSXRlbSwgaSlcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRPdXRzaWRlTGFiZWxDb25maWcocGllSXRlbSkge1xuICB2YXIgZGF0YSA9IHBpZUl0ZW0uZGF0YTtcbiAgdmFyIGNvbmZpZ3MgPSBnZXRPdXRzaWRlTGFiZWxDb25maWcocGllSXRlbSk7XG4gIGNvbmZpZ3MuZm9yRWFjaChmdW5jdGlvbiAoY29uZmlnLCBpKSB7XG4gICAgY29uZmlnLnNoYXBlLnBvc2l0aW9uID0gZGF0YVtpXS5sYWJlbExpbmVbMV07XG4gIH0pO1xuICByZXR1cm4gY29uZmlncztcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZUxhYmVsU2hhcGUocGllSXRlbSwgaSkge1xuICB2YXIgb3V0c2lkZUxhYmVsID0gcGllSXRlbS5vdXRzaWRlTGFiZWwsXG4gICAgICBkYXRhID0gcGllSXRlbS5kYXRhO1xuICB2YXIgZm9ybWF0dGVyID0gb3V0c2lkZUxhYmVsLmZvcm1hdHRlcjtcbiAgdmFyIF9kYXRhJGkgPSBkYXRhW2ldLFxuICAgICAgbGFiZWxMaW5lID0gX2RhdGEkaS5sYWJlbExpbmUsXG4gICAgICBuYW1lID0gX2RhdGEkaS5uYW1lLFxuICAgICAgcGVyY2VudCA9IF9kYXRhJGkucGVyY2VudCxcbiAgICAgIHZhbHVlID0gX2RhdGEkaS52YWx1ZTtcbiAgdmFyIGZvcm1hdHRlclR5cGUgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShmb3JtYXR0ZXIpO1xuICB2YXIgbGFiZWwgPSAnJztcblxuICBpZiAoZm9ybWF0dGVyVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBsYWJlbCA9IGZvcm1hdHRlci5yZXBsYWNlKCd7bmFtZX0nLCBuYW1lKTtcbiAgICBsYWJlbCA9IGxhYmVsLnJlcGxhY2UoJ3twZXJjZW50fScsIHBlcmNlbnQpO1xuICAgIGxhYmVsID0gbGFiZWwucmVwbGFjZSgne3ZhbHVlfScsIHZhbHVlKTtcbiAgfVxuXG4gIGlmIChmb3JtYXR0ZXJUeXBlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgbGFiZWwgPSBmb3JtYXR0ZXIoZGF0YVtpXSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGNvbnRlbnQ6IGxhYmVsLFxuICAgIHBvc2l0aW9uOiBsYWJlbExpbmVbMl1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZUxhYmVsU3R5bGUocGllSXRlbSwgaSkge1xuICB2YXIgb3V0c2lkZUxhYmVsID0gcGllSXRlbS5vdXRzaWRlTGFiZWwsXG4gICAgICBkYXRhID0gcGllSXRlbS5kYXRhO1xuICB2YXIgX2RhdGEkaTIgPSBkYXRhW2ldLFxuICAgICAgY29sb3IgPSBfZGF0YSRpMi5jb2xvcixcbiAgICAgIGFsaWduID0gX2RhdGEkaTIuYWxpZ247XG4gIHZhciBzdHlsZSA9IG91dHNpZGVMYWJlbC5zdHlsZTtcbiAgcmV0dXJuICgwLCBfdXRpbDIuZGVlcE1lcmdlKShfb2JqZWN0U3ByZWFkKHtcbiAgICBmaWxsOiBjb2xvclxuICB9LCBhbGlnbiksIHN0eWxlKTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLnJhZGFyID0gcmFkYXI7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX2luZGV4ID0gcmVxdWlyZShcIi4uL2NvbmZpZy9pbmRleFwiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG52YXIgX2NvbG9yID0gcmVxdWlyZShcIkBqaWFtaW5naGkvY29sb3JcIik7XG5cbnZhciBfdXRpbDIgPSByZXF1aXJlKFwiLi4vdXRpbFwiKTtcblxuZnVuY3Rpb24gb3duS2V5cyhvYmplY3QsIGVudW1lcmFibGVPbmx5KSB7IHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTsgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHsgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7IGlmIChlbnVtZXJhYmxlT25seSkgc3ltYm9scyA9IHN5bWJvbHMuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHsgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBzeW0pLmVudW1lcmFibGU7IH0pOyBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7IH0gcmV0dXJuIGtleXM7IH1cblxuZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307IGlmIChpICUgMikgeyBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7ICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTsgfSk7IH0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpIHsgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzb3VyY2UpKTsgfSBlbHNlIHsgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsgfSk7IH0gfSByZXR1cm4gdGFyZ2V0OyB9XG5cbmZ1bmN0aW9uIHJhZGFyKGNoYXJ0KSB7XG4gIHZhciBvcHRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuICB2YXIgc2VyaWVzID0gb3B0aW9uLnNlcmllcztcbiAgaWYgKCFzZXJpZXMpIHNlcmllcyA9IFtdO1xuICB2YXIgcmFkYXJzID0gKDAsIF91dGlsMi5pbml0TmVlZFNlcmllcykoc2VyaWVzLCBfaW5kZXgucmFkYXJDb25maWcsICdyYWRhcicpO1xuICByYWRhcnMgPSBjYWxjUmFkYXJQb3NpdGlvbihyYWRhcnMsIGNoYXJ0KTtcbiAgcmFkYXJzID0gY2FsY1JhZGFyTGFiZWxQb3NpdGlvbihyYWRhcnMsIGNoYXJ0KTtcbiAgcmFkYXJzID0gY2FsY1JhZGFyTGFiZWxBbGlnbihyYWRhcnMsIGNoYXJ0KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogcmFkYXJzLFxuICAgIGtleTogJ3JhZGFyJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0UmFkYXJDb25maWcsXG4gICAgZ2V0U3RhcnRHcmFwaENvbmZpZzogZ2V0U3RhcnRSYWRhckNvbmZpZyxcbiAgICBiZWZvcmVDaGFuZ2U6IGJlZm9yZUNoYW5nZVJhZGFyXG4gIH0pO1xuICAoMCwgX3VwZGF0ZXIuZG9VcGRhdGUpKHtcbiAgICBjaGFydDogY2hhcnQsXG4gICAgc2VyaWVzOiByYWRhcnMsXG4gICAga2V5OiAncmFkYXJQb2ludCcsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFBvaW50Q29uZmlnLFxuICAgIGdldFN0YXJ0R3JhcGhDb25maWc6IGdldFN0YXJ0UG9pbnRDb25maWdcbiAgfSk7XG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IHJhZGFycyxcbiAgICBrZXk6ICdyYWRhckxhYmVsJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0TGFiZWxDb25maWdcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNSYWRhclBvc2l0aW9uKHJhZGFycywgY2hhcnQpIHtcbiAgdmFyIHJhZGFyQXhpcyA9IGNoYXJ0LnJhZGFyQXhpcztcbiAgaWYgKCFyYWRhckF4aXMpIHJldHVybiBbXTtcbiAgdmFyIGluZGljYXRvciA9IHJhZGFyQXhpcy5pbmRpY2F0b3IsXG4gICAgICBheGlzTGluZUFuZ2xlcyA9IHJhZGFyQXhpcy5heGlzTGluZUFuZ2xlcyxcbiAgICAgIHJhZGl1cyA9IHJhZGFyQXhpcy5yYWRpdXMsXG4gICAgICBjZW50ZXJQb3MgPSByYWRhckF4aXMuY2VudGVyUG9zO1xuICByYWRhcnMuZm9yRWFjaChmdW5jdGlvbiAocmFkYXJJdGVtKSB7XG4gICAgdmFyIGRhdGEgPSByYWRhckl0ZW0uZGF0YTtcbiAgICByYWRhckl0ZW0uZGF0YVJhZGl1cyA9IFtdO1xuICAgIHJhZGFySXRlbS5yYWRhclBvc2l0aW9uID0gaW5kaWNhdG9yLm1hcChmdW5jdGlvbiAoX3JlZiwgaSkge1xuICAgICAgdmFyIG1heCA9IF9yZWYubWF4LFxuICAgICAgICAgIG1pbiA9IF9yZWYubWluO1xuICAgICAgdmFyIHYgPSBkYXRhW2ldO1xuICAgICAgaWYgKHR5cGVvZiBtYXggIT09ICdudW1iZXInKSBtYXggPSB2O1xuICAgICAgaWYgKHR5cGVvZiBtaW4gIT09ICdudW1iZXInKSBtaW4gPSAwO1xuICAgICAgaWYgKHR5cGVvZiB2ICE9PSAnbnVtYmVyJykgdiA9IG1pbjtcbiAgICAgIHZhciBkYXRhUmFkaXVzID0gKHYgLSBtaW4pIC8gKG1heCAtIG1pbikgKiByYWRpdXM7XG4gICAgICByYWRhckl0ZW0uZGF0YVJhZGl1c1tpXSA9IGRhdGFSYWRpdXM7XG4gICAgICByZXR1cm4gX3V0aWwuZ2V0Q2lyY2xlUmFkaWFuUG9pbnQuYXBwbHkodm9pZCAwLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNlbnRlclBvcykuY29uY2F0KFtkYXRhUmFkaXVzLCBheGlzTGluZUFuZ2xlc1tpXV0pKTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiByYWRhcnM7XG59XG5cbmZ1bmN0aW9uIGNhbGNSYWRhckxhYmVsUG9zaXRpb24ocmFkYXJzLCBjaGFydCkge1xuICB2YXIgcmFkYXJBeGlzID0gY2hhcnQucmFkYXJBeGlzO1xuICBpZiAoIXJhZGFyQXhpcykgcmV0dXJuIFtdO1xuICB2YXIgY2VudGVyUG9zID0gcmFkYXJBeGlzLmNlbnRlclBvcyxcbiAgICAgIGF4aXNMaW5lQW5nbGVzID0gcmFkYXJBeGlzLmF4aXNMaW5lQW5nbGVzO1xuICByYWRhcnMuZm9yRWFjaChmdW5jdGlvbiAocmFkYXJJdGVtKSB7XG4gICAgdmFyIGRhdGFSYWRpdXMgPSByYWRhckl0ZW0uZGF0YVJhZGl1cyxcbiAgICAgICAgbGFiZWwgPSByYWRhckl0ZW0ubGFiZWw7XG4gICAgdmFyIGxhYmVsR2FwID0gbGFiZWwubGFiZWxHYXA7XG4gICAgcmFkYXJJdGVtLmxhYmVsUG9zaXRpb24gPSBkYXRhUmFkaXVzLm1hcChmdW5jdGlvbiAociwgaSkge1xuICAgICAgcmV0dXJuIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXJQb3MpLmNvbmNhdChbciArIGxhYmVsR2FwLCBheGlzTGluZUFuZ2xlc1tpXV0pKTtcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiByYWRhcnM7XG59XG5cbmZ1bmN0aW9uIGNhbGNSYWRhckxhYmVsQWxpZ24ocmFkYXJzLCBjaGFydCkge1xuICB2YXIgcmFkYXJBeGlzID0gY2hhcnQucmFkYXJBeGlzO1xuICBpZiAoIXJhZGFyQXhpcykgcmV0dXJuIFtdO1xuXG4gIHZhciBfcmFkYXJBeGlzJGNlbnRlclBvcyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShyYWRhckF4aXMuY2VudGVyUG9zLCAyKSxcbiAgICAgIHggPSBfcmFkYXJBeGlzJGNlbnRlclBvc1swXSxcbiAgICAgIHkgPSBfcmFkYXJBeGlzJGNlbnRlclBvc1sxXTtcblxuICByYWRhcnMuZm9yRWFjaChmdW5jdGlvbiAocmFkYXJJdGVtKSB7XG4gICAgdmFyIGxhYmVsUG9zaXRpb24gPSByYWRhckl0ZW0ubGFiZWxQb3NpdGlvbjtcbiAgICB2YXIgbGFiZWxBbGlnbiA9IGxhYmVsUG9zaXRpb24ubWFwKGZ1bmN0aW9uIChfcmVmMikge1xuICAgICAgdmFyIF9yZWYzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYyLCAyKSxcbiAgICAgICAgICBseCA9IF9yZWYzWzBdLFxuICAgICAgICAgIGx5ID0gX3JlZjNbMV07XG5cbiAgICAgIHZhciB0ZXh0QWxpZ24gPSBseCA+IHggPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgICAgdmFyIHRleHRCYXNlbGluZSA9IGx5ID4geSA/ICd0b3AnIDogJ2JvdHRvbSc7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0QWxpZ246IHRleHRBbGlnbixcbiAgICAgICAgdGV4dEJhc2VsaW5lOiB0ZXh0QmFzZWxpbmVcbiAgICAgIH07XG4gICAgfSk7XG4gICAgcmFkYXJJdGVtLmxhYmVsQWxpZ24gPSBsYWJlbEFsaWduO1xuICB9KTtcbiAgcmV0dXJuIHJhZGFycztcbn1cblxuZnVuY3Rpb24gZ2V0UmFkYXJDb25maWcocmFkYXJJdGVtKSB7XG4gIHZhciBhbmltYXRpb25DdXJ2ZSA9IHJhZGFySXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gcmFkYXJJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gcmFkYXJJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIFt7XG4gICAgbmFtZTogJ3BvbHlsaW5lJyxcbiAgICBpbmRleDogckxldmVsLFxuICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgc2hhcGU6IGdldFJhZGFyU2hhcGUocmFkYXJJdGVtKSxcbiAgICBzdHlsZTogZ2V0UmFkYXJTdHlsZShyYWRhckl0ZW0pXG4gIH1dO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydFJhZGFyQ29uZmlnKHJhZGFySXRlbSwgdXBkYXRlcikge1xuICB2YXIgY2VudGVyUG9zID0gdXBkYXRlci5jaGFydC5yYWRhckF4aXMuY2VudGVyUG9zO1xuICB2YXIgY29uZmlnID0gZ2V0UmFkYXJDb25maWcocmFkYXJJdGVtKVswXTtcbiAgdmFyIHBvaW50TnVtID0gY29uZmlnLnNoYXBlLnBvaW50cy5sZW5ndGg7XG4gIHZhciBwb2ludHMgPSBuZXcgQXJyYXkocG9pbnROdW0pLmZpbGwoMCkubWFwKGZ1bmN0aW9uIChmb28pIHtcbiAgICByZXR1cm4gKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXJQb3MpO1xuICB9KTtcbiAgY29uZmlnLnNoYXBlLnBvaW50cyA9IHBvaW50cztcbiAgcmV0dXJuIFtjb25maWddO1xufVxuXG5mdW5jdGlvbiBnZXRSYWRhclNoYXBlKHJhZGFySXRlbSkge1xuICB2YXIgcmFkYXJQb3NpdGlvbiA9IHJhZGFySXRlbS5yYWRhclBvc2l0aW9uO1xuICByZXR1cm4ge1xuICAgIHBvaW50czogcmFkYXJQb3NpdGlvbixcbiAgICBjbG9zZTogdHJ1ZVxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRSYWRhclN0eWxlKHJhZGFySXRlbSkge1xuICB2YXIgcmFkYXJTdHlsZSA9IHJhZGFySXRlbS5yYWRhclN0eWxlLFxuICAgICAgY29sb3IgPSByYWRhckl0ZW0uY29sb3I7XG4gIHZhciBjb2xvclJnYmFWYWx1ZSA9ICgwLCBfY29sb3IuZ2V0UmdiYVZhbHVlKShjb2xvcik7XG4gIGNvbG9yUmdiYVZhbHVlWzNdID0gMC41O1xuICB2YXIgcmFkYXJEZWZhdWx0Q29sb3IgPSB7XG4gICAgc3Ryb2tlOiBjb2xvcixcbiAgICBmaWxsOiAoMCwgX2NvbG9yLmdldENvbG9yRnJvbVJnYlZhbHVlKShjb2xvclJnYmFWYWx1ZSlcbiAgfTtcbiAgcmV0dXJuICgwLCBfdXRpbDIuZGVlcE1lcmdlKShyYWRhckRlZmF1bHRDb2xvciwgcmFkYXJTdHlsZSk7XG59XG5cbmZ1bmN0aW9uIGJlZm9yZUNoYW5nZVJhZGFyKGdyYXBoLCBfcmVmNCkge1xuICB2YXIgc2hhcGUgPSBfcmVmNC5zaGFwZTtcbiAgdmFyIGdyYXBoUG9pbnRzID0gZ3JhcGguc2hhcGUucG9pbnRzO1xuICB2YXIgZ3JhcGhQb2ludHNOdW0gPSBncmFwaFBvaW50cy5sZW5ndGg7XG4gIHZhciBwb2ludHNOdW0gPSBzaGFwZS5wb2ludHMubGVuZ3RoO1xuXG4gIGlmIChwb2ludHNOdW0gPiBncmFwaFBvaW50c051bSkge1xuICAgIHZhciBsYXN0UG9pbnQgPSBncmFwaFBvaW50cy5zbGljZSgtMSlbMF07XG4gICAgdmFyIG5ld0FkZFBvaW50cyA9IG5ldyBBcnJheShwb2ludHNOdW0gLSBncmFwaFBvaW50c051bSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbykge1xuICAgICAgcmV0dXJuICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobGFzdFBvaW50KTtcbiAgICB9KTtcbiAgICBncmFwaFBvaW50cy5wdXNoLmFwcGx5KGdyYXBoUG9pbnRzLCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKG5ld0FkZFBvaW50cykpO1xuICB9IGVsc2UgaWYgKHBvaW50c051bSA8IGdyYXBoUG9pbnRzTnVtKSB7XG4gICAgZ3JhcGhQb2ludHMuc3BsaWNlKHBvaW50c051bSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0UG9pbnRDb25maWcocmFkYXJJdGVtKSB7XG4gIHZhciByYWRhclBvc2l0aW9uID0gcmFkYXJJdGVtLnJhZGFyUG9zaXRpb24sXG4gICAgICBhbmltYXRpb25DdXJ2ZSA9IHJhZGFySXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gcmFkYXJJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gcmFkYXJJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIHJhZGFyUG9zaXRpb24ubWFwKGZ1bmN0aW9uIChmb28sIGkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ2NpcmNsZScsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgdmlzaWJsZTogcmFkYXJJdGVtLnBvaW50LnNob3csXG4gICAgICBzaGFwZTogZ2V0UG9pbnRTaGFwZShyYWRhckl0ZW0sIGkpLFxuICAgICAgc3R5bGU6IGdldFBvaW50U3R5bGUocmFkYXJJdGVtLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRTdGFydFBvaW50Q29uZmlnKHJhZGFySXRlbSkge1xuICB2YXIgY29uZmlncyA9IGdldFBvaW50Q29uZmlnKHJhZGFySXRlbSk7XG4gIGNvbmZpZ3MuZm9yRWFjaChmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgcmV0dXJuIGNvbmZpZy5zaGFwZS5yID0gMC4wMTtcbiAgfSk7XG4gIHJldHVybiBjb25maWdzO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludFNoYXBlKHJhZGFySXRlbSwgaSkge1xuICB2YXIgcmFkYXJQb3NpdGlvbiA9IHJhZGFySXRlbS5yYWRhclBvc2l0aW9uLFxuICAgICAgcG9pbnQgPSByYWRhckl0ZW0ucG9pbnQ7XG4gIHZhciByYWRpdXMgPSBwb2ludC5yYWRpdXM7XG4gIHZhciBwb3NpdGlvbiA9IHJhZGFyUG9zaXRpb25baV07XG4gIHJldHVybiB7XG4gICAgcng6IHBvc2l0aW9uWzBdLFxuICAgIHJ5OiBwb3NpdGlvblsxXSxcbiAgICByOiByYWRpdXNcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UG9pbnRTdHlsZShyYWRhckl0ZW0sIGkpIHtcbiAgdmFyIHBvaW50ID0gcmFkYXJJdGVtLnBvaW50LFxuICAgICAgY29sb3IgPSByYWRhckl0ZW0uY29sb3I7XG4gIHZhciBzdHlsZSA9IHBvaW50LnN0eWxlO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHtcbiAgICBzdHJva2U6IGNvbG9yXG4gIH0sIHN0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0TGFiZWxDb25maWcocmFkYXJJdGVtKSB7XG4gIHZhciBsYWJlbFBvc2l0aW9uID0gcmFkYXJJdGVtLmxhYmVsUG9zaXRpb24sXG4gICAgICBhbmltYXRpb25DdXJ2ZSA9IHJhZGFySXRlbS5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gcmFkYXJJdGVtLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gcmFkYXJJdGVtLnJMZXZlbDtcbiAgcmV0dXJuIGxhYmVsUG9zaXRpb24ubWFwKGZ1bmN0aW9uIChmb28sIGkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ3RleHQnLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IHJhZGFySXRlbS5sYWJlbC5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IGdldExhYmVsU2hhcGUocmFkYXJJdGVtLCBpKSxcbiAgICAgIHN0eWxlOiBnZXRMYWJlbFN0eWxlKHJhZGFySXRlbSwgaSlcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0TGFiZWxTaGFwZShyYWRhckl0ZW0sIGkpIHtcbiAgdmFyIGxhYmVsUG9zaXRpb24gPSByYWRhckl0ZW0ubGFiZWxQb3NpdGlvbixcbiAgICAgIGxhYmVsID0gcmFkYXJJdGVtLmxhYmVsLFxuICAgICAgZGF0YSA9IHJhZGFySXRlbS5kYXRhO1xuICB2YXIgb2Zmc2V0ID0gbGFiZWwub2Zmc2V0LFxuICAgICAgZm9ybWF0dGVyID0gbGFiZWwuZm9ybWF0dGVyO1xuICB2YXIgcG9zaXRpb24gPSBtZXJnZVBvaW50T2Zmc2V0KGxhYmVsUG9zaXRpb25baV0sIG9mZnNldCk7XG4gIHZhciBsYWJlbFRleHQgPSBkYXRhW2ldID8gZGF0YVtpXS50b1N0cmluZygpIDogJzAnO1xuICB2YXIgZm9ybWF0dGVyVHlwZSA9ICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKGZvcm1hdHRlcik7XG4gIGlmIChmb3JtYXR0ZXJUeXBlID09PSAnc3RyaW5nJykgbGFiZWxUZXh0ID0gZm9ybWF0dGVyLnJlcGxhY2UoJ3t2YWx1ZX0nLCBsYWJlbFRleHQpO1xuICBpZiAoZm9ybWF0dGVyVHlwZSA9PT0gJ2Z1bmN0aW9uJykgbGFiZWxUZXh0ID0gZm9ybWF0dGVyKGxhYmVsVGV4dCk7XG4gIHJldHVybiB7XG4gICAgY29udGVudDogbGFiZWxUZXh0LFxuICAgIHBvc2l0aW9uOiBwb3NpdGlvblxuICB9O1xufVxuXG5mdW5jdGlvbiBtZXJnZVBvaW50T2Zmc2V0KF9yZWY1LCBfcmVmNikge1xuICB2YXIgX3JlZjcgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjUsIDIpLFxuICAgICAgeCA9IF9yZWY3WzBdLFxuICAgICAgeSA9IF9yZWY3WzFdO1xuXG4gIHZhciBfcmVmOCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmNiwgMiksXG4gICAgICBveCA9IF9yZWY4WzBdLFxuICAgICAgb3kgPSBfcmVmOFsxXTtcblxuICByZXR1cm4gW3ggKyBveCwgeSArIG95XTtcbn1cblxuZnVuY3Rpb24gZ2V0TGFiZWxTdHlsZShyYWRhckl0ZW0sIGkpIHtcbiAgdmFyIGxhYmVsID0gcmFkYXJJdGVtLmxhYmVsLFxuICAgICAgY29sb3IgPSByYWRhckl0ZW0uY29sb3IsXG4gICAgICBsYWJlbEFsaWduID0gcmFkYXJJdGVtLmxhYmVsQWxpZ247XG4gIHZhciBzdHlsZSA9IGxhYmVsLnN0eWxlO1xuXG4gIHZhciBkZWZhdWx0Q29sb3JBbmRBbGlnbiA9IF9vYmplY3RTcHJlYWQoe1xuICAgIGZpbGw6IGNvbG9yXG4gIH0sIGxhYmVsQWxpZ25baV0pO1xuXG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoZGVmYXVsdENvbG9yQW5kQWxpZ24sIHN0eWxlKTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLnJhZGFyQXhpcyA9IHJhZGFyQXhpcztcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfZGVmaW5lUHJvcGVydHkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9kZWZpbmVQcm9wZXJ0eVwiKSk7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdXBkYXRlciA9IHJlcXVpcmUoXCIuLi9jbGFzcy91cGRhdGVyLmNsYXNzXCIpO1xuXG52YXIgX2luZGV4ID0gcmVxdWlyZShcIi4uL2NvbmZpZy9pbmRleFwiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG52YXIgX3V0aWwyID0gcmVxdWlyZShcIi4uL3V0aWxcIik7XG5cbmZ1bmN0aW9uIG93bktleXMob2JqZWN0LCBlbnVtZXJhYmxlT25seSkgeyB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG9iamVjdCk7IGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7IHZhciBzeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmplY3QpOyBpZiAoZW51bWVyYWJsZU9ubHkpIHN5bWJvbHMgPSBzeW1ib2xzLmZpbHRlcihmdW5jdGlvbiAoc3ltKSB7IHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgc3ltKS5lbnVtZXJhYmxlOyB9KTsga2V5cy5wdXNoLmFwcGx5KGtleXMsIHN5bWJvbHMpOyB9IHJldHVybiBrZXlzOyB9XG5cbmZ1bmN0aW9uIF9vYmplY3RTcHJlYWQodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV0gIT0gbnVsbCA/IGFyZ3VtZW50c1tpXSA6IHt9OyBpZiAoaSAlIDIpIHsgb3duS2V5cyhzb3VyY2UsIHRydWUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyAoMCwgX2RlZmluZVByb3BlcnR5MltcImRlZmF1bHRcIl0pKHRhcmdldCwga2V5LCBzb3VyY2Vba2V5XSk7IH0pOyB9IGVsc2UgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoc291cmNlKSk7IH0gZWxzZSB7IG93bktleXMoc291cmNlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHNvdXJjZSwga2V5KSk7IH0pOyB9IH0gcmV0dXJuIHRhcmdldDsgfVxuXG5mdW5jdGlvbiByYWRhckF4aXMoY2hhcnQpIHtcbiAgdmFyIG9wdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG4gIHZhciByYWRhciA9IG9wdGlvbi5yYWRhcjtcbiAgdmFyIHJhZGFyQXhpcyA9IFtdO1xuXG4gIGlmIChyYWRhcikge1xuICAgIHJhZGFyQXhpcyA9IG1lcmdlUmFkYXJBeGlzRGVmYXVsdENvbmZpZyhyYWRhcik7XG4gICAgcmFkYXJBeGlzID0gY2FsY1JhZGFyQXhpc0NlbnRlcihyYWRhckF4aXMsIGNoYXJ0KTtcbiAgICByYWRhckF4aXMgPSBjYWxjUmFkYXJBeGlzUmluZ1JhZGl1cyhyYWRhckF4aXMsIGNoYXJ0KTtcbiAgICByYWRhckF4aXMgPSBjYWxjUmFkYXJBeGlzTGluZVBvc2l0aW9uKHJhZGFyQXhpcyk7XG4gICAgcmFkYXJBeGlzID0gY2FsY1JhZGFyQXhpc0FyZWFSYWRpdXMocmFkYXJBeGlzKTtcbiAgICByYWRhckF4aXMgPSBjYWxjUmFkYXJBeGlzTGFiZWxQb3NpdGlvbihyYWRhckF4aXMpO1xuICAgIHJhZGFyQXhpcyA9IFtyYWRhckF4aXNdO1xuICB9XG5cbiAgdmFyIHJhZGFyQXhpc0ZvclVwZGF0ZSA9IHJhZGFyQXhpcztcbiAgaWYgKHJhZGFyQXhpcy5sZW5ndGggJiYgIXJhZGFyQXhpc1swXS5zaG93KSByYWRhckF4aXNGb3JVcGRhdGUgPSBbXTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogcmFkYXJBeGlzRm9yVXBkYXRlLFxuICAgIGtleTogJ3JhZGFyQXhpc1NwbGl0QXJlYScsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFNwbGl0QXJlYUNvbmZpZyxcbiAgICBiZWZvcmVVcGRhdGU6IGJlZm9yZVVwZGF0ZVNwbGl0QXJlYSxcbiAgICBiZWZvcmVDaGFuZ2U6IGJlZm9yZUNoYW5nZVNwbGl0QXJlYVxuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogcmFkYXJBeGlzRm9yVXBkYXRlLFxuICAgIGtleTogJ3JhZGFyQXhpc1NwbGl0TGluZScsXG4gICAgZ2V0R3JhcGhDb25maWc6IGdldFNwbGl0TGluZUNvbmZpZyxcbiAgICBiZWZvcmVVcGRhdGU6IGJlZm9yZVVwZGF0ZVNwbGl0TGluZSxcbiAgICBiZWZvcmVDaGFuZ2U6IGJlZm9yZUNoYW5nZVNwbGl0TGluZVxuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogcmFkYXJBeGlzRm9yVXBkYXRlLFxuICAgIGtleTogJ3JhZGFyQXhpc0xpbmUnLFxuICAgIGdldEdyYXBoQ29uZmlnOiBnZXRBeGlzTGluZUNvbmZpZ1xuICB9KTtcbiAgKDAsIF91cGRhdGVyLmRvVXBkYXRlKSh7XG4gICAgY2hhcnQ6IGNoYXJ0LFxuICAgIHNlcmllczogcmFkYXJBeGlzRm9yVXBkYXRlLFxuICAgIGtleTogJ3JhZGFyQXhpc0xhYmxlJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0QXhpc0xhYmVsQ29uZmlnXG4gIH0pO1xuICBjaGFydC5yYWRhckF4aXMgPSByYWRhckF4aXNbMF07XG59XG5cbmZ1bmN0aW9uIG1lcmdlUmFkYXJBeGlzRGVmYXVsdENvbmZpZyhyYWRhcikge1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKCgwLCBfdXRpbC5kZWVwQ2xvbmUpKF9pbmRleC5yYWRhckF4aXNDb25maWcpLCByYWRhcik7XG59XG5cbmZ1bmN0aW9uIGNhbGNSYWRhckF4aXNDZW50ZXIocmFkYXJBeGlzLCBjaGFydCkge1xuICB2YXIgYXJlYSA9IGNoYXJ0LnJlbmRlci5hcmVhO1xuICB2YXIgY2VudGVyID0gcmFkYXJBeGlzLmNlbnRlcjtcbiAgcmFkYXJBeGlzLmNlbnRlclBvcyA9IGNlbnRlci5tYXAoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICBpZiAodHlwZW9mIHYgPT09ICdudW1iZXInKSByZXR1cm4gdjtcbiAgICByZXR1cm4gcGFyc2VJbnQodikgLyAxMDAgKiBhcmVhW2ldO1xuICB9KTtcbiAgcmV0dXJuIHJhZGFyQXhpcztcbn1cblxuZnVuY3Rpb24gY2FsY1JhZGFyQXhpc1JpbmdSYWRpdXMocmFkYXJBeGlzLCBjaGFydCkge1xuICB2YXIgYXJlYSA9IGNoYXJ0LnJlbmRlci5hcmVhO1xuICB2YXIgc3BsaXROdW0gPSByYWRhckF4aXMuc3BsaXROdW0sXG4gICAgICByYWRpdXMgPSByYWRhckF4aXMucmFkaXVzO1xuICB2YXIgbWF4UmFkaXVzID0gTWF0aC5taW4uYXBwbHkoTWF0aCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShhcmVhKSkgLyAyO1xuICBpZiAodHlwZW9mIHJhZGl1cyAhPT0gJ251bWJlcicpIHJhZGl1cyA9IHBhcnNlSW50KHJhZGl1cykgLyAxMDAgKiBtYXhSYWRpdXM7XG4gIHZhciBzcGxpdEdhcCA9IHJhZGl1cyAvIHNwbGl0TnVtO1xuICByYWRhckF4aXMucmluZ1JhZGl1cyA9IG5ldyBBcnJheShzcGxpdE51bSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiBzcGxpdEdhcCAqIChpICsgMSk7XG4gIH0pO1xuICByYWRhckF4aXMucmFkaXVzID0gcmFkaXVzO1xuICByZXR1cm4gcmFkYXJBeGlzO1xufVxuXG5mdW5jdGlvbiBjYWxjUmFkYXJBeGlzTGluZVBvc2l0aW9uKHJhZGFyQXhpcykge1xuICB2YXIgaW5kaWNhdG9yID0gcmFkYXJBeGlzLmluZGljYXRvcixcbiAgICAgIGNlbnRlclBvcyA9IHJhZGFyQXhpcy5jZW50ZXJQb3MsXG4gICAgICByYWRpdXMgPSByYWRhckF4aXMucmFkaXVzLFxuICAgICAgc3RhcnRBbmdsZSA9IHJhZGFyQXhpcy5zdGFydEFuZ2xlO1xuICB2YXIgZnVsbEFuZ2xlID0gTWF0aC5QSSAqIDI7XG4gIHZhciBpbmRpY2F0b3JOdW0gPSBpbmRpY2F0b3IubGVuZ3RoO1xuICB2YXIgaW5kaWNhdG9yR2FwID0gZnVsbEFuZ2xlIC8gaW5kaWNhdG9yTnVtO1xuICB2YXIgYW5nbGVzID0gbmV3IEFycmF5KGluZGljYXRvck51bSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiBpbmRpY2F0b3JHYXAgKiBpICsgc3RhcnRBbmdsZTtcbiAgfSk7XG4gIHJhZGFyQXhpcy5heGlzTGluZUFuZ2xlcyA9IGFuZ2xlcztcbiAgcmFkYXJBeGlzLmF4aXNMaW5lUG9zaXRpb24gPSBhbmdsZXMubWFwKGZ1bmN0aW9uIChnKSB7XG4gICAgcmV0dXJuIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXJQb3MpLmNvbmNhdChbcmFkaXVzLCBnXSkpO1xuICB9KTtcbiAgcmV0dXJuIHJhZGFyQXhpcztcbn1cblxuZnVuY3Rpb24gY2FsY1JhZGFyQXhpc0FyZWFSYWRpdXMocmFkYXJBeGlzKSB7XG4gIHZhciByaW5nUmFkaXVzID0gcmFkYXJBeGlzLnJpbmdSYWRpdXM7XG4gIHZhciBzdWJSYWRpdXMgPSByaW5nUmFkaXVzWzBdIC8gMjtcbiAgcmFkYXJBeGlzLmFyZWFSYWRpdXMgPSByaW5nUmFkaXVzLm1hcChmdW5jdGlvbiAocikge1xuICAgIHJldHVybiByIC0gc3ViUmFkaXVzO1xuICB9KTtcbiAgcmV0dXJuIHJhZGFyQXhpcztcbn1cblxuZnVuY3Rpb24gY2FsY1JhZGFyQXhpc0xhYmVsUG9zaXRpb24ocmFkYXJBeGlzKSB7XG4gIHZhciBheGlzTGluZUFuZ2xlcyA9IHJhZGFyQXhpcy5heGlzTGluZUFuZ2xlcyxcbiAgICAgIGNlbnRlclBvcyA9IHJhZGFyQXhpcy5jZW50ZXJQb3MsXG4gICAgICByYWRpdXMgPSByYWRhckF4aXMucmFkaXVzLFxuICAgICAgYXhpc0xhYmVsID0gcmFkYXJBeGlzLmF4aXNMYWJlbDtcbiAgcmFkaXVzICs9IGF4aXNMYWJlbC5sYWJlbEdhcDtcbiAgcmFkYXJBeGlzLmF4aXNMYWJlbFBvc2l0aW9uID0gYXhpc0xpbmVBbmdsZXMubWFwKGZ1bmN0aW9uIChhbmdsZSkge1xuICAgIHJldHVybiBfdXRpbC5nZXRDaXJjbGVSYWRpYW5Qb2ludC5hcHBseSh2b2lkIDAsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY2VudGVyUG9zKS5jb25jYXQoW3JhZGl1cywgYW5nbGVdKSk7XG4gIH0pO1xuICByZXR1cm4gcmFkYXJBeGlzO1xufVxuXG5mdW5jdGlvbiBnZXRTcGxpdEFyZWFDb25maWcocmFkYXJBeGlzKSB7XG4gIHZhciBhcmVhUmFkaXVzID0gcmFkYXJBeGlzLmFyZWFSYWRpdXMsXG4gICAgICBwb2x5Z29uID0gcmFkYXJBeGlzLnBvbHlnb24sXG4gICAgICBhbmltYXRpb25DdXJ2ZSA9IHJhZGFyQXhpcy5hbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lID0gcmFkYXJBeGlzLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gcmFkYXJBeGlzLnJMZXZlbDtcbiAgdmFyIG5hbWUgPSBwb2x5Z29uID8gJ3JlZ1BvbHlnb24nIDogJ3JpbmcnO1xuICByZXR1cm4gYXJlYVJhZGl1cy5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IHJMZXZlbCxcbiAgICAgIHZpc2libGU6IHJhZGFyQXhpcy5zcGxpdEFyZWEuc2hvdyxcbiAgICAgIGFuaW1hdGlvbkN1cnZlOiBhbmltYXRpb25DdXJ2ZSxcbiAgICAgIGFuaW1hdGlvbkZyYW1lOiBhbmltYXRpb25GcmFtZSxcbiAgICAgIHNoYXBlOiBnZXRTcGxpdEFyZWFTaGFwZShyYWRhckF4aXMsIGkpLFxuICAgICAgc3R5bGU6IGdldFNwbGl0QXJlYVN0eWxlKHJhZGFyQXhpcywgaSlcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0U3BsaXRBcmVhU2hhcGUocmFkYXJBeGlzLCBpKSB7XG4gIHZhciBwb2x5Z29uID0gcmFkYXJBeGlzLnBvbHlnb24sXG4gICAgICBhcmVhUmFkaXVzID0gcmFkYXJBeGlzLmFyZWFSYWRpdXMsXG4gICAgICBpbmRpY2F0b3IgPSByYWRhckF4aXMuaW5kaWNhdG9yLFxuICAgICAgY2VudGVyUG9zID0gcmFkYXJBeGlzLmNlbnRlclBvcztcbiAgdmFyIGluZGljYXRvck51bSA9IGluZGljYXRvci5sZW5ndGg7XG4gIHZhciBzaGFwZSA9IHtcbiAgICByeDogY2VudGVyUG9zWzBdLFxuICAgIHJ5OiBjZW50ZXJQb3NbMV0sXG4gICAgcjogYXJlYVJhZGl1c1tpXVxuICB9O1xuICBpZiAocG9seWdvbikgc2hhcGUuc2lkZSA9IGluZGljYXRvck51bTtcbiAgcmV0dXJuIHNoYXBlO1xufVxuXG5mdW5jdGlvbiBnZXRTcGxpdEFyZWFTdHlsZShyYWRhckF4aXMsIGkpIHtcbiAgdmFyIHNwbGl0QXJlYSA9IHJhZGFyQXhpcy5zcGxpdEFyZWEsXG4gICAgICByaW5nUmFkaXVzID0gcmFkYXJBeGlzLnJpbmdSYWRpdXMsXG4gICAgICBheGlzTGluZUFuZ2xlcyA9IHJhZGFyQXhpcy5heGlzTGluZUFuZ2xlcyxcbiAgICAgIHBvbHlnb24gPSByYWRhckF4aXMucG9seWdvbixcbiAgICAgIGNlbnRlclBvcyA9IHJhZGFyQXhpcy5jZW50ZXJQb3M7XG4gIHZhciBjb2xvciA9IHNwbGl0QXJlYS5jb2xvcixcbiAgICAgIHN0eWxlID0gc3BsaXRBcmVhLnN0eWxlO1xuICBzdHlsZSA9IF9vYmplY3RTcHJlYWQoe1xuICAgIGZpbGw6ICdyZ2JhKDAsIDAsIDAsIDApJ1xuICB9LCBzdHlsZSk7XG4gIHZhciBsaW5lV2lkdGggPSByaW5nUmFkaXVzWzBdIC0gMDtcblxuICBpZiAocG9seWdvbikge1xuICAgIHZhciBwb2ludDEgPSBfdXRpbC5nZXRDaXJjbGVSYWRpYW5Qb2ludC5hcHBseSh2b2lkIDAsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY2VudGVyUG9zKS5jb25jYXQoW3JpbmdSYWRpdXNbMF0sIGF4aXNMaW5lQW5nbGVzWzBdXSkpO1xuXG4gICAgdmFyIHBvaW50MiA9IF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50LmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjZW50ZXJQb3MpLmNvbmNhdChbcmluZ1JhZGl1c1swXSwgYXhpc0xpbmVBbmdsZXNbMV1dKSk7XG5cbiAgICBsaW5lV2lkdGggPSAoMCwgX3V0aWwyLmdldFBvaW50VG9MaW5lRGlzdGFuY2UpKGNlbnRlclBvcywgcG9pbnQxLCBwb2ludDIpO1xuICB9XG5cbiAgc3R5bGUgPSAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoKDAsIF91dGlsLmRlZXBDbG9uZSkoc3R5bGUsIHRydWUpLCB7XG4gICAgbGluZVdpZHRoOiBsaW5lV2lkdGhcbiAgfSk7XG4gIGlmICghY29sb3IubGVuZ3RoKSByZXR1cm4gc3R5bGU7XG4gIHZhciBjb2xvck51bSA9IGNvbG9yLmxlbmd0aDtcbiAgcmV0dXJuICgwLCBfdXRpbDIuZGVlcE1lcmdlKShzdHlsZSwge1xuICAgIHN0cm9rZTogY29sb3JbaSAlIGNvbG9yTnVtXVxuICB9KTtcbn1cblxuZnVuY3Rpb24gYmVmb3JlVXBkYXRlU3BsaXRBcmVhKGdyYXBocywgcmFkYXJBeGlzLCBpLCB1cGRhdGVyKSB7XG4gIHZhciBjYWNoZSA9IGdyYXBoc1tpXTtcbiAgaWYgKCFjYWNoZSkgcmV0dXJuO1xuICB2YXIgcmVuZGVyID0gdXBkYXRlci5jaGFydC5yZW5kZXI7XG4gIHZhciBwb2x5Z29uID0gcmFkYXJBeGlzLnBvbHlnb247XG4gIHZhciBuYW1lID0gY2FjaGVbMF0ubmFtZTtcbiAgdmFyIGN1cnJlbnROYW1lID0gcG9seWdvbiA/ICdyZWdQb2x5Z29uJyA6ICdyaW5nJztcbiAgdmFyIGRlbEFsbCA9IGN1cnJlbnROYW1lICE9PSBuYW1lO1xuICBpZiAoIWRlbEFsbCkgcmV0dXJuO1xuICBjYWNoZS5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgcmV0dXJuIHJlbmRlci5kZWxHcmFwaChnKTtcbiAgfSk7XG4gIGdyYXBoc1tpXSA9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGJlZm9yZUNoYW5nZVNwbGl0QXJlYShncmFwaCwgY29uZmlnKSB7XG4gIHZhciBzaWRlID0gY29uZmlnLnNoYXBlLnNpZGU7XG4gIGlmICh0eXBlb2Ygc2lkZSAhPT0gJ251bWJlcicpIHJldHVybjtcbiAgZ3JhcGguc2hhcGUuc2lkZSA9IHNpZGU7XG59XG5cbmZ1bmN0aW9uIGdldFNwbGl0TGluZUNvbmZpZyhyYWRhckF4aXMpIHtcbiAgdmFyIHJpbmdSYWRpdXMgPSByYWRhckF4aXMucmluZ1JhZGl1cyxcbiAgICAgIHBvbHlnb24gPSByYWRhckF4aXMucG9seWdvbixcbiAgICAgIGFuaW1hdGlvbkN1cnZlID0gcmFkYXJBeGlzLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSByYWRhckF4aXMuYW5pbWF0aW9uRnJhbWUsXG4gICAgICByTGV2ZWwgPSByYWRhckF4aXMuckxldmVsO1xuICB2YXIgbmFtZSA9IHBvbHlnb24gPyAncmVnUG9seWdvbicgOiAncmluZyc7XG4gIHJldHVybiByaW5nUmFkaXVzLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgdmlzaWJsZTogcmFkYXJBeGlzLnNwbGl0TGluZS5zaG93LFxuICAgICAgc2hhcGU6IGdldFNwbGl0TGluZVNoYXBlKHJhZGFyQXhpcywgaSksXG4gICAgICBzdHlsZTogZ2V0U3BsaXRMaW5lU3R5bGUocmFkYXJBeGlzLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRTcGxpdExpbmVTaGFwZShyYWRhckF4aXMsIGkpIHtcbiAgdmFyIHJpbmdSYWRpdXMgPSByYWRhckF4aXMucmluZ1JhZGl1cyxcbiAgICAgIGNlbnRlclBvcyA9IHJhZGFyQXhpcy5jZW50ZXJQb3MsXG4gICAgICBpbmRpY2F0b3IgPSByYWRhckF4aXMuaW5kaWNhdG9yLFxuICAgICAgcG9seWdvbiA9IHJhZGFyQXhpcy5wb2x5Z29uO1xuICB2YXIgc2hhcGUgPSB7XG4gICAgcng6IGNlbnRlclBvc1swXSxcbiAgICByeTogY2VudGVyUG9zWzFdLFxuICAgIHI6IHJpbmdSYWRpdXNbaV1cbiAgfTtcbiAgdmFyIGluZGljYXRvck51bSA9IGluZGljYXRvci5sZW5ndGg7XG4gIGlmIChwb2x5Z29uKSBzaGFwZS5zaWRlID0gaW5kaWNhdG9yTnVtO1xuICByZXR1cm4gc2hhcGU7XG59XG5cbmZ1bmN0aW9uIGdldFNwbGl0TGluZVN0eWxlKHJhZGFyQXhpcywgaSkge1xuICB2YXIgc3BsaXRMaW5lID0gcmFkYXJBeGlzLnNwbGl0TGluZTtcbiAgdmFyIGNvbG9yID0gc3BsaXRMaW5lLmNvbG9yLFxuICAgICAgc3R5bGUgPSBzcGxpdExpbmUuc3R5bGU7XG4gIHN0eWxlID0gX29iamVjdFNwcmVhZCh7XG4gICAgZmlsbDogJ3JnYmEoMCwgMCwgMCwgMCknXG4gIH0sIHN0eWxlKTtcbiAgaWYgKCFjb2xvci5sZW5ndGgpIHJldHVybiBzdHlsZTtcbiAgdmFyIGNvbG9yTnVtID0gY29sb3IubGVuZ3RoO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHN0eWxlLCB7XG4gICAgc3Ryb2tlOiBjb2xvcltpICUgY29sb3JOdW1dXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBiZWZvcmVVcGRhdGVTcGxpdExpbmUoZ3JhcGhzLCByYWRhckF4aXMsIGksIHVwZGF0ZXIpIHtcbiAgdmFyIGNhY2hlID0gZ3JhcGhzW2ldO1xuICBpZiAoIWNhY2hlKSByZXR1cm47XG4gIHZhciByZW5kZXIgPSB1cGRhdGVyLmNoYXJ0LnJlbmRlcjtcbiAgdmFyIHBvbHlnb24gPSByYWRhckF4aXMucG9seWdvbjtcbiAgdmFyIG5hbWUgPSBjYWNoZVswXS5uYW1lO1xuICB2YXIgY3VycmVuTmFtZSA9IHBvbHlnb24gPyAncmVnUG9seWdvbicgOiAncmluZyc7XG4gIHZhciBkZWxBbGwgPSBjdXJyZW5OYW1lICE9PSBuYW1lO1xuICBpZiAoIWRlbEFsbCkgcmV0dXJuO1xuICBjYWNoZS5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgcmV0dXJuIHJlbmRlci5kZWxHcmFwaChnKTtcbiAgfSk7XG4gIGdyYXBoc1tpXSA9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGJlZm9yZUNoYW5nZVNwbGl0TGluZShncmFwaCwgY29uZmlnKSB7XG4gIHZhciBzaWRlID0gY29uZmlnLnNoYXBlLnNpZGU7XG4gIGlmICh0eXBlb2Ygc2lkZSAhPT0gJ251bWJlcicpIHJldHVybjtcbiAgZ3JhcGguc2hhcGUuc2lkZSA9IHNpZGU7XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMaW5lQ29uZmlnKHJhZGFyQXhpcykge1xuICB2YXIgYXhpc0xpbmVQb3NpdGlvbiA9IHJhZGFyQXhpcy5heGlzTGluZVBvc2l0aW9uLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSByYWRhckF4aXMuYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZSA9IHJhZGFyQXhpcy5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IHJhZGFyQXhpcy5yTGV2ZWw7XG4gIHJldHVybiBheGlzTGluZVBvc2l0aW9uLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdwb2x5bGluZScsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogcmFkYXJBeGlzLmF4aXNMaW5lLnNob3csXG4gICAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZTogYW5pbWF0aW9uRnJhbWUsXG4gICAgICBzaGFwZTogZ2V0QXhpc0xpbmVTaGFwZShyYWRhckF4aXMsIGkpLFxuICAgICAgc3R5bGU6IGdldEF4aXNMaW5lU3R5bGUocmFkYXJBeGlzLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRBeGlzTGluZVNoYXBlKHJhZGFyQXhpcywgaSkge1xuICB2YXIgY2VudGVyUG9zID0gcmFkYXJBeGlzLmNlbnRlclBvcyxcbiAgICAgIGF4aXNMaW5lUG9zaXRpb24gPSByYWRhckF4aXMuYXhpc0xpbmVQb3NpdGlvbjtcbiAgdmFyIHBvaW50cyA9IFtjZW50ZXJQb3MsIGF4aXNMaW5lUG9zaXRpb25baV1dO1xuICByZXR1cm4ge1xuICAgIHBvaW50czogcG9pbnRzXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMaW5lU3R5bGUocmFkYXJBeGlzLCBpKSB7XG4gIHZhciBheGlzTGluZSA9IHJhZGFyQXhpcy5heGlzTGluZTtcbiAgdmFyIGNvbG9yID0gYXhpc0xpbmUuY29sb3IsXG4gICAgICBzdHlsZSA9IGF4aXNMaW5lLnN0eWxlO1xuICBpZiAoIWNvbG9yLmxlbmd0aCkgcmV0dXJuIHN0eWxlO1xuICB2YXIgY29sb3JOdW0gPSBjb2xvci5sZW5ndGg7XG4gIHJldHVybiAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoc3R5bGUsIHtcbiAgICBzdHJva2U6IGNvbG9yW2kgJSBjb2xvck51bV1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMYWJlbENvbmZpZyhyYWRhckF4aXMpIHtcbiAgdmFyIGF4aXNMYWJlbFBvc2l0aW9uID0gcmFkYXJBeGlzLmF4aXNMYWJlbFBvc2l0aW9uLFxuICAgICAgYW5pbWF0aW9uQ3VydmUgPSByYWRhckF4aXMuYW5pbWF0aW9uQ3VydmUsXG4gICAgICBhbmltYXRpb25GcmFtZSA9IHJhZGFyQXhpcy5hbmltYXRpb25GcmFtZSxcbiAgICAgIHJMZXZlbCA9IHJhZGFyQXhpcy5yTGV2ZWw7XG4gIHJldHVybiBheGlzTGFiZWxQb3NpdGlvbi5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAndGV4dCcsXG4gICAgICBpbmRleDogckxldmVsLFxuICAgICAgdmlzaWJsZTogcmFkYXJBeGlzLmF4aXNMYWJlbC5zaG93LFxuICAgICAgYW5pbWF0aW9uQ3VydmU6IGFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgICAgc2hhcGU6IGdldEF4aXNMYWJsZVNoYXBlKHJhZGFyQXhpcywgaSksXG4gICAgICBzdHlsZTogZ2V0QXhpc0xhYmxlU3R5bGUocmFkYXJBeGlzLCBpKVxuICAgIH07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRBeGlzTGFibGVTaGFwZShyYWRhckF4aXMsIGkpIHtcbiAgdmFyIGF4aXNMYWJlbFBvc2l0aW9uID0gcmFkYXJBeGlzLmF4aXNMYWJlbFBvc2l0aW9uLFxuICAgICAgaW5kaWNhdG9yID0gcmFkYXJBeGlzLmluZGljYXRvcjtcbiAgcmV0dXJuIHtcbiAgICBjb250ZW50OiBpbmRpY2F0b3JbaV0ubmFtZSxcbiAgICBwb3NpdGlvbjogYXhpc0xhYmVsUG9zaXRpb25baV1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0QXhpc0xhYmxlU3R5bGUocmFkYXJBeGlzLCBpKSB7XG4gIHZhciBheGlzTGFiZWwgPSByYWRhckF4aXMuYXhpc0xhYmVsLFxuICAgICAgX3JhZGFyQXhpcyRjZW50ZXJQb3MgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocmFkYXJBeGlzLmNlbnRlclBvcywgMiksXG4gICAgICB4ID0gX3JhZGFyQXhpcyRjZW50ZXJQb3NbMF0sXG4gICAgICB5ID0gX3JhZGFyQXhpcyRjZW50ZXJQb3NbMV0sXG4gICAgICBheGlzTGFiZWxQb3NpdGlvbiA9IHJhZGFyQXhpcy5heGlzTGFiZWxQb3NpdGlvbjtcblxuICB2YXIgY29sb3IgPSBheGlzTGFiZWwuY29sb3IsXG4gICAgICBzdHlsZSA9IGF4aXNMYWJlbC5zdHlsZTtcblxuICB2YXIgX2F4aXNMYWJlbFBvc2l0aW9uJGkgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoYXhpc0xhYmVsUG9zaXRpb25baV0sIDIpLFxuICAgICAgbGFiZWxYcG9zID0gX2F4aXNMYWJlbFBvc2l0aW9uJGlbMF0sXG4gICAgICBsYWJlbFlQb3MgPSBfYXhpc0xhYmVsUG9zaXRpb24kaVsxXTtcblxuICB2YXIgdGV4dEFsaWduID0gbGFiZWxYcG9zID4geCA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gIHZhciB0ZXh0QmFzZWxpbmUgPSBsYWJlbFlQb3MgPiB5ID8gJ3RvcCcgOiAnYm90dG9tJztcbiAgc3R5bGUgPSAoMCwgX3V0aWwyLmRlZXBNZXJnZSkoe1xuICAgIHRleHRBbGlnbjogdGV4dEFsaWduLFxuICAgIHRleHRCYXNlbGluZTogdGV4dEJhc2VsaW5lXG4gIH0sIHN0eWxlKTtcbiAgaWYgKCFjb2xvci5sZW5ndGgpIHJldHVybiBzdHlsZTtcbiAgdmFyIGNvbG9yTnVtID0gY29sb3IubGVuZ3RoO1xuICByZXR1cm4gKDAsIF91dGlsMi5kZWVwTWVyZ2UpKHN0eWxlLCB7XG4gICAgZmlsbDogY29sb3JbaSAlIGNvbG9yTnVtXVxuICB9KTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLnRpdGxlID0gdGl0bGU7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX3VwZGF0ZXIgPSByZXF1aXJlKFwiLi4vY2xhc3MvdXBkYXRlci5jbGFzc1wiKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG52YXIgX2NvbmZpZyA9IHJlcXVpcmUoXCIuLi9jb25maWdcIik7XG5cbnZhciBfdXRpbDIgPSByZXF1aXJlKFwiLi4vdXRpbFwiKTtcblxuZnVuY3Rpb24gdGl0bGUoY2hhcnQpIHtcbiAgdmFyIG9wdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG4gIHZhciB0aXRsZSA9IFtdO1xuXG4gIGlmIChvcHRpb24udGl0bGUpIHtcbiAgICB0aXRsZVswXSA9ICgwLCBfdXRpbDIuZGVlcE1lcmdlKSgoMCwgX3V0aWwuZGVlcENsb25lKShfY29uZmlnLnRpdGxlQ29uZmlnLCB0cnVlKSwgb3B0aW9uLnRpdGxlKTtcbiAgfVxuXG4gICgwLCBfdXBkYXRlci5kb1VwZGF0ZSkoe1xuICAgIGNoYXJ0OiBjaGFydCxcbiAgICBzZXJpZXM6IHRpdGxlLFxuICAgIGtleTogJ3RpdGxlJyxcbiAgICBnZXRHcmFwaENvbmZpZzogZ2V0VGl0bGVDb25maWdcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFRpdGxlQ29uZmlnKHRpdGxlSXRlbSwgdXBkYXRlcikge1xuICB2YXIgYW5pbWF0aW9uQ3VydmUgPSBfY29uZmlnLnRpdGxlQ29uZmlnLmFuaW1hdGlvbkN1cnZlLFxuICAgICAgYW5pbWF0aW9uRnJhbWUgPSBfY29uZmlnLnRpdGxlQ29uZmlnLmFuaW1hdGlvbkZyYW1lLFxuICAgICAgckxldmVsID0gX2NvbmZpZy50aXRsZUNvbmZpZy5yTGV2ZWw7XG4gIHZhciBzaGFwZSA9IGdldFRpdGxlU2hhcGUodGl0bGVJdGVtLCB1cGRhdGVyKTtcbiAgdmFyIHN0eWxlID0gZ2V0VGl0bGVTdHlsZSh0aXRsZUl0ZW0pO1xuICByZXR1cm4gW3tcbiAgICBuYW1lOiAndGV4dCcsXG4gICAgaW5kZXg6IHJMZXZlbCxcbiAgICB2aXNpYmxlOiB0aXRsZUl0ZW0uc2hvdyxcbiAgICBhbmltYXRpb25DdXJ2ZTogYW5pbWF0aW9uQ3VydmUsXG4gICAgYW5pbWF0aW9uRnJhbWU6IGFuaW1hdGlvbkZyYW1lLFxuICAgIHNoYXBlOiBzaGFwZSxcbiAgICBzdHlsZTogc3R5bGVcbiAgfV07XG59XG5cbmZ1bmN0aW9uIGdldFRpdGxlU2hhcGUodGl0bGVJdGVtLCB1cGRhdGVyKSB7XG4gIHZhciBvZmZzZXQgPSB0aXRsZUl0ZW0ub2Zmc2V0LFxuICAgICAgdGV4dCA9IHRpdGxlSXRlbS50ZXh0O1xuICB2YXIgX3VwZGF0ZXIkY2hhcnQkZ3JpZEFyID0gdXBkYXRlci5jaGFydC5ncmlkQXJlYSxcbiAgICAgIHggPSBfdXBkYXRlciRjaGFydCRncmlkQXIueCxcbiAgICAgIHkgPSBfdXBkYXRlciRjaGFydCRncmlkQXIueSxcbiAgICAgIHcgPSBfdXBkYXRlciRjaGFydCRncmlkQXIudztcblxuICB2YXIgX29mZnNldCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShvZmZzZXQsIDIpLFxuICAgICAgb3ggPSBfb2Zmc2V0WzBdLFxuICAgICAgb3kgPSBfb2Zmc2V0WzFdO1xuXG4gIHJldHVybiB7XG4gICAgY29udGVudDogdGV4dCxcbiAgICBwb3NpdGlvbjogW3ggKyB3IC8gMiArIG94LCB5ICsgb3ldXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFRpdGxlU3R5bGUodGl0bGVJdGVtKSB7XG4gIHZhciBzdHlsZSA9IHRpdGxlSXRlbS5zdHlsZTtcbiAgcmV0dXJuIHN0eWxlO1xufSIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIF9jUmVuZGVyID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXJcIik7XG5cbnZhciBfdXRpbCA9IHJlcXVpcmUoXCJAamlhbWluZ2hpL2MtcmVuZGVyL2xpYi9wbHVnaW4vdXRpbFwiKTtcblxudmFyIF9jb2xvciA9IHJlcXVpcmUoXCJAamlhbWluZ2hpL2NvbG9yXCIpO1xuXG52YXIgX2luZGV4ID0gcmVxdWlyZShcIi4uL3V0aWwvaW5kZXhcIik7XG5cbnZhciBwaWUgPSB7XG4gIHNoYXBlOiB7XG4gICAgcng6IDAsXG4gICAgcnk6IDAsXG4gICAgaXI6IDAsXG4gICAgb3I6IDAsXG4gICAgc3RhcnRBbmdsZTogMCxcbiAgICBlbmRBbmdsZTogMCxcbiAgICBjbG9ja1dpc2U6IHRydWVcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZikge1xuICAgIHZhciBzaGFwZSA9IF9yZWYuc2hhcGU7XG4gICAgdmFyIGtleXMgPSBbJ3J4JywgJ3J5JywgJ2lyJywgJ29yJywgJ3N0YXJ0QW5nbGUnLCAnZW5kQW5nbGUnXTtcblxuICAgIGlmIChrZXlzLmZpbmQoZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiBzaGFwZVtrZXldICE9PSAnbnVtYmVyJztcbiAgICB9KSkge1xuICAgICAgY29uc29sZS5lcnJvcignUGllIHNoYXBlIGNvbmZpZ3VyYXRpb24gaXMgYWJub3JtYWwhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjIsIF9yZWYzKSB7XG4gICAgdmFyIGN0eCA9IF9yZWYyLmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMy5zaGFwZTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIGlyID0gc2hhcGUuaXIsXG4gICAgICAgIG9yID0gc2hhcGUub3IsXG4gICAgICAgIHN0YXJ0QW5nbGUgPSBzaGFwZS5zdGFydEFuZ2xlLFxuICAgICAgICBlbmRBbmdsZSA9IHNoYXBlLmVuZEFuZ2xlLFxuICAgICAgICBjbG9ja1dpc2UgPSBzaGFwZS5jbG9ja1dpc2U7XG4gICAgcnggPSBwYXJzZUludChyeCkgKyAwLjU7XG4gICAgcnkgPSBwYXJzZUludChyeSkgKyAwLjU7XG4gICAgY3R4LmFyYyhyeCwgcnksIGlyID4gMCA/IGlyIDogMCwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsICFjbG9ja1dpc2UpO1xuICAgIHZhciBjb25uZWN0UG9pbnQxID0gKDAsIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50KShyeCwgcnksIG9yLCBlbmRBbmdsZSkubWFwKGZ1bmN0aW9uIChwKSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnQocCkgKyAwLjU7XG4gICAgfSk7XG4gICAgdmFyIGNvbm5lY3RQb2ludDIgPSAoMCwgX3V0aWwuZ2V0Q2lyY2xlUmFkaWFuUG9pbnQpKHJ4LCByeSwgaXIsIHN0YXJ0QW5nbGUpLm1hcChmdW5jdGlvbiAocCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHApICsgMC41O1xuICAgIH0pO1xuICAgIGN0eC5saW5lVG8uYXBwbHkoY3R4LCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNvbm5lY3RQb2ludDEpKTtcbiAgICBjdHguYXJjKHJ4LCByeSwgb3IgPiAwID8gb3IgOiAwLCBlbmRBbmdsZSwgc3RhcnRBbmdsZSwgY2xvY2tXaXNlKTtcbiAgICBjdHgubGluZVRvLmFwcGx5KGN0eCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShjb25uZWN0UG9pbnQyKSk7XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguZmlsbCgpO1xuICB9XG59O1xudmFyIGFnQXJjID0ge1xuICBzaGFwZToge1xuICAgIHJ4OiAwLFxuICAgIHJ5OiAwLFxuICAgIHI6IDAsXG4gICAgc3RhcnRBbmdsZTogMCxcbiAgICBlbmRBbmdsZTogMCxcbiAgICBncmFkaWVudFN0YXJ0QW5nbGU6IG51bGwsXG4gICAgZ3JhZGllbnRFbmRBbmdsZTogbnVsbFxuICB9LFxuICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihfcmVmNCkge1xuICAgIHZhciBzaGFwZSA9IF9yZWY0LnNoYXBlO1xuICAgIHZhciBrZXlzID0gWydyeCcsICdyeScsICdyJywgJ3N0YXJ0QW5nbGUnLCAnZW5kQW5nbGUnXTtcblxuICAgIGlmIChrZXlzLmZpbmQoZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiBzaGFwZVtrZXldICE9PSAnbnVtYmVyJztcbiAgICB9KSkge1xuICAgICAgY29uc29sZS5lcnJvcignQWdBcmMgc2hhcGUgY29uZmlndXJhdGlvbiBpcyBhYm5vcm1hbCEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgZHJhdzogZnVuY3Rpb24gZHJhdyhfcmVmNSwgX3JlZjYpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjUuY3R4O1xuICAgIHZhciBzaGFwZSA9IF9yZWY2LnNoYXBlLFxuICAgICAgICBzdHlsZSA9IF9yZWY2LnN0eWxlO1xuICAgIHZhciBncmFkaWVudCA9IHN0eWxlLmdyYWRpZW50O1xuICAgIGdyYWRpZW50ID0gZ3JhZGllbnQubWFwKGZ1bmN0aW9uIChjdikge1xuICAgICAgcmV0dXJuICgwLCBfY29sb3IuZ2V0Q29sb3JGcm9tUmdiVmFsdWUpKGN2KTtcbiAgICB9KTtcblxuICAgIGlmIChncmFkaWVudC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGdyYWRpZW50ID0gW2dyYWRpZW50WzBdLCBncmFkaWVudFswXV07XG4gICAgfVxuXG4gICAgdmFyIGdyYWRpZW50QXJjTnVtID0gZ3JhZGllbnQubGVuZ3RoIC0gMTtcbiAgICB2YXIgZ3JhZGllbnRTdGFydEFuZ2xlID0gc2hhcGUuZ3JhZGllbnRTdGFydEFuZ2xlLFxuICAgICAgICBncmFkaWVudEVuZEFuZ2xlID0gc2hhcGUuZ3JhZGllbnRFbmRBbmdsZSxcbiAgICAgICAgc3RhcnRBbmdsZSA9IHNoYXBlLnN0YXJ0QW5nbGUsXG4gICAgICAgIGVuZEFuZ2xlID0gc2hhcGUuZW5kQW5nbGUsXG4gICAgICAgIHIgPSBzaGFwZS5yLFxuICAgICAgICByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5O1xuICAgIGlmIChncmFkaWVudFN0YXJ0QW5nbGUgPT09IG51bGwpIGdyYWRpZW50U3RhcnRBbmdsZSA9IHN0YXJ0QW5nbGU7XG4gICAgaWYgKGdyYWRpZW50RW5kQW5nbGUgPT09IG51bGwpIGdyYWRpZW50RW5kQW5nbGUgPSBlbmRBbmdsZTtcbiAgICB2YXIgYW5nbGVHYXAgPSAoZ3JhZGllbnRFbmRBbmdsZSAtIGdyYWRpZW50U3RhcnRBbmdsZSkgLyBncmFkaWVudEFyY051bTtcbiAgICBpZiAoYW5nbGVHYXAgPT09IE1hdGguUEkgKiAyKSBhbmdsZUdhcCA9IE1hdGguUEkgKiAyIC0gMC4wMDE7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGdyYWRpZW50QXJjTnVtOyBpKyspIHtcbiAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgIHZhciBzdGFydFBvaW50ID0gKDAsIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50KShyeCwgcnksIHIsIHN0YXJ0QW5nbGUgKyBhbmdsZUdhcCAqIGkpO1xuICAgICAgdmFyIGVuZFBvaW50ID0gKDAsIF91dGlsLmdldENpcmNsZVJhZGlhblBvaW50KShyeCwgcnksIHIsIHN0YXJ0QW5nbGUgKyBhbmdsZUdhcCAqIChpICsgMSkpO1xuICAgICAgdmFyIGNvbG9yID0gKDAsIF9pbmRleC5nZXRMaW5lYXJHcmFkaWVudENvbG9yKShjdHgsIHN0YXJ0UG9pbnQsIGVuZFBvaW50LCBbZ3JhZGllbnRbaV0sIGdyYWRpZW50W2kgKyAxXV0pO1xuICAgICAgdmFyIGFyY1N0YXJ0QW5nbGUgPSBzdGFydEFuZ2xlICsgYW5nbGVHYXAgKiBpO1xuICAgICAgdmFyIGFyY0VuZEFuZ2xlID0gc3RhcnRBbmdsZSArIGFuZ2xlR2FwICogKGkgKyAxKTtcbiAgICAgIHZhciBkb0JyZWFrID0gZmFsc2U7XG5cbiAgICAgIGlmIChhcmNFbmRBbmdsZSA+IGVuZEFuZ2xlKSB7XG4gICAgICAgIGFyY0VuZEFuZ2xlID0gZW5kQW5nbGU7XG4gICAgICAgIGRvQnJlYWsgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjdHguYXJjKHJ4LCByeSwgciwgYXJjU3RhcnRBbmdsZSwgYXJjRW5kQW5nbGUpO1xuICAgICAgY3R4LnN0cm9rZVN0eWxlID0gY29sb3I7XG4gICAgICBjdHguc3Ryb2tlKCk7XG4gICAgICBpZiAoZG9CcmVhaykgYnJlYWs7XG4gICAgfVxuICB9XG59O1xudmFyIG51bWJlclRleHQgPSB7XG4gIHNoYXBlOiB7XG4gICAgbnVtYmVyOiBbXSxcbiAgICBjb250ZW50OiAnJyxcbiAgICBwb3NpdGlvbjogWzAsIDBdLFxuICAgIHRvRml4ZWQ6IDBcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjcpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNy5zaGFwZTtcbiAgICB2YXIgbnVtYmVyID0gc2hhcGUubnVtYmVyLFxuICAgICAgICBjb250ZW50ID0gc2hhcGUuY29udGVudCxcbiAgICAgICAgcG9zaXRpb24gPSBzaGFwZS5wb3NpdGlvbjtcblxuICAgIGlmICghKG51bWJlciBpbnN0YW5jZW9mIEFycmF5KSB8fCB0eXBlb2YgY29udGVudCAhPT0gJ3N0cmluZycgfHwgIShwb3NpdGlvbiBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgY29uc29sZS5lcnJvcignTnVtYmVyVGV4dCBzaGFwZSBjb25maWd1cmF0aW9uIGlzIGFibm9ybWFsIScpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBkcmF3OiBmdW5jdGlvbiBkcmF3KF9yZWY4LCBfcmVmOSkge1xuICAgIHZhciBjdHggPSBfcmVmOC5jdHg7XG4gICAgdmFyIHNoYXBlID0gX3JlZjkuc2hhcGU7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIHZhciBudW1iZXIgPSBzaGFwZS5udW1iZXIsXG4gICAgICAgIGNvbnRlbnQgPSBzaGFwZS5jb250ZW50LFxuICAgICAgICBwb3NpdGlvbiA9IHNoYXBlLnBvc2l0aW9uLFxuICAgICAgICB0b0ZpeGVkID0gc2hhcGUudG9GaXhlZDtcbiAgICB2YXIgdGV4dFNlZ21lbnRzID0gY29udGVudC5zcGxpdCgne250fScpO1xuICAgIHZhciBsYXN0U2VnbWVudEluZGV4ID0gdGV4dFNlZ21lbnRzLmxlbmd0aCAtIDE7XG4gICAgdmFyIHRleHRTdHJpbmcgPSAnJztcbiAgICB0ZXh0U2VnbWVudHMuZm9yRWFjaChmdW5jdGlvbiAodCwgaSkge1xuICAgICAgdmFyIGN1cnJlbnROdW1iZXIgPSBudW1iZXJbaV07XG4gICAgICBpZiAoaSA9PT0gbGFzdFNlZ21lbnRJbmRleCkgY3VycmVudE51bWJlciA9ICcnO1xuICAgICAgaWYgKHR5cGVvZiBjdXJyZW50TnVtYmVyID09PSAnbnVtYmVyJykgY3VycmVudE51bWJlciA9IGN1cnJlbnROdW1iZXIudG9GaXhlZCh0b0ZpeGVkKTtcbiAgICAgIHRleHRTdHJpbmcgKz0gdCArIChjdXJyZW50TnVtYmVyIHx8ICcnKTtcbiAgICB9KTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgY3R4LnN0cm9rZVRleHQuYXBwbHkoY3R4LCBbdGV4dFN0cmluZ10uY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9zaXRpb24pKSk7XG4gICAgY3R4LmZpbGxUZXh0LmFwcGx5KGN0eCwgW3RleHRTdHJpbmddLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHBvc2l0aW9uKSkpO1xuICB9XG59O1xudmFyIGxpbmVJY29uID0ge1xuICBzaGFwZToge1xuICAgIHg6IDAsXG4gICAgeTogMCxcbiAgICB3OiAwLFxuICAgIGg6IDBcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjEwKSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjEwLnNoYXBlO1xuICAgIHZhciB4ID0gc2hhcGUueCxcbiAgICAgICAgeSA9IHNoYXBlLnksXG4gICAgICAgIHcgPSBzaGFwZS53LFxuICAgICAgICBoID0gc2hhcGUuaDtcblxuICAgIGlmICh0eXBlb2YgeCAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHkgIT09ICdudW1iZXInIHx8IHR5cGVvZiB3ICE9PSAnbnVtYmVyJyB8fCB0eXBlb2YgaCAhPT0gJ251bWJlcicpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2xpbmVJY29uIHNoYXBlIGNvbmZpZ3VyYXRpb24gaXMgYWJub3JtYWwhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjExLCBfcmVmMTIpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjExLmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMTIuc2hhcGU7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIHZhciB4ID0gc2hhcGUueCxcbiAgICAgICAgeSA9IHNoYXBlLnksXG4gICAgICAgIHcgPSBzaGFwZS53LFxuICAgICAgICBoID0gc2hhcGUuaDtcbiAgICB2YXIgaGFsZkggPSBoIC8gMjtcbiAgICBjdHguc3Ryb2tlU3R5bGUgPSBjdHguZmlsbFN0eWxlO1xuICAgIGN0eC5tb3ZlVG8oeCwgeSArIGhhbGZIKTtcbiAgICBjdHgubGluZVRvKHggKyB3LCB5ICsgaGFsZkgpO1xuICAgIGN0eC5saW5lV2lkdGggPSAxO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHJhZGl1cyA9IGhhbGZIIC0gNSAqIDI7XG4gICAgaWYgKHJhZGl1cyA8PSAwKSByYWRpdXMgPSAzO1xuICAgIGN0eC5hcmMoeCArIHcgLyAyLCB5ICsgaGFsZkgsIHJhZGl1cywgMCwgTWF0aC5QSSAqIDIpO1xuICAgIGN0eC5saW5lV2lkdGggPSA1O1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguZmlsbFN0eWxlID0gJyNmZmYnO1xuICAgIGN0eC5maWxsKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWYxMykge1xuICAgIHZhciBzaGFwZSA9IF9yZWYxMy5zaGFwZTtcbiAgICB2YXIgeCA9IHNoYXBlLngsXG4gICAgICAgIHkgPSBzaGFwZS55LFxuICAgICAgICB3ID0gc2hhcGUudyxcbiAgICAgICAgaCA9IHNoYXBlLmg7XG4gICAgcmV0dXJuICgwLCBfdXRpbC5jaGVja1BvaW50SXNJblJlY3QpKHBvc2l0aW9uLCB4LCB5LCB3LCBoKTtcbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWYxNCkge1xuICAgIHZhciBzaGFwZSA9IF9yZWYxNC5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmMTQuc3R5bGU7XG4gICAgdmFyIHggPSBzaGFwZS54LFxuICAgICAgICB5ID0gc2hhcGUueSxcbiAgICAgICAgdyA9IHNoYXBlLncsXG4gICAgICAgIGggPSBzaGFwZS5oO1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gW3ggKyB3IC8gMiwgeSArIGggLyAyXTtcbiAgfVxufTtcbigwLCBfY1JlbmRlci5leHRlbmROZXdHcmFwaCkoJ3BpZScsIHBpZSk7XG4oMCwgX2NSZW5kZXIuZXh0ZW5kTmV3R3JhcGgpKCdhZ0FyYycsIGFnQXJjKTtcbigwLCBfY1JlbmRlci5leHRlbmROZXdHcmFwaCkoJ251bWJlclRleHQnLCBudW1iZXJUZXh0KTtcbigwLCBfY1JlbmRlci5leHRlbmROZXdHcmFwaCkoJ2xpbmVJY29uJywgbGluZUljb24pOyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImNoYW5nZURlZmF1bHRDb25maWdcIiwge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICByZXR1cm4gX2NvbmZpZy5jaGFuZ2VEZWZhdWx0Q29uZmlnO1xuICB9XG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX2NoYXJ0cyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vY2xhc3MvY2hhcnRzLmNsYXNzXCIpKTtcblxudmFyIF9jb25maWcgPSByZXF1aXJlKFwiLi9jb25maWdcIik7XG5cbnZhciBfZGVmYXVsdCA9IF9jaGFydHNbXCJkZWZhdWx0XCJdO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmZpbHRlck5vbk51bWJlciA9IGZpbHRlck5vbk51bWJlcjtcbmV4cG9ydHMuZGVlcE1lcmdlID0gZGVlcE1lcmdlO1xuZXhwb3J0cy5tdWxBZGQgPSBtdWxBZGQ7XG5leHBvcnRzLm1lcmdlU2FtZVN0YWNrRGF0YSA9IG1lcmdlU2FtZVN0YWNrRGF0YTtcbmV4cG9ydHMuZ2V0VHdvUG9pbnREaXN0YW5jZSA9IGdldFR3b1BvaW50RGlzdGFuY2U7XG5leHBvcnRzLmdldExpbmVhckdyYWRpZW50Q29sb3IgPSBnZXRMaW5lYXJHcmFkaWVudENvbG9yO1xuZXhwb3J0cy5nZXRQb2x5bGluZUxlbmd0aCA9IGdldFBvbHlsaW5lTGVuZ3RoO1xuZXhwb3J0cy5nZXRQb2ludFRvTGluZURpc3RhbmNlID0gZ2V0UG9pbnRUb0xpbmVEaXN0YW5jZTtcbmV4cG9ydHMuaW5pdE5lZWRTZXJpZXMgPSBpbml0TmVlZFNlcmllcztcbmV4cG9ydHMucmFkaWFuVG9BbmdsZSA9IHJhZGlhblRvQW5nbGU7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfdHlwZW9mMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdHlwZW9mXCIpKTtcblxudmFyIF91dGlsID0gcmVxdWlyZShcIkBqaWFtaW5naGkvYy1yZW5kZXIvbGliL3BsdWdpbi91dGlsXCIpO1xuXG5mdW5jdGlvbiBmaWx0ZXJOb25OdW1iZXIoYXJyYXkpIHtcbiAgcmV0dXJuIGFycmF5LmZpbHRlcihmdW5jdGlvbiAobikge1xuICAgIHJldHVybiB0eXBlb2YgbiA9PT0gJ251bWJlcic7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBkZWVwTWVyZ2UodGFyZ2V0LCBtZXJnZWQpIHtcbiAgZm9yICh2YXIga2V5IGluIG1lcmdlZCkge1xuICAgIGlmICh0YXJnZXRba2V5XSAmJiAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKSh0YXJnZXRba2V5XSkgPT09ICdvYmplY3QnKSB7XG4gICAgICBkZWVwTWVyZ2UodGFyZ2V0W2tleV0sIG1lcmdlZFtrZXldKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmICgoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShtZXJnZWRba2V5XSkgPT09ICdvYmplY3QnKSB7XG4gICAgICB0YXJnZXRba2V5XSA9ICgwLCBfdXRpbC5kZWVwQ2xvbmUpKG1lcmdlZFtrZXldLCB0cnVlKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHRhcmdldFtrZXldID0gbWVyZ2VkW2tleV07XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBtdWxBZGQobnVtcykge1xuICBudW1zID0gZmlsdGVyTm9uTnVtYmVyKG51bXMpO1xuICByZXR1cm4gbnVtcy5yZWR1Y2UoZnVuY3Rpb24gKGFsbCwgbnVtKSB7XG4gICAgcmV0dXJuIGFsbCArIG51bTtcbiAgfSwgMCk7XG59XG5cbmZ1bmN0aW9uIG1lcmdlU2FtZVN0YWNrRGF0YShpdGVtLCBzZXJpZXMpIHtcbiAgdmFyIHN0YWNrID0gaXRlbS5zdGFjaztcbiAgaWYgKCFzdGFjaykgcmV0dXJuICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoaXRlbS5kYXRhKTtcbiAgdmFyIHN0YWNrcyA9IHNlcmllcy5maWx0ZXIoZnVuY3Rpb24gKF9yZWYpIHtcbiAgICB2YXIgcyA9IF9yZWYuc3RhY2s7XG4gICAgcmV0dXJuIHMgPT09IHN0YWNrO1xuICB9KTtcbiAgdmFyIGluZGV4ID0gc3RhY2tzLmZpbmRJbmRleChmdW5jdGlvbiAoX3JlZjIpIHtcbiAgICB2YXIgZCA9IF9yZWYyLmRhdGE7XG4gICAgcmV0dXJuIGQgPT09IGl0ZW0uZGF0YTtcbiAgfSk7XG4gIHZhciBkYXRhcyA9IHN0YWNrcy5zcGxpY2UoMCwgaW5kZXggKyAxKS5tYXAoZnVuY3Rpb24gKF9yZWYzKSB7XG4gICAgdmFyIGRhdGEgPSBfcmVmMy5kYXRhO1xuICAgIHJldHVybiBkYXRhO1xuICB9KTtcbiAgdmFyIGRhdGFMZW5ndGggPSBkYXRhc1swXS5sZW5ndGg7XG4gIHJldHVybiBuZXcgQXJyYXkoZGF0YUxlbmd0aCkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiBtdWxBZGQoZGF0YXMubWFwKGZ1bmN0aW9uIChkKSB7XG4gICAgICByZXR1cm4gZFtpXTtcbiAgICB9KSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRUd29Qb2ludERpc3RhbmNlKHBvaW50T25lLCBwb2ludFR3bykge1xuICB2YXIgbWludXNYID0gTWF0aC5hYnMocG9pbnRPbmVbMF0gLSBwb2ludFR3b1swXSk7XG4gIHZhciBtaW51c1kgPSBNYXRoLmFicyhwb2ludE9uZVsxXSAtIHBvaW50VHdvWzFdKTtcbiAgcmV0dXJuIE1hdGguc3FydChtaW51c1ggKiBtaW51c1ggKyBtaW51c1kgKiBtaW51c1kpO1xufVxuXG5mdW5jdGlvbiBnZXRMaW5lYXJHcmFkaWVudENvbG9yKGN0eCwgYmVnaW4sIGVuZCwgY29sb3IpIHtcbiAgaWYgKCFjdHggfHwgIWJlZ2luIHx8ICFlbmQgfHwgIWNvbG9yLmxlbmd0aCkgcmV0dXJuO1xuICB2YXIgY29sb3JzID0gY29sb3I7XG4gIHR5cGVvZiBjb2xvcnMgPT09ICdzdHJpbmcnICYmIChjb2xvcnMgPSBbY29sb3IsIGNvbG9yXSk7XG4gIHZhciBsaW5lYXJHcmFkaWVudENvbG9yID0gY3R4LmNyZWF0ZUxpbmVhckdyYWRpZW50LmFwcGx5KGN0eCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShiZWdpbikuY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoZW5kKSkpO1xuICB2YXIgY29sb3JHYXAgPSAxIC8gKGNvbG9ycy5sZW5ndGggLSAxKTtcbiAgY29sb3JzLmZvckVhY2goZnVuY3Rpb24gKGMsIGkpIHtcbiAgICByZXR1cm4gbGluZWFyR3JhZGllbnRDb2xvci5hZGRDb2xvclN0b3AoY29sb3JHYXAgKiBpLCBjKTtcbiAgfSk7XG4gIHJldHVybiBsaW5lYXJHcmFkaWVudENvbG9yO1xufVxuXG5mdW5jdGlvbiBnZXRQb2x5bGluZUxlbmd0aChwb2ludHMpIHtcbiAgdmFyIGxpbmVTZWdtZW50cyA9IG5ldyBBcnJheShwb2ludHMubGVuZ3RoIC0gMSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKGZvbywgaSkge1xuICAgIHJldHVybiBbcG9pbnRzW2ldLCBwb2ludHNbaSArIDFdXTtcbiAgfSk7XG4gIHZhciBsZW5ndGhzID0gbGluZVNlZ21lbnRzLm1hcChmdW5jdGlvbiAoaXRlbSkge1xuICAgIHJldHVybiBnZXRUd29Qb2ludERpc3RhbmNlLmFwcGx5KHZvaWQgMCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShpdGVtKSk7XG4gIH0pO1xuICByZXR1cm4gbXVsQWRkKGxlbmd0aHMpO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludFRvTGluZURpc3RhbmNlKHBvaW50LCBsaW5lUG9pbnRPbmUsIGxpbmVQb2ludFR3bykge1xuICB2YXIgYSA9IGdldFR3b1BvaW50RGlzdGFuY2UocG9pbnQsIGxpbmVQb2ludE9uZSk7XG4gIHZhciBiID0gZ2V0VHdvUG9pbnREaXN0YW5jZShwb2ludCwgbGluZVBvaW50VHdvKTtcbiAgdmFyIGMgPSBnZXRUd29Qb2ludERpc3RhbmNlKGxpbmVQb2ludE9uZSwgbGluZVBvaW50VHdvKTtcbiAgcmV0dXJuIDAuNSAqIE1hdGguc3FydCgoYSArIGIgKyBjKSAqIChhICsgYiAtIGMpICogKGEgKyBjIC0gYikgKiAoYiArIGMgLSBhKSkgLyBjO1xufVxuXG5mdW5jdGlvbiBpbml0TmVlZFNlcmllcyhzZXJpZXMsIGNvbmZpZywgdHlwZSkge1xuICBzZXJpZXMgPSBzZXJpZXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmNCkge1xuICAgIHZhciBzdCA9IF9yZWY0LnR5cGU7XG4gICAgcmV0dXJuIHN0ID09PSB0eXBlO1xuICB9KTtcbiAgc2VyaWVzID0gc2VyaWVzLm1hcChmdW5jdGlvbiAoaXRlbSkge1xuICAgIHJldHVybiBkZWVwTWVyZ2UoKDAsIF91dGlsLmRlZXBDbG9uZSkoY29uZmlnLCB0cnVlKSwgaXRlbSk7XG4gIH0pO1xuICByZXR1cm4gc2VyaWVzLmZpbHRlcihmdW5jdGlvbiAoX3JlZjUpIHtcbiAgICB2YXIgc2hvdyA9IF9yZWY1LnNob3c7XG4gICAgcmV0dXJuIHNob3c7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByYWRpYW5Ub0FuZ2xlKHJhZGlhbikge1xuICByZXR1cm4gcmFkaWFuIC8gTWF0aC5QSSAqIDE4MDtcbn0iLCJmdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGFycikpIHJldHVybiBhcnI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX2FycmF5V2l0aEhvbGVzOyIsImZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBhcnIyID0gbmV3IEFycmF5KGFyci5sZW5ndGgpOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhcnIyW2ldID0gYXJyW2ldO1xuICAgIH1cblxuICAgIHJldHVybiBhcnIyO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX2FycmF5V2l0aG91dEhvbGVzOyIsImZ1bmN0aW9uIGFzeW5jR2VuZXJhdG9yU3RlcChnZW4sIHJlc29sdmUsIHJlamVjdCwgX25leHQsIF90aHJvdywga2V5LCBhcmcpIHtcbiAgdHJ5IHtcbiAgICB2YXIgaW5mbyA9IGdlbltrZXldKGFyZyk7XG4gICAgdmFyIHZhbHVlID0gaW5mby52YWx1ZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZWplY3QoZXJyb3IpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChpbmZvLmRvbmUpIHtcbiAgICByZXNvbHZlKHZhbHVlKTtcbiAgfSBlbHNlIHtcbiAgICBQcm9taXNlLnJlc29sdmUodmFsdWUpLnRoZW4oX25leHQsIF90aHJvdyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX2FzeW5jVG9HZW5lcmF0b3IoZm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXMsXG4gICAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIHZhciBnZW4gPSBmbi5hcHBseShzZWxmLCBhcmdzKTtcblxuICAgICAgZnVuY3Rpb24gX25leHQodmFsdWUpIHtcbiAgICAgICAgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcIm5leHRcIiwgdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBfdGhyb3coZXJyKSB7XG4gICAgICAgIGFzeW5jR2VuZXJhdG9yU3RlcChnZW4sIHJlc29sdmUsIHJlamVjdCwgX25leHQsIF90aHJvdywgXCJ0aHJvd1wiLCBlcnIpO1xuICAgICAgfVxuXG4gICAgICBfbmV4dCh1bmRlZmluZWQpO1xuICAgIH0pO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IF9hc3luY1RvR2VuZXJhdG9yOyIsImZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX2NsYXNzQ2FsbENoZWNrOyIsImZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBvYmopIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHtcbiAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB3cml0YWJsZTogdHJ1ZVxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIG9ialtrZXldID0gdmFsdWU7XG4gIH1cblxuICByZXR1cm4gb2JqO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZWZpbmVQcm9wZXJ0eTsiLCJmdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikge1xuICByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDoge1xuICAgIFwiZGVmYXVsdFwiOiBvYmpcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0OyIsImZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICBpZiAoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChpdGVyKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlcikgPT09IFwiW29iamVjdCBBcmd1bWVudHNdXCIpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IF9pdGVyYWJsZVRvQXJyYXk7IiwiZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkge1xuICB2YXIgX2FyciA9IFtdO1xuICB2YXIgX24gPSB0cnVlO1xuICB2YXIgX2QgPSBmYWxzZTtcbiAgdmFyIF9lID0gdW5kZWZpbmVkO1xuXG4gIHRyeSB7XG4gICAgZm9yICh2YXIgX2kgPSBhcnJbU3ltYm9sLml0ZXJhdG9yXSgpLCBfczsgIShfbiA9IChfcyA9IF9pLm5leHQoKSkuZG9uZSk7IF9uID0gdHJ1ZSkge1xuICAgICAgX2Fyci5wdXNoKF9zLnZhbHVlKTtcblxuICAgICAgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgX2QgPSB0cnVlO1xuICAgIF9lID0gZXJyO1xuICB9IGZpbmFsbHkge1xuICAgIHRyeSB7XG4gICAgICBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdICE9IG51bGwpIF9pW1wicmV0dXJuXCJdKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChfZCkgdGhyb3cgX2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9hcnI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX2l0ZXJhYmxlVG9BcnJheUxpbWl0OyIsImZ1bmN0aW9uIF9ub25JdGVyYWJsZVJlc3QoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IF9ub25JdGVyYWJsZVJlc3Q7IiwiZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkge1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIHNwcmVhZCBub24taXRlcmFibGUgaW5zdGFuY2VcIik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX25vbkl0ZXJhYmxlU3ByZWFkOyIsInZhciBhcnJheVdpdGhIb2xlcyA9IHJlcXVpcmUoXCIuL2FycmF5V2l0aEhvbGVzXCIpO1xuXG52YXIgaXRlcmFibGVUb0FycmF5TGltaXQgPSByZXF1aXJlKFwiLi9pdGVyYWJsZVRvQXJyYXlMaW1pdFwiKTtcblxudmFyIG5vbkl0ZXJhYmxlUmVzdCA9IHJlcXVpcmUoXCIuL25vbkl0ZXJhYmxlUmVzdFwiKTtcblxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7XG4gIHJldHVybiBhcnJheVdpdGhIb2xlcyhhcnIpIHx8IGl0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgfHwgbm9uSXRlcmFibGVSZXN0KCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX3NsaWNlZFRvQXJyYXk7IiwidmFyIGFycmF5V2l0aG91dEhvbGVzID0gcmVxdWlyZShcIi4vYXJyYXlXaXRob3V0SG9sZXNcIik7XG5cbnZhciBpdGVyYWJsZVRvQXJyYXkgPSByZXF1aXJlKFwiLi9pdGVyYWJsZVRvQXJyYXlcIik7XG5cbnZhciBub25JdGVyYWJsZVNwcmVhZCA9IHJlcXVpcmUoXCIuL25vbkl0ZXJhYmxlU3ByZWFkXCIpO1xuXG5mdW5jdGlvbiBfdG9Db25zdW1hYmxlQXJyYXkoYXJyKSB7XG4gIHJldHVybiBhcnJheVdpdGhvdXRIb2xlcyhhcnIpIHx8IGl0ZXJhYmxlVG9BcnJheShhcnIpIHx8IG5vbkl0ZXJhYmxlU3ByZWFkKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gX3RvQ29uc3VtYWJsZUFycmF5OyIsImZ1bmN0aW9uIF90eXBlb2YyKG9iaikgeyBpZiAodHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIpIHsgX3R5cGVvZjIgPSBmdW5jdGlvbiBfdHlwZW9mMihvYmopIHsgcmV0dXJuIHR5cGVvZiBvYmo7IH07IH0gZWxzZSB7IF90eXBlb2YyID0gZnVuY3Rpb24gX3R5cGVvZjIob2JqKSB7IHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqOyB9OyB9IHJldHVybiBfdHlwZW9mMihvYmopOyB9XG5cbmZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgX3R5cGVvZjIoU3ltYm9sLml0ZXJhdG9yKSA9PT0gXCJzeW1ib2xcIikge1xuICAgIG1vZHVsZS5leHBvcnRzID0gX3R5cGVvZiA9IGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICByZXR1cm4gX3R5cGVvZjIob2JqKTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIG1vZHVsZS5leHBvcnRzID0gX3R5cGVvZiA9IGZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogX3R5cGVvZjIob2JqKTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBfdHlwZW9mOyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlZ2VuZXJhdG9yLXJ1bnRpbWVcIik7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmJlemllckN1cnZlVG9Qb2x5bGluZSA9IGJlemllckN1cnZlVG9Qb2x5bGluZTtcbmV4cG9ydHMuZ2V0QmV6aWVyQ3VydmVMZW5ndGggPSBnZXRCZXppZXJDdXJ2ZUxlbmd0aDtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX3NsaWNlZFRvQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9zbGljZWRUb0FycmF5XCIpKTtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIHNxcnQgPSBNYXRoLnNxcnQsXG4gICAgcG93ID0gTWF0aC5wb3csXG4gICAgY2VpbCA9IE1hdGguY2VpbCxcbiAgICBhYnMgPSBNYXRoLmFiczsgLy8gSW5pdGlhbGl6ZSB0aGUgbnVtYmVyIG9mIHBvaW50cyBwZXIgY3VydmVcblxudmFyIGRlZmF1bHRTZWdtZW50UG9pbnRzTnVtID0gNTA7XG4vKipcclxuICogQGV4YW1wbGUgZGF0YSBzdHJ1Y3R1cmUgb2YgYmV6aWVyQ3VydmVcclxuICogYmV6aWVyQ3VydmUgPSBbXHJcbiAqICAvLyBTdGFydGluZyBwb2ludCBvZiB0aGUgY3VydmVcclxuICogIFsxMCwgMTBdLFxyXG4gKiAgLy8gQmV6aWVyQ3VydmUgc2VnbWVudCBkYXRhIChjb250cm9sUG9pbnQxLCBjb250cm9sUG9pbnQyLCBlbmRQb2ludClcclxuICogIFtcclxuICogICAgWzIwLCAyMF0sIFs0MCwgMjBdLCBbNTAsIDEwXVxyXG4gKiAgXSxcclxuICogIC4uLlxyXG4gKiBdXHJcbiAqL1xuXG4vKipcclxuICogQGRlc2NyaXB0aW9uICAgICAgICAgICAgICAgQWJzdHJhY3QgdGhlIGN1cnZlIGFzIGEgcG9seWxpbmUgY29uc2lzdGluZyBvZiBOIHBvaW50c1xyXG4gKiBAcGFyYW0ge0FycmF5fSBiZXppZXJDdXJ2ZSBiZXppZXJDdXJ2ZSBkYXRhXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBwcmVjaXNpb24gIGNhbGN1bGF0aW9uIGFjY3VyYWN5LiBSZWNvbW1lbmRlZCBmb3IgMS0yMC4gRGVmYXVsdCA9IDVcclxuICogQHJldHVybiB7T2JqZWN0fSAgICAgICAgICAgQ2FsY3VsYXRpb24gcmVzdWx0cyBhbmQgcmVsYXRlZCBkYXRhXHJcbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICAgICAgIE9wdGlvbi5zZWdtZW50UG9pbnRzIFBvaW50IGRhdGEgdGhhdCBjb25zdGl0dXRlcyBhIHBvbHlsaW5lIGFmdGVyIGNhbGN1bGF0aW9uXHJcbiAqIEByZXR1cm4ge051bWJlcn0gICAgICAgICAgIE9wdGlvbi5jeWNsZXMgTnVtYmVyIG9mIGl0ZXJhdGlvbnNcclxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgICAgT3B0aW9uLnJvdW5kcyBUaGUgbnVtYmVyIG9mIHJlY3Vyc2lvbnMgZm9yIHRoZSBsYXN0IGl0ZXJhdGlvblxyXG4gKi9cblxuZnVuY3Rpb24gYWJzdHJhY3RCZXppZXJDdXJ2ZVRvUG9seWxpbmUoYmV6aWVyQ3VydmUpIHtcbiAgdmFyIHByZWNpc2lvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogNTtcbiAgdmFyIHNlZ21lbnRzTnVtID0gYmV6aWVyQ3VydmUubGVuZ3RoIC0gMTtcbiAgdmFyIHN0YXJ0UG9pbnQgPSBiZXppZXJDdXJ2ZVswXTtcbiAgdmFyIGVuZFBvaW50ID0gYmV6aWVyQ3VydmVbc2VnbWVudHNOdW1dWzJdO1xuICB2YXIgc2VnbWVudHMgPSBiZXppZXJDdXJ2ZS5zbGljZSgxKTtcbiAgdmFyIGdldFNlZ21lbnRUUG9pbnRGdW5zID0gc2VnbWVudHMubWFwKGZ1bmN0aW9uIChzZWcsIGkpIHtcbiAgICB2YXIgYmVnaW5Qb2ludCA9IGkgPT09IDAgPyBzdGFydFBvaW50IDogc2VnbWVudHNbaSAtIDFdWzJdO1xuICAgIHJldHVybiBjcmVhdGVHZXRCZXppZXJDdXJ2ZVRQb2ludEZ1bi5hcHBseSh2b2lkIDAsIFtiZWdpblBvaW50XS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShzZWcpKSk7XG4gIH0pOyAvLyBJbml0aWFsaXplIHRoZSBjdXJ2ZSB0byBhIHBvbHlsaW5lXG5cbiAgdmFyIHNlZ21lbnRQb2ludHNOdW0gPSBuZXcgQXJyYXkoc2VnbWVudHNOdW0pLmZpbGwoZGVmYXVsdFNlZ21lbnRQb2ludHNOdW0pO1xuICB2YXIgc2VnbWVudFBvaW50cyA9IGdldFNlZ21lbnRQb2ludHNCeU51bShnZXRTZWdtZW50VFBvaW50RnVucywgc2VnbWVudFBvaW50c051bSk7IC8vIENhbGN1bGF0ZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQgcG9pbnRzIGJ5IGl0ZXJhdGl2ZWx5XG5cbiAgdmFyIHJlc3VsdCA9IGNhbGNVbmlmb3JtUG9pbnRzQnlJdGVyYXRpb24oc2VnbWVudFBvaW50cywgZ2V0U2VnbWVudFRQb2ludEZ1bnMsIHNlZ21lbnRzLCBwcmVjaXNpb24pO1xuICByZXN1bHQuc2VnbWVudFBvaW50cy5wdXNoKGVuZFBvaW50KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gIEdlbmVyYXRlIGEgbWV0aG9kIGZvciBvYnRhaW5pbmcgY29ycmVzcG9uZGluZyBwb2ludCBieSB0IGFjY29yZGluZyB0byBjdXJ2ZSBkYXRhXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGJlZ2luUG9pbnQgICAgQmV6aWVyQ3VydmUgYmVnaW4gcG9pbnQuIFt4LCB5XVxyXG4gKiBAcGFyYW0ge0FycmF5fSBjb250cm9sUG9pbnQxIEJlemllckN1cnZlIGNvbnRyb2xQb2ludDEuIFt4LCB5XVxyXG4gKiBAcGFyYW0ge0FycmF5fSBjb250cm9sUG9pbnQyIEJlemllckN1cnZlIGNvbnRyb2xQb2ludDIuIFt4LCB5XVxyXG4gKiBAcGFyYW0ge0FycmF5fSBlbmRQb2ludCAgICAgIEJlemllckN1cnZlIGVuZCBwb2ludC4gW3gsIHldXHJcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBFeHBlY3RlZCBmdW5jdGlvblxyXG4gKi9cblxuXG5mdW5jdGlvbiBjcmVhdGVHZXRCZXppZXJDdXJ2ZVRQb2ludEZ1bihiZWdpblBvaW50LCBjb250cm9sUG9pbnQxLCBjb250cm9sUG9pbnQyLCBlbmRQb2ludCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHQpIHtcbiAgICB2YXIgdFN1YmVkMSA9IDEgLSB0O1xuICAgIHZhciB0U3ViZWQxUG93MyA9IHBvdyh0U3ViZWQxLCAzKTtcbiAgICB2YXIgdFN1YmVkMVBvdzIgPSBwb3codFN1YmVkMSwgMik7XG4gICAgdmFyIHRQb3czID0gcG93KHQsIDMpO1xuICAgIHZhciB0UG93MiA9IHBvdyh0LCAyKTtcbiAgICByZXR1cm4gW2JlZ2luUG9pbnRbMF0gKiB0U3ViZWQxUG93MyArIDMgKiBjb250cm9sUG9pbnQxWzBdICogdCAqIHRTdWJlZDFQb3cyICsgMyAqIGNvbnRyb2xQb2ludDJbMF0gKiB0UG93MiAqIHRTdWJlZDEgKyBlbmRQb2ludFswXSAqIHRQb3czLCBiZWdpblBvaW50WzFdICogdFN1YmVkMVBvdzMgKyAzICogY29udHJvbFBvaW50MVsxXSAqIHQgKiB0U3ViZWQxUG93MiArIDMgKiBjb250cm9sUG9pbnQyWzFdICogdFBvdzIgKiB0U3ViZWQxICsgZW5kUG9pbnRbMV0gKiB0UG93M107XG4gIH07XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gcG9pbnRzXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvaW50MSBCZXppZXJDdXJ2ZSBiZWdpbiBwb2ludC4gW3gsIHldXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvaW50MiBCZXppZXJDdXJ2ZSBjb250cm9sUG9pbnQxLiBbeCwgeV1cclxuICogQHJldHVybiB7TnVtYmVyfSBFeHBlY3RlZCBkaXN0YW5jZVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRUd29Qb2ludERpc3RhbmNlKF9yZWYsIF9yZWYyKSB7XG4gIHZhciBfcmVmMyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmLCAyKSxcbiAgICAgIGF4ID0gX3JlZjNbMF0sXG4gICAgICBheSA9IF9yZWYzWzFdO1xuXG4gIHZhciBfcmVmNCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMiwgMiksXG4gICAgICBieCA9IF9yZWY0WzBdLFxuICAgICAgYnkgPSBfcmVmNFsxXTtcblxuICByZXR1cm4gc3FydChwb3coYXggLSBieCwgMikgKyBwb3coYXkgLSBieSwgMikpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHN1bSBvZiB0aGUgYXJyYXkgb2YgbnVtYmVyc1xyXG4gKiBAcGFyYW0ge0FycmF5fSBudW1zIEFuIGFycmF5IG9mIG51bWJlcnNcclxuICogQHJldHVybiB7TnVtYmVyfSBFeHBlY3RlZCBzdW1cclxuICovXG5cblxuZnVuY3Rpb24gZ2V0TnVtc1N1bShudW1zKSB7XG4gIHJldHVybiBudW1zLnJlZHVjZShmdW5jdGlvbiAoc3VtLCBudW0pIHtcbiAgICByZXR1cm4gc3VtICsgbnVtO1xuICB9LCAwKTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBkaXN0YW5jZSBvZiBtdWx0aXBsZSBzZXRzIG9mIHBvaW50c1xyXG4gKiBAcGFyYW0ge0FycmF5fSBzZWdtZW50UG9pbnRzIE11bHRpcGxlIHNldHMgb2YgcG9pbnQgZGF0YVxyXG4gKiBAcmV0dXJuIHtBcnJheX0gRGlzdGFuY2Ugb2YgbXVsdGlwbGUgc2V0cyBvZiBwb2ludCBkYXRhXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldFNlZ21lbnRQb2ludHNEaXN0YW5jZShzZWdtZW50UG9pbnRzKSB7XG4gIHJldHVybiBzZWdtZW50UG9pbnRzLm1hcChmdW5jdGlvbiAocG9pbnRzLCBpKSB7XG4gICAgcmV0dXJuIG5ldyBBcnJheShwb2ludHMubGVuZ3RoIC0gMSkuZmlsbCgwKS5tYXAoZnVuY3Rpb24gKHRlbXAsIGopIHtcbiAgICAgIHJldHVybiBnZXRUd29Qb2ludERpc3RhbmNlKHBvaW50c1tqXSwgcG9pbnRzW2ogKyAxXSk7XG4gICAgfSk7XG4gIH0pO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGRpc3RhbmNlIG9mIG11bHRpcGxlIHNldHMgb2YgcG9pbnRzXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHNlZ21lbnRQb2ludHMgTXVsdGlwbGUgc2V0cyBvZiBwb2ludCBkYXRhXHJcbiAqIEByZXR1cm4ge0FycmF5fSBEaXN0YW5jZSBvZiBtdWx0aXBsZSBzZXRzIG9mIHBvaW50IGRhdGFcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0U2VnbWVudFBvaW50c0J5TnVtKGdldFNlZ21lbnRUUG9pbnRGdW5zLCBzZWdtZW50UG9pbnRzTnVtKSB7XG4gIHJldHVybiBnZXRTZWdtZW50VFBvaW50RnVucy5tYXAoZnVuY3Rpb24gKGdldFNlZ21lbnRUUG9pbnRGdW4sIGkpIHtcbiAgICB2YXIgdEdhcCA9IDEgLyBzZWdtZW50UG9pbnRzTnVtW2ldO1xuICAgIHJldHVybiBuZXcgQXJyYXkoc2VnbWVudFBvaW50c051bVtpXSkuZmlsbCgnJykubWFwKGZ1bmN0aW9uIChmb28sIGopIHtcbiAgICAgIHJldHVybiBnZXRTZWdtZW50VFBvaW50RnVuKGogKiB0R2FwKTtcbiAgICB9KTtcbiAgfSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgc3VtIG9mIGRldmlhdGlvbnMgYmV0d2VlbiBsaW5lIHNlZ21lbnQgYW5kIHRoZSBhdmVyYWdlIGxlbmd0aFxyXG4gKiBAcGFyYW0ge0FycmF5fSBzZWdtZW50UG9pbnRzRGlzdGFuY2UgU2VnbWVudCBsZW5ndGggb2YgcG9seWxpbmVcclxuICogQHBhcmFtIHtOdW1iZXJ9IGF2Z0xlbmd0aCAgICAgICAgICAgIEF2ZXJhZ2UgbGVuZ3RoIG9mIHRoZSBsaW5lIHNlZ21lbnRcclxuICogQHJldHVybiB7TnVtYmVyfSBEZXZpYXRpb25zXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldEFsbERldmlhdGlvbnMoc2VnbWVudFBvaW50c0Rpc3RhbmNlLCBhdmdMZW5ndGgpIHtcbiAgcmV0dXJuIHNlZ21lbnRQb2ludHNEaXN0YW5jZS5tYXAoZnVuY3Rpb24gKHNlZykge1xuICAgIHJldHVybiBzZWcubWFwKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gYWJzKHMgLSBhdmdMZW5ndGgpO1xuICAgIH0pO1xuICB9KS5tYXAoZnVuY3Rpb24gKHNlZykge1xuICAgIHJldHVybiBnZXROdW1zU3VtKHNlZyk7XG4gIH0pLnJlZHVjZShmdW5jdGlvbiAodG90YWwsIHYpIHtcbiAgICByZXR1cm4gdG90YWwgKyB2O1xuICB9LCAwKTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ2FsY3VsYXRlIHVuaWZvcm1seSBkaXN0cmlidXRlZCBwb2ludHMgYnkgaXRlcmF0aXZlbHlcclxuICogQHBhcmFtIHtBcnJheX0gc2VnbWVudFBvaW50cyAgICAgICAgTXVsdGlwbGUgc2V0ZCBvZiBwb2ludHMgdGhhdCBtYWtlIHVwIGEgcG9seWxpbmVcclxuICogQHBhcmFtIHtBcnJheX0gZ2V0U2VnbWVudFRQb2ludEZ1bnMgRnVuY3Rpb25zIG9mIGdldCBhIHBvaW50IG9uIHRoZSBjdXJ2ZSB3aXRoIHRcclxuICogQHBhcmFtIHtBcnJheX0gc2VnbWVudHMgICAgICAgICAgICAgQmV6aWVyQ3VydmUgZGF0YVxyXG4gKiBAcGFyYW0ge051bWJlcn0gcHJlY2lzaW9uICAgICAgICAgICBDYWxjdWxhdGlvbiBhY2N1cmFjeVxyXG4gKiBAcmV0dXJuIHtPYmplY3R9IENhbGN1bGF0aW9uIHJlc3VsdHMgYW5kIHJlbGF0ZWQgZGF0YVxyXG4gKiBAcmV0dXJuIHtBcnJheX0gIE9wdGlvbi5zZWdtZW50UG9pbnRzIFBvaW50IGRhdGEgdGhhdCBjb25zdGl0dXRlcyBhIHBvbHlsaW5lIGFmdGVyIGNhbGN1bGF0aW9uXHJcbiAqIEByZXR1cm4ge051bWJlcn0gT3B0aW9uLmN5Y2xlcyBOdW1iZXIgb2YgaXRlcmF0aW9uc1xyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IE9wdGlvbi5yb3VuZHMgVGhlIG51bWJlciBvZiByZWN1cnNpb25zIGZvciB0aGUgbGFzdCBpdGVyYXRpb25cclxuICovXG5cblxuZnVuY3Rpb24gY2FsY1VuaWZvcm1Qb2ludHNCeUl0ZXJhdGlvbihzZWdtZW50UG9pbnRzLCBnZXRTZWdtZW50VFBvaW50RnVucywgc2VnbWVudHMsIHByZWNpc2lvbikge1xuICAvLyBUaGUgbnVtYmVyIG9mIGxvb3BzIGZvciB0aGUgY3VycmVudCBpdGVyYXRpb25cbiAgdmFyIHJvdW5kcyA9IDQ7IC8vIE51bWJlciBvZiBpdGVyYXRpb25zXG5cbiAgdmFyIGN5Y2xlcyA9IDE7XG5cbiAgdmFyIF9sb29wID0gZnVuY3Rpb24gX2xvb3AoKSB7XG4gICAgLy8gUmVjYWxjdWxhdGUgdGhlIG51bWJlciBvZiBwb2ludHMgcGVyIGN1cnZlIGJhc2VkIG9uIHRoZSBsYXN0IGl0ZXJhdGlvbiBkYXRhXG4gICAgdmFyIHRvdGFsUG9pbnRzTnVtID0gc2VnbWVudFBvaW50cy5yZWR1Y2UoZnVuY3Rpb24gKHRvdGFsLCBzZWcpIHtcbiAgICAgIHJldHVybiB0b3RhbCArIHNlZy5sZW5ndGg7XG4gICAgfSwgMCk7IC8vIEFkZCBsYXN0IHBvaW50cyBvZiBzZWdtZW50IHRvIGNhbGMgZXhhY3Qgc2VnbWVudCBsZW5ndGhcblxuICAgIHNlZ21lbnRQb2ludHMuZm9yRWFjaChmdW5jdGlvbiAoc2VnLCBpKSB7XG4gICAgICByZXR1cm4gc2VnLnB1c2goc2VnbWVudHNbaV1bMl0pO1xuICAgIH0pO1xuICAgIHZhciBzZWdtZW50UG9pbnRzRGlzdGFuY2UgPSBnZXRTZWdtZW50UG9pbnRzRGlzdGFuY2Uoc2VnbWVudFBvaW50cyk7XG4gICAgdmFyIGxpbmVTZWdtZW50TnVtID0gc2VnbWVudFBvaW50c0Rpc3RhbmNlLnJlZHVjZShmdW5jdGlvbiAodG90YWwsIHNlZykge1xuICAgICAgcmV0dXJuIHRvdGFsICsgc2VnLmxlbmd0aDtcbiAgICB9LCAwKTtcbiAgICB2YXIgc2VnbWVudGxlbmd0aCA9IHNlZ21lbnRQb2ludHNEaXN0YW5jZS5tYXAoZnVuY3Rpb24gKHNlZykge1xuICAgICAgcmV0dXJuIGdldE51bXNTdW0oc2VnKTtcbiAgICB9KTtcbiAgICB2YXIgdG90YWxMZW5ndGggPSBnZXROdW1zU3VtKHNlZ21lbnRsZW5ndGgpO1xuICAgIHZhciBhdmdMZW5ndGggPSB0b3RhbExlbmd0aCAvIGxpbmVTZWdtZW50TnVtOyAvLyBDaGVjayBpZiBwcmVjaXNpb24gaXMgcmVhY2hlZFxuXG4gICAgdmFyIGFsbERldmlhdGlvbnMgPSBnZXRBbGxEZXZpYXRpb25zKHNlZ21lbnRQb2ludHNEaXN0YW5jZSwgYXZnTGVuZ3RoKTtcbiAgICBpZiAoYWxsRGV2aWF0aW9ucyA8PSBwcmVjaXNpb24pIHJldHVybiBcImJyZWFrXCI7XG4gICAgdG90YWxQb2ludHNOdW0gPSBjZWlsKGF2Z0xlbmd0aCAvIHByZWNpc2lvbiAqIHRvdGFsUG9pbnRzTnVtICogMS4xKTtcbiAgICB2YXIgc2VnbWVudFBvaW50c051bSA9IHNlZ21lbnRsZW5ndGgubWFwKGZ1bmN0aW9uIChsZW5ndGgpIHtcbiAgICAgIHJldHVybiBjZWlsKGxlbmd0aCAvIHRvdGFsTGVuZ3RoICogdG90YWxQb2ludHNOdW0pO1xuICAgIH0pOyAvLyBDYWxjdWxhdGUgdGhlIHBvaW50cyBhZnRlciByZWRpc3RyaWJ1dGlvblxuXG4gICAgc2VnbWVudFBvaW50cyA9IGdldFNlZ21lbnRQb2ludHNCeU51bShnZXRTZWdtZW50VFBvaW50RnVucywgc2VnbWVudFBvaW50c051bSk7XG4gICAgdG90YWxQb2ludHNOdW0gPSBzZWdtZW50UG9pbnRzLnJlZHVjZShmdW5jdGlvbiAodG90YWwsIHNlZykge1xuICAgICAgcmV0dXJuIHRvdGFsICsgc2VnLmxlbmd0aDtcbiAgICB9LCAwKTtcbiAgICB2YXIgc2VnbWVudFBvaW50c0Zvckxlbmd0aCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoc2VnbWVudFBvaW50cykpO1xuICAgIHNlZ21lbnRQb2ludHNGb3JMZW5ndGguZm9yRWFjaChmdW5jdGlvbiAoc2VnLCBpKSB7XG4gICAgICByZXR1cm4gc2VnLnB1c2goc2VnbWVudHNbaV1bMl0pO1xuICAgIH0pO1xuICAgIHNlZ21lbnRQb2ludHNEaXN0YW5jZSA9IGdldFNlZ21lbnRQb2ludHNEaXN0YW5jZShzZWdtZW50UG9pbnRzRm9yTGVuZ3RoKTtcbiAgICBsaW5lU2VnbWVudE51bSA9IHNlZ21lbnRQb2ludHNEaXN0YW5jZS5yZWR1Y2UoZnVuY3Rpb24gKHRvdGFsLCBzZWcpIHtcbiAgICAgIHJldHVybiB0b3RhbCArIHNlZy5sZW5ndGg7XG4gICAgfSwgMCk7XG4gICAgc2VnbWVudGxlbmd0aCA9IHNlZ21lbnRQb2ludHNEaXN0YW5jZS5tYXAoZnVuY3Rpb24gKHNlZykge1xuICAgICAgcmV0dXJuIGdldE51bXNTdW0oc2VnKTtcbiAgICB9KTtcbiAgICB0b3RhbExlbmd0aCA9IGdldE51bXNTdW0oc2VnbWVudGxlbmd0aCk7XG4gICAgYXZnTGVuZ3RoID0gdG90YWxMZW5ndGggLyBsaW5lU2VnbWVudE51bTtcbiAgICB2YXIgc3RlcFNpemUgPSAxIC8gdG90YWxQb2ludHNOdW0gLyAxMDsgLy8gUmVjdXJzaXZlbHkgZm9yIGVhY2ggc2VnbWVudCBvZiB0aGUgcG9seWxpbmVcblxuICAgIGdldFNlZ21lbnRUUG9pbnRGdW5zLmZvckVhY2goZnVuY3Rpb24gKGdldFNlZ21lbnRUUG9pbnRGdW4sIGkpIHtcbiAgICAgIHZhciBjdXJyZW50U2VnbWVudFBvaW50c051bSA9IHNlZ21lbnRQb2ludHNOdW1baV07XG4gICAgICB2YXIgdCA9IG5ldyBBcnJheShjdXJyZW50U2VnbWVudFBvaW50c051bSkuZmlsbCgnJykubWFwKGZ1bmN0aW9uIChmb28sIGopIHtcbiAgICAgICAgcmV0dXJuIGogLyBzZWdtZW50UG9pbnRzTnVtW2ldO1xuICAgICAgfSk7IC8vIFJlcGVhdGVkIHJlY3Vyc2l2ZSBvZmZzZXRcblxuICAgICAgZm9yICh2YXIgciA9IDA7IHIgPCByb3VuZHM7IHIrKykge1xuICAgICAgICB2YXIgZGlzdGFuY2UgPSBnZXRTZWdtZW50UG9pbnRzRGlzdGFuY2UoW3NlZ21lbnRQb2ludHNbaV1dKVswXTtcbiAgICAgICAgdmFyIGRldmlhdGlvbnMgPSBkaXN0YW5jZS5tYXAoZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgICByZXR1cm4gZCAtIGF2Z0xlbmd0aDtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBvZmZzZXQgPSAwO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgY3VycmVudFNlZ21lbnRQb2ludHNOdW07IGorKykge1xuICAgICAgICAgIGlmIChqID09PSAwKSByZXR1cm47XG4gICAgICAgICAgb2Zmc2V0ICs9IGRldmlhdGlvbnNbaiAtIDFdO1xuICAgICAgICAgIHRbal0gLT0gc3RlcFNpemUgKiBvZmZzZXQ7XG4gICAgICAgICAgaWYgKHRbal0gPiAxKSB0W2pdID0gMTtcbiAgICAgICAgICBpZiAodFtqXSA8IDApIHRbal0gPSAwO1xuICAgICAgICAgIHNlZ21lbnRQb2ludHNbaV1bal0gPSBnZXRTZWdtZW50VFBvaW50RnVuKHRbal0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcm91bmRzICo9IDQ7XG4gICAgY3ljbGVzKys7XG4gIH07XG5cbiAgZG8ge1xuICAgIHZhciBfcmV0ID0gX2xvb3AoKTtcblxuICAgIGlmIChfcmV0ID09PSBcImJyZWFrXCIpIGJyZWFrO1xuICB9IHdoaWxlIChyb3VuZHMgPD0gMTAyNSk7XG5cbiAgc2VnbWVudFBvaW50cyA9IHNlZ21lbnRQb2ludHMucmVkdWNlKGZ1bmN0aW9uIChhbGwsIHNlZykge1xuICAgIHJldHVybiBhbGwuY29uY2F0KHNlZyk7XG4gIH0sIFtdKTtcbiAgcmV0dXJuIHtcbiAgICBzZWdtZW50UG9pbnRzOiBzZWdtZW50UG9pbnRzLFxuICAgIGN5Y2xlczogY3ljbGVzLFxuICAgIHJvdW5kczogcm91bmRzXG4gIH07XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgcG9seWxpbmUgY29ycmVzcG9uZGluZyB0byB0aGUgQmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGJlemllckN1cnZlIEJlemllckN1cnZlIGRhdGFcclxuICogQHBhcmFtIHtOdW1iZXJ9IHByZWNpc2lvbiAgQ2FsY3VsYXRpb24gYWNjdXJhY3kuIFJlY29tbWVuZGVkIGZvciAxLTIwLiBEZWZhdWx0ID0gNVxyXG4gKiBAcmV0dXJuIHtBcnJheXxCb29sZWFufSBQb2ludCBkYXRhIHRoYXQgY29uc3RpdHV0ZXMgYSBwb2x5bGluZSBhZnRlciBjYWxjdWxhdGlvbiAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gYmV6aWVyQ3VydmVUb1BvbHlsaW5lKGJlemllckN1cnZlKSB7XG4gIHZhciBwcmVjaXNpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDU7XG5cbiAgaWYgKCFiZXppZXJDdXJ2ZSkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2JlemllckN1cnZlVG9Qb2x5bGluZTogTWlzc2luZyBwYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICghKGJlemllckN1cnZlIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgY29uc29sZS5lcnJvcignYmV6aWVyQ3VydmVUb1BvbHlsaW5lOiBQYXJhbWV0ZXIgYmV6aWVyQ3VydmUgbXVzdCBiZSBhbiBhcnJheSEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIHByZWNpc2lvbiAhPT0gJ251bWJlcicpIHtcbiAgICBjb25zb2xlLmVycm9yKCdiZXppZXJDdXJ2ZVRvUG9seWxpbmU6IFBhcmFtZXRlciBwcmVjaXNpb24gbXVzdCBiZSBhIG51bWJlciEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgX2Fic3RyYWN0QmV6aWVyQ3VydmVUID0gYWJzdHJhY3RCZXppZXJDdXJ2ZVRvUG9seWxpbmUoYmV6aWVyQ3VydmUsIHByZWNpc2lvbiksXG4gICAgICBzZWdtZW50UG9pbnRzID0gX2Fic3RyYWN0QmV6aWVyQ3VydmVULnNlZ21lbnRQb2ludHM7XG5cbiAgcmV0dXJuIHNlZ21lbnRQb2ludHM7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgYmV6aWVyIGN1cnZlIGxlbmd0aFxyXG4gKiBAcGFyYW0ge0FycmF5fSBiZXppZXJDdXJ2ZSBiZXppZXJDdXJ2ZSBkYXRhXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBwcmVjaXNpb24gIGNhbGN1bGF0aW9uIGFjY3VyYWN5LiBSZWNvbW1lbmRlZCBmb3IgNS0xMC4gRGVmYXVsdCA9IDVcclxuICogQHJldHVybiB7TnVtYmVyfEJvb2xlYW59IEJlemllckN1cnZlIGxlbmd0aCAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0QmV6aWVyQ3VydmVMZW5ndGgoYmV6aWVyQ3VydmUpIHtcbiAgdmFyIHByZWNpc2lvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogNTtcblxuICBpZiAoIWJlemllckN1cnZlKSB7XG4gICAgY29uc29sZS5lcnJvcignZ2V0QmV6aWVyQ3VydmVMZW5ndGg6IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoIShiZXppZXJDdXJ2ZSBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2dldEJlemllckN1cnZlTGVuZ3RoOiBQYXJhbWV0ZXIgYmV6aWVyQ3VydmUgbXVzdCBiZSBhbiBhcnJheSEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIHByZWNpc2lvbiAhPT0gJ251bWJlcicpIHtcbiAgICBjb25zb2xlLmVycm9yKCdnZXRCZXppZXJDdXJ2ZUxlbmd0aDogUGFyYW1ldGVyIHByZWNpc2lvbiBtdXN0IGJlIGEgbnVtYmVyIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBfYWJzdHJhY3RCZXppZXJDdXJ2ZVQyID0gYWJzdHJhY3RCZXppZXJDdXJ2ZVRvUG9seWxpbmUoYmV6aWVyQ3VydmUsIHByZWNpc2lvbiksXG4gICAgICBzZWdtZW50UG9pbnRzID0gX2Fic3RyYWN0QmV6aWVyQ3VydmVUMi5zZWdtZW50UG9pbnRzOyAvLyBDYWxjdWxhdGUgdGhlIHRvdGFsIGxlbmd0aCBvZiB0aGUgcG9pbnRzIHRoYXQgbWFrZSB1cCB0aGUgcG9seWxpbmVcblxuXG4gIHZhciBwb2ludHNEaXN0YW5jZSA9IGdldFNlZ21lbnRQb2ludHNEaXN0YW5jZShbc2VnbWVudFBvaW50c10pWzBdO1xuICB2YXIgbGVuZ3RoID0gZ2V0TnVtc1N1bShwb2ludHNEaXN0YW5jZSk7XG4gIHJldHVybiBsZW5ndGg7XG59XG5cbnZhciBfZGVmYXVsdCA9IGJlemllckN1cnZlVG9Qb2x5bGluZTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSB2b2lkIDA7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX3RvQ29uc3VtYWJsZUFycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdG9Db25zdW1hYmxlQXJyYXlcIikpO1xuXG4vKipcclxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IHRoZSBwb2x5bGluZSBmb3JtZWQgYnkgTiBwb2ludHMgaW50byBhIHNldCBvZiBiZXppZXIgY3VydmVcclxuICogQHBhcmFtIHtBcnJheX0gcG9seWxpbmUgQSBzZXQgb2YgcG9pbnRzIHRoYXQgbWFrZSB1cCBhIHBvbHlsaW5lXHJcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gY2xvc2UgIENsb3NlZCBjdXJ2ZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0QSBTbW9vdGhuZXNzXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBvZmZzZXRCIFNtb290aG5lc3NcclxuICogQHJldHVybiB7QXJyYXl8Qm9vbGVhbn0gQSBzZXQgb2YgYmV6aWVyIGN1cnZlIChJbnZhbGlkIGlucHV0IHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cbmZ1bmN0aW9uIHBvbHlsaW5lVG9CZXppZXJDdXJ2ZShwb2x5bGluZSkge1xuICB2YXIgY2xvc2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuICB2YXIgb2Zmc2V0QSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogMC4yNTtcbiAgdmFyIG9mZnNldEIgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IDAuMjU7XG5cbiAgaWYgKCEocG9seWxpbmUgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICBjb25zb2xlLmVycm9yKCdwb2x5bGluZVRvQmV6aWVyQ3VydmU6IFBhcmFtZXRlciBwb2x5bGluZSBtdXN0IGJlIGFuIGFycmF5IScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChwb2x5bGluZS5sZW5ndGggPD0gMikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ3BvbHlsaW5lVG9CZXppZXJDdXJ2ZTogQ29udmVydGluZyB0byBhIGN1cnZlIHJlcXVpcmVzIGF0IGxlYXN0IDMgcG9pbnRzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciBzdGFydFBvaW50ID0gcG9seWxpbmVbMF07XG4gIHZhciBiZXppZXJDdXJ2ZUxpbmVOdW0gPSBwb2x5bGluZS5sZW5ndGggLSAxO1xuICB2YXIgYmV6aWVyQ3VydmVQb2ludHMgPSBuZXcgQXJyYXkoYmV6aWVyQ3VydmVMaW5lTnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIFtdLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGdldEJlemllckN1cnZlTGluZUNvbnRyb2xQb2ludHMocG9seWxpbmUsIGksIGNsb3NlLCBvZmZzZXRBLCBvZmZzZXRCKSksIFtwb2x5bGluZVtpICsgMV1dKTtcbiAgfSk7XG4gIGlmIChjbG9zZSkgY2xvc2VCZXppZXJDdXJ2ZShiZXppZXJDdXJ2ZVBvaW50cywgc3RhcnRQb2ludCk7XG4gIGJlemllckN1cnZlUG9pbnRzLnVuc2hpZnQocG9seWxpbmVbMF0pO1xuICByZXR1cm4gYmV6aWVyQ3VydmVQb2ludHM7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgY29udHJvbCBwb2ludHMgb2YgdGhlIEJlemllciBjdXJ2ZVxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2x5bGluZSBBIHNldCBvZiBwb2ludHMgdGhhdCBtYWtlIHVwIGEgcG9seWxpbmVcclxuICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4ICAgVGhlIGluZGV4IG9mIHdoaWNoIGdldCBjb250cm9scyBwb2ludHMncyBwb2ludCBpbiBwb2x5bGluZVxyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGNsb3NlICBDbG9zZWQgY3VydmVcclxuICogQHBhcmFtIHtOdW1iZXJ9IG9mZnNldEEgU21vb3RobmVzc1xyXG4gKiBAcGFyYW0ge051bWJlcn0gb2Zmc2V0QiBTbW9vdGhuZXNzXHJcbiAqIEByZXR1cm4ge0FycmF5fSBDb250cm9sIHBvaW50c1xyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRCZXppZXJDdXJ2ZUxpbmVDb250cm9sUG9pbnRzKHBvbHlsaW5lLCBpbmRleCkge1xuICB2YXIgY2xvc2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlO1xuICB2YXIgb2Zmc2V0QSA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogMC4yNTtcbiAgdmFyIG9mZnNldEIgPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IDAuMjU7XG4gIHZhciBwb2ludE51bSA9IHBvbHlsaW5lLmxlbmd0aDtcbiAgaWYgKHBvaW50TnVtIDwgMyB8fCBpbmRleCA+PSBwb2ludE51bSkgcmV0dXJuO1xuICB2YXIgYmVmb3JlUG9pbnRJbmRleCA9IGluZGV4IC0gMTtcbiAgaWYgKGJlZm9yZVBvaW50SW5kZXggPCAwKSBiZWZvcmVQb2ludEluZGV4ID0gY2xvc2UgPyBwb2ludE51bSArIGJlZm9yZVBvaW50SW5kZXggOiAwO1xuICB2YXIgYWZ0ZXJQb2ludEluZGV4ID0gaW5kZXggKyAxO1xuICBpZiAoYWZ0ZXJQb2ludEluZGV4ID49IHBvaW50TnVtKSBhZnRlclBvaW50SW5kZXggPSBjbG9zZSA/IGFmdGVyUG9pbnRJbmRleCAtIHBvaW50TnVtIDogcG9pbnROdW0gLSAxO1xuICB2YXIgYWZ0ZXJOZXh0UG9pbnRJbmRleCA9IGluZGV4ICsgMjtcbiAgaWYgKGFmdGVyTmV4dFBvaW50SW5kZXggPj0gcG9pbnROdW0pIGFmdGVyTmV4dFBvaW50SW5kZXggPSBjbG9zZSA/IGFmdGVyTmV4dFBvaW50SW5kZXggLSBwb2ludE51bSA6IHBvaW50TnVtIC0gMTtcbiAgdmFyIHBvaW50QmVmb3JlID0gcG9seWxpbmVbYmVmb3JlUG9pbnRJbmRleF07XG4gIHZhciBwb2ludE1pZGRsZSA9IHBvbHlsaW5lW2luZGV4XTtcbiAgdmFyIHBvaW50QWZ0ZXIgPSBwb2x5bGluZVthZnRlclBvaW50SW5kZXhdO1xuICB2YXIgcG9pbnRBZnRlck5leHQgPSBwb2x5bGluZVthZnRlck5leHRQb2ludEluZGV4XTtcbiAgcmV0dXJuIFtbcG9pbnRNaWRkbGVbMF0gKyBvZmZzZXRBICogKHBvaW50QWZ0ZXJbMF0gLSBwb2ludEJlZm9yZVswXSksIHBvaW50TWlkZGxlWzFdICsgb2Zmc2V0QSAqIChwb2ludEFmdGVyWzFdIC0gcG9pbnRCZWZvcmVbMV0pXSwgW3BvaW50QWZ0ZXJbMF0gLSBvZmZzZXRCICogKHBvaW50QWZ0ZXJOZXh0WzBdIC0gcG9pbnRNaWRkbGVbMF0pLCBwb2ludEFmdGVyWzFdIC0gb2Zmc2V0QiAqIChwb2ludEFmdGVyTmV4dFsxXSAtIHBvaW50TWlkZGxlWzFdKV1dO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGxhc3QgY3VydmUgb2YgdGhlIGNsb3N1cmVcclxuICogQHBhcmFtIHtBcnJheX0gYmV6aWVyQ3VydmUgQSBzZXQgb2Ygc3ViLWN1cnZlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHN0YXJ0UG9pbnQgIFN0YXJ0IHBvaW50XHJcbiAqIEByZXR1cm4ge0FycmF5fSBUaGUgbGFzdCBjdXJ2ZSBmb3IgY2xvc3VyZVxyXG4gKi9cblxuXG5mdW5jdGlvbiBjbG9zZUJlemllckN1cnZlKGJlemllckN1cnZlLCBzdGFydFBvaW50KSB7XG4gIHZhciBmaXJzdFN1YkN1cnZlID0gYmV6aWVyQ3VydmVbMF07XG4gIHZhciBsYXN0U3ViQ3VydmUgPSBiZXppZXJDdXJ2ZS5zbGljZSgtMSlbMF07XG4gIGJlemllckN1cnZlLnB1c2goW2dldFN5bW1ldHJ5UG9pbnQobGFzdFN1YkN1cnZlWzFdLCBsYXN0U3ViQ3VydmVbMl0pLCBnZXRTeW1tZXRyeVBvaW50KGZpcnN0U3ViQ3VydmVbMF0sIHN0YXJ0UG9pbnQpLCBzdGFydFBvaW50XSk7XG4gIHJldHVybiBiZXppZXJDdXJ2ZTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBzeW1tZXRyeSBwb2ludFxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2ludCAgICAgICBTeW1tZXRyaWMgcG9pbnRcclxuICogQHBhcmFtIHtBcnJheX0gY2VudGVyUG9pbnQgU3ltbWV0cmljIGNlbnRlclxyXG4gKiBAcmV0dXJuIHtBcnJheX0gU3ltbWV0cmljIHBvaW50XHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldFN5bW1ldHJ5UG9pbnQocG9pbnQsIGNlbnRlclBvaW50KSB7XG4gIHZhciBfcG9pbnQgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQsIDIpLFxuICAgICAgcHggPSBfcG9pbnRbMF0sXG4gICAgICBweSA9IF9wb2ludFsxXTtcblxuICB2YXIgX2NlbnRlclBvaW50ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGNlbnRlclBvaW50LCAyKSxcbiAgICAgIGN4ID0gX2NlbnRlclBvaW50WzBdLFxuICAgICAgY3kgPSBfY2VudGVyUG9pbnRbMV07XG5cbiAgdmFyIG1pbnVzWCA9IGN4IC0gcHg7XG4gIHZhciBtaW51c1kgPSBjeSAtIHB5O1xuICByZXR1cm4gW2N4ICsgbWludXNYLCBjeSArIG1pbnVzWV07XG59XG5cbnZhciBfZGVmYXVsdCA9IHBvbHlsaW5lVG9CZXppZXJDdXJ2ZTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiYmV6aWVyQ3VydmVUb1BvbHlsaW5lXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9iZXppZXJDdXJ2ZVRvUG9seWxpbmUuYmV6aWVyQ3VydmVUb1BvbHlsaW5lO1xuICB9XG59KTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcImdldEJlemllckN1cnZlTGVuZ3RoXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9iZXppZXJDdXJ2ZVRvUG9seWxpbmUuZ2V0QmV6aWVyQ3VydmVMZW5ndGg7XG4gIH1cbn0pO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwicG9seWxpbmVUb0JlemllckN1cnZlXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9wb2x5bGluZVRvQmV6aWVyQ3VydmVbXCJkZWZhdWx0XCJdO1xuICB9XG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX2JlemllckN1cnZlVG9Qb2x5bGluZSA9IHJlcXVpcmUoXCIuL2NvcmUvYmV6aWVyQ3VydmVUb1BvbHlsaW5lXCIpO1xuXG52YXIgX3BvbHlsaW5lVG9CZXppZXJDdXJ2ZSA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vY29yZS9wb2x5bGluZVRvQmV6aWVyQ3VydmVcIikpO1xuXG52YXIgX2RlZmF1bHQgPSB7XG4gIGJlemllckN1cnZlVG9Qb2x5bGluZTogX2JlemllckN1cnZlVG9Qb2x5bGluZS5iZXppZXJDdXJ2ZVRvUG9seWxpbmUsXG4gIGdldEJlemllckN1cnZlTGVuZ3RoOiBfYmV6aWVyQ3VydmVUb1BvbHlsaW5lLmdldEJlemllckN1cnZlTGVuZ3RoLFxuICBwb2x5bGluZVRvQmV6aWVyQ3VydmU6IF9wb2x5bGluZVRvQmV6aWVyQ3VydmVbXCJkZWZhdWx0XCJdXG59O1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IHZvaWQgMDtcblxudmFyIF9kZWZpbmVQcm9wZXJ0eTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2RlZmluZVByb3BlcnR5XCIpKTtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIF9jbGFzc0NhbGxDaGVjazIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2NsYXNzQ2FsbENoZWNrXCIpKTtcblxudmFyIF9jb2xvciA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBqaWFtaW5naGkvY29sb3JcIikpO1xuXG52YXIgX2JlemllckN1cnZlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGppYW1pbmdoaS9iZXppZXItY3VydmVcIikpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiLi4vcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfZ3JhcGhzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi4vY29uZmlnL2dyYXBoc1wiKSk7XG5cbnZhciBfZ3JhcGggPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL2dyYXBoLmNsYXNzXCIpKTtcblxuZnVuY3Rpb24gb3duS2V5cyhvYmplY3QsIGVudW1lcmFibGVPbmx5KSB7IHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqZWN0KTsgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHsgdmFyIHN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iamVjdCk7IGlmIChlbnVtZXJhYmxlT25seSkgc3ltYm9scyA9IHN5bWJvbHMuZmlsdGVyKGZ1bmN0aW9uIChzeW0pIHsgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBzeW0pLmVudW1lcmFibGU7IH0pOyBrZXlzLnB1c2guYXBwbHkoa2V5cywgc3ltYm9scyk7IH0gcmV0dXJuIGtleXM7IH1cblxuZnVuY3Rpb24gX29iamVjdFNwcmVhZCh0YXJnZXQpIHsgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHsgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307IGlmIChpICUgMikgeyBvd25LZXlzKHNvdXJjZSwgdHJ1ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7ICgwLCBfZGVmaW5lUHJvcGVydHkyW1wiZGVmYXVsdFwiXSkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTsgfSk7IH0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMpIHsgT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhzb3VyY2UpKTsgfSBlbHNlIHsgb3duS2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsgfSk7IH0gfSByZXR1cm4gdGFyZ2V0OyB9XG5cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gICAgICAgICAgIENsYXNzIG9mIENSZW5kZXJcclxuICogQHBhcmFtIHtPYmplY3R9IGNhbnZhcyBDYW52YXMgRE9NXHJcbiAqIEByZXR1cm4ge0NSZW5kZXJ9ICAgICAgSW5zdGFuY2Ugb2YgQ1JlbmRlclxyXG4gKi9cbnZhciBDUmVuZGVyID0gZnVuY3Rpb24gQ1JlbmRlcihjYW52YXMpIHtcbiAgKDAsIF9jbGFzc0NhbGxDaGVjazJbXCJkZWZhdWx0XCJdKSh0aGlzLCBDUmVuZGVyKTtcblxuICBpZiAoIWNhbnZhcykge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0NSZW5kZXIgTWlzc2luZyBwYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgdmFyIGNsaWVudFdpZHRoID0gY2FudmFzLmNsaWVudFdpZHRoLFxuICAgICAgY2xpZW50SGVpZ2h0ID0gY2FudmFzLmNsaWVudEhlaWdodDtcbiAgdmFyIGFyZWEgPSBbY2xpZW50V2lkdGgsIGNsaWVudEhlaWdodF07XG4gIGNhbnZhcy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgY2xpZW50V2lkdGgpO1xuICBjYW52YXMuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBjbGllbnRIZWlnaHQpO1xuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQ29udGV4dCBvZiB0aGUgY2FudmFzXHJcbiAgICogQHR5cGUge09iamVjdH1cclxuICAgKiBAZXhhbXBsZSBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG4gICAqL1xuXG4gIHRoaXMuY3R4ID0gY3R4O1xuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gV2lkdGggYW5kIGhlaWdodCBvZiB0aGUgY2FudmFzXHJcbiAgICogQHR5cGUge0FycmF5fVxyXG4gICAqIEBleGFtcGxlIGFyZWEgPSBbMzAw77yMMTAwXVxyXG4gICAqL1xuXG4gIHRoaXMuYXJlYSA9IGFyZWE7XG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHJlbmRlciBpcyBpbiBhbmltYXRpb24gcmVuZGVyaW5nXHJcbiAgICogQHR5cGUge0Jvb2xlYW59XHJcbiAgICogQGV4YW1wbGUgYW5pbWF0aW9uU3RhdHVzID0gdHJ1ZXxmYWxzZVxyXG4gICAqL1xuXG4gIHRoaXMuYW5pbWF0aW9uU3RhdHVzID0gZmFsc2U7XG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBBZGRlZCBncmFwaFxyXG4gICAqIEB0eXBlIHtbR3JhcGhdfVxyXG4gICAqIEBleGFtcGxlIGdyYXBocyA9IFtHcmFwaCwgR3JhcGgsIC4uLl1cclxuICAgKi9cblxuICB0aGlzLmdyYXBocyA9IFtdO1xuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQ29sb3IgcGx1Z2luXHJcbiAgICogQHR5cGUge09iamVjdH1cclxuICAgKiBAbGluayBodHRwczovL2dpdGh1Yi5jb20vamlhbWluZzc0My9jb2xvclxyXG4gICAqL1xuXG4gIHRoaXMuY29sb3IgPSBfY29sb3JbXCJkZWZhdWx0XCJdO1xuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gQmV6aWVyIEN1cnZlIHBsdWdpblxyXG4gICAqIEB0eXBlIHtPYmplY3R9XHJcbiAgICogQGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2ppYW1pbmc3NDMvQmV6aWVyQ3VydmVcclxuICAgKi9cblxuICB0aGlzLmJlemllckN1cnZlID0gX2JlemllckN1cnZlW1wiZGVmYXVsdFwiXTsgLy8gYmluZCBldmVudCBoYW5kbGVyXG5cbiAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG1vdXNlRG93bi5iaW5kKHRoaXMpKTtcbiAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdXNlTW92ZS5iaW5kKHRoaXMpKTtcbiAgY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBtb3VzZVVwLmJpbmQodGhpcykpO1xufTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gICAgICAgIENsZWFyIGNhbnZhcyBkcmF3aW5nIGFyZWFcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5cbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gQ1JlbmRlcjtcblxuQ1JlbmRlci5wcm90b3R5cGUuY2xlYXJBcmVhID0gZnVuY3Rpb24gKCkge1xuICB2YXIgX3RoaXMkY3R4O1xuXG4gIHZhciBhcmVhID0gdGhpcy5hcmVhO1xuXG4gIChfdGhpcyRjdHggPSB0aGlzLmN0eCkuY2xlYXJSZWN0LmFwcGx5KF90aGlzJGN0eCwgWzAsIDBdLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGFyZWEpKSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiAgICAgICAgICAgQWRkIGdyYXBoIHRvIHJlbmRlclxyXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIEdyYXBoIGNvbmZpZ3VyYXRpb25cclxuICogQHJldHVybiB7R3JhcGh9ICAgICAgICBHcmFwaCBpbnN0YW5jZVxyXG4gKi9cblxuXG5DUmVuZGVyLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBjb25maWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9O1xuICB2YXIgbmFtZSA9IGNvbmZpZy5uYW1lO1xuXG4gIGlmICghbmFtZSkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2FkZCBNaXNzaW5nIHBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGdyYXBoQ29uZmlnID0gX2dyYXBoc1tcImRlZmF1bHRcIl0uZ2V0KG5hbWUpO1xuXG4gIGlmICghZ3JhcGhDb25maWcpIHtcbiAgICBjb25zb2xlLndhcm4oJ05vIGNvcnJlc3BvbmRpbmcgZ3JhcGggY29uZmlndXJhdGlvbiBmb3VuZCEnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgZ3JhcGggPSBuZXcgX2dyYXBoW1wiZGVmYXVsdFwiXShncmFwaENvbmZpZywgY29uZmlnKTtcbiAgaWYgKCFncmFwaC52YWxpZGF0b3IoZ3JhcGgpKSByZXR1cm47XG4gIGdyYXBoLnJlbmRlciA9IHRoaXM7XG4gIHRoaXMuZ3JhcGhzLnB1c2goZ3JhcGgpO1xuICB0aGlzLnNvcnRHcmFwaHNCeUluZGV4KCk7XG4gIHRoaXMuZHJhd0FsbEdyYXBoKCk7XG4gIHJldHVybiBncmFwaDtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFNvcnQgdGhlIGdyYXBoIGJ5IGluZGV4XHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5DUmVuZGVyLnByb3RvdHlwZS5zb3J0R3JhcGhzQnlJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGdyYXBocyA9IHRoaXMuZ3JhcGhzO1xuICBncmFwaHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChhLmluZGV4ID4gYi5pbmRleCkgcmV0dXJuIDE7XG4gICAgaWYgKGEuaW5kZXggPT09IGIuaW5kZXgpIHJldHVybiAwO1xuICAgIGlmIChhLmluZGV4IDwgYi5pbmRleCkgcmV0dXJuIC0xO1xuICB9KTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uICAgICAgICAgRGVsZXRlIGdyYXBoIGluIHJlbmRlclxyXG4gKiBAcGFyYW0ge0dyYXBofSBncmFwaCBUaGUgZ3JhcGggdG8gYmUgZGVsZXRlZFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9ICBWb2lkXHJcbiAqL1xuXG5cbkNSZW5kZXIucHJvdG90eXBlLmRlbEdyYXBoID0gZnVuY3Rpb24gKGdyYXBoKSB7XG4gIGlmICh0eXBlb2YgZ3JhcGguZGVsUHJvY2Vzc29yICE9PSAnZnVuY3Rpb24nKSByZXR1cm47XG4gIGdyYXBoLmRlbFByb2Nlc3Nvcih0aGlzKTtcbiAgdGhpcy5ncmFwaHMgPSB0aGlzLmdyYXBocy5maWx0ZXIoZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoO1xuICB9KTtcbiAgdGhpcy5kcmF3QWxsR3JhcGgoKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uICAgICAgICBEZWxldGUgYWxsIGdyYXBoIGluIHJlbmRlclxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuQ1JlbmRlci5wcm90b3R5cGUuZGVsQWxsR3JhcGggPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgdGhpcy5ncmFwaHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gZ3JhcGguZGVsUHJvY2Vzc29yKF90aGlzKTtcbiAgfSk7XG4gIHRoaXMuZ3JhcGhzID0gdGhpcy5ncmFwaHMuZmlsdGVyKGZ1bmN0aW9uIChncmFwaCkge1xuICAgIHJldHVybiBncmFwaDtcbiAgfSk7XG4gIHRoaXMuZHJhd0FsbEdyYXBoKCk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiAgICAgICAgRHJhdyBhbGwgdGhlIGdyYXBocyBpbiB0aGUgcmVuZGVyXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5DUmVuZGVyLnByb3RvdHlwZS5kcmF3QWxsR3JhcGggPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gIHRoaXMuY2xlYXJBcmVhKCk7XG4gIHRoaXMuZ3JhcGhzLmZpbHRlcihmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gZ3JhcGggJiYgZ3JhcGgudmlzaWJsZTtcbiAgfSkuZm9yRWFjaChmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gZ3JhcGguZHJhd1Byb2Nlc3NvcihfdGhpczIsIGdyYXBoKTtcbiAgfSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiAgICAgIEFuaW1hdGUgdGhlIGdyYXBoIHdob3NlIGFuaW1hdGlvbiBxdWV1ZSBpcyBub3QgZW1wdHlcclxuICogICAgICAgICAgICAgICAgICAgYW5kIHRoZSBhbmltYXRpb25QYXVzZSBpcyBlcXVhbCB0byBmYWxzZVxyXG4gKiBAcmV0dXJuIHtQcm9taXNlfSBBbmltYXRpb24gUHJvbWlzZVxyXG4gKi9cblxuXG5DUmVuZGVyLnByb3RvdHlwZS5sYXVuY2hBbmltYXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gIHZhciBhbmltYXRpb25TdGF0dXMgPSB0aGlzLmFuaW1hdGlvblN0YXR1cztcbiAgaWYgKGFuaW1hdGlvblN0YXR1cykgcmV0dXJuO1xuICB0aGlzLmFuaW1hdGlvblN0YXR1cyA9IHRydWU7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgIGFuaW1hdGlvbi5jYWxsKF90aGlzMywgZnVuY3Rpb24gKCkge1xuICAgICAgX3RoaXMzLmFuaW1hdGlvblN0YXR1cyA9IGZhbHNlO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0sIERhdGUubm93KCkpO1xuICB9KTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFRyeSB0byBhbmltYXRlIGV2ZXJ5IGdyYXBoXHJcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIENhbGxiYWNrIGluIGFuaW1hdGlvbiBlbmRcclxuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWVTdGFtcCAgVGltZSBzdGFtcCBvZiBhbmltYXRpb24gc3RhcnRcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGFuaW1hdGlvbihjYWxsYmFjaywgdGltZVN0YW1wKSB7XG4gIHZhciBncmFwaHMgPSB0aGlzLmdyYXBocztcblxuICBpZiAoIWFuaW1hdGlvbkFibGUoZ3JhcGhzKSkge1xuICAgIGNhbGxiYWNrKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgZ3JhcGhzLmZvckVhY2goZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLnR1cm5OZXh0QW5pbWF0aW9uRnJhbWUodGltZVN0YW1wKTtcbiAgfSk7XG4gIHRoaXMuZHJhd0FsbEdyYXBoKCk7XG4gIHJlcXVlc3RBbmltYXRpb25GcmFtZShhbmltYXRpb24uYmluZCh0aGlzLCBjYWxsYmFjaywgdGltZVN0YW1wKSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEZpbmQgaWYgdGhlcmUgYXJlIGdyYXBoIHRoYXQgY2FuIGJlIGFuaW1hdGVkXHJcbiAqIEBwYXJhbSB7W0dyYXBoXX0gZ3JhcGhzXHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59XHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGFuaW1hdGlvbkFibGUoZ3JhcGhzKSB7XG4gIHJldHVybiBncmFwaHMuZmluZChmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gIWdyYXBoLmFuaW1hdGlvblBhdXNlICYmIGdyYXBoLmFuaW1hdGlvbkZyYW1lU3RhdGUubGVuZ3RoO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciBvZiBDUmVuZGVyIG1vdXNlZG93biBldmVudFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuZnVuY3Rpb24gbW91c2VEb3duKGUpIHtcbiAgdmFyIGdyYXBocyA9IHRoaXMuZ3JhcGhzO1xuICB2YXIgaG92ZXJHcmFwaCA9IGdyYXBocy5maW5kKGZ1bmN0aW9uIChncmFwaCkge1xuICAgIHJldHVybiBncmFwaC5zdGF0dXMgPT09ICdob3Zlcic7XG4gIH0pO1xuICBpZiAoIWhvdmVyR3JhcGgpIHJldHVybjtcbiAgaG92ZXJHcmFwaC5zdGF0dXMgPSAnYWN0aXZlJztcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciBvZiBDUmVuZGVyIG1vdXNlbW92ZSBldmVudFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuZnVuY3Rpb24gbW91c2VNb3ZlKGUpIHtcbiAgdmFyIG9mZnNldFggPSBlLm9mZnNldFgsXG4gICAgICBvZmZzZXRZID0gZS5vZmZzZXRZO1xuICB2YXIgcG9zaXRpb24gPSBbb2Zmc2V0WCwgb2Zmc2V0WV07XG4gIHZhciBncmFwaHMgPSB0aGlzLmdyYXBocztcbiAgdmFyIGFjdGl2ZUdyYXBoID0gZ3JhcGhzLmZpbmQoZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLnN0YXR1cyA9PT0gJ2FjdGl2ZScgfHwgZ3JhcGguc3RhdHVzID09PSAnZHJhZyc7XG4gIH0pO1xuXG4gIGlmIChhY3RpdmVHcmFwaCkge1xuICAgIGlmICghYWN0aXZlR3JhcGguZHJhZykgcmV0dXJuO1xuXG4gICAgaWYgKHR5cGVvZiBhY3RpdmVHcmFwaC5tb3ZlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdObyBtb3ZlIG1ldGhvZCBpcyBwcm92aWRlZCwgY2Fubm90IGJlIGRyYWdnZWQhJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgYWN0aXZlR3JhcGgubW92ZVByb2Nlc3NvcihlKTtcbiAgICBhY3RpdmVHcmFwaC5zdGF0dXMgPSAnZHJhZyc7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGhvdmVyR3JhcGggPSBncmFwaHMuZmluZChmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gZ3JhcGguc3RhdHVzID09PSAnaG92ZXInO1xuICB9KTtcbiAgdmFyIGhvdmVyQWJsZUdyYXBocyA9IGdyYXBocy5maWx0ZXIoZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLmhvdmVyICYmICh0eXBlb2YgZ3JhcGguaG92ZXJDaGVjayA9PT0gJ2Z1bmN0aW9uJyB8fCBncmFwaC5ob3ZlclJlY3QpO1xuICB9KTtcbiAgdmFyIGhvdmVyZWRHcmFwaCA9IGhvdmVyQWJsZUdyYXBocy5maW5kKGZ1bmN0aW9uIChncmFwaCkge1xuICAgIHJldHVybiBncmFwaC5ob3ZlckNoZWNrUHJvY2Vzc29yKHBvc2l0aW9uLCBncmFwaCk7XG4gIH0pO1xuXG4gIGlmIChob3ZlcmVkR3JhcGgpIHtcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9IGhvdmVyZWRHcmFwaC5zdHlsZS5ob3ZlckN1cnNvcjtcbiAgfSBlbHNlIHtcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9ICdkZWZhdWx0JztcbiAgfVxuXG4gIHZhciBob3ZlckdyYXBoTW91c2VPdXRlcklzRnVuID0gZmFsc2UsXG4gICAgICBob3ZlcmVkR3JhcGhNb3VzZUVudGVySXNGdW4gPSBmYWxzZTtcbiAgaWYgKGhvdmVyR3JhcGgpIGhvdmVyR3JhcGhNb3VzZU91dGVySXNGdW4gPSB0eXBlb2YgaG92ZXJHcmFwaC5tb3VzZU91dGVyID09PSAnZnVuY3Rpb24nO1xuICBpZiAoaG92ZXJlZEdyYXBoKSBob3ZlcmVkR3JhcGhNb3VzZUVudGVySXNGdW4gPSB0eXBlb2YgaG92ZXJlZEdyYXBoLm1vdXNlRW50ZXIgPT09ICdmdW5jdGlvbic7XG4gIGlmICghaG92ZXJlZEdyYXBoICYmICFob3ZlckdyYXBoKSByZXR1cm47XG5cbiAgaWYgKCFob3ZlcmVkR3JhcGggJiYgaG92ZXJHcmFwaCkge1xuICAgIGlmIChob3ZlckdyYXBoTW91c2VPdXRlcklzRnVuKSBob3ZlckdyYXBoLm1vdXNlT3V0ZXIoZSwgaG92ZXJHcmFwaCk7XG4gICAgaG92ZXJHcmFwaC5zdGF0dXMgPSAnc3RhdGljJztcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoaG92ZXJlZEdyYXBoICYmIGhvdmVyZWRHcmFwaCA9PT0gaG92ZXJHcmFwaCkgcmV0dXJuO1xuXG4gIGlmIChob3ZlcmVkR3JhcGggJiYgIWhvdmVyR3JhcGgpIHtcbiAgICBpZiAoaG92ZXJlZEdyYXBoTW91c2VFbnRlcklzRnVuKSBob3ZlcmVkR3JhcGgubW91c2VFbnRlcihlLCBob3ZlcmVkR3JhcGgpO1xuICAgIGhvdmVyZWRHcmFwaC5zdGF0dXMgPSAnaG92ZXInO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChob3ZlcmVkR3JhcGggJiYgaG92ZXJHcmFwaCAmJiBob3ZlcmVkR3JhcGggIT09IGhvdmVyR3JhcGgpIHtcbiAgICBpZiAoaG92ZXJHcmFwaE1vdXNlT3V0ZXJJc0Z1bikgaG92ZXJHcmFwaC5tb3VzZU91dGVyKGUsIGhvdmVyR3JhcGgpO1xuICAgIGhvdmVyR3JhcGguc3RhdHVzID0gJ3N0YXRpYyc7XG4gICAgaWYgKGhvdmVyZWRHcmFwaE1vdXNlRW50ZXJJc0Z1bikgaG92ZXJlZEdyYXBoLm1vdXNlRW50ZXIoZSwgaG92ZXJlZEdyYXBoKTtcbiAgICBob3ZlcmVkR3JhcGguc3RhdHVzID0gJ2hvdmVyJztcbiAgfVxufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBIYW5kbGVyIG9mIENSZW5kZXIgbW91c2V1cCBldmVudFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuZnVuY3Rpb24gbW91c2VVcChlKSB7XG4gIHZhciBncmFwaHMgPSB0aGlzLmdyYXBocztcbiAgdmFyIGFjdGl2ZUdyYXBoID0gZ3JhcGhzLmZpbmQoZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLnN0YXR1cyA9PT0gJ2FjdGl2ZSc7XG4gIH0pO1xuICB2YXIgZHJhZ0dyYXBoID0gZ3JhcGhzLmZpbmQoZnVuY3Rpb24gKGdyYXBoKSB7XG4gICAgcmV0dXJuIGdyYXBoLnN0YXR1cyA9PT0gJ2RyYWcnO1xuICB9KTtcbiAgaWYgKGFjdGl2ZUdyYXBoICYmIHR5cGVvZiBhY3RpdmVHcmFwaC5jbGljayA9PT0gJ2Z1bmN0aW9uJykgYWN0aXZlR3JhcGguY2xpY2soZSwgYWN0aXZlR3JhcGgpO1xuICBncmFwaHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JhcGgpIHtcbiAgICByZXR1cm4gZ3JhcGggJiYgKGdyYXBoLnN0YXR1cyA9ICdzdGF0aWMnKTtcbiAgfSk7XG4gIGlmIChhY3RpdmVHcmFwaCkgYWN0aXZlR3JhcGguc3RhdHVzID0gJ2hvdmVyJztcbiAgaWYgKGRyYWdHcmFwaCkgZHJhZ0dyYXBoLnN0YXR1cyA9ICdob3Zlcic7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uICAgICAgICAgQ2xvbmUgR3JhcGhcclxuICogQHBhcmFtIHtHcmFwaH0gZ3JhcGggVGhlIHRhcmdldCB0byBiZSBjbG9uZWRcclxuICogQHJldHVybiB7R3JhcGh9ICAgICAgQ2xvbmVkIGdyYXBoXHJcbiAqL1xuXG5cbkNSZW5kZXIucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKGdyYXBoKSB7XG4gIHZhciBzdHlsZSA9IGdyYXBoLnN0eWxlLmdldFN0eWxlKCk7XG5cbiAgdmFyIGNsb25lZEdyYXBoID0gX29iamVjdFNwcmVhZCh7fSwgZ3JhcGgsIHtcbiAgICBzdHlsZTogc3R5bGVcbiAgfSk7XG5cbiAgZGVsZXRlIGNsb25lZEdyYXBoLnJlbmRlcjtcbiAgY2xvbmVkR3JhcGggPSAoMCwgX3V0aWwuZGVlcENsb25lKShjbG9uZWRHcmFwaCwgdHJ1ZSk7XG4gIHJldHVybiB0aGlzLmFkZChjbG9uZWRHcmFwaCk7XG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX3JlZ2VuZXJhdG9yID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvcmVnZW5lcmF0b3JcIikpO1xuXG52YXIgX2FzeW5jVG9HZW5lcmF0b3IyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9hc3luY1RvR2VuZXJhdG9yXCIpKTtcblxudmFyIF90eXBlb2YyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90eXBlb2ZcIikpO1xuXG52YXIgX3RvQ29uc3VtYWJsZUFycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvdG9Db25zdW1hYmxlQXJyYXlcIikpO1xuXG52YXIgX2NsYXNzQ2FsbENoZWNrMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvY2xhc3NDYWxsQ2hlY2tcIikpO1xuXG52YXIgX3N0eWxlID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9zdHlsZS5jbGFzc1wiKSk7XG5cbnZhciBfdHJhbnNpdGlvbiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBqaWFtaW5naGkvdHJhbnNpdGlvblwiKSk7XG5cbnZhciBfdXRpbCA9IHJlcXVpcmUoXCIuLi9wbHVnaW4vdXRpbFwiKTtcblxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBDbGFzcyBHcmFwaFxyXG4gKiBAcGFyYW0ge09iamVjdH0gZ3JhcGggIEdyYXBoIGRlZmF1bHQgY29uZmlndXJhdGlvblxyXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIEdyYXBoIGNvbmZpZ1xyXG4gKiBAcmV0dXJuIHtHcmFwaH0gSW5zdGFuY2Ugb2YgR3JhcGhcclxuICovXG52YXIgR3JhcGggPSBmdW5jdGlvbiBHcmFwaChncmFwaCwgY29uZmlnKSB7XG4gICgwLCBfY2xhc3NDYWxsQ2hlY2syW1wiZGVmYXVsdFwiXSkodGhpcywgR3JhcGgpO1xuICBjb25maWcgPSAoMCwgX3V0aWwuZGVlcENsb25lKShjb25maWcsIHRydWUpO1xuICB2YXIgZGVmYXVsdENvbmZpZyA9IHtcbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBXZWF0aGVyIHRvIHJlbmRlciBncmFwaFxyXG4gICAgICogQHR5cGUge0Jvb2xlYW59XHJcbiAgICAgKiBAZGVmYXVsdCB2aXNpYmxlID0gdHJ1ZVxyXG4gICAgICovXG4gICAgdmlzaWJsZTogdHJ1ZSxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZW5hYmxlIGRyYWdcclxuICAgICAqIEB0eXBlIHtCb29sZWFufVxyXG4gICAgICogQGRlZmF1bHQgZHJhZyA9IGZhbHNlXHJcbiAgICAgKi9cbiAgICBkcmFnOiBmYWxzZSxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZXRoZXIgdG8gZW5hYmxlIGhvdmVyXHJcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cclxuICAgICAqIEBkZWZhdWx0IGhvdmVyID0gZmFsc2VcclxuICAgICAqL1xuICAgIGhvdmVyOiBmYWxzZSxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEdyYXBoIHJlbmRlcmluZyBpbmRleFxyXG4gICAgICogIEdpdmUgcHJpb3JpdHkgdG8gaW5kZXggaGlnaCBncmFwaCBpbiByZW5kZXJpbmdcclxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XHJcbiAgICAgKiBAZXhhbXBsZSBpbmRleCA9IDFcclxuICAgICAqL1xuICAgIGluZGV4OiAxLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gQW5pbWF0aW9uIGRlbGF5IHRpbWUobXMpXHJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxyXG4gICAgICogQGRlZmF1bHQgYW5pbWF0aW9uRGVsYXkgPSAwXHJcbiAgICAgKi9cbiAgICBhbmltYXRpb25EZWxheTogMCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIE51bWJlciBvZiBhbmltYXRpb24gZnJhbWVzXHJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxyXG4gICAgICogQGRlZmF1bHQgYW5pbWF0aW9uRnJhbWUgPSAzMFxyXG4gICAgICovXG4gICAgYW5pbWF0aW9uRnJhbWU6IDMwLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gQW5pbWF0aW9uIGR5bmFtaWMgY3VydmUgKFN1cHBvcnRlZCBieSB0cmFuc2l0aW9uKVxyXG4gICAgICogQHR5cGUge1N0cmluZ31cclxuICAgICAqIEBkZWZhdWx0IGFuaW1hdGlvbkN1cnZlID0gJ2xpbmVhcidcclxuICAgICAqIEBsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qaWFtaW5nNzQzL1RyYW5zaXRpb25cclxuICAgICAqL1xuICAgIGFuaW1hdGlvbkN1cnZlOiAnbGluZWFyJyxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFdlYXRoZXIgdG8gcGF1c2UgZ3JhcGggYW5pbWF0aW9uXHJcbiAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cclxuICAgICAqIEBkZWZhdWx0IGFuaW1hdGlvblBhdXNlID0gZmFsc2VcclxuICAgICAqL1xuICAgIGFuaW1hdGlvblBhdXNlOiBmYWxzZSxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFJlY3Rhbmd1bGFyIGhvdmVyIGRldGVjdGlvbiB6b25lXHJcbiAgICAgKiAgVXNlIHRoaXMgbWV0aG9kIGZvciBob3ZlciBkZXRlY3Rpb24gZmlyc3RcclxuICAgICAqIEB0eXBlIHtOdWxsfEFycmF5fVxyXG4gICAgICogQGRlZmF1bHQgaG92ZXJSZWN0ID0gbnVsbFxyXG4gICAgICogQGV4YW1wbGUgaG92ZXJSZWN0ID0gWzAsIDAsIDEwMCwgMTAwXSAvLyBbUmVjdCBzdGFydCB4LCB5LCBSZWN0IHdpZHRoLCBoZWlnaHRdXHJcbiAgICAgKi9cbiAgICBob3ZlclJlY3Q6IG51bGwsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBNb3VzZSBlbnRlciBldmVudCBoYW5kbGVyXHJcbiAgICAgKiBAdHlwZSB7RnVuY3Rpb258TnVsbH1cclxuICAgICAqIEBkZWZhdWx0IG1vdXNlRW50ZXIgPSBudWxsXHJcbiAgICAgKi9cbiAgICBtb3VzZUVudGVyOiBudWxsLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gTW91c2Ugb3V0ZXIgZXZlbnQgaGFuZGxlclxyXG4gICAgICogQHR5cGUge0Z1bmN0aW9ufE51bGx9XHJcbiAgICAgKiBAZGVmYXVsdCBtb3VzZU91dGVyID0gbnVsbFxyXG4gICAgICovXG4gICAgbW91c2VPdXRlcjogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIE1vdXNlIGNsaWNrIGV2ZW50IGhhbmRsZXJcclxuICAgICAqIEB0eXBlIHtGdW5jdGlvbnxOdWxsfVxyXG4gICAgICogQGRlZmF1bHQgY2xpY2sgPSBudWxsXHJcbiAgICAgKi9cbiAgICBjbGljazogbnVsbFxuICB9O1xuICB2YXIgY29uZmlnQWJsZU5vdCA9IHtcbiAgICBzdGF0dXM6ICdzdGF0aWMnLFxuICAgIGFuaW1hdGlvblJvb3Q6IFtdLFxuICAgIGFuaW1hdGlvbktleXM6IFtdLFxuICAgIGFuaW1hdGlvbkZyYW1lU3RhdGU6IFtdLFxuICAgIGNhY2hlOiB7fVxuICB9O1xuICBpZiAoIWNvbmZpZy5zaGFwZSkgY29uZmlnLnNoYXBlID0ge307XG4gIGlmICghY29uZmlnLnN0eWxlKSBjb25maWcuc3R5bGUgPSB7fTtcbiAgdmFyIHNoYXBlID0gT2JqZWN0LmFzc2lnbih7fSwgZ3JhcGguc2hhcGUsIGNvbmZpZy5zaGFwZSk7XG4gIE9iamVjdC5hc3NpZ24oZGVmYXVsdENvbmZpZywgY29uZmlnLCBjb25maWdBYmxlTm90KTtcbiAgT2JqZWN0LmFzc2lnbih0aGlzLCBncmFwaCwgZGVmYXVsdENvbmZpZyk7XG4gIHRoaXMuc2hhcGUgPSBzaGFwZTtcbiAgdGhpcy5zdHlsZSA9IG5ldyBfc3R5bGVbXCJkZWZhdWx0XCJdKGNvbmZpZy5zdHlsZSk7XG4gIHRoaXMuYWRkZWRQcm9jZXNzb3IoKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFByb2Nlc3NvciBvZiBhZGRlZFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBHcmFwaDtcblxuR3JhcGgucHJvdG90eXBlLmFkZGVkUHJvY2Vzc29yID0gZnVuY3Rpb24gKCkge1xuICBpZiAodHlwZW9mIHRoaXMuc2V0R3JhcGhDZW50ZXIgPT09ICdmdW5jdGlvbicpIHRoaXMuc2V0R3JhcGhDZW50ZXIobnVsbCwgdGhpcyk7IC8vIFRoZSBsaWZlIGN5Y2xlICdhZGRlZFwiXG5cbiAgaWYgKHR5cGVvZiB0aGlzLmFkZGVkID09PSAnZnVuY3Rpb24nKSB0aGlzLmFkZGVkKHRoaXMpO1xufTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUHJvY2Vzc29yIG9mIGRyYXdcclxuICogQHBhcmFtIHtDUmVuZGVyfSByZW5kZXIgSW5zdGFuY2Ugb2YgQ1JlbmRlclxyXG4gKiBAcGFyYW0ge0dyYXBofSBncmFwaCAgICBJbnN0YW5jZSBvZiBHcmFwaFxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuR3JhcGgucHJvdG90eXBlLmRyYXdQcm9jZXNzb3IgPSBmdW5jdGlvbiAocmVuZGVyLCBncmFwaCkge1xuICB2YXIgY3R4ID0gcmVuZGVyLmN0eDtcbiAgZ3JhcGguc3R5bGUuaW5pdFN0eWxlKGN0eCk7XG4gIGlmICh0eXBlb2YgdGhpcy5iZWZvcmVEcmF3ID09PSAnZnVuY3Rpb24nKSB0aGlzLmJlZm9yZURyYXcodGhpcywgcmVuZGVyKTtcbiAgZ3JhcGguZHJhdyhyZW5kZXIsIGdyYXBoKTtcbiAgaWYgKHR5cGVvZiB0aGlzLmRyYXdlZCA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5kcmF3ZWQodGhpcywgcmVuZGVyKTtcbiAgZ3JhcGguc3R5bGUucmVzdG9yZVRyYW5zZm9ybShjdHgpO1xufTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUHJvY2Vzc29yIG9mIGhvdmVyIGNoZWNrXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvc2l0aW9uIE1vdXNlIFBvc2l0aW9uXHJcbiAqIEBwYXJhbSB7R3JhcGh9IGdyYXBoICAgIEluc3RhbmNlIG9mIEdyYXBoXHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJlc3VsdCBvZiBob3ZlciBjaGVja1xyXG4gKi9cblxuXG5HcmFwaC5wcm90b3R5cGUuaG92ZXJDaGVja1Byb2Nlc3NvciA9IGZ1bmN0aW9uIChwb3NpdGlvbiwgX3JlZikge1xuICB2YXIgaG92ZXJSZWN0ID0gX3JlZi5ob3ZlclJlY3QsXG4gICAgICBzdHlsZSA9IF9yZWYuc3R5bGUsXG4gICAgICBob3ZlckNoZWNrID0gX3JlZi5ob3ZlckNoZWNrO1xuICB2YXIgZ3JhcGhDZW50ZXIgPSBzdHlsZS5ncmFwaENlbnRlcixcbiAgICAgIHJvdGF0ZSA9IHN0eWxlLnJvdGF0ZSxcbiAgICAgIHNjYWxlID0gc3R5bGUuc2NhbGUsXG4gICAgICB0cmFuc2xhdGUgPSBzdHlsZS50cmFuc2xhdGU7XG5cbiAgaWYgKGdyYXBoQ2VudGVyKSB7XG4gICAgaWYgKHJvdGF0ZSkgcG9zaXRpb24gPSAoMCwgX3V0aWwuZ2V0Um90YXRlUG9pbnRQb3MpKC1yb3RhdGUsIHBvc2l0aW9uLCBncmFwaENlbnRlcik7XG4gICAgaWYgKHNjYWxlKSBwb3NpdGlvbiA9ICgwLCBfdXRpbC5nZXRTY2FsZVBvaW50UG9zKShzY2FsZS5tYXAoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiAxIC8gcztcbiAgICB9KSwgcG9zaXRpb24sIGdyYXBoQ2VudGVyKTtcbiAgICBpZiAodHJhbnNsYXRlKSBwb3NpdGlvbiA9ICgwLCBfdXRpbC5nZXRUcmFuc2xhdGVQb2ludFBvcykodHJhbnNsYXRlLm1hcChmdW5jdGlvbiAodikge1xuICAgICAgcmV0dXJuIHYgKiAtMTtcbiAgICB9KSwgcG9zaXRpb24pO1xuICB9XG5cbiAgaWYgKGhvdmVyUmVjdCkgcmV0dXJuIF91dGlsLmNoZWNrUG9pbnRJc0luUmVjdC5hcHBseSh2b2lkIDAsIFtwb3NpdGlvbl0uY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoaG92ZXJSZWN0KSkpO1xuICByZXR1cm4gaG92ZXJDaGVjayhwb3NpdGlvbiwgdGhpcyk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzb3Igb2YgbW92ZVxyXG4gKiBAcGFyYW0ge0V2ZW50fSBlIE1vdXNlIG1vdmVtZW50IGV2ZW50XHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5HcmFwaC5wcm90b3R5cGUubW92ZVByb2Nlc3NvciA9IGZ1bmN0aW9uIChlKSB7XG4gIHRoaXMubW92ZShlLCB0aGlzKTtcbiAgaWYgKHR5cGVvZiB0aGlzLmJlZm9yZU1vdmUgPT09ICdmdW5jdGlvbicpIHRoaXMuYmVmb3JlTW92ZShlLCB0aGlzKTtcbiAgaWYgKHR5cGVvZiB0aGlzLnNldEdyYXBoQ2VudGVyID09PSAnZnVuY3Rpb24nKSB0aGlzLnNldEdyYXBoQ2VudGVyKGUsIHRoaXMpO1xuICBpZiAodHlwZW9mIHRoaXMubW92ZWQgPT09ICdmdW5jdGlvbicpIHRoaXMubW92ZWQoZSwgdGhpcyk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBVcGRhdGUgZ3JhcGggc3RhdGVcclxuICogQHBhcmFtIHtTdHJpbmd9IGF0dHJOYW1lIFVwZGF0ZWQgYXR0cmlidXRlIG5hbWVcclxuICogQHBhcmFtIHtBbnl9IGNoYW5nZSAgICAgIFVwZGF0ZWQgdmFsdWVcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5cbkdyYXBoLnByb3RvdHlwZS5hdHRyID0gZnVuY3Rpb24gKGF0dHJOYW1lKSB7XG4gIHZhciBjaGFuZ2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcbiAgaWYgKCFhdHRyTmFtZSB8fCBjaGFuZ2UgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZhbHNlO1xuICB2YXIgaXNPYmplY3QgPSAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKSh0aGlzW2F0dHJOYW1lXSkgPT09ICdvYmplY3QnO1xuICBpZiAoaXNPYmplY3QpIGNoYW5nZSA9ICgwLCBfdXRpbC5kZWVwQ2xvbmUpKGNoYW5nZSwgdHJ1ZSk7XG4gIHZhciByZW5kZXIgPSB0aGlzLnJlbmRlcjtcblxuICBpZiAoYXR0ck5hbWUgPT09ICdzdHlsZScpIHtcbiAgICB0aGlzLnN0eWxlLnVwZGF0ZShjaGFuZ2UpO1xuICB9IGVsc2UgaWYgKGlzT2JqZWN0KSB7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzW2F0dHJOYW1lXSwgY2hhbmdlKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzW2F0dHJOYW1lXSA9IGNoYW5nZTtcbiAgfVxuXG4gIGlmIChhdHRyTmFtZSA9PT0gJ2luZGV4JykgcmVuZGVyLnNvcnRHcmFwaHNCeUluZGV4KCk7XG4gIHJlbmRlci5kcmF3QWxsR3JhcGgoKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZSBncmFwaGljcyBzdGF0ZSAod2l0aCBhbmltYXRpb24pXHJcbiAqICBPbmx5IHNoYXBlIGFuZCBzdHlsZSBhdHRyaWJ1dGVzIGFyZSBzdXBwb3J0ZWRcclxuICogQHBhcmFtIHtTdHJpbmd9IGF0dHJOYW1lIFVwZGF0ZWQgYXR0cmlidXRlIG5hbWVcclxuICogQHBhcmFtIHtBbnl9IGNoYW5nZSAgICAgIFVwZGF0ZWQgdmFsdWVcclxuICogQHBhcmFtIHtCb29sZWFufSB3YWl0ICAgIFdoZXRoZXIgdG8gc3RvcmUgdGhlIGFuaW1hdGlvbiB3YWl0aW5nXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgdGhlIG5leHQgYW5pbWF0aW9uIHJlcXVlc3RcclxuICogQHJldHVybiB7UHJvbWlzZX0gQW5pbWF0aW9uIFByb21pc2VcclxuICovXG5cblxuR3JhcGgucHJvdG90eXBlLmFuaW1hdGlvbiA9XG4vKiNfX1BVUkVfXyovXG5mdW5jdGlvbiAoKSB7XG4gIHZhciBfcmVmMiA9ICgwLCBfYXN5bmNUb0dlbmVyYXRvcjJbXCJkZWZhdWx0XCJdKShcbiAgLyojX19QVVJFX18qL1xuICBfcmVnZW5lcmF0b3JbXCJkZWZhdWx0XCJdLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTIoYXR0ck5hbWUsIGNoYW5nZSkge1xuICAgIHZhciB3YWl0LFxuICAgICAgICBjaGFuZ2VSb290LFxuICAgICAgICBjaGFuZ2VLZXlzLFxuICAgICAgICBiZWZvcmVTdGF0ZSxcbiAgICAgICAgYW5pbWF0aW9uRnJhbWUsXG4gICAgICAgIGFuaW1hdGlvbkN1cnZlLFxuICAgICAgICBhbmltYXRpb25EZWxheSxcbiAgICAgICAgYW5pbWF0aW9uRnJhbWVTdGF0ZSxcbiAgICAgICAgcmVuZGVyLFxuICAgICAgICBfYXJnczIgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvcltcImRlZmF1bHRcIl0ud3JhcChmdW5jdGlvbiBfY2FsbGVlMiQoX2NvbnRleHQyKSB7XG4gICAgICB3aGlsZSAoMSkge1xuICAgICAgICBzd2l0Y2ggKF9jb250ZXh0Mi5wcmV2ID0gX2NvbnRleHQyLm5leHQpIHtcbiAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICB3YWl0ID0gX2FyZ3MyLmxlbmd0aCA+IDIgJiYgX2FyZ3MyWzJdICE9PSB1bmRlZmluZWQgPyBfYXJnczJbMl0gOiBmYWxzZTtcblxuICAgICAgICAgICAgaWYgKCEoYXR0ck5hbWUgIT09ICdzaGFwZScgJiYgYXR0ck5hbWUgIT09ICdzdHlsZScpKSB7XG4gICAgICAgICAgICAgIF9jb250ZXh0Mi5uZXh0ID0gNDtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ09ubHkgc3VwcG9ydGVkIHNoYXBlIGFuZCBzdHlsZSBhbmltYXRpb24hJyk7XG4gICAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiKTtcblxuICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIGNoYW5nZSA9ICgwLCBfdXRpbC5kZWVwQ2xvbmUpKGNoYW5nZSwgdHJ1ZSk7XG4gICAgICAgICAgICBpZiAoYXR0ck5hbWUgPT09ICdzdHlsZScpIHRoaXMuc3R5bGUuY29sb3JQcm9jZXNzb3IoY2hhbmdlKTtcbiAgICAgICAgICAgIGNoYW5nZVJvb3QgPSB0aGlzW2F0dHJOYW1lXTtcbiAgICAgICAgICAgIGNoYW5nZUtleXMgPSBPYmplY3Qua2V5cyhjaGFuZ2UpO1xuICAgICAgICAgICAgYmVmb3JlU3RhdGUgPSB7fTtcbiAgICAgICAgICAgIGNoYW5nZUtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBiZWZvcmVTdGF0ZVtrZXldID0gY2hhbmdlUm9vdFtrZXldO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBhbmltYXRpb25GcmFtZSA9IHRoaXMuYW5pbWF0aW9uRnJhbWUsIGFuaW1hdGlvbkN1cnZlID0gdGhpcy5hbmltYXRpb25DdXJ2ZSwgYW5pbWF0aW9uRGVsYXkgPSB0aGlzLmFuaW1hdGlvbkRlbGF5O1xuICAgICAgICAgICAgYW5pbWF0aW9uRnJhbWVTdGF0ZSA9ICgwLCBfdHJhbnNpdGlvbltcImRlZmF1bHRcIl0pKGFuaW1hdGlvbkN1cnZlLCBiZWZvcmVTdGF0ZSwgY2hhbmdlLCBhbmltYXRpb25GcmFtZSwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmFuaW1hdGlvblJvb3QucHVzaChjaGFuZ2VSb290KTtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uS2V5cy5wdXNoKGNoYW5nZUtleXMpO1xuICAgICAgICAgICAgdGhpcy5hbmltYXRpb25GcmFtZVN0YXRlLnB1c2goYW5pbWF0aW9uRnJhbWVTdGF0ZSk7XG5cbiAgICAgICAgICAgIGlmICghd2FpdCkge1xuICAgICAgICAgICAgICBfY29udGV4dDIubmV4dCA9IDE3O1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5hYnJ1cHQoXCJyZXR1cm5cIik7XG5cbiAgICAgICAgICBjYXNlIDE3OlxuICAgICAgICAgICAgaWYgKCEoYW5pbWF0aW9uRGVsYXkgPiAwKSkge1xuICAgICAgICAgICAgICBfY29udGV4dDIubmV4dCA9IDIwO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgX2NvbnRleHQyLm5leHQgPSAyMDtcbiAgICAgICAgICAgIHJldHVybiBkZWxheShhbmltYXRpb25EZWxheSk7XG5cbiAgICAgICAgICBjYXNlIDIwOlxuICAgICAgICAgICAgcmVuZGVyID0gdGhpcy5yZW5kZXI7XG4gICAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiLCBuZXcgUHJvbWlzZShcbiAgICAgICAgICAgIC8qI19fUFVSRV9fKi9cbiAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgdmFyIF9yZWYzID0gKDAsIF9hc3luY1RvR2VuZXJhdG9yMltcImRlZmF1bHRcIl0pKFxuICAgICAgICAgICAgICAvKiNfX1BVUkVfXyovXG4gICAgICAgICAgICAgIF9yZWdlbmVyYXRvcltcImRlZmF1bHRcIl0ubWFyayhmdW5jdGlvbiBfY2FsbGVlKHJlc29sdmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3JlZ2VuZXJhdG9yW1wiZGVmYXVsdFwiXS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUkKF9jb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICB3aGlsZSAoMSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKF9jb250ZXh0LnByZXYgPSBfY29udGV4dC5uZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2NvbnRleHQubmV4dCA9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyLmxhdW5jaEFuaW1hdGlvbigpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY29udGV4dC5zdG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LCBfY2FsbGVlKTtcbiAgICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoX3gzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9yZWYzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KCkpKTtcblxuICAgICAgICAgIGNhc2UgMjI6XG4gICAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5zdG9wKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMiwgdGhpcyk7XG4gIH0pKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKF94LCBfeDIpIHtcbiAgICByZXR1cm4gX3JlZjIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfTtcbn0oKTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gRXh0cmFjdCB0aGUgbmV4dCBmcmFtZSBvZiBkYXRhIGZyb20gdGhlIGFuaW1hdGlvbiBxdWV1ZVxyXG4gKiAgICAgICAgICAgICAgYW5kIHVwZGF0ZSB0aGUgZ3JhcGggc3RhdGVcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5cbkdyYXBoLnByb3RvdHlwZS50dXJuTmV4dEFuaW1hdGlvbkZyYW1lID0gZnVuY3Rpb24gKHRpbWVTdGFtcCkge1xuICB2YXIgYW5pbWF0aW9uRGVsYXkgPSB0aGlzLmFuaW1hdGlvbkRlbGF5LFxuICAgICAgYW5pbWF0aW9uUm9vdCA9IHRoaXMuYW5pbWF0aW9uUm9vdCxcbiAgICAgIGFuaW1hdGlvbktleXMgPSB0aGlzLmFuaW1hdGlvbktleXMsXG4gICAgICBhbmltYXRpb25GcmFtZVN0YXRlID0gdGhpcy5hbmltYXRpb25GcmFtZVN0YXRlLFxuICAgICAgYW5pbWF0aW9uUGF1c2UgPSB0aGlzLmFuaW1hdGlvblBhdXNlO1xuICBpZiAoYW5pbWF0aW9uUGF1c2UpIHJldHVybjtcbiAgaWYgKERhdGUubm93KCkgLSB0aW1lU3RhbXAgPCBhbmltYXRpb25EZWxheSkgcmV0dXJuO1xuICBhbmltYXRpb25Sb290LmZvckVhY2goZnVuY3Rpb24gKHJvb3QsIGkpIHtcbiAgICBhbmltYXRpb25LZXlzW2ldLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgcm9vdFtrZXldID0gYW5pbWF0aW9uRnJhbWVTdGF0ZVtpXVswXVtrZXldO1xuICAgIH0pO1xuICB9KTtcbiAgYW5pbWF0aW9uRnJhbWVTdGF0ZS5mb3JFYWNoKGZ1bmN0aW9uIChzdGF0ZUl0ZW0sIGkpIHtcbiAgICBzdGF0ZUl0ZW0uc2hpZnQoKTtcbiAgICB2YXIgbm9GcmFtZSA9IHN0YXRlSXRlbS5sZW5ndGggPT09IDA7XG4gICAgaWYgKG5vRnJhbWUpIGFuaW1hdGlvblJvb3RbaV0gPSBudWxsO1xuICAgIGlmIChub0ZyYW1lKSBhbmltYXRpb25LZXlzW2ldID0gbnVsbDtcbiAgfSk7XG4gIHRoaXMuYW5pbWF0aW9uRnJhbWVTdGF0ZSA9IGFuaW1hdGlvbkZyYW1lU3RhdGUuZmlsdGVyKGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgIHJldHVybiBzdGF0ZS5sZW5ndGg7XG4gIH0pO1xuICB0aGlzLmFuaW1hdGlvblJvb3QgPSBhbmltYXRpb25Sb290LmZpbHRlcihmdW5jdGlvbiAocm9vdCkge1xuICAgIHJldHVybiByb290O1xuICB9KTtcbiAgdGhpcy5hbmltYXRpb25LZXlzID0gYW5pbWF0aW9uS2V5cy5maWx0ZXIoZnVuY3Rpb24gKGtleXMpIHtcbiAgICByZXR1cm4ga2V5cztcbiAgfSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBTa2lwIHRvIHRoZSBsYXN0IGZyYW1lIG9mIGFuaW1hdGlvblxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuR3JhcGgucHJvdG90eXBlLmFuaW1hdGlvbkVuZCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGFuaW1hdGlvbkZyYW1lU3RhdGUgPSB0aGlzLmFuaW1hdGlvbkZyYW1lU3RhdGUsXG4gICAgICBhbmltYXRpb25LZXlzID0gdGhpcy5hbmltYXRpb25LZXlzLFxuICAgICAgYW5pbWF0aW9uUm9vdCA9IHRoaXMuYW5pbWF0aW9uUm9vdCxcbiAgICAgIHJlbmRlciA9IHRoaXMucmVuZGVyO1xuICBhbmltYXRpb25Sb290LmZvckVhY2goZnVuY3Rpb24gKHJvb3QsIGkpIHtcbiAgICB2YXIgY3VycmVudEtleXMgPSBhbmltYXRpb25LZXlzW2ldO1xuICAgIHZhciBsYXN0U3RhdGUgPSBhbmltYXRpb25GcmFtZVN0YXRlW2ldLnBvcCgpO1xuICAgIGN1cnJlbnRLZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIHJvb3Rba2V5XSA9IGxhc3RTdGF0ZVtrZXldO1xuICAgIH0pO1xuICB9KTtcbiAgdGhpcy5hbmltYXRpb25GcmFtZVN0YXRlID0gW107XG4gIHRoaXMuYW5pbWF0aW9uS2V5cyA9IFtdO1xuICB0aGlzLmFuaW1hdGlvblJvb3QgPSBbXTtcbiAgcmV0dXJuIHJlbmRlci5kcmF3QWxsR3JhcGgoKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFBhdXNlIGFuaW1hdGlvbiBiZWhhdmlvclxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuR3JhcGgucHJvdG90eXBlLnBhdXNlQW5pbWF0aW9uID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmF0dHIoJ2FuaW1hdGlvblBhdXNlJywgdHJ1ZSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBUcnkgYW5pbWF0aW9uIGJlaGF2aW9yXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5HcmFwaC5wcm90b3R5cGUucGxheUFuaW1hdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHJlbmRlciA9IHRoaXMucmVuZGVyO1xuICB0aGlzLmF0dHIoJ2FuaW1hdGlvblBhdXNlJywgZmFsc2UpO1xuICByZXR1cm4gbmV3IFByb21pc2UoXG4gIC8qI19fUFVSRV9fKi9cbiAgZnVuY3Rpb24gKCkge1xuICAgIHZhciBfcmVmNCA9ICgwLCBfYXN5bmNUb0dlbmVyYXRvcjJbXCJkZWZhdWx0XCJdKShcbiAgICAvKiNfX1BVUkVfXyovXG4gICAgX3JlZ2VuZXJhdG9yW1wiZGVmYXVsdFwiXS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUzKHJlc29sdmUpIHtcbiAgICAgIHJldHVybiBfcmVnZW5lcmF0b3JbXCJkZWZhdWx0XCJdLndyYXAoZnVuY3Rpb24gX2NhbGxlZTMkKF9jb250ZXh0Mykge1xuICAgICAgICB3aGlsZSAoMSkge1xuICAgICAgICAgIHN3aXRjaCAoX2NvbnRleHQzLnByZXYgPSBfY29udGV4dDMubmV4dCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDI7XG4gICAgICAgICAgICAgIHJldHVybiByZW5kZXIubGF1bmNoQW5pbWF0aW9uKCk7XG5cbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuXG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgICAgIHJldHVybiBfY29udGV4dDMuc3RvcCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSwgX2NhbGxlZTMpO1xuICAgIH0pKTtcblxuICAgIHJldHVybiBmdW5jdGlvbiAoX3g0KSB7XG4gICAgICByZXR1cm4gX3JlZjQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9KCkpO1xufTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUHJvY2Vzc29yIG9mIGRlbGV0ZVxyXG4gKiBAcGFyYW0ge0NSZW5kZXJ9IHJlbmRlciBJbnN0YW5jZSBvZiBDUmVuZGVyXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5HcmFwaC5wcm90b3R5cGUuZGVsUHJvY2Vzc29yID0gZnVuY3Rpb24gKHJlbmRlcikge1xuICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gIHZhciBncmFwaHMgPSByZW5kZXIuZ3JhcGhzO1xuICB2YXIgaW5kZXggPSBncmFwaHMuZmluZEluZGV4KGZ1bmN0aW9uIChncmFwaCkge1xuICAgIHJldHVybiBncmFwaCA9PT0gX3RoaXM7XG4gIH0pO1xuICBpZiAoaW5kZXggPT09IC0xKSByZXR1cm47XG4gIGlmICh0eXBlb2YgdGhpcy5iZWZvcmVEZWxldGUgPT09ICdmdW5jdGlvbicpIHRoaXMuYmVmb3JlRGVsZXRlKHRoaXMpO1xuICBncmFwaHMuc3BsaWNlKGluZGV4LCAxLCBudWxsKTtcbiAgaWYgKHR5cGVvZiB0aGlzLmRlbGV0ZWQgPT09ICdmdW5jdGlvbicpIHRoaXMuZGVsZXRlZCh0aGlzKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFJldHVybiBhIHRpbWVkIHJlbGVhc2UgUHJvbWlzZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gdGltZSBSZWxlYXNlIHRpbWVcclxuICogQHJldHVybiB7UHJvbWlzZX0gQSB0aW1lZCByZWxlYXNlIFByb21pc2VcclxuICovXG5cblxuZnVuY3Rpb24gZGVsYXkodGltZSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICBzZXRUaW1lb3V0KHJlc29sdmUsIHRpbWUpO1xuICB9KTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IHZvaWQgMDtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIF9jbGFzc0NhbGxDaGVjazIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2NsYXNzQ2FsbENoZWNrXCIpKTtcblxudmFyIF9jb2xvciA9IHJlcXVpcmUoXCJAamlhbWluZ2hpL2NvbG9yXCIpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiLi4vcGx1Z2luL3V0aWxcIik7XG5cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ2xhc3MgU3R5bGVcclxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlICBTdHlsZSBjb25maWd1cmF0aW9uXHJcbiAqIEByZXR1cm4ge1N0eWxlfSBJbnN0YW5jZSBvZiBTdHlsZVxyXG4gKi9cbnZhciBTdHlsZSA9IGZ1bmN0aW9uIFN0eWxlKHN0eWxlKSB7XG4gICgwLCBfY2xhc3NDYWxsQ2hlY2syW1wiZGVmYXVsdFwiXSkodGhpcywgU3R5bGUpO1xuICB0aGlzLmNvbG9yUHJvY2Vzc29yKHN0eWxlKTtcbiAgdmFyIGRlZmF1bHRTdHlsZSA9IHtcbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBSZ2JhIHZhbHVlIG9mIGdyYXBoIGZpbGwgY29sb3JcclxuICAgICAqIEB0eXBlIHtBcnJheX1cclxuICAgICAqIEBkZWZhdWx0IGZpbGwgPSBbMCwgMCwgMCwgMV1cclxuICAgICAqL1xuICAgIGZpbGw6IFswLCAwLCAwLCAxXSxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFJnYmEgdmFsdWUgb2YgZ3JhcGggc3Ryb2tlIGNvbG9yXHJcbiAgICAgKiBAdHlwZSB7QXJyYXl9XHJcbiAgICAgKiBAZGVmYXVsdCBzdHJva2UgPSBbMCwgMCwgMCwgMV1cclxuICAgICAqL1xuICAgIHN0cm9rZTogWzAsIDAsIDAsIDBdLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gT3BhY2l0eSBvZiBncmFwaFxyXG4gICAgICogQHR5cGUge051bWJlcn1cclxuICAgICAqIEBkZWZhdWx0IG9wYWNpdHkgPSAxXHJcbiAgICAgKi9cbiAgICBvcGFjaXR5OiAxLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gTGluZUNhcCBvZiBDdHhcclxuICAgICAqIEB0eXBlIHtTdHJpbmd9XHJcbiAgICAgKiBAZGVmYXVsdCBsaW5lQ2FwID0gbnVsbFxyXG4gICAgICogQGV4YW1wbGUgbGluZUNhcCA9ICdidXR0J3wncm91bmQnfCdzcXVhcmUnXHJcbiAgICAgKi9cbiAgICBsaW5lQ2FwOiBudWxsLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gTGluZWpvaW4gb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgbGluZUpvaW4gPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSBsaW5lSm9pbiA9ICdyb3VuZCd8J2JldmVsJ3wnbWl0ZXInXHJcbiAgICAgKi9cbiAgICBsaW5lSm9pbjogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIExpbmVEYXNoIG9mIEN0eFxyXG4gICAgICogQHR5cGUge0FycmF5fVxyXG4gICAgICogQGRlZmF1bHQgbGluZURhc2ggPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSBsaW5lRGFzaCA9IFsxMCwgMTBdXHJcbiAgICAgKi9cbiAgICBsaW5lRGFzaDogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIExpbmVEYXNoT2Zmc2V0IG9mIEN0eFxyXG4gICAgICogQHR5cGUge051bWJlcn1cclxuICAgICAqIEBkZWZhdWx0IGxpbmVEYXNoT2Zmc2V0ID0gbnVsbFxyXG4gICAgICogQGV4YW1wbGUgbGluZURhc2hPZmZzZXQgPSAxMFxyXG4gICAgICovXG4gICAgbGluZURhc2hPZmZzZXQ6IG51bGwsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBTaGFkb3dCbHVyIG9mIEN0eFxyXG4gICAgICogQHR5cGUge051bWJlcn1cclxuICAgICAqIEBkZWZhdWx0IHNoYWRvd0JsdXIgPSAwXHJcbiAgICAgKi9cbiAgICBzaGFkb3dCbHVyOiAwLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gUmdiYSB2YWx1ZSBvZiBncmFwaCBzaGFkb3cgY29sb3JcclxuICAgICAqIEB0eXBlIHtBcnJheX1cclxuICAgICAqIEBkZWZhdWx0IHNoYWRvd0NvbG9yID0gWzAsIDAsIDAsIDBdXHJcbiAgICAgKi9cbiAgICBzaGFkb3dDb2xvcjogWzAsIDAsIDAsIDBdLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gU2hhZG93T2Zmc2V0WCBvZiBDdHhcclxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XHJcbiAgICAgKiBAZGVmYXVsdCBzaGFkb3dPZmZzZXRYID0gMFxyXG4gICAgICovXG4gICAgc2hhZG93T2Zmc2V0WDogMCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFNoYWRvd09mZnNldFkgb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxyXG4gICAgICogQGRlZmF1bHQgc2hhZG93T2Zmc2V0WSA9IDBcclxuICAgICAqL1xuICAgIHNoYWRvd09mZnNldFk6IDAsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBMaW5lV2lkdGggb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxyXG4gICAgICogQGRlZmF1bHQgbGluZVdpZHRoID0gMFxyXG4gICAgICovXG4gICAgbGluZVdpZHRoOiAwLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gQ2VudGVyIHBvaW50IG9mIHRoZSBncmFwaFxyXG4gICAgICogQHR5cGUge0FycmF5fVxyXG4gICAgICogQGRlZmF1bHQgZ3JhcGhDZW50ZXIgPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSBncmFwaENlbnRlciA9IFsxMCwgMTBdXHJcbiAgICAgKi9cbiAgICBncmFwaENlbnRlcjogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEdyYXBoIHNjYWxlXHJcbiAgICAgKiBAdHlwZSB7QXJyYXl9XHJcbiAgICAgKiBAZGVmYXVsdCBzY2FsZSA9IG51bGxcclxuICAgICAqIEBleGFtcGxlIHNjYWxlID0gWzEuNSwgMS41XVxyXG4gICAgICovXG4gICAgc2NhbGU6IG51bGwsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBHcmFwaCByb3RhdGlvbiBkZWdyZWVcclxuICAgICAqIEB0eXBlIHtOdW1iZXJ9XHJcbiAgICAgKiBAZGVmYXVsdCByb3RhdGUgPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSByb3RhdGUgPSAxMFxyXG4gICAgICovXG4gICAgcm90YXRlOiBudWxsLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gR3JhcGggdHJhbnNsYXRlIGRpc3RhbmNlXHJcbiAgICAgKiBAdHlwZSB7QXJyYXl9XHJcbiAgICAgKiBAZGVmYXVsdCB0cmFuc2xhdGUgPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSB0cmFuc2xhdGUgPSBbMTAsIDEwXVxyXG4gICAgICovXG4gICAgdHJhbnNsYXRlOiBudWxsLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gQ3Vyc29yIHN0YXR1cyB3aGVuIGhvdmVyXHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgaG92ZXJDdXJzb3IgPSAncG9pbnRlcidcclxuICAgICAqIEBleGFtcGxlIGhvdmVyQ3Vyc29yID0gJ2RlZmF1bHQnfCdwb2ludGVyJ3wnYXV0byd8J2Nyb3NzaGFpcid8J21vdmUnfCd3YWl0J3wuLi5cclxuICAgICAqL1xuICAgIGhvdmVyQ3Vyc29yOiAncG9pbnRlcicsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBGb250IHN0eWxlIG9mIEN0eFxyXG4gICAgICogQHR5cGUge1N0cmluZ31cclxuICAgICAqIEBkZWZhdWx0IGZvbnRTdHlsZSA9ICdub3JtYWwnXHJcbiAgICAgKiBAZXhhbXBsZSBmb250U3R5bGUgPSAnbm9ybWFsJ3wnaXRhbGljJ3wnb2JsaXF1ZSdcclxuICAgICAqL1xuICAgIGZvbnRTdHlsZTogJ25vcm1hbCcsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBGb250IHZhcmllbnQgb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgZm9udFZhcmllbnQgPSAnbm9ybWFsJ1xyXG4gICAgICogQGV4YW1wbGUgZm9udFZhcmllbnQgPSAnbm9ybWFsJ3wnc21hbGwtY2FwcydcclxuICAgICAqL1xuICAgIGZvbnRWYXJpZW50OiAnbm9ybWFsJyxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEZvbnQgd2VpZ2h0IG9mIEN0eFxyXG4gICAgICogQHR5cGUge1N0cmluZ3xOdW1iZXJ9XHJcbiAgICAgKiBAZGVmYXVsdCBmb250V2VpZ2h0ID0gJ25vcm1hbCdcclxuICAgICAqIEBleGFtcGxlIGZvbnRXZWlnaHQgPSAnbm9ybWFsJ3wnYm9sZCd8J2JvbGRlcid8J2xpZ2h0ZXInfE51bWJlclxyXG4gICAgICovXG4gICAgZm9udFdlaWdodDogJ25vcm1hbCcsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBGb250IHNpemUgb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7TnVtYmVyfVxyXG4gICAgICogQGRlZmF1bHQgZm9udFNpemUgPSAxMFxyXG4gICAgICovXG4gICAgZm9udFNpemU6IDEwLFxuXG4gICAgLyoqXHJcbiAgICAgKiBAZGVzY3JpcHRpb24gRm9udCBmYW1pbHkgb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgZm9udEZhbWlseSA9ICdBcmlhbCdcclxuICAgICAqL1xuICAgIGZvbnRGYW1pbHk6ICdBcmlhbCcsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBUZXh0QWxpZ24gb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgdGV4dEFsaWduID0gJ2NlbnRlcidcclxuICAgICAqIEBleGFtcGxlIHRleHRBbGlnbiA9ICdzdGFydCd8J2VuZCd8J2xlZnQnfCdyaWdodCd8J2NlbnRlcidcclxuICAgICAqL1xuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBUZXh0QmFzZWxpbmUgb2YgQ3R4XHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgdGV4dEJhc2VsaW5lID0gJ21pZGRsZSdcclxuICAgICAqIEBleGFtcGxlIHRleHRCYXNlbGluZSA9ICd0b3AnfCdib3R0b20nfCdtaWRkbGUnfCdhbHBoYWJldGljJ3wnaGFuZ2luZydcclxuICAgICAqL1xuICAgIHRleHRCYXNlbGluZTogJ21pZGRsZScsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgY29sb3IgdXNlZCB0byBjcmVhdGUgdGhlIGdyYWRpZW50XHJcbiAgICAgKiBAdHlwZSB7QXJyYXl9XHJcbiAgICAgKiBAZGVmYXVsdCBncmFkaWVudENvbG9yID0gbnVsbFxyXG4gICAgICogQGV4YW1wbGUgZ3JhZGllbnRDb2xvciA9IFsnIzAwMCcsICcjMTExJywgJyMyMjInXVxyXG4gICAgICovXG4gICAgZ3JhZGllbnRDb2xvcjogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEdyYWRpZW50IHR5cGVcclxuICAgICAqIEB0eXBlIHtTdHJpbmd9XHJcbiAgICAgKiBAZGVmYXVsdCBncmFkaWVudFR5cGUgPSAnbGluZWFyJ1xyXG4gICAgICogQGV4YW1wbGUgZ3JhZGllbnRUeXBlID0gJ2xpbmVhcicgfCAncmFkaWFsJ1xyXG4gICAgICovXG4gICAgZ3JhZGllbnRUeXBlOiAnbGluZWFyJyxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEdyYWRpZW50IHBhcmFtc1xyXG4gICAgICogQHR5cGUge0FycmF5fVxyXG4gICAgICogQGRlZmF1bHQgZ3JhZGllbnRQYXJhbXMgPSBudWxsXHJcbiAgICAgKiBAZXhhbXBsZSBncmFkaWVudFBhcmFtcyA9IFt4MCwgeTAsIHgxLCB5MV0gKExpbmVhciBHcmFkaWVudClcclxuICAgICAqIEBleGFtcGxlIGdyYWRpZW50UGFyYW1zID0gW3gwLCB5MCwgcjAsIHgxLCB5MSwgcjFdIChSYWRpYWwgR3JhZGllbnQpXHJcbiAgICAgKi9cbiAgICBncmFkaWVudFBhcmFtczogbnVsbCxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIFdoZW4gdG8gdXNlIGdyYWRpZW50c1xyXG4gICAgICogQHR5cGUge1N0cmluZ31cclxuICAgICAqIEBkZWZhdWx0IGdyYWRpZW50V2l0aCA9ICdzdHJva2UnXHJcbiAgICAgKiBAZXhhbXBsZSBncmFkaWVudFdpdGggPSAnc3Ryb2tlJyB8ICdmaWxsJ1xyXG4gICAgICovXG4gICAgZ3JhZGllbnRXaXRoOiAnc3Ryb2tlJyxcblxuICAgIC8qKlxyXG4gICAgICogQGRlc2NyaXB0aW9uIEdyYWRpZW50IGNvbG9yIHN0b3BzXHJcbiAgICAgKiBAdHlwZSB7U3RyaW5nfVxyXG4gICAgICogQGRlZmF1bHQgZ3JhZGllbnRTdG9wcyA9ICdhdXRvJ1xyXG4gICAgICogQGV4YW1wbGUgZ3JhZGllbnRTdG9wcyA9ICdhdXRvJyB8IFswLCAuMiwgLjMsIDFdXHJcbiAgICAgKi9cbiAgICBncmFkaWVudFN0b3BzOiAnYXV0bycsXG5cbiAgICAvKipcclxuICAgICAqIEBkZXNjcmlwdGlvbiBFeHRlbmRlZCBjb2xvciB0aGF0IHN1cHBvcnRzIGFuaW1hdGlvbiB0cmFuc2l0aW9uXHJcbiAgICAgKiBAdHlwZSB7QXJyYXl8T2JqZWN0fVxyXG4gICAgICogQGRlZmF1bHQgY29sb3JzID0gbnVsbFxyXG4gICAgICogQGV4YW1wbGUgY29sb3JzID0gWycjMDAwJywgJyMxMTEnLCAnIzIyMicsICdyZWQnIF1cclxuICAgICAqIEBleGFtcGxlIGNvbG9ycyA9IHsgYTogJyMwMDAnLCBiOiAnIzExMScgfVxyXG4gICAgICovXG4gICAgY29sb3JzOiBudWxsXG4gIH07XG4gIE9iamVjdC5hc3NpZ24odGhpcywgZGVmYXVsdFN0eWxlLCBzdHlsZSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBTZXQgY29sb3JzIHRvIHJnYmEgdmFsdWVcclxuICogQHBhcmFtIHtPYmplY3R9IHN0eWxlIHN0eWxlIGNvbmZpZ1xyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHJldmVyc2UgV2hldGhlciB0byBwZXJmb3JtIHJldmVyc2Ugb3BlcmF0aW9uXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IFN0eWxlO1xuXG5TdHlsZS5wcm90b3R5cGUuY29sb3JQcm9jZXNzb3IgPSBmdW5jdGlvbiAoc3R5bGUpIHtcbiAgdmFyIHJldmVyc2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuICB2YXIgcHJvY2Vzc29yID0gcmV2ZXJzZSA/IF9jb2xvci5nZXRDb2xvckZyb21SZ2JWYWx1ZSA6IF9jb2xvci5nZXRSZ2JhVmFsdWU7XG4gIHZhciBjb2xvclByb2Nlc3NvcktleXMgPSBbJ2ZpbGwnLCAnc3Ryb2tlJywgJ3NoYWRvd0NvbG9yJ107XG4gIHZhciBhbGxLZXlzID0gT2JqZWN0LmtleXMoc3R5bGUpO1xuICB2YXIgY29sb3JLZXlzID0gYWxsS2V5cy5maWx0ZXIoZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiBjb2xvclByb2Nlc3NvcktleXMuZmluZChmdW5jdGlvbiAoaykge1xuICAgICAgcmV0dXJuIGsgPT09IGtleTtcbiAgICB9KTtcbiAgfSk7XG4gIGNvbG9yS2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gc3R5bGVba2V5XSA9IHByb2Nlc3NvcihzdHlsZVtrZXldKTtcbiAgfSk7XG4gIHZhciBncmFkaWVudENvbG9yID0gc3R5bGUuZ3JhZGllbnRDb2xvcixcbiAgICAgIGNvbG9ycyA9IHN0eWxlLmNvbG9ycztcbiAgaWYgKGdyYWRpZW50Q29sb3IpIHN0eWxlLmdyYWRpZW50Q29sb3IgPSBncmFkaWVudENvbG9yLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBwcm9jZXNzb3IoYyk7XG4gIH0pO1xuXG4gIGlmIChjb2xvcnMpIHtcbiAgICB2YXIgY29sb3JzS2V5cyA9IE9iamVjdC5rZXlzKGNvbG9ycyk7XG4gICAgY29sb3JzS2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHJldHVybiBjb2xvcnNba2V5XSA9IHByb2Nlc3Nvcihjb2xvcnNba2V5XSk7XG4gICAgfSk7XG4gIH1cbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEluaXQgZ3JhcGggc3R5bGVcclxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBDb250ZXh0IG9mIGNhbnZhc1xyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuU3R5bGUucHJvdG90eXBlLmluaXRTdHlsZSA9IGZ1bmN0aW9uIChjdHgpIHtcbiAgaW5pdFRyYW5zZm9ybShjdHgsIHRoaXMpO1xuICBpbml0R3JhcGhTdHlsZShjdHgsIHRoaXMpO1xuICBpbml0R3JhZGllbnQoY3R4LCB0aGlzKTtcbn07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEluaXQgY2FudmFzIHRyYW5zZm9ybVxyXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4ICBDb250ZXh0IG9mIGNhbnZhc1xyXG4gKiBAcGFyYW0ge1N0eWxlfSBzdHlsZSBJbnN0YW5jZSBvZiBTdHlsZVxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuZnVuY3Rpb24gaW5pdFRyYW5zZm9ybShjdHgsIHN0eWxlKSB7XG4gIGN0eC5zYXZlKCk7XG4gIHZhciBncmFwaENlbnRlciA9IHN0eWxlLmdyYXBoQ2VudGVyLFxuICAgICAgcm90YXRlID0gc3R5bGUucm90YXRlLFxuICAgICAgc2NhbGUgPSBzdHlsZS5zY2FsZSxcbiAgICAgIHRyYW5zbGF0ZSA9IHN0eWxlLnRyYW5zbGF0ZTtcbiAgaWYgKCEoZ3JhcGhDZW50ZXIgaW5zdGFuY2VvZiBBcnJheSkpIHJldHVybjtcbiAgY3R4LnRyYW5zbGF0ZS5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoZ3JhcGhDZW50ZXIpKTtcbiAgaWYgKHJvdGF0ZSkgY3R4LnJvdGF0ZShyb3RhdGUgKiBNYXRoLlBJIC8gMTgwKTtcbiAgaWYgKHNjYWxlIGluc3RhbmNlb2YgQXJyYXkpIGN0eC5zY2FsZS5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoc2NhbGUpKTtcbiAgaWYgKHRyYW5zbGF0ZSkgY3R4LnRyYW5zbGF0ZS5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkodHJhbnNsYXRlKSk7XG4gIGN0eC50cmFuc2xhdGUoLWdyYXBoQ2VudGVyWzBdLCAtZ3JhcGhDZW50ZXJbMV0pO1xufVxuXG52YXIgYXV0b1NldFN0eWxlS2V5cyA9IFsnbGluZUNhcCcsICdsaW5lSm9pbicsICdsaW5lRGFzaE9mZnNldCcsICdzaGFkb3dPZmZzZXRYJywgJ3NoYWRvd09mZnNldFknLCAnbGluZVdpZHRoJywgJ3RleHRBbGlnbicsICd0ZXh0QmFzZWxpbmUnXTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gU2V0IHRoZSBzdHlsZSBvZiBjYW52YXMgY3R4XHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggIENvbnRleHQgb2YgY2FudmFzXHJcbiAqIEBwYXJhbSB7U3R5bGV9IHN0eWxlIEluc3RhbmNlIG9mIFN0eWxlXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuZnVuY3Rpb24gaW5pdEdyYXBoU3R5bGUoY3R4LCBzdHlsZSkge1xuICB2YXIgZmlsbCA9IHN0eWxlLmZpbGwsXG4gICAgICBzdHJva2UgPSBzdHlsZS5zdHJva2UsXG4gICAgICBzaGFkb3dDb2xvciA9IHN0eWxlLnNoYWRvd0NvbG9yLFxuICAgICAgb3BhY2l0eSA9IHN0eWxlLm9wYWNpdHk7XG4gIGF1dG9TZXRTdHlsZUtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKGtleSB8fCB0eXBlb2Yga2V5ID09PSAnbnVtYmVyJykgY3R4W2tleV0gPSBzdHlsZVtrZXldO1xuICB9KTtcbiAgZmlsbCA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoZmlsbCk7XG4gIHN0cm9rZSA9ICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoc3Ryb2tlKTtcbiAgc2hhZG93Q29sb3IgPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHNoYWRvd0NvbG9yKTtcbiAgZmlsbFszXSAqPSBvcGFjaXR5O1xuICBzdHJva2VbM10gKj0gb3BhY2l0eTtcbiAgc2hhZG93Q29sb3JbM10gKj0gb3BhY2l0eTtcbiAgY3R4LmZpbGxTdHlsZSA9ICgwLCBfY29sb3IuZ2V0Q29sb3JGcm9tUmdiVmFsdWUpKGZpbGwpO1xuICBjdHguc3Ryb2tlU3R5bGUgPSAoMCwgX2NvbG9yLmdldENvbG9yRnJvbVJnYlZhbHVlKShzdHJva2UpO1xuICBjdHguc2hhZG93Q29sb3IgPSAoMCwgX2NvbG9yLmdldENvbG9yRnJvbVJnYlZhbHVlKShzaGFkb3dDb2xvcik7XG4gIHZhciBsaW5lRGFzaCA9IHN0eWxlLmxpbmVEYXNoLFxuICAgICAgc2hhZG93Qmx1ciA9IHN0eWxlLnNoYWRvd0JsdXI7XG5cbiAgaWYgKGxpbmVEYXNoKSB7XG4gICAgbGluZURhc2ggPSBsaW5lRGFzaC5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICAgIHJldHVybiB2ID49IDAgPyB2IDogMDtcbiAgICB9KTtcbiAgICBjdHguc2V0TGluZURhc2gobGluZURhc2gpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBzaGFkb3dCbHVyID09PSAnbnVtYmVyJykgY3R4LnNoYWRvd0JsdXIgPSBzaGFkb3dCbHVyID4gMCA/IHNoYWRvd0JsdXIgOiAwLjAwMTtcbiAgdmFyIGZvbnRTdHlsZSA9IHN0eWxlLmZvbnRTdHlsZSxcbiAgICAgIGZvbnRWYXJpZW50ID0gc3R5bGUuZm9udFZhcmllbnQsXG4gICAgICBmb250V2VpZ2h0ID0gc3R5bGUuZm9udFdlaWdodCxcbiAgICAgIGZvbnRTaXplID0gc3R5bGUuZm9udFNpemUsXG4gICAgICBmb250RmFtaWx5ID0gc3R5bGUuZm9udEZhbWlseTtcbiAgY3R4LmZvbnQgPSBmb250U3R5bGUgKyAnICcgKyBmb250VmFyaWVudCArICcgJyArIGZvbnRXZWlnaHQgKyAnICcgKyBmb250U2l6ZSArICdweCcgKyAnICcgKyBmb250RmFtaWx5O1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBTZXQgdGhlIGdyYWRpZW50IGNvbG9yIG9mIGNhbnZhcyBjdHhcclxuICogQHBhcmFtIHtPYmplY3R9IGN0eCAgQ29udGV4dCBvZiBjYW52YXNcclxuICogQHBhcmFtIHtTdHlsZX0gc3R5bGUgSW5zdGFuY2Ugb2YgU3R5bGVcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGluaXRHcmFkaWVudChjdHgsIHN0eWxlKSB7XG4gIGlmICghZ3JhZGllbnRWYWxpZGF0b3Ioc3R5bGUpKSByZXR1cm47XG4gIHZhciBncmFkaWVudENvbG9yID0gc3R5bGUuZ3JhZGllbnRDb2xvcixcbiAgICAgIGdyYWRpZW50UGFyYW1zID0gc3R5bGUuZ3JhZGllbnRQYXJhbXMsXG4gICAgICBncmFkaWVudFR5cGUgPSBzdHlsZS5ncmFkaWVudFR5cGUsXG4gICAgICBncmFkaWVudFdpdGggPSBzdHlsZS5ncmFkaWVudFdpdGgsXG4gICAgICBncmFkaWVudFN0b3BzID0gc3R5bGUuZ3JhZGllbnRTdG9wcyxcbiAgICAgIG9wYWNpdHkgPSBzdHlsZS5vcGFjaXR5O1xuICBncmFkaWVudENvbG9yID0gZ3JhZGllbnRDb2xvci5tYXAoZnVuY3Rpb24gKGNvbG9yKSB7XG4gICAgdmFyIGNvbG9yT3BhY2l0eSA9IGNvbG9yWzNdICogb3BhY2l0eTtcbiAgICB2YXIgY2xvbmVkQ29sb3IgPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGNvbG9yKTtcbiAgICBjbG9uZWRDb2xvclszXSA9IGNvbG9yT3BhY2l0eTtcbiAgICByZXR1cm4gY2xvbmVkQ29sb3I7XG4gIH0pO1xuICBncmFkaWVudENvbG9yID0gZ3JhZGllbnRDb2xvci5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICByZXR1cm4gKDAsIF9jb2xvci5nZXRDb2xvckZyb21SZ2JWYWx1ZSkoYyk7XG4gIH0pO1xuICBpZiAoZ3JhZGllbnRTdG9wcyA9PT0gJ2F1dG8nKSBncmFkaWVudFN0b3BzID0gZ2V0QXV0b0NvbG9yU3RvcHMoZ3JhZGllbnRDb2xvcik7XG4gIHZhciBncmFkaWVudCA9IGN0eFtcImNyZWF0ZVwiLmNvbmNhdChncmFkaWVudFR5cGUuc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIGdyYWRpZW50VHlwZS5zbGljZSgxKSwgXCJHcmFkaWVudFwiKV0uYXBwbHkoY3R4LCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGdyYWRpZW50UGFyYW1zKSk7XG4gIGdyYWRpZW50U3RvcHMuZm9yRWFjaChmdW5jdGlvbiAoc3RvcCwgaSkge1xuICAgIHJldHVybiBncmFkaWVudC5hZGRDb2xvclN0b3Aoc3RvcCwgZ3JhZGllbnRDb2xvcltpXSk7XG4gIH0pO1xuICBjdHhbXCJcIi5jb25jYXQoZ3JhZGllbnRXaXRoLCBcIlN0eWxlXCIpXSA9IGdyYWRpZW50O1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBDaGVjayBpZiB0aGUgZ3JhZGllbnQgY29uZmlndXJhdGlvbiBpcyBsZWdhbFxyXG4gKiBAcGFyYW0ge1N0eWxlfSBzdHlsZSBJbnN0YW5jZSBvZiBTdHlsZVxyXG4gKiBAcmV0dXJuIHtCb29sZWFufSBDaGVjayBSZXN1bHRcclxuICovXG5cblxuZnVuY3Rpb24gZ3JhZGllbnRWYWxpZGF0b3Ioc3R5bGUpIHtcbiAgdmFyIGdyYWRpZW50Q29sb3IgPSBzdHlsZS5ncmFkaWVudENvbG9yLFxuICAgICAgZ3JhZGllbnRQYXJhbXMgPSBzdHlsZS5ncmFkaWVudFBhcmFtcyxcbiAgICAgIGdyYWRpZW50VHlwZSA9IHN0eWxlLmdyYWRpZW50VHlwZSxcbiAgICAgIGdyYWRpZW50V2l0aCA9IHN0eWxlLmdyYWRpZW50V2l0aCxcbiAgICAgIGdyYWRpZW50U3RvcHMgPSBzdHlsZS5ncmFkaWVudFN0b3BzO1xuICBpZiAoIWdyYWRpZW50Q29sb3IgfHwgIWdyYWRpZW50UGFyYW1zKSByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKGdyYWRpZW50Q29sb3IubGVuZ3RoID09PSAxKSB7XG4gICAgY29uc29sZS53YXJuKCdUaGUgZ3JhZGllbnQgbmVlZHMgdG8gcHJvdmlkZSBhdCBsZWFzdCB0d28gY29sb3JzJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGdyYWRpZW50VHlwZSAhPT0gJ2xpbmVhcicgJiYgZ3JhZGllbnRUeXBlICE9PSAncmFkaWFsJykge1xuICAgIGNvbnNvbGUud2FybignR3JhZGllbnRUeXBlIG9ubHkgc3VwcG9ydHMgbGluZWFyIG9yIHJhZGlhbCwgY3VycmVudCB2YWx1ZSBpcyAnICsgZ3JhZGllbnRUeXBlKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgZ3JhZGllbnRQYXJhbXNMZW5ndGggPSBncmFkaWVudFBhcmFtcy5sZW5ndGg7XG5cbiAgaWYgKGdyYWRpZW50VHlwZSA9PT0gJ2xpbmVhcicgJiYgZ3JhZGllbnRQYXJhbXNMZW5ndGggIT09IDQgfHwgZ3JhZGllbnRUeXBlID09PSAncmFkaWFsJyAmJiBncmFkaWVudFBhcmFtc0xlbmd0aCAhPT0gNikge1xuICAgIGNvbnNvbGUud2FybignVGhlIGV4cGVjdGVkIGxlbmd0aCBvZiBncmFkaWVudFBhcmFtcyBpcyAnICsgKGdyYWRpZW50VHlwZSA9PT0gJ2xpbmVhcicgPyAnNCcgOiAnNicpKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoZ3JhZGllbnRXaXRoICE9PSAnZmlsbCcgJiYgZ3JhZGllbnRXaXRoICE9PSAnc3Ryb2tlJykge1xuICAgIGNvbnNvbGUud2FybignR3JhZGllbnRXaXRoIG9ubHkgc3VwcG9ydHMgZmlsbCBvciBzdHJva2UsIGN1cnJlbnQgdmFsdWUgaXMgJyArIGdyYWRpZW50V2l0aCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGdyYWRpZW50U3RvcHMgIT09ICdhdXRvJyAmJiAhKGdyYWRpZW50U3RvcHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICBjb25zb2xlLndhcm4oXCJncmFkaWVudFN0b3BzIG9ubHkgc3VwcG9ydHMgJ2F1dG8nIG9yIE51bWJlciBBcnJheSAoWzAsIC41LCAxXSksIGN1cnJlbnQgdmFsdWUgaXMgXCIgKyBncmFkaWVudFN0b3BzKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IGEgdW5pZm9ybSBncmFkaWVudCBjb2xvciBzdG9wXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGNvbG9yIEdyYWRpZW50IGNvbG9yXHJcbiAqIEByZXR1cm4ge0FycmF5fSBHcmFkaWVudCBjb2xvciBzdG9wXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldEF1dG9Db2xvclN0b3BzKGNvbG9yKSB7XG4gIHZhciBzdG9wR2FwID0gMSAvIChjb2xvci5sZW5ndGggLSAxKTtcbiAgcmV0dXJuIGNvbG9yLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgcmV0dXJuIHN0b3BHYXAgKiBpO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUmVzdG9yZSBjYW52YXMgY3R4IHRyYW5zZm9ybVxyXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4ICBDb250ZXh0IG9mIGNhbnZhc1xyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuU3R5bGUucHJvdG90eXBlLnJlc3RvcmVUcmFuc2Zvcm0gPSBmdW5jdGlvbiAoY3R4KSB7XG4gIGN0eC5yZXN0b3JlKCk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBVcGRhdGUgc3R5bGUgZGF0YVxyXG4gKiBAcGFyYW0ge09iamVjdH0gY2hhbmdlIENoYW5nZWQgZGF0YVxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IFZvaWRcclxuICovXG5cblxuU3R5bGUucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChjaGFuZ2UpIHtcbiAgdGhpcy5jb2xvclByb2Nlc3NvcihjaGFuZ2UpO1xuICBPYmplY3QuYXNzaWduKHRoaXMsIGNoYW5nZSk7XG59O1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGN1cnJlbnQgc3R5bGUgY29uZmlndXJhdGlvblxyXG4gKiBAcmV0dXJuIHtPYmplY3R9IFN0eWxlIGNvbmZpZ3VyYXRpb25cclxuICovXG5cblxuU3R5bGUucHJvdG90eXBlLmdldFN0eWxlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgY2xvbmVkU3R5bGUgPSAoMCwgX3V0aWwuZGVlcENsb25lKSh0aGlzLCB0cnVlKTtcbiAgdGhpcy5jb2xvclByb2Nlc3NvcihjbG9uZWRTdHlsZSwgdHJ1ZSk7XG4gIHJldHVybiBjbG9uZWRTdHlsZTtcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5leHRlbmROZXdHcmFwaCA9IGV4dGVuZE5ld0dyYXBoO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBleHBvcnRzLnRleHQgPSBleHBvcnRzLmJlemllckN1cnZlID0gZXhwb3J0cy5zbW9vdGhsaW5lID0gZXhwb3J0cy5wb2x5bGluZSA9IGV4cG9ydHMucmVnUG9seWdvbiA9IGV4cG9ydHMuc2VjdG9yID0gZXhwb3J0cy5hcmMgPSBleHBvcnRzLnJpbmcgPSBleHBvcnRzLnJlY3QgPSBleHBvcnRzLmVsbGlwc2UgPSBleHBvcnRzLmNpcmNsZSA9IHZvaWQgMDtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIF9zbGljZWRUb0FycmF5MiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvc2xpY2VkVG9BcnJheVwiKSk7XG5cbnZhciBfYmV6aWVyQ3VydmUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGppYW1pbmdoaS9iZXppZXItY3VydmVcIikpO1xuXG52YXIgX3V0aWwgPSByZXF1aXJlKFwiLi4vcGx1Z2luL3V0aWxcIik7XG5cbnZhciBfY2FudmFzID0gcmVxdWlyZShcIi4uL3BsdWdpbi9jYW52YXNcIik7XG5cbnZhciBwb2x5bGluZVRvQmV6aWVyQ3VydmUgPSBfYmV6aWVyQ3VydmUyW1wiZGVmYXVsdFwiXS5wb2x5bGluZVRvQmV6aWVyQ3VydmUsXG4gICAgYmV6aWVyQ3VydmVUb1BvbHlsaW5lID0gX2JlemllckN1cnZlMltcImRlZmF1bHRcIl0uYmV6aWVyQ3VydmVUb1BvbHlsaW5lO1xudmFyIGNpcmNsZSA9IHtcbiAgc2hhcGU6IHtcbiAgICByeDogMCxcbiAgICByeTogMCxcbiAgICByOiAwXG4gIH0sXG4gIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKF9yZWYpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmLnNoYXBlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5LFxuICAgICAgICByID0gc2hhcGUucjtcblxuICAgIGlmICh0eXBlb2YgcnggIT09ICdudW1iZXInIHx8IHR5cGVvZiByeSAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHIgIT09ICdudW1iZXInKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdDaXJjbGUgc2hhcGUgY29uZmlndXJhdGlvbiBpcyBhYm5vcm1hbCEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgZHJhdzogZnVuY3Rpb24gZHJhdyhfcmVmMiwgX3JlZjMpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjIuY3R4O1xuICAgIHZhciBzaGFwZSA9IF9yZWYzLnNoYXBlO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeSxcbiAgICAgICAgciA9IHNoYXBlLnI7XG4gICAgY3R4LmFyYyhyeCwgcnksIHIgPiAwID8gciA6IDAuMDEsIDAsIE1hdGguUEkgKiAyKTtcbiAgICBjdHguZmlsbCgpO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWY0KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjQuc2hhcGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIHIgPSBzaGFwZS5yO1xuICAgIHJldHVybiAoMCwgX3V0aWwuY2hlY2tQb2ludElzSW5DaXJjbGUpKHBvc2l0aW9uLCByeCwgcnksIHIpO1xuICB9LFxuICBzZXRHcmFwaENlbnRlcjogZnVuY3Rpb24gc2V0R3JhcGhDZW50ZXIoZSwgX3JlZjUpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNS5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNS5zdHlsZTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeTtcbiAgICBzdHlsZS5ncmFwaENlbnRlciA9IFtyeCwgcnldO1xuICB9LFxuICBtb3ZlOiBmdW5jdGlvbiBtb3ZlKF9yZWY2LCBfcmVmNykge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmNi5tb3ZlbWVudFgsXG4gICAgICAgIG1vdmVtZW50WSA9IF9yZWY2Lm1vdmVtZW50WTtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNy5zaGFwZTtcbiAgICB0aGlzLmF0dHIoJ3NoYXBlJywge1xuICAgICAgcng6IHNoYXBlLnJ4ICsgbW92ZW1lbnRYLFxuICAgICAgcnk6IHNoYXBlLnJ5ICsgbW92ZW1lbnRZXG4gICAgfSk7XG4gIH1cbn07XG5leHBvcnRzLmNpcmNsZSA9IGNpcmNsZTtcbnZhciBlbGxpcHNlID0ge1xuICBzaGFwZToge1xuICAgIHJ4OiAwLFxuICAgIHJ5OiAwLFxuICAgIGhyOiAwLFxuICAgIHZyOiAwXG4gIH0sXG4gIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKF9yZWY4KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjguc2hhcGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIGhyID0gc2hhcGUuaHIsXG4gICAgICAgIHZyID0gc2hhcGUudnI7XG5cbiAgICBpZiAodHlwZW9mIHJ4ICE9PSAnbnVtYmVyJyB8fCB0eXBlb2YgcnkgIT09ICdudW1iZXInIHx8IHR5cGVvZiBociAhPT0gJ251bWJlcicgfHwgdHlwZW9mIHZyICE9PSAnbnVtYmVyJykge1xuICAgICAgY29uc29sZS5lcnJvcignRWxsaXBzZSBzaGFwZSBjb25maWd1cmF0aW9uIGlzIGFibm9ybWFsIScpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBkcmF3OiBmdW5jdGlvbiBkcmF3KF9yZWY5LCBfcmVmMTApIHtcbiAgICB2YXIgY3R4ID0gX3JlZjkuY3R4O1xuICAgIHZhciBzaGFwZSA9IF9yZWYxMC5zaGFwZTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIGhyID0gc2hhcGUuaHIsXG4gICAgICAgIHZyID0gc2hhcGUudnI7XG4gICAgY3R4LmVsbGlwc2UocngsIHJ5LCBociA+IDAgPyBociA6IDAuMDEsIHZyID4gMCA/IHZyIDogMC4wMSwgMCwgMCwgTWF0aC5QSSAqIDIpO1xuICAgIGN0eC5maWxsKCk7XG4gICAgY3R4LnN0cm9rZSgpO1xuICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgfSxcbiAgaG92ZXJDaGVjazogZnVuY3Rpb24gaG92ZXJDaGVjayhwb3NpdGlvbiwgX3JlZjExKSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjExLnNoYXBlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5LFxuICAgICAgICBociA9IHNoYXBlLmhyLFxuICAgICAgICB2ciA9IHNoYXBlLnZyO1xuICAgIHZhciBhID0gTWF0aC5tYXgoaHIsIHZyKTtcbiAgICB2YXIgYiA9IE1hdGgubWluKGhyLCB2cik7XG4gICAgdmFyIGMgPSBNYXRoLnNxcnQoYSAqIGEgLSBiICogYik7XG4gICAgdmFyIGxlZnRGb2N1c1BvaW50ID0gW3J4IC0gYywgcnldO1xuICAgIHZhciByaWdodEZvY3VzUG9pbnQgPSBbcnggKyBjLCByeV07XG4gICAgdmFyIGRpc3RhbmNlID0gKDAsIF91dGlsLmdldFR3b1BvaW50RGlzdGFuY2UpKHBvc2l0aW9uLCBsZWZ0Rm9jdXNQb2ludCkgKyAoMCwgX3V0aWwuZ2V0VHdvUG9pbnREaXN0YW5jZSkocG9zaXRpb24sIHJpZ2h0Rm9jdXNQb2ludCk7XG4gICAgcmV0dXJuIGRpc3RhbmNlIDw9IDIgKiBhO1xuICB9LFxuICBzZXRHcmFwaENlbnRlcjogZnVuY3Rpb24gc2V0R3JhcGhDZW50ZXIoZSwgX3JlZjEyKSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjEyLnNoYXBlLFxuICAgICAgICBzdHlsZSA9IF9yZWYxMi5zdHlsZTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeTtcbiAgICBzdHlsZS5ncmFwaENlbnRlciA9IFtyeCwgcnldO1xuICB9LFxuICBtb3ZlOiBmdW5jdGlvbiBtb3ZlKF9yZWYxMywgX3JlZjE0KSB7XG4gICAgdmFyIG1vdmVtZW50WCA9IF9yZWYxMy5tb3ZlbWVudFgsXG4gICAgICAgIG1vdmVtZW50WSA9IF9yZWYxMy5tb3ZlbWVudFk7XG4gICAgdmFyIHNoYXBlID0gX3JlZjE0LnNoYXBlO1xuICAgIHRoaXMuYXR0cignc2hhcGUnLCB7XG4gICAgICByeDogc2hhcGUucnggKyBtb3ZlbWVudFgsXG4gICAgICByeTogc2hhcGUucnkgKyBtb3ZlbWVudFlcbiAgICB9KTtcbiAgfVxufTtcbmV4cG9ydHMuZWxsaXBzZSA9IGVsbGlwc2U7XG52YXIgcmVjdCA9IHtcbiAgc2hhcGU6IHtcbiAgICB4OiAwLFxuICAgIHk6IDAsXG4gICAgdzogMCxcbiAgICBoOiAwXG4gIH0sXG4gIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKF9yZWYxNSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWYxNS5zaGFwZTtcbiAgICB2YXIgeCA9IHNoYXBlLngsXG4gICAgICAgIHkgPSBzaGFwZS55LFxuICAgICAgICB3ID0gc2hhcGUudyxcbiAgICAgICAgaCA9IHNoYXBlLmg7XG5cbiAgICBpZiAodHlwZW9mIHggIT09ICdudW1iZXInIHx8IHR5cGVvZiB5ICE9PSAnbnVtYmVyJyB8fCB0eXBlb2YgdyAhPT0gJ251bWJlcicgfHwgdHlwZW9mIGggIT09ICdudW1iZXInKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdSZWN0IHNoYXBlIGNvbmZpZ3VyYXRpb24gaXMgYWJub3JtYWwhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjE2LCBfcmVmMTcpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjE2LmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMTcuc2hhcGU7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIHZhciB4ID0gc2hhcGUueCxcbiAgICAgICAgeSA9IHNoYXBlLnksXG4gICAgICAgIHcgPSBzaGFwZS53LFxuICAgICAgICBoID0gc2hhcGUuaDtcbiAgICBjdHgucmVjdCh4LCB5LCB3LCBoKTtcbiAgICBjdHguZmlsbCgpO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWYxOCkge1xuICAgIHZhciBzaGFwZSA9IF9yZWYxOC5zaGFwZTtcbiAgICB2YXIgeCA9IHNoYXBlLngsXG4gICAgICAgIHkgPSBzaGFwZS55LFxuICAgICAgICB3ID0gc2hhcGUudyxcbiAgICAgICAgaCA9IHNoYXBlLmg7XG4gICAgcmV0dXJuICgwLCBfdXRpbC5jaGVja1BvaW50SXNJblJlY3QpKHBvc2l0aW9uLCB4LCB5LCB3LCBoKTtcbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWYxOSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWYxOS5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmMTkuc3R5bGU7XG4gICAgdmFyIHggPSBzaGFwZS54LFxuICAgICAgICB5ID0gc2hhcGUueSxcbiAgICAgICAgdyA9IHNoYXBlLncsXG4gICAgICAgIGggPSBzaGFwZS5oO1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gW3ggKyB3IC8gMiwgeSArIGggLyAyXTtcbiAgfSxcbiAgbW92ZTogZnVuY3Rpb24gbW92ZShfcmVmMjAsIF9yZWYyMSkge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmMjAubW92ZW1lbnRYLFxuICAgICAgICBtb3ZlbWVudFkgPSBfcmVmMjAubW92ZW1lbnRZO1xuICAgIHZhciBzaGFwZSA9IF9yZWYyMS5zaGFwZTtcbiAgICB0aGlzLmF0dHIoJ3NoYXBlJywge1xuICAgICAgeDogc2hhcGUueCArIG1vdmVtZW50WCxcbiAgICAgIHk6IHNoYXBlLnkgKyBtb3ZlbWVudFlcbiAgICB9KTtcbiAgfVxufTtcbmV4cG9ydHMucmVjdCA9IHJlY3Q7XG52YXIgcmluZyA9IHtcbiAgc2hhcGU6IHtcbiAgICByeDogMCxcbiAgICByeTogMCxcbiAgICByOiAwXG4gIH0sXG4gIHZhbGlkYXRvcjogZnVuY3Rpb24gdmFsaWRhdG9yKF9yZWYyMikge1xuICAgIHZhciBzaGFwZSA9IF9yZWYyMi5zaGFwZTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeSxcbiAgICAgICAgciA9IHNoYXBlLnI7XG5cbiAgICBpZiAodHlwZW9mIHJ4ICE9PSAnbnVtYmVyJyB8fCB0eXBlb2YgcnkgIT09ICdudW1iZXInIHx8IHR5cGVvZiByICE9PSAnbnVtYmVyJykge1xuICAgICAgY29uc29sZS5lcnJvcignUmluZyBzaGFwZSBjb25maWd1cmF0aW9uIGlzIGFibm9ybWFsIScpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBkcmF3OiBmdW5jdGlvbiBkcmF3KF9yZWYyMywgX3JlZjI0KSB7XG4gICAgdmFyIGN0eCA9IF9yZWYyMy5jdHg7XG4gICAgdmFyIHNoYXBlID0gX3JlZjI0LnNoYXBlO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeSxcbiAgICAgICAgciA9IHNoYXBlLnI7XG4gICAgY3R4LmFyYyhyeCwgcnksIHIgPiAwID8gciA6IDAuMDEsIDAsIE1hdGguUEkgKiAyKTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICB9LFxuICBob3ZlckNoZWNrOiBmdW5jdGlvbiBob3ZlckNoZWNrKHBvc2l0aW9uLCBfcmVmMjUpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMjUuc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjI1LnN0eWxlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5LFxuICAgICAgICByID0gc2hhcGUucjtcbiAgICB2YXIgbGluZVdpZHRoID0gc3R5bGUubGluZVdpZHRoO1xuICAgIHZhciBoYWxmTGluZVdpZHRoID0gbGluZVdpZHRoIC8gMjtcbiAgICB2YXIgbWluRGlzdGFuY2UgPSByIC0gaGFsZkxpbmVXaWR0aDtcbiAgICB2YXIgbWF4RGlzdGFuY2UgPSByICsgaGFsZkxpbmVXaWR0aDtcbiAgICB2YXIgZGlzdGFuY2UgPSAoMCwgX3V0aWwuZ2V0VHdvUG9pbnREaXN0YW5jZSkocG9zaXRpb24sIFtyeCwgcnldKTtcbiAgICByZXR1cm4gZGlzdGFuY2UgPj0gbWluRGlzdGFuY2UgJiYgZGlzdGFuY2UgPD0gbWF4RGlzdGFuY2U7XG4gIH0sXG4gIHNldEdyYXBoQ2VudGVyOiBmdW5jdGlvbiBzZXRHcmFwaENlbnRlcihlLCBfcmVmMjYpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMjYuc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjI2LnN0eWxlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5O1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gW3J4LCByeV07XG4gIH0sXG4gIG1vdmU6IGZ1bmN0aW9uIG1vdmUoX3JlZjI3LCBfcmVmMjgpIHtcbiAgICB2YXIgbW92ZW1lbnRYID0gX3JlZjI3Lm1vdmVtZW50WCxcbiAgICAgICAgbW92ZW1lbnRZID0gX3JlZjI3Lm1vdmVtZW50WTtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMjguc2hhcGU7XG4gICAgdGhpcy5hdHRyKCdzaGFwZScsIHtcbiAgICAgIHJ4OiBzaGFwZS5yeCArIG1vdmVtZW50WCxcbiAgICAgIHJ5OiBzaGFwZS5yeSArIG1vdmVtZW50WVxuICAgIH0pO1xuICB9XG59O1xuZXhwb3J0cy5yaW5nID0gcmluZztcbnZhciBhcmMgPSB7XG4gIHNoYXBlOiB7XG4gICAgcng6IDAsXG4gICAgcnk6IDAsXG4gICAgcjogMCxcbiAgICBzdGFydEFuZ2xlOiAwLFxuICAgIGVuZEFuZ2xlOiAwLFxuICAgIGNsb2NrV2lzZTogdHJ1ZVxuICB9LFxuICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihfcmVmMjkpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMjkuc2hhcGU7XG4gICAgdmFyIGtleXMgPSBbJ3J4JywgJ3J5JywgJ3InLCAnc3RhcnRBbmdsZScsICdlbmRBbmdsZSddO1xuXG4gICAgaWYgKGtleXMuZmluZChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHNoYXBlW2tleV0gIT09ICdudW1iZXInO1xuICAgIH0pKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdBcmMgc2hhcGUgY29uZmlndXJhdGlvbiBpcyBhYm5vcm1hbCEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgZHJhdzogZnVuY3Rpb24gZHJhdyhfcmVmMzAsIF9yZWYzMSkge1xuICAgIHZhciBjdHggPSBfcmVmMzAuY3R4O1xuICAgIHZhciBzaGFwZSA9IF9yZWYzMS5zaGFwZTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIHIgPSBzaGFwZS5yLFxuICAgICAgICBzdGFydEFuZ2xlID0gc2hhcGUuc3RhcnRBbmdsZSxcbiAgICAgICAgZW5kQW5nbGUgPSBzaGFwZS5lbmRBbmdsZSxcbiAgICAgICAgY2xvY2tXaXNlID0gc2hhcGUuY2xvY2tXaXNlO1xuICAgIGN0eC5hcmMocngsIHJ5LCByID4gMCA/IHIgOiAwLjAwMSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsICFjbG9ja1dpc2UpO1xuICAgIGN0eC5zdHJva2UoKTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWYzMikge1xuICAgIHZhciBzaGFwZSA9IF9yZWYzMi5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmMzIuc3R5bGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIHIgPSBzaGFwZS5yLFxuICAgICAgICBzdGFydEFuZ2xlID0gc2hhcGUuc3RhcnRBbmdsZSxcbiAgICAgICAgZW5kQW5nbGUgPSBzaGFwZS5lbmRBbmdsZSxcbiAgICAgICAgY2xvY2tXaXNlID0gc2hhcGUuY2xvY2tXaXNlO1xuICAgIHZhciBsaW5lV2lkdGggPSBzdHlsZS5saW5lV2lkdGg7XG4gICAgdmFyIGhhbGZMaW5lV2lkdGggPSBsaW5lV2lkdGggLyAyO1xuICAgIHZhciBpbnNpZGVSYWRpdXMgPSByIC0gaGFsZkxpbmVXaWR0aDtcbiAgICB2YXIgb3V0c2lkZVJhZGl1cyA9IHIgKyBoYWxmTGluZVdpZHRoO1xuICAgIHJldHVybiAhKDAsIF91dGlsLmNoZWNrUG9pbnRJc0luU2VjdG9yKShwb3NpdGlvbiwgcngsIHJ5LCBpbnNpZGVSYWRpdXMsIHN0YXJ0QW5nbGUsIGVuZEFuZ2xlLCBjbG9ja1dpc2UpICYmICgwLCBfdXRpbC5jaGVja1BvaW50SXNJblNlY3RvcikocG9zaXRpb24sIHJ4LCByeSwgb3V0c2lkZVJhZGl1cywgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGNsb2NrV2lzZSk7XG4gIH0sXG4gIHNldEdyYXBoQ2VudGVyOiBmdW5jdGlvbiBzZXRHcmFwaENlbnRlcihlLCBfcmVmMzMpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMzMuc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjMzLnN0eWxlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5O1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gW3J4LCByeV07XG4gIH0sXG4gIG1vdmU6IGZ1bmN0aW9uIG1vdmUoX3JlZjM0LCBfcmVmMzUpIHtcbiAgICB2YXIgbW92ZW1lbnRYID0gX3JlZjM0Lm1vdmVtZW50WCxcbiAgICAgICAgbW92ZW1lbnRZID0gX3JlZjM0Lm1vdmVtZW50WTtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMzUuc2hhcGU7XG4gICAgdGhpcy5hdHRyKCdzaGFwZScsIHtcbiAgICAgIHJ4OiBzaGFwZS5yeCArIG1vdmVtZW50WCxcbiAgICAgIHJ5OiBzaGFwZS5yeSArIG1vdmVtZW50WVxuICAgIH0pO1xuICB9XG59O1xuZXhwb3J0cy5hcmMgPSBhcmM7XG52YXIgc2VjdG9yID0ge1xuICBzaGFwZToge1xuICAgIHJ4OiAwLFxuICAgIHJ5OiAwLFxuICAgIHI6IDAsXG4gICAgc3RhcnRBbmdsZTogMCxcbiAgICBlbmRBbmdsZTogMCxcbiAgICBjbG9ja1dpc2U6IHRydWVcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjM2KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjM2LnNoYXBlO1xuICAgIHZhciBrZXlzID0gWydyeCcsICdyeScsICdyJywgJ3N0YXJ0QW5nbGUnLCAnZW5kQW5nbGUnXTtcblxuICAgIGlmIChrZXlzLmZpbmQoZnVuY3Rpb24gKGtleSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiBzaGFwZVtrZXldICE9PSAnbnVtYmVyJztcbiAgICB9KSkge1xuICAgICAgY29uc29sZS5lcnJvcignU2VjdG9yIHNoYXBlIGNvbmZpZ3VyYXRpb24gaXMgYWJub3JtYWwhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjM3LCBfcmVmMzgpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjM3LmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmMzguc2hhcGU7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5LFxuICAgICAgICByID0gc2hhcGUucixcbiAgICAgICAgc3RhcnRBbmdsZSA9IHNoYXBlLnN0YXJ0QW5nbGUsXG4gICAgICAgIGVuZEFuZ2xlID0gc2hhcGUuZW5kQW5nbGUsXG4gICAgICAgIGNsb2NrV2lzZSA9IHNoYXBlLmNsb2NrV2lzZTtcbiAgICBjdHguYXJjKHJ4LCByeSwgciA+IDAgPyByIDogMC4wMSwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsICFjbG9ja1dpc2UpO1xuICAgIGN0eC5saW5lVG8ocngsIHJ5KTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgY3R4LnN0cm9rZSgpO1xuICAgIGN0eC5maWxsKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWYzOSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWYzOS5zaGFwZTtcbiAgICB2YXIgcnggPSBzaGFwZS5yeCxcbiAgICAgICAgcnkgPSBzaGFwZS5yeSxcbiAgICAgICAgciA9IHNoYXBlLnIsXG4gICAgICAgIHN0YXJ0QW5nbGUgPSBzaGFwZS5zdGFydEFuZ2xlLFxuICAgICAgICBlbmRBbmdsZSA9IHNoYXBlLmVuZEFuZ2xlLFxuICAgICAgICBjbG9ja1dpc2UgPSBzaGFwZS5jbG9ja1dpc2U7XG4gICAgcmV0dXJuICgwLCBfdXRpbC5jaGVja1BvaW50SXNJblNlY3RvcikocG9zaXRpb24sIHJ4LCByeSwgciwgc3RhcnRBbmdsZSwgZW5kQW5nbGUsIGNsb2NrV2lzZSk7XG4gIH0sXG4gIHNldEdyYXBoQ2VudGVyOiBmdW5jdGlvbiBzZXRHcmFwaENlbnRlcihlLCBfcmVmNDApIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNDAuc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjQwLnN0eWxlO1xuICAgIHZhciByeCA9IHNoYXBlLnJ4LFxuICAgICAgICByeSA9IHNoYXBlLnJ5O1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gW3J4LCByeV07XG4gIH0sXG4gIG1vdmU6IGZ1bmN0aW9uIG1vdmUoX3JlZjQxLCBfcmVmNDIpIHtcbiAgICB2YXIgbW92ZW1lbnRYID0gX3JlZjQxLm1vdmVtZW50WCxcbiAgICAgICAgbW92ZW1lbnRZID0gX3JlZjQxLm1vdmVtZW50WTtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNDIuc2hhcGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnk7XG4gICAgdGhpcy5hdHRyKCdzaGFwZScsIHtcbiAgICAgIHJ4OiByeCArIG1vdmVtZW50WCxcbiAgICAgIHJ5OiByeSArIG1vdmVtZW50WVxuICAgIH0pO1xuICB9XG59O1xuZXhwb3J0cy5zZWN0b3IgPSBzZWN0b3I7XG52YXIgcmVnUG9seWdvbiA9IHtcbiAgc2hhcGU6IHtcbiAgICByeDogMCxcbiAgICByeTogMCxcbiAgICByOiAwLFxuICAgIHNpZGU6IDBcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjQzKSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjQzLnNoYXBlO1xuICAgIHZhciBzaWRlID0gc2hhcGUuc2lkZTtcbiAgICB2YXIga2V5cyA9IFsncngnLCAncnknLCAncicsICdzaWRlJ107XG5cbiAgICBpZiAoa2V5cy5maW5kKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHJldHVybiB0eXBlb2Ygc2hhcGVba2V5XSAhPT0gJ251bWJlcic7XG4gICAgfSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1JlZ1BvbHlnb24gc2hhcGUgY29uZmlndXJhdGlvbiBpcyBhYm5vcm1hbCEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoc2lkZSA8IDMpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1JlZ1BvbHlnb24gYXQgbGVhc3QgdHJpZ29uIScpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBkcmF3OiBmdW5jdGlvbiBkcmF3KF9yZWY0NCwgX3JlZjQ1KSB7XG4gICAgdmFyIGN0eCA9IF9yZWY0NC5jdHg7XG4gICAgdmFyIHNoYXBlID0gX3JlZjQ1LnNoYXBlLFxuICAgICAgICBjYWNoZSA9IF9yZWY0NS5jYWNoZTtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnksXG4gICAgICAgIHIgPSBzaGFwZS5yLFxuICAgICAgICBzaWRlID0gc2hhcGUuc2lkZTtcblxuICAgIGlmICghY2FjaGUucG9pbnRzIHx8IGNhY2hlLnJ4ICE9PSByeCB8fCBjYWNoZS5yeSAhPT0gcnkgfHwgY2FjaGUuciAhPT0gciB8fCBjYWNoZS5zaWRlICE9PSBzaWRlKSB7XG4gICAgICB2YXIgX3BvaW50cyA9ICgwLCBfdXRpbC5nZXRSZWd1bGFyUG9seWdvblBvaW50cykocngsIHJ5LCByLCBzaWRlKTtcblxuICAgICAgT2JqZWN0LmFzc2lnbihjYWNoZSwge1xuICAgICAgICBwb2ludHM6IF9wb2ludHMsXG4gICAgICAgIHJ4OiByeCxcbiAgICAgICAgcnk6IHJ5LFxuICAgICAgICByOiByLFxuICAgICAgICBzaWRlOiBzaWRlXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcG9pbnRzID0gY2FjaGUucG9pbnRzO1xuICAgICgwLCBfY2FudmFzLmRyYXdQb2x5bGluZVBhdGgpKGN0eCwgcG9pbnRzKTtcbiAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgY3R4LnN0cm9rZSgpO1xuICAgIGN0eC5maWxsKCk7XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWY0Nikge1xuICAgIHZhciBjYWNoZSA9IF9yZWY0Ni5jYWNoZTtcbiAgICB2YXIgcG9pbnRzID0gY2FjaGUucG9pbnRzO1xuICAgIHJldHVybiAoMCwgX3V0aWwuY2hlY2tQb2ludElzSW5Qb2x5Z29uKShwb3NpdGlvbiwgcG9pbnRzKTtcbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWY0Nykge1xuICAgIHZhciBzaGFwZSA9IF9yZWY0Ny5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNDcuc3R5bGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnk7XG4gICAgc3R5bGUuZ3JhcGhDZW50ZXIgPSBbcngsIHJ5XTtcbiAgfSxcbiAgbW92ZTogZnVuY3Rpb24gbW92ZShfcmVmNDgsIF9yZWY0OSkge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmNDgubW92ZW1lbnRYLFxuICAgICAgICBtb3ZlbWVudFkgPSBfcmVmNDgubW92ZW1lbnRZO1xuICAgIHZhciBzaGFwZSA9IF9yZWY0OS5zaGFwZSxcbiAgICAgICAgY2FjaGUgPSBfcmVmNDkuY2FjaGU7XG4gICAgdmFyIHJ4ID0gc2hhcGUucngsXG4gICAgICAgIHJ5ID0gc2hhcGUucnk7XG4gICAgY2FjaGUucnggKz0gbW92ZW1lbnRYO1xuICAgIGNhY2hlLnJ5ICs9IG1vdmVtZW50WTtcbiAgICB0aGlzLmF0dHIoJ3NoYXBlJywge1xuICAgICAgcng6IHJ4ICsgbW92ZW1lbnRYLFxuICAgICAgcnk6IHJ5ICsgbW92ZW1lbnRZXG4gICAgfSk7XG4gICAgY2FjaGUucG9pbnRzID0gY2FjaGUucG9pbnRzLm1hcChmdW5jdGlvbiAoX3JlZjUwKSB7XG4gICAgICB2YXIgX3JlZjUxID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY1MCwgMiksXG4gICAgICAgICAgeCA9IF9yZWY1MVswXSxcbiAgICAgICAgICB5ID0gX3JlZjUxWzFdO1xuXG4gICAgICByZXR1cm4gW3ggKyBtb3ZlbWVudFgsIHkgKyBtb3ZlbWVudFldO1xuICAgIH0pO1xuICB9XG59O1xuZXhwb3J0cy5yZWdQb2x5Z29uID0gcmVnUG9seWdvbjtcbnZhciBwb2x5bGluZSA9IHtcbiAgc2hhcGU6IHtcbiAgICBwb2ludHM6IFtdLFxuICAgIGNsb3NlOiBmYWxzZVxuICB9LFxuICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihfcmVmNTIpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNTIuc2hhcGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cztcblxuICAgIGlmICghKHBvaW50cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgY29uc29sZS5lcnJvcignUG9seWxpbmUgcG9pbnRzIHNob3VsZCBiZSBhbiBhcnJheSEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgZHJhdzogZnVuY3Rpb24gZHJhdyhfcmVmNTMsIF9yZWY1NCkge1xuICAgIHZhciBjdHggPSBfcmVmNTMuY3R4O1xuICAgIHZhciBzaGFwZSA9IF9yZWY1NC5zaGFwZSxcbiAgICAgICAgbGluZVdpZHRoID0gX3JlZjU0LnN0eWxlLmxpbmVXaWR0aDtcbiAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cyxcbiAgICAgICAgY2xvc2UgPSBzaGFwZS5jbG9zZTtcbiAgICBpZiAobGluZVdpZHRoID09PSAxKSBwb2ludHMgPSAoMCwgX3V0aWwuZWxpbWluYXRlQmx1cikocG9pbnRzKTtcbiAgICAoMCwgX2NhbnZhcy5kcmF3UG9seWxpbmVQYXRoKShjdHgsIHBvaW50cyk7XG5cbiAgICBpZiAoY2xvc2UpIHtcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgIGN0eC5maWxsKCk7XG4gICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWY1NSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWY1NS5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNTUuc3R5bGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cyxcbiAgICAgICAgY2xvc2UgPSBzaGFwZS5jbG9zZTtcbiAgICB2YXIgbGluZVdpZHRoID0gc3R5bGUubGluZVdpZHRoO1xuXG4gICAgaWYgKGNsb3NlKSB7XG4gICAgICByZXR1cm4gKDAsIF91dGlsLmNoZWNrUG9pbnRJc0luUG9seWdvbikocG9zaXRpb24sIHBvaW50cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAoMCwgX3V0aWwuY2hlY2tQb2ludElzTmVhclBvbHlsaW5lKShwb3NpdGlvbiwgcG9pbnRzLCBsaW5lV2lkdGgpO1xuICAgIH1cbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWY1Nikge1xuICAgIHZhciBzaGFwZSA9IF9yZWY1Ni5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNTYuc3R5bGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cztcbiAgICBzdHlsZS5ncmFwaENlbnRlciA9IHBvaW50c1swXTtcbiAgfSxcbiAgbW92ZTogZnVuY3Rpb24gbW92ZShfcmVmNTcsIF9yZWY1OCkge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmNTcubW92ZW1lbnRYLFxuICAgICAgICBtb3ZlbWVudFkgPSBfcmVmNTcubW92ZW1lbnRZO1xuICAgIHZhciBzaGFwZSA9IF9yZWY1OC5zaGFwZTtcbiAgICB2YXIgcG9pbnRzID0gc2hhcGUucG9pbnRzO1xuICAgIHZhciBtb3ZlQWZ0ZXJQb2ludHMgPSBwb2ludHMubWFwKGZ1bmN0aW9uIChfcmVmNTkpIHtcbiAgICAgIHZhciBfcmVmNjAgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjU5LCAyKSxcbiAgICAgICAgICB4ID0gX3JlZjYwWzBdLFxuICAgICAgICAgIHkgPSBfcmVmNjBbMV07XG5cbiAgICAgIHJldHVybiBbeCArIG1vdmVtZW50WCwgeSArIG1vdmVtZW50WV07XG4gICAgfSk7XG4gICAgdGhpcy5hdHRyKCdzaGFwZScsIHtcbiAgICAgIHBvaW50czogbW92ZUFmdGVyUG9pbnRzXG4gICAgfSk7XG4gIH1cbn07XG5leHBvcnRzLnBvbHlsaW5lID0gcG9seWxpbmU7XG52YXIgc21vb3RobGluZSA9IHtcbiAgc2hhcGU6IHtcbiAgICBwb2ludHM6IFtdLFxuICAgIGNsb3NlOiBmYWxzZVxuICB9LFxuICB2YWxpZGF0b3I6IGZ1bmN0aW9uIHZhbGlkYXRvcihfcmVmNjEpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNjEuc2hhcGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cztcblxuICAgIGlmICghKHBvaW50cyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgY29uc29sZS5lcnJvcignU21vb3RobGluZSBwb2ludHMgc2hvdWxkIGJlIGFuIGFycmF5IScpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuICBkcmF3OiBmdW5jdGlvbiBkcmF3KF9yZWY2MiwgX3JlZjYzKSB7XG4gICAgdmFyIGN0eCA9IF9yZWY2Mi5jdHg7XG4gICAgdmFyIHNoYXBlID0gX3JlZjYzLnNoYXBlLFxuICAgICAgICBjYWNoZSA9IF9yZWY2My5jYWNoZTtcbiAgICB2YXIgcG9pbnRzID0gc2hhcGUucG9pbnRzLFxuICAgICAgICBjbG9zZSA9IHNoYXBlLmNsb3NlO1xuXG4gICAgaWYgKCFjYWNoZS5wb2ludHMgfHwgY2FjaGUucG9pbnRzLnRvU3RyaW5nKCkgIT09IHBvaW50cy50b1N0cmluZygpKSB7XG4gICAgICB2YXIgX2JlemllckN1cnZlID0gcG9seWxpbmVUb0JlemllckN1cnZlKHBvaW50cywgY2xvc2UpO1xuXG4gICAgICB2YXIgaG92ZXJQb2ludHMgPSBiZXppZXJDdXJ2ZVRvUG9seWxpbmUoX2JlemllckN1cnZlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24oY2FjaGUsIHtcbiAgICAgICAgcG9pbnRzOiAoMCwgX3V0aWwuZGVlcENsb25lKShwb2ludHMsIHRydWUpLFxuICAgICAgICBiZXppZXJDdXJ2ZTogX2JlemllckN1cnZlLFxuICAgICAgICBob3ZlclBvaW50czogaG92ZXJQb2ludHNcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBiZXppZXJDdXJ2ZSA9IGNhY2hlLmJlemllckN1cnZlO1xuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAoMCwgX2NhbnZhcy5kcmF3QmV6aWVyQ3VydmVQYXRoKShjdHgsIGJlemllckN1cnZlLnNsaWNlKDEpLCBiZXppZXJDdXJ2ZVswXSk7XG5cbiAgICBpZiAoY2xvc2UpIHtcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgIGN0eC5maWxsKCk7XG4gICAgICBjdHguc3Ryb2tlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9XG4gIH0sXG4gIGhvdmVyQ2hlY2s6IGZ1bmN0aW9uIGhvdmVyQ2hlY2socG9zaXRpb24sIF9yZWY2NCkge1xuICAgIHZhciBjYWNoZSA9IF9yZWY2NC5jYWNoZSxcbiAgICAgICAgc2hhcGUgPSBfcmVmNjQuc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjY0LnN0eWxlO1xuICAgIHZhciBob3ZlclBvaW50cyA9IGNhY2hlLmhvdmVyUG9pbnRzO1xuICAgIHZhciBjbG9zZSA9IHNoYXBlLmNsb3NlO1xuICAgIHZhciBsaW5lV2lkdGggPSBzdHlsZS5saW5lV2lkdGg7XG5cbiAgICBpZiAoY2xvc2UpIHtcbiAgICAgIHJldHVybiAoMCwgX3V0aWwuY2hlY2tQb2ludElzSW5Qb2x5Z29uKShwb3NpdGlvbiwgaG92ZXJQb2ludHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gKDAsIF91dGlsLmNoZWNrUG9pbnRJc05lYXJQb2x5bGluZSkocG9zaXRpb24sIGhvdmVyUG9pbnRzLCBsaW5lV2lkdGgpO1xuICAgIH1cbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWY2NSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWY2NS5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNjUuc3R5bGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cztcbiAgICBzdHlsZS5ncmFwaENlbnRlciA9IHBvaW50c1swXTtcbiAgfSxcbiAgbW92ZTogZnVuY3Rpb24gbW92ZShfcmVmNjYsIF9yZWY2Nykge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmNjYubW92ZW1lbnRYLFxuICAgICAgICBtb3ZlbWVudFkgPSBfcmVmNjYubW92ZW1lbnRZO1xuICAgIHZhciBzaGFwZSA9IF9yZWY2Ny5zaGFwZSxcbiAgICAgICAgY2FjaGUgPSBfcmVmNjcuY2FjaGU7XG4gICAgdmFyIHBvaW50cyA9IHNoYXBlLnBvaW50cztcbiAgICB2YXIgbW92ZUFmdGVyUG9pbnRzID0gcG9pbnRzLm1hcChmdW5jdGlvbiAoX3JlZjY4KSB7XG4gICAgICB2YXIgX3JlZjY5ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY2OCwgMiksXG4gICAgICAgICAgeCA9IF9yZWY2OVswXSxcbiAgICAgICAgICB5ID0gX3JlZjY5WzFdO1xuXG4gICAgICByZXR1cm4gW3ggKyBtb3ZlbWVudFgsIHkgKyBtb3ZlbWVudFldO1xuICAgIH0pO1xuICAgIGNhY2hlLnBvaW50cyA9IG1vdmVBZnRlclBvaW50cztcblxuICAgIHZhciBfY2FjaGUkYmV6aWVyQ3VydmUkID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKGNhY2hlLmJlemllckN1cnZlWzBdLCAyKSxcbiAgICAgICAgZnggPSBfY2FjaGUkYmV6aWVyQ3VydmUkWzBdLFxuICAgICAgICBmeSA9IF9jYWNoZSRiZXppZXJDdXJ2ZSRbMV07XG5cbiAgICB2YXIgY3VydmVzID0gY2FjaGUuYmV6aWVyQ3VydmUuc2xpY2UoMSk7XG4gICAgY2FjaGUuYmV6aWVyQ3VydmUgPSBbW2Z4ICsgbW92ZW1lbnRYLCBmeSArIG1vdmVtZW50WV1dLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKGN1cnZlcy5tYXAoZnVuY3Rpb24gKGN1cnZlKSB7XG4gICAgICByZXR1cm4gY3VydmUubWFwKGZ1bmN0aW9uIChfcmVmNzApIHtcbiAgICAgICAgdmFyIF9yZWY3MSA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmNzAsIDIpLFxuICAgICAgICAgICAgeCA9IF9yZWY3MVswXSxcbiAgICAgICAgICAgIHkgPSBfcmVmNzFbMV07XG5cbiAgICAgICAgcmV0dXJuIFt4ICsgbW92ZW1lbnRYLCB5ICsgbW92ZW1lbnRZXTtcbiAgICAgIH0pO1xuICAgIH0pKSk7XG4gICAgY2FjaGUuaG92ZXJQb2ludHMgPSBjYWNoZS5ob3ZlclBvaW50cy5tYXAoZnVuY3Rpb24gKF9yZWY3Mikge1xuICAgICAgdmFyIF9yZWY3MyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmNzIsIDIpLFxuICAgICAgICAgIHggPSBfcmVmNzNbMF0sXG4gICAgICAgICAgeSA9IF9yZWY3M1sxXTtcblxuICAgICAgcmV0dXJuIFt4ICsgbW92ZW1lbnRYLCB5ICsgbW92ZW1lbnRZXTtcbiAgICB9KTtcbiAgICB0aGlzLmF0dHIoJ3NoYXBlJywge1xuICAgICAgcG9pbnRzOiBtb3ZlQWZ0ZXJQb2ludHNcbiAgICB9KTtcbiAgfVxufTtcbmV4cG9ydHMuc21vb3RobGluZSA9IHNtb290aGxpbmU7XG52YXIgYmV6aWVyQ3VydmUgPSB7XG4gIHNoYXBlOiB7XG4gICAgcG9pbnRzOiBbXSxcbiAgICBjbG9zZTogZmFsc2VcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjc0KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjc0LnNoYXBlO1xuICAgIHZhciBwb2ludHMgPSBzaGFwZS5wb2ludHM7XG5cbiAgICBpZiAoIShwb2ludHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0JlemllckN1cnZlIHBvaW50cyBzaG91bGQgYmUgYW4gYXJyYXkhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjc1LCBfcmVmNzYpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjc1LmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmNzYuc2hhcGUsXG4gICAgICAgIGNhY2hlID0gX3JlZjc2LmNhY2hlO1xuICAgIHZhciBwb2ludHMgPSBzaGFwZS5wb2ludHMsXG4gICAgICAgIGNsb3NlID0gc2hhcGUuY2xvc2U7XG5cbiAgICBpZiAoIWNhY2hlLnBvaW50cyB8fCBjYWNoZS5wb2ludHMudG9TdHJpbmcoKSAhPT0gcG9pbnRzLnRvU3RyaW5nKCkpIHtcbiAgICAgIHZhciBob3ZlclBvaW50cyA9IGJlemllckN1cnZlVG9Qb2x5bGluZShwb2ludHMsIDIwKTtcbiAgICAgIE9iamVjdC5hc3NpZ24oY2FjaGUsIHtcbiAgICAgICAgcG9pbnRzOiAoMCwgX3V0aWwuZGVlcENsb25lKShwb2ludHMsIHRydWUpLFxuICAgICAgICBob3ZlclBvaW50czogaG92ZXJQb2ludHNcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAoMCwgX2NhbnZhcy5kcmF3QmV6aWVyQ3VydmVQYXRoKShjdHgsIHBvaW50cy5zbGljZSgxKSwgcG9pbnRzWzBdKTtcblxuICAgIGlmIChjbG9zZSkge1xuICAgICAgY3R4LmNsb3NlUGF0aCgpO1xuICAgICAgY3R4LmZpbGwoKTtcbiAgICAgIGN0eC5zdHJva2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3R4LnN0cm9rZSgpO1xuICAgIH1cbiAgfSxcbiAgaG92ZXJDaGVjazogZnVuY3Rpb24gaG92ZXJDaGVjayhwb3NpdGlvbiwgX3JlZjc3KSB7XG4gICAgdmFyIGNhY2hlID0gX3JlZjc3LmNhY2hlLFxuICAgICAgICBzaGFwZSA9IF9yZWY3Ny5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmNzcuc3R5bGU7XG4gICAgdmFyIGhvdmVyUG9pbnRzID0gY2FjaGUuaG92ZXJQb2ludHM7XG4gICAgdmFyIGNsb3NlID0gc2hhcGUuY2xvc2U7XG4gICAgdmFyIGxpbmVXaWR0aCA9IHN0eWxlLmxpbmVXaWR0aDtcblxuICAgIGlmIChjbG9zZSkge1xuICAgICAgcmV0dXJuICgwLCBfdXRpbC5jaGVja1BvaW50SXNJblBvbHlnb24pKHBvc2l0aW9uLCBob3ZlclBvaW50cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAoMCwgX3V0aWwuY2hlY2tQb2ludElzTmVhclBvbHlsaW5lKShwb3NpdGlvbiwgaG92ZXJQb2ludHMsIGxpbmVXaWR0aCk7XG4gICAgfVxuICB9LFxuICBzZXRHcmFwaENlbnRlcjogZnVuY3Rpb24gc2V0R3JhcGhDZW50ZXIoZSwgX3JlZjc4KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjc4LnNoYXBlLFxuICAgICAgICBzdHlsZSA9IF9yZWY3OC5zdHlsZTtcbiAgICB2YXIgcG9pbnRzID0gc2hhcGUucG9pbnRzO1xuICAgIHN0eWxlLmdyYXBoQ2VudGVyID0gcG9pbnRzWzBdO1xuICB9LFxuICBtb3ZlOiBmdW5jdGlvbiBtb3ZlKF9yZWY3OSwgX3JlZjgwKSB7XG4gICAgdmFyIG1vdmVtZW50WCA9IF9yZWY3OS5tb3ZlbWVudFgsXG4gICAgICAgIG1vdmVtZW50WSA9IF9yZWY3OS5tb3ZlbWVudFk7XG4gICAgdmFyIHNoYXBlID0gX3JlZjgwLnNoYXBlLFxuICAgICAgICBjYWNoZSA9IF9yZWY4MC5jYWNoZTtcbiAgICB2YXIgcG9pbnRzID0gc2hhcGUucG9pbnRzO1xuXG4gICAgdmFyIF9wb2ludHMkID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKHBvaW50c1swXSwgMiksXG4gICAgICAgIGZ4ID0gX3BvaW50cyRbMF0sXG4gICAgICAgIGZ5ID0gX3BvaW50cyRbMV07XG5cbiAgICB2YXIgY3VydmVzID0gcG9pbnRzLnNsaWNlKDEpO1xuICAgIHZhciBiZXppZXJDdXJ2ZSA9IFtbZnggKyBtb3ZlbWVudFgsIGZ5ICsgbW92ZW1lbnRZXV0uY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoY3VydmVzLm1hcChmdW5jdGlvbiAoY3VydmUpIHtcbiAgICAgIHJldHVybiBjdXJ2ZS5tYXAoZnVuY3Rpb24gKF9yZWY4MSkge1xuICAgICAgICB2YXIgX3JlZjgyID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY4MSwgMiksXG4gICAgICAgICAgICB4ID0gX3JlZjgyWzBdLFxuICAgICAgICAgICAgeSA9IF9yZWY4MlsxXTtcblxuICAgICAgICByZXR1cm4gW3ggKyBtb3ZlbWVudFgsIHkgKyBtb3ZlbWVudFldO1xuICAgICAgfSk7XG4gICAgfSkpKTtcbiAgICBjYWNoZS5wb2ludHMgPSBiZXppZXJDdXJ2ZTtcbiAgICBjYWNoZS5ob3ZlclBvaW50cyA9IGNhY2hlLmhvdmVyUG9pbnRzLm1hcChmdW5jdGlvbiAoX3JlZjgzKSB7XG4gICAgICB2YXIgX3JlZjg0ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY4MywgMiksXG4gICAgICAgICAgeCA9IF9yZWY4NFswXSxcbiAgICAgICAgICB5ID0gX3JlZjg0WzFdO1xuXG4gICAgICByZXR1cm4gW3ggKyBtb3ZlbWVudFgsIHkgKyBtb3ZlbWVudFldO1xuICAgIH0pO1xuICAgIHRoaXMuYXR0cignc2hhcGUnLCB7XG4gICAgICBwb2ludHM6IGJlemllckN1cnZlXG4gICAgfSk7XG4gIH1cbn07XG5leHBvcnRzLmJlemllckN1cnZlID0gYmV6aWVyQ3VydmU7XG52YXIgdGV4dCA9IHtcbiAgc2hhcGU6IHtcbiAgICBjb250ZW50OiAnJyxcbiAgICBwb3NpdGlvbjogW10sXG4gICAgbWF4V2lkdGg6IHVuZGVmaW5lZCxcbiAgICByb3dHYXA6IDBcbiAgfSxcbiAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IoX3JlZjg1KSB7XG4gICAgdmFyIHNoYXBlID0gX3JlZjg1LnNoYXBlO1xuICAgIHZhciBjb250ZW50ID0gc2hhcGUuY29udGVudCxcbiAgICAgICAgcG9zaXRpb24gPSBzaGFwZS5wb3NpdGlvbixcbiAgICAgICAgcm93R2FwID0gc2hhcGUucm93R2FwO1xuXG4gICAgaWYgKHR5cGVvZiBjb250ZW50ICE9PSAnc3RyaW5nJykge1xuICAgICAgY29uc29sZS5lcnJvcignVGV4dCBjb250ZW50IHNob3VsZCBiZSBhIHN0cmluZyEnKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIShwb3NpdGlvbiBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgY29uc29sZS5lcnJvcignVGV4dCBwb3NpdGlvbiBzaG91bGQgYmUgYW4gYXJyYXkhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiByb3dHYXAgIT09ICdudW1iZXInKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdUZXh0IHJvd0dhcCBzaG91bGQgYmUgYSBudW1iZXIhJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGRyYXc6IGZ1bmN0aW9uIGRyYXcoX3JlZjg2LCBfcmVmODcpIHtcbiAgICB2YXIgY3R4ID0gX3JlZjg2LmN0eDtcbiAgICB2YXIgc2hhcGUgPSBfcmVmODcuc2hhcGU7XG4gICAgdmFyIGNvbnRlbnQgPSBzaGFwZS5jb250ZW50LFxuICAgICAgICBwb3NpdGlvbiA9IHNoYXBlLnBvc2l0aW9uLFxuICAgICAgICBtYXhXaWR0aCA9IHNoYXBlLm1heFdpZHRoLFxuICAgICAgICByb3dHYXAgPSBzaGFwZS5yb3dHYXA7XG4gICAgdmFyIHRleHRCYXNlbGluZSA9IGN0eC50ZXh0QmFzZWxpbmUsXG4gICAgICAgIGZvbnQgPSBjdHguZm9udDtcbiAgICB2YXIgZm9udFNpemUgPSBwYXJzZUludChmb250LnJlcGxhY2UoL1xcRC9nLCAnJykpO1xuXG4gICAgdmFyIF9wb3NpdGlvbiA9IHBvc2l0aW9uLFxuICAgICAgICBfcG9zaXRpb24yID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9wb3NpdGlvbiwgMiksXG4gICAgICAgIHggPSBfcG9zaXRpb24yWzBdLFxuICAgICAgICB5ID0gX3Bvc2l0aW9uMlsxXTtcblxuICAgIGNvbnRlbnQgPSBjb250ZW50LnNwbGl0KCdcXG4nKTtcbiAgICB2YXIgcm93TnVtID0gY29udGVudC5sZW5ndGg7XG4gICAgdmFyIGxpbmVIZWlnaHQgPSBmb250U2l6ZSArIHJvd0dhcDtcbiAgICB2YXIgYWxsSGVpZ2h0ID0gcm93TnVtICogbGluZUhlaWdodCAtIHJvd0dhcDtcbiAgICB2YXIgb2Zmc2V0ID0gMDtcblxuICAgIGlmICh0ZXh0QmFzZWxpbmUgPT09ICdtaWRkbGUnKSB7XG4gICAgICBvZmZzZXQgPSBhbGxIZWlnaHQgLyAyO1xuICAgICAgeSArPSBmb250U2l6ZSAvIDI7XG4gICAgfVxuXG4gICAgaWYgKHRleHRCYXNlbGluZSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIG9mZnNldCA9IGFsbEhlaWdodDtcbiAgICAgIHkgKz0gZm9udFNpemU7XG4gICAgfVxuXG4gICAgcG9zaXRpb24gPSBuZXcgQXJyYXkocm93TnVtKS5maWxsKDApLm1hcChmdW5jdGlvbiAoZm9vLCBpKSB7XG4gICAgICByZXR1cm4gW3gsIHkgKyBpICogbGluZUhlaWdodCAtIG9mZnNldF07XG4gICAgfSk7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGNvbnRlbnQuZm9yRWFjaChmdW5jdGlvbiAodGV4dCwgaSkge1xuICAgICAgY3R4LmZpbGxUZXh0LmFwcGx5KGN0eCwgW3RleHRdLmNvbmNhdCgoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHBvc2l0aW9uW2ldKSwgW21heFdpZHRoXSkpO1xuICAgICAgY3R4LnN0cm9rZVRleHQuYXBwbHkoY3R4LCBbdGV4dF0uY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9zaXRpb25baV0pLCBbbWF4V2lkdGhdKSk7XG4gICAgfSk7XG4gICAgY3R4LmNsb3NlUGF0aCgpO1xuICB9LFxuICBob3ZlckNoZWNrOiBmdW5jdGlvbiBob3ZlckNoZWNrKHBvc2l0aW9uLCBfcmVmODgpIHtcbiAgICB2YXIgc2hhcGUgPSBfcmVmODguc2hhcGUsXG4gICAgICAgIHN0eWxlID0gX3JlZjg4LnN0eWxlO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcbiAgc2V0R3JhcGhDZW50ZXI6IGZ1bmN0aW9uIHNldEdyYXBoQ2VudGVyKGUsIF9yZWY4OSkge1xuICAgIHZhciBzaGFwZSA9IF9yZWY4OS5zaGFwZSxcbiAgICAgICAgc3R5bGUgPSBfcmVmODkuc3R5bGU7XG4gICAgdmFyIHBvc2l0aW9uID0gc2hhcGUucG9zaXRpb247XG4gICAgc3R5bGUuZ3JhcGhDZW50ZXIgPSAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHBvc2l0aW9uKTtcbiAgfSxcbiAgbW92ZTogZnVuY3Rpb24gbW92ZShfcmVmOTAsIF9yZWY5MSkge1xuICAgIHZhciBtb3ZlbWVudFggPSBfcmVmOTAubW92ZW1lbnRYLFxuICAgICAgICBtb3ZlbWVudFkgPSBfcmVmOTAubW92ZW1lbnRZO1xuICAgIHZhciBzaGFwZSA9IF9yZWY5MS5zaGFwZTtcblxuICAgIHZhciBfc2hhcGUkcG9zaXRpb24gPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoc2hhcGUucG9zaXRpb24sIDIpLFxuICAgICAgICB4ID0gX3NoYXBlJHBvc2l0aW9uWzBdLFxuICAgICAgICB5ID0gX3NoYXBlJHBvc2l0aW9uWzFdO1xuXG4gICAgdGhpcy5hdHRyKCdzaGFwZScsIHtcbiAgICAgIHBvc2l0aW9uOiBbeCArIG1vdmVtZW50WCwgeSArIG1vdmVtZW50WV1cbiAgICB9KTtcbiAgfVxufTtcbmV4cG9ydHMudGV4dCA9IHRleHQ7XG52YXIgZ3JhcGhzID0gbmV3IE1hcChbWydjaXJjbGUnLCBjaXJjbGVdLCBbJ2VsbGlwc2UnLCBlbGxpcHNlXSwgWydyZWN0JywgcmVjdF0sIFsncmluZycsIHJpbmddLCBbJ2FyYycsIGFyY10sIFsnc2VjdG9yJywgc2VjdG9yXSwgWydyZWdQb2x5Z29uJywgcmVnUG9seWdvbl0sIFsncG9seWxpbmUnLCBwb2x5bGluZV0sIFsnc21vb3RobGluZScsIHNtb290aGxpbmVdLCBbJ2JlemllckN1cnZlJywgYmV6aWVyQ3VydmVdLCBbJ3RleHQnLCB0ZXh0XV0pO1xudmFyIF9kZWZhdWx0ID0gZ3JhcGhzO1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBFeHRlbmQgbmV3IGdyYXBoXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lICAgTmFtZSBvZiBHcmFwaFxyXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIENvbmZpZ3VyYXRpb24gb2YgR3JhcGhcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IF9kZWZhdWx0O1xuXG5mdW5jdGlvbiBleHRlbmROZXdHcmFwaChuYW1lLCBjb25maWcpIHtcbiAgaWYgKCFuYW1lIHx8ICFjb25maWcpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFeHRlbmROZXdHcmFwaCBNaXNzaW5nIFBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFjb25maWcuc2hhcGUpIHtcbiAgICBjb25zb2xlLmVycm9yKCdSZXF1aXJlZCBhdHRyaWJ1dGUgb2Ygc2hhcGUgdG8gZXh0ZW5kTmV3R3JhcGghJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFjb25maWcudmFsaWRhdG9yKSB7XG4gICAgY29uc29sZS5lcnJvcignUmVxdWlyZWQgZnVuY3Rpb24gb2YgdmFsaWRhdG9yIHRvIGV4dGVuZE5ld0dyYXBoIScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghY29uZmlnLmRyYXcpIHtcbiAgICBjb25zb2xlLmVycm9yKCdSZXF1aXJlZCBmdW5jdGlvbiBvZiBkcmF3IHRvIGV4dGVuZE5ld0dyYXBoIScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGdyYXBocy5zZXQobmFtZSwgY29uZmlnKTtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJDUmVuZGVyXCIsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgcmV0dXJuIF9jcmVuZGVyW1wiZGVmYXVsdFwiXTtcbiAgfVxufSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJleHRlbmROZXdHcmFwaFwiLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgIHJldHVybiBfZ3JhcGhzLmV4dGVuZE5ld0dyYXBoO1xuICB9XG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gdm9pZCAwO1xuXG52YXIgX2NyZW5kZXIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCIuL2NsYXNzL2NyZW5kZXIuY2xhc3NcIikpO1xuXG52YXIgX2dyYXBocyA9IHJlcXVpcmUoXCIuL2NvbmZpZy9ncmFwaHNcIik7XG5cbnZhciBfZGVmYXVsdCA9IF9jcmVuZGVyW1wiZGVmYXVsdFwiXTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gX2RlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0ID0gcmVxdWlyZShcIkBiYWJlbC9ydW50aW1lL2hlbHBlcnMvaW50ZXJvcFJlcXVpcmVEZWZhdWx0XCIpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5kcmF3UG9seWxpbmVQYXRoID0gZHJhd1BvbHlsaW5lUGF0aDtcbmV4cG9ydHMuZHJhd0JlemllckN1cnZlUGF0aCA9IGRyYXdCZXppZXJDdXJ2ZVBhdGg7XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IHZvaWQgMDtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBEcmF3IGEgcG9seWxpbmUgcGF0aFxyXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4ICAgICAgICBDYW52YXMgMmQgY29udGV4dFxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2ludHMgICAgICBUaGUgcG9pbnRzIHRoYXQgbWFrZXMgdXAgYSBwb2x5bGluZVxyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGJlZ2luUGF0aCBXaGV0aGVyIHRvIGV4ZWN1dGUgYmVnaW5QYXRoXHJcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gY2xvc2VQYXRoIFdoZXRoZXIgdG8gZXhlY3V0ZSBjbG9zZVBhdGhcclxuICogQHJldHVybiB7VW5kZWZpbmVkfSBWb2lkXHJcbiAqL1xuZnVuY3Rpb24gZHJhd1BvbHlsaW5lUGF0aChjdHgsIHBvaW50cykge1xuICB2YXIgYmVnaW5QYXRoID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcbiAgdmFyIGNsb3NlUGF0aCA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogZmFsc2U7XG4gIGlmICghY3R4IHx8IHBvaW50cy5sZW5ndGggPCAyKSByZXR1cm4gZmFsc2U7XG4gIGlmIChiZWdpblBhdGgpIGN0eC5iZWdpblBhdGgoKTtcbiAgcG9pbnRzLmZvckVhY2goZnVuY3Rpb24gKHBvaW50LCBpKSB7XG4gICAgcmV0dXJuIHBvaW50ICYmIChpID09PSAwID8gY3R4Lm1vdmVUby5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQpKSA6IGN0eC5saW5lVG8uYXBwbHkoY3R4LCAoMCwgX3RvQ29uc3VtYWJsZUFycmF5MltcImRlZmF1bHRcIl0pKHBvaW50KSkpO1xuICB9KTtcbiAgaWYgKGNsb3NlUGF0aCkgY3R4LmNsb3NlUGF0aCgpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBEcmF3IGEgYmV6aWVyIGN1cnZlIHBhdGhcclxuICogQHBhcmFtIHtPYmplY3R9IGN0eCAgICAgICAgQ2FudmFzIDJkIGNvbnRleHRcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnRzICAgICAgVGhlIHBvaW50cyB0aGF0IG1ha2VzIHVwIGEgYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IG1vdmVUbyAgICAgIFRoZSBwb2ludCBuZWVkIHRvIGV4Y3V0ZSBtb3ZlVG9cclxuICogQHBhcmFtIHtCb29sZWFufSBiZWdpblBhdGggV2hldGhlciB0byBleGVjdXRlIGJlZ2luUGF0aFxyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGNsb3NlUGF0aCBXaGV0aGVyIHRvIGV4ZWN1dGUgY2xvc2VQYXRoXHJcbiAqIEByZXR1cm4ge1VuZGVmaW5lZH0gVm9pZFxyXG4gKi9cblxuXG5mdW5jdGlvbiBkcmF3QmV6aWVyQ3VydmVQYXRoKGN0eCwgcG9pbnRzKSB7XG4gIHZhciBtb3ZlVG8gPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlO1xuICB2YXIgYmVnaW5QYXRoID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiBmYWxzZTtcbiAgdmFyIGNsb3NlUGF0aCA9IGFyZ3VtZW50cy5sZW5ndGggPiA0ICYmIGFyZ3VtZW50c1s0XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzRdIDogZmFsc2U7XG4gIGlmICghY3R4IHx8ICFwb2ludHMpIHJldHVybiBmYWxzZTtcbiAgaWYgKGJlZ2luUGF0aCkgY3R4LmJlZ2luUGF0aCgpO1xuICBpZiAobW92ZVRvKSBjdHgubW92ZVRvLmFwcGx5KGN0eCwgKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShtb3ZlVG8pKTtcbiAgcG9pbnRzLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICByZXR1cm4gaXRlbSAmJiBjdHguYmV6aWVyQ3VydmVUby5hcHBseShjdHgsICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoaXRlbVswXSkuY29uY2F0KCgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoaXRlbVsxXSksICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkoaXRlbVsyXSkpKTtcbiAgfSk7XG4gIGlmIChjbG9zZVBhdGgpIGN0eC5jbG9zZVBhdGgoKTtcbn1cblxudmFyIF9kZWZhdWx0ID0ge1xuICBkcmF3UG9seWxpbmVQYXRoOiBkcmF3UG9seWxpbmVQYXRoLFxuICBkcmF3QmV6aWVyQ3VydmVQYXRoOiBkcmF3QmV6aWVyQ3VydmVQYXRoXG59O1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLmRlZXBDbG9uZSA9IGRlZXBDbG9uZTtcbmV4cG9ydHMuZWxpbWluYXRlQmx1ciA9IGVsaW1pbmF0ZUJsdXI7XG5leHBvcnRzLmNoZWNrUG9pbnRJc0luQ2lyY2xlID0gY2hlY2tQb2ludElzSW5DaXJjbGU7XG5leHBvcnRzLmdldFR3b1BvaW50RGlzdGFuY2UgPSBnZXRUd29Qb2ludERpc3RhbmNlO1xuZXhwb3J0cy5jaGVja1BvaW50SXNJblBvbHlnb24gPSBjaGVja1BvaW50SXNJblBvbHlnb247XG5leHBvcnRzLmNoZWNrUG9pbnRJc0luU2VjdG9yID0gY2hlY2tQb2ludElzSW5TZWN0b3I7XG5leHBvcnRzLmNoZWNrUG9pbnRJc05lYXJQb2x5bGluZSA9IGNoZWNrUG9pbnRJc05lYXJQb2x5bGluZTtcbmV4cG9ydHMuY2hlY2tQb2ludElzSW5SZWN0ID0gY2hlY2tQb2ludElzSW5SZWN0O1xuZXhwb3J0cy5nZXRSb3RhdGVQb2ludFBvcyA9IGdldFJvdGF0ZVBvaW50UG9zO1xuZXhwb3J0cy5nZXRTY2FsZVBvaW50UG9zID0gZ2V0U2NhbGVQb2ludFBvcztcbmV4cG9ydHMuZ2V0VHJhbnNsYXRlUG9pbnRQb3MgPSBnZXRUcmFuc2xhdGVQb2ludFBvcztcbmV4cG9ydHMuZ2V0RGlzdGFuY2VCZXR3ZWVuUG9pbnRBbmRMaW5lID0gZ2V0RGlzdGFuY2VCZXR3ZWVuUG9pbnRBbmRMaW5lO1xuZXhwb3J0cy5nZXRDaXJjbGVSYWRpYW5Qb2ludCA9IGdldENpcmNsZVJhZGlhblBvaW50O1xuZXhwb3J0cy5nZXRSZWd1bGFyUG9seWdvblBvaW50cyA9IGdldFJlZ3VsYXJQb2x5Z29uUG9pbnRzO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSB2b2lkIDA7XG5cbnZhciBfdG9Db25zdW1hYmxlQXJyYXkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy90b0NvbnN1bWFibGVBcnJheVwiKSk7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBhYnMgPSBNYXRoLmFicyxcbiAgICBzcXJ0ID0gTWF0aC5zcXJ0LFxuICAgIHNpbiA9IE1hdGguc2luLFxuICAgIGNvcyA9IE1hdGguY29zLFxuICAgIG1heCA9IE1hdGgubWF4LFxuICAgIG1pbiA9IE1hdGgubWluLFxuICAgIFBJID0gTWF0aC5QSTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ2xvbmUgYW4gb2JqZWN0IG9yIGFycmF5XHJcbiAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmplY3QgQ2xvbmVkIG9iamVjdFxyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHJlY3Vyc2lvbiAgIFdoZXRoZXIgdG8gdXNlIHJlY3Vyc2l2ZSBjbG9uaW5nXHJcbiAqIEByZXR1cm4ge09iamVjdHxBcnJheX0gQ2xvbmUgb2JqZWN0XHJcbiAqL1xuXG5mdW5jdGlvbiBkZWVwQ2xvbmUob2JqZWN0KSB7XG4gIHZhciByZWN1cnNpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuICBpZiAoIW9iamVjdCkgcmV0dXJuIG9iamVjdDtcbiAgdmFyIHBhcnNlID0gSlNPTi5wYXJzZSxcbiAgICAgIHN0cmluZ2lmeSA9IEpTT04uc3RyaW5naWZ5O1xuICBpZiAoIXJlY3Vyc2lvbikgcmV0dXJuIHBhcnNlKHN0cmluZ2lmeShvYmplY3QpKTtcbiAgdmFyIGNsb25lZE9iaiA9IG9iamVjdCBpbnN0YW5jZW9mIEFycmF5ID8gW10gOiB7fTtcblxuICBpZiAob2JqZWN0ICYmICgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKG9iamVjdCkgPT09ICdvYmplY3QnKSB7XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIGlmIChvYmplY3Rba2V5XSAmJiAoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShvYmplY3Rba2V5XSkgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgY2xvbmVkT2JqW2tleV0gPSBkZWVwQ2xvbmUob2JqZWN0W2tleV0sIHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNsb25lZE9ialtrZXldID0gb2JqZWN0W2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gY2xvbmVkT2JqO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBFbGltaW5hdGUgbGluZSBibHVyIGR1ZSB0byAxcHggbGluZSB3aWR0aFxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2ludHMgTGluZSBwb2ludHNcclxuICogQHJldHVybiB7QXJyYXl9IExpbmUgcG9pbnRzIGFmdGVyIHByb2Nlc3NlZFxyXG4gKi9cblxuXG5mdW5jdGlvbiBlbGltaW5hdGVCbHVyKHBvaW50cykge1xuICByZXR1cm4gcG9pbnRzLm1hcChmdW5jdGlvbiAoX3JlZikge1xuICAgIHZhciBfcmVmMiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmLCAyKSxcbiAgICAgICAgeCA9IF9yZWYyWzBdLFxuICAgICAgICB5ID0gX3JlZjJbMV07XG5cbiAgICByZXR1cm4gW3BhcnNlSW50KHgpICsgMC41LCBwYXJzZUludCh5KSArIDAuNV07XG4gIH0pO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBDaGVjayBpZiB0aGUgcG9pbnQgaXMgaW5zaWRlIHRoZSBjaXJjbGVcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgUG9zdGlvbiBvZiBwb2ludFxyXG4gKiBAcGFyYW0ge051bWJlcn0gcnggICBDaXJjbGUgeCBjb29yZGluYXRlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSByeSAgIENpcmNsZSB5IGNvb3JkaW5hdGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHIgICAgQ2lyY2xlIHJhZGl1c1xyXG4gKiBAcmV0dXJuIHtCb29sZWFufSBSZXN1bHQgb2YgY2hlY2tcclxuICovXG5cblxuZnVuY3Rpb24gY2hlY2tQb2ludElzSW5DaXJjbGUocG9pbnQsIHJ4LCByeSwgcikge1xuICByZXR1cm4gZ2V0VHdvUG9pbnREaXN0YW5jZShwb2ludCwgW3J4LCByeV0pIDw9IHI7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gcG9pbnRzXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvaW50MSBwb2ludDFcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQyIHBvaW50MlxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IERpc3RhbmNlIGJldHdlZW4gdHdvIHBvaW50c1xyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRUd29Qb2ludERpc3RhbmNlKF9yZWYzLCBfcmVmNCkge1xuICB2YXIgX3JlZjUgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjMsIDIpLFxuICAgICAgeGEgPSBfcmVmNVswXSxcbiAgICAgIHlhID0gX3JlZjVbMV07XG5cbiAgdmFyIF9yZWY2ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWY0LCAyKSxcbiAgICAgIHhiID0gX3JlZjZbMF0sXG4gICAgICB5YiA9IF9yZWY2WzFdO1xuXG4gIHZhciBtaW51c1ggPSBhYnMoeGEgLSB4Yik7XG4gIHZhciBtaW51c1kgPSBhYnMoeWEgLSB5Yik7XG4gIHJldHVybiBzcXJ0KG1pbnVzWCAqIG1pbnVzWCArIG1pbnVzWSAqIG1pbnVzWSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIENoZWNrIGlmIHRoZSBwb2ludCBpcyBpbnNpZGUgdGhlIHBvbHlnb25cclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgIFBvc3Rpb24gb2YgcG9pbnRcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnRzIFRoZSBwb2ludHMgdGhhdCBtYWtlcyB1cCBhIHBvbHlsaW5lXHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJlc3VsdCBvZiBjaGVja1xyXG4gKi9cblxuXG5mdW5jdGlvbiBjaGVja1BvaW50SXNJblBvbHlnb24ocG9pbnQsIHBvbHlnb24pIHtcbiAgdmFyIGNvdW50ZXIgPSAwO1xuXG4gIHZhciBfcG9pbnQgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQsIDIpLFxuICAgICAgeCA9IF9wb2ludFswXSxcbiAgICAgIHkgPSBfcG9pbnRbMV07XG5cbiAgdmFyIHBvaW50TnVtID0gcG9seWdvbi5sZW5ndGg7XG5cbiAgZm9yICh2YXIgaSA9IDEsIHAxID0gcG9seWdvblswXTsgaSA8PSBwb2ludE51bTsgaSsrKSB7XG4gICAgdmFyIHAyID0gcG9seWdvbltpICUgcG9pbnROdW1dO1xuXG4gICAgaWYgKHggPiBtaW4ocDFbMF0sIHAyWzBdKSAmJiB4IDw9IG1heChwMVswXSwgcDJbMF0pKSB7XG4gICAgICBpZiAoeSA8PSBtYXgocDFbMV0sIHAyWzFdKSkge1xuICAgICAgICBpZiAocDFbMF0gIT09IHAyWzBdKSB7XG4gICAgICAgICAgdmFyIHhpbnRlcnMgPSAoeCAtIHAxWzBdKSAqIChwMlsxXSAtIHAxWzFdKSAvIChwMlswXSAtIHAxWzBdKSArIHAxWzFdO1xuXG4gICAgICAgICAgaWYgKHAxWzFdID09PSBwMlsxXSB8fCB5IDw9IHhpbnRlcnMpIHtcbiAgICAgICAgICAgIGNvdW50ZXIrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBwMSA9IHAyO1xuICB9XG5cbiAgcmV0dXJuIGNvdW50ZXIgJSAyID09PSAxO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBDaGVjayBpZiB0aGUgcG9pbnQgaXMgaW5zaWRlIHRoZSBzZWN0b3JcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgICAgICAgUG9zdGlvbiBvZiBwb2ludFxyXG4gKiBAcGFyYW0ge051bWJlcn0gcnggICAgICAgICBTZWN0b3IgeCBjb29yZGluYXRlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSByeSAgICAgICAgIFNlY3RvciB5IGNvb3JkaW5hdGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHIgICAgICAgICAgU2VjdG9yIHJhZGl1c1xyXG4gKiBAcGFyYW0ge051bWJlcn0gc3RhcnRBbmdsZSBTZWN0b3Igc3RhcnQgYW5nbGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IGVuZEFuZ2xlICAgU2VjdG9yIGVuZCBhbmdsZVxyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGNsb2NrV2lzZSBXaGV0aGVyIHRoZSBzZWN0b3IgYW5nbGUgaXMgY2xvY2t3aXNlXHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJlc3VsdCBvZiBjaGVja1xyXG4gKi9cblxuXG5mdW5jdGlvbiBjaGVja1BvaW50SXNJblNlY3Rvcihwb2ludCwgcngsIHJ5LCByLCBzdGFydEFuZ2xlLCBlbmRBbmdsZSwgY2xvY2tXaXNlKSB7XG4gIGlmICghcG9pbnQpIHJldHVybiBmYWxzZTtcbiAgaWYgKGdldFR3b1BvaW50RGlzdGFuY2UocG9pbnQsIFtyeCwgcnldKSA+IHIpIHJldHVybiBmYWxzZTtcblxuICBpZiAoIWNsb2NrV2lzZSkge1xuICAgIHZhciBfZGVlcENsb25lID0gZGVlcENsb25lKFtlbmRBbmdsZSwgc3RhcnRBbmdsZV0pO1xuXG4gICAgdmFyIF9kZWVwQ2xvbmUyID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9kZWVwQ2xvbmUsIDIpO1xuXG4gICAgc3RhcnRBbmdsZSA9IF9kZWVwQ2xvbmUyWzBdO1xuICAgIGVuZEFuZ2xlID0gX2RlZXBDbG9uZTJbMV07XG4gIH1cblxuICB2YXIgcmV2ZXJzZUJFID0gc3RhcnRBbmdsZSA+IGVuZEFuZ2xlO1xuXG4gIGlmIChyZXZlcnNlQkUpIHtcbiAgICB2YXIgX3JlZjcgPSBbZW5kQW5nbGUsIHN0YXJ0QW5nbGVdO1xuICAgIHN0YXJ0QW5nbGUgPSBfcmVmN1swXTtcbiAgICBlbmRBbmdsZSA9IF9yZWY3WzFdO1xuICB9XG5cbiAgdmFyIG1pbnVzID0gZW5kQW5nbGUgLSBzdGFydEFuZ2xlO1xuICBpZiAobWludXMgPj0gUEkgKiAyKSByZXR1cm4gdHJ1ZTtcblxuICB2YXIgX3BvaW50MiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShwb2ludCwgMiksXG4gICAgICB4ID0gX3BvaW50MlswXSxcbiAgICAgIHkgPSBfcG9pbnQyWzFdO1xuXG4gIHZhciBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQgPSBnZXRDaXJjbGVSYWRpYW5Qb2ludChyeCwgcnksIHIsIHN0YXJ0QW5nbGUpLFxuICAgICAgX2dldENpcmNsZVJhZGlhblBvaW50MiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQsIDIpLFxuICAgICAgYnggPSBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQyWzBdLFxuICAgICAgYnkgPSBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQyWzFdO1xuXG4gIHZhciBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQzID0gZ2V0Q2lyY2xlUmFkaWFuUG9pbnQocngsIHJ5LCByLCBlbmRBbmdsZSksXG4gICAgICBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQ0ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9nZXRDaXJjbGVSYWRpYW5Qb2ludDMsIDIpLFxuICAgICAgZXggPSBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQ0WzBdLFxuICAgICAgZXkgPSBfZ2V0Q2lyY2xlUmFkaWFuUG9pbnQ0WzFdO1xuXG4gIHZhciB2UG9pbnQgPSBbeCAtIHJ4LCB5IC0gcnldO1xuICB2YXIgdkJBcm0gPSBbYnggLSByeCwgYnkgLSByeV07XG4gIHZhciB2RUFybSA9IFtleCAtIHJ4LCBleSAtIHJ5XTtcbiAgdmFyIHJldmVyc2UgPSBtaW51cyA+IFBJO1xuXG4gIGlmIChyZXZlcnNlKSB7XG4gICAgdmFyIF9kZWVwQ2xvbmUzID0gZGVlcENsb25lKFt2RUFybSwgdkJBcm1dKTtcblxuICAgIHZhciBfZGVlcENsb25lNCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfZGVlcENsb25lMywgMik7XG5cbiAgICB2QkFybSA9IF9kZWVwQ2xvbmU0WzBdO1xuICAgIHZFQXJtID0gX2RlZXBDbG9uZTRbMV07XG4gIH1cblxuICB2YXIgaW5TZWN0b3IgPSBpc0Nsb2NrV2lzZSh2QkFybSwgdlBvaW50KSAmJiAhaXNDbG9ja1dpc2UodkVBcm0sIHZQb2ludCk7XG4gIGlmIChyZXZlcnNlKSBpblNlY3RvciA9ICFpblNlY3RvcjtcbiAgaWYgKHJldmVyc2VCRSkgaW5TZWN0b3IgPSAhaW5TZWN0b3I7XG4gIHJldHVybiBpblNlY3Rvcjtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gRGV0ZXJtaW5lIGlmIHRoZSBwb2ludCBpcyBpbiB0aGUgY2xvY2t3aXNlIGRpcmVjdGlvbiBvZiB0aGUgdmVjdG9yXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHZBcm0gICBWZWN0b3JcclxuICogQHBhcmFtIHtBcnJheX0gdlBvaW50IFBvaW50XHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IFJlc3VsdCBvZiBjaGVja1xyXG4gKi9cblxuXG5mdW5jdGlvbiBpc0Nsb2NrV2lzZSh2QXJtLCB2UG9pbnQpIHtcbiAgdmFyIF92QXJtID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKHZBcm0sIDIpLFxuICAgICAgYXggPSBfdkFybVswXSxcbiAgICAgIGF5ID0gX3ZBcm1bMV07XG5cbiAgdmFyIF92UG9pbnQgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkodlBvaW50LCAyKSxcbiAgICAgIHB4ID0gX3ZQb2ludFswXSxcbiAgICAgIHB5ID0gX3ZQb2ludFsxXTtcblxuICByZXR1cm4gLWF5ICogcHggKyBheCAqIHB5ID4gMDtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ2hlY2sgaWYgdGhlIHBvaW50IGlzIGluc2lkZSB0aGUgcG9seWxpbmVcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgICAgICBQb3N0aW9uIG9mIHBvaW50XHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvbHlsaW5lICAgVGhlIHBvaW50cyB0aGF0IG1ha2VzIHVwIGEgcG9seWxpbmVcclxuICogQHBhcmFtIHtOdW1iZXJ9IGxpbmVXaWR0aCBQb2x5bGluZSBsaW5ld2lkdGhcclxuICogQHJldHVybiB7Qm9vbGVhbn0gUmVzdWx0IG9mIGNoZWNrXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGNoZWNrUG9pbnRJc05lYXJQb2x5bGluZShwb2ludCwgcG9seWxpbmUsIGxpbmVXaWR0aCkge1xuICB2YXIgaGFsZkxpbmVXaWR0aCA9IGxpbmVXaWR0aCAvIDI7XG4gIHZhciBtb3ZlVXBQb2x5bGluZSA9IHBvbHlsaW5lLm1hcChmdW5jdGlvbiAoX3JlZjgpIHtcbiAgICB2YXIgX3JlZjkgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjgsIDIpLFxuICAgICAgICB4ID0gX3JlZjlbMF0sXG4gICAgICAgIHkgPSBfcmVmOVsxXTtcblxuICAgIHJldHVybiBbeCwgeSAtIGhhbGZMaW5lV2lkdGhdO1xuICB9KTtcbiAgdmFyIG1vdmVEb3duUG9seWxpbmUgPSBwb2x5bGluZS5tYXAoZnVuY3Rpb24gKF9yZWYxMCkge1xuICAgIHZhciBfcmVmMTEgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjEwLCAyKSxcbiAgICAgICAgeCA9IF9yZWYxMVswXSxcbiAgICAgICAgeSA9IF9yZWYxMVsxXTtcblxuICAgIHJldHVybiBbeCwgeSArIGhhbGZMaW5lV2lkdGhdO1xuICB9KTtcbiAgdmFyIHBvbHlnb24gPSBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShtb3ZlVXBQb2x5bGluZSksICgwLCBfdG9Db25zdW1hYmxlQXJyYXkyW1wiZGVmYXVsdFwiXSkobW92ZURvd25Qb2x5bGluZS5yZXZlcnNlKCkpKTtcbiAgcmV0dXJuIGNoZWNrUG9pbnRJc0luUG9seWdvbihwb2ludCwgcG9seWdvbik7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIENoZWNrIGlmIHRoZSBwb2ludCBpcyBpbnNpZGUgdGhlIHJlY3RcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgICBQb3N0aW9uIG9mIHBvaW50XHJcbiAqIEBwYXJhbSB7TnVtYmVyfSB4ICAgICAgUmVjdCBzdGFydCB4IGNvb3JkaW5hdGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHkgICAgICBSZWN0IHN0YXJ0IHkgY29vcmRpbmF0ZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gd2lkdGggIFJlY3Qgd2lkdGhcclxuICogQHBhcmFtIHtOdW1iZXJ9IGhlaWdodCBSZWN0IGhlaWdodFxyXG4gKiBAcmV0dXJuIHtCb29sZWFufSBSZXN1bHQgb2YgY2hlY2tcclxuICovXG5cblxuZnVuY3Rpb24gY2hlY2tQb2ludElzSW5SZWN0KF9yZWYxMiwgeCwgeSwgd2lkdGgsIGhlaWdodCkge1xuICB2YXIgX3JlZjEzID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYxMiwgMiksXG4gICAgICBweCA9IF9yZWYxM1swXSxcbiAgICAgIHB5ID0gX3JlZjEzWzFdO1xuXG4gIGlmIChweCA8IHgpIHJldHVybiBmYWxzZTtcbiAgaWYgKHB5IDwgeSkgcmV0dXJuIGZhbHNlO1xuICBpZiAocHggPiB4ICsgd2lkdGgpIHJldHVybiBmYWxzZTtcbiAgaWYgKHB5ID4geSArIGhlaWdodCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgcm90YXRlZCBwb2ludFxyXG4gKiBAcGFyYW0ge051bWJlcn0gcm90YXRlIERlZ3JlZSBvZiByb3RhdGlvblxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2ludCAgIFBvc3Rpb24gb2YgcG9pbnRcclxuICogQHBhcmFtIHtBcnJheX0gb3JpZ2luICBSb3RhdGlvbiBjZW50ZXJcclxuICogQHBhcmFtIHtBcnJheX0gb3JpZ2luICBSb3RhdGlvbiBjZW50ZXJcclxuICogQHJldHVybiB7TnVtYmVyfSBDb29yZGluYXRlcyBhZnRlciByb3RhdGlvblxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRSb3RhdGVQb2ludFBvcygpIHtcbiAgdmFyIHJvdGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogMDtcbiAgdmFyIHBvaW50ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQ7XG4gIHZhciBvcmlnaW4gPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IFswLCAwXTtcbiAgaWYgKCFwb2ludCkgcmV0dXJuIGZhbHNlO1xuICBpZiAocm90YXRlICUgMzYwID09PSAwKSByZXR1cm4gcG9pbnQ7XG5cbiAgdmFyIF9wb2ludDMgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQsIDIpLFxuICAgICAgeCA9IF9wb2ludDNbMF0sXG4gICAgICB5ID0gX3BvaW50M1sxXTtcblxuICB2YXIgX29yaWdpbiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShvcmlnaW4sIDIpLFxuICAgICAgb3ggPSBfb3JpZ2luWzBdLFxuICAgICAgb3kgPSBfb3JpZ2luWzFdO1xuXG4gIHJvdGF0ZSAqPSBQSSAvIDE4MDtcbiAgcmV0dXJuIFsoeCAtIG94KSAqIGNvcyhyb3RhdGUpIC0gKHkgLSBveSkgKiBzaW4ocm90YXRlKSArIG94LCAoeCAtIG94KSAqIHNpbihyb3RhdGUpICsgKHkgLSBveSkgKiBjb3Mocm90YXRlKSArIG95XTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgc2NhbGVkIHBvaW50XHJcbiAqIEBwYXJhbSB7QXJyYXl9IHNjYWxlICBTY2FsZSBmYWN0b3JcclxuICogQHBhcmFtIHtBcnJheX0gcG9pbnQgIFBvc3Rpb24gb2YgcG9pbnRcclxuICogQHBhcmFtIHtBcnJheX0gb3JpZ2luIFNjYWxlIGNlbnRlclxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IENvb3JkaW5hdGVzIGFmdGVyIHNjYWxlXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldFNjYWxlUG9pbnRQb3MoKSB7XG4gIHZhciBzY2FsZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogWzEsIDFdO1xuICB2YXIgcG9pbnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDtcbiAgdmFyIG9yaWdpbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogWzAsIDBdO1xuICBpZiAoIXBvaW50KSByZXR1cm4gZmFsc2U7XG4gIGlmIChzY2FsZSA9PT0gMSkgcmV0dXJuIHBvaW50O1xuXG4gIHZhciBfcG9pbnQ0ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKHBvaW50LCAyKSxcbiAgICAgIHggPSBfcG9pbnQ0WzBdLFxuICAgICAgeSA9IF9wb2ludDRbMV07XG5cbiAgdmFyIF9vcmlnaW4yID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKG9yaWdpbiwgMiksXG4gICAgICBveCA9IF9vcmlnaW4yWzBdLFxuICAgICAgb3kgPSBfb3JpZ2luMlsxXTtcblxuICB2YXIgX3NjYWxlID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKHNjYWxlLCAyKSxcbiAgICAgIHhzID0gX3NjYWxlWzBdLFxuICAgICAgeXMgPSBfc2NhbGVbMV07XG5cbiAgdmFyIHJlbGF0aXZlUG9zWCA9IHggLSBveDtcbiAgdmFyIHJlbGF0aXZlUG9zWSA9IHkgLSBveTtcbiAgcmV0dXJuIFtyZWxhdGl2ZVBvc1ggKiB4cyArIG94LCByZWxhdGl2ZVBvc1kgKiB5cyArIG95XTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgc2NhbGVkIHBvaW50XHJcbiAqIEBwYXJhbSB7QXJyYXl9IHRyYW5zbGF0ZSBUcmFuc2xhdGlvbiBkaXN0YW5jZVxyXG4gKiBAcGFyYW0ge0FycmF5fSBwb2ludCAgICAgUG9zdGlvbiBvZiBwb2ludFxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IENvb3JkaW5hdGVzIGFmdGVyIHRyYW5zbGF0aW9uXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldFRyYW5zbGF0ZVBvaW50UG9zKHRyYW5zbGF0ZSwgcG9pbnQpIHtcbiAgaWYgKCF0cmFuc2xhdGUgfHwgIXBvaW50KSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIF9wb2ludDUgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQsIDIpLFxuICAgICAgeCA9IF9wb2ludDVbMF0sXG4gICAgICB5ID0gX3BvaW50NVsxXTtcblxuICB2YXIgX3RyYW5zbGF0ZSA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKSh0cmFuc2xhdGUsIDIpLFxuICAgICAgdHggPSBfdHJhbnNsYXRlWzBdLFxuICAgICAgdHkgPSBfdHJhbnNsYXRlWzFdO1xuXG4gIHJldHVybiBbeCArIHR4LCB5ICsgdHldO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGRpc3RhbmNlIGZyb20gdGhlIHBvaW50IHRvIHRoZSBsaW5lXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHBvaW50ICAgICBQb3N0aW9uIG9mIHBvaW50XHJcbiAqIEBwYXJhbSB7QXJyYXl9IGxpbmVCZWdpbiBMaW5lIHN0YXJ0IHBvc2l0aW9uXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGxpbmVFbmQgICBMaW5lIGVuZCBwb3NpdGlvblxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IERpc3RhbmNlIGJldHdlZW4gcG9pbnQgYW5kIGxpbmVcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0RGlzdGFuY2VCZXR3ZWVuUG9pbnRBbmRMaW5lKHBvaW50LCBsaW5lQmVnaW4sIGxpbmVFbmQpIHtcbiAgaWYgKCFwb2ludCB8fCAhbGluZUJlZ2luIHx8ICFsaW5lRW5kKSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIF9wb2ludDYgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkocG9pbnQsIDIpLFxuICAgICAgeCA9IF9wb2ludDZbMF0sXG4gICAgICB5ID0gX3BvaW50NlsxXTtcblxuICB2YXIgX2xpbmVCZWdpbiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShsaW5lQmVnaW4sIDIpLFxuICAgICAgeDEgPSBfbGluZUJlZ2luWzBdLFxuICAgICAgeTEgPSBfbGluZUJlZ2luWzFdO1xuXG4gIHZhciBfbGluZUVuZCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShsaW5lRW5kLCAyKSxcbiAgICAgIHgyID0gX2xpbmVFbmRbMF0sXG4gICAgICB5MiA9IF9saW5lRW5kWzFdO1xuXG4gIHZhciBhID0geTIgLSB5MTtcbiAgdmFyIGIgPSB4MSAtIHgyO1xuICB2YXIgYyA9IHkxICogKHgyIC0geDEpIC0geDEgKiAoeTIgLSB5MSk7XG4gIHZhciBtb2xlY3VsZSA9IGFicyhhICogeCArIGIgKiB5ICsgYyk7XG4gIHZhciBkZW5vbWluYXRvciA9IHNxcnQoYSAqIGEgKyBiICogYik7XG4gIHJldHVybiBtb2xlY3VsZSAvIGRlbm9taW5hdG9yO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBzcGVjaWZpZWQgcmFkaWFuIG9uIHRoZSBjaXJjbGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHggICAgICBDaXJjbGUgeCBjb29yZGluYXRlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSB5ICAgICAgQ2lyY2xlIHkgY29vcmRpbmF0ZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkaXVzIENpcmNsZSByYWRpdXNcclxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZGlhbiBTcGVjZmllZCByYWRpYW5cclxuICogQHJldHVybiB7QXJyYXl9IFBvc3Rpb24gb2YgcG9pbnRcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0Q2lyY2xlUmFkaWFuUG9pbnQoeCwgeSwgcmFkaXVzLCByYWRpYW4pIHtcbiAgcmV0dXJuIFt4ICsgY29zKHJhZGlhbikgKiByYWRpdXMsIHkgKyBzaW4ocmFkaWFuKSAqIHJhZGl1c107XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgcG9pbnRzIHRoYXQgbWFrZSB1cCBhIHJlZ3VsYXIgcG9seWdvblxyXG4gKiBAcGFyYW0ge051bWJlcn0geCAgICAgWCBjb29yZGluYXRlIG9mIHRoZSBwb2x5Z29uIGluc2NyaWJlZCBjaXJjbGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHkgICAgIFkgY29vcmRpbmF0ZSBvZiB0aGUgcG9seWdvbiBpbnNjcmliZWQgY2lyY2xlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSByICAgICBSYWRpdXMgb2YgdGhlIHBvbHlnb24gaW5zY3JpYmVkIGNpcmNsZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gc2lkZSAgU2lkZSBudW1iZXJcclxuICogQHBhcmFtIHtOdW1iZXJ9IG1pbnVzIFJhZGlhbiBvZmZzZXRcclxuICogQHJldHVybiB7QXJyYXl9IFBvaW50cyB0aGF0IG1ha2UgdXAgYSByZWd1bGFyIHBvbHlnb25cclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmVndWxhclBvbHlnb25Qb2ludHMocngsIHJ5LCByLCBzaWRlKSB7XG4gIHZhciBtaW51cyA9IGFyZ3VtZW50cy5sZW5ndGggPiA0ICYmIGFyZ3VtZW50c1s0XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzRdIDogUEkgKiAtMC41O1xuICB2YXIgcmFkaWFuR2FwID0gUEkgKiAyIC8gc2lkZTtcbiAgdmFyIHJhZGlhbnMgPSBuZXcgQXJyYXkoc2lkZSkuZmlsbCgnJykubWFwKGZ1bmN0aW9uICh0LCBpKSB7XG4gICAgcmV0dXJuIGkgKiByYWRpYW5HYXAgKyBtaW51cztcbiAgfSk7XG4gIHJldHVybiByYWRpYW5zLm1hcChmdW5jdGlvbiAocmFkaWFuKSB7XG4gICAgcmV0dXJuIGdldENpcmNsZVJhZGlhblBvaW50KHJ4LCByeSwgciwgcmFkaWFuKTtcbiAgfSk7XG59XG5cbnZhciBfZGVmYXVsdCA9IHtcbiAgZGVlcENsb25lOiBkZWVwQ2xvbmUsXG4gIGVsaW1pbmF0ZUJsdXI6IGVsaW1pbmF0ZUJsdXIsXG4gIGNoZWNrUG9pbnRJc0luQ2lyY2xlOiBjaGVja1BvaW50SXNJbkNpcmNsZSxcbiAgY2hlY2tQb2ludElzSW5Qb2x5Z29uOiBjaGVja1BvaW50SXNJblBvbHlnb24sXG4gIGNoZWNrUG9pbnRJc0luU2VjdG9yOiBjaGVja1BvaW50SXNJblNlY3RvcixcbiAgY2hlY2tQb2ludElzTmVhclBvbHlsaW5lOiBjaGVja1BvaW50SXNOZWFyUG9seWxpbmUsXG4gIGdldFR3b1BvaW50RGlzdGFuY2U6IGdldFR3b1BvaW50RGlzdGFuY2UsXG4gIGdldFJvdGF0ZVBvaW50UG9zOiBnZXRSb3RhdGVQb2ludFBvcyxcbiAgZ2V0U2NhbGVQb2ludFBvczogZ2V0U2NhbGVQb2ludFBvcyxcbiAgZ2V0VHJhbnNsYXRlUG9pbnRQb3M6IGdldFRyYW5zbGF0ZVBvaW50UG9zLFxuICBnZXRDaXJjbGVSYWRpYW5Qb2ludDogZ2V0Q2lyY2xlUmFkaWFuUG9pbnQsXG4gIGdldFJlZ3VsYXJQb2x5Z29uUG9pbnRzOiBnZXRSZWd1bGFyUG9seWdvblBvaW50cyxcbiAgZ2V0RGlzdGFuY2VCZXR3ZWVuUG9pbnRBbmRMaW5lOiBnZXREaXN0YW5jZUJldHdlZW5Qb2ludEFuZExpbmVcbn07XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSB2b2lkIDA7XG5cbnZhciBfZGVmYXVsdCA9IG5ldyBNYXAoW1sndHJhbnNwYXJlbnQnLCAncmdiYSgwLDAsMCwwKSddLCBbJ2JsYWNrJywgJyMwMDAwMDAnXSwgWydzaWx2ZXInLCAnI0MwQzBDMCddLCBbJ2dyYXknLCAnIzgwODA4MCddLCBbJ3doaXRlJywgJyNGRkZGRkYnXSwgWydtYXJvb24nLCAnIzgwMDAwMCddLCBbJ3JlZCcsICcjRkYwMDAwJ10sIFsncHVycGxlJywgJyM4MDAwODAnXSwgWydmdWNoc2lhJywgJyNGRjAwRkYnXSwgWydncmVlbicsICcjMDA4MDAwJ10sIFsnbGltZScsICcjMDBGRjAwJ10sIFsnb2xpdmUnLCAnIzgwODAwMCddLCBbJ3llbGxvdycsICcjRkZGRjAwJ10sIFsnbmF2eScsICcjMDAwMDgwJ10sIFsnYmx1ZScsICcjMDAwMEZGJ10sIFsndGVhbCcsICcjMDA4MDgwJ10sIFsnYXF1YScsICcjMDBGRkZGJ10sIFsnYWxpY2VibHVlJywgJyNmMGY4ZmYnXSwgWydhbnRpcXVld2hpdGUnLCAnI2ZhZWJkNyddLCBbJ2FxdWFtYXJpbmUnLCAnIzdmZmZkNCddLCBbJ2F6dXJlJywgJyNmMGZmZmYnXSwgWydiZWlnZScsICcjZjVmNWRjJ10sIFsnYmlzcXVlJywgJyNmZmU0YzQnXSwgWydibGFuY2hlZGFsbW9uZCcsICcjZmZlYmNkJ10sIFsnYmx1ZXZpb2xldCcsICcjOGEyYmUyJ10sIFsnYnJvd24nLCAnI2E1MmEyYSddLCBbJ2J1cmx5d29vZCcsICcjZGViODg3J10sIFsnY2FkZXRibHVlJywgJyM1ZjllYTAnXSwgWydjaGFydHJldXNlJywgJyM3ZmZmMDAnXSwgWydjaG9jb2xhdGUnLCAnI2QyNjkxZSddLCBbJ2NvcmFsJywgJyNmZjdmNTAnXSwgWydjb3JuZmxvd2VyYmx1ZScsICcjNjQ5NWVkJ10sIFsnY29ybnNpbGsnLCAnI2ZmZjhkYyddLCBbJ2NyaW1zb24nLCAnI2RjMTQzYyddLCBbJ2N5YW4nLCAnIzAwZmZmZiddLCBbJ2RhcmtibHVlJywgJyMwMDAwOGInXSwgWydkYXJrY3lhbicsICcjMDA4YjhiJ10sIFsnZGFya2dvbGRlbnJvZCcsICcjYjg4NjBiJ10sIFsnZGFya2dyYXknLCAnI2E5YTlhOSddLCBbJ2RhcmtncmVlbicsICcjMDA2NDAwJ10sIFsnZGFya2dyZXknLCAnI2E5YTlhOSddLCBbJ2RhcmtraGFraScsICcjYmRiNzZiJ10sIFsnZGFya21hZ2VudGEnLCAnIzhiMDA4YiddLCBbJ2RhcmtvbGl2ZWdyZWVuJywgJyM1NTZiMmYnXSwgWydkYXJrb3JhbmdlJywgJyNmZjhjMDAnXSwgWydkYXJrb3JjaGlkJywgJyM5OTMyY2MnXSwgWydkYXJrcmVkJywgJyM4YjAwMDAnXSwgWydkYXJrc2FsbW9uJywgJyNlOTk2N2EnXSwgWydkYXJrc2VhZ3JlZW4nLCAnIzhmYmM4ZiddLCBbJ2RhcmtzbGF0ZWJsdWUnLCAnIzQ4M2Q4YiddLCBbJ2RhcmtzbGF0ZWdyYXknLCAnIzJmNGY0ZiddLCBbJ2RhcmtzbGF0ZWdyZXknLCAnIzJmNGY0ZiddLCBbJ2Rhcmt0dXJxdW9pc2UnLCAnIzAwY2VkMSddLCBbJ2Rhcmt2aW9sZXQnLCAnIzk0MDBkMyddLCBbJ2RlZXBwaW5rJywgJyNmZjE0OTMnXSwgWydkZWVwc2t5Ymx1ZScsICcjMDBiZmZmJ10sIFsnZGltZ3JheScsICcjNjk2OTY5J10sIFsnZGltZ3JleScsICcjNjk2OTY5J10sIFsnZG9kZ2VyYmx1ZScsICcjMWU5MGZmJ10sIFsnZmlyZWJyaWNrJywgJyNiMjIyMjInXSwgWydmbG9yYWx3aGl0ZScsICcjZmZmYWYwJ10sIFsnZm9yZXN0Z3JlZW4nLCAnIzIyOGIyMiddLCBbJ2dhaW5zYm9ybycsICcjZGNkY2RjJ10sIFsnZ2hvc3R3aGl0ZScsICcjZjhmOGZmJ10sIFsnZ29sZCcsICcjZmZkNzAwJ10sIFsnZ29sZGVucm9kJywgJyNkYWE1MjAnXSwgWydncmVlbnllbGxvdycsICcjYWRmZjJmJ10sIFsnZ3JleScsICcjODA4MDgwJ10sIFsnaG9uZXlkZXcnLCAnI2YwZmZmMCddLCBbJ2hvdHBpbmsnLCAnI2ZmNjliNCddLCBbJ2luZGlhbnJlZCcsICcjY2Q1YzVjJ10sIFsnaW5kaWdvJywgJyM0YjAwODInXSwgWydpdm9yeScsICcjZmZmZmYwJ10sIFsna2hha2knLCAnI2YwZTY4YyddLCBbJ2xhdmVuZGVyJywgJyNlNmU2ZmEnXSwgWydsYXZlbmRlcmJsdXNoJywgJyNmZmYwZjUnXSwgWydsYXduZ3JlZW4nLCAnIzdjZmMwMCddLCBbJ2xlbW9uY2hpZmZvbicsICcjZmZmYWNkJ10sIFsnbGlnaHRibHVlJywgJyNhZGQ4ZTYnXSwgWydsaWdodGNvcmFsJywgJyNmMDgwODAnXSwgWydsaWdodGN5YW4nLCAnI2UwZmZmZiddLCBbJ2xpZ2h0Z29sZGVucm9keWVsbG93JywgJyNmYWZhZDInXSwgWydsaWdodGdyYXknLCAnI2QzZDNkMyddLCBbJ2xpZ2h0Z3JlZW4nLCAnIzkwZWU5MCddLCBbJ2xpZ2h0Z3JleScsICcjZDNkM2QzJ10sIFsnbGlnaHRwaW5rJywgJyNmZmI2YzEnXSwgWydsaWdodHNhbG1vbicsICcjZmZhMDdhJ10sIFsnbGlnaHRzZWFncmVlbicsICcjMjBiMmFhJ10sIFsnbGlnaHRza3libHVlJywgJyM4N2NlZmEnXSwgWydsaWdodHNsYXRlZ3JheScsICcjNzc4ODk5J10sIFsnbGlnaHRzbGF0ZWdyZXknLCAnIzc3ODg5OSddLCBbJ2xpZ2h0c3RlZWxibHVlJywgJyNiMGM0ZGUnXSwgWydsaWdodHllbGxvdycsICcjZmZmZmUwJ10sIFsnbGltZWdyZWVuJywgJyMzMmNkMzInXSwgWydsaW5lbicsICcjZmFmMGU2J10sIFsnbWFnZW50YScsICcjZmYwMGZmJ10sIFsnbWVkaXVtYXF1YW1hcmluZScsICcjNjZjZGFhJ10sIFsnbWVkaXVtYmx1ZScsICcjMDAwMGNkJ10sIFsnbWVkaXVtb3JjaGlkJywgJyNiYTU1ZDMnXSwgWydtZWRpdW1wdXJwbGUnLCAnIzkzNzBkYiddLCBbJ21lZGl1bXNlYWdyZWVuJywgJyMzY2IzNzEnXSwgWydtZWRpdW1zbGF0ZWJsdWUnLCAnIzdiNjhlZSddLCBbJ21lZGl1bXNwcmluZ2dyZWVuJywgJyMwMGZhOWEnXSwgWydtZWRpdW10dXJxdW9pc2UnLCAnIzQ4ZDFjYyddLCBbJ21lZGl1bXZpb2xldHJlZCcsICcjYzcxNTg1J10sIFsnbWlkbmlnaHRibHVlJywgJyMxOTE5NzAnXSwgWydtaW50Y3JlYW0nLCAnI2Y1ZmZmYSddLCBbJ21pc3R5cm9zZScsICcjZmZlNGUxJ10sIFsnbW9jY2FzaW4nLCAnI2ZmZTRiNSddLCBbJ25hdmFqb3doaXRlJywgJyNmZmRlYWQnXSwgWydvbGRsYWNlJywgJyNmZGY1ZTYnXSwgWydvbGl2ZWRyYWInLCAnIzZiOGUyMyddLCBbJ29yYW5nZScsICcjZmZhNTAwJ10sIFsnb3JhbmdlcmVkJywgJyNmZjQ1MDAnXSwgWydvcmNoaWQnLCAnI2RhNzBkNiddLCBbJ3BhbGVnb2xkZW5yb2QnLCAnI2VlZThhYSddLCBbJ3BhbGVncmVlbicsICcjOThmYjk4J10sIFsncGFsZXR1cnF1b2lzZScsICcjYWZlZWVlJ10sIFsncGFsZXZpb2xldHJlZCcsICcjZGI3MDkzJ10sIFsncGFwYXlhd2hpcCcsICcjZmZlZmQ1J10sIFsncGVhY2hwdWZmJywgJyNmZmRhYjknXSwgWydwZXJ1JywgJyNjZDg1M2YnXSwgWydwaW5rJywgJyNmZmMwY2InXSwgWydwbHVtJywgJyNkZGEwZGQnXSwgWydwb3dkZXJibHVlJywgJyNiMGUwZTYnXSwgWydyb3N5YnJvd24nLCAnI2JjOGY4ZiddLCBbJ3JveWFsYmx1ZScsICcjNDE2OWUxJ10sIFsnc2FkZGxlYnJvd24nLCAnIzhiNDUxMyddLCBbJ3NhbG1vbicsICcjZmE4MDcyJ10sIFsnc2FuZHlicm93bicsICcjZjRhNDYwJ10sIFsnc2VhZ3JlZW4nLCAnIzJlOGI1NyddLCBbJ3NlYXNoZWxsJywgJyNmZmY1ZWUnXSwgWydzaWVubmEnLCAnI2EwNTIyZCddLCBbJ3NreWJsdWUnLCAnIzg3Y2VlYiddLCBbJ3NsYXRlYmx1ZScsICcjNmE1YWNkJ10sIFsnc2xhdGVncmF5JywgJyM3MDgwOTAnXSwgWydzbGF0ZWdyZXknLCAnIzcwODA5MCddLCBbJ3Nub3cnLCAnI2ZmZmFmYSddLCBbJ3NwcmluZ2dyZWVuJywgJyMwMGZmN2YnXSwgWydzdGVlbGJsdWUnLCAnIzQ2ODJiNCddLCBbJ3RhbicsICcjZDJiNDhjJ10sIFsndGhpc3RsZScsICcjZDhiZmQ4J10sIFsndG9tYXRvJywgJyNmZjYzNDcnXSwgWyd0dXJxdW9pc2UnLCAnIzQwZTBkMCddLCBbJ3Zpb2xldCcsICcjZWU4MmVlJ10sIFsnd2hlYXQnLCAnI2Y1ZGViMyddLCBbJ3doaXRlc21va2UnLCAnI2Y1ZjVmNSddLCBbJ3llbGxvd2dyZWVuJywgJyM5YWNkMzInXV0pO1xuXG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IF9kZWZhdWx0OyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2ludGVyb3BSZXF1aXJlRGVmYXVsdCA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL2ludGVyb3BSZXF1aXJlRGVmYXVsdFwiKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHMuZ2V0UmdiVmFsdWUgPSBnZXRSZ2JWYWx1ZTtcbmV4cG9ydHMuZ2V0UmdiYVZhbHVlID0gZ2V0UmdiYVZhbHVlO1xuZXhwb3J0cy5nZXRPcGFjaXR5ID0gZ2V0T3BhY2l0eTtcbmV4cG9ydHMudG9SZ2IgPSB0b1JnYjtcbmV4cG9ydHMudG9IZXggPSB0b0hleDtcbmV4cG9ydHMuZ2V0Q29sb3JGcm9tUmdiVmFsdWUgPSBnZXRDb2xvckZyb21SZ2JWYWx1ZTtcbmV4cG9ydHMuZGFya2VuID0gZGFya2VuO1xuZXhwb3J0cy5saWdodGVuID0gbGlnaHRlbjtcbmV4cG9ydHMuZmFkZSA9IGZhZGU7XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IHZvaWQgMDtcblxudmFyIF90b0NvbnN1bWFibGVBcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3RvQ29uc3VtYWJsZUFycmF5XCIpKTtcblxudmFyIF9rZXl3b3JkcyA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQocmVxdWlyZShcIi4vY29uZmlnL2tleXdvcmRzXCIpKTtcblxudmFyIGhleFJlZyA9IC9eIyhbMC05YS1mQS1mXXszfXxbMC05YS1mQS1mXXs2fSkkLztcbnZhciByZ2JSZWcgPSAvXihyZ2J8cmdiYXxSR0J8UkdCQSkvO1xudmFyIHJnYmFSZWcgPSAvXihyZ2JhfFJHQkEpLztcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ29sb3IgdmFsaWRhdG9yXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBjb2xvciBIZXh8UmdifFJnYmEgY29sb3Igb3IgY29sb3Iga2V5d29yZFxyXG4gKiBAcmV0dXJuIHtTdHJpbmd8Qm9vbGVhbn0gVmFsaWQgY29sb3IgT3IgZmFsc2VcclxuICovXG5cbmZ1bmN0aW9uIHZhbGlkYXRvcihjb2xvcikge1xuICB2YXIgaXNIZXggPSBoZXhSZWcudGVzdChjb2xvcik7XG4gIHZhciBpc1JnYiA9IHJnYlJlZy50ZXN0KGNvbG9yKTtcbiAgaWYgKGlzSGV4IHx8IGlzUmdiKSByZXR1cm4gY29sb3I7XG4gIGNvbG9yID0gZ2V0Q29sb3JCeUtleXdvcmQoY29sb3IpO1xuXG4gIGlmICghY29sb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdDb2xvcjogSW52YWxpZCBjb2xvciEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gY29sb3I7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCBjb2xvciBieSBrZXl3b3JkXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXl3b3JkIENvbG9yIGtleXdvcmQgbGlrZSByZWQsIGdyZWVuIGFuZCBldGMuXHJcbiAqIEByZXR1cm4ge1N0cmluZ3xCb29sZWFufSBIZXggb3IgcmdiYSBjb2xvciAoSW52YWxpZCBrZXl3b3JkIHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRDb2xvckJ5S2V5d29yZChrZXl3b3JkKSB7XG4gIGlmICgha2V5d29yZCkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2dldENvbG9yQnlLZXl3b3JkczogTWlzc2luZyBwYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICghX2tleXdvcmRzW1wiZGVmYXVsdFwiXS5oYXMoa2V5d29yZCkpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIF9rZXl3b3Jkc1tcImRlZmF1bHRcIl0uZ2V0KGtleXdvcmQpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIFJnYiB2YWx1ZSBvZiB0aGUgY29sb3JcclxuICogQHBhcmFtIHtTdHJpbmd9IGNvbG9yIEhleHxSZ2J8UmdiYSBjb2xvciBvciBjb2xvciBrZXl3b3JkXHJcbiAqIEByZXR1cm4ge0FycmF5PE51bWJlcj58Qm9vbGVhbn0gUmdiIHZhbHVlIG9mIHRoZSBjb2xvciAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmdiVmFsdWUoY29sb3IpIHtcbiAgaWYgKCFjb2xvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2dldFJnYlZhbHVlOiBNaXNzaW5nIHBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29sb3IgPSB2YWxpZGF0b3IoY29sb3IpO1xuICBpZiAoIWNvbG9yKSByZXR1cm4gZmFsc2U7XG4gIHZhciBpc0hleCA9IGhleFJlZy50ZXN0KGNvbG9yKTtcbiAgdmFyIGlzUmdiID0gcmdiUmVnLnRlc3QoY29sb3IpO1xuICB2YXIgbG93ZXJDb2xvciA9IGNvbG9yLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChpc0hleCkgcmV0dXJuIGdldFJnYlZhbHVlRnJvbUhleChsb3dlckNvbG9yKTtcbiAgaWYgKGlzUmdiKSByZXR1cm4gZ2V0UmdiVmFsdWVGcm9tUmdiKGxvd2VyQ29sb3IpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHJnYiB2YWx1ZSBvZiB0aGUgaGV4IGNvbG9yXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBjb2xvciBIZXggY29sb3JcclxuICogQHJldHVybiB7QXJyYXk8TnVtYmVyPn0gUmdiIHZhbHVlIG9mIHRoZSBjb2xvclxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRSZ2JWYWx1ZUZyb21IZXgoY29sb3IpIHtcbiAgY29sb3IgPSBjb2xvci5yZXBsYWNlKCcjJywgJycpO1xuICBpZiAoY29sb3IubGVuZ3RoID09PSAzKSBjb2xvciA9IEFycmF5LmZyb20oY29sb3IpLm1hcChmdW5jdGlvbiAoaGV4TnVtKSB7XG4gICAgcmV0dXJuIGhleE51bSArIGhleE51bTtcbiAgfSkuam9pbignJyk7XG4gIGNvbG9yID0gY29sb3Iuc3BsaXQoJycpO1xuICByZXR1cm4gbmV3IEFycmF5KDMpLmZpbGwoMCkubWFwKGZ1bmN0aW9uICh0LCBpKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KFwiMHhcIi5jb25jYXQoY29sb3JbaSAqIDJdKS5jb25jYXQoY29sb3JbaSAqIDIgKyAxXSkpO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSByZ2IgdmFsdWUgb2YgdGhlIHJnYi9yZ2JhIGNvbG9yXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBjb2xvciBIZXggY29sb3JcclxuICogQHJldHVybiB7QXJyYXl9IFJnYiB2YWx1ZSBvZiB0aGUgY29sb3JcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmdiVmFsdWVGcm9tUmdiKGNvbG9yKSB7XG4gIHJldHVybiBjb2xvci5yZXBsYWNlKC9yZ2JcXCh8cmdiYVxcKHxcXCkvZywgJycpLnNwbGl0KCcsJykuc2xpY2UoMCwgMykubWFwKGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KG4pO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBSZ2JhIHZhbHVlIG9mIHRoZSBjb2xvclxyXG4gKiBAcGFyYW0ge1N0cmluZ30gY29sb3IgSGV4fFJnYnxSZ2JhIGNvbG9yIG9yIGNvbG9yIGtleXdvcmRcclxuICogQHJldHVybiB7QXJyYXk8TnVtYmVyPnxCb29sZWFufSBSZ2JhIHZhbHVlIG9mIHRoZSBjb2xvciAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmdiYVZhbHVlKGNvbG9yKSB7XG4gIGlmICghY29sb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdnZXRSZ2JhVmFsdWU6IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgY29sb3JWYWx1ZSA9IGdldFJnYlZhbHVlKGNvbG9yKTtcbiAgaWYgKCFjb2xvclZhbHVlKSByZXR1cm4gZmFsc2U7XG4gIGNvbG9yVmFsdWUucHVzaChnZXRPcGFjaXR5KGNvbG9yKSk7XG4gIHJldHVybiBjb2xvclZhbHVlO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIG9wYWNpdHkgb2YgY29sb3JcclxuICogQHBhcmFtIHtTdHJpbmd9IGNvbG9yIEhleHxSZ2J8UmdiYSBjb2xvciBvciBjb2xvciBrZXl3b3JkXHJcbiAqIEByZXR1cm4ge051bWJlcnxCb29sZWFufSBDb2xvciBvcGFjaXR5IChJbnZhbGlkIGlucHV0IHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRPcGFjaXR5KGNvbG9yKSB7XG4gIGlmICghY29sb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdnZXRPcGFjaXR5OiBNaXNzaW5nIHBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29sb3IgPSB2YWxpZGF0b3IoY29sb3IpO1xuICBpZiAoIWNvbG9yKSByZXR1cm4gZmFsc2U7XG4gIHZhciBpc1JnYmEgPSByZ2JhUmVnLnRlc3QoY29sb3IpO1xuICBpZiAoIWlzUmdiYSkgcmV0dXJuIDE7XG4gIGNvbG9yID0gY29sb3IudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIE51bWJlcihjb2xvci5zcGxpdCgnLCcpLnNsaWNlKC0xKVswXS5yZXBsYWNlKC9bKXxcXHNdL2csICcnKSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIENvbnZlcnQgY29sb3IgdG8gUmdifFJnYmEgY29sb3JcclxuICogQHBhcmFtIHtTdHJpbmd9IGNvbG9yICAgSGV4fFJnYnxSZ2JhIGNvbG9yIG9yIGNvbG9yIGtleXdvcmRcclxuICogQHBhcmFtIHtOdW1iZXJ9IG9wYWNpdHkgVGhlIG9wYWNpdHkgb2YgY29sb3JcclxuICogQHJldHVybiB7U3RyaW5nfEJvb2xlYW59IFJnYnxSZ2JhIGNvbG9yIChJbnZhbGlkIGlucHV0IHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cblxuXG5mdW5jdGlvbiB0b1JnYihjb2xvciwgb3BhY2l0eSkge1xuICBpZiAoIWNvbG9yKSB7XG4gICAgY29uc29sZS5lcnJvcigndG9SZ2I6IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgcmdiVmFsdWUgPSBnZXRSZ2JWYWx1ZShjb2xvcik7XG4gIGlmICghcmdiVmFsdWUpIHJldHVybiBmYWxzZTtcbiAgdmFyIGFkZE9wYWNpdHkgPSB0eXBlb2Ygb3BhY2l0eSA9PT0gJ251bWJlcic7XG4gIGlmIChhZGRPcGFjaXR5KSByZXR1cm4gJ3JnYmEoJyArIHJnYlZhbHVlLmpvaW4oJywnKSArIFwiLFwiLmNvbmNhdChvcGFjaXR5LCBcIilcIik7XG4gIHJldHVybiAncmdiKCcgKyByZ2JWYWx1ZS5qb2luKCcsJykgKyAnKSc7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIENvbnZlcnQgY29sb3IgdG8gSGV4IGNvbG9yXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBjb2xvciBIZXh8UmdifFJnYmEgY29sb3Igb3IgY29sb3Iga2V5d29yZFxyXG4gKiBAcmV0dXJuIHtTdHJpbmd8Qm9vbGVhbn0gSGV4IGNvbG9yIChJbnZhbGlkIGlucHV0IHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cblxuXG5mdW5jdGlvbiB0b0hleChjb2xvcikge1xuICBpZiAoIWNvbG9yKSB7XG4gICAgY29uc29sZS5lcnJvcigndG9IZXg6IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoaGV4UmVnLnRlc3QoY29sb3IpKSByZXR1cm4gY29sb3I7XG4gIGNvbG9yID0gZ2V0UmdiVmFsdWUoY29sb3IpO1xuICBpZiAoIWNvbG9yKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiAnIycgKyBjb2xvci5tYXAoZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gTnVtYmVyKG4pLnRvU3RyaW5nKDE2KTtcbiAgfSkubWFwKGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gPT09ICcwJyA/ICcwMCcgOiBuO1xuICB9KS5qb2luKCcnKTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IENvbG9yIGZyb20gUmdifFJnYmEgdmFsdWVcclxuICogQHBhcmFtIHtBcnJheTxOdW1iZXI+fSB2YWx1ZSBSZ2J8UmdiYSBjb2xvciB2YWx1ZVxyXG4gKiBAcmV0dXJuIHtTdHJpbmd8Qm9vbGVhbn0gUmdifFJnYmEgY29sb3IgKEludmFsaWQgaW5wdXQgd2lsbCByZXR1cm4gZmFsc2UpXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldENvbG9yRnJvbVJnYlZhbHVlKHZhbHVlKSB7XG4gIGlmICghdmFsdWUpIHtcbiAgICBjb25zb2xlLmVycm9yKCdnZXRDb2xvckZyb21SZ2JWYWx1ZTogTWlzc2luZyBwYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciB2YWx1ZUxlbmd0aCA9IHZhbHVlLmxlbmd0aDtcblxuICBpZiAodmFsdWVMZW5ndGggIT09IDMgJiYgdmFsdWVMZW5ndGggIT09IDQpIHtcbiAgICBjb25zb2xlLmVycm9yKCdnZXRDb2xvckZyb21SZ2JWYWx1ZTogVmFsdWUgaXMgaWxsZWdhbCEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgY29sb3IgPSB2YWx1ZUxlbmd0aCA9PT0gMyA/ICdyZ2IoJyA6ICdyZ2JhKCc7XG4gIGNvbG9yICs9IHZhbHVlLmpvaW4oJywnKSArICcpJztcbiAgcmV0dXJuIGNvbG9yO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBEZWVwZW4gY29sb3JcclxuICogQHBhcmFtIHtTdHJpbmd9IGNvbG9yIEhleHxSZ2J8UmdiYSBjb2xvciBvciBjb2xvciBrZXl3b3JkXHJcbiAqIEByZXR1cm4ge051bWJlcn0gUGVyY2VudCBvZiBEZWVwZW4gKDEtMTAwKVxyXG4gKiBAcmV0dXJuIHtTdHJpbmd8Qm9vbGVhbn0gUmdiYSBjb2xvciAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gZGFya2VuKGNvbG9yKSB7XG4gIHZhciBwZXJjZW50ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAwO1xuXG4gIGlmICghY29sb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdkYXJrZW46IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgcmdiYVZhbHVlID0gZ2V0UmdiYVZhbHVlKGNvbG9yKTtcbiAgaWYgKCFyZ2JhVmFsdWUpIHJldHVybiBmYWxzZTtcbiAgcmdiYVZhbHVlID0gcmdiYVZhbHVlLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgIHJldHVybiBpID09PSAzID8gdiA6IHYgLSBNYXRoLmNlaWwoMi41NSAqIHBlcmNlbnQpO1xuICB9KS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICByZXR1cm4gdiA8IDAgPyAwIDogdjtcbiAgfSk7XG4gIHJldHVybiBnZXRDb2xvckZyb21SZ2JWYWx1ZShyZ2JhVmFsdWUpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBCcmlnaHRlbiBjb2xvclxyXG4gKiBAcGFyYW0ge1N0cmluZ30gY29sb3IgSGV4fFJnYnxSZ2JhIGNvbG9yIG9yIGNvbG9yIGtleXdvcmRcclxuICogQHJldHVybiB7TnVtYmVyfSBQZXJjZW50IG9mIGJyaWdodGVuICgxLTEwMClcclxuICogQHJldHVybiB7U3RyaW5nfEJvb2xlYW59IFJnYmEgY29sb3IgKEludmFsaWQgaW5wdXQgd2lsbCByZXR1cm4gZmFsc2UpXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGxpZ2h0ZW4oY29sb3IpIHtcbiAgdmFyIHBlcmNlbnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDA7XG5cbiAgaWYgKCFjb2xvcikge1xuICAgIGNvbnNvbGUuZXJyb3IoJ2xpZ2h0ZW46IE1pc3NpbmcgcGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgcmdiYVZhbHVlID0gZ2V0UmdiYVZhbHVlKGNvbG9yKTtcbiAgaWYgKCFyZ2JhVmFsdWUpIHJldHVybiBmYWxzZTtcbiAgcmdiYVZhbHVlID0gcmdiYVZhbHVlLm1hcChmdW5jdGlvbiAodiwgaSkge1xuICAgIHJldHVybiBpID09PSAzID8gdiA6IHYgKyBNYXRoLmNlaWwoMi41NSAqIHBlcmNlbnQpO1xuICB9KS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICByZXR1cm4gdiA+IDI1NSA/IDI1NSA6IHY7XG4gIH0pO1xuICByZXR1cm4gZ2V0Q29sb3JGcm9tUmdiVmFsdWUocmdiYVZhbHVlKTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQWRqdXN0IGNvbG9yIG9wYWNpdHlcclxuICogQHBhcmFtIHtTdHJpbmd9IGNvbG9yICAgSGV4fFJnYnxSZ2JhIGNvbG9yIG9yIGNvbG9yIGtleXdvcmRcclxuICogQHBhcmFtIHtOdW1iZXJ9IFBlcmNlbnQgb2Ygb3BhY2l0eVxyXG4gKiBAcmV0dXJuIHtTdHJpbmd8Qm9vbGVhbn0gUmdiYSBjb2xvciAoSW52YWxpZCBpbnB1dCB3aWxsIHJldHVybiBmYWxzZSlcclxuICovXG5cblxuZnVuY3Rpb24gZmFkZShjb2xvcikge1xuICB2YXIgcGVyY2VudCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogMTAwO1xuXG4gIGlmICghY29sb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdmYWRlOiBNaXNzaW5nIHBhcmFtZXRlcnMhJyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIHJnYlZhbHVlID0gZ2V0UmdiVmFsdWUoY29sb3IpO1xuICBpZiAoIXJnYlZhbHVlKSByZXR1cm4gZmFsc2U7XG4gIHZhciByZ2JhVmFsdWUgPSBbXS5jb25jYXQoKDAsIF90b0NvbnN1bWFibGVBcnJheTJbXCJkZWZhdWx0XCJdKShyZ2JWYWx1ZSksIFtwZXJjZW50IC8gMTAwXSk7XG4gIHJldHVybiBnZXRDb2xvckZyb21SZ2JWYWx1ZShyZ2JhVmFsdWUpO1xufVxuXG52YXIgX2RlZmF1bHQgPSB7XG4gIGZhZGU6IGZhZGUsXG4gIHRvSGV4OiB0b0hleCxcbiAgdG9SZ2I6IHRvUmdiLFxuICBkYXJrZW46IGRhcmtlbixcbiAgbGlnaHRlbjogbGlnaHRlbixcbiAgZ2V0T3BhY2l0eTogZ2V0T3BhY2l0eSxcbiAgZ2V0UmdiVmFsdWU6IGdldFJnYlZhbHVlLFxuICBnZXRSZ2JhVmFsdWU6IGdldFJnYmFWYWx1ZSxcbiAgZ2V0Q29sb3JGcm9tUmdiVmFsdWU6IGdldENvbG9yRnJvbVJnYlZhbHVlXG59O1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcbmV4cG9ydHNbXCJkZWZhdWx0XCJdID0gZXhwb3J0cy5lYXNlSW5PdXRCb3VuY2UgPSBleHBvcnRzLmVhc2VPdXRCb3VuY2UgPSBleHBvcnRzLmVhc2VJbkJvdW5jZSA9IGV4cG9ydHMuZWFzZUluT3V0RWxhc3RpYyA9IGV4cG9ydHMuZWFzZU91dEVsYXN0aWMgPSBleHBvcnRzLmVhc2VJbkVsYXN0aWMgPSBleHBvcnRzLmVhc2VJbk91dEJhY2sgPSBleHBvcnRzLmVhc2VPdXRCYWNrID0gZXhwb3J0cy5lYXNlSW5CYWNrID0gZXhwb3J0cy5lYXNlSW5PdXRRdWludCA9IGV4cG9ydHMuZWFzZU91dFF1aW50ID0gZXhwb3J0cy5lYXNlSW5RdWludCA9IGV4cG9ydHMuZWFzZUluT3V0UXVhcnQgPSBleHBvcnRzLmVhc2VPdXRRdWFydCA9IGV4cG9ydHMuZWFzZUluUXVhcnQgPSBleHBvcnRzLmVhc2VJbk91dEN1YmljID0gZXhwb3J0cy5lYXNlT3V0Q3ViaWMgPSBleHBvcnRzLmVhc2VJbkN1YmljID0gZXhwb3J0cy5lYXNlSW5PdXRRdWFkID0gZXhwb3J0cy5lYXNlT3V0UXVhZCA9IGV4cG9ydHMuZWFzZUluUXVhZCA9IGV4cG9ydHMuZWFzZUluT3V0U2luZSA9IGV4cG9ydHMuZWFzZU91dFNpbmUgPSBleHBvcnRzLmVhc2VJblNpbmUgPSBleHBvcnRzLmxpbmVhciA9IHZvaWQgMDtcbnZhciBsaW5lYXIgPSBbW1swLCAxXSwgJycsIFswLjMzLCAwLjY3XV0sIFtbMSwgMF0sIFswLjY3LCAwLjMzXV1dO1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBTaW5lXHJcbiAqL1xuXG5leHBvcnRzLmxpbmVhciA9IGxpbmVhcjtcbnZhciBlYXNlSW5TaW5lID0gW1tbMCwgMV1dLCBbWzAuNTM4LCAwLjU2NF0sIFswLjE2OSwgMC45MTJdLCBbMC44ODAsIDAuMTk2XV0sIFtbMSwgMF1dXTtcbmV4cG9ydHMuZWFzZUluU2luZSA9IGVhc2VJblNpbmU7XG52YXIgZWFzZU91dFNpbmUgPSBbW1swLCAxXV0sIFtbMC40NDQsIDAuNDQ4XSwgWzAuMTY5LCAwLjczNl0sIFswLjcxOCwgMC4xNl1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VPdXRTaW5lID0gZWFzZU91dFNpbmU7XG52YXIgZWFzZUluT3V0U2luZSA9IFtbWzAsIDFdXSwgW1swLjUsIDAuNV0sIFswLjIsIDFdLCBbMC44LCAwXV0sIFtbMSwgMF1dXTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gUXVhZFxyXG4gKi9cblxuZXhwb3J0cy5lYXNlSW5PdXRTaW5lID0gZWFzZUluT3V0U2luZTtcbnZhciBlYXNlSW5RdWFkID0gW1tbMCwgMV1dLCBbWzAuNTUwLCAwLjU4NF0sIFswLjIzMSwgMC45MDRdLCBbMC44NjgsIDAuMjY0XV0sIFtbMSwgMF1dXTtcbmV4cG9ydHMuZWFzZUluUXVhZCA9IGVhc2VJblF1YWQ7XG52YXIgZWFzZU91dFF1YWQgPSBbW1swLCAxXV0sIFtbMC40MTMsIDAuNDI4XSwgWzAuMDY1LCAwLjgxNl0sIFswLjc2MCwgMC4wNF1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VPdXRRdWFkID0gZWFzZU91dFF1YWQ7XG52YXIgZWFzZUluT3V0UXVhZCA9IFtbWzAsIDFdXSwgW1swLjUsIDAuNV0sIFswLjMsIDAuOV0sIFswLjcsIDAuMV1dLCBbWzEsIDBdXV07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEN1YmljXHJcbiAqL1xuXG5leHBvcnRzLmVhc2VJbk91dFF1YWQgPSBlYXNlSW5PdXRRdWFkO1xudmFyIGVhc2VJbkN1YmljID0gW1tbMCwgMV1dLCBbWzAuNjc5LCAwLjY4OF0sIFswLjM2NiwgMC45OTJdLCBbMC45OTIsIDAuMzg0XV0sIFtbMSwgMF1dXTtcbmV4cG9ydHMuZWFzZUluQ3ViaWMgPSBlYXNlSW5DdWJpYztcbnZhciBlYXNlT3V0Q3ViaWMgPSBbW1swLCAxXV0sIFtbMC4zMjEsIDAuMzEyXSwgWzAuMDA4LCAwLjYxNl0sIFswLjYzNCwgMC4wMDhdXSwgW1sxLCAwXV1dO1xuZXhwb3J0cy5lYXNlT3V0Q3ViaWMgPSBlYXNlT3V0Q3ViaWM7XG52YXIgZWFzZUluT3V0Q3ViaWMgPSBbW1swLCAxXV0sIFtbMC41LCAwLjVdLCBbMC4zLCAxXSwgWzAuNywgMF1dLCBbWzEsIDBdXV07XG4vKipcclxuICogQGRlc2NyaXB0aW9uIFF1YXJ0XHJcbiAqL1xuXG5leHBvcnRzLmVhc2VJbk91dEN1YmljID0gZWFzZUluT3V0Q3ViaWM7XG52YXIgZWFzZUluUXVhcnQgPSBbW1swLCAxXV0sIFtbMC44MTIsIDAuNzRdLCBbMC42MTEsIDAuOTg4XSwgWzEuMDEzLCAwLjQ5Ml1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VJblF1YXJ0ID0gZWFzZUluUXVhcnQ7XG52YXIgZWFzZU91dFF1YXJ0ID0gW1tbMCwgMV1dLCBbWzAuMTUyLCAwLjI0NF0sIFswLjAwMSwgMC40NDhdLCBbMC4yODUsIC0wLjAyXV0sIFtbMSwgMF1dXTtcbmV4cG9ydHMuZWFzZU91dFF1YXJ0ID0gZWFzZU91dFF1YXJ0O1xudmFyIGVhc2VJbk91dFF1YXJ0ID0gW1tbMCwgMV1dLCBbWzAuNSwgMC41XSwgWzAuNCwgMV0sIFswLjYsIDBdXSwgW1sxLCAwXV1dO1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBRdWludFxyXG4gKi9cblxuZXhwb3J0cy5lYXNlSW5PdXRRdWFydCA9IGVhc2VJbk91dFF1YXJ0O1xudmFyIGVhc2VJblF1aW50ID0gW1tbMCwgMV1dLCBbWzAuODU3LCAwLjg1Nl0sIFswLjcxNCwgMV0sIFsxLCAwLjcxMl1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VJblF1aW50ID0gZWFzZUluUXVpbnQ7XG52YXIgZWFzZU91dFF1aW50ID0gW1tbMCwgMV1dLCBbWzAuMTA4LCAwLjJdLCBbMC4wMDEsIDAuNF0sIFswLjIxNCwgLTAuMDEyXV0sIFtbMSwgMF1dXTtcbmV4cG9ydHMuZWFzZU91dFF1aW50ID0gZWFzZU91dFF1aW50O1xudmFyIGVhc2VJbk91dFF1aW50ID0gW1tbMCwgMV1dLCBbWzAuNSwgMC41XSwgWzAuNSwgMV0sIFswLjUsIDBdXSwgW1sxLCAwXV1dO1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBCYWNrXHJcbiAqL1xuXG5leHBvcnRzLmVhc2VJbk91dFF1aW50ID0gZWFzZUluT3V0UXVpbnQ7XG52YXIgZWFzZUluQmFjayA9IFtbWzAsIDFdXSwgW1swLjY2NywgMC44OTZdLCBbMC4zODAsIDEuMTg0XSwgWzAuOTU1LCAwLjYxNl1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VJbkJhY2sgPSBlYXNlSW5CYWNrO1xudmFyIGVhc2VPdXRCYWNrID0gW1tbMCwgMV1dLCBbWzAuMzM1LCAwLjAyOF0sIFswLjA2MSwgMC4yMl0sIFswLjYzMSwgLTAuMThdXSwgW1sxLCAwXV1dO1xuZXhwb3J0cy5lYXNlT3V0QmFjayA9IGVhc2VPdXRCYWNrO1xudmFyIGVhc2VJbk91dEJhY2sgPSBbW1swLCAxXV0sIFtbMC41LCAwLjVdLCBbMC40LCAxLjRdLCBbMC42LCAtMC40XV0sIFtbMSwgMF1dXTtcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gRWxhc3RpY1xyXG4gKi9cblxuZXhwb3J0cy5lYXNlSW5PdXRCYWNrID0gZWFzZUluT3V0QmFjaztcbnZhciBlYXNlSW5FbGFzdGljID0gW1tbMCwgMV1dLCBbWzAuNDc0LCAwLjk2NF0sIFswLjM4MiwgMC45ODhdLCBbMC41NTcsIDAuOTUyXV0sIFtbMC42MTksIDEuMDc2XSwgWzAuNTY1LCAxLjA4OF0sIFswLjY2OSwgMS4wOF1dLCBbWzAuNzcwLCAwLjkxNl0sIFswLjcxMiwgMC45MjRdLCBbMC44NDcsIDAuOTA0XV0sIFtbMC45MTEsIDEuMzA0XSwgWzAuODcyLCAxLjMxNl0sIFswLjk2MSwgMS4zNF1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VJbkVsYXN0aWMgPSBlYXNlSW5FbGFzdGljO1xudmFyIGVhc2VPdXRFbGFzdGljID0gW1tbMCwgMV1dLCBbWzAuMDczLCAtMC4zMl0sIFswLjAzNCwgLTAuMzI4XSwgWzAuMTA0LCAtMC4zNDRdXSwgW1swLjE5MSwgMC4wOTJdLCBbMC4xMTAsIDAuMDZdLCBbMC4yNTYsIDAuMDhdXSwgW1swLjMxMCwgLTAuMDc2XSwgWzAuMjYwLCAtMC4wNjhdLCBbMC4zNTcsIC0wLjA3Nl1dLCBbWzAuNDMyLCAwLjAzMl0sIFswLjM2MiwgMC4wMjhdLCBbMC42ODMsIC0wLjAwNF1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VPdXRFbGFzdGljID0gZWFzZU91dEVsYXN0aWM7XG52YXIgZWFzZUluT3V0RWxhc3RpYyA9IFtbWzAsIDFdXSwgW1swLjIxMCwgMC45NF0sIFswLjE2NywgMC44ODRdLCBbMC4yNTIsIDAuOThdXSwgW1swLjI5OSwgMS4xMDRdLCBbMC4yNTYsIDEuMDkyXSwgWzAuMzQ3LCAxLjEwOF1dLCBbWzAuNSwgMC40OTZdLCBbMC40NTEsIDAuNjcyXSwgWzAuNTQ4LCAwLjMyNF1dLCBbWzAuNjk2LCAtMC4xMDhdLCBbMC42NTIsIC0wLjExMl0sIFswLjc0MSwgLTAuMTI0XV0sIFtbMC44MDUsIDAuMDY0XSwgWzAuNzU2LCAwLjAxMl0sIFswLjg2NiwgMC4wOTZdXSwgW1sxLCAwXV1dO1xuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBCb3VuY2VcclxuICovXG5cbmV4cG9ydHMuZWFzZUluT3V0RWxhc3RpYyA9IGVhc2VJbk91dEVsYXN0aWM7XG52YXIgZWFzZUluQm91bmNlID0gW1tbMCwgMV1dLCBbWzAuMTQ4LCAxXSwgWzAuMDc1LCAwLjg2OF0sIFswLjE5MywgMC44NDhdXSwgW1swLjMyNiwgMV0sIFswLjI3NiwgMC44MzZdLCBbMC40MDUsIDAuNzEyXV0sIFtbMC42MDAsIDFdLCBbMC41MTEsIDAuNzA4XSwgWzAuNjcxLCAwLjM0OF1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VJbkJvdW5jZSA9IGVhc2VJbkJvdW5jZTtcbnZhciBlYXNlT3V0Qm91bmNlID0gW1tbMCwgMV1dLCBbWzAuMzU3LCAwLjAwNF0sIFswLjI3MCwgMC41OTJdLCBbMC4zNzYsIDAuMjUyXV0sIFtbMC42MDQsIC0wLjAwNF0sIFswLjU0OCwgMC4zMTJdLCBbMC42NjksIDAuMTg0XV0sIFtbMC44MjAsIDBdLCBbMC43NDksIDAuMTg0XSwgWzAuOTA1LCAwLjEzMl1dLCBbWzEsIDBdXV07XG5leHBvcnRzLmVhc2VPdXRCb3VuY2UgPSBlYXNlT3V0Qm91bmNlO1xudmFyIGVhc2VJbk91dEJvdW5jZSA9IFtbWzAsIDFdXSwgW1swLjEwMiwgMV0sIFswLjA1MCwgMC44NjRdLCBbMC4xMTcsIDAuODZdXSwgW1swLjIxNiwgMC45OTZdLCBbMC4yMDgsIDAuODQ0XSwgWzAuMjI3LCAwLjgwOF1dLCBbWzAuMzQ3LCAwLjk5Nl0sIFswLjM0MywgMC44XSwgWzAuNDgwLCAwLjI5Ml1dLCBbWzAuNjM1LCAwLjAwNF0sIFswLjUxMSwgMC42NzZdLCBbMC42NTYsIDAuMjA4XV0sIFtbMC43ODcsIDBdLCBbMC43NjAsIDAuMl0sIFswLjc5NSwgMC4xNDRdXSwgW1swLjkwNSwgLTAuMDA0XSwgWzAuODk5LCAwLjE2NF0sIFswLjk0NCwgMC4xNDRdXSwgW1sxLCAwXV1dO1xuZXhwb3J0cy5lYXNlSW5PdXRCb3VuY2UgPSBlYXNlSW5PdXRCb3VuY2U7XG5cbnZhciBfZGVmYXVsdCA9IG5ldyBNYXAoW1snbGluZWFyJywgbGluZWFyXSwgWydlYXNlSW5TaW5lJywgZWFzZUluU2luZV0sIFsnZWFzZU91dFNpbmUnLCBlYXNlT3V0U2luZV0sIFsnZWFzZUluT3V0U2luZScsIGVhc2VJbk91dFNpbmVdLCBbJ2Vhc2VJblF1YWQnLCBlYXNlSW5RdWFkXSwgWydlYXNlT3V0UXVhZCcsIGVhc2VPdXRRdWFkXSwgWydlYXNlSW5PdXRRdWFkJywgZWFzZUluT3V0UXVhZF0sIFsnZWFzZUluQ3ViaWMnLCBlYXNlSW5DdWJpY10sIFsnZWFzZU91dEN1YmljJywgZWFzZU91dEN1YmljXSwgWydlYXNlSW5PdXRDdWJpYycsIGVhc2VJbk91dEN1YmljXSwgWydlYXNlSW5RdWFydCcsIGVhc2VJblF1YXJ0XSwgWydlYXNlT3V0UXVhcnQnLCBlYXNlT3V0UXVhcnRdLCBbJ2Vhc2VJbk91dFF1YXJ0JywgZWFzZUluT3V0UXVhcnRdLCBbJ2Vhc2VJblF1aW50JywgZWFzZUluUXVpbnRdLCBbJ2Vhc2VPdXRRdWludCcsIGVhc2VPdXRRdWludF0sIFsnZWFzZUluT3V0UXVpbnQnLCBlYXNlSW5PdXRRdWludF0sIFsnZWFzZUluQmFjaycsIGVhc2VJbkJhY2tdLCBbJ2Vhc2VPdXRCYWNrJywgZWFzZU91dEJhY2tdLCBbJ2Vhc2VJbk91dEJhY2snLCBlYXNlSW5PdXRCYWNrXSwgWydlYXNlSW5FbGFzdGljJywgZWFzZUluRWxhc3RpY10sIFsnZWFzZU91dEVsYXN0aWMnLCBlYXNlT3V0RWxhc3RpY10sIFsnZWFzZUluT3V0RWxhc3RpYycsIGVhc2VJbk91dEVsYXN0aWNdLCBbJ2Vhc2VJbkJvdW5jZScsIGVhc2VJbkJvdW5jZV0sIFsnZWFzZU91dEJvdW5jZScsIGVhc2VPdXRCb3VuY2VdLCBbJ2Vhc2VJbk91dEJvdW5jZScsIGVhc2VJbk91dEJvdW5jZV1dKTtcblxuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSBfZGVmYXVsdDsiLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQgPSByZXF1aXJlKFwiQGJhYmVsL3J1bnRpbWUvaGVscGVycy9pbnRlcm9wUmVxdWlyZURlZmF1bHRcIik7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG5leHBvcnRzLnRyYW5zaXRpb24gPSB0cmFuc2l0aW9uO1xuZXhwb3J0cy5pbmplY3ROZXdDdXJ2ZSA9IGluamVjdE5ld0N1cnZlO1xuZXhwb3J0c1tcImRlZmF1bHRcIl0gPSB2b2lkIDA7XG5cbnZhciBfc2xpY2VkVG9BcnJheTIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3NsaWNlZFRvQXJyYXlcIikpO1xuXG52YXIgX3R5cGVvZjIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9oZWxwZXJzL3R5cGVvZlwiKSk7XG5cbnZhciBfY3VydmVzID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChyZXF1aXJlKFwiLi9jb25maWcvY3VydmVzXCIpKTtcblxudmFyIGRlZmF1bHRUcmFuc2l0aW9uQkMgPSAnbGluZWFyJztcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBOLWZyYW1lIGFuaW1hdGlvbiBzdGF0ZSBieSB0aGUgc3RhcnQgYW5kIGVuZCBzdGF0ZVxyXG4gKiAgICAgICAgICAgICAgb2YgdGhlIGFuaW1hdGlvbiBhbmQgdGhlIGVhc2luZyBjdXJ2ZVxyXG4gKiBAcGFyYW0ge1N0cmluZ3xBcnJheX0gdEJDICAgICAgICAgICAgICAgRWFzaW5nIGN1cnZlIG5hbWUgb3IgZGF0YVxyXG4gKiBAcGFyYW0ge051bWJlcnxBcnJheXxPYmplY3R9IHN0YXJ0U3RhdGUgQW5pbWF0aW9uIHN0YXJ0IHN0YXRlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfEFycmF5fE9iamVjdH0gZW5kU3RhdGUgICBBbmltYXRpb24gZW5kIHN0YXRlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBmcmFtZU51bSAgICAgICAgICAgICAgICBOdW1iZXIgb2YgQW5pbWF0aW9uIGZyYW1lc1xyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGRlZXAgICAgICAgICAgICAgICAgICAgV2hldGhlciB0byB1c2UgcmVjdXJzaXZlIG1vZGVcclxuICogQHJldHVybiB7QXJyYXl8Qm9vbGVhbn0gU3RhdGUgb2YgZWFjaCBmcmFtZSBvZiB0aGUgYW5pbWF0aW9uIChJbnZhbGlkIGlucHV0IHdpbGwgcmV0dXJuIGZhbHNlKVxyXG4gKi9cblxuZnVuY3Rpb24gdHJhbnNpdGlvbih0QkMpIHtcbiAgdmFyIHN0YXJ0U3RhdGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7XG4gIHZhciBlbmRTdGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogbnVsbDtcbiAgdmFyIGZyYW1lTnVtID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiAzMDtcbiAgdmFyIGRlZXAgPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IGZhbHNlO1xuICBpZiAoIWNoZWNrUGFyYW1zLmFwcGx5KHZvaWQgMCwgYXJndW1lbnRzKSkgcmV0dXJuIGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgLy8gR2V0IHRoZSB0cmFuc2l0aW9uIGJlemllciBjdXJ2ZVxuICAgIHZhciBiZXppZXJDdXJ2ZSA9IGdldEJlemllckN1cnZlKHRCQyk7IC8vIEdldCB0aGUgcHJvZ3Jlc3Mgb2YgZWFjaCBmcmFtZSBzdGF0ZVxuXG4gICAgdmFyIGZyYW1lU3RhdGVQcm9ncmVzcyA9IGdldEZyYW1lU3RhdGVQcm9ncmVzcyhiZXppZXJDdXJ2ZSwgZnJhbWVOdW0pOyAvLyBJZiB0aGUgcmVjdXJzaW9uIG1vZGUgaXMgbm90IGVuYWJsZWQgb3IgdGhlIHN0YXRlIHR5cGUgaXMgTnVtYmVyLCB0aGUgc2hhbGxvdyBzdGF0ZSBjYWxjdWxhdGlvbiBpcyBwZXJmb3JtZWQgZGlyZWN0bHkuXG5cbiAgICBpZiAoIWRlZXAgfHwgdHlwZW9mIGVuZFN0YXRlID09PSAnbnVtYmVyJykgcmV0dXJuIGdldFRyYW5zaXRpb25TdGF0ZShzdGFydFN0YXRlLCBlbmRTdGF0ZSwgZnJhbWVTdGF0ZVByb2dyZXNzKTtcbiAgICByZXR1cm4gcmVjdXJzaW9uVHJhbnNpdGlvblN0YXRlKHN0YXJ0U3RhdGUsIGVuZFN0YXRlLCBmcmFtZVN0YXRlUHJvZ3Jlc3MpO1xuICB9IGNhdGNoIChfdW51c2VkKSB7XG4gICAgY29uc29sZS53YXJuKCdUcmFuc2l0aW9uIHBhcmFtZXRlciBtYXkgYmUgYWJub3JtYWwhJyk7XG4gICAgcmV0dXJuIFtlbmRTdGF0ZV07XG4gIH1cbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gQ2hlY2sgaWYgdGhlIHBhcmFtZXRlcnMgYXJlIGxlZ2FsXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSB0QkMgICAgICBOYW1lIG9mIHRyYW5zaXRpb24gYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7QW55fSBzdGFydFN0YXRlICBUcmFuc2l0aW9uIHN0YXJ0IHN0YXRlXHJcbiAqIEBwYXJhbSB7QW55fSBlbmRTdGF0ZSAgICBUcmFuc2l0aW9uIGVuZCBzdGF0ZVxyXG4gKiBAcGFyYW0ge051bWJlcn0gZnJhbWVOdW0gTnVtYmVyIG9mIHRyYW5zaXRpb24gZnJhbWVzXHJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IElzIHRoZSBwYXJhbWV0ZXIgbGVnYWxcclxuICovXG5cblxuZnVuY3Rpb24gY2hlY2tQYXJhbXModEJDKSB7XG4gIHZhciBzdGFydFN0YXRlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTtcbiAgdmFyIGVuZFN0YXRlID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcbiAgdmFyIGZyYW1lTnVtID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiAzMDtcblxuICBpZiAoIXRCQyB8fCBzdGFydFN0YXRlID09PSBmYWxzZSB8fCBlbmRTdGF0ZSA9PT0gZmFsc2UgfHwgIWZyYW1lTnVtKSB7XG4gICAgY29uc29sZS5lcnJvcigndHJhbnNpdGlvbjogTWlzc2luZyBQYXJhbWV0ZXJzIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICgoMCwgX3R5cGVvZjJbXCJkZWZhdWx0XCJdKShzdGFydFN0YXRlKSAhPT0gKDAsIF90eXBlb2YyW1wiZGVmYXVsdFwiXSkoZW5kU3RhdGUpKSB7XG4gICAgY29uc29sZS5lcnJvcigndHJhbnNpdGlvbjogSW5jb25zaXN0ZW50IFN0YXR1cyBUeXBlcyEnKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgc3RhdGVUeXBlID0gKDAsIF90eXBlb2YyW1wiZGVmYXVsdFwiXSkoZW5kU3RhdGUpO1xuXG4gIGlmIChzdGF0ZVR5cGUgPT09ICdzdHJpbmcnIHx8IHN0YXRlVHlwZSA9PT0gJ2Jvb2xlYW4nIHx8ICF0QkMubGVuZ3RoKSB7XG4gICAgY29uc29sZS5lcnJvcigndHJhbnNpdGlvbjogVW5zdXBwb3J0ZWQgRGF0YSBUeXBlIG9mIFN0YXRlIScpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmICghX2N1cnZlc1tcImRlZmF1bHRcIl0uaGFzKHRCQykgJiYgISh0QkMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICBjb25zb2xlLndhcm4oJ3RyYW5zaXRpb246IFRyYW5zaXRpb24gY3VydmUgbm90IGZvdW5kLCBkZWZhdWx0IGN1cnZlIHdpbGwgYmUgdXNlZCEnKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHRyYW5zaXRpb24gYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSB0QkMgTmFtZSBvZiB0cmFuc2l0aW9uIGJlemllciBjdXJ2ZVxyXG4gKiBAcmV0dXJuIHtBcnJheX0gQmV6aWVyIGN1cnZlIGRhdGFcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0QmV6aWVyQ3VydmUodEJDKSB7XG4gIHZhciBiZXppZXJDdXJ2ZSA9ICcnO1xuXG4gIGlmIChfY3VydmVzW1wiZGVmYXVsdFwiXS5oYXModEJDKSkge1xuICAgIGJlemllckN1cnZlID0gX2N1cnZlc1tcImRlZmF1bHRcIl0uZ2V0KHRCQyk7XG4gIH0gZWxzZSBpZiAodEJDIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICBiZXppZXJDdXJ2ZSA9IHRCQztcbiAgfSBlbHNlIHtcbiAgICBiZXppZXJDdXJ2ZSA9IF9jdXJ2ZXNbXCJkZWZhdWx0XCJdLmdldChkZWZhdWx0VHJhbnNpdGlvbkJDKTtcbiAgfVxuXG4gIHJldHVybiBiZXppZXJDdXJ2ZTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSBwcm9ncmVzcyBvZiBlYWNoIGZyYW1lIHN0YXRlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGJlemllckN1cnZlIFRyYW5zaXRpb24gYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBmcmFtZU51bSAgIE51bWJlciBvZiB0cmFuc2l0aW9uIGZyYW1lc1xyXG4gKiBAcmV0dXJuIHtBcnJheX0gUHJvZ3Jlc3Mgb2YgZWFjaCBmcmFtZSBzdGF0ZVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRGcmFtZVN0YXRlUHJvZ3Jlc3MoYmV6aWVyQ3VydmUsIGZyYW1lTnVtKSB7XG4gIHZhciB0TWludXMgPSAxIC8gKGZyYW1lTnVtIC0gMSk7XG4gIHZhciB0U3RhdGUgPSBuZXcgQXJyYXkoZnJhbWVOdW0pLmZpbGwoMCkubWFwKGZ1bmN0aW9uICh0LCBpKSB7XG4gICAgcmV0dXJuIGkgKiB0TWludXM7XG4gIH0pO1xuICB2YXIgZnJhbWVTdGF0ZSA9IHRTdGF0ZS5tYXAoZnVuY3Rpb24gKHQpIHtcbiAgICByZXR1cm4gZ2V0RnJhbWVTdGF0ZUZyb21UKGJlemllckN1cnZlLCB0KTtcbiAgfSk7XG4gIHJldHVybiBmcmFtZVN0YXRlO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIHByb2dyZXNzIG9mIHRoZSBjb3JyZXNwb25kaW5nIGZyYW1lIGFjY29yZGluZyB0byB0XHJcbiAqIEBwYXJhbSB7QXJyYXl9IGJlemllckN1cnZlIFRyYW5zaXRpb24gYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSB0ICAgICAgICAgIEN1cnJlbnQgZnJhbWUgdFxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IFByb2dyZXNzIG9mIGN1cnJlbnQgZnJhbWVcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0RnJhbWVTdGF0ZUZyb21UKGJlemllckN1cnZlLCB0KSB7XG4gIHZhciB0QmV6aWVyQ3VydmVQb2ludCA9IGdldEJlemllckN1cnZlUG9pbnRGcm9tVChiZXppZXJDdXJ2ZSwgdCk7XG4gIHZhciBiZXppZXJDdXJ2ZVBvaW50VCA9IGdldEJlemllckN1cnZlUG9pbnRURnJvbVJlVCh0QmV6aWVyQ3VydmVQb2ludCwgdCk7XG4gIHJldHVybiBnZXRCZXppZXJDdXJ2ZVRTdGF0ZSh0QmV6aWVyQ3VydmVQb2ludCwgYmV6aWVyQ3VydmVQb2ludFQpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdGhlIGNvcnJlc3BvbmRpbmcgc3ViLWN1cnZlIGFjY29yZGluZyB0byB0XHJcbiAqIEBwYXJhbSB7QXJyYXl9IGJlemllckN1cnZlIFRyYW5zaXRpb24gYmV6aWVyIGN1cnZlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSB0ICAgICAgICAgIEN1cnJlbnQgZnJhbWUgdFxyXG4gKiBAcmV0dXJuIHtBcnJheX0gU3ViLWN1cnZlIG9mIHRcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0QmV6aWVyQ3VydmVQb2ludEZyb21UKGJlemllckN1cnZlLCB0KSB7XG4gIHZhciBsYXN0SW5kZXggPSBiZXppZXJDdXJ2ZS5sZW5ndGggLSAxO1xuICB2YXIgYmVnaW4gPSAnJyxcbiAgICAgIGVuZCA9ICcnO1xuICBiZXppZXJDdXJ2ZS5maW5kSW5kZXgoZnVuY3Rpb24gKGl0ZW0sIGkpIHtcbiAgICBpZiAoaSA9PT0gbGFzdEluZGV4KSByZXR1cm47XG4gICAgYmVnaW4gPSBpdGVtO1xuICAgIGVuZCA9IGJlemllckN1cnZlW2kgKyAxXTtcbiAgICB2YXIgY3VycmVudE1haW5Qb2ludFggPSBiZWdpblswXVswXTtcbiAgICB2YXIgbmV4dE1haW5Qb2ludFggPSBlbmRbMF1bMF07XG4gICAgcmV0dXJuIHQgPj0gY3VycmVudE1haW5Qb2ludFggJiYgdCA8IG5leHRNYWluUG9pbnRYO1xuICB9KTtcbiAgdmFyIHAwID0gYmVnaW5bMF07XG4gIHZhciBwMSA9IGJlZ2luWzJdIHx8IGJlZ2luWzBdO1xuICB2YXIgcDIgPSBlbmRbMV0gfHwgZW5kWzBdO1xuICB2YXIgcDMgPSBlbmRbMF07XG4gIHJldHVybiBbcDAsIHAxLCBwMiwgcDNdO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgbG9jYWwgdCBiYXNlZCBvbiB0IGFuZCBzdWItY3VydmVcclxuICogQHBhcmFtIHtBcnJheX0gYmV6aWVyQ3VydmUgU3ViLWN1cnZlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSB0ICAgICAgICAgIEN1cnJlbnQgZnJhbWUgdFxyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IGxvY2FsIHQgb2Ygc3ViLWN1cnZlXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldEJlemllckN1cnZlUG9pbnRURnJvbVJlVChiZXppZXJDdXJ2ZSwgdCkge1xuICB2YXIgcmVCZWdpblggPSBiZXppZXJDdXJ2ZVswXVswXTtcbiAgdmFyIHJlRW5kWCA9IGJlemllckN1cnZlWzNdWzBdO1xuICB2YXIgeE1pbnVzID0gcmVFbmRYIC0gcmVCZWdpblg7XG4gIHZhciB0TWludXMgPSB0IC0gcmVCZWdpblg7XG4gIHJldHVybiB0TWludXMgLyB4TWludXM7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgY3VydmUgcHJvZ3Jlc3Mgb2YgdFxyXG4gKiBAcGFyYW0ge0FycmF5fSBiZXppZXJDdXJ2ZSBTdWItY3VydmVcclxuICogQHBhcmFtIHtOdW1iZXJ9IHQgICAgICAgICAgQ3VycmVudCBmcmFtZSB0XHJcbiAqIEByZXR1cm4ge051bWJlcn0gUHJvZ3Jlc3Mgb2YgY3VycmVudCBmcmFtZVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRCZXppZXJDdXJ2ZVRTdGF0ZShfcmVmLCB0KSB7XG4gIHZhciBfcmVmMiA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmLCA0KSxcbiAgICAgIF9yZWYyJCA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMlswXSwgMiksXG4gICAgICBwMCA9IF9yZWYyJFsxXSxcbiAgICAgIF9yZWYyJDIgPSAoMCwgX3NsaWNlZFRvQXJyYXkyW1wiZGVmYXVsdFwiXSkoX3JlZjJbMV0sIDIpLFxuICAgICAgcDEgPSBfcmVmMiQyWzFdLFxuICAgICAgX3JlZjIkMyA9ICgwLCBfc2xpY2VkVG9BcnJheTJbXCJkZWZhdWx0XCJdKShfcmVmMlsyXSwgMiksXG4gICAgICBwMiA9IF9yZWYyJDNbMV0sXG4gICAgICBfcmVmMiQ0ID0gKDAsIF9zbGljZWRUb0FycmF5MltcImRlZmF1bHRcIl0pKF9yZWYyWzNdLCAyKSxcbiAgICAgIHAzID0gX3JlZjIkNFsxXTtcblxuICB2YXIgcG93ID0gTWF0aC5wb3c7XG4gIHZhciB0TWludXMgPSAxIC0gdDtcbiAgdmFyIHJlc3VsdDEgPSBwMCAqIHBvdyh0TWludXMsIDMpO1xuICB2YXIgcmVzdWx0MiA9IDMgKiBwMSAqIHQgKiBwb3codE1pbnVzLCAyKTtcbiAgdmFyIHJlc3VsdDMgPSAzICogcDIgKiBwb3codCwgMikgKiB0TWludXM7XG4gIHZhciByZXN1bHQ0ID0gcDMgKiBwb3codCwgMyk7XG4gIHJldHVybiAxIC0gKHJlc3VsdDEgKyByZXN1bHQyICsgcmVzdWx0MyArIHJlc3VsdDQpO1xufVxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBHZXQgdHJhbnNpdGlvbiBzdGF0ZSBhY2NvcmRpbmcgdG8gZnJhbWUgcHJvZ3Jlc3NcclxuICogQHBhcmFtIHtBbnl9IHN0YXJ0U3RhdGUgICBUcmFuc2l0aW9uIHN0YXJ0IHN0YXRlXHJcbiAqIEBwYXJhbSB7QW55fSBlbmRTdGF0ZSAgICAgVHJhbnNpdGlvbiBlbmQgc3RhdGVcclxuICogQHBhcmFtIHtBcnJheX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZSBwcm9ncmVzc1xyXG4gKiBAcmV0dXJuIHtBcnJheX0gVHJhbnNpdGlvbiBmcmFtZSBzdGF0ZVxyXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRUcmFuc2l0aW9uU3RhdGUoYmVnaW4sIGVuZCwgZnJhbWVTdGF0ZSkge1xuICB2YXIgc3RhdGVUeXBlID0gJ29iamVjdCc7XG4gIGlmICh0eXBlb2YgYmVnaW4gPT09ICdudW1iZXInKSBzdGF0ZVR5cGUgPSAnbnVtYmVyJztcbiAgaWYgKGJlZ2luIGluc3RhbmNlb2YgQXJyYXkpIHN0YXRlVHlwZSA9ICdhcnJheSc7XG4gIGlmIChzdGF0ZVR5cGUgPT09ICdudW1iZXInKSByZXR1cm4gZ2V0TnVtYmVyVHJhbnNpdGlvblN0YXRlKGJlZ2luLCBlbmQsIGZyYW1lU3RhdGUpO1xuICBpZiAoc3RhdGVUeXBlID09PSAnYXJyYXknKSByZXR1cm4gZ2V0QXJyYXlUcmFuc2l0aW9uU3RhdGUoYmVnaW4sIGVuZCwgZnJhbWVTdGF0ZSk7XG4gIGlmIChzdGF0ZVR5cGUgPT09ICdvYmplY3QnKSByZXR1cm4gZ2V0T2JqZWN0VHJhbnNpdGlvblN0YXRlKGJlZ2luLCBlbmQsIGZyYW1lU3RhdGUpO1xuICByZXR1cm4gZnJhbWVTdGF0ZS5tYXAoZnVuY3Rpb24gKHQpIHtcbiAgICByZXR1cm4gZW5kO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSB0cmFuc2l0aW9uIGRhdGEgb2YgdGhlIG51bWJlciB0eXBlXHJcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydFN0YXRlIFRyYW5zaXRpb24gc3RhcnQgc3RhdGVcclxuICogQHBhcmFtIHtOdW1iZXJ9IGVuZFN0YXRlICAgVHJhbnNpdGlvbiBlbmQgc3RhdGVcclxuICogQHBhcmFtIHtBcnJheX0gZnJhbWVTdGF0ZSAgRnJhbWUgc3RhdGUgcHJvZ3Jlc3NcclxuICogQHJldHVybiB7QXJyYXl9IFRyYW5zaXRpb24gZnJhbWUgc3RhdGVcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0TnVtYmVyVHJhbnNpdGlvblN0YXRlKGJlZ2luLCBlbmQsIGZyYW1lU3RhdGUpIHtcbiAgdmFyIG1pbnVzID0gZW5kIC0gYmVnaW47XG4gIHJldHVybiBmcmFtZVN0YXRlLm1hcChmdW5jdGlvbiAocykge1xuICAgIHJldHVybiBiZWdpbiArIG1pbnVzICogcztcbiAgfSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgdHJhbnNpdGlvbiBkYXRhIG9mIHRoZSBhcnJheSB0eXBlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IHN0YXJ0U3RhdGUgVHJhbnNpdGlvbiBzdGFydCBzdGF0ZVxyXG4gKiBAcGFyYW0ge0FycmF5fSBlbmRTdGF0ZSAgIFRyYW5zaXRpb24gZW5kIHN0YXRlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUgcHJvZ3Jlc3NcclxuICogQHJldHVybiB7QXJyYXl9IFRyYW5zaXRpb24gZnJhbWUgc3RhdGVcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0QXJyYXlUcmFuc2l0aW9uU3RhdGUoYmVnaW4sIGVuZCwgZnJhbWVTdGF0ZSkge1xuICB2YXIgbWludXMgPSBlbmQubWFwKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgaWYgKHR5cGVvZiB2ICE9PSAnbnVtYmVyJykgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB2IC0gYmVnaW5baV07XG4gIH0pO1xuICByZXR1cm4gZnJhbWVTdGF0ZS5tYXAoZnVuY3Rpb24gKHMpIHtcbiAgICByZXR1cm4gbWludXMubWFwKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICBpZiAodiA9PT0gZmFsc2UpIHJldHVybiBlbmRbaV07XG4gICAgICByZXR1cm4gYmVnaW5baV0gKyB2ICogcztcbiAgICB9KTtcbiAgfSk7XG59XG4vKipcclxuICogQGRlc2NyaXB0aW9uIEdldCB0aGUgdHJhbnNpdGlvbiBkYXRhIG9mIHRoZSBvYmplY3QgdHlwZVxyXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhcnRTdGF0ZSBUcmFuc2l0aW9uIHN0YXJ0IHN0YXRlXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBlbmRTdGF0ZSAgIFRyYW5zaXRpb24gZW5kIHN0YXRlXHJcbiAqIEBwYXJhbSB7QXJyYXl9IGZyYW1lU3RhdGUgIEZyYW1lIHN0YXRlIHByb2dyZXNzXHJcbiAqIEByZXR1cm4ge0FycmF5fSBUcmFuc2l0aW9uIGZyYW1lIHN0YXRlXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldE9iamVjdFRyYW5zaXRpb25TdGF0ZShiZWdpbiwgZW5kLCBmcmFtZVN0YXRlKSB7XG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoZW5kKTtcbiAgdmFyIGJlZ2luVmFsdWUgPSBrZXlzLm1hcChmdW5jdGlvbiAoaykge1xuICAgIHJldHVybiBiZWdpbltrXTtcbiAgfSk7XG4gIHZhciBlbmRWYWx1ZSA9IGtleXMubWFwKGZ1bmN0aW9uIChrKSB7XG4gICAgcmV0dXJuIGVuZFtrXTtcbiAgfSk7XG4gIHZhciBhcnJheVN0YXRlID0gZ2V0QXJyYXlUcmFuc2l0aW9uU3RhdGUoYmVnaW5WYWx1ZSwgZW5kVmFsdWUsIGZyYW1lU3RhdGUpO1xuICByZXR1cm4gYXJyYXlTdGF0ZS5tYXAoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICB2YXIgZnJhbWVEYXRhID0ge307XG4gICAgaXRlbS5mb3JFYWNoKGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gZnJhbWVEYXRhW2tleXNbaV1dID0gdjtcbiAgICB9KTtcbiAgICByZXR1cm4gZnJhbWVEYXRhO1xuICB9KTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gR2V0IHRoZSB0cmFuc2l0aW9uIHN0YXRlIGRhdGEgYnkgcmVjdXJzaW9uXHJcbiAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBzdGFydFN0YXRlIFRyYW5zaXRpb24gc3RhcnQgc3RhdGVcclxuICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGVuZFN0YXRlICAgVHJhbnNpdGlvbiBlbmQgc3RhdGVcclxuICogQHBhcmFtIHtBcnJheX0gZnJhbWVTdGF0ZSAgICAgICAgRnJhbWUgc3RhdGUgcHJvZ3Jlc3NcclxuICogQHJldHVybiB7QXJyYXl9IFRyYW5zaXRpb24gZnJhbWUgc3RhdGVcclxuICovXG5cblxuZnVuY3Rpb24gcmVjdXJzaW9uVHJhbnNpdGlvblN0YXRlKGJlZ2luLCBlbmQsIGZyYW1lU3RhdGUpIHtcbiAgdmFyIHN0YXRlID0gZ2V0VHJhbnNpdGlvblN0YXRlKGJlZ2luLCBlbmQsIGZyYW1lU3RhdGUpO1xuXG4gIHZhciBfbG9vcCA9IGZ1bmN0aW9uIF9sb29wKGtleSkge1xuICAgIHZhciBiVGVtcCA9IGJlZ2luW2tleV07XG4gICAgdmFyIGVUZW1wID0gZW5kW2tleV07XG4gICAgaWYgKCgwLCBfdHlwZW9mMltcImRlZmF1bHRcIl0pKGVUZW1wKSAhPT0gJ29iamVjdCcpIHJldHVybiBcImNvbnRpbnVlXCI7XG4gICAgdmFyIGRhdGEgPSByZWN1cnNpb25UcmFuc2l0aW9uU3RhdGUoYlRlbXAsIGVUZW1wLCBmcmFtZVN0YXRlKTtcbiAgICBzdGF0ZS5mb3JFYWNoKGZ1bmN0aW9uIChmcywgaSkge1xuICAgICAgcmV0dXJuIGZzW2tleV0gPSBkYXRhW2ldO1xuICAgIH0pO1xuICB9O1xuXG4gIGZvciAodmFyIGtleSBpbiBlbmQpIHtcbiAgICB2YXIgX3JldCA9IF9sb29wKGtleSk7XG5cbiAgICBpZiAoX3JldCA9PT0gXCJjb250aW51ZVwiKSBjb250aW51ZTtcbiAgfVxuXG4gIHJldHVybiBzdGF0ZTtcbn1cbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gSW5qZWN0IG5ldyBjdXJ2ZSBpbnRvIGN1cnZlcyBhcyBjb25maWdcclxuICogQHBhcmFtIHtBbnl9IGtleSAgICAgVGhlIGtleSBvZiBjdXJ2ZVxyXG4gKiBAcGFyYW0ge0FycmF5fSBjdXJ2ZSBCZXppZXIgY3VydmUgZGF0YVxyXG4gKiBAcmV0dXJuIHtVbmRlZmluZWR9IE5vIHJldHVyblxyXG4gKi9cblxuXG5mdW5jdGlvbiBpbmplY3ROZXdDdXJ2ZShrZXksIGN1cnZlKSB7XG4gIGlmICgha2V5IHx8ICFjdXJ2ZSkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ0luamVjdE5ld0N1cnZlIE1pc3NpbmcgUGFyYW1ldGVycyEnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBfY3VydmVzW1wiZGVmYXVsdFwiXS5zZXQoa2V5LCBjdXJ2ZSk7XG59XG5cbnZhciBfZGVmYXVsdCA9IHRyYW5zaXRpb247XG5leHBvcnRzW1wiZGVmYXVsdFwiXSA9IF9kZWZhdWx0OyIsIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE0LXByZXNlbnQsIEZhY2Vib29rLCBJbmMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxudmFyIHJ1bnRpbWUgPSAoZnVuY3Rpb24gKGV4cG9ydHMpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgdmFyIE9wID0gT2JqZWN0LnByb3RvdHlwZTtcbiAgdmFyIGhhc093biA9IE9wLmhhc093blByb3BlcnR5O1xuICB2YXIgdW5kZWZpbmVkOyAvLyBNb3JlIGNvbXByZXNzaWJsZSB0aGFuIHZvaWQgMC5cbiAgdmFyICRTeW1ib2wgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgPyBTeW1ib2wgOiB7fTtcbiAgdmFyIGl0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5pdGVyYXRvciB8fCBcIkBAaXRlcmF0b3JcIjtcbiAgdmFyIGFzeW5jSXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLmFzeW5jSXRlcmF0b3IgfHwgXCJAQGFzeW5jSXRlcmF0b3JcIjtcbiAgdmFyIHRvU3RyaW5nVGFnU3ltYm9sID0gJFN5bWJvbC50b1N0cmluZ1RhZyB8fCBcIkBAdG9TdHJpbmdUYWdcIjtcblxuICBmdW5jdGlvbiB3cmFwKGlubmVyRm4sIG91dGVyRm4sIHNlbGYsIHRyeUxvY3NMaXN0KSB7XG4gICAgLy8gSWYgb3V0ZXJGbiBwcm92aWRlZCBhbmQgb3V0ZXJGbi5wcm90b3R5cGUgaXMgYSBHZW5lcmF0b3IsIHRoZW4gb3V0ZXJGbi5wcm90b3R5cGUgaW5zdGFuY2VvZiBHZW5lcmF0b3IuXG4gICAgdmFyIHByb3RvR2VuZXJhdG9yID0gb3V0ZXJGbiAmJiBvdXRlckZuLnByb3RvdHlwZSBpbnN0YW5jZW9mIEdlbmVyYXRvciA/IG91dGVyRm4gOiBHZW5lcmF0b3I7XG4gICAgdmFyIGdlbmVyYXRvciA9IE9iamVjdC5jcmVhdGUocHJvdG9HZW5lcmF0b3IucHJvdG90eXBlKTtcbiAgICB2YXIgY29udGV4dCA9IG5ldyBDb250ZXh0KHRyeUxvY3NMaXN0IHx8IFtdKTtcblxuICAgIC8vIFRoZSAuX2ludm9rZSBtZXRob2QgdW5pZmllcyB0aGUgaW1wbGVtZW50YXRpb25zIG9mIHRoZSAubmV4dCxcbiAgICAvLyAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMuXG4gICAgZ2VuZXJhdG9yLl9pbnZva2UgPSBtYWtlSW52b2tlTWV0aG9kKGlubmVyRm4sIHNlbGYsIGNvbnRleHQpO1xuXG4gICAgcmV0dXJuIGdlbmVyYXRvcjtcbiAgfVxuICBleHBvcnRzLndyYXAgPSB3cmFwO1xuXG4gIC8vIFRyeS9jYXRjaCBoZWxwZXIgdG8gbWluaW1pemUgZGVvcHRpbWl6YXRpb25zLiBSZXR1cm5zIGEgY29tcGxldGlvblxuICAvLyByZWNvcmQgbGlrZSBjb250ZXh0LnRyeUVudHJpZXNbaV0uY29tcGxldGlvbi4gVGhpcyBpbnRlcmZhY2UgY291bGRcbiAgLy8gaGF2ZSBiZWVuIChhbmQgd2FzIHByZXZpb3VzbHkpIGRlc2lnbmVkIHRvIHRha2UgYSBjbG9zdXJlIHRvIGJlXG4gIC8vIGludm9rZWQgd2l0aG91dCBhcmd1bWVudHMsIGJ1dCBpbiBhbGwgdGhlIGNhc2VzIHdlIGNhcmUgYWJvdXQgd2VcbiAgLy8gYWxyZWFkeSBoYXZlIGFuIGV4aXN0aW5nIG1ldGhvZCB3ZSB3YW50IHRvIGNhbGwsIHNvIHRoZXJlJ3Mgbm8gbmVlZFxuICAvLyB0byBjcmVhdGUgYSBuZXcgZnVuY3Rpb24gb2JqZWN0LiBXZSBjYW4gZXZlbiBnZXQgYXdheSB3aXRoIGFzc3VtaW5nXG4gIC8vIHRoZSBtZXRob2QgdGFrZXMgZXhhY3RseSBvbmUgYXJndW1lbnQsIHNpbmNlIHRoYXQgaGFwcGVucyB0byBiZSB0cnVlXG4gIC8vIGluIGV2ZXJ5IGNhc2UsIHNvIHdlIGRvbid0IGhhdmUgdG8gdG91Y2ggdGhlIGFyZ3VtZW50cyBvYmplY3QuIFRoZVxuICAvLyBvbmx5IGFkZGl0aW9uYWwgYWxsb2NhdGlvbiByZXF1aXJlZCBpcyB0aGUgY29tcGxldGlvbiByZWNvcmQsIHdoaWNoXG4gIC8vIGhhcyBhIHN0YWJsZSBzaGFwZSBhbmQgc28gaG9wZWZ1bGx5IHNob3VsZCBiZSBjaGVhcCB0byBhbGxvY2F0ZS5cbiAgZnVuY3Rpb24gdHJ5Q2F0Y2goZm4sIG9iaiwgYXJnKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwibm9ybWFsXCIsIGFyZzogZm4uY2FsbChvYmosIGFyZykgfTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiB7IHR5cGU6IFwidGhyb3dcIiwgYXJnOiBlcnIgfTtcbiAgICB9XG4gIH1cblxuICB2YXIgR2VuU3RhdGVTdXNwZW5kZWRTdGFydCA9IFwic3VzcGVuZGVkU3RhcnRcIjtcbiAgdmFyIEdlblN0YXRlU3VzcGVuZGVkWWllbGQgPSBcInN1c3BlbmRlZFlpZWxkXCI7XG4gIHZhciBHZW5TdGF0ZUV4ZWN1dGluZyA9IFwiZXhlY3V0aW5nXCI7XG4gIHZhciBHZW5TdGF0ZUNvbXBsZXRlZCA9IFwiY29tcGxldGVkXCI7XG5cbiAgLy8gUmV0dXJuaW5nIHRoaXMgb2JqZWN0IGZyb20gdGhlIGlubmVyRm4gaGFzIHRoZSBzYW1lIGVmZmVjdCBhc1xuICAvLyBicmVha2luZyBvdXQgb2YgdGhlIGRpc3BhdGNoIHN3aXRjaCBzdGF0ZW1lbnQuXG4gIHZhciBDb250aW51ZVNlbnRpbmVsID0ge307XG5cbiAgLy8gRHVtbXkgY29uc3RydWN0b3IgZnVuY3Rpb25zIHRoYXQgd2UgdXNlIGFzIHRoZSAuY29uc3RydWN0b3IgYW5kXG4gIC8vIC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUgcHJvcGVydGllcyBmb3IgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIEdlbmVyYXRvclxuICAvLyBvYmplY3RzLiBGb3IgZnVsbCBzcGVjIGNvbXBsaWFuY2UsIHlvdSBtYXkgd2lzaCB0byBjb25maWd1cmUgeW91clxuICAvLyBtaW5pZmllciBub3QgdG8gbWFuZ2xlIHRoZSBuYW1lcyBvZiB0aGVzZSB0d28gZnVuY3Rpb25zLlxuICBmdW5jdGlvbiBHZW5lcmF0b3IoKSB7fVxuICBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9XG4gIGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKCkge31cblxuICAvLyBUaGlzIGlzIGEgcG9seWZpbGwgZm9yICVJdGVyYXRvclByb3RvdHlwZSUgZm9yIGVudmlyb25tZW50cyB0aGF0XG4gIC8vIGRvbid0IG5hdGl2ZWx5IHN1cHBvcnQgaXQuXG4gIHZhciBJdGVyYXRvclByb3RvdHlwZSA9IHt9O1xuICBJdGVyYXRvclByb3RvdHlwZVtpdGVyYXRvclN5bWJvbF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgdmFyIGdldFByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mO1xuICB2YXIgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90byAmJiBnZXRQcm90byhnZXRQcm90byh2YWx1ZXMoW10pKSk7XG4gIGlmIChOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAmJlxuICAgICAgTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUgIT09IE9wICYmXG4gICAgICBoYXNPd24uY2FsbChOYXRpdmVJdGVyYXRvclByb3RvdHlwZSwgaXRlcmF0b3JTeW1ib2wpKSB7XG4gICAgLy8gVGhpcyBlbnZpcm9ubWVudCBoYXMgYSBuYXRpdmUgJUl0ZXJhdG9yUHJvdG90eXBlJTsgdXNlIGl0IGluc3RlYWRcbiAgICAvLyBvZiB0aGUgcG9seWZpbGwuXG4gICAgSXRlcmF0b3JQcm90b3R5cGUgPSBOYXRpdmVJdGVyYXRvclByb3RvdHlwZTtcbiAgfVxuXG4gIHZhciBHcCA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLnByb3RvdHlwZSA9XG4gICAgR2VuZXJhdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUpO1xuICBHZW5lcmF0b3JGdW5jdGlvbi5wcm90b3R5cGUgPSBHcC5jb25zdHJ1Y3RvciA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlO1xuICBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEdlbmVyYXRvckZ1bmN0aW9uO1xuICBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZVt0b1N0cmluZ1RhZ1N5bWJvbF0gPVxuICAgIEdlbmVyYXRvckZ1bmN0aW9uLmRpc3BsYXlOYW1lID0gXCJHZW5lcmF0b3JGdW5jdGlvblwiO1xuXG4gIC8vIEhlbHBlciBmb3IgZGVmaW5pbmcgdGhlIC5uZXh0LCAudGhyb3csIGFuZCAucmV0dXJuIG1ldGhvZHMgb2YgdGhlXG4gIC8vIEl0ZXJhdG9yIGludGVyZmFjZSBpbiB0ZXJtcyBvZiBhIHNpbmdsZSAuX2ludm9rZSBtZXRob2QuXG4gIGZ1bmN0aW9uIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhwcm90b3R5cGUpIHtcbiAgICBbXCJuZXh0XCIsIFwidGhyb3dcIiwgXCJyZXR1cm5cIl0uZm9yRWFjaChmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgIHByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24oYXJnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pbnZva2UobWV0aG9kLCBhcmcpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbiA9IGZ1bmN0aW9uKGdlbkZ1bikge1xuICAgIHZhciBjdG9yID0gdHlwZW9mIGdlbkZ1biA9PT0gXCJmdW5jdGlvblwiICYmIGdlbkZ1bi5jb25zdHJ1Y3RvcjtcbiAgICByZXR1cm4gY3RvclxuICAgICAgPyBjdG9yID09PSBHZW5lcmF0b3JGdW5jdGlvbiB8fFxuICAgICAgICAvLyBGb3IgdGhlIG5hdGl2ZSBHZW5lcmF0b3JGdW5jdGlvbiBjb25zdHJ1Y3RvciwgdGhlIGJlc3Qgd2UgY2FuXG4gICAgICAgIC8vIGRvIGlzIHRvIGNoZWNrIGl0cyAubmFtZSBwcm9wZXJ0eS5cbiAgICAgICAgKGN0b3IuZGlzcGxheU5hbWUgfHwgY3Rvci5uYW1lKSA9PT0gXCJHZW5lcmF0b3JGdW5jdGlvblwiXG4gICAgICA6IGZhbHNlO1xuICB9O1xuXG4gIGV4cG9ydHMubWFyayA9IGZ1bmN0aW9uKGdlbkZ1bikge1xuICAgIGlmIChPYmplY3Quc2V0UHJvdG90eXBlT2YpIHtcbiAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihnZW5GdW4sIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ2VuRnVuLl9fcHJvdG9fXyA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlO1xuICAgICAgaWYgKCEodG9TdHJpbmdUYWdTeW1ib2wgaW4gZ2VuRnVuKSkge1xuICAgICAgICBnZW5GdW5bdG9TdHJpbmdUYWdTeW1ib2xdID0gXCJHZW5lcmF0b3JGdW5jdGlvblwiO1xuICAgICAgfVxuICAgIH1cbiAgICBnZW5GdW4ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHcCk7XG4gICAgcmV0dXJuIGdlbkZ1bjtcbiAgfTtcblxuICAvLyBXaXRoaW4gdGhlIGJvZHkgb2YgYW55IGFzeW5jIGZ1bmN0aW9uLCBgYXdhaXQgeGAgaXMgdHJhbnNmb3JtZWQgdG9cbiAgLy8gYHlpZWxkIHJlZ2VuZXJhdG9yUnVudGltZS5hd3JhcCh4KWAsIHNvIHRoYXQgdGhlIHJ1bnRpbWUgY2FuIHRlc3RcbiAgLy8gYGhhc093bi5jYWxsKHZhbHVlLCBcIl9fYXdhaXRcIilgIHRvIGRldGVybWluZSBpZiB0aGUgeWllbGRlZCB2YWx1ZSBpc1xuICAvLyBtZWFudCB0byBiZSBhd2FpdGVkLlxuICBleHBvcnRzLmF3cmFwID0gZnVuY3Rpb24oYXJnKSB7XG4gICAgcmV0dXJuIHsgX19hd2FpdDogYXJnIH07XG4gIH07XG5cbiAgZnVuY3Rpb24gQXN5bmNJdGVyYXRvcihnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIHJlY29yZCA9IHRyeUNhdGNoKGdlbmVyYXRvclttZXRob2RdLCBnZW5lcmF0b3IsIGFyZyk7XG4gICAgICBpZiAocmVjb3JkLnR5cGUgPT09IFwidGhyb3dcIikge1xuICAgICAgICByZWplY3QocmVjb3JkLmFyZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcmVzdWx0ID0gcmVjb3JkLmFyZztcbiAgICAgICAgdmFyIHZhbHVlID0gcmVzdWx0LnZhbHVlO1xuICAgICAgICBpZiAodmFsdWUgJiZcbiAgICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgICAgaGFzT3duLmNhbGwodmFsdWUsIFwiX19hd2FpdFwiKSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodmFsdWUuX19hd2FpdCkudGhlbihmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgICAgaW52b2tlKFwibmV4dFwiLCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICB9LCBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIGludm9rZShcInRocm93XCIsIGVyciwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodmFsdWUpLnRoZW4oZnVuY3Rpb24odW53cmFwcGVkKSB7XG4gICAgICAgICAgLy8gV2hlbiBhIHlpZWxkZWQgUHJvbWlzZSBpcyByZXNvbHZlZCwgaXRzIGZpbmFsIHZhbHVlIGJlY29tZXNcbiAgICAgICAgICAvLyB0aGUgLnZhbHVlIG9mIHRoZSBQcm9taXNlPHt2YWx1ZSxkb25lfT4gcmVzdWx0IGZvciB0aGVcbiAgICAgICAgICAvLyBjdXJyZW50IGl0ZXJhdGlvbi5cbiAgICAgICAgICByZXN1bHQudmFsdWUgPSB1bndyYXBwZWQ7XG4gICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9LCBmdW5jdGlvbihlcnJvcikge1xuICAgICAgICAgIC8vIElmIGEgcmVqZWN0ZWQgUHJvbWlzZSB3YXMgeWllbGRlZCwgdGhyb3cgdGhlIHJlamVjdGlvbiBiYWNrXG4gICAgICAgICAgLy8gaW50byB0aGUgYXN5bmMgZ2VuZXJhdG9yIGZ1bmN0aW9uIHNvIGl0IGNhbiBiZSBoYW5kbGVkIHRoZXJlLlxuICAgICAgICAgIHJldHVybiBpbnZva2UoXCJ0aHJvd1wiLCBlcnJvciwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHByZXZpb3VzUHJvbWlzZTtcblxuICAgIGZ1bmN0aW9uIGVucXVldWUobWV0aG9kLCBhcmcpIHtcbiAgICAgIGZ1bmN0aW9uIGNhbGxJbnZva2VXaXRoTWV0aG9kQW5kQXJnKCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgaW52b2tlKG1ldGhvZCwgYXJnLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHByZXZpb3VzUHJvbWlzZSA9XG4gICAgICAgIC8vIElmIGVucXVldWUgaGFzIGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiB3ZSB3YW50IHRvIHdhaXQgdW50aWxcbiAgICAgICAgLy8gYWxsIHByZXZpb3VzIFByb21pc2VzIGhhdmUgYmVlbiByZXNvbHZlZCBiZWZvcmUgY2FsbGluZyBpbnZva2UsXG4gICAgICAgIC8vIHNvIHRoYXQgcmVzdWx0cyBhcmUgYWx3YXlzIGRlbGl2ZXJlZCBpbiB0aGUgY29ycmVjdCBvcmRlci4gSWZcbiAgICAgICAgLy8gZW5xdWV1ZSBoYXMgbm90IGJlZW4gY2FsbGVkIGJlZm9yZSwgdGhlbiBpdCBpcyBpbXBvcnRhbnQgdG9cbiAgICAgICAgLy8gY2FsbCBpbnZva2UgaW1tZWRpYXRlbHksIHdpdGhvdXQgd2FpdGluZyBvbiBhIGNhbGxiYWNrIHRvIGZpcmUsXG4gICAgICAgIC8vIHNvIHRoYXQgdGhlIGFzeW5jIGdlbmVyYXRvciBmdW5jdGlvbiBoYXMgdGhlIG9wcG9ydHVuaXR5IHRvIGRvXG4gICAgICAgIC8vIGFueSBuZWNlc3Nhcnkgc2V0dXAgaW4gYSBwcmVkaWN0YWJsZSB3YXkuIFRoaXMgcHJlZGljdGFiaWxpdHlcbiAgICAgICAgLy8gaXMgd2h5IHRoZSBQcm9taXNlIGNvbnN0cnVjdG9yIHN5bmNocm9ub3VzbHkgaW52b2tlcyBpdHNcbiAgICAgICAgLy8gZXhlY3V0b3IgY2FsbGJhY2ssIGFuZCB3aHkgYXN5bmMgZnVuY3Rpb25zIHN5bmNocm9ub3VzbHlcbiAgICAgICAgLy8gZXhlY3V0ZSBjb2RlIGJlZm9yZSB0aGUgZmlyc3QgYXdhaXQuIFNpbmNlIHdlIGltcGxlbWVudCBzaW1wbGVcbiAgICAgICAgLy8gYXN5bmMgZnVuY3Rpb25zIGluIHRlcm1zIG9mIGFzeW5jIGdlbmVyYXRvcnMsIGl0IGlzIGVzcGVjaWFsbHlcbiAgICAgICAgLy8gaW1wb3J0YW50IHRvIGdldCB0aGlzIHJpZ2h0LCBldmVuIHRob3VnaCBpdCByZXF1aXJlcyBjYXJlLlxuICAgICAgICBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbihcbiAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZyxcbiAgICAgICAgICAvLyBBdm9pZCBwcm9wYWdhdGluZyBmYWlsdXJlcyB0byBQcm9taXNlcyByZXR1cm5lZCBieSBsYXRlclxuICAgICAgICAgIC8vIGludm9jYXRpb25zIG9mIHRoZSBpdGVyYXRvci5cbiAgICAgICAgICBjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZ1xuICAgICAgICApIDogY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKTtcbiAgICB9XG5cbiAgICAvLyBEZWZpbmUgdGhlIHVuaWZpZWQgaGVscGVyIG1ldGhvZCB0aGF0IGlzIHVzZWQgdG8gaW1wbGVtZW50IC5uZXh0LFxuICAgIC8vIC50aHJvdywgYW5kIC5yZXR1cm4gKHNlZSBkZWZpbmVJdGVyYXRvck1ldGhvZHMpLlxuICAgIHRoaXMuX2ludm9rZSA9IGVucXVldWU7XG4gIH1cblxuICBkZWZpbmVJdGVyYXRvck1ldGhvZHMoQXN5bmNJdGVyYXRvci5wcm90b3R5cGUpO1xuICBBc3luY0l0ZXJhdG9yLnByb3RvdHlwZVthc3luY0l0ZXJhdG9yU3ltYm9sXSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcbiAgZXhwb3J0cy5Bc3luY0l0ZXJhdG9yID0gQXN5bmNJdGVyYXRvcjtcblxuICAvLyBOb3RlIHRoYXQgc2ltcGxlIGFzeW5jIGZ1bmN0aW9ucyBhcmUgaW1wbGVtZW50ZWQgb24gdG9wIG9mXG4gIC8vIEFzeW5jSXRlcmF0b3Igb2JqZWN0czsgdGhleSBqdXN0IHJldHVybiBhIFByb21pc2UgZm9yIHRoZSB2YWx1ZSBvZlxuICAvLyB0aGUgZmluYWwgcmVzdWx0IHByb2R1Y2VkIGJ5IHRoZSBpdGVyYXRvci5cbiAgZXhwb3J0cy5hc3luYyA9IGZ1bmN0aW9uKGlubmVyRm4sIG91dGVyRm4sIHNlbGYsIHRyeUxvY3NMaXN0KSB7XG4gICAgdmFyIGl0ZXIgPSBuZXcgQXN5bmNJdGVyYXRvcihcbiAgICAgIHdyYXAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QpXG4gICAgKTtcblxuICAgIHJldHVybiBleHBvcnRzLmlzR2VuZXJhdG9yRnVuY3Rpb24ob3V0ZXJGbilcbiAgICAgID8gaXRlciAvLyBJZiBvdXRlckZuIGlzIGEgZ2VuZXJhdG9yLCByZXR1cm4gdGhlIGZ1bGwgaXRlcmF0b3IuXG4gICAgICA6IGl0ZXIubmV4dCgpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7XG4gICAgICAgIH0pO1xuICB9O1xuXG4gIGZ1bmN0aW9uIG1ha2VJbnZva2VNZXRob2QoaW5uZXJGbiwgc2VsZiwgY29udGV4dCkge1xuICAgIHZhciBzdGF0ZSA9IEdlblN0YXRlU3VzcGVuZGVkU3RhcnQ7XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gaW52b2tlKG1ldGhvZCwgYXJnKSB7XG4gICAgICBpZiAoc3RhdGUgPT09IEdlblN0YXRlRXhlY3V0aW5nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IHJ1bm5pbmdcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVDb21wbGV0ZWQpIHtcbiAgICAgICAgaWYgKG1ldGhvZCA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgdGhyb3cgYXJnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmUgZm9yZ2l2aW5nLCBwZXIgMjUuMy4zLjMuMyBvZiB0aGUgc3BlYzpcbiAgICAgICAgLy8gaHR0cHM6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLWdlbmVyYXRvcnJlc3VtZVxuICAgICAgICByZXR1cm4gZG9uZVJlc3VsdCgpO1xuICAgICAgfVxuXG4gICAgICBjb250ZXh0Lm1ldGhvZCA9IG1ldGhvZDtcbiAgICAgIGNvbnRleHQuYXJnID0gYXJnO1xuXG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICB2YXIgZGVsZWdhdGUgPSBjb250ZXh0LmRlbGVnYXRlO1xuICAgICAgICBpZiAoZGVsZWdhdGUpIHtcbiAgICAgICAgICB2YXIgZGVsZWdhdGVSZXN1bHQgPSBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTtcbiAgICAgICAgICBpZiAoZGVsZWdhdGVSZXN1bHQpIHtcbiAgICAgICAgICAgIGlmIChkZWxlZ2F0ZVJlc3VsdCA9PT0gQ29udGludWVTZW50aW5lbCkgY29udGludWU7XG4gICAgICAgICAgICByZXR1cm4gZGVsZWdhdGVSZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbnRleHQubWV0aG9kID09PSBcIm5leHRcIikge1xuICAgICAgICAgIC8vIFNldHRpbmcgY29udGV4dC5fc2VudCBmb3IgbGVnYWN5IHN1cHBvcnQgb2YgQmFiZWwnc1xuICAgICAgICAgIC8vIGZ1bmN0aW9uLnNlbnQgaW1wbGVtZW50YXRpb24uXG4gICAgICAgICAgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09IFwidGhyb3dcIikge1xuICAgICAgICAgIGlmIChzdGF0ZSA9PT0gR2VuU3RhdGVTdXNwZW5kZWRTdGFydCkge1xuICAgICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDtcbiAgICAgICAgICAgIHRocm93IGNvbnRleHQuYXJnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoY29udGV4dC5tZXRob2QgPT09IFwicmV0dXJuXCIpIHtcbiAgICAgICAgICBjb250ZXh0LmFicnVwdChcInJldHVyblwiLCBjb250ZXh0LmFyZyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0ZSA9IEdlblN0YXRlRXhlY3V0aW5nO1xuXG4gICAgICAgIHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKHJlY29yZC50eXBlID09PSBcIm5vcm1hbFwiKSB7XG4gICAgICAgICAgLy8gSWYgYW4gZXhjZXB0aW9uIGlzIHRocm93biBmcm9tIGlubmVyRm4sIHdlIGxlYXZlIHN0YXRlID09PVxuICAgICAgICAgIC8vIEdlblN0YXRlRXhlY3V0aW5nIGFuZCBsb29wIGJhY2sgZm9yIGFub3RoZXIgaW52b2NhdGlvbi5cbiAgICAgICAgICBzdGF0ZSA9IGNvbnRleHQuZG9uZVxuICAgICAgICAgICAgPyBHZW5TdGF0ZUNvbXBsZXRlZFxuICAgICAgICAgICAgOiBHZW5TdGF0ZVN1c3BlbmRlZFlpZWxkO1xuXG4gICAgICAgICAgaWYgKHJlY29yZC5hcmcgPT09IENvbnRpbnVlU2VudGluZWwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogcmVjb3JkLmFyZyxcbiAgICAgICAgICAgIGRvbmU6IGNvbnRleHQuZG9uZVxuICAgICAgICAgIH07XG5cbiAgICAgICAgfSBlbHNlIGlmIChyZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgc3RhdGUgPSBHZW5TdGF0ZUNvbXBsZXRlZDtcbiAgICAgICAgICAvLyBEaXNwYXRjaCB0aGUgZXhjZXB0aW9uIGJ5IGxvb3BpbmcgYmFjayBhcm91bmQgdG8gdGhlXG4gICAgICAgICAgLy8gY29udGV4dC5kaXNwYXRjaEV4Y2VwdGlvbihjb250ZXh0LmFyZykgY2FsbCBhYm92ZS5cbiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIjtcbiAgICAgICAgICBjb250ZXh0LmFyZyA9IHJlY29yZC5hcmc7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQ2FsbCBkZWxlZ2F0ZS5pdGVyYXRvcltjb250ZXh0Lm1ldGhvZF0oY29udGV4dC5hcmcpIGFuZCBoYW5kbGUgdGhlXG4gIC8vIHJlc3VsdCwgZWl0aGVyIGJ5IHJldHVybmluZyBhIHsgdmFsdWUsIGRvbmUgfSByZXN1bHQgZnJvbSB0aGVcbiAgLy8gZGVsZWdhdGUgaXRlcmF0b3IsIG9yIGJ5IG1vZGlmeWluZyBjb250ZXh0Lm1ldGhvZCBhbmQgY29udGV4dC5hcmcsXG4gIC8vIHNldHRpbmcgY29udGV4dC5kZWxlZ2F0ZSB0byBudWxsLCBhbmQgcmV0dXJuaW5nIHRoZSBDb250aW51ZVNlbnRpbmVsLlxuICBmdW5jdGlvbiBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIG1ldGhvZCA9IGRlbGVnYXRlLml0ZXJhdG9yW2NvbnRleHQubWV0aG9kXTtcbiAgICBpZiAobWV0aG9kID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIEEgLnRocm93IG9yIC5yZXR1cm4gd2hlbiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIG5vIC50aHJvd1xuICAgICAgLy8gbWV0aG9kIGFsd2F5cyB0ZXJtaW5hdGVzIHRoZSB5aWVsZCogbG9vcC5cbiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsO1xuXG4gICAgICBpZiAoY29udGV4dC5tZXRob2QgPT09IFwidGhyb3dcIikge1xuICAgICAgICAvLyBOb3RlOiBbXCJyZXR1cm5cIl0gbXVzdCBiZSB1c2VkIGZvciBFUzMgcGFyc2luZyBjb21wYXRpYmlsaXR5LlxuICAgICAgICBpZiAoZGVsZWdhdGUuaXRlcmF0b3JbXCJyZXR1cm5cIl0pIHtcbiAgICAgICAgICAvLyBJZiB0aGUgZGVsZWdhdGUgaXRlcmF0b3IgaGFzIGEgcmV0dXJuIG1ldGhvZCwgZ2l2ZSBpdCBhXG4gICAgICAgICAgLy8gY2hhbmNlIHRvIGNsZWFuIHVwLlxuICAgICAgICAgIGNvbnRleHQubWV0aG9kID0gXCJyZXR1cm5cIjtcbiAgICAgICAgICBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBtYXliZUludm9rZURlbGVnYXRlKGRlbGVnYXRlLCBjb250ZXh0KTtcblxuICAgICAgICAgIGlmIChjb250ZXh0Lm1ldGhvZCA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgICAvLyBJZiBtYXliZUludm9rZURlbGVnYXRlKGNvbnRleHQpIGNoYW5nZWQgY29udGV4dC5tZXRob2QgZnJvbVxuICAgICAgICAgICAgLy8gXCJyZXR1cm5cIiB0byBcInRocm93XCIsIGxldCB0aGF0IG92ZXJyaWRlIHRoZSBUeXBlRXJyb3IgYmVsb3cuXG4gICAgICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIjtcbiAgICAgICAgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgIFwiVGhlIGl0ZXJhdG9yIGRvZXMgbm90IHByb3ZpZGUgYSAndGhyb3cnIG1ldGhvZFwiKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgfVxuXG4gICAgdmFyIHJlY29yZCA9IHRyeUNhdGNoKG1ldGhvZCwgZGVsZWdhdGUuaXRlcmF0b3IsIGNvbnRleHQuYXJnKTtcblxuICAgIGlmIChyZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIjtcbiAgICAgIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZztcbiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsO1xuICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgfVxuXG4gICAgdmFyIGluZm8gPSByZWNvcmQuYXJnO1xuXG4gICAgaWYgKCEgaW5mbykge1xuICAgICAgY29udGV4dC5tZXRob2QgPSBcInRocm93XCI7XG4gICAgICBjb250ZXh0LmFyZyA9IG5ldyBUeXBlRXJyb3IoXCJpdGVyYXRvciByZXN1bHQgaXMgbm90IGFuIG9iamVjdFwiKTtcbiAgICAgIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsO1xuICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgfVxuXG4gICAgaWYgKGluZm8uZG9uZSkge1xuICAgICAgLy8gQXNzaWduIHRoZSByZXN1bHQgb2YgdGhlIGZpbmlzaGVkIGRlbGVnYXRlIHRvIHRoZSB0ZW1wb3JhcnlcbiAgICAgIC8vIHZhcmlhYmxlIHNwZWNpZmllZCBieSBkZWxlZ2F0ZS5yZXN1bHROYW1lIChzZWUgZGVsZWdhdGVZaWVsZCkuXG4gICAgICBjb250ZXh0W2RlbGVnYXRlLnJlc3VsdE5hbWVdID0gaW5mby52YWx1ZTtcblxuICAgICAgLy8gUmVzdW1lIGV4ZWN1dGlvbiBhdCB0aGUgZGVzaXJlZCBsb2NhdGlvbiAoc2VlIGRlbGVnYXRlWWllbGQpLlxuICAgICAgY29udGV4dC5uZXh0ID0gZGVsZWdhdGUubmV4dExvYztcblxuICAgICAgLy8gSWYgY29udGV4dC5tZXRob2Qgd2FzIFwidGhyb3dcIiBidXQgdGhlIGRlbGVnYXRlIGhhbmRsZWQgdGhlXG4gICAgICAvLyBleGNlcHRpb24sIGxldCB0aGUgb3V0ZXIgZ2VuZXJhdG9yIHByb2NlZWQgbm9ybWFsbHkuIElmXG4gICAgICAvLyBjb250ZXh0Lm1ldGhvZCB3YXMgXCJuZXh0XCIsIGZvcmdldCBjb250ZXh0LmFyZyBzaW5jZSBpdCBoYXMgYmVlblxuICAgICAgLy8gXCJjb25zdW1lZFwiIGJ5IHRoZSBkZWxlZ2F0ZSBpdGVyYXRvci4gSWYgY29udGV4dC5tZXRob2Qgd2FzXG4gICAgICAvLyBcInJldHVyblwiLCBhbGxvdyB0aGUgb3JpZ2luYWwgLnJldHVybiBjYWxsIHRvIGNvbnRpbnVlIGluIHRoZVxuICAgICAgLy8gb3V0ZXIgZ2VuZXJhdG9yLlxuICAgICAgaWYgKGNvbnRleHQubWV0aG9kICE9PSBcInJldHVyblwiKSB7XG4gICAgICAgIGNvbnRleHQubWV0aG9kID0gXCJuZXh0XCI7XG4gICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlLXlpZWxkIHRoZSByZXN1bHQgcmV0dXJuZWQgYnkgdGhlIGRlbGVnYXRlIG1ldGhvZC5cbiAgICAgIHJldHVybiBpbmZvO1xuICAgIH1cblxuICAgIC8vIFRoZSBkZWxlZ2F0ZSBpdGVyYXRvciBpcyBmaW5pc2hlZCwgc28gZm9yZ2V0IGl0IGFuZCBjb250aW51ZSB3aXRoXG4gICAgLy8gdGhlIG91dGVyIGdlbmVyYXRvci5cbiAgICBjb250ZXh0LmRlbGVnYXRlID0gbnVsbDtcbiAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDtcbiAgfVxuXG4gIC8vIERlZmluZSBHZW5lcmF0b3IucHJvdG90eXBlLntuZXh0LHRocm93LHJldHVybn0gaW4gdGVybXMgb2YgdGhlXG4gIC8vIHVuaWZpZWQgLl9pbnZva2UgaGVscGVyIG1ldGhvZC5cbiAgZGVmaW5lSXRlcmF0b3JNZXRob2RzKEdwKTtcblxuICBHcFt0b1N0cmluZ1RhZ1N5bWJvbF0gPSBcIkdlbmVyYXRvclwiO1xuXG4gIC8vIEEgR2VuZXJhdG9yIHNob3VsZCBhbHdheXMgcmV0dXJuIGl0c2VsZiBhcyB0aGUgaXRlcmF0b3Igb2JqZWN0IHdoZW4gdGhlXG4gIC8vIEBAaXRlcmF0b3IgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGl0LiBTb21lIGJyb3dzZXJzJyBpbXBsZW1lbnRhdGlvbnMgb2YgdGhlXG4gIC8vIGl0ZXJhdG9yIHByb3RvdHlwZSBjaGFpbiBpbmNvcnJlY3RseSBpbXBsZW1lbnQgdGhpcywgY2F1c2luZyB0aGUgR2VuZXJhdG9yXG4gIC8vIG9iamVjdCB0byBub3QgYmUgcmV0dXJuZWQgZnJvbSB0aGlzIGNhbGwuIFRoaXMgZW5zdXJlcyB0aGF0IGRvZXNuJ3QgaGFwcGVuLlxuICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL3JlZ2VuZXJhdG9yL2lzc3Vlcy8yNzQgZm9yIG1vcmUgZGV0YWlscy5cbiAgR3BbaXRlcmF0b3JTeW1ib2xdID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgR3AudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXCJbb2JqZWN0IEdlbmVyYXRvcl1cIjtcbiAgfTtcblxuICBmdW5jdGlvbiBwdXNoVHJ5RW50cnkobG9jcykge1xuICAgIHZhciBlbnRyeSA9IHsgdHJ5TG9jOiBsb2NzWzBdIH07XG5cbiAgICBpZiAoMSBpbiBsb2NzKSB7XG4gICAgICBlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV07XG4gICAgfVxuXG4gICAgaWYgKDIgaW4gbG9jcykge1xuICAgICAgZW50cnkuZmluYWxseUxvYyA9IGxvY3NbMl07XG4gICAgICBlbnRyeS5hZnRlckxvYyA9IGxvY3NbM107XG4gICAgfVxuXG4gICAgdGhpcy50cnlFbnRyaWVzLnB1c2goZW50cnkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzZXRUcnlFbnRyeShlbnRyeSkge1xuICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uIHx8IHt9O1xuICAgIHJlY29yZC50eXBlID0gXCJub3JtYWxcIjtcbiAgICBkZWxldGUgcmVjb3JkLmFyZztcbiAgICBlbnRyeS5jb21wbGV0aW9uID0gcmVjb3JkO1xuICB9XG5cbiAgZnVuY3Rpb24gQ29udGV4dCh0cnlMb2NzTGlzdCkge1xuICAgIC8vIFRoZSByb290IGVudHJ5IG9iamVjdCAoZWZmZWN0aXZlbHkgYSB0cnkgc3RhdGVtZW50IHdpdGhvdXQgYSBjYXRjaFxuICAgIC8vIG9yIGEgZmluYWxseSBibG9jaykgZ2l2ZXMgdXMgYSBwbGFjZSB0byBzdG9yZSB2YWx1ZXMgdGhyb3duIGZyb21cbiAgICAvLyBsb2NhdGlvbnMgd2hlcmUgdGhlcmUgaXMgbm8gZW5jbG9zaW5nIHRyeSBzdGF0ZW1lbnQuXG4gICAgdGhpcy50cnlFbnRyaWVzID0gW3sgdHJ5TG9jOiBcInJvb3RcIiB9XTtcbiAgICB0cnlMb2NzTGlzdC5mb3JFYWNoKHB1c2hUcnlFbnRyeSwgdGhpcyk7XG4gICAgdGhpcy5yZXNldCh0cnVlKTtcbiAgfVxuXG4gIGV4cG9ydHMua2V5cyA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAga2V5cy5wdXNoKGtleSk7XG4gICAgfVxuICAgIGtleXMucmV2ZXJzZSgpO1xuXG4gICAgLy8gUmF0aGVyIHRoYW4gcmV0dXJuaW5nIGFuIG9iamVjdCB3aXRoIGEgbmV4dCBtZXRob2QsIHdlIGtlZXBcbiAgICAvLyB0aGluZ3Mgc2ltcGxlIGFuZCByZXR1cm4gdGhlIG5leHQgZnVuY3Rpb24gaXRzZWxmLlxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgd2hpbGUgKGtleXMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBrZXlzLnBvcCgpO1xuICAgICAgICBpZiAoa2V5IGluIG9iamVjdCkge1xuICAgICAgICAgIG5leHQudmFsdWUgPSBrZXk7XG4gICAgICAgICAgbmV4dC5kb25lID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gVG8gYXZvaWQgY3JlYXRpbmcgYW4gYWRkaXRpb25hbCBvYmplY3QsIHdlIGp1c3QgaGFuZyB0aGUgLnZhbHVlXG4gICAgICAvLyBhbmQgLmRvbmUgcHJvcGVydGllcyBvZmYgdGhlIG5leHQgZnVuY3Rpb24gb2JqZWN0IGl0c2VsZi4gVGhpc1xuICAgICAgLy8gYWxzbyBlbnN1cmVzIHRoYXQgdGhlIG1pbmlmaWVyIHdpbGwgbm90IGFub255bWl6ZSB0aGUgZnVuY3Rpb24uXG4gICAgICBuZXh0LmRvbmUgPSB0cnVlO1xuICAgICAgcmV0dXJuIG5leHQ7XG4gICAgfTtcbiAgfTtcblxuICBmdW5jdGlvbiB2YWx1ZXMoaXRlcmFibGUpIHtcbiAgICBpZiAoaXRlcmFibGUpIHtcbiAgICAgIHZhciBpdGVyYXRvck1ldGhvZCA9IGl0ZXJhYmxlW2l0ZXJhdG9yU3ltYm9sXTtcbiAgICAgIGlmIChpdGVyYXRvck1ldGhvZCkge1xuICAgICAgICByZXR1cm4gaXRlcmF0b3JNZXRob2QuY2FsbChpdGVyYWJsZSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgaXRlcmFibGUubmV4dCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIHJldHVybiBpdGVyYWJsZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc05hTihpdGVyYWJsZS5sZW5ndGgpKSB7XG4gICAgICAgIHZhciBpID0gLTEsIG5leHQgPSBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgICAgIHdoaWxlICgrK2kgPCBpdGVyYWJsZS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd24uY2FsbChpdGVyYWJsZSwgaSkpIHtcbiAgICAgICAgICAgICAgbmV4dC52YWx1ZSA9IGl0ZXJhYmxlW2ldO1xuICAgICAgICAgICAgICBuZXh0LmRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbmV4dC52YWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBuZXh0LmRvbmUgPSB0cnVlO1xuXG4gICAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIG5leHQubmV4dCA9IG5leHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIGFuIGl0ZXJhdG9yIHdpdGggbm8gdmFsdWVzLlxuICAgIHJldHVybiB7IG5leHQ6IGRvbmVSZXN1bHQgfTtcbiAgfVxuICBleHBvcnRzLnZhbHVlcyA9IHZhbHVlcztcblxuICBmdW5jdGlvbiBkb25lUmVzdWx0KCkge1xuICAgIHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWUgfTtcbiAgfVxuXG4gIENvbnRleHQucHJvdG90eXBlID0ge1xuICAgIGNvbnN0cnVjdG9yOiBDb250ZXh0LFxuXG4gICAgcmVzZXQ6IGZ1bmN0aW9uKHNraXBUZW1wUmVzZXQpIHtcbiAgICAgIHRoaXMucHJldiA9IDA7XG4gICAgICB0aGlzLm5leHQgPSAwO1xuICAgICAgLy8gUmVzZXR0aW5nIGNvbnRleHQuX3NlbnQgZm9yIGxlZ2FjeSBzdXBwb3J0IG9mIEJhYmVsJ3NcbiAgICAgIC8vIGZ1bmN0aW9uLnNlbnQgaW1wbGVtZW50YXRpb24uXG4gICAgICB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5kb25lID0gZmFsc2U7XG4gICAgICB0aGlzLmRlbGVnYXRlID0gbnVsbDtcblxuICAgICAgdGhpcy5tZXRob2QgPSBcIm5leHRcIjtcbiAgICAgIHRoaXMuYXJnID0gdW5kZWZpbmVkO1xuXG4gICAgICB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KTtcblxuICAgICAgaWYgKCFza2lwVGVtcFJlc2V0KSB7XG4gICAgICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcykge1xuICAgICAgICAgIC8vIE5vdCBzdXJlIGFib3V0IHRoZSBvcHRpbWFsIG9yZGVyIG9mIHRoZXNlIGNvbmRpdGlvbnM6XG4gICAgICAgICAgaWYgKG5hbWUuY2hhckF0KDApID09PSBcInRcIiAmJlxuICAgICAgICAgICAgICBoYXNPd24uY2FsbCh0aGlzLCBuYW1lKSAmJlxuICAgICAgICAgICAgICAhaXNOYU4oK25hbWUuc2xpY2UoMSkpKSB7XG4gICAgICAgICAgICB0aGlzW25hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBzdG9wOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuZG9uZSA9IHRydWU7XG5cbiAgICAgIHZhciByb290RW50cnkgPSB0aGlzLnRyeUVudHJpZXNbMF07XG4gICAgICB2YXIgcm9vdFJlY29yZCA9IHJvb3RFbnRyeS5jb21wbGV0aW9uO1xuICAgICAgaWYgKHJvb3RSZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgIHRocm93IHJvb3RSZWNvcmQuYXJnO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5ydmFsO1xuICAgIH0sXG5cbiAgICBkaXNwYXRjaEV4Y2VwdGlvbjogZnVuY3Rpb24oZXhjZXB0aW9uKSB7XG4gICAgICBpZiAodGhpcy5kb25lKSB7XG4gICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgIH1cblxuICAgICAgdmFyIGNvbnRleHQgPSB0aGlzO1xuICAgICAgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7XG4gICAgICAgIHJlY29yZC50eXBlID0gXCJ0aHJvd1wiO1xuICAgICAgICByZWNvcmQuYXJnID0gZXhjZXB0aW9uO1xuICAgICAgICBjb250ZXh0Lm5leHQgPSBsb2M7XG5cbiAgICAgICAgaWYgKGNhdWdodCkge1xuICAgICAgICAgIC8vIElmIHRoZSBkaXNwYXRjaGVkIGV4Y2VwdGlvbiB3YXMgY2F1Z2h0IGJ5IGEgY2F0Y2ggYmxvY2ssXG4gICAgICAgICAgLy8gdGhlbiBsZXQgdGhhdCBjYXRjaCBibG9jayBoYW5kbGUgdGhlIGV4Y2VwdGlvbiBub3JtYWxseS5cbiAgICAgICAgICBjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiO1xuICAgICAgICAgIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICEhIGNhdWdodDtcbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07XG4gICAgICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uO1xuXG4gICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09IFwicm9vdFwiKSB7XG4gICAgICAgICAgLy8gRXhjZXB0aW9uIHRocm93biBvdXRzaWRlIG9mIGFueSB0cnkgYmxvY2sgdGhhdCBjb3VsZCBoYW5kbGVcbiAgICAgICAgICAvLyBpdCwgc28gc2V0IHRoZSBjb21wbGV0aW9uIHZhbHVlIG9mIHRoZSBlbnRpcmUgZnVuY3Rpb24gdG9cbiAgICAgICAgICAvLyB0aHJvdyB0aGUgZXhjZXB0aW9uLlxuICAgICAgICAgIHJldHVybiBoYW5kbGUoXCJlbmRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikge1xuICAgICAgICAgIHZhciBoYXNDYXRjaCA9IGhhc093bi5jYWxsKGVudHJ5LCBcImNhdGNoTG9jXCIpO1xuICAgICAgICAgIHZhciBoYXNGaW5hbGx5ID0gaGFzT3duLmNhbGwoZW50cnksIFwiZmluYWxseUxvY1wiKTtcblxuICAgICAgICAgIGlmIChoYXNDYXRjaCAmJiBoYXNGaW5hbGx5KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgdHJ1ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH0gZWxzZSBpZiAoaGFzQ2F0Y2gpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnByZXYgPCBlbnRyeS5jYXRjaExvYykge1xuICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlKGVudHJ5LmNhdGNoTG9jLCB0cnVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH0gZWxzZSBpZiAoaGFzRmluYWxseSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseVwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuXG4gICAgYWJydXB0OiBmdW5jdGlvbih0eXBlLCBhcmcpIHtcbiAgICAgIGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldO1xuICAgICAgICBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldiAmJlxuICAgICAgICAgICAgaGFzT3duLmNhbGwoZW50cnksIFwiZmluYWxseUxvY1wiKSAmJlxuICAgICAgICAgICAgdGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykge1xuICAgICAgICAgIHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZmluYWxseUVudHJ5ICYmXG4gICAgICAgICAgKHR5cGUgPT09IFwiYnJlYWtcIiB8fFxuICAgICAgICAgICB0eXBlID09PSBcImNvbnRpbnVlXCIpICYmXG4gICAgICAgICAgZmluYWxseUVudHJ5LnRyeUxvYyA8PSBhcmcgJiZcbiAgICAgICAgICBhcmcgPD0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MpIHtcbiAgICAgICAgLy8gSWdub3JlIHRoZSBmaW5hbGx5IGVudHJ5IGlmIGNvbnRyb2wgaXMgbm90IGp1bXBpbmcgdG8gYVxuICAgICAgICAvLyBsb2NhdGlvbiBvdXRzaWRlIHRoZSB0cnkvY2F0Y2ggYmxvY2suXG4gICAgICAgIGZpbmFsbHlFbnRyeSA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHZhciByZWNvcmQgPSBmaW5hbGx5RW50cnkgPyBmaW5hbGx5RW50cnkuY29tcGxldGlvbiA6IHt9O1xuICAgICAgcmVjb3JkLnR5cGUgPSB0eXBlO1xuICAgICAgcmVjb3JkLmFyZyA9IGFyZztcblxuICAgICAgaWYgKGZpbmFsbHlFbnRyeSkge1xuICAgICAgICB0aGlzLm1ldGhvZCA9IFwibmV4dFwiO1xuICAgICAgICB0aGlzLm5leHQgPSBmaW5hbGx5RW50cnkuZmluYWxseUxvYztcbiAgICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLmNvbXBsZXRlKHJlY29yZCk7XG4gICAgfSxcblxuICAgIGNvbXBsZXRlOiBmdW5jdGlvbihyZWNvcmQsIGFmdGVyTG9jKSB7XG4gICAgICBpZiAocmVjb3JkLnR5cGUgPT09IFwidGhyb3dcIikge1xuICAgICAgICB0aHJvdyByZWNvcmQuYXJnO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVjb3JkLnR5cGUgPT09IFwiYnJlYWtcIiB8fFxuICAgICAgICAgIHJlY29yZC50eXBlID09PSBcImNvbnRpbnVlXCIpIHtcbiAgICAgICAgdGhpcy5uZXh0ID0gcmVjb3JkLmFyZztcbiAgICAgIH0gZWxzZSBpZiAocmVjb3JkLnR5cGUgPT09IFwicmV0dXJuXCIpIHtcbiAgICAgICAgdGhpcy5ydmFsID0gdGhpcy5hcmcgPSByZWNvcmQuYXJnO1xuICAgICAgICB0aGlzLm1ldGhvZCA9IFwicmV0dXJuXCI7XG4gICAgICAgIHRoaXMubmV4dCA9IFwiZW5kXCI7XG4gICAgICB9IGVsc2UgaWYgKHJlY29yZC50eXBlID09PSBcIm5vcm1hbFwiICYmIGFmdGVyTG9jKSB7XG4gICAgICAgIHRoaXMubmV4dCA9IGFmdGVyTG9jO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDtcbiAgICB9LFxuXG4gICAgZmluaXNoOiBmdW5jdGlvbihmaW5hbGx5TG9jKSB7XG4gICAgICBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTtcbiAgICAgICAgaWYgKGVudHJ5LmZpbmFsbHlMb2MgPT09IGZpbmFsbHlMb2MpIHtcbiAgICAgICAgICB0aGlzLmNvbXBsZXRlKGVudHJ5LmNvbXBsZXRpb24sIGVudHJ5LmFmdGVyTG9jKTtcbiAgICAgICAgICByZXNldFRyeUVudHJ5KGVudHJ5KTtcbiAgICAgICAgICByZXR1cm4gQ29udGludWVTZW50aW5lbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBcImNhdGNoXCI6IGZ1bmN0aW9uKHRyeUxvYykge1xuICAgICAgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07XG4gICAgICAgIGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykge1xuICAgICAgICAgIHZhciByZWNvcmQgPSBlbnRyeS5jb21wbGV0aW9uO1xuICAgICAgICAgIGlmIChyZWNvcmQudHlwZSA9PT0gXCJ0aHJvd1wiKSB7XG4gICAgICAgICAgICB2YXIgdGhyb3duID0gcmVjb3JkLmFyZztcbiAgICAgICAgICAgIHJlc2V0VHJ5RW50cnkoZW50cnkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhyb3duO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFRoZSBjb250ZXh0LmNhdGNoIG1ldGhvZCBtdXN0IG9ubHkgYmUgY2FsbGVkIHdpdGggYSBsb2NhdGlvblxuICAgICAgLy8gYXJndW1lbnQgdGhhdCBjb3JyZXNwb25kcyB0byBhIGtub3duIGNhdGNoIGJsb2NrLlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaWxsZWdhbCBjYXRjaCBhdHRlbXB0XCIpO1xuICAgIH0sXG5cbiAgICBkZWxlZ2F0ZVlpZWxkOiBmdW5jdGlvbihpdGVyYWJsZSwgcmVzdWx0TmFtZSwgbmV4dExvYykge1xuICAgICAgdGhpcy5kZWxlZ2F0ZSA9IHtcbiAgICAgICAgaXRlcmF0b3I6IHZhbHVlcyhpdGVyYWJsZSksXG4gICAgICAgIHJlc3VsdE5hbWU6IHJlc3VsdE5hbWUsXG4gICAgICAgIG5leHRMb2M6IG5leHRMb2NcbiAgICAgIH07XG5cbiAgICAgIGlmICh0aGlzLm1ldGhvZCA9PT0gXCJuZXh0XCIpIHtcbiAgICAgICAgLy8gRGVsaWJlcmF0ZWx5IGZvcmdldCB0aGUgbGFzdCBzZW50IHZhbHVlIHNvIHRoYXQgd2UgZG9uJ3RcbiAgICAgICAgLy8gYWNjaWRlbnRhbGx5IHBhc3MgaXQgb24gdG8gdGhlIGRlbGVnYXRlLlxuICAgICAgICB0aGlzLmFyZyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIENvbnRpbnVlU2VudGluZWw7XG4gICAgfVxuICB9O1xuXG4gIC8vIFJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGlzIHNjcmlwdCBpcyBleGVjdXRpbmcgYXMgYSBDb21tb25KUyBtb2R1bGVcbiAgLy8gb3Igbm90LCByZXR1cm4gdGhlIHJ1bnRpbWUgb2JqZWN0IHNvIHRoYXQgd2UgY2FuIGRlY2xhcmUgdGhlIHZhcmlhYmxlXG4gIC8vIHJlZ2VuZXJhdG9yUnVudGltZSBpbiB0aGUgb3V0ZXIgc2NvcGUsIHdoaWNoIGFsbG93cyB0aGlzIG1vZHVsZSB0byBiZVxuICAvLyBpbmplY3RlZCBlYXNpbHkgYnkgYGJpbi9yZWdlbmVyYXRvciAtLWluY2x1ZGUtcnVudGltZSBzY3JpcHQuanNgLlxuICByZXR1cm4gZXhwb3J0cztcblxufShcbiAgLy8gSWYgdGhpcyBzY3JpcHQgaXMgZXhlY3V0aW5nIGFzIGEgQ29tbW9uSlMgbW9kdWxlLCB1c2UgbW9kdWxlLmV4cG9ydHNcbiAgLy8gYXMgdGhlIHJlZ2VuZXJhdG9yUnVudGltZSBuYW1lc3BhY2UuIE90aGVyd2lzZSBjcmVhdGUgYSBuZXcgZW1wdHlcbiAgLy8gb2JqZWN0LiBFaXRoZXIgd2F5LCB0aGUgcmVzdWx0aW5nIG9iamVjdCB3aWxsIGJlIHVzZWQgdG8gaW5pdGlhbGl6ZVxuICAvLyB0aGUgcmVnZW5lcmF0b3JSdW50aW1lIHZhcmlhYmxlIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlLlxuICB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiID8gbW9kdWxlLmV4cG9ydHMgOiB7fVxuKSk7XG5cbnRyeSB7XG4gIHJlZ2VuZXJhdG9yUnVudGltZSA9IHJ1bnRpbWU7XG59IGNhdGNoIChhY2NpZGVudGFsU3RyaWN0TW9kZSkge1xuICAvLyBUaGlzIG1vZHVsZSBzaG91bGQgbm90IGJlIHJ1bm5pbmcgaW4gc3RyaWN0IG1vZGUsIHNvIHRoZSBhYm92ZVxuICAvLyBhc3NpZ25tZW50IHNob3VsZCBhbHdheXMgd29yayB1bmxlc3Mgc29tZXRoaW5nIGlzIG1pc2NvbmZpZ3VyZWQuIEp1c3RcbiAgLy8gaW4gY2FzZSBydW50aW1lLmpzIGFjY2lkZW50YWxseSBydW5zIGluIHN0cmljdCBtb2RlLCB3ZSBjYW4gZXNjYXBlXG4gIC8vIHN0cmljdCBtb2RlIHVzaW5nIGEgZ2xvYmFsIEZ1bmN0aW9uIGNhbGwuIFRoaXMgY291bGQgY29uY2VpdmFibHkgZmFpbFxuICAvLyBpZiBhIENvbnRlbnQgU2VjdXJpdHkgUG9saWN5IGZvcmJpZHMgdXNpbmcgRnVuY3Rpb24sIGJ1dCBpbiB0aGF0IGNhc2VcbiAgLy8gdGhlIHByb3BlciBzb2x1dGlvbiBpcyB0byBmaXggdGhlIGFjY2lkZW50YWwgc3RyaWN0IG1vZGUgcHJvYmxlbS4gSWZcbiAgLy8geW91J3ZlIG1pc2NvbmZpZ3VyZWQgeW91ciBidW5kbGVyIHRvIGZvcmNlIHN0cmljdCBtb2RlIGFuZCBhcHBsaWVkIGFcbiAgLy8gQ1NQIHRvIGZvcmJpZCBGdW5jdGlvbiwgYW5kIHlvdSdyZSBub3Qgd2lsbGluZyB0byBmaXggZWl0aGVyIG9mIHRob3NlXG4gIC8vIHByb2JsZW1zLCBwbGVhc2UgZGV0YWlsIHlvdXIgdW5pcXVlIHByZWRpY2FtZW50IGluIGEgR2l0SHViIGlzc3VlLlxuICBGdW5jdGlvbihcInJcIiwgXCJyZWdlbmVyYXRvclJ1bnRpbWUgPSByXCIpKHJ1bnRpbWUpO1xufVxuIl19
|