From 268a412e9b1a8a754cdb8a3661b314456a2fc9f1 Mon Sep 17 00:00:00 2001 From: pratu16x7 Date: Sat, 28 Oct 2017 20:59:30 +0530 Subject: [PATCH] add babel, eslint; dom and utils modules --- .babelrc | 12 +- .eslintrc.json | 33 + dist/frappe-charts.min.js | 4253 ++++++++++++++++++++--------------- docs/assets/js/index.js | 38 +- docs/index.html | 6 +- package-lock.json | 2529 ++++++++++++++++++++- package.json | 8 +- rollup.config.js | 15 +- src/charts.js | 510 +---- src/dom.js | 219 ++ src/scripts/test.js | 0 src/{ => styles}/charts.css | 0 src/utils.js | 34 + 13 files changed, 5369 insertions(+), 2288 deletions(-) create mode 100644 .eslintrc.json create mode 100644 src/dom.js create mode 100644 src/scripts/test.js rename src/{ => styles}/charts.css (100%) create mode 100644 src/utils.js diff --git a/.babelrc b/.babelrc index ac95979..6570dbf 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,10 @@ { "presets": [ - [ - "es2015", - { + ["latest", { + "es2015": { "modules": false } - ] - ] -} + }] + ], + "plugins": ["external-helpers"] +} \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..c066e75 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "sourceType": "module" + }, + "rules": { + "indent": [ + "error", + "tab" + ], + "linebreak-style": [ + "error", + "unix" + ], + "semi": [ + "error", + "always" + ], + "no-console": [ + "error", + { + "allow": ["warn", "error"] + } + ] + }, + "globals": { + "ENV": true + } +} \ No newline at end of file diff --git a/dist/frappe-charts.min.js b/dist/frappe-charts.min.js index c91504c..de860e4 100644 --- a/dist/frappe-charts.min.js +++ b/dist/frappe-charts.min.js @@ -1,2246 +1,2775 @@ -(function () { +var Chart = (function () { 'use strict'; -let frappe = {chart:{}, chart_types:['line', 'bar', 'percentage', 'heatmap']}; +var asyncGenerator = function () { + function AwaitValue(value) { + this.value = value; + } + + function AsyncGenerator(gen) { + var front, back; + + function send(key, arg) { + return new Promise(function (resolve, reject) { + var request = { + key: key, + arg: arg, + resolve: resolve, + reject: reject, + next: null + }; + + if (back) { + back = back.next = request; + } else { + front = back = request; + resume(key, arg); + } + }); + } + + function resume(key, arg) { + try { + var result = gen[key](arg); + var value = result.value; + + if (value instanceof AwaitValue) { + Promise.resolve(value.value).then(function (arg) { + resume("next", arg); + }, function (arg) { + resume("throw", arg); + }); + } else { + settle(result.done ? "return" : "normal", result.value); + } + } catch (err) { + settle("throw", err); + } + } + + function settle(type, value) { + switch (type) { + case "return": + front.resolve({ + value: value, + done: true + }); + break; + + case "throw": + front.reject(value); + break; + + default: + front.resolve({ + value: value, + done: false + }); + break; + } + + front = front.next; + + if (front) { + resume(front.key, front.arg); + } else { + back = null; + } + } + + this._invoke = send; + + if (typeof gen.return !== "function") { + this.return = undefined; + } + } + + if (typeof Symbol === "function" && Symbol.asyncIterator) { + AsyncGenerator.prototype[Symbol.asyncIterator] = function () { + return this; + }; + } + + AsyncGenerator.prototype.next = function (arg) { + return this._invoke("next", arg); + }; + + AsyncGenerator.prototype.throw = function (arg) { + return this._invoke("throw", arg); + }; + + AsyncGenerator.prototype.return = function (arg) { + return this._invoke("return", arg); + }; + + return { + wrap: function (fn) { + return function () { + return new AsyncGenerator(fn.apply(this, arguments)); + }; + }, + await: function (value) { + return new AwaitValue(value); + } + }; +}(); + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; -frappe.chart.FrappeChart = class { - constructor({ - parent = "", - height = 240, +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } - title = '', subtitle = '', + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); - data = {}, - format_lambdas = {}, - summary = [], - is_navigable = 0, - type = '' - }) { - if(Object.getPrototypeOf(this) === frappe.chart.FrappeChart.prototype) { - if(type === 'line') { - return new frappe.chart.LineChart(arguments[0]); - } else if(type === 'bar') { - return new frappe.chart.BarChart(arguments[0]); - } else if(type === 'percentage') { - return new frappe.chart.PercentageChart(arguments[0]); - } else if(type === 'heatmap') { - return new frappe.chart.HeatMap(arguments[0]); - } else { - return new frappe.chart.LineChart(arguments[0]); - } - } - this.raw_chart_args = arguments[0]; - this.parent = document.querySelector(parent); - this.title = title; - this.subtitle = subtitle; - this.data = data; - this.format_lambdas = format_lambdas; +var get = function get(object, property, receiver) { + if (object === null) object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); - this.specific_values = data.specific_values || []; - this.summary = summary; + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); - this.is_navigable = is_navigable; - if(this.is_navigable) { - this.current_index = 0; - } + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ("value" in desc) { + return desc.value; + } else { + var getter = desc.get; - $$.createSVG('svg', { - className: 'chart', - inside: parent, - width: 1000, - height: height - }); + if (getter === undefined) { + return undefined; + } - this.set_margins(height); - } + return getter.call(receiver); + } +}; - get_different_chart(type) { - if(!frappe.chart_types.includes(type)) { - console.error(`'${type}' is not a valid chart type.`); - } - if(type === this.type) return; +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; - // Only across compatible types - let compatible_types = { - bar: ['line', 'percentage'], - line: ['bar', 'percentage'], - percentage: ['bar', 'line'], - heatmap: [] - }; - if(!compatible_types[this.type].includes(type)) { - console.error(`'${this.type}' chart cannot be converted to a '${type}' chart.`); - } - // Okay, this is anticlimactic - // this function will need to be 'change_chart_type(type)' - // that will update only the required elements, but for now ... - return new frappe.chart.FrappeChart({ - parent: this.raw_chart_args.parent, - data: this.raw_chart_args.data, - type: type, - height: this.raw_chart_args.height - }); - } - set_margins(height) { - this.base_height = height; - this.height = height - 40; - this.translate_x = 60; - this.translate_y = 10; - } - setup() { - this.bind_window_events(); - this.refresh(true); - } - bind_window_events() { - window.addEventListener('resize', () => this.refresh()); - window.addEventListener('orientationchange', () => this.refresh()); - } - refresh(init=false) { - this.setup_base_values(); - this.set_width(); - this.setup_container(); - this.setup_components(); - this.setup_values(); - this.setup_utils(); - this.make_graph_components(init); - this.make_tooltip(); - if(this.summary.length > 0) { - this.show_custom_summary(); - } else { - this.show_summary(); - } +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } - if(this.is_navigable) { - this.setup_navigation(init); - } - } + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; - set_width() { - let special_values_width = 0; - this.specific_values.map(val => { - if(this.get_strwidth(val.title) > special_values_width) { - special_values_width = this.get_strwidth(val.title) - 40; - } - }); - this.base_width = this.parent.offsetWidth - special_values_width; - this.width = this.base_width - this.translate_x * 2; - } - setup_base_values() {} - setup_container() { - this.container = $$.create('div', { - className: 'chart-container', - innerHTML: `
${this.title}
-
${this.subtitle}
-
-
` - }); - // Chart needs a dedicated parent element - this.parent.innerHTML = ''; - this.parent.appendChild(this.container); - this.chart_wrapper = this.container.querySelector('.frappe-chart'); - this.stats_wrapper = this.container.querySelector('.graph-stats-container'); +var slicedToArray = function () { + function sliceIterator(arr, i) { + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; - this.make_chart_area(); - this.make_draw_area(); - } + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); - make_chart_area() { - this.svg = $$.createSVG('svg', { - className: 'chart', - inside: this.chart_wrapper, - width: this.base_width, - height: this.base_height - }); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"]) _i["return"](); + } finally { + if (_d) throw _e; + } + } - this.svg_defs = $$.createSVG('defs', { - inside: this.svg, - }); + return _arr; + } - return this.svg; - } + return function (arr, i) { + if (Array.isArray(arr)) { + return arr; + } else if (Symbol.iterator in Object(arr)) { + return sliceIterator(arr, i); + } else { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); + } + }; +}(); - make_draw_area() { - this.draw_area = $$.createSVG("g", { - className: this.type + '-chart', - inside: this.svg, - transform: `translate(${this.translate_x}, ${this.translate_y})` - }); - } - setup_components() { } - make_tooltip() { - this.tip = new frappe.chart.SvgTip({ - parent: this.chart_wrapper, - }); - this.bind_tooltip(); - } - show_summary() {} - show_custom_summary() { - this.summary.map(d => { - let stats = $$.create('div', { - className: 'stats', - innerHTML: `${d.title}: ${d.value}` - }); - this.stats_wrapper.appendChild(stats); - }); - } - setup_navigation(init=false) { - this.make_overlay(); - - if(init) { - this.bind_overlay(); - - document.addEventListener('keydown', (e) => { - if($$.isElementInViewport(this.chart_wrapper)) { - e = e || window.event; - - if (e.keyCode == '37') { - this.on_left_arrow(); - } else if (e.keyCode == '39') { - this.on_right_arrow(); - } else if (e.keyCode == '38') { - this.on_up_arrow(); - } else if (e.keyCode == '40') { - this.on_down_arrow(); - } else if (e.keyCode == '13') { - this.on_enter_key(); - } - } - }); - } - } - make_overlay() {} - bind_overlay() {} - on_left_arrow() {} - on_right_arrow() {} - on_up_arrow() {} - on_down_arrow() {} - on_enter_key() {} - get_data_point(index=this.current_index) { - // check for length - let data_point = { - index: index - }; - let y = this.y[0]; - ['svg_units', 'y_tops', 'values'].map(key => { - let data_key = key.slice(0, key.length-1); - data_point[data_key] = y[key][index]; - }); - data_point.label = this.x[index]; - return data_point; - } - update_current_data_point(index) { - if(index < 0) index = 0; - if(index >= this.x.length) index = this.x.length - 1; - if(index === this.current_index) return; - this.current_index = index; - $$.fire(this.parent, "data-select", this.get_data_point()); - } - // Helpers - get_strwidth(string) { - return string.length * 8; - } - // Objects - setup_utils() { } + +var toConsumableArray = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } else { + return Array.from(arr); + } }; -frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { - constructor(args) { - super(args); +function $(expr, con) { + return typeof expr === "string" ? (con || document).querySelector(expr) : expr || null; +} - this.x = this.data.labels; - this.y = this.data.datasets; +$.findNodeIndex = function (node) { + var i = 0; + while (node.previousSibling) { + node = node.previousSibling; + i++; + } + return i; +}; - this.get_y_label = this.format_lambdas.y_label; - this.get_y_tooltip = this.format_lambdas.y_tooltip; - this.get_x_tooltip = this.format_lambdas.x_tooltip; +$.create = function (tag, o) { + var element = document.createElement(tag); - this.colors = ['green', 'blue', 'violet', 'red', 'orange', - 'yellow', 'light-blue', 'light-green', 'purple', 'magenta']; + for (var i in o) { + var val = o[i]; - this.zero_line = this.height; + if (i === "inside") { + $(val).appendChild(element); + } else if (i === "around") { + var ref = $(val); + ref.parentNode.insertBefore(element, ref); + element.appendChild(ref); + } else if (i in element) { + element[i] = val; + } else { + element.setAttribute(i, val); + } } - setup_values() { - this.data.datasets.map(d => { - d.values = d.values.map(val => (!isNaN(val) ? val : 0)); - }); - this.setup_x(); - this.setup_y(); - } + return element; +}; - setup_x() { - this.set_avg_unit_width_and_x_offset(); +$.createSVG = function (tag, o) { + var element = document.createElementNS("http://www.w3.org/2000/svg", tag); - if(this.x_axis_positions) { - this.x_old_axis_positions = this.x_axis_positions.slice(); - } - this.x_axis_positions = this.x.map((d, i) => - $$.float_2(this.x_offset + i * this.avg_unit_width)); + for (var i in o) { + var val = o[i]; - if(!this.x_old_axis_positions) { - this.x_old_axis_positions = this.x_axis_positions.slice(); + if (i === "inside") { + $(val).appendChild(element); + } else if (i === "around") { + var ref = $(val); + ref.parentNode.insertBefore(element, ref); + element.appendChild(ref); + } else { + if (i === "className") { + i = "class"; + } + if (i === "innerHTML") { + element['textContent'] = val; + } else { + element.setAttribute(i, val); + } } } - setup_y() { - if(this.y_axis_values) { - this.y_old_axis_values = this.y_axis_values.slice(); - } + return element; +}; - let values = this.get_all_y_values(); +$.runSVGAnimation = function (svg_container, elements) { + // let parent = elements[0][0]['unit'].parentNode; - if(this.y_sums && this.y_sums.length > 0) { - values = values.concat(this.y_sums); - } + var new_elements = []; + var anim_elements = []; - this.y_axis_values = this.get_y_axis_points(values); + elements.map(function (element) { + var obj = element[0]; + var parent = obj.unit.parentNode; + // let index = let findNodeIndex(obj.unit); - if(!this.y_old_axis_values) { - this.y_old_axis_values = this.y_axis_values.slice(); - } + var anim_element = void 0, + new_element = void 0; - const y_pts = this.y_axis_values; - const value_range = y_pts[y_pts.length-1] - y_pts[0]; + element[0] = obj.unit; - if(this.multiplier) this.old_multiplier = this.multiplier; - this.multiplier = this.height / value_range; - if(!this.old_multiplier) this.old_multiplier = this.multiplier; + var _$$animateSVG = $.animateSVG.apply($, toConsumableArray(element)); - const zero_index = y_pts.indexOf(0); - const interval = y_pts[1] - y_pts[0]; - const interval_height = interval * this.multiplier; + var _$$animateSVG2 = slicedToArray(_$$animateSVG, 2); - if(this.zero_line) this.old_zero_line = this.zero_line; - this.zero_line = this.height - (zero_index * interval_height); - if(!this.old_zero_line) this.old_zero_line = this.zero_line; - } + anim_element = _$$animateSVG2[0]; + new_element = _$$animateSVG2[1]; - setup_components() { - super.setup_components(); - this.setup_marker_components(); - this.setup_aggregation_components(); - this.setup_graph_components(); - } - setup_marker_components() { - this.y_axis_group = $$.createSVG('g', {className: 'y axis', inside: this.draw_area}); - this.x_axis_group = $$.createSVG('g', {className: 'x axis', inside: this.draw_area}); - this.specific_y_group = $$.createSVG('g', {className: 'specific axis', inside: this.draw_area}); - } + new_elements.push(new_element); + anim_elements.push([anim_element, parent]); - setup_aggregation_components() { - this.sum_group = $$.createSVG('g', {className: 'data-points', inside: this.draw_area}); - this.average_group = $$.createSVG('g', {className: 'chart-area', inside: this.draw_area}); - } + parent.replaceChild(anim_element, obj.unit); - setup_graph_components() { - this.svg_units_groups = []; - this.y.map((d, i) => { - this.svg_units_groups[i] = $$.createSVG('g', { - className: 'data-points data-points-' + i, - inside: this.draw_area - }); - }); - } + if (obj.array) { + obj.array[obj.index] = new_element; + } else { + obj.object[obj.key] = new_element; + } + }); - make_graph_components(init=false) { - this.make_y_axis(); - this.make_x_axis(); - this.draw_graph(init); - this.make_y_specifics(); - } + var anim_svg = svg_container.cloneNode(true); - // make VERTICAL lines for x values - make_x_axis(animate=false) { - let start_at, height, text_start_at, axis_line_class = ''; - if(this.x_axis_mode === 'span') { // long spanning lines - start_at = -7; - height = this.height + 15; - text_start_at = this.height + 25; - } else if(this.x_axis_mode === 'tick'){ // short label lines - start_at = this.height; - height = 6; - text_start_at = 9; - axis_line_class = 'x-axis-label'; - } - - this.x_axis_group.setAttribute('transform', `translate(0,${start_at})`); - - if(animate) { - this.make_anim_x_axis(height, text_start_at, axis_line_class); - return; - } - - this.x_axis_group.textContent = ''; - this.x.map((point, i) => { - this.x_axis_group.appendChild( - this.make_x_line( - height, - text_start_at, - point, - 'x-value-text', - axis_line_class, - this.x_axis_positions[i] - ) - ); - }); - } + anim_elements.map(function (anim_element, i) { + anim_element[1].replaceChild(new_elements[i], anim_element[0]); + elements[i][0] = new_elements[i]; + }); - // make HORIZONTAL lines for y values - make_y_axis(animate=false) { - if(animate) { - this.make_anim_y_axis(); - this.make_anim_y_specifics(); - return; - } - - let [width, text_end_at, axis_line_class, start_at] = this.get_y_axis_line_props(); - - this.y_axis_group.textContent = ''; - this.y_axis_values.map((value, i) => { - this.y_axis_group.appendChild( - this.make_y_line( - start_at, - width, - text_end_at, - value, - 'y-value-text', - axis_line_class, - this.zero_line - value * this.multiplier, - (value === 0 && i !== 0) // Non-first Zero line - ) - ); - }); - } + return anim_svg; +}; - get_y_axis_line_props(specific=false) { - if(specific) { - return[this.width, this.width + 5, 'specific-value', 0]; - } - let width, text_end_at = -9, axis_line_class = '', start_at = 0; - if(this.y_axis_mode === 'span') { // long spanning lines - width = this.width + 6; - start_at = -6; - } else if(this.y_axis_mode === 'tick'){ // short label lines - width = -6; - axis_line_class = 'y-axis-label'; +$.animateSVG = function (element, props, dur) { + var easing_type = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "linear"; + var type = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : undefined; + var old_values = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; + + var easing = { + ease: "0.25 0.1 0.25 1", + linear: "0 0 1 1", + // easein: "0.42 0 1 1", + easein: "0.1 0.8 0.2 1", + easeout: "0 0 0.58 1", + easeinout: "0.42 0 0.58 1" + }; + + var anim_element = element.cloneNode(true); + var new_element = element.cloneNode(true); + + for (var attributeName in props) { + var animate_element = void 0; + if (attributeName === 'transform') { + animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform"); + } else { + animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate"); } + var current_value = old_values[attributeName] || element.getAttribute(attributeName); + var value = props[attributeName]; - return [width, text_end_at, axis_line_class, start_at]; - } + var anim_attr = { + attributeName: attributeName, + from: current_value, + to: value, + begin: "0s", + dur: dur / 1000 + "s", + values: current_value + ";" + value, + keySplines: easing[easing_type], + keyTimes: "0;1", + calcMode: "spline", + fill: 'freeze' + }; - draw_graph(init=false) { - if(init) { - this.draw_new_graph_and_animate(); - return; + if (type) { + anim_attr["type"] = type; } - this.y.map((d, i) => { - d.svg_units = []; - this.make_path && this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); - this.make_new_units(d, i); - }); - } - draw_new_graph_and_animate() { - let data = []; - this.y.map((d, i) => { - // Anim: Don't draw initial values, store them and update later - d.y_tops = new Array(d.values.length).fill(this.zero_line); // no value - data.push({values: d.values}); - d.svg_units = []; - - this.make_path && this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); - this.make_new_units(d, i); - }); - - setTimeout(() => { - this.update_values(data); - }, 350); - } + for (var i in anim_attr) { + animate_element.setAttribute(i, anim_attr[i]); + } - setup_navigation(init) { - // Hack: defer nav till initial update_values - setTimeout(() => { - super.setup_navigation(init); - }, 500); - } + anim_element.appendChild(animate_element); - make_new_units(d, i) { - this.make_new_units_for_dataset( - this.x_axis_positions, - d.y_tops, - d.color || this.colors[i], - i, - this.y.length - ); + if (type) { + new_element.setAttribute(attributeName, "translate(" + value + ")"); + } else { + new_element.setAttribute(attributeName, value); + } } - make_new_units_for_dataset(x_values, y_values, color, dataset_index, no_of_datasets, group, array, unit) { - if(!group) group = this.svg_units_groups[dataset_index]; - if(!array) array = this.y[dataset_index].svg_units; - if(!unit) unit = this.unit_args; - - group.textContent = ''; - array.length = 0; - - y_values.map((y, i) => { - let data_unit = this.draw[unit.type]( - x_values[i], - y, - unit.args, - color, - dataset_index, - no_of_datasets - ); - group.appendChild(data_unit); - array.push(data_unit); - }); - } + return [anim_element, new_element]; +}; - make_y_specifics() { - this.specific_y_group.textContent = ''; - this.specific_values.map(d => { - this.specific_y_group.appendChild( - this.make_y_line( - 0, - this.width, - this.width + 5, - d.title.toUpperCase(), - 'specific-value', - 'specific-value', - this.zero_line - d.value * this.multiplier, - false, - d.line_type - ) - ); - }); - } +$.offset = function (element) { + var rect = element.getBoundingClientRect(); + return { + // https://stackoverflow.com/a/7436602/6495043 + // rect.top varies with scroll, so we add whatever has been + // scrolled to it to get absolute distance from actual page top + top: rect.top + (document.documentElement.scrollTop || document.body.scrollTop), + left: rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft) + }; +}; - bind_tooltip() { - // TODO: could be in tooltip itself, as it is a given functionality for its parent - this.chart_wrapper.addEventListener('mousemove', (e) => { - let offset = $$.offset(this.chart_wrapper); - let relX = e.pageX - offset.left - this.translate_x; - let relY = e.pageY - offset.top - this.translate_y; +$.isElementInViewport = function (el) { + // Although straightforward: https://stackoverflow.com/a/7557433/6495043 + var rect = el.getBoundingClientRect(); - if(relY < this.height + this.translate_y * 2) { - this.map_tooltip_x_position_and_show(relX); - } else { - this.tip.hide_tip(); - } - }); - } + return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ + rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ + ; +}; - map_tooltip_x_position_and_show(relX) { - for(var i=this.x_axis_positions.length - 1; i >= 0 ; i--) { - let x_val = this.x_axis_positions[i]; - // let delta = i === 0 ? this.avg_unit_width : x_val - this.x_axis_positions[i-1]; - if(relX > x_val - this.avg_unit_width/2) { - let x = x_val + this.translate_x; - let y = this.y_min_tops[i] + this.translate_y; - - let title = this.x.formatted && this.x.formatted.length>0 - ? this.x.formatted[i] : this.x[i]; - let values = this.y.map((set, j) => { - return { - title: set.title, - value: set.formatted ? set.formatted[i] : set.values[i], - color: set.color || this.colors[j], - } - }); +$.bind = function (element, o) { + if (element) { + for (var event in o) { + var callback = o[event]; - // TODO: upside-down tooltips for negative values? - this.tip.set_values(x, y, title, '', values); - this.tip.show_tip(); - break; - } + event.split(/\s+/).forEach(function (event) { + element.addEventListener(event, callback); + }); } } +}; - // API - show_sums() { - this.updating = true; +$.unbind = function (element, o) { + if (element) { + for (var event in o) { + var callback = o[event]; - this.y_sums = new Array(this.x_axis_positions.length).fill(0); - this.y.map(d => { - d.values.map( (value, i) => { - this.y_sums[i] += value; + event.split(/\s+/).forEach(function (event) { + element.removeEventListener(event, callback); }); - }); - - // Remake y axis, animate - this.update_values(); - - // Then make sum units, don't animate - this.sum_units = []; + } + } +}; - this.make_new_units_for_dataset( - this.x_axis_positions, - this.y_sums.map( val => $$.float_2(this.zero_line - val * this.multiplier)), - 'light-grey', - 0, - 1, - this.sum_group, - this.sum_units - ); +$.fire = function (target, type, properties) { + var evt = document.createEvent("HTMLEvents"); - // this.make_path && this.make_path(d, i, old_x, old_y, d.color || this.colors[i]); + evt.initEvent(type, true, true); - this.updating = false; + for (var j in properties) { + evt[j] = properties[j]; } - hide_sums() { - if(this.updating) return; - this.y_sums = []; - this.sum_group.textContent = ''; - this.sum_units = []; - this.update_values(); - } + return target.dispatchEvent(evt); +}; - show_average() { - this.old_specific_values = this.specific_values.slice(); - this.y.map((d, i) => { - let sum = 0; - d.values.map(e => {sum+=e;}); - let average = sum/d.values.length; +function float_2(d) { + return parseFloat(d.toFixed(2)); +} - this.specific_values.push({ - title: "AVG" + " " + (i+1), - line_type: "dashed", - value: average, - auto: 1 - }); - }); +function arrays_equal(arr1, arr2) { + if (arr1.length !== arr2.length) return false; + var are_equal = true; + arr1.map(function (d, i) { + if (arr2[i] !== d) are_equal = false; + }); + return are_equal; +} - console.log(this.specific_values); +var Chart = function () { + function Chart(_ref) { + var _ref$parent = _ref.parent, + parent = _ref$parent === undefined ? "" : _ref$parent, + _ref$height = _ref.height, + height = _ref$height === undefined ? 240 : _ref$height, + _ref$title = _ref.title, + title = _ref$title === undefined ? '' : _ref$title, + _ref$subtitle = _ref.subtitle, + subtitle = _ref$subtitle === undefined ? '' : _ref$subtitle, + _ref$data = _ref.data, + data = _ref$data === undefined ? {} : _ref$data, + _ref$format_lambdas = _ref.format_lambdas, + format_lambdas = _ref$format_lambdas === undefined ? {} : _ref$format_lambdas, + _ref$summary = _ref.summary, + summary = _ref$summary === undefined ? [] : _ref$summary, + _ref$is_navigable = _ref.is_navigable, + is_navigable = _ref$is_navigable === undefined ? 0 : _ref$is_navigable, + _ref$type = _ref.type, + type = _ref$type === undefined ? '' : _ref$type; + classCallCheck(this, Chart); + + if (Object.getPrototypeOf(this) === Chart.prototype) { + if (type === 'line') { + return new LineChart(arguments[0]); + } else if (type === 'bar') { + return new BarChart(arguments[0]); + } else if (type === 'percentage') { + return new PercentageChart(arguments[0]); + } else if (type === 'heatmap') { + return new HeatMap(arguments[0]); + } else { + return new LineChart(arguments[0]); + } + } - this.update_values(); - } + this.raw_chart_args = arguments[0]; - hide_average() { - this.old_specific_values = this.specific_values.slice(); + this.parent = document.querySelector(parent); + this.title = title; + this.subtitle = subtitle; - let indices_to_remove = []; - this.specific_values.map((d, i) => { - if(d.auto) indices_to_remove.unshift(i); - }); + this.data = data; + this.format_lambdas = format_lambdas; - console.log(indices_to_remove); + this.specific_values = data.specific_values || []; + this.summary = summary; - indices_to_remove.map(index => { - this.specific_values.splice(index, 1); - }); + this.is_navigable = is_navigable; + if (this.is_navigable) { + this.current_index = 0; + } - console.log(this.specific_values); + this.chart_types = ['line', 'bar', 'percentage', 'heatmap']; - this.update_values(); + this.set_margins(height); } - update_values(new_y, new_x) { - if(!new_x) { - new_x = this.x; + createClass(Chart, [{ + key: 'get_different_chart', + value: function get_different_chart(type) { + if (!this.chart_types.includes(type)) { + console.error('\'' + type + '\' is not a valid chart type.'); + } + if (type === this.type) return; + + // Only across compatible types + var compatible_types = { + bar: ['line', 'percentage'], + line: ['bar', 'percentage'], + percentage: ['bar', 'line'], + heatmap: [] + }; + + if (!compatible_types[this.type].includes(type)) { + console.error('\'' + this.type + '\' chart cannot be converted to a \'' + type + '\' chart.'); + } + + // Okay, this is anticlimactic + // this function will need to actually be 'change_chart_type(type)' + // that will update only the required elements, but for now ... + return new Chart({ + parent: this.raw_chart_args.parent, + data: this.raw_chart_args.data, + type: type, + height: this.raw_chart_args.height + }); + } + }, { + key: 'set_margins', + value: function set_margins(height) { + this.base_height = height; + this.height = height - 40; + this.translate_x = 60; + this.translate_y = 10; + } + }, { + key: 'setup', + value: function setup() { + this.bind_window_events(); + this.refresh(true); + } + }, { + key: 'bind_window_events', + value: function bind_window_events() { + var _this = this; + + window.addEventListener('resize', function () { + return _this.refresh(); + }); + window.addEventListener('orientationchange', function () { + return _this.refresh(); + }); } - this.elements_to_animate = []; - this.updating = true; + }, { + key: 'refresh', + value: function refresh() { + var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - this.old_x_values = this.x.slice(); - this.old_y_axis_tops = this.y.map(d => d.y_tops.slice()); + this.setup_base_values(); + this.set_width(); - this.old_y_values = this.y.map(d => d.values); + this.setup_container(); + this.setup_components(); - this.no_of_extra_pts = new_x.length - this.x.length; + this.setup_values(); + this.setup_utils(); - // Just update values prop, setup_x/y() will do the rest - if(new_y) this.y.map((d, i) => {d.values = new_y[i].values;}); - if(new_x) this.x = new_x; + this.make_graph_components(init); + this.make_tooltip(); - this.setup_x(); - this.setup_y(); + if (this.summary.length > 0) { + this.show_custom_summary(); + } else { + this.show_summary(); + } - // Animate only if positions have changed - if(!$$.arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) { - this.make_x_axis(true); - setTimeout(() => { - if(!this.updating) this.make_x_axis(); - }, 300); + if (this.is_navigable) { + this.setup_navigation(init); + } + } + }, { + key: 'set_width', + value: function set_width() { + var _this2 = this; + + var special_values_width = 0; + this.specific_values.map(function (val) { + if (_this2.get_strwidth(val.title) > special_values_width) { + special_values_width = _this2.get_strwidth(val.title) - 40; + } + }); + this.base_width = this.parent.offsetWidth - special_values_width; + this.width = this.base_width - this.translate_x * 2; } + }, { + key: 'setup_base_values', + value: function setup_base_values() {} + }, { + key: 'setup_container', + value: function setup_container() { + this.container = $.create('div', { + className: 'chart-container', + innerHTML: '
' + this.title + '
\n\t\t\t\t
' + this.subtitle + '
\n\t\t\t\t
\n\t\t\t\t
' + }); - if(!$$.arrays_equal(this.y_old_axis_values, this.y_axis_values) || - (this.old_specific_values && - !$$.arrays_equal(this.old_specific_values, this.specific_values))) { + // Chart needs a dedicated parent element + this.parent.innerHTML = ''; + this.parent.appendChild(this.container); - this.make_y_axis(true); - setTimeout(() => { - if(!this.updating) { - this.make_y_axis(); - this.make_y_specifics(); - } - }, 300); + this.chart_wrapper = this.container.querySelector('.frappe-chart'); + this.stats_wrapper = this.container.querySelector('.graph-stats-container'); + + this.make_chart_area(); + this.make_draw_area(); } + }, { + key: 'make_chart_area', + value: function make_chart_area() { + this.svg = $.createSVG('svg', { + className: 'chart', + inside: this.chart_wrapper, + width: this.base_width, + height: this.base_height + }); - // Change in data, so calculate dependencies - this.calc_y_dependencies(); + this.svg_defs = $.createSVG('defs', { + inside: this.svg + }); - this.animate_graphs(); + return this.svg; + } + }, { + key: 'make_draw_area', + value: function make_draw_area() { + this.draw_area = $.createSVG("g", { + className: this.type + '-chart', + inside: this.svg, + transform: 'translate(' + this.translate_x + ', ' + this.translate_y + ')' + }); + } + }, { + key: 'setup_components', + value: function setup_components() {} + }, { + key: 'make_tooltip', + value: function make_tooltip() { + this.tip = new SvgTip({ + parent: this.chart_wrapper + }); + this.bind_tooltip(); + } + }, { + key: 'show_summary', + value: function show_summary() {} + }, { + key: 'show_custom_summary', + value: function show_custom_summary() { + var _this3 = this; + + this.summary.map(function (d) { + var stats = $.create('div', { + className: 'stats', + innerHTML: '' + d.title + ': ' + d.value + '' + }); + _this3.stats_wrapper.appendChild(stats); + }); + } + }, { + key: 'setup_navigation', + value: function setup_navigation() { + var _this4 = this; + + var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + this.make_overlay(); + + if (init) { + this.bind_overlay(); + + document.addEventListener('keydown', function (e) { + if ($.isElementInViewport(_this4.chart_wrapper)) { + e = e || window.event; + + if (e.keyCode == '37') { + _this4.on_left_arrow(); + } else if (e.keyCode == '39') { + _this4.on_right_arrow(); + } else if (e.keyCode == '38') { + _this4.on_up_arrow(); + } else if (e.keyCode == '40') { + _this4.on_down_arrow(); + } else if (e.keyCode == '13') { + _this4.on_enter_key(); + } + } + }); + } + } + }, { + key: 'make_overlay', + value: function make_overlay() {} + }, { + key: 'bind_overlay', + value: function bind_overlay() {} + }, { + key: 'on_left_arrow', + value: function on_left_arrow() {} + }, { + key: 'on_right_arrow', + value: function on_right_arrow() {} + }, { + key: 'on_up_arrow', + value: function on_up_arrow() {} + }, { + key: 'on_down_arrow', + value: function on_down_arrow() {} + }, { + key: 'on_enter_key', + value: function on_enter_key() {} + }, { + key: 'get_data_point', + value: function get_data_point() { + var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.current_index; + + // check for length + var data_point = { + index: index + }; + var y = this.y[0]; + ['svg_units', 'y_tops', 'values'].map(function (key) { + var data_key = key.slice(0, key.length - 1); + data_point[data_key] = y[key][index]; + }); + data_point.label = this.x[index]; + return data_point; + } + }, { + key: 'update_current_data_point', + value: function update_current_data_point(index) { + if (index < 0) index = 0; + if (index >= this.x.length) index = this.x.length - 1; + if (index === this.current_index) return; + this.current_index = index; + $.fire(this.parent, "data-select", this.get_data_point()); + } - // Trigger animation with the animatable elements in this.elements_to_animate - this.run_animation(); + // Helpers - this.updating = false; - } + }, { + key: 'get_strwidth', + value: function get_strwidth(string) { + return string.length * 8; + } - add_data_point(y_point, x_point, index=this.x.length) { - let new_y = this.y.map(data_set => { return {values:data_set.values}; }); - new_y.map((d, i) => { d.values.splice(index, 0, y_point[i]); }); - let new_x = this.x.slice(); - new_x.splice(index, 0, x_point); + // Objects - this.update_values(new_y, new_x); - } + }, { + key: 'setup_utils', + value: function setup_utils() {} + }]); + return Chart; +}(); - remove_data_point(index = this.x.length-1) { - if(this.x.length < 3) return; +var AxisChart = function (_Chart) { + inherits(AxisChart, _Chart); - let new_y = this.y.map(data_set => { return {values:data_set.values}; }); - new_y.map((d, i) => { d.values.splice(index, 1); }); - let new_x = this.x.slice(); - new_x.splice(index, 1); + function AxisChart(args) { + classCallCheck(this, AxisChart); - this.update_values(new_y, new_x); - } + var _this5 = possibleConstructorReturn(this, (AxisChart.__proto__ || Object.getPrototypeOf(AxisChart)).call(this, args)); - run_animation() { - let anim_svg = $$.runSVGAnimation(this.svg, this.elements_to_animate); + _this5.x = _this5.data.labels; + _this5.y = _this5.data.datasets; - if(this.svg.parentNode == this.chart_wrapper) { - this.chart_wrapper.removeChild(this.svg); - this.chart_wrapper.appendChild(anim_svg); + _this5.get_y_label = _this5.format_lambdas.y_label; + _this5.get_y_tooltip = _this5.format_lambdas.y_tooltip; + _this5.get_x_tooltip = _this5.format_lambdas.x_tooltip; - } + _this5.colors = ['green', 'blue', 'violet', 'red', 'orange', 'yellow', 'light-blue', 'light-green', 'purple', 'magenta']; - // Replace the new svg (data has long been replaced) - setTimeout(() => { - if(anim_svg.parentNode == this.chart_wrapper) { - this.chart_wrapper.removeChild(anim_svg); - this.chart_wrapper.appendChild(this.svg); - } - }, 200); + _this5.zero_line = _this5.height; + return _this5; } - animate_graphs() { - this.y.map((d, i) => { - // Pre-prep, equilize no of positions between old and new - let [old_x, old_y, new_x, new_y] = this.calc_old_and_new_postions(d, i); - if(this.no_of_extra_pts >= 0) { - this.make_path && this.make_path(d, i, old_x, old_y, d.color || this.colors[i]); - this.make_new_units_for_dataset(old_x, old_y, d.color || this.colors[i], i, this.y.length); - } - d.path && this.animate_path(d, i, old_x, old_y, new_x, new_y); - this.animate_units(d, i, old_x, old_y, new_x, new_y); - }); - - // TODO: replace with real units - setTimeout(() => { - this.y.map((d, i) => { - this.make_path && this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); - this.make_new_units(d, i); + createClass(AxisChart, [{ + key: 'setup_values', + value: function setup_values() { + this.data.datasets.map(function (d) { + d.values = d.values.map(function (val) { + return !isNaN(val) ? val : 0; + }); }); - }, 300); - } - - animate_path(d, i, old_x, old_y, new_x, new_y) { - // Animate path - const new_points_list = new_y.map((y, i) => (new_x[i] + ',' + y)); - const new_path_str = new_points_list.join("L"); + this.setup_x(); + this.setup_y(); + } + }, { + key: 'setup_x', + value: function setup_x() { + var _this6 = this; - const path_args = [{unit: d.path, object: d, key: 'path'}, {d:"M"+new_path_str}, 250, "easein"]; - this.elements_to_animate.push(path_args); + this.set_avg_unit_width_and_x_offset(); - // Animate region - if(d.region_path) { - let reg_start_pt = `0,${this.zero_line}L`; - let reg_end_pt = `L${this.width},${this.zero_line}`; + if (this.x_axis_positions) { + this.x_old_axis_positions = this.x_axis_positions.slice(); + } + this.x_axis_positions = this.x.map(function (d, i) { + return float_2(_this6.x_offset + i * _this6.avg_unit_width); + }); - const region_args = [ - {unit: d.region_path, object: d, key: 'region_path'}, - {d:"M" + reg_start_pt + new_path_str + reg_end_pt}, - 250, - "easein" - ]; - this.elements_to_animate.push(region_args); + if (!this.x_old_axis_positions) { + this.x_old_axis_positions = this.x_axis_positions.slice(); + } } - } - - animate_units(d, index, old_x, old_y, new_x, new_y) { - let type = this.unit_args.type; - - d.svg_units.map((unit, i) => { - this.elements_to_animate.push(this.animate[type]( - {unit:unit, array:d.svg_units, index: i}, // unit, with info to replace where it came from in the data - new_x[i], - new_y[i], - index - )); - }); - } - - calc_old_and_new_postions(d, i) { - let old_x = this.x_old_axis_positions.slice(); - let new_x = this.x_axis_positions.slice(); + }, { + key: 'setup_y', + value: function setup_y() { + if (this.y_axis_values) { + this.y_old_axis_values = this.y_axis_values.slice(); + } - let old_y = this.old_y_axis_tops[i].slice(); - let new_y = d.y_tops.slice(); + var values = this.get_all_y_values(); - const last_old_x_pos = old_x[old_x.length - 1]; - const last_old_y_pos = old_y[old_y.length - 1]; + if (this.y_sums && this.y_sums.length > 0) { + values = values.concat(this.y_sums); + } - const last_new_x_pos = new_x[new_x.length - 1]; - const last_new_y_pos = new_y[new_y.length - 1]; + this.y_axis_values = this.get_y_axis_points(values); - if(this.no_of_extra_pts >= 0) { - // First substitute current path with a squiggled one (looking the same but - // having more points at end), - // then animate to stretch it later to new points - // (new points already have more points) + if (!this.y_old_axis_values) { + this.y_old_axis_values = this.y_axis_values.slice(); + } - // Hence, the extra end points will correspond to current(old) positions - let filler_x = new Array(Math.abs(this.no_of_extra_pts)).fill(last_old_x_pos); - let filler_y = new Array(Math.abs(this.no_of_extra_pts)).fill(last_old_y_pos); + var y_pts = this.y_axis_values; + var value_range = y_pts[y_pts.length - 1] - y_pts[0]; - old_x = old_x.concat(filler_x); - old_y = old_y.concat(filler_y); + if (this.multiplier) this.old_multiplier = this.multiplier; + this.multiplier = this.height / value_range; + if (!this.old_multiplier) this.old_multiplier = this.multiplier; - } else { - // Just modify the new points to have extra points - // with the same position at end - let filler_x = new Array(Math.abs(this.no_of_extra_pts)).fill(last_new_x_pos); - let filler_y = new Array(Math.abs(this.no_of_extra_pts)).fill(last_new_y_pos); + var zero_index = y_pts.indexOf(0); + var interval = y_pts[1] - y_pts[0]; + var interval_height = interval * this.multiplier; - new_x = new_x.concat(filler_x); - new_y = new_y.concat(filler_y); + if (this.zero_line) this.old_zero_line = this.zero_line; + this.zero_line = this.height - zero_index * interval_height; + if (!this.old_zero_line) this.old_zero_line = this.zero_line; + } + }, { + key: 'setup_components', + value: function setup_components() { + get(AxisChart.prototype.__proto__ || Object.getPrototypeOf(AxisChart.prototype), 'setup_components', this).call(this); + this.setup_marker_components(); + this.setup_aggregation_components(); + this.setup_graph_components(); + } + }, { + key: 'setup_marker_components', + value: function setup_marker_components() { + this.y_axis_group = $.createSVG('g', { className: 'y axis', inside: this.draw_area }); + this.x_axis_group = $.createSVG('g', { className: 'x axis', inside: this.draw_area }); + this.specific_y_group = $.createSVG('g', { className: 'specific axis', inside: this.draw_area }); + } + }, { + key: 'setup_aggregation_components', + value: function setup_aggregation_components() { + this.sum_group = $.createSVG('g', { className: 'data-points', inside: this.draw_area }); + this.average_group = $.createSVG('g', { className: 'chart-area', inside: this.draw_area }); + } + }, { + key: 'setup_graph_components', + value: function setup_graph_components() { + var _this7 = this; + + this.svg_units_groups = []; + this.y.map(function (d, i) { + _this7.svg_units_groups[i] = $.createSVG('g', { + className: 'data-points data-points-' + i, + inside: _this7.draw_area + }); + }); + } + }, { + key: 'make_graph_components', + value: function make_graph_components() { + var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + this.make_y_axis(); + this.make_x_axis(); + this.draw_graph(init); + this.make_y_specifics(); } - return [old_x, old_y, new_x, new_y]; - } - - make_anim_x_axis(height, text_start_at, axis_line_class) { - // Animate X AXIS to account for more or less axis lines - - const old_pos = this.x_old_axis_positions; - const new_pos = this.x_axis_positions; - - const old_vals = this.old_x_values; - const new_vals = this.x; - - const last_line_pos = old_pos[old_pos.length - 1]; - - let add_and_animate_line = (value, old_pos, new_pos, i) => { - const x_line = this.make_x_line( - height, - text_start_at, - value, // new value - 'x-value-text', - axis_line_class, - old_pos // old position - ); - this.x_axis_group.appendChild(x_line); - - this.elements_to_animate && this.elements_to_animate.push([ - {unit: x_line, array: [0], index: 0}, - {transform: `${ new_pos }, 0`}, - 250, - "easein", - "translate", - {transform: `${ old_pos }, 0`} - ]); - }; - - this.x_axis_group.textContent = ''; + // make VERTICAL lines for x values + + }, { + key: 'make_x_axis', + value: function make_x_axis() { + var _this8 = this; + + var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + var start_at = void 0, + height = void 0, + text_start_at = void 0, + axis_line_class = ''; + if (this.x_axis_mode === 'span') { + // long spanning lines + start_at = -7; + height = this.height + 15; + text_start_at = this.height + 25; + } else if (this.x_axis_mode === 'tick') { + // short label lines + start_at = this.height; + height = 6; + text_start_at = 9; + axis_line_class = 'x-axis-label'; + } - this.make_new_axis_anim_lines( - old_pos, - new_pos, - old_vals, - new_vals, - last_line_pos, - add_and_animate_line - ); - } + this.x_axis_group.setAttribute('transform', 'translate(0,' + start_at + ')'); - make_anim_y_axis() { - // Animate Y AXIS to account for more or less axis lines + if (animate) { + this.make_anim_x_axis(height, text_start_at, axis_line_class); + return; + } - const old_pos = this.y_old_axis_values.map(value => - this.zero_line - value * this.multiplier); - const new_pos = this.y_axis_values.map(value => - this.zero_line - value * this.multiplier); + this.x_axis_group.textContent = ''; + this.x.map(function (point, i) { + _this8.x_axis_group.appendChild(_this8.make_x_line(height, text_start_at, point, 'x-value-text', axis_line_class, _this8.x_axis_positions[i])); + }); + } - const old_vals = this.y_old_axis_values; - const new_vals = this.y_axis_values; + // make HORIZONTAL lines for y values - const last_line_pos = old_pos[old_pos.length - 1]; + }, { + key: 'make_y_axis', + value: function make_y_axis() { + var _this9 = this; - this.y_axis_group.textContent = ''; + var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - this.make_new_axis_anim_lines( - old_pos, - new_pos, - old_vals, - new_vals, - last_line_pos, - this.add_and_animate_y_line.bind(this), - this.y_axis_group - ); - } + if (animate) { + this.make_anim_y_axis(); + this.make_anim_y_specifics(); + return; + } - make_anim_y_specifics() { - this.specific_y_group.textContent = ''; - this.specific_values.map((d, i) => { - this.add_and_animate_y_line( - d.title, - this.old_zero_line - d.value * this.old_multiplier, - this.zero_line - d.value * this.multiplier, - 0, - this.specific_y_group, - d.line_type, - true - ); - }); - } + var _get_y_axis_line_prop = this.get_y_axis_line_props(), + _get_y_axis_line_prop2 = slicedToArray(_get_y_axis_line_prop, 4), + width = _get_y_axis_line_prop2[0], + text_end_at = _get_y_axis_line_prop2[1], + axis_line_class = _get_y_axis_line_prop2[2], + start_at = _get_y_axis_line_prop2[3]; + + this.y_axis_group.textContent = ''; + this.y_axis_values.map(function (value, i) { + _this9.y_axis_group.appendChild(_this9.make_y_line(start_at, width, text_end_at, value, 'y-value-text', axis_line_class, _this9.zero_line - value * _this9.multiplier, value === 0 && i !== 0 // Non-first Zero line + )); + }); + } + }, { + key: 'get_y_axis_line_props', + value: function get_y_axis_line_props() { + var specific = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - make_new_axis_anim_lines(old_pos, new_pos, old_vals, new_vals, last_line_pos, add_and_animate_line, group) { - let superimposed_positions, superimposed_values; - let no_of_extras = new_vals.length - old_vals.length; - if(no_of_extras > 0) { - // More axis are needed - // First make only the superimposed (same position) ones - // Add in the extras at the end later - superimposed_positions = new_pos.slice(0, old_pos.length); - superimposed_values = new_vals.slice(0, old_vals.length); - } else { - // Axis have to be reduced - // Fake it by moving all current extra axis to the last position - // You'll need filler positions and values in the new arrays - const filler_vals = new Array(Math.abs(no_of_extras)).fill(""); - superimposed_values = new_vals.concat(filler_vals); + if (specific) { + return [this.width, this.width + 5, 'specific-value', 0]; + } + var width = void 0, + text_end_at = -9, + axis_line_class = '', + start_at = 0; + if (this.y_axis_mode === 'span') { + // long spanning lines + width = this.width + 6; + start_at = -6; + } else if (this.y_axis_mode === 'tick') { + // short label lines + width = -6; + axis_line_class = 'y-axis-label'; + } - const filler_pos = new Array(Math.abs(no_of_extras)).fill(last_line_pos); - superimposed_positions = new_pos.concat(filler_pos); + return [width, text_end_at, axis_line_class, start_at]; } + }, { + key: 'draw_graph', + value: function draw_graph() { + var _this10 = this; - superimposed_values.map((value, i) => { - add_and_animate_line(value, old_pos[i], superimposed_positions[i], i, group); - }); + var init = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - if(no_of_extras > 0) { - // Add in extra axis in the end - // and then animate to new positions - const extra_values = new_vals.slice(old_vals.length); - const extra_positions = new_pos.slice(old_pos.length); - - extra_values.map((value, i) => { - add_and_animate_line(value, last_line_pos, extra_positions[i], i, group); + if (init) { + this.draw_new_graph_and_animate(); + return; + } + this.y.map(function (d, i) { + d.svg_units = []; + _this10.make_path && _this10.make_path(d, i, _this10.x_axis_positions, d.y_tops, d.color || _this10.colors[i]); + _this10.make_new_units(d, i); }); } - } - - make_x_line(height, text_start_at, point, label_class, axis_line_class, x_pos) { - let allowed_space = this.avg_unit_width * 1.5; + }, { + key: 'draw_new_graph_and_animate', + value: function draw_new_graph_and_animate() { + var _this11 = this; + + var data = []; + this.y.map(function (d, i) { + // Anim: Don't draw initial values, store them and update later + d.y_tops = new Array(d.values.length).fill(_this11.zero_line); // no value + data.push({ values: d.values }); + d.svg_units = []; + + _this11.make_path && _this11.make_path(d, i, _this11.x_axis_positions, d.y_tops, d.color || _this11.colors[i]); + _this11.make_new_units(d, i); + }); - if(this.get_strwidth(point) > allowed_space) { - let allowed_letters = allowed_space / 8; - point = point.slice(0, allowed_letters-3) + " ..."; + setTimeout(function () { + _this11.update_values(data); + }, 350); + } + }, { + key: 'setup_navigation', + value: function setup_navigation(init) { + var _this12 = this; + + // Hack: defer nav till initial update_values + setTimeout(function () { + get(AxisChart.prototype.__proto__ || Object.getPrototypeOf(AxisChart.prototype), 'setup_navigation', _this12).call(_this12, init); + }, 500); + } + }, { + key: 'make_new_units', + value: function make_new_units(d, i) { + this.make_new_units_for_dataset(this.x_axis_positions, d.y_tops, d.color || this.colors[i], i, this.y.length); + } + }, { + key: 'make_new_units_for_dataset', + value: function make_new_units_for_dataset(x_values, y_values, color, dataset_index, no_of_datasets, group, array, unit) { + var _this13 = this; + + if (!group) group = this.svg_units_groups[dataset_index]; + if (!array) array = this.y[dataset_index].svg_units; + if (!unit) unit = this.unit_args; + + group.textContent = ''; + array.length = 0; + + y_values.map(function (y, i) { + var data_unit = _this13.draw[unit.type](x_values[i], y, unit.args, color, dataset_index, no_of_datasets); + group.appendChild(data_unit); + array.push(data_unit); + }); + } + }, { + key: 'make_y_specifics', + value: function make_y_specifics() { + var _this14 = this; + + this.specific_y_group.textContent = ''; + this.specific_values.map(function (d) { + _this14.specific_y_group.appendChild(_this14.make_y_line(0, _this14.width, _this14.width + 5, d.title.toUpperCase(), 'specific-value', 'specific-value', _this14.zero_line - d.value * _this14.multiplier, false, d.line_type)); + }); + } + }, { + key: 'bind_tooltip', + value: function bind_tooltip() { + var _this15 = this; + + // TODO: could be in tooltip itself, as it is a given functionality for its parent + this.chart_wrapper.addEventListener('mousemove', function (e) { + var offset = $.offset(_this15.chart_wrapper); + var relX = e.pageX - offset.left - _this15.translate_x; + var relY = e.pageY - offset.top - _this15.translate_y; + + if (relY < _this15.height + _this15.translate_y * 2) { + _this15.map_tooltip_x_position_and_show(relX); + } else { + _this15.tip.hide_tip(); + } + }); + } + }, { + key: 'map_tooltip_x_position_and_show', + value: function map_tooltip_x_position_and_show(relX) { + var _this16 = this; + + for (var i = this.x_axis_positions.length - 1; i >= 0; i--) { + var x_val = this.x_axis_positions[i]; + // let delta = i === 0 ? this.avg_unit_width : x_val - this.x_axis_positions[i-1]; + if (relX > x_val - this.avg_unit_width / 2) { + var x = x_val + this.translate_x; + var y = this.y_min_tops[i] + this.translate_y; + + var title = this.x.formatted && this.x.formatted.length > 0 ? this.x.formatted[i] : this.x[i]; + var values = this.y.map(function (set$$1, j) { + return { + title: set$$1.title, + value: set$$1.formatted ? set$$1.formatted[i] : set$$1.values[i], + color: set$$1.color || _this16.colors[j] + }; + }); + + // TODO: upside-down tooltips for negative values? + this.tip.set_values(x, y, title, '', values); + this.tip.show_tip(); + break; + } + } } - let line = $$.createSVG('line', { - x1: 0, - x2: 0, - y1: 0, - y2: height - }); + // API - let text = $$.createSVG('text', { - className: label_class, - x: 0, - y: text_start_at, - dy: '.71em', - innerHTML: point - }); + }, { + key: 'show_sums', + value: function show_sums() { + var _this17 = this; - let x_level = $$.createSVG('g', { - className: `tick ${axis_line_class}`, - transform: `translate(${ x_pos }, 0)` - }); + this.updating = true; - x_level.appendChild(line); - x_level.appendChild(text); + this.y_sums = new Array(this.x_axis_positions.length).fill(0); + this.y.map(function (d) { + d.values.map(function (value, i) { + _this17.y_sums[i] += value; + }); + }); - return x_level; - } + // Remake y axis, animate + this.update_values(); - make_y_line(start_at, width, text_end_at, point, label_class, axis_line_class, y_pos, darker=false, line_type="") { - let line = $$.createSVG('line', { - className: line_type === "dashed" ? "dashed": "", - x1: start_at, - x2: width, - y1: 0, - y2: 0 - }); + // Then make sum units, don't animate + this.sum_units = []; - let text = $$.createSVG('text', { - className: label_class, - x: text_end_at, - y: 0, - dy: '.32em', - innerHTML: point+"" - }); + this.make_new_units_for_dataset(this.x_axis_positions, this.y_sums.map(function (val) { + return float_2(_this17.zero_line - val * _this17.multiplier); + }), 'light-grey', 0, 1, this.sum_group, this.sum_units); - let y_level = $$.createSVG('g', { - className: `tick ${axis_line_class}`, - transform: `translate(0, ${y_pos})` - }); + // this.make_path && this.make_path(d, i, old_x, old_y, d.color || this.colors[i]); - if(darker) { - line.style.stroke = "rgba(27, 31, 35, 0.6)"; + this.updating = false; } + }, { + key: 'hide_sums', + value: function hide_sums() { + if (this.updating) return; + this.y_sums = []; + this.sum_group.textContent = ''; + this.sum_units = []; + this.update_values(); + } + }, { + key: 'show_average', + value: function show_average() { + var _this18 = this; + + this.old_specific_values = this.specific_values.slice(); + this.y.map(function (d, i) { + var sum = 0; + d.values.map(function (e) { + sum += e; + }); + var average = sum / d.values.length; - y_level.appendChild(line); - y_level.appendChild(text); - - return y_level; - } - - add_and_animate_y_line(value, old_pos, new_pos, i, group, type, specific=false) { - let [width, text_end_at, axis_line_class, start_at] = this.get_y_axis_line_props(specific); - let axis_label_class = !specific ? 'y-value-text' : 'specific-value'; - value = !specific ? value : (value+"").toUpperCase(); - const y_line = this.make_y_line( - start_at, - width, - text_end_at, - value, - axis_label_class, - axis_line_class, - old_pos, // old position - (value === 0 && i !== 0), // Non-first Zero line - type - ); - - group.appendChild(y_line); - - this.elements_to_animate && this.elements_to_animate.push([ - {unit: y_line, array: [0], index: 0}, - {transform: `0, ${ new_pos }`}, - 250, - "easein", - "translate", - {transform: `0, ${ old_pos }`} - ]); - } + _this18.specific_values.push({ + title: "AVG" + " " + (i + 1), + line_type: "dashed", + value: average, + auto: 1 + }); + }); - get_y_axis_points(array) { - //*** Where the magic happens *** + this.update_values(); + } + }, { + key: 'hide_average', + value: function hide_average() { + var _this19 = this; - // Calculates best-fit y intervals from given values - // and returns the interval array + this.old_specific_values = this.specific_values.slice(); - // TODO: Fractions + var indices_to_remove = []; + this.specific_values.map(function (d, i) { + if (d.auto) indices_to_remove.unshift(i); + }); - let max_bound, min_bound, pos_no_of_parts, neg_no_of_parts, part_size; + indices_to_remove.map(function (index) { + _this19.specific_values.splice(index, 1); + }); - // Critical values - let max_val = parseInt(Math.max(...array)); - let min_val = parseInt(Math.min(...array)); - if(min_val >= 0) { - min_val = 0; + this.update_values(); } + }, { + key: 'update_values', + value: function update_values(new_y, new_x) { + var _this20 = this; - let get_params = (value1, value2) => { - let bound1, bound2, no_of_parts_1, no_of_parts_2, interval_size; - if((value1+"").length <= 1) { - [bound1, no_of_parts_1] = [10, 5]; - } else { - [bound1, no_of_parts_1] = this.calc_upper_bound_and_no_of_parts(value1); + if (!new_x) { + new_x = this.x; } + this.elements_to_animate = []; + this.updating = true; - interval_size = bound1 / no_of_parts_1; - no_of_parts_2 = this.calc_no_of_parts(value2, interval_size); - bound2 = no_of_parts_2 * interval_size; + this.old_x_values = this.x.slice(); + this.old_y_axis_tops = this.y.map(function (d) { + return d.y_tops.slice(); + }); - return [bound1, bound2, no_of_parts_1, no_of_parts_2, interval_size]; - }; + this.old_y_values = this.y.map(function (d) { + return d.values; + }); - const abs_min_val = min_val * -1; - if(abs_min_val <= max_val) { - // Get the positive region intervals - // then calc negative ones accordingly - [max_bound, min_bound, pos_no_of_parts, neg_no_of_parts, part_size] - = get_params(max_val, abs_min_val); - if(abs_min_val === 0) { - min_bound = 0; neg_no_of_parts = 0; - } - } else { - // Get the negative region here first - [min_bound, max_bound, neg_no_of_parts, pos_no_of_parts, part_size] - = get_params(abs_min_val, max_val); - } + this.no_of_extra_pts = new_x.length - this.x.length; - // Make both region parts even - if(pos_no_of_parts % 2 !== 0 && neg_no_of_parts > 0) pos_no_of_parts++; - if(neg_no_of_parts % 2 !== 0) { - // every increase in no_of_parts entails an increase in corresponding bound - // except here, it happens implicitly after every calc_no_of_parts() call - neg_no_of_parts++; - min_bound += part_size; - } + // Just update values prop, setup_x/y() will do the rest + if (new_y) this.y.map(function (d, i) { + d.values = new_y[i].values; + }); + if (new_x) this.x = new_x; - let no_of_parts = pos_no_of_parts + neg_no_of_parts; - if(no_of_parts > 5) { - no_of_parts /= 2; - part_size *= 2; - } + this.setup_x(); + this.setup_y(); - return this.get_intervals( - (-1) * min_bound, - part_size, - no_of_parts - ); - } + // Animate only if positions have changed + if (!arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) { + this.make_x_axis(true); + setTimeout(function () { + if (!_this20.updating) _this20.make_x_axis(); + }, 300); + } - get_intervals(start, interval_size, count) { - let intervals = []; - for(var i = 0; i <= count; i++){ - intervals.push(start); - start += interval_size; - } - return intervals; - } + if (!arrays_equal(this.y_old_axis_values, this.y_axis_values) || this.old_specific_values && !arrays_equal(this.old_specific_values, this.specific_values)) { - calc_upper_bound_and_no_of_parts(max_val) { - // Given a positive value, calculates a nice-number upper bound - // and a consequent optimal number of parts + this.make_y_axis(true); + setTimeout(function () { + if (!_this20.updating) { + _this20.make_y_axis(); + _this20.make_y_specifics(); + } + }, 300); + } - const part_size = Math.pow(10, ((max_val+"").length - 1)); - const no_of_parts = this.calc_no_of_parts(max_val, part_size); + // Change in data, so calculate dependencies + this.calc_y_dependencies(); - // Use it to get a nice even upper bound - const upper_bound = part_size * no_of_parts; + this.animate_graphs(); - return [upper_bound, no_of_parts]; - } + // Trigger animation with the animatable elements in this.elements_to_animate + this.run_animation(); - calc_no_of_parts(value, divisor) { - // value should be a positive number, divisor should be greater than 0 - // returns an even no of parts - let no_of_parts = Math.ceil(value / divisor); - if(no_of_parts % 2 !== 0) no_of_parts++; // Make it an even number + this.updating = false; + } + }, { + key: 'add_data_point', + value: function add_data_point(y_point, x_point) { + var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.x.length; - return no_of_parts; - } + var new_y = this.y.map(function (data_set) { + return { values: data_set.values }; + }); + new_y.map(function (d, i) { + d.values.splice(index, 0, y_point[i]); + }); + var new_x = this.x.slice(); + new_x.splice(index, 0, x_point); - get_optimal_no_of_parts(no_of_parts) { - // aka Divide by 2 if too large - return (no_of_parts < 5) ? no_of_parts : no_of_parts / 2; - } + this.update_values(new_y, new_x); + } + }, { + key: 'remove_data_point', + value: function remove_data_point() { + var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.x.length - 1; - set_avg_unit_width_and_x_offset() { - // Set the ... you get it - this.avg_unit_width = this.width/(this.x.length - 1); - this.x_offset = 0; - } + if (this.x.length < 3) return; + + var new_y = this.y.map(function (data_set) { + return { values: data_set.values }; + }); + new_y.map(function (d) { + d.values.splice(index, 1); + }); + var new_x = this.x.slice(); + new_x.splice(index, 1); - get_all_y_values() { - let all_values = []; + this.update_values(new_y, new_x); + } + }, { + key: 'run_animation', + value: function run_animation() { + var _this21 = this; - // Add in all the y values in the datasets - this.y.map(d => { - all_values = all_values.concat(d.values); - }); + var anim_svg = $.runSVGAnimation(this.svg, this.elements_to_animate); - // Add in all the specific values - return all_values.concat(this.specific_values.map(d => d.value)); - } + if (this.svg.parentNode == this.chart_wrapper) { + this.chart_wrapper.removeChild(this.svg); + this.chart_wrapper.appendChild(anim_svg); + } - calc_y_dependencies() { - this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999); - this.y.map(d => { - d.y_tops = d.values.map( val => $$.float_2(this.zero_line - val * this.multiplier)); - d.y_tops.map( (y_top, i) => { - if(y_top < this.y_min_tops[i]) { - this.y_min_tops[i] = y_top; + // Replace the new svg (data has long been replaced) + setTimeout(function () { + if (anim_svg.parentNode == _this21.chart_wrapper) { + _this21.chart_wrapper.removeChild(anim_svg); + _this21.chart_wrapper.appendChild(_this21.svg); } + }, 200); + } + }, { + key: 'animate_graphs', + value: function animate_graphs() { + var _this22 = this; + + this.y.map(function (d, i) { + // Pre-prep, equilize no of positions between old and new + var _calc_old_and_new_pos = _this22.calc_old_and_new_postions(d, i), + _calc_old_and_new_pos2 = slicedToArray(_calc_old_and_new_pos, 4), + old_x = _calc_old_and_new_pos2[0], + old_y = _calc_old_and_new_pos2[1], + new_x = _calc_old_and_new_pos2[2], + new_y = _calc_old_and_new_pos2[3]; + + if (_this22.no_of_extra_pts >= 0) { + _this22.make_path && _this22.make_path(d, i, old_x, old_y, d.color || _this22.colors[i]); + _this22.make_new_units_for_dataset(old_x, old_y, d.color || _this22.colors[i], i, _this22.y.length); + } + d.path && _this22.animate_path(d, i, old_x, old_y, new_x, new_y); + _this22.animate_units(d, i, old_x, old_y, new_x, new_y); }); - }); - } - get_bar_height_and_y_attr(y_top) { - let height, y; - if (y_top <= this.zero_line) { - height = this.zero_line - y_top; - y = y_top; + // TODO: replace with real units + setTimeout(function () { + _this22.y.map(function (d, i) { + _this22.make_path && _this22.make_path(d, i, _this22.x_axis_positions, d.y_tops, d.color || _this22.colors[i]); + _this22.make_new_units(d, i); + }); + }, 300); + } + }, { + key: 'animate_path', + value: function animate_path(d, i, old_x, old_y, new_x, new_y) { + // Animate path + var new_points_list = new_y.map(function (y, i) { + return new_x[i] + ',' + y; + }); + var new_path_str = new_points_list.join("L"); - // In case of invisible bars - if(height === 0) { - height = this.height * 0.01; - y -= height; - } - } else { - height = y_top - this.zero_line; - y = this.zero_line; + var path_args = [{ unit: d.path, object: d, key: 'path' }, { d: "M" + new_path_str }, 250, "easein"]; + this.elements_to_animate.push(path_args); + + // Animate region + if (d.region_path) { + var reg_start_pt = '0,' + this.zero_line + 'L'; + var reg_end_pt = 'L' + this.width + ',' + this.zero_line; - // In case of invisible bars - if(height === 0) { - height = this.height * 0.01; + var region_args = [{ unit: d.region_path, object: d, key: 'region_path' }, { d: "M" + reg_start_pt + new_path_str + reg_end_pt }, 250, "easein"]; + this.elements_to_animate.push(region_args); } } + }, { + key: 'animate_units', + value: function animate_units(d, index, old_x, old_y, new_x, new_y) { + var _this23 = this; - return [height, y]; - } + var type = this.unit_args.type; - setup_utils() { - this.draw = { - 'bar': (x, y_top, args, color, index, no_of_datasets) => { - let total_width = this.avg_unit_width - args.space_width; - let start_x = x - total_width/2; + d.svg_units.map(function (unit, i) { + _this23.elements_to_animate.push(_this23.animate[type]({ unit: unit, array: d.svg_units, index: i }, // unit, with info to replace where it came from in the data + new_x[i], new_y[i], index)); + }); + } + }, { + key: 'calc_old_and_new_postions', + value: function calc_old_and_new_postions(d, i) { + var old_x = this.x_old_axis_positions.slice(); + var new_x = this.x_axis_positions.slice(); - let width = total_width / no_of_datasets; - let current_x = start_x + width * index; + var old_y = this.old_y_axis_tops[i].slice(); + var new_y = d.y_tops.slice(); - let [height, y] = this.get_bar_height_and_y_attr(y_top); + var last_old_x_pos = old_x[old_x.length - 1]; + var last_old_y_pos = old_y[old_y.length - 1]; - return $$.createSVG('rect', { - className: `bar mini fill ${color}`, - x: current_x, - y: y, - width: width, - height: height - }); + var last_new_x_pos = new_x[new_x.length - 1]; + var last_new_y_pos = new_y[new_y.length - 1]; - }, - 'dot': (x, y, args, color) => { - return $$.createSVG('circle', { - className: `fill ${color}`, - cx: x, - cy: y, - r: args.radius - }); - } - }; + if (this.no_of_extra_pts >= 0) { + // First substitute current path with a squiggled one (looking the same but + // having more points at end), + // then animate to stretch it later to new points + // (new points already have more points) - this.animate = { - 'bar': (bar_obj, x, y_top, index) => { - let start = x - this.avg_unit_width/4; - let width = (this.avg_unit_width/2)/this.y.length; - let [height, y] = this.get_bar_height_and_y_attr(y_top); + // Hence, the extra end points will correspond to current(old) positions + var filler_x = new Array(Math.abs(this.no_of_extra_pts)).fill(last_old_x_pos); + var filler_y = new Array(Math.abs(this.no_of_extra_pts)).fill(last_old_y_pos); - x = start + (width * index); - - return [bar_obj, {width: width, height: height, x: x, y: y}, 250, "easein"]; - // bar.animate({height: args.new_height, y: y_top}, 250, mina.easein); - }, - 'dot': (dot_obj, x, y_top) => { - return [dot_obj, {cx: x, cy: y_top}, 300, "easein"]; - // dot.animate({cy: y_top}, 250, mina.easein); - } - }; - } -}; - -frappe.chart.BarChart = class BarChart extends frappe.chart.AxisChart { - constructor(args) { - super(args); - - this.type = 'bar'; - this.x_axis_mode = args.x_axis_mode || 'tick'; - this.y_axis_mode = args.y_axis_mode || 'span'; - this.setup(); - } + old_x = old_x.concat(filler_x); + old_y = old_y.concat(filler_y); + } else { + // Just modify the new points to have extra points + // with the same position at end + var _filler_x = new Array(Math.abs(this.no_of_extra_pts)).fill(last_new_x_pos); + var _filler_y = new Array(Math.abs(this.no_of_extra_pts)).fill(last_new_y_pos); - setup_values() { - super.setup_values(); - this.x_offset = this.avg_unit_width; - this.unit_args = { - type: 'bar', - args: { - space_width: this.avg_unit_width/2, + new_x = new_x.concat(_filler_x); + new_y = new_y.concat(_filler_y); } - }; - } - - make_overlay() { - // Just make one out of the first element - let index = this.x.length - 1; - let unit = this.y[0].svg_units[index]; - this.update_current_data_point(index); - if(this.overlay) { - this.overlay.parentNode.removeChild(this.overlay); + return [old_x, old_y, new_x, new_y]; } + }, { + key: 'make_anim_x_axis', + value: function make_anim_x_axis(height, text_start_at, axis_line_class) { + var _this24 = this; - this.overlay = unit.cloneNode(); - this.overlay.style.fill = '#000000'; - this.overlay.style.opacity = '0.4'; - this.draw_area.appendChild(this.overlay); - } + // Animate X AXIS to account for more or less axis lines - bind_overlay() { - // on event, update overlay - this.parent.addEventListener('data-select', (e) => { - this.update_overlay(e.svg_unit); - }); - } + var old_pos = this.x_old_axis_positions; + var new_pos = this.x_axis_positions; - update_overlay(unit) { - let attributes = []; - Object.keys(unit.attributes).map(index => { - attributes.push(unit.attributes[index]); - }); + var old_vals = this.old_x_values; + var new_vals = this.x; - attributes.filter(attr => attr.specified).map(attr => { - this.overlay.setAttribute(attr.name, attr.nodeValue); - }); - } + var last_line_pos = old_pos[old_pos.length - 1]; - on_left_arrow() { - this.update_current_data_point(this.current_index - 1); - } + var add_and_animate_line = function add_and_animate_line(value, old_pos, new_pos) { + var x_line = _this24.make_x_line(height, text_start_at, value, // new value + 'x-value-text', axis_line_class, old_pos // old position + ); + _this24.x_axis_group.appendChild(x_line); - on_right_arrow() { - this.update_current_data_point(this.current_index + 1); - } + _this24.elements_to_animate && _this24.elements_to_animate.push([{ unit: x_line, array: [0], index: 0 }, { transform: new_pos + ', 0' }, 250, "easein", "translate", { transform: old_pos + ', 0' }]); + }; - set_avg_unit_width_and_x_offset() { - this.avg_unit_width = this.width/(this.x.length + 1); - this.x_offset = this.avg_unit_width; - } -}; + this.x_axis_group.textContent = ''; -frappe.chart.LineChart = class LineChart extends frappe.chart.AxisChart { - constructor(args) { - super(args); - if(Object.getPrototypeOf(this) !== frappe.chart.LineChart.prototype) { - return; + this.make_new_axis_anim_lines(old_pos, new_pos, old_vals, new_vals, last_line_pos, add_and_animate_line); } + }, { + key: 'make_anim_y_axis', + value: function make_anim_y_axis() { + var _this25 = this; - this.type = 'line'; - this.region_fill = args.region_fill; - this.x_axis_mode = args.x_axis_mode || 'span'; - this.y_axis_mode = args.y_axis_mode || 'span'; + // Animate Y AXIS to account for more or less axis lines - this.setup(); - } - - setup_graph_components() { - this.setup_path_groups(); - super.setup_graph_components(); - } - - setup_path_groups() { - this.paths_groups = []; - this.y.map((d, i) => { - this.paths_groups[i] = $$.createSVG('g', { - className: 'path-group path-group-' + i, - inside: this.draw_area + var old_pos = this.y_old_axis_values.map(function (value) { + return _this25.zero_line - value * _this25.multiplier; + }); + var new_pos = this.y_axis_values.map(function (value) { + return _this25.zero_line - value * _this25.multiplier; }); - }); - } - - setup_values() { - super.setup_values(); - this.unit_args = { - type: 'dot', - args: { radius: 8 } - }; - } - - make_paths() { - this.y.map((d, i) => { - this.make_path(d, i, this.x_axis_positions, d.y_tops, d.color || this.colors[i]); - }); - } - - make_path(d, i, x_positions, y_positions, color) { - // let points_list = y_positions.map((y, i) => (x_positions[i] + ',' + y)); - // let points_str = points_list.join("L"); - - // this.paths_groups[i].textContent = ''; - - // d.path = $$.createSVG('path', { - // inside: this.paths_groups[i], - // className: `stroke ${color}`, - // d: "M"+points_str - // }); - - // if(this.region_fill) { - // let gradient_id ='path-fill-gradient' + '-' + color; - - // this.gradient_def = $$.createSVG('linearGradient', { - // inside: this.svg_defs, - // id: gradient_id, - // x1: 0, - // x2: 0, - // y1: 0, - // y2: 1 - // }); - - // function set_gradient_stop(grad_elem, offset, color, opacity) { - // $$.createSVG('stop', { - // 'className': 'stop-color ' + color, - // 'inside': grad_elem, - // 'offset': offset, - // 'stop-opacity': opacity - // }); - // } - - // set_gradient_stop(this.gradient_def, "0%", color, 0.4); - // set_gradient_stop(this.gradient_def, "50%", color, 0.2); - // set_gradient_stop(this.gradient_def, "100%", color, 0); - - // d.region_path = $$.createSVG('path', { - // inside: this.paths_groups[i], - // className: `region-fill`, - // d: "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`, - // }); - - // d.region_path.style.stroke = "none"; - // d.region_path.style.fill = `url(#${gradient_id})`; - // } - } -}; - -frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.FrappeChart { - constructor(args) { - super(args); - this.type = 'percentage'; - this.get_y_label = this.format_lambdas.y_label; - this.get_x_tooltip = this.format_lambdas.x_tooltip; - this.get_y_tooltip = this.format_lambdas.y_tooltip; + var old_vals = this.y_old_axis_values; + var new_vals = this.y_axis_values; - this.max_slices = 10; - this.max_legend_points = 6; + var last_line_pos = old_pos[old_pos.length - 1]; - this.colors = args.colors; + this.y_axis_group.textContent = ''; - if(!this.colors || this.colors.length < this.data.labels.length) { - this.colors = ['light-blue', 'blue', 'violet', 'red', 'orange', - 'yellow', 'green', 'light-green', 'purple', 'magenta']; + this.make_new_axis_anim_lines(old_pos, new_pos, old_vals, new_vals, last_line_pos, this.add_and_animate_y_line.bind(this), this.y_axis_group); } + }, { + key: 'make_anim_y_specifics', + value: function make_anim_y_specifics() { + var _this26 = this; + + this.specific_y_group.textContent = ''; + this.specific_values.map(function (d) { + _this26.add_and_animate_y_line(d.title, _this26.old_zero_line - d.value * _this26.old_multiplier, _this26.zero_line - d.value * _this26.multiplier, 0, _this26.specific_y_group, d.line_type, true); + }); + } + }, { + key: 'make_new_axis_anim_lines', + value: function make_new_axis_anim_lines(old_pos, new_pos, old_vals, new_vals, last_line_pos, add_and_animate_line, group) { + var superimposed_positions = void 0, + superimposed_values = void 0; + var no_of_extras = new_vals.length - old_vals.length; + if (no_of_extras > 0) { + // More axis are needed + // First make only the superimposed (same position) ones + // Add in the extras at the end later + superimposed_positions = new_pos.slice(0, old_pos.length); + superimposed_values = new_vals.slice(0, old_vals.length); + } else { + // Axis have to be reduced + // Fake it by moving all current extra axis to the last position + // You'll need filler positions and values in the new arrays + var filler_vals = new Array(Math.abs(no_of_extras)).fill(""); + superimposed_values = new_vals.concat(filler_vals); + + var filler_pos = new Array(Math.abs(no_of_extras)).fill(last_line_pos); + superimposed_positions = new_pos.concat(filler_pos); + } - this.setup(); - } - - make_chart_area() { - this.chart_wrapper.className += ' ' + 'graph-focus-margin'; - this.chart_wrapper.style.marginTop = '45px'; - - this.stats_wrapper.className += ' ' + 'graph-focus-margin'; - this.stats_wrapper.style.marginBottom = '30px'; - this.stats_wrapper.style.paddingTop = '0px'; - } + superimposed_values.map(function (value, i) { + add_and_animate_line(value, old_pos[i], superimposed_positions[i], i, group); + }); - make_draw_area() { - this.chart_div = $$.create('div', { - className: 'div', - inside: this.chart_wrapper, - width: this.base_width, - height: this.base_height - }); - - this.chart = $$.create('div', { - className: 'progress-chart', - inside: this.chart_div - }); - } + if (no_of_extras > 0) { + // Add in extra axis in the end + // and then animate to new positions + var extra_values = new_vals.slice(old_vals.length); + var extra_positions = new_pos.slice(old_pos.length); - setup_components() { - this.percentage_bar = $$.create('div', { - className: 'progress', - inside: this.chart - }); - } + extra_values.map(function (value, i) { + add_and_animate_line(value, last_line_pos, extra_positions[i], i, group); + }); + } + } + }, { + key: 'make_x_line', + value: function make_x_line(height, text_start_at, point, label_class, axis_line_class, x_pos) { + var allowed_space = this.avg_unit_width * 1.5; + + if (this.get_strwidth(point) > allowed_space) { + var allowed_letters = allowed_space / 8; + point = point.slice(0, allowed_letters - 3) + " ..."; + } - setup_values() { - this.slice_totals = []; - let all_totals = this.data.labels.map((d, i) => { - let total = 0; - this.data.datasets.map(e => { - total += e.values[i]; + var line = $.createSVG('line', { + x1: 0, + x2: 0, + y1: 0, + y2: height }); - return [total, d]; - }).filter(d => { return d[0] > 0; }); // keep only positive results - - let totals = all_totals; - - if(all_totals.length > this.max_slices) { - all_totals.sort((a, b) => { return b[0] - a[0]; }); - totals = all_totals.slice(0, this.max_slices-1); - let others = all_totals.slice(this.max_slices-1); + var text = $.createSVG('text', { + className: label_class, + x: 0, + y: text_start_at, + dy: '.71em', + innerHTML: point + }); - let sum_of_others = 0; - others.map(d => {sum_of_others += d[0];}); + var x_level = $.createSVG('g', { + className: 'tick ' + axis_line_class, + transform: 'translate(' + x_pos + ', 0)' + }); - totals.push([sum_of_others, 'Rest']); + x_level.appendChild(line); + x_level.appendChild(text); - this.colors[this.max_slices-1] = 'grey'; + return x_level; } - - this.labels = []; - totals.map(d => { - this.slice_totals.push(d[0]); - this.labels.push(d[1]); - }); - - this.legend_totals = this.slice_totals.slice(0, this.max_legend_points); - } - - setup_utils() { } - - make_graph_components() { - this.grand_total = this.slice_totals.reduce((a, b) => a + b, 0); - this.slices = []; - this.slice_totals.map((total, i) => { - let slice = $$.create('div', { - className: `progress-bar background ${this.colors[i]}`, - style: `width: ${total*100/this.grand_total}%`, - inside: this.percentage_bar + }, { + key: 'make_y_line', + value: function make_y_line(start_at, width, text_end_at, point, label_class, axis_line_class, y_pos) { + var darker = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false; + var line_type = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : ""; + + var line = $.createSVG('line', { + className: line_type === "dashed" ? "dashed" : "", + x1: start_at, + x2: width, + y1: 0, + y2: 0 }); - this.slices.push(slice); - }); - } - bind_tooltip() { - this.slices.map((slice, i) => { - slice.addEventListener('mouseenter', () => { - let g_off = $$.offset(this.chart_wrapper), p_off = $$.offset(slice); - - let x = p_off.left - g_off.left + slice.offsetWidth/2; - let y = p_off.top - g_off.top - 6; - let title = (this.formatted_labels && this.formatted_labels.length>0 - ? this.formatted_labels[i] : this.labels[i]) + ': '; - let percent = (this.slice_totals[i]*100/this.grand_total).toFixed(1); + var text = $.createSVG('text', { + className: label_class, + x: text_end_at, + y: 0, + dy: '.32em', + innerHTML: point + "" + }); - this.tip.set_values(x, y, title, percent + "%"); - this.tip.show_tip(); + var y_level = $.createSVG('g', { + className: 'tick ' + axis_line_class, + transform: 'translate(0, ' + y_pos + ')' }); - }); - } - show_summary() { - let x_values = this.formatted_labels && this.formatted_labels.length > 0 - ? this.formatted_labels : this.labels; - this.legend_totals.map((d, i) => { - if(d) { - let stats = $$.create('div', { - className: 'stats', - inside: this.stats_wrapper - }); - stats.innerHTML = ` - ${x_values[i]}: - ${d} - `; + if (darker) { + line.style.stroke = "rgba(27, 31, 35, 0.6)"; } - }); - } -}; -frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { - constructor({ - start = '', - domain = '', - subdomain = '', - data = {}, - discrete_domains = 0, - count_label = '' - }) { - super(arguments[0]); - - this.type = 'heatmap'; - - this.domain = domain; - this.subdomain = subdomain; - this.data = data; - this.discrete_domains = discrete_domains; - this.count_label = count_label; + y_level.appendChild(line); + y_level.appendChild(text); - let today = new Date(); - this.start = start || this.add_days(today, 365); + return y_level; + } + }, { + key: 'add_and_animate_y_line', + value: function add_and_animate_y_line(value, old_pos, new_pos, i, group, type) { + var specific = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; + + var _get_y_axis_line_prop3 = this.get_y_axis_line_props(specific), + _get_y_axis_line_prop4 = slicedToArray(_get_y_axis_line_prop3, 4), + width = _get_y_axis_line_prop4[0], + text_end_at = _get_y_axis_line_prop4[1], + axis_line_class = _get_y_axis_line_prop4[2], + start_at = _get_y_axis_line_prop4[3]; + + var axis_label_class = !specific ? 'y-value-text' : 'specific-value'; + value = !specific ? value : (value + "").toUpperCase(); + var y_line = this.make_y_line(start_at, width, text_end_at, value, axis_label_class, axis_line_class, old_pos, // old position + value === 0 && i !== 0, // Non-first Zero line + type); + + group.appendChild(y_line); + + this.elements_to_animate && this.elements_to_animate.push([{ unit: y_line, array: [0], index: 0 }, { transform: '0, ' + new_pos }, 250, "easein", "translate", { transform: '0, ' + old_pos }]); + } + }, { + key: 'get_y_axis_points', + value: function get_y_axis_points(array) { + var _this27 = this; - this.legend_colors = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']; + //*** Where the magic happens *** - this.translate_x = 0; - this.setup(); - } + // Calculates best-fit y intervals from given values + // and returns the interval array - setup_base_values() { - this.today = new Date(); + // TODO: Fractions - if(!this.start) { - this.start = new Date(); - this.start.setFullYear( this.start.getFullYear() - 1 ); - } - this.first_week_start = new Date(this.start.toDateString()); - this.last_week_start = new Date(this.today.toDateString()); - if(this.first_week_start.getDay() !== 7) { - this.add_days(this.first_week_start, (-1) * this.first_week_start.getDay()); - } - if(this.last_week_start.getDay() !== 7) { - this.add_days(this.last_week_start, (-1) * this.last_week_start.getDay()); - } - this.no_of_cols = this.get_weeks_between(this.first_week_start + '', this.last_week_start + '') + 1; - } + var max_bound = void 0, + min_bound = void 0, + pos_no_of_parts = void 0, + neg_no_of_parts = void 0, + part_size = void 0; // eslint-disable-line no-unused-vars - set_width() { - this.base_width = (this.no_of_cols) * 12; + // Critical values + var max_val = parseInt(Math.max.apply(Math, toConsumableArray(array))); + var min_val = parseInt(Math.min.apply(Math, toConsumableArray(array))); + if (min_val >= 0) { + min_val = 0; + } - if(this.discrete_domains) { - this.base_width += (12 * 12); - } - } + var get_params = function get_params(value1, value2) { + var bound1 = void 0, + bound2 = void 0, + no_of_parts_1 = void 0, + no_of_parts_2 = void 0, + interval_size = void 0; + if ((value1 + "").length <= 1) { + bound1 = 10; + no_of_parts_1 = 5; + } else { + var _calc_upper_bound_and = _this27.calc_upper_bound_and_no_of_parts(value1); + + var _calc_upper_bound_and2 = slicedToArray(_calc_upper_bound_and, 2); + + bound1 = _calc_upper_bound_and2[0]; + no_of_parts_1 = _calc_upper_bound_and2[1]; + } - setup_components() { - this.domain_label_group = $$.createSVG("g", { - className: "domain-label-group chart-label", - inside: this.draw_area - }); - this.data_groups = $$.createSVG("g", { - className: "data-groups", - inside: this.draw_area, - transform: `translate(0, 20)` - }); - } + interval_size = bound1 / no_of_parts_1; + no_of_parts_2 = _this27.calc_no_of_parts(value2, interval_size); + bound2 = no_of_parts_2 * interval_size; - setup_values() { - this.domain_label_group.textContent = ''; - this.data_groups.textContent = ''; - this.distribution = this.get_distribution(this.data, this.legend_colors); - this.month_names = ["January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" - ]; + return [bound1, bound2, no_of_parts_1, no_of_parts_2, interval_size]; + }; - this.render_all_weeks_and_store_x_values(this.no_of_cols); - } + var abs_min_val = min_val * -1; + if (abs_min_val <= max_val) { + var _get_params = get_params(max_val, abs_min_val); + // Get the positive region intervals + // then calc negative ones accordingly - render_all_weeks_and_store_x_values(no_of_weeks) { - let current_week_sunday = new Date(this.first_week_start); - this.week_col = 0; - this.current_month = current_week_sunday.getMonth(); - - this.months = [this.current_month + '']; - this.month_weeks = {}, this.month_start_points = []; - this.month_weeks[this.current_month] = 0; - this.month_start_points.push(13); - - for(var i = 0; i < no_of_weeks; i++) { - let data_group, month_change = 0; - let day = new Date(current_week_sunday); - - [data_group, month_change] = this.get_week_squares_group(day, this.week_col); - this.data_groups.appendChild(data_group); - this.week_col += 1 + parseInt(this.discrete_domains && month_change); - this.month_weeks[this.current_month]++; - if(month_change) { - this.current_month = (this.current_month + 1) % 12; - this.months.push(this.current_month + ''); - this.month_weeks[this.current_month] = 1; - } - this.add_days(current_week_sunday, 7); - } - this.render_month_labels(); - } - get_week_squares_group(current_date, index) { - const no_of_weekdays = 7; - const square_side = 10; - const cell_padding = 2; - const step = 1; + var _get_params2 = slicedToArray(_get_params, 5); - let month_change = 0; - let week_col_change = 0; + min_bound = _get_params2[1]; + pos_no_of_parts = _get_params2[2]; + neg_no_of_parts = _get_params2[3]; + part_size = _get_params2[4]; - let data_group = $$.createSVG("g", { - className: "data-group", - inside: this.data_groups - }); + if (abs_min_val === 0) { + min_bound = 0;neg_no_of_parts = 0; + } + } else { + var _get_params3 = get_params(abs_min_val, max_val); + // Get the negative region here first - for(var y = 0, i = 0; i < no_of_weekdays; i += step, y += (square_side + cell_padding)) { - let data_value = 0; - let color_index = 0; - let timestamp = Math.floor(current_date.getTime()/1000).toFixed(1); + var _get_params4 = slicedToArray(_get_params3, 5); - if(this.data[timestamp]) { - data_value = this.data[timestamp]; - color_index = this.get_max_checkpoint(data_value, this.distribution); + min_bound = _get_params4[0]; + neg_no_of_parts = _get_params4[2]; + pos_no_of_parts = _get_params4[3]; + part_size = _get_params4[4]; } - if(this.data[Math.round(timestamp)]) { - data_value = this.data[Math.round(timestamp)]; - color_index = this.get_max_checkpoint(data_value, this.distribution); + // Make both region parts even + if (pos_no_of_parts % 2 !== 0 && neg_no_of_parts > 0) pos_no_of_parts++; + if (neg_no_of_parts % 2 !== 0) { + // every increase in no_of_parts entails an increase in corresponding bound + // except here, it happens implicitly after every calc_no_of_parts() call + neg_no_of_parts++; + min_bound += part_size; } - let x = 13 + (index + week_col_change) * 12; - - $$.createSVG("rect", { - className: 'day', - inside: data_group, - x: x, - y: y, - width: square_side, - height: square_side, - fill: this.legend_colors[color_index], - 'data-date': this.get_dd_mm_yyyy(current_date), - 'data-value': data_value, - 'data-day': current_date.getDay() - }); - - let next_date = new Date(current_date); - this.add_days(next_date, 1); - if(next_date.getMonth() - current_date.getMonth()) { - month_change = 1; - if(this.discrete_domains) { - week_col_change = 1; - } + var no_of_parts = pos_no_of_parts + neg_no_of_parts; + if (no_of_parts > 5) { + no_of_parts /= 2; + part_size *= 2; + } - this.month_start_points.push(13 + (index + week_col_change) * 12); + return this.get_intervals(-1 * min_bound, part_size, no_of_parts); + } + }, { + key: 'get_intervals', + value: function get_intervals(start, interval_size, count) { + var intervals = []; + for (var i = 0; i <= count; i++) { + intervals.push(start); + start += interval_size; } - current_date = next_date; + return intervals; } + }, { + key: 'calc_upper_bound_and_no_of_parts', + value: function calc_upper_bound_and_no_of_parts(max_val) { + // Given a positive value, calculates a nice-number upper bound + // and a consequent optimal number of parts - return [data_group, month_change]; - } + var part_size = Math.pow(10, (max_val + "").length - 1); + var no_of_parts = this.calc_no_of_parts(max_val, part_size); - render_month_labels() { - // this.first_month_label = 1; - // if (this.first_week_start.getDate() > 8) { - // this.first_month_label = 0; - // } - // this.last_month_label = 1; - - // let first_month = this.months.shift(); - // let first_month_start = this.month_start_points.shift(); - // render first month if - - // let last_month = this.months.pop(); - // let last_month_start = this.month_start_points.pop(); - // render last month if - - this.months.shift(); - this.month_start_points.shift(); - this.months.pop(); - this.month_start_points.pop(); - - this.month_start_points.map((start, i) => { - let month_name = this.month_names[this.months[i]].substring(0, 3); - - $$.createSVG('text', { - className: 'y-value-text', - inside: this.domain_label_group, - x: start + 12, - y: 10, - dy: '.32em', - innerHTML: month_name - }); + // Use it to get a nice even upper bound + var upper_bound = part_size * no_of_parts; - }); - } - - make_graph_components() { - Array.prototype.slice.call( - this.container.querySelectorAll('.graph-stats-container, .sub-title, .title') - ).map(d => { - d.style.display = 'None'; - }); - this.chart_wrapper.style.marginTop = '0px'; - this.chart_wrapper.style.paddingTop = '0px'; - } + return [upper_bound, no_of_parts]; + } + }, { + key: 'calc_no_of_parts', + value: function calc_no_of_parts(value, divisor) { + // value should be a positive number, divisor should be greater than 0 + // returns an even no of parts + var no_of_parts = Math.ceil(value / divisor); + if (no_of_parts % 2 !== 0) no_of_parts++; // Make it an even number + + return no_of_parts; + } + }, { + key: 'get_optimal_no_of_parts', + value: function get_optimal_no_of_parts(no_of_parts) { + // aka Divide by 2 if too large + return no_of_parts < 5 ? no_of_parts : no_of_parts / 2; + } + }, { + key: 'set_avg_unit_width_and_x_offset', + value: function set_avg_unit_width_and_x_offset() { + // Set the ... you get it + this.avg_unit_width = this.width / (this.x.length - 1); + this.x_offset = 0; + } + }, { + key: 'get_all_y_values', + value: function get_all_y_values() { + var all_values = []; + + // Add in all the y values in the datasets + this.y.map(function (d) { + all_values = all_values.concat(d.values); + }); - bind_tooltip() { - Array.prototype.slice.call( - document.querySelectorAll(".data-group .day") - ).map(el => { - el.addEventListener('mouseenter', (e) => { - let count = e.target.getAttribute('data-value'); - let date_parts = e.target.getAttribute('data-date').split('-'); + // Add in all the specific values + return all_values.concat(this.specific_values.map(function (d) { + return d.value; + })); + } + }, { + key: 'calc_y_dependencies', + value: function calc_y_dependencies() { + var _this28 = this; + + this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999); + this.y.map(function (d) { + d.y_tops = d.values.map(function (val) { + return float_2(_this28.zero_line - val * _this28.multiplier); + }); + d.y_tops.map(function (y_top, i) { + if (y_top < _this28.y_min_tops[i]) { + _this28.y_min_tops[i] = y_top; + } + }); + }); + } + }, { + key: 'get_bar_height_and_y_attr', + value: function get_bar_height_and_y_attr(y_top) { + var height = void 0, + y = void 0; + if (y_top <= this.zero_line) { + height = this.zero_line - y_top; + y = y_top; + + // In case of invisible bars + if (height === 0) { + height = this.height * 0.01; + y -= height; + } + } else { + height = y_top - this.zero_line; + y = this.zero_line; - let month = this.month_names[parseInt(date_parts[1])-1].substring(0, 3); + // In case of invisible bars + if (height === 0) { + height = this.height * 0.01; + } + } - let g_off = this.chart_wrapper.getBoundingClientRect(), p_off = e.target.getBoundingClientRect(); + return [height, y]; + } + }, { + key: 'setup_utils', + value: function setup_utils() { + var _this29 = this; + + this.draw = { + 'bar': function bar(x, y_top, args, color, index, no_of_datasets) { + var total_width = _this29.avg_unit_width - args.space_width; + var start_x = x - total_width / 2; + + var width = total_width / no_of_datasets; + var current_x = start_x + width * index; + + var _get_bar_height_and_y = _this29.get_bar_height_and_y_attr(y_top), + _get_bar_height_and_y2 = slicedToArray(_get_bar_height_and_y, 2), + height = _get_bar_height_and_y2[0], + y = _get_bar_height_and_y2[1]; + + return $.createSVG('rect', { + className: 'bar mini fill ' + color, + x: current_x, + y: y, + width: width, + height: height + }); + }, + 'dot': function dot(x, y, args, color) { + return $.createSVG('circle', { + className: 'fill ' + color, + cx: x, + cy: y, + r: args.radius + }); + } + }; + + this.animate = { + 'bar': function bar(bar_obj, x, y_top, index) { + var start = x - _this29.avg_unit_width / 4; + var width = _this29.avg_unit_width / 2 / _this29.y.length; + + var _get_bar_height_and_y3 = _this29.get_bar_height_and_y_attr(y_top), + _get_bar_height_and_y4 = slicedToArray(_get_bar_height_and_y3, 2), + height = _get_bar_height_and_y4[0], + y = _get_bar_height_and_y4[1]; + + x = start + width * index; + + return [bar_obj, { width: width, height: height, x: x, y: y }, 250, "easein"]; + // bar.animate({height: args.new_height, y: y_top}, 250, mina.easein); + }, + 'dot': function dot(dot_obj, x, y_top) { + return [dot_obj, { cx: x, cy: y_top }, 300, "easein"]; + // dot.animate({cy: y_top}, 250, mina.easein); + } + }; + } + }]); + return AxisChart; +}(Chart); + +var BarChart = function (_AxisChart) { + inherits(BarChart, _AxisChart); + + function BarChart(args) { + classCallCheck(this, BarChart); + + var _this30 = possibleConstructorReturn(this, (BarChart.__proto__ || Object.getPrototypeOf(BarChart)).call(this, args)); + + _this30.type = 'bar'; + _this30.x_axis_mode = args.x_axis_mode || 'tick'; + _this30.y_axis_mode = args.y_axis_mode || 'span'; + _this30.setup(); + return _this30; + } + + createClass(BarChart, [{ + key: 'setup_values', + value: function setup_values() { + get(BarChart.prototype.__proto__ || Object.getPrototypeOf(BarChart.prototype), 'setup_values', this).call(this); + this.x_offset = this.avg_unit_width; + this.unit_args = { + type: 'bar', + args: { + space_width: this.avg_unit_width / 2 + } + }; + } + }, { + key: 'make_overlay', + value: function make_overlay() { + // Just make one out of the first element + var index = this.x.length - 1; + var unit = this.y[0].svg_units[index]; + this.update_current_data_point(index); + + if (this.overlay) { + this.overlay.parentNode.removeChild(this.overlay); + } - let width = parseInt(e.target.getAttribute('width')); - let x = p_off.left - g_off.left + (width+2)/2; - let y = p_off.top - g_off.top - (width+2)/2; - let value = count + ' ' + this.count_label; - let name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2]; + this.overlay = unit.cloneNode(); + this.overlay.style.fill = '#000000'; + this.overlay.style.opacity = '0.4'; + this.draw_area.appendChild(this.overlay); + } + }, { + key: 'bind_overlay', + value: function bind_overlay() { + var _this31 = this; + + // on event, update overlay + this.parent.addEventListener('data-select', function (e) { + _this31.update_overlay(e.svg_unit); + }); + } + }, { + key: 'update_overlay', + value: function update_overlay(unit) { + var _this32 = this; + + var attributes = []; + Object.keys(unit.attributes).map(function (index) { + attributes.push(unit.attributes[index]); + }); - this.tip.set_values(x, y, name, value, [], 1); - this.tip.show_tip(); + attributes.filter(function (attr) { + return attr.specified; + }).map(function (attr) { + _this32.overlay.setAttribute(attr.name, attr.nodeValue); }); - }); - } + } + }, { + key: 'on_left_arrow', + value: function on_left_arrow() { + this.update_current_data_point(this.current_index - 1); + } + }, { + key: 'on_right_arrow', + value: function on_right_arrow() { + this.update_current_data_point(this.current_index + 1); + } + }, { + key: 'set_avg_unit_width_and_x_offset', + value: function set_avg_unit_width_and_x_offset() { + this.avg_unit_width = this.width / (this.x.length + 1); + this.x_offset = this.avg_unit_width; + } + }]); + return BarChart; +}(AxisChart); - update(data) { - this.data = data; - this.setup_values(); - this.bind_tooltip(); - } +var LineChart = function (_AxisChart2) { + inherits(LineChart, _AxisChart2); - get_distribution(data={}, mapper_array) { - let data_values = Object.keys(data).map(key => data[key]); - let data_max_value = Math.max(...data_values); + function LineChart(args) { + classCallCheck(this, LineChart); - let distribution_step = 1 / (mapper_array.length - 1); - let distribution = []; + var _this33 = possibleConstructorReturn(this, (LineChart.__proto__ || Object.getPrototypeOf(LineChart)).call(this, args)); - mapper_array.map((color, i) => { - let checkpoint = data_max_value * (distribution_step * i); - distribution.push(checkpoint); - }); + if (Object.getPrototypeOf(_this33) !== LineChart.prototype) { + return possibleConstructorReturn(_this33); + } - return distribution; - } + _this33.type = 'line'; + _this33.region_fill = args.region_fill; + _this33.x_axis_mode = args.x_axis_mode || 'span'; + _this33.y_axis_mode = args.y_axis_mode || 'span'; - get_max_checkpoint(value, distribution) { - return distribution.filter((d, i) => { - if(i === 1) { - return distribution[0] < value; - } - return d <= value; - }).length - 1; + _this33.setup(); + return _this33; } - // TODO: date utils, move these out - - // https://stackoverflow.com/a/11252167/6495043 - treat_as_utc(date_str) { - let result = new Date(date_str); - result.setMinutes(result.getMinutes() - result.getTimezoneOffset()); - return result; - } + createClass(LineChart, [{ + key: 'setup_graph_components', + value: function setup_graph_components() { + this.setup_path_groups(); + get(LineChart.prototype.__proto__ || Object.getPrototypeOf(LineChart.prototype), 'setup_graph_components', this).call(this); + } + }, { + key: 'setup_path_groups', + value: function setup_path_groups() { + var _this34 = this; + + this.paths_groups = []; + this.y.map(function (d, i) { + _this34.paths_groups[i] = $.createSVG('g', { + className: 'path-group path-group-' + i, + inside: _this34.draw_area + }); + }); + } + }, { + key: 'setup_values', + value: function setup_values() { + get(LineChart.prototype.__proto__ || Object.getPrototypeOf(LineChart.prototype), 'setup_values', this).call(this); + this.unit_args = { + type: 'dot', + args: { radius: 8 } + }; + } + }, { + key: 'make_paths', + value: function make_paths() { + var _this35 = this; - get_dd_mm_yyyy(date) { - let dd = date.getDate(); - let mm = date.getMonth() + 1; // getMonth() is zero-based - return [ - (dd>9 ? '' : '0') + dd, - (mm>9 ? '' : '0') + mm, - date.getFullYear() - ].join('-'); - } + this.y.map(function (d, i) { + _this35.make_path(d, i, _this35.x_axis_positions, d.y_tops, d.color || _this35.colors[i]); + }); + } + }, { + key: 'make_path', + value: function make_path(d, i, x_positions, y_positions, color) { + var points_list = y_positions.map(function (y, i) { + return x_positions[i] + ',' + y; + }); + var points_str = points_list.join("L"); - get_weeks_between(start_date_str, end_date_str) { - return Math.ceil(this.get_days_between(start_date_str, end_date_str) / 7); - } + this.paths_groups[i].textContent = ''; - get_days_between(start_date_str, end_date_str) { - let milliseconds_per_day = 24 * 60 * 60 * 1000; - return (this.treat_as_utc(end_date_str) - this.treat_as_utc(start_date_str)) / milliseconds_per_day; - } + d.path = $.createSVG('path', { + inside: this.paths_groups[i], + className: 'stroke ' + color, + d: "M" + points_str + }); - // mutates - add_days(date, number_of_days) { - date.setDate(date.getDate() + number_of_days); - } + if (this.region_fill) { + var gradient_id = 'path-fill-gradient' + '-' + color; - get_month_name() {} -}; + this.gradient_def = $.createSVG('linearGradient', { + inside: this.svg_defs, + id: gradient_id, + x1: 0, + x2: 0, + y1: 0, + y2: 1 + }); -frappe.chart.SvgTip = class { - constructor({ - parent = null - }) { - this.parent = parent; - this.title_name = ''; - this.title_value = ''; - this.list_values = []; - this.title_value_first = 0; + var set_gradient_stop = function set_gradient_stop(grad_elem, offset, color, opacity) { + $.createSVG('stop', { + 'className': 'stop-color ' + color, + 'inside': grad_elem, + 'offset': offset, + 'stop-opacity': opacity + }); + }; + + set_gradient_stop(this.gradient_def, "0%", color, 0.4); + set_gradient_stop(this.gradient_def, "50%", color, 0.2); + set_gradient_stop(this.gradient_def, "100%", color, 0); + + d.region_path = $.createSVG('path', { + inside: this.paths_groups[i], + className: 'region-fill', + d: "M" + ('0,' + this.zero_line + 'L') + points_str + ('L' + this.width + ',' + this.zero_line) + }); - this.x = 0; - this.y = 0; + d.region_path.style.stroke = "none"; + d.region_path.style.fill = 'url(#' + gradient_id + ')'; + } + } + }]); + return LineChart; +}(AxisChart); - this.top = 0; - this.left = 0; +var PercentageChart = function (_Chart2) { + inherits(PercentageChart, _Chart2); - this.setup(); - } + function PercentageChart(args) { + classCallCheck(this, PercentageChart); - setup() { - this.make_tooltip(); - } + var _this36 = possibleConstructorReturn(this, (PercentageChart.__proto__ || Object.getPrototypeOf(PercentageChart)).call(this, args)); - refresh() { - this.fill(); - this.calc_position(); - // this.show_tip(); - } + _this36.type = 'percentage'; - make_tooltip() { - this.container = $$.create('div', { - inside: this.parent, - className: 'graph-svg-tip comparison', - innerHTML: ` - -
` - }); - this.hide_tip(); + _this36.get_y_label = _this36.format_lambdas.y_label; + _this36.get_x_tooltip = _this36.format_lambdas.x_tooltip; + _this36.get_y_tooltip = _this36.format_lambdas.y_tooltip; - this.title = this.container.querySelector('.title'); - this.data_point_list = this.container.querySelector('.data-point-list'); + _this36.max_slices = 10; + _this36.max_legend_points = 6; - this.parent.addEventListener('mouseleave', () => { - this.hide_tip(); - }); - } + _this36.colors = args.colors; - fill() { - let title; - if(this.title_value_first) { - title = `${this.title_value}${this.title_name}`; - } else { - title = `${this.title_name}${this.title_value}`; + if (!_this36.colors || _this36.colors.length < _this36.data.labels.length) { + _this36.colors = ['light-blue', 'blue', 'violet', 'red', 'orange', 'yellow', 'green', 'light-green', 'purple', 'magenta']; } - this.title.innerHTML = title; - this.data_point_list.innerHTML = ''; - - this.list_values.map((set) => { - let li = $$.create('li', { - className: `border-top ${set.color || 'black'}`, - innerHTML: `${set.value ? set.value : '' } - ${set.title ? set.title : '' }` - }); - this.data_point_list.appendChild(li); - }); + _this36.setup(); + return _this36; } - calc_position() { - this.top = this.y - this.container.offsetHeight; - this.left = this.x - this.container.offsetWidth/2; - let max_left = this.parent.offsetWidth - this.container.offsetWidth; + createClass(PercentageChart, [{ + key: 'make_chart_area', + value: function make_chart_area() { + this.chart_wrapper.className += ' ' + 'graph-focus-margin'; + this.chart_wrapper.style.marginTop = '45px'; - let pointer = this.container.querySelector('.svg-pointer'); - - if(this.left < 0) { - pointer.style.left = `calc(50% - ${-1 * this.left}px)`; - this.left = 0; - } else if(this.left > max_left) { - let delta = this.left - max_left; - pointer.style.left = `calc(50% + ${delta}px)`; - this.left = max_left; - } else { - pointer.style.left = `50%`; + this.stats_wrapper.className += ' ' + 'graph-focus-margin'; + this.stats_wrapper.style.marginBottom = '30px'; + this.stats_wrapper.style.paddingTop = '0px'; } - } - - set_values(x, y, title_name = '', title_value = '', list_values = [], title_value_first = 0) { - this.title_name = title_name; - this.title_value = title_value; - this.list_values = list_values; - this.x = x; - this.y = y; - this.title_value_first = title_value_first; - this.refresh(); - } - - hide_tip() { - this.container.style.top = '0px'; - this.container.style.left = '0px'; - this.container.style.opacity = '0'; - } - - show_tip() { - this.container.style.top = this.top + 'px'; - this.container.style.left = this.left + 'px'; - this.container.style.opacity = '1'; - } -}; - -// Helpers -frappe.chart.utils = {}; -$$.float_2 = d => parseFloat(d.toFixed(2)); -function $$(expr, con) { - return typeof expr === "string"? (con || document).querySelector(expr) : expr || null; -} - -$$.arrays_equal = (arr1, arr2) => { - if(arr1.length !== arr2.length) return false; - let are_equal = true; - arr1.map((d, i) => { - if(arr2[i] !== d) are_equal = false; - }); - return are_equal; -}; - -$$.shuffle = (array) => { - // https://stackoverflow.com/a/2450976/6495043 - // Awesomeness: https://bost.ocks.org/mike/shuffle/ - - var currentIndex = array.length, temporaryValue, randomIndex; + }, { + key: 'make_draw_area', + value: function make_draw_area() { + this.chart_div = $.create('div', { + className: 'div', + inside: this.chart_wrapper, + width: this.base_width, + height: this.base_height + }); - // While there remain elements to shuffle... - while (0 !== currentIndex) { + this.chart = $.create('div', { + className: 'progress-chart', + inside: this.chart_div + }); + } + }, { + key: 'setup_components', + value: function setup_components() { + this.percentage_bar = $.create('div', { + className: 'progress', + inside: this.chart + }); + } + }, { + key: 'setup_values', + value: function setup_values() { + var _this37 = this; + + this.slice_totals = []; + var all_totals = this.data.labels.map(function (d, i) { + var total = 0; + _this37.data.datasets.map(function (e) { + total += e.values[i]; + }); + return [total, d]; + }).filter(function (d) { + return d[0] > 0; + }); // keep only positive results - // Pick a remaining element... - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex -= 1; + var totals = all_totals; - // And swap it with the current element. - temporaryValue = array[currentIndex]; - array[currentIndex] = array[randomIndex]; - array[randomIndex] = temporaryValue; - } + if (all_totals.length > this.max_slices) { + all_totals.sort(function (a, b) { + return b[0] - a[0]; + }); - return array; + totals = all_totals.slice(0, this.max_slices - 1); + var others = all_totals.slice(this.max_slices - 1); -}; + var sum_of_others = 0; + others.map(function (d) { + sum_of_others += d[0]; + }); -// $$.findNodeIndex = (node) => -// { -// var i = 0; -// while (node = node.previousSibling) { -// if (node.nodeType === 1) { ++i; } -// } -// return i; -// } + totals.push([sum_of_others, 'Rest']); -$$.create = function(tag, o) { - var element = document.createElement(tag); + this.colors[this.max_slices - 1] = 'grey'; + } - for (var i in o) { - var val = o[i]; + this.labels = []; + totals.map(function (d) { + _this37.slice_totals.push(d[0]); + _this37.labels.push(d[1]); + }); - if (i === "inside") { - $$(val).appendChild(element); + this.legend_totals = this.slice_totals.slice(0, this.max_legend_points); } - else if (i === "around") { - var ref = $$(val); - ref.parentNode.insertBefore(element, ref); - element.appendChild(ref); + }, { + key: 'setup_utils', + value: function setup_utils() {} + }, { + key: 'make_graph_components', + value: function make_graph_components() { + var _this38 = this; + + this.grand_total = this.slice_totals.reduce(function (a, b) { + return a + b; + }, 0); + this.slices = []; + this.slice_totals.map(function (total, i) { + var slice = $.create('div', { + className: 'progress-bar background ' + _this38.colors[i], + style: 'width: ' + total * 100 / _this38.grand_total + '%', + inside: _this38.percentage_bar + }); + _this38.slices.push(slice); + }); } - else if (i in element) { - element[i] = val; + }, { + key: 'bind_tooltip', + value: function bind_tooltip() { + var _this39 = this; + + this.slices.map(function (slice, i) { + slice.addEventListener('mouseenter', function () { + var g_off = $.offset(_this39.chart_wrapper), + p_off = $.offset(slice); + + var x = p_off.left - g_off.left + slice.offsetWidth / 2; + var y = p_off.top - g_off.top - 6; + var title = (_this39.formatted_labels && _this39.formatted_labels.length > 0 ? _this39.formatted_labels[i] : _this39.labels[i]) + ': '; + var percent = (_this39.slice_totals[i] * 100 / _this39.grand_total).toFixed(1); + + _this39.tip.set_values(x, y, title, percent + "%"); + _this39.tip.show_tip(); + }); + }); } - else { - element.setAttribute(i, val); + }, { + key: 'show_summary', + value: function show_summary() { + var _this40 = this; + + var x_values = this.formatted_labels && this.formatted_labels.length > 0 ? this.formatted_labels : this.labels; + this.legend_totals.map(function (d, i) { + if (d) { + var stats = $.create('div', { + className: 'stats', + inside: _this40.stats_wrapper + }); + stats.innerHTML = '\n\t\t\t\t\t' + x_values[i] + ':\n\t\t\t\t\t' + d + '\n\t\t\t\t'; + } + }); } - } - - return element; -}; - -$$.createSVG = function(tag, o) { - var element = document.createElementNS("http://www.w3.org/2000/svg", tag); - - for (var i in o) { - var val = o[i]; + }]); + return PercentageChart; +}(Chart); + +var HeatMap = function (_Chart3) { + inherits(HeatMap, _Chart3); + + function HeatMap(_ref2) { + var _ref2$start = _ref2.start, + start = _ref2$start === undefined ? '' : _ref2$start, + _ref2$domain = _ref2.domain, + domain = _ref2$domain === undefined ? '' : _ref2$domain, + _ref2$subdomain = _ref2.subdomain, + subdomain = _ref2$subdomain === undefined ? '' : _ref2$subdomain, + _ref2$data = _ref2.data, + data = _ref2$data === undefined ? {} : _ref2$data, + _ref2$discrete_domain = _ref2.discrete_domains, + discrete_domains = _ref2$discrete_domain === undefined ? 0 : _ref2$discrete_domain, + _ref2$count_label = _ref2.count_label, + count_label = _ref2$count_label === undefined ? '' : _ref2$count_label; + classCallCheck(this, HeatMap); + + var _this41 = possibleConstructorReturn(this, (HeatMap.__proto__ || Object.getPrototypeOf(HeatMap)).call(this, arguments[0])); + + _this41.type = 'heatmap'; + + _this41.domain = domain; + _this41.subdomain = subdomain; + _this41.data = data; + _this41.discrete_domains = discrete_domains; + _this41.count_label = count_label; + + var today = new Date(); + _this41.start = start || _this41.add_days(today, 365); + + _this41.legend_colors = ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']; + + _this41.translate_x = 0; + _this41.setup(); + return _this41; + } + + createClass(HeatMap, [{ + key: 'setup_base_values', + value: function setup_base_values() { + this.today = new Date(); + + if (!this.start) { + this.start = new Date(); + this.start.setFullYear(this.start.getFullYear() - 1); + } + this.first_week_start = new Date(this.start.toDateString()); + this.last_week_start = new Date(this.today.toDateString()); + if (this.first_week_start.getDay() !== 7) { + this.add_days(this.first_week_start, -1 * this.first_week_start.getDay()); + } + if (this.last_week_start.getDay() !== 7) { + this.add_days(this.last_week_start, -1 * this.last_week_start.getDay()); + } + this.no_of_cols = this.get_weeks_between(this.first_week_start + '', this.last_week_start + '') + 1; + } + }, { + key: 'set_width', + value: function set_width() { + this.base_width = this.no_of_cols * 12; - if (i === "inside") { - $$(val).appendChild(element); + if (this.discrete_domains) { + this.base_width += 12 * 12; + } } - else if (i === "around") { - var ref = $$(val); - ref.parentNode.insertBefore(element, ref); - element.appendChild(ref); + }, { + key: 'setup_components', + value: function setup_components() { + this.domain_label_group = $.createSVG("g", { + className: "domain-label-group chart-label", + inside: this.draw_area + }); + this.data_groups = $.createSVG("g", { + className: "data-groups", + inside: this.draw_area, + transform: 'translate(0, 20)' + }); } - else { - if(i === "className") { i = "class"; } - if(i === "innerHTML") { - element['textContent'] = val; - } else { - element.setAttribute(i, val); + }, { + key: 'setup_values', + value: function setup_values() { + this.domain_label_group.textContent = ''; + this.data_groups.textContent = ''; + this.distribution = this.get_distribution(this.data, this.legend_colors); + this.month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + + this.render_all_weeks_and_store_x_values(this.no_of_cols); + } + }, { + key: 'render_all_weeks_and_store_x_values', + value: function render_all_weeks_and_store_x_values(no_of_weeks) { + var current_week_sunday = new Date(this.first_week_start); + this.week_col = 0; + this.current_month = current_week_sunday.getMonth(); + + this.months = [this.current_month + '']; + this.month_weeks = {}, this.month_start_points = []; + this.month_weeks[this.current_month] = 0; + this.month_start_points.push(13); + + for (var i = 0; i < no_of_weeks; i++) { + var data_group = void 0, + month_change = 0; + var day = new Date(current_week_sunday); + + var _get_week_squares_gro = this.get_week_squares_group(day, this.week_col); + + var _get_week_squares_gro2 = slicedToArray(_get_week_squares_gro, 2); + + data_group = _get_week_squares_gro2[0]; + month_change = _get_week_squares_gro2[1]; + + this.data_groups.appendChild(data_group); + this.week_col += 1 + parseInt(this.discrete_domains && month_change); + this.month_weeks[this.current_month]++; + if (month_change) { + this.current_month = (this.current_month + 1) % 12; + this.months.push(this.current_month + ''); + this.month_weeks[this.current_month] = 1; + } + this.add_days(current_week_sunday, 7); } + this.render_month_labels(); } - } - - return element; -}; + }, { + key: 'get_week_squares_group', + value: function get_week_squares_group(current_date, index) { + var no_of_weekdays = 7; + var square_side = 10; + var cell_padding = 2; + var step = 1; + + var month_change = 0; + var week_col_change = 0; + + var data_group = $.createSVG("g", { + className: "data-group", + inside: this.data_groups + }); -$$.runSVGAnimation = (svg_container, elements) => { - // let parent = elements[0][0]['unit'].parentNode; + for (var y = 0, i = 0; i < no_of_weekdays; i += step, y += square_side + cell_padding) { + var data_value = 0; + var color_index = 0; - let new_elements = []; - let anim_elements = []; + var timestamp = Math.floor(current_date.getTime() / 1000).toFixed(1); - elements.map(element => { - let obj = element[0]; - let parent = obj.unit.parentNode; - // let index = $$.findNodeIndex(obj.unit); + if (this.data[timestamp]) { + data_value = this.data[timestamp]; + color_index = this.get_max_checkpoint(data_value, this.distribution); + } - let anim_element, new_element; + if (this.data[Math.round(timestamp)]) { + data_value = this.data[Math.round(timestamp)]; + color_index = this.get_max_checkpoint(data_value, this.distribution); + } - element[0] = obj.unit; + var x = 13 + (index + week_col_change) * 12; - [anim_element, new_element] = $$.animateSVG(...element); + $.createSVG("rect", { + className: 'day', + inside: data_group, + x: x, + y: y, + width: square_side, + height: square_side, + fill: this.legend_colors[color_index], + 'data-date': this.get_dd_mm_yyyy(current_date), + 'data-value': data_value, + 'data-day': current_date.getDay() + }); - new_elements.push(new_element); - anim_elements.push([anim_element, parent]); + var next_date = new Date(current_date); + this.add_days(next_date, 1); + if (next_date.getMonth() - current_date.getMonth()) { + month_change = 1; + if (this.discrete_domains) { + week_col_change = 1; + } - parent.replaceChild(anim_element, obj.unit); + this.month_start_points.push(13 + (index + week_col_change) * 12); + } + current_date = next_date; + } - if(obj.array) { - obj.array[obj.index] = new_element; - } else { - obj.object[obj.key] = new_element; + return [data_group, month_change]; } - }); + }, { + key: 'render_month_labels', + value: function render_month_labels() { + var _this42 = this; + + // this.first_month_label = 1; + // if (this.first_week_start.getDate() > 8) { + // this.first_month_label = 0; + // } + // this.last_month_label = 1; + + // let first_month = this.months.shift(); + // let first_month_start = this.month_start_points.shift(); + // render first month if + + // let last_month = this.months.pop(); + // let last_month_start = this.month_start_points.pop(); + // render last month if + + this.months.shift(); + this.month_start_points.shift(); + this.months.pop(); + this.month_start_points.pop(); + + this.month_start_points.map(function (start, i) { + var month_name = _this42.month_names[_this42.months[i]].substring(0, 3); + + $.createSVG('text', { + className: 'y-value-text', + inside: _this42.domain_label_group, + x: start + 12, + y: 10, + dy: '.32em', + innerHTML: month_name + }); + }); + } + }, { + key: 'make_graph_components', + value: function make_graph_components() { + Array.prototype.slice.call(this.container.querySelectorAll('.graph-stats-container, .sub-title, .title')).map(function (d) { + d.style.display = 'None'; + }); + this.chart_wrapper.style.marginTop = '0px'; + this.chart_wrapper.style.paddingTop = '0px'; + } + }, { + key: 'bind_tooltip', + value: function bind_tooltip() { + var _this43 = this; - let anim_svg = svg_container.cloneNode(true); + Array.prototype.slice.call(document.querySelectorAll(".data-group .day")).map(function (el) { + el.addEventListener('mouseenter', function (e) { + var count = e.target.getAttribute('data-value'); + var date_parts = e.target.getAttribute('data-date').split('-'); - anim_elements.map((anim_element, i) => { - anim_element[1].replaceChild(new_elements[i], anim_element[0]); - elements[i][0] = new_elements[i]; - }); + var month = _this43.month_names[parseInt(date_parts[1]) - 1].substring(0, 3); - return anim_svg; -}; + var g_off = _this43.chart_wrapper.getBoundingClientRect(), + p_off = e.target.getBoundingClientRect(); -// $$.animateMotion = (element, props, dur, easing_type="linear") + var width = parseInt(e.target.getAttribute('width')); + var x = p_off.left - g_off.left + (width + 2) / 2; + var y = p_off.top - g_off.top - (width + 2) / 2; + var value = count + ' ' + _this43.count_label; + var name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2]; -$$.animateSVG = (element, props, dur, easing_type="linear", type=undefined, old_values={}) => { - let easing = { - ease: "0.25 0.1 0.25 1", - linear: "0 0 1 1", - // easein: "0.42 0 1 1", - easein: "0.1 0.8 0.2 1", - easeout: "0 0 0.58 1", - easeinout: "0.42 0 0.58 1" - }; + _this43.tip.set_values(x, y, name, value, [], 1); + _this43.tip.show_tip(); + }); + }); + } + }, { + key: 'update', + value: function update(data) { + this.data = data; + this.setup_values(); + this.bind_tooltip(); + } + }, { + key: 'get_distribution', + value: function get_distribution() { + var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var mapper_array = arguments[1]; + + var data_values = Object.keys(data).map(function (key) { + return data[key]; + }); + var data_max_value = Math.max.apply(Math, toConsumableArray(data_values)); - let anim_element = element.cloneNode(true); - let new_element = element.cloneNode(true); + var distribution_step = 1 / (mapper_array.length - 1); + var distribution = []; - for(var attributeName in props) { - let animate_element; - if(attributeName === 'transform') { - animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform"); - } else { - animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate"); + mapper_array.map(function (color, i) { + var checkpoint = data_max_value * (distribution_step * i); + distribution.push(checkpoint); + }); + + return distribution; + } + }, { + key: 'get_max_checkpoint', + value: function get_max_checkpoint(value, distribution) { + return distribution.filter(function (d, i) { + if (i === 1) { + return distribution[0] < value; + } + return d <= value; + }).length - 1; } - let current_value = old_values[attributeName] || element.getAttribute(attributeName); - let value = props[attributeName]; - let anim_attr = { - attributeName: attributeName, - from: current_value, - to: value, - begin: "0s", - dur: dur/1000 + "s", - values: current_value + ";" + value, - keySplines: easing[easing_type], - keyTimes: "0;1", - calcMode: "spline", - fill: 'freeze' - }; + // TODO: date utils, move these out - if(type) { - anim_attr["type"] = type; - } + // https://stackoverflow.com/a/11252167/6495043 - for (var i in anim_attr) { - animate_element.setAttribute(i, anim_attr[i]); + }, { + key: 'treat_as_utc', + value: function treat_as_utc(date_str) { + var result = new Date(date_str); + result.setMinutes(result.getMinutes() - result.getTimezoneOffset()); + return result; + } + }, { + key: 'get_dd_mm_yyyy', + value: function get_dd_mm_yyyy(date) { + var dd = date.getDate(); + var mm = date.getMonth() + 1; // getMonth() is zero-based + return [(dd > 9 ? '' : '0') + dd, (mm > 9 ? '' : '0') + mm, date.getFullYear()].join('-'); + } + }, { + key: 'get_weeks_between', + value: function get_weeks_between(start_date_str, end_date_str) { + return Math.ceil(this.get_days_between(start_date_str, end_date_str) / 7); + } + }, { + key: 'get_days_between', + value: function get_days_between(start_date_str, end_date_str) { + var milliseconds_per_day = 24 * 60 * 60 * 1000; + return (this.treat_as_utc(end_date_str) - this.treat_as_utc(start_date_str)) / milliseconds_per_day; } - anim_element.appendChild(animate_element); + // mutates - if(type) { - new_element.setAttribute(attributeName, `translate(${value})`); - } else { - new_element.setAttribute(attributeName, value); + }, { + key: 'add_days', + value: function add_days(date, number_of_days) { + date.setDate(date.getDate() + number_of_days); } - } + }, { + key: 'get_month_name', + value: function get_month_name() {} + }]); + return HeatMap; +}(Chart); + +var SvgTip = function () { + function SvgTip(_ref3) { + var _ref3$parent = _ref3.parent, + parent = _ref3$parent === undefined ? null : _ref3$parent; + classCallCheck(this, SvgTip); - return [anim_element, new_element]; -}; + this.parent = parent; + this.title_name = ''; + this.title_value = ''; + this.list_values = []; + this.title_value_first = 0; -$$.offset = (element) => { - let rect = element.getBoundingClientRect(); - return { - // https://stackoverflow.com/a/7436602/6495043 - // rect.top varies with scroll, so we add whatever has been - // scrolled to it to get absolute distance from actual page top - top: rect.top + (document.documentElement.scrollTop || document.body.scrollTop), - left: rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft) - } -}; + this.x = 0; + this.y = 0; -$$.isElementInViewport = (el) => { - // Although straightforward: https://stackoverflow.com/a/7557433/6495043 - var rect = el.getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ - rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ - ); -}; + this.top = 0; + this.left = 0; -$$.bind = function(element, o) { - if (element) { - for (var event in o) { - var callback = o[event]; + this.setup(); + } - event.split(/\s+/).forEach(function (event) { - element.addEventListener(event, callback); - }); + createClass(SvgTip, [{ + key: 'setup', + value: function setup() { + this.make_tooltip(); } - } -}; + }, { + key: 'refresh', + value: function refresh() { + this.fill(); + this.calc_position(); + // this.show_tip(); + } + }, { + key: 'make_tooltip', + value: function make_tooltip() { + var _this44 = this; + + this.container = $.create('div', { + inside: this.parent, + className: 'graph-svg-tip comparison', + innerHTML: '\n\t\t\t\t\n\t\t\t\t
' + }); + this.hide_tip(); -$$.unbind = function(element, o) { - if (element) { - for (var event in o) { - var callback = o[event]; + this.title = this.container.querySelector('.title'); + this.data_point_list = this.container.querySelector('.data-point-list'); - event.split(/\s+/).forEach(function(event) { - element.removeEventListener(event, callback); + this.parent.addEventListener('mouseleave', function () { + _this44.hide_tip(); }); } - } -}; - -$$.fire = function(target, type, properties) { - var evt = document.createEvent("HTMLEvents"); + }, { + key: 'fill', + value: function fill() { + var _this45 = this; + + var title = void 0; + if (this.title_value_first) { + title = '' + this.title_value + '' + this.title_name; + } else { + title = this.title_name + '' + this.title_value + ''; + } + this.title.innerHTML = title; + this.data_point_list.innerHTML = ''; - evt.initEvent(type, true, true ); + this.list_values.map(function (set$$1) { + var li = $.create('li', { + className: 'border-top ' + (set$$1.color || 'black'), + innerHTML: '' + (set$$1.value ? set$$1.value : '') + '\n\t\t\t\t\t' + (set$$1.title ? set$$1.title : '') + }); - for (var j in properties) { - evt[j] = properties[j]; - } + _this45.data_point_list.appendChild(li); + }); + } + }, { + key: 'calc_position', + value: function calc_position() { + this.top = this.y - this.container.offsetHeight; + this.left = this.x - this.container.offsetWidth / 2; + var max_left = this.parent.offsetWidth - this.container.offsetWidth; + + var pointer = this.container.querySelector('.svg-pointer'); + + if (this.left < 0) { + pointer.style.left = 'calc(50% - ' + -1 * this.left + 'px)'; + this.left = 0; + } else if (this.left > max_left) { + var delta = this.left - max_left; + pointer.style.left = 'calc(50% + ' + delta + 'px)'; + this.left = max_left; + } else { + pointer.style.left = '50%'; + } + } + }, { + key: 'set_values', + value: function set_values(x, y) { + var title_name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; + var title_value = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ''; + var list_values = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : []; + var title_value_first = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; + + this.title_name = title_name; + this.title_value = title_value; + this.list_values = list_values; + this.x = x; + this.y = y; + this.title_value_first = title_value_first; + this.refresh(); + } + }, { + key: 'hide_tip', + value: function hide_tip() { + this.container.style.top = '0px'; + this.container.style.left = '0px'; + this.container.style.opacity = '0'; + } + }, { + key: 'show_tip', + value: function show_tip() { + this.container.style.top = this.top + 'px'; + this.container.style.left = this.left + 'px'; + this.container.style.opacity = '1'; + } + }]); + return SvgTip; +}(); - return target.dispatchEvent(evt); -}; +return Chart; }()); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhcHBlLWNoYXJ0cy5taW4uanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jaGFydHMuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IGZyYXBwZSA9IHtjaGFydDp7fSwgY2hhcnRfdHlwZXM6WydsaW5lJywgJ2JhcicsICdwZXJjZW50YWdlJywgJ2hlYXRtYXAnXX07XG5cbmZyYXBwZS5jaGFydC5GcmFwcGVDaGFydCA9IGNsYXNzIHtcblx0Y29uc3RydWN0b3Ioe1xuXHRcdHBhcmVudCA9IFwiXCIsXG5cdFx0aGVpZ2h0ID0gMjQwLFxuXG5cdFx0dGl0bGUgPSAnJywgc3VidGl0bGUgPSAnJyxcblxuXHRcdGRhdGEgPSB7fSxcblx0XHRmb3JtYXRfbGFtYmRhcyA9IHt9LFxuXG5cdFx0c3VtbWFyeSA9IFtdLFxuXG5cdFx0aXNfbmF2aWdhYmxlID0gMCxcblxuXHRcdHR5cGUgPSAnJ1xuXHR9KSB7XG5cdFx0aWYoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpID09PSBmcmFwcGUuY2hhcnQuRnJhcHBlQ2hhcnQucHJvdG90eXBlKSB7XG5cdFx0XHRpZih0eXBlID09PSAnbGluZScpIHtcblx0XHRcdFx0cmV0dXJuIG5ldyBmcmFwcGUuY2hhcnQuTGluZUNoYXJ0KGFyZ3VtZW50c1swXSk7XG5cdFx0XHR9IGVsc2UgaWYodHlwZSA9PT0gJ2JhcicpIHtcblx0XHRcdFx0cmV0dXJuIG5ldyBmcmFwcGUuY2hhcnQuQmFyQ2hhcnQoYXJndW1lbnRzWzBdKTtcblx0XHRcdH0gZWxzZSBpZih0eXBlID09PSAncGVyY2VudGFnZScpIHtcblx0XHRcdFx0cmV0dXJuIG5ldyBmcmFwcGUuY2hhcnQuUGVyY2VudGFnZUNoYXJ0KGFyZ3VtZW50c1swXSk7XG5cdFx0XHR9IGVsc2UgaWYodHlwZSA9PT0gJ2hlYXRtYXAnKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgZnJhcHBlLmNoYXJ0LkhlYXRNYXAoYXJndW1lbnRzWzBdKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiBuZXcgZnJhcHBlLmNoYXJ0LkxpbmVDaGFydChhcmd1bWVudHNbMF0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMucmF3X2NoYXJ0X2FyZ3MgPSBhcmd1bWVudHNbMF07XG5cblx0XHR0aGlzLnBhcmVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IocGFyZW50KTtcblx0XHR0aGlzLnRpdGxlID0gdGl0bGU7XG5cdFx0dGhpcy5zdWJ0aXRsZSA9IHN1YnRpdGxlO1xuXG5cdFx0dGhpcy5kYXRhID0gZGF0YTtcblx0XHR0aGlzLmZvcm1hdF9sYW1iZGFzID0gZm9ybWF0X2xhbWJkYXM7XG5cblx0XHR0aGlzLnNwZWNpZmljX3ZhbHVlcyA9IGRhdGEuc3BlY2lmaWNfdmFsdWVzIHx8IFtdO1xuXHRcdHRoaXMuc3VtbWFyeSA9IHN1bW1hcnk7XG5cblx0XHR0aGlzLmlzX25hdmlnYWJsZSA9IGlzX25hdmlnYWJsZTtcblx0XHRpZih0aGlzLmlzX25hdmlnYWJsZSkge1xuXHRcdFx0dGhpcy5jdXJyZW50X2luZGV4ID0gMDtcblx0XHR9XG5cblx0XHQkJC5jcmVhdGVTVkcoJ3N2ZycsIHtcblx0XHRcdGNsYXNzTmFtZTogJ2NoYXJ0Jyxcblx0XHRcdGluc2lkZTogcGFyZW50LFxuXHRcdFx0d2lkdGg6IDEwMDAsXG5cdFx0XHRoZWlnaHQ6IGhlaWdodFxuXHRcdH0pO1xuXG5cdFx0dGhpcy5zZXRfbWFyZ2lucyhoZWlnaHQpO1xuXHR9XG5cblx0Z2V0X2RpZmZlcmVudF9jaGFydCh0eXBlKSB7XG5cdFx0aWYoIWZyYXBwZS5jaGFydF90eXBlcy5pbmNsdWRlcyh0eXBlKSkge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJyR7dHlwZX0nIGlzIG5vdCBhIHZhbGlkIGNoYXJ0IHR5cGUuYCk7XG5cdFx0fVxuXHRcdGlmKHR5cGUgPT09IHRoaXMudHlwZSkgcmV0dXJuO1xuXG5cdFx0Ly8gT25seSBhY3Jvc3MgY29tcGF0aWJsZSB0eXBlc1xuXHRcdGxldCBjb21wYXRpYmxlX3R5cGVzID0ge1xuXHRcdFx0YmFyOiBbJ2xpbmUnLCAncGVyY2VudGFnZSddLFxuXHRcdFx0bGluZTogWydiYXInLCAncGVyY2VudGFnZSddLFxuXHRcdFx0cGVyY2VudGFnZTogWydiYXInLCAnbGluZSddLFxuXHRcdFx0aGVhdG1hcDogW11cblx0XHR9XG5cblx0XHRpZighY29tcGF0aWJsZV90eXBlc1t0aGlzLnR5cGVdLmluY2x1ZGVzKHR5cGUpKSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKGAnJHt0aGlzLnR5cGV9JyBjaGFydCBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEgJyR7dHlwZX0nIGNoYXJ0LmApO1xuXHRcdH1cblxuXHRcdC8vIE9rYXksIHRoaXMgaXMgYW50aWNsaW1hY3RpY1xuXHRcdC8vIHRoaXMgZnVuY3Rpb24gd2lsbCBuZWVkIHRvIGJlICdjaGFuZ2VfY2hhcnRfdHlwZSh0eXBlKSdcblx0XHQvLyB0aGF0IHdpbGwgdXBkYXRlIG9ubHkgdGhlIHJlcXVpcmVkIGVsZW1lbnRzLCBidXQgZm9yIG5vdyAuLi5cblx0XHRyZXR1cm4gbmV3IGZyYXBwZS5jaGFydC5GcmFwcGVDaGFydCh7XG5cdFx0XHRwYXJlbnQ6IHRoaXMucmF3X2NoYXJ0X2FyZ3MucGFyZW50LFxuXHRcdFx0ZGF0YTogdGhpcy5yYXdfY2hhcnRfYXJncy5kYXRhLFxuXHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdGhlaWdodDogdGhpcy5yYXdfY2hhcnRfYXJncy5oZWlnaHRcblx0XHR9KTtcblx0fVxuXG5cdHNldF9tYXJnaW5zKGhlaWdodCkge1xuXHRcdHRoaXMuYmFzZV9oZWlnaHQgPSBoZWlnaHQ7XG5cdFx0dGhpcy5oZWlnaHQgPSBoZWlnaHQgLSA0MDtcblx0XHR0aGlzLnRyYW5zbGF0ZV94ID0gNjA7XG5cdFx0dGhpcy50cmFuc2xhdGVfeSA9IDEwO1xuXHR9XG5cblx0c2V0dXAoKSB7XG5cdFx0dGhpcy5iaW5kX3dpbmRvd19ldmVudHMoKTtcblx0XHR0aGlzLnJlZnJlc2godHJ1ZSk7XG5cdH1cblxuXHRiaW5kX3dpbmRvd19ldmVudHMoKSB7XG5cdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHRoaXMucmVmcmVzaCgpKTtcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb3JpZW50YXRpb25jaGFuZ2UnLCAoKSA9PiB0aGlzLnJlZnJlc2goKSk7XG5cdH1cblxuXHRyZWZyZXNoKGluaXQ9ZmFsc2UpIHtcblx0XHR0aGlzLnNldHVwX2Jhc2VfdmFsdWVzKCk7XG5cdFx0dGhpcy5zZXRfd2lkdGgoKTtcblxuXHRcdHRoaXMuc2V0dXBfY29udGFpbmVyKCk7XG5cdFx0dGhpcy5zZXR1cF9jb21wb25lbnRzKCk7XG5cblx0XHR0aGlzLnNldHVwX3ZhbHVlcygpO1xuXHRcdHRoaXMuc2V0dXBfdXRpbHMoKTtcblxuXHRcdHRoaXMubWFrZV9ncmFwaF9jb21wb25lbnRzKGluaXQpO1xuXHRcdHRoaXMubWFrZV90b29sdGlwKCk7XG5cblx0XHRpZih0aGlzLnN1bW1hcnkubGVuZ3RoID4gMCkge1xuXHRcdFx0dGhpcy5zaG93X2N1c3RvbV9zdW1tYXJ5KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19zdW1tYXJ5KCk7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy5pc19uYXZpZ2FibGUpIHtcblx0XHRcdHRoaXMuc2V0dXBfbmF2aWdhdGlvbihpbml0KTtcblx0XHR9XG5cdH1cblxuXHRzZXRfd2lkdGgoKSB7XG5cdFx0bGV0IHNwZWNpYWxfdmFsdWVzX3dpZHRoID0gMDtcblx0XHR0aGlzLnNwZWNpZmljX3ZhbHVlcy5tYXAodmFsID0+IHtcblx0XHRcdGlmKHRoaXMuZ2V0X3N0cndpZHRoKHZhbC50aXRsZSkgPiBzcGVjaWFsX3ZhbHVlc193aWR0aCkge1xuXHRcdFx0XHRzcGVjaWFsX3ZhbHVlc193aWR0aCA9IHRoaXMuZ2V0X3N0cndpZHRoKHZhbC50aXRsZSkgLSA0MDtcblx0XHRcdH1cblx0XHR9KTtcblx0XHR0aGlzLmJhc2Vfd2lkdGggPSB0aGlzLnBhcmVudC5vZmZzZXRXaWR0aCAtIHNwZWNpYWxfdmFsdWVzX3dpZHRoO1xuXHRcdHRoaXMud2lkdGggPSB0aGlzLmJhc2Vfd2lkdGggLSB0aGlzLnRyYW5zbGF0ZV94ICogMjtcblx0fVxuXG5cdHNldHVwX2Jhc2VfdmFsdWVzKCkge31cblxuXHRzZXR1cF9jb250YWluZXIoKSB7XG5cdFx0dGhpcy5jb250YWluZXIgPSAkJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdGNsYXNzTmFtZTogJ2NoYXJ0LWNvbnRhaW5lcicsXG5cdFx0XHRpbm5lckhUTUw6IGA8aDYgY2xhc3M9XCJ0aXRsZVwiIHN0eWxlPVwibWFyZ2luLXRvcDogMTVweDtcIj4ke3RoaXMudGl0bGV9PC9oNj5cblx0XHRcdFx0PGg2IGNsYXNzPVwic3ViLXRpdGxlIHVwcGVyY2FzZVwiPiR7dGhpcy5zdWJ0aXRsZX08L2g2PlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZnJhcHBlLWNoYXJ0IGdyYXBoaWNzXCI+PC9kaXY+XG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJncmFwaC1zdGF0cy1jb250YWluZXJcIj48L2Rpdj5gXG5cdFx0fSk7XG5cblx0XHQvLyBDaGFydCBuZWVkcyBhIGRlZGljYXRlZCBwYXJlbnQgZWxlbWVudFxuXHRcdHRoaXMucGFyZW50LmlubmVySFRNTCA9ICcnO1xuXHRcdHRoaXMucGFyZW50LmFwcGVuZENoaWxkKHRoaXMuY29udGFpbmVyKTtcblxuXHRcdHRoaXMuY2hhcnRfd3JhcHBlciA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5mcmFwcGUtY2hhcnQnKTtcblx0XHR0aGlzLnN0YXRzX3dyYXBwZXIgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuZ3JhcGgtc3RhdHMtY29udGFpbmVyJyk7XG5cblx0XHR0aGlzLm1ha2VfY2hhcnRfYXJlYSgpO1xuXHRcdHRoaXMubWFrZV9kcmF3X2FyZWEoKTtcblx0fVxuXG5cdG1ha2VfY2hhcnRfYXJlYSgpIHtcblx0XHR0aGlzLnN2ZyA9ICQkLmNyZWF0ZVNWRygnc3ZnJywge1xuXHRcdFx0Y2xhc3NOYW1lOiAnY2hhcnQnLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmNoYXJ0X3dyYXBwZXIsXG5cdFx0XHR3aWR0aDogdGhpcy5iYXNlX3dpZHRoLFxuXHRcdFx0aGVpZ2h0OiB0aGlzLmJhc2VfaGVpZ2h0XG5cdFx0fSk7XG5cblx0XHR0aGlzLnN2Z19kZWZzID0gJCQuY3JlYXRlU1ZHKCdkZWZzJywge1xuXHRcdFx0aW5zaWRlOiB0aGlzLnN2Zyxcblx0XHR9KTtcblxuXHRcdHJldHVybiB0aGlzLnN2Zztcblx0fVxuXG5cdG1ha2VfZHJhd19hcmVhKCkge1xuXHRcdHRoaXMuZHJhd19hcmVhID0gJCQuY3JlYXRlU1ZHKFwiZ1wiLCB7XG5cdFx0XHRjbGFzc05hbWU6IHRoaXMudHlwZSArICctY2hhcnQnLFxuXHRcdFx0aW5zaWRlOiB0aGlzLnN2Zyxcblx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke3RoaXMudHJhbnNsYXRlX3h9LCAke3RoaXMudHJhbnNsYXRlX3l9KWBcblx0XHR9KTtcblx0fVxuXG5cdHNldHVwX2NvbXBvbmVudHMoKSB7IH1cblxuXHRtYWtlX3Rvb2x0aXAoKSB7XG5cdFx0dGhpcy50aXAgPSBuZXcgZnJhcHBlLmNoYXJ0LlN2Z1RpcCh7XG5cdFx0XHRwYXJlbnQ6IHRoaXMuY2hhcnRfd3JhcHBlcixcblx0XHR9KTtcblx0XHR0aGlzLmJpbmRfdG9vbHRpcCgpO1xuXHR9XG5cblxuXHRzaG93X3N1bW1hcnkoKSB7fVxuXHRzaG93X2N1c3RvbV9zdW1tYXJ5KCkge1xuXHRcdHRoaXMuc3VtbWFyeS5tYXAoZCA9PiB7XG5cdFx0XHRsZXQgc3RhdHMgPSAkJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAnc3RhdHMnLFxuXHRcdFx0XHRpbm5lckhUTUw6IGA8c3BhbiBjbGFzcz1cImluZGljYXRvciAke2QuY29sb3J9XCI+JHtkLnRpdGxlfTogJHtkLnZhbHVlfTwvc3Bhbj5gXG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuc3RhdHNfd3JhcHBlci5hcHBlbmRDaGlsZChzdGF0cyk7XG5cdFx0fSk7XG5cdH1cblxuXHRzZXR1cF9uYXZpZ2F0aW9uKGluaXQ9ZmFsc2UpIHtcblx0XHR0aGlzLm1ha2Vfb3ZlcmxheSgpO1xuXG5cdFx0aWYoaW5pdCkge1xuXHRcdFx0dGhpcy5iaW5kX292ZXJsYXkoKTtcblxuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlKSA9PiB7XG5cdFx0XHRcdGlmKCQkLmlzRWxlbWVudEluVmlld3BvcnQodGhpcy5jaGFydF93cmFwcGVyKSkge1xuXHRcdFx0XHRcdGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcblxuXHRcdFx0XHRcdGlmIChlLmtleUNvZGUgPT0gJzM3Jykge1xuXHRcdFx0XHRcdFx0dGhpcy5vbl9sZWZ0X2Fycm93KCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChlLmtleUNvZGUgPT0gJzM5Jykge1xuXHRcdFx0XHRcdFx0dGhpcy5vbl9yaWdodF9hcnJvdygpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZS5rZXlDb2RlID09ICczOCcpIHtcblx0XHRcdFx0XHRcdHRoaXMub25fdXBfYXJyb3coKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSAnNDAnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9uX2Rvd25fYXJyb3coKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSAnMTMnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9uX2VudGVyX2tleSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0bWFrZV9vdmVybGF5KCkge31cblx0YmluZF9vdmVybGF5KCkge31cblxuXHRvbl9sZWZ0X2Fycm93KCkge31cblx0b25fcmlnaHRfYXJyb3coKSB7fVxuXHRvbl91cF9hcnJvdygpIHt9XG5cdG9uX2Rvd25fYXJyb3coKSB7fVxuXHRvbl9lbnRlcl9rZXkoKSB7fVxuXG5cdGdldF9kYXRhX3BvaW50KGluZGV4PXRoaXMuY3VycmVudF9pbmRleCkge1xuXHRcdC8vIGNoZWNrIGZvciBsZW5ndGhcblx0XHRsZXQgZGF0YV9wb2ludCA9IHtcblx0XHRcdGluZGV4OiBpbmRleFxuXHRcdH07XG5cdFx0bGV0IHkgPSB0aGlzLnlbMF07XG5cdFx0WydzdmdfdW5pdHMnLCAneV90b3BzJywgJ3ZhbHVlcyddLm1hcChrZXkgPT4ge1xuXHRcdFx0bGV0IGRhdGFfa2V5ID0ga2V5LnNsaWNlKDAsIGtleS5sZW5ndGgtMSk7XG5cdFx0XHRkYXRhX3BvaW50W2RhdGFfa2V5XSA9IHlba2V5XVtpbmRleF07XG5cdFx0fSk7XG5cdFx0ZGF0YV9wb2ludC5sYWJlbCA9IHRoaXMueFtpbmRleF07XG5cdFx0cmV0dXJuIGRhdGFfcG9pbnQ7XG5cdH1cblxuXHR1cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KGluZGV4KSB7XG5cdFx0aWYoaW5kZXggPCAwKSBpbmRleCA9IDA7XG5cdFx0aWYoaW5kZXggPj0gdGhpcy54Lmxlbmd0aCkgaW5kZXggPSB0aGlzLngubGVuZ3RoIC0gMTtcblx0XHRpZihpbmRleCA9PT0gdGhpcy5jdXJyZW50X2luZGV4KSByZXR1cm47XG5cdFx0dGhpcy5jdXJyZW50X2luZGV4ID0gaW5kZXg7XG5cdFx0JCQuZmlyZSh0aGlzLnBhcmVudCwgXCJkYXRhLXNlbGVjdFwiLCB0aGlzLmdldF9kYXRhX3BvaW50KCkpO1xuXHR9XG5cblx0Ly8gSGVscGVyc1xuXHRnZXRfc3Ryd2lkdGgoc3RyaW5nKSB7XG5cdFx0cmV0dXJuIHN0cmluZy5sZW5ndGggKiA4O1xuXHR9XG5cblx0Ly8gT2JqZWN0c1xuXHRzZXR1cF91dGlscygpIHsgfVxufVxuXG5mcmFwcGUuY2hhcnQuQXhpc0NoYXJ0ID0gY2xhc3MgQXhpc0NoYXJ0IGV4dGVuZHMgZnJhcHBlLmNoYXJ0LkZyYXBwZUNoYXJ0IHtcblx0Y29uc3RydWN0b3IoYXJncykge1xuXHRcdHN1cGVyKGFyZ3MpO1xuXG5cdFx0dGhpcy54ID0gdGhpcy5kYXRhLmxhYmVscztcblx0XHR0aGlzLnkgPSB0aGlzLmRhdGEuZGF0YXNldHM7XG5cblx0XHR0aGlzLmdldF95X2xhYmVsID0gdGhpcy5mb3JtYXRfbGFtYmRhcy55X2xhYmVsO1xuXHRcdHRoaXMuZ2V0X3lfdG9vbHRpcCA9IHRoaXMuZm9ybWF0X2xhbWJkYXMueV90b29sdGlwO1xuXHRcdHRoaXMuZ2V0X3hfdG9vbHRpcCA9IHRoaXMuZm9ybWF0X2xhbWJkYXMueF90b29sdGlwO1xuXG5cdFx0dGhpcy5jb2xvcnMgPSBbJ2dyZWVuJywgJ2JsdWUnLCAndmlvbGV0JywgJ3JlZCcsICdvcmFuZ2UnLFxuXHRcdFx0XHQneWVsbG93JywgJ2xpZ2h0LWJsdWUnLCAnbGlnaHQtZ3JlZW4nLCAncHVycGxlJywgJ21hZ2VudGEnXTtcblxuXHRcdHRoaXMuemVyb19saW5lID0gdGhpcy5oZWlnaHQ7XG5cdH1cblxuXHRzZXR1cF92YWx1ZXMoKSB7XG5cdFx0dGhpcy5kYXRhLmRhdGFzZXRzLm1hcChkID0+IHtcblx0XHRcdGQudmFsdWVzID0gZC52YWx1ZXMubWFwKHZhbCA9PiAoIWlzTmFOKHZhbCkgPyB2YWwgOiAwKSk7XG5cdFx0fSk7XG5cdFx0dGhpcy5zZXR1cF94KCk7XG5cdFx0dGhpcy5zZXR1cF95KCk7XG5cdH1cblxuXHRzZXR1cF94KCkge1xuXHRcdHRoaXMuc2V0X2F2Z191bml0X3dpZHRoX2FuZF94X29mZnNldCgpO1xuXG5cdFx0aWYodGhpcy54X2F4aXNfcG9zaXRpb25zKSB7XG5cdFx0XHR0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zID0gIHRoaXMueF9heGlzX3Bvc2l0aW9ucy5zbGljZSgpO1xuXHRcdH1cblx0XHR0aGlzLnhfYXhpc19wb3NpdGlvbnMgPSB0aGlzLngubWFwKChkLCBpKSA9PlxuXHRcdFx0JCQuZmxvYXRfMih0aGlzLnhfb2Zmc2V0ICsgaSAqIHRoaXMuYXZnX3VuaXRfd2lkdGgpKTtcblxuXHRcdGlmKCF0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zKSB7XG5cdFx0XHR0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zID0gdGhpcy54X2F4aXNfcG9zaXRpb25zLnNsaWNlKCk7XG5cdFx0fVxuXHR9XG5cblx0c2V0dXBfeSgpIHtcblx0XHRpZih0aGlzLnlfYXhpc192YWx1ZXMpIHtcblx0XHRcdHRoaXMueV9vbGRfYXhpc192YWx1ZXMgPSAgdGhpcy55X2F4aXNfdmFsdWVzLnNsaWNlKCk7XG5cdFx0fVxuXG5cdFx0bGV0IHZhbHVlcyA9IHRoaXMuZ2V0X2FsbF95X3ZhbHVlcygpO1xuXG5cdFx0aWYodGhpcy55X3N1bXMgJiYgdGhpcy55X3N1bXMubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFsdWVzID0gdmFsdWVzLmNvbmNhdCh0aGlzLnlfc3Vtcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy55X2F4aXNfdmFsdWVzID0gdGhpcy5nZXRfeV9heGlzX3BvaW50cyh2YWx1ZXMpO1xuXG5cdFx0aWYoIXRoaXMueV9vbGRfYXhpc192YWx1ZXMpIHtcblx0XHRcdHRoaXMueV9vbGRfYXhpc192YWx1ZXMgPSB0aGlzLnlfYXhpc192YWx1ZXMuc2xpY2UoKTtcblx0XHR9XG5cblx0XHRjb25zdCB5X3B0cyA9IHRoaXMueV9heGlzX3ZhbHVlcztcblx0XHRjb25zdCB2YWx1ZV9yYW5nZSA9IHlfcHRzW3lfcHRzLmxlbmd0aC0xXSAtIHlfcHRzWzBdO1xuXG5cdFx0aWYodGhpcy5tdWx0aXBsaWVyKSB0aGlzLm9sZF9tdWx0aXBsaWVyID0gdGhpcy5tdWx0aXBsaWVyO1xuXHRcdHRoaXMubXVsdGlwbGllciA9IHRoaXMuaGVpZ2h0IC8gdmFsdWVfcmFuZ2U7XG5cdFx0aWYoIXRoaXMub2xkX211bHRpcGxpZXIpIHRoaXMub2xkX211bHRpcGxpZXIgPSB0aGlzLm11bHRpcGxpZXI7XG5cblx0XHRjb25zdCB6ZXJvX2luZGV4ID0geV9wdHMuaW5kZXhPZigwKTtcblx0XHRjb25zdCBpbnRlcnZhbCA9IHlfcHRzWzFdIC0geV9wdHNbMF07XG5cdFx0Y29uc3QgaW50ZXJ2YWxfaGVpZ2h0ID0gaW50ZXJ2YWwgKiB0aGlzLm11bHRpcGxpZXI7XG5cblx0XHRpZih0aGlzLnplcm9fbGluZSkgdGhpcy5vbGRfemVyb19saW5lID0gdGhpcy56ZXJvX2xpbmU7XG5cdFx0dGhpcy56ZXJvX2xpbmUgPSB0aGlzLmhlaWdodCAtICh6ZXJvX2luZGV4ICogaW50ZXJ2YWxfaGVpZ2h0KTtcblx0XHRpZighdGhpcy5vbGRfemVyb19saW5lKSB0aGlzLm9sZF96ZXJvX2xpbmUgPSB0aGlzLnplcm9fbGluZTtcblx0fVxuXG5cdHNldHVwX2NvbXBvbmVudHMoKSB7XG5cdFx0c3VwZXIuc2V0dXBfY29tcG9uZW50cygpO1xuXHRcdHRoaXMuc2V0dXBfbWFya2VyX2NvbXBvbmVudHMoKTtcblx0XHR0aGlzLnNldHVwX2FnZ3JlZ2F0aW9uX2NvbXBvbmVudHMoKTtcblx0XHR0aGlzLnNldHVwX2dyYXBoX2NvbXBvbmVudHMoKTtcblx0fVxuXG5cdHNldHVwX21hcmtlcl9jb21wb25lbnRzKCkge1xuXHRcdHRoaXMueV9heGlzX2dyb3VwID0gJCQuY3JlYXRlU1ZHKCdnJywge2NsYXNzTmFtZTogJ3kgYXhpcycsIGluc2lkZTogdGhpcy5kcmF3X2FyZWF9KTtcblx0XHR0aGlzLnhfYXhpc19ncm91cCA9ICQkLmNyZWF0ZVNWRygnZycsIHtjbGFzc05hbWU6ICd4IGF4aXMnLCBpbnNpZGU6IHRoaXMuZHJhd19hcmVhfSk7XG5cdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwID0gJCQuY3JlYXRlU1ZHKCdnJywge2NsYXNzTmFtZTogJ3NwZWNpZmljIGF4aXMnLCBpbnNpZGU6IHRoaXMuZHJhd19hcmVhfSk7XG5cdH1cblxuXHRzZXR1cF9hZ2dyZWdhdGlvbl9jb21wb25lbnRzKCkge1xuXHRcdHRoaXMuc3VtX2dyb3VwID0gJCQuY3JlYXRlU1ZHKCdnJywge2NsYXNzTmFtZTogJ2RhdGEtcG9pbnRzJywgaW5zaWRlOiB0aGlzLmRyYXdfYXJlYX0pO1xuXHRcdHRoaXMuYXZlcmFnZV9ncm91cCA9ICQkLmNyZWF0ZVNWRygnZycsIHtjbGFzc05hbWU6ICdjaGFydC1hcmVhJywgaW5zaWRlOiB0aGlzLmRyYXdfYXJlYX0pO1xuXHR9XG5cblx0c2V0dXBfZ3JhcGhfY29tcG9uZW50cygpIHtcblx0XHR0aGlzLnN2Z191bml0c19ncm91cHMgPSBbXTtcblx0XHR0aGlzLnkubWFwKChkLCBpKSA9PiB7XG5cdFx0XHR0aGlzLnN2Z191bml0c19ncm91cHNbaV0gPSAkJC5jcmVhdGVTVkcoJ2cnLCB7XG5cdFx0XHRcdGNsYXNzTmFtZTogJ2RhdGEtcG9pbnRzIGRhdGEtcG9pbnRzLScgKyBpLFxuXHRcdFx0XHRpbnNpZGU6IHRoaXMuZHJhd19hcmVhXG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfZ3JhcGhfY29tcG9uZW50cyhpbml0PWZhbHNlKSB7XG5cdFx0dGhpcy5tYWtlX3lfYXhpcygpO1xuXHRcdHRoaXMubWFrZV94X2F4aXMoKTtcblx0XHR0aGlzLmRyYXdfZ3JhcGgoaW5pdCk7XG5cdFx0dGhpcy5tYWtlX3lfc3BlY2lmaWNzKCk7XG5cdH1cblxuXHQvLyBtYWtlIFZFUlRJQ0FMIGxpbmVzIGZvciB4IHZhbHVlc1xuXHRtYWtlX3hfYXhpcyhhbmltYXRlPWZhbHNlKSB7XG5cdFx0bGV0IHN0YXJ0X2F0LCBoZWlnaHQsIHRleHRfc3RhcnRfYXQsIGF4aXNfbGluZV9jbGFzcyA9ICcnO1xuXHRcdGlmKHRoaXMueF9heGlzX21vZGUgPT09ICdzcGFuJykge1x0XHQvLyBsb25nIHNwYW5uaW5nIGxpbmVzXG5cdFx0XHRzdGFydF9hdCA9IC03O1xuXHRcdFx0aGVpZ2h0ID0gdGhpcy5oZWlnaHQgKyAxNTtcblx0XHRcdHRleHRfc3RhcnRfYXQgPSB0aGlzLmhlaWdodCArIDI1O1xuXHRcdH0gZWxzZSBpZih0aGlzLnhfYXhpc19tb2RlID09PSAndGljaycpe1x0Ly8gc2hvcnQgbGFiZWwgbGluZXNcblx0XHRcdHN0YXJ0X2F0ID0gdGhpcy5oZWlnaHQ7XG5cdFx0XHRoZWlnaHQgPSA2O1xuXHRcdFx0dGV4dF9zdGFydF9hdCA9IDk7XG5cdFx0XHRheGlzX2xpbmVfY2xhc3MgPSAneC1heGlzLWxhYmVsJztcblx0XHR9XG5cblx0XHR0aGlzLnhfYXhpc19ncm91cC5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoMCwke3N0YXJ0X2F0fSlgKTtcblxuXHRcdGlmKGFuaW1hdGUpIHtcblx0XHRcdHRoaXMubWFrZV9hbmltX3hfYXhpcyhoZWlnaHQsIHRleHRfc3RhcnRfYXQsIGF4aXNfbGluZV9jbGFzcyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy54X2F4aXNfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLngubWFwKChwb2ludCwgaSkgPT4ge1xuXHRcdFx0dGhpcy54X2F4aXNfZ3JvdXAuYXBwZW5kQ2hpbGQoXG5cdFx0XHRcdHRoaXMubWFrZV94X2xpbmUoXG5cdFx0XHRcdFx0aGVpZ2h0LFxuXHRcdFx0XHRcdHRleHRfc3RhcnRfYXQsXG5cdFx0XHRcdFx0cG9pbnQsXG5cdFx0XHRcdFx0J3gtdmFsdWUtdGV4dCcsXG5cdFx0XHRcdFx0YXhpc19saW5lX2NsYXNzLFxuXHRcdFx0XHRcdHRoaXMueF9heGlzX3Bvc2l0aW9uc1tpXVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0Ly8gbWFrZSBIT1JJWk9OVEFMIGxpbmVzIGZvciB5IHZhbHVlc1xuXHRtYWtlX3lfYXhpcyhhbmltYXRlPWZhbHNlKSB7XG5cdFx0aWYoYW5pbWF0ZSkge1xuXHRcdFx0dGhpcy5tYWtlX2FuaW1feV9heGlzKCk7XG5cdFx0XHR0aGlzLm1ha2VfYW5pbV95X3NwZWNpZmljcygpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGxldCBbd2lkdGgsIHRleHRfZW5kX2F0LCBheGlzX2xpbmVfY2xhc3MsIHN0YXJ0X2F0XSA9IHRoaXMuZ2V0X3lfYXhpc19saW5lX3Byb3BzKCk7XG5cblx0XHR0aGlzLnlfYXhpc19ncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdHRoaXMueV9heGlzX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHR0aGlzLnlfYXhpc19ncm91cC5hcHBlbmRDaGlsZChcblx0XHRcdFx0dGhpcy5tYWtlX3lfbGluZShcblx0XHRcdFx0XHRzdGFydF9hdCxcblx0XHRcdFx0XHR3aWR0aCxcblx0XHRcdFx0XHR0ZXh0X2VuZF9hdCxcblx0XHRcdFx0XHR2YWx1ZSxcblx0XHRcdFx0XHQneS12YWx1ZS10ZXh0Jyxcblx0XHRcdFx0XHRheGlzX2xpbmVfY2xhc3MsXG5cdFx0XHRcdFx0dGhpcy56ZXJvX2xpbmUgLSB2YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0XHQodmFsdWUgPT09IDAgJiYgaSAhPT0gMCkgLy8gTm9uLWZpcnN0IFplcm8gbGluZVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0Z2V0X3lfYXhpc19saW5lX3Byb3BzKHNwZWNpZmljPWZhbHNlKSB7XG5cdFx0aWYoc3BlY2lmaWMpIHtcblx0XHRcdHJldHVyblt0aGlzLndpZHRoLCB0aGlzLndpZHRoICsgNSwgJ3NwZWNpZmljLXZhbHVlJywgMF07XG5cdFx0fVxuXHRcdGxldCB3aWR0aCwgdGV4dF9lbmRfYXQgPSAtOSwgYXhpc19saW5lX2NsYXNzID0gJycsIHN0YXJ0X2F0ID0gMDtcblx0XHRpZih0aGlzLnlfYXhpc19tb2RlID09PSAnc3BhbicpIHtcdFx0Ly8gbG9uZyBzcGFubmluZyBsaW5lc1xuXHRcdFx0d2lkdGggPSB0aGlzLndpZHRoICsgNjtcblx0XHRcdHN0YXJ0X2F0ID0gLTY7XG5cdFx0fSBlbHNlIGlmKHRoaXMueV9heGlzX21vZGUgPT09ICd0aWNrJyl7XHQvLyBzaG9ydCBsYWJlbCBsaW5lc1xuXHRcdFx0d2lkdGggPSAtNjtcblx0XHRcdGF4aXNfbGluZV9jbGFzcyA9ICd5LWF4aXMtbGFiZWwnO1xuXHRcdH1cblxuXHRcdHJldHVybiBbd2lkdGgsIHRleHRfZW5kX2F0LCBheGlzX2xpbmVfY2xhc3MsIHN0YXJ0X2F0XTtcblx0fVxuXG5cdGRyYXdfZ3JhcGgoaW5pdD1mYWxzZSkge1xuXHRcdGlmKGluaXQpIHtcblx0XHRcdHRoaXMuZHJhd19uZXdfZ3JhcGhfYW5kX2FuaW1hdGUoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0ZC5zdmdfdW5pdHMgPSBbXTtcblx0XHRcdHRoaXMubWFrZV9wYXRoICYmIHRoaXMubWFrZV9wYXRoKGQsIGksIHRoaXMueF9heGlzX3Bvc2l0aW9ucywgZC55X3RvcHMsIGQuY29sb3IgfHwgdGhpcy5jb2xvcnNbaV0pO1xuXHRcdFx0dGhpcy5tYWtlX25ld191bml0cyhkLCBpKTtcblx0XHR9KTtcblx0fVxuXG5cdGRyYXdfbmV3X2dyYXBoX2FuZF9hbmltYXRlKCkge1xuXHRcdGxldCBkYXRhID0gW107XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0Ly8gQW5pbTogRG9uJ3QgZHJhdyBpbml0aWFsIHZhbHVlcywgc3RvcmUgdGhlbSBhbmQgdXBkYXRlIGxhdGVyXG5cdFx0XHRkLnlfdG9wcyA9IG5ldyBBcnJheShkLnZhbHVlcy5sZW5ndGgpLmZpbGwodGhpcy56ZXJvX2xpbmUpOyAvLyBubyB2YWx1ZVxuXHRcdFx0ZGF0YS5wdXNoKHt2YWx1ZXM6IGQudmFsdWVzfSk7XG5cdFx0XHRkLnN2Z191bml0cyA9IFtdO1xuXG5cdFx0XHR0aGlzLm1ha2VfcGF0aCAmJiB0aGlzLm1ha2VfcGF0aChkLCBpLCB0aGlzLnhfYXhpc19wb3NpdGlvbnMsIGQueV90b3BzLCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblx0XHRcdHRoaXMubWFrZV9uZXdfdW5pdHMoZCwgaSk7XG5cdFx0fSk7XG5cblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMudXBkYXRlX3ZhbHVlcyhkYXRhKTtcblx0XHR9LCAzNTApO1xuXHR9XG5cblx0c2V0dXBfbmF2aWdhdGlvbihpbml0KSB7XG5cdFx0Ly8gSGFjazogZGVmZXIgbmF2IHRpbGwgaW5pdGlhbCB1cGRhdGVfdmFsdWVzXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRzdXBlci5zZXR1cF9uYXZpZ2F0aW9uKGluaXQpO1xuXHRcdH0sIDUwMCk7XG5cdH1cblxuXHRtYWtlX25ld191bml0cyhkLCBpKSB7XG5cdFx0dGhpcy5tYWtlX25ld191bml0c19mb3JfZGF0YXNldChcblx0XHRcdHRoaXMueF9heGlzX3Bvc2l0aW9ucyxcblx0XHRcdGQueV90b3BzLFxuXHRcdFx0ZC5jb2xvciB8fCB0aGlzLmNvbG9yc1tpXSxcblx0XHRcdGksXG5cdFx0XHR0aGlzLnkubGVuZ3RoXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfbmV3X3VuaXRzX2Zvcl9kYXRhc2V0KHhfdmFsdWVzLCB5X3ZhbHVlcywgY29sb3IsIGRhdGFzZXRfaW5kZXgsIG5vX29mX2RhdGFzZXRzLCBncm91cCwgYXJyYXksIHVuaXQpIHtcblx0XHRpZighZ3JvdXApIGdyb3VwID0gdGhpcy5zdmdfdW5pdHNfZ3JvdXBzW2RhdGFzZXRfaW5kZXhdO1xuXHRcdGlmKCFhcnJheSkgYXJyYXkgPSB0aGlzLnlbZGF0YXNldF9pbmRleF0uc3ZnX3VuaXRzO1xuXHRcdGlmKCF1bml0KSB1bml0ID0gdGhpcy51bml0X2FyZ3M7XG5cblx0XHRncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdGFycmF5Lmxlbmd0aCA9IDA7XG5cblx0XHR5X3ZhbHVlcy5tYXAoKHksIGkpID0+IHtcblx0XHRcdGxldCBkYXRhX3VuaXQgPSB0aGlzLmRyYXdbdW5pdC50eXBlXShcblx0XHRcdFx0eF92YWx1ZXNbaV0sXG5cdFx0XHRcdHksXG5cdFx0XHRcdHVuaXQuYXJncyxcblx0XHRcdFx0Y29sb3IsXG5cdFx0XHRcdGRhdGFzZXRfaW5kZXgsXG5cdFx0XHRcdG5vX29mX2RhdGFzZXRzXG5cdFx0XHQpO1xuXHRcdFx0Z3JvdXAuYXBwZW5kQ2hpbGQoZGF0YV91bml0KTtcblx0XHRcdGFycmF5LnB1c2goZGF0YV91bml0KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfeV9zcGVjaWZpY3MoKSB7XG5cdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLnRleHRDb250ZW50ID0gJyc7XG5cdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMubWFwKGQgPT4ge1xuXHRcdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLmFwcGVuZENoaWxkKFxuXHRcdFx0XHR0aGlzLm1ha2VfeV9saW5lKFxuXHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0dGhpcy53aWR0aCxcblx0XHRcdFx0XHR0aGlzLndpZHRoICsgNSxcblx0XHRcdFx0XHRkLnRpdGxlLnRvVXBwZXJDYXNlKCksXG5cdFx0XHRcdFx0J3NwZWNpZmljLXZhbHVlJyxcblx0XHRcdFx0XHQnc3BlY2lmaWMtdmFsdWUnLFxuXHRcdFx0XHRcdHRoaXMuemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0XHRmYWxzZSxcblx0XHRcdFx0XHRkLmxpbmVfdHlwZVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0YmluZF90b29sdGlwKCkge1xuXHRcdC8vIFRPRE86IGNvdWxkIGJlIGluIHRvb2x0aXAgaXRzZWxmLCBhcyBpdCBpcyBhIGdpdmVuIGZ1bmN0aW9uYWxpdHkgZm9yIGl0cyBwYXJlbnRcblx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgKGUpID0+IHtcblx0XHRcdGxldCBvZmZzZXQgPSAkJC5vZmZzZXQodGhpcy5jaGFydF93cmFwcGVyKTtcblx0XHRcdGxldCByZWxYID0gZS5wYWdlWCAtIG9mZnNldC5sZWZ0IC0gdGhpcy50cmFuc2xhdGVfeDtcblx0XHRcdGxldCByZWxZID0gZS5wYWdlWSAtIG9mZnNldC50b3AgLSB0aGlzLnRyYW5zbGF0ZV95O1xuXG5cdFx0XHRpZihyZWxZIDwgdGhpcy5oZWlnaHQgKyB0aGlzLnRyYW5zbGF0ZV95ICogMikge1xuXHRcdFx0XHR0aGlzLm1hcF90b29sdGlwX3hfcG9zaXRpb25fYW5kX3Nob3cocmVsWCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnRpcC5oaWRlX3RpcCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0bWFwX3Rvb2x0aXBfeF9wb3NpdGlvbl9hbmRfc2hvdyhyZWxYKSB7XG5cdFx0Zm9yKHZhciBpPXRoaXMueF9heGlzX3Bvc2l0aW9ucy5sZW5ndGggLSAxOyBpID49IDAgOyBpLS0pIHtcblx0XHRcdGxldCB4X3ZhbCA9IHRoaXMueF9heGlzX3Bvc2l0aW9uc1tpXTtcblx0XHRcdC8vIGxldCBkZWx0YSA9IGkgPT09IDAgPyB0aGlzLmF2Z191bml0X3dpZHRoIDogeF92YWwgLSB0aGlzLnhfYXhpc19wb3NpdGlvbnNbaS0xXTtcblx0XHRcdGlmKHJlbFggPiB4X3ZhbCAtIHRoaXMuYXZnX3VuaXRfd2lkdGgvMikge1xuXHRcdFx0XHRsZXQgeCA9IHhfdmFsICsgdGhpcy50cmFuc2xhdGVfeDtcblx0XHRcdFx0bGV0IHkgPSB0aGlzLnlfbWluX3RvcHNbaV0gKyB0aGlzLnRyYW5zbGF0ZV95O1xuXG5cdFx0XHRcdGxldCB0aXRsZSA9IHRoaXMueC5mb3JtYXR0ZWQgJiYgdGhpcy54LmZvcm1hdHRlZC5sZW5ndGg+MFxuXHRcdFx0XHRcdD8gdGhpcy54LmZvcm1hdHRlZFtpXSA6IHRoaXMueFtpXTtcblx0XHRcdFx0bGV0IHZhbHVlcyA9IHRoaXMueS5tYXAoKHNldCwgaikgPT4ge1xuXHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHR0aXRsZTogc2V0LnRpdGxlLFxuXHRcdFx0XHRcdFx0dmFsdWU6IHNldC5mb3JtYXR0ZWQgPyBzZXQuZm9ybWF0dGVkW2ldIDogc2V0LnZhbHVlc1tpXSxcblx0XHRcdFx0XHRcdGNvbG9yOiBzZXQuY29sb3IgfHwgdGhpcy5jb2xvcnNbal0sXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQvLyBUT0RPOiB1cHNpZGUtZG93biB0b29sdGlwcyBmb3IgbmVnYXRpdmUgdmFsdWVzP1xuXHRcdFx0XHR0aGlzLnRpcC5zZXRfdmFsdWVzKHgsIHksIHRpdGxlLCAnJywgdmFsdWVzKTtcblx0XHRcdFx0dGhpcy50aXAuc2hvd190aXAoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQVBJXG5cdHNob3dfc3VtcygpIHtcblx0XHR0aGlzLnVwZGF0aW5nID0gdHJ1ZTtcblxuXHRcdHRoaXMueV9zdW1zID0gbmV3IEFycmF5KHRoaXMueF9heGlzX3Bvc2l0aW9ucy5sZW5ndGgpLmZpbGwoMCk7XG5cdFx0dGhpcy55Lm1hcChkID0+IHtcblx0XHRcdGQudmFsdWVzLm1hcCggKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRcdHRoaXMueV9zdW1zW2ldICs9IHZhbHVlO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHQvLyBSZW1ha2UgeSBheGlzLCBhbmltYXRlXG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKCk7XG5cblx0XHQvLyBUaGVuIG1ha2Ugc3VtIHVuaXRzLCBkb24ndCBhbmltYXRlXG5cdFx0dGhpcy5zdW1fdW5pdHMgPSBbXTtcblxuXHRcdHRoaXMubWFrZV9uZXdfdW5pdHNfZm9yX2RhdGFzZXQoXG5cdFx0XHR0aGlzLnhfYXhpc19wb3NpdGlvbnMsXG5cdFx0XHR0aGlzLnlfc3Vtcy5tYXAoIHZhbCA9PiAkJC5mbG9hdF8yKHRoaXMuemVyb19saW5lIC0gdmFsICogdGhpcy5tdWx0aXBsaWVyKSksXG5cdFx0XHQnbGlnaHQtZ3JleScsXG5cdFx0XHQwLFxuXHRcdFx0MSxcblx0XHRcdHRoaXMuc3VtX2dyb3VwLFxuXHRcdFx0dGhpcy5zdW1fdW5pdHNcblx0XHQpO1xuXG5cdFx0Ly8gdGhpcy5tYWtlX3BhdGggJiYgdGhpcy5tYWtlX3BhdGgoZCwgaSwgb2xkX3gsIG9sZF95LCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblxuXHRcdHRoaXMudXBkYXRpbmcgPSBmYWxzZTtcblx0fVxuXG5cdGhpZGVfc3VtcygpIHtcblx0XHRpZih0aGlzLnVwZGF0aW5nKSByZXR1cm47XG5cdFx0dGhpcy55X3N1bXMgPSBbXTtcblx0XHR0aGlzLnN1bV9ncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdHRoaXMuc3VtX3VuaXRzID0gW107XG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKCk7XG5cdH1cblxuXHRzaG93X2F2ZXJhZ2UoKSB7XG5cdFx0dGhpcy5vbGRfc3BlY2lmaWNfdmFsdWVzID0gdGhpcy5zcGVjaWZpY192YWx1ZXMuc2xpY2UoKTtcblx0XHR0aGlzLnkubWFwKChkLCBpKSA9PiB7XG5cdFx0XHRsZXQgc3VtID0gMDtcblx0XHRcdGQudmFsdWVzLm1hcChlID0+IHtzdW0rPWV9KTtcblx0XHRcdGxldCBhdmVyYWdlID0gc3VtL2QudmFsdWVzLmxlbmd0aDtcblxuXHRcdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMucHVzaCh7XG5cdFx0XHRcdHRpdGxlOiBcIkFWR1wiICsgXCIgXCIgKyAoaSsxKSxcblx0XHRcdFx0bGluZV90eXBlOiBcImRhc2hlZFwiLFxuXHRcdFx0XHR2YWx1ZTogYXZlcmFnZSxcblx0XHRcdFx0YXV0bzogMVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHRjb25zb2xlLmxvZyh0aGlzLnNwZWNpZmljX3ZhbHVlcyk7XG5cblx0XHR0aGlzLnVwZGF0ZV92YWx1ZXMoKTtcblx0fVxuXG5cdGhpZGVfYXZlcmFnZSgpIHtcblx0XHR0aGlzLm9sZF9zcGVjaWZpY192YWx1ZXMgPSB0aGlzLnNwZWNpZmljX3ZhbHVlcy5zbGljZSgpO1xuXG5cdFx0bGV0IGluZGljZXNfdG9fcmVtb3ZlID0gW107XG5cdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMubWFwKChkLCBpKSA9PiB7XG5cdFx0XHRpZihkLmF1dG8pIGluZGljZXNfdG9fcmVtb3ZlLnVuc2hpZnQoaSk7XG5cdFx0fSk7XG5cblx0XHRjb25zb2xlLmxvZyhpbmRpY2VzX3RvX3JlbW92ZSk7XG5cblx0XHRpbmRpY2VzX3RvX3JlbW92ZS5tYXAoaW5kZXggPT4ge1xuXHRcdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9KTtcblxuXHRcdGNvbnNvbGUubG9nKHRoaXMuc3BlY2lmaWNfdmFsdWVzKTtcblxuXHRcdHRoaXMudXBkYXRlX3ZhbHVlcygpO1xuXHR9XG5cblx0dXBkYXRlX3ZhbHVlcyhuZXdfeSwgbmV3X3gpIHtcblx0XHRpZighbmV3X3gpIHtcblx0XHRcdG5ld194ID0gdGhpcy54O1xuXHRcdH1cblx0XHR0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUgPSBbXTtcblx0XHR0aGlzLnVwZGF0aW5nID0gdHJ1ZTtcblxuXHRcdHRoaXMub2xkX3hfdmFsdWVzID0gdGhpcy54LnNsaWNlKCk7XG5cdFx0dGhpcy5vbGRfeV9heGlzX3RvcHMgPSB0aGlzLnkubWFwKGQgPT4gZC55X3RvcHMuc2xpY2UoKSk7XG5cblx0XHR0aGlzLm9sZF95X3ZhbHVlcyA9IHRoaXMueS5tYXAoZCA9PiBkLnZhbHVlcyk7XG5cblx0XHR0aGlzLm5vX29mX2V4dHJhX3B0cyA9IG5ld194Lmxlbmd0aCAtIHRoaXMueC5sZW5ndGg7XG5cblx0XHQvLyBKdXN0IHVwZGF0ZSB2YWx1ZXMgcHJvcCwgc2V0dXBfeC95KCkgd2lsbCBkbyB0aGUgcmVzdFxuXHRcdGlmKG5ld195KSB0aGlzLnkubWFwKChkLCBpKSA9PiB7ZC52YWx1ZXMgPSBuZXdfeVtpXS52YWx1ZXM7fSk7XG5cdFx0aWYobmV3X3gpIHRoaXMueCA9IG5ld194O1xuXG5cdFx0dGhpcy5zZXR1cF94KCk7XG5cdFx0dGhpcy5zZXR1cF95KCk7XG5cblx0XHQvLyBBbmltYXRlIG9ubHkgaWYgcG9zaXRpb25zIGhhdmUgY2hhbmdlZFxuXHRcdGlmKCEkJC5hcnJheXNfZXF1YWwodGhpcy54X29sZF9heGlzX3Bvc2l0aW9ucywgdGhpcy54X2F4aXNfcG9zaXRpb25zKSkge1xuXHRcdFx0dGhpcy5tYWtlX3hfYXhpcyh0cnVlKTtcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRpZighdGhpcy51cGRhdGluZykgdGhpcy5tYWtlX3hfYXhpcygpO1xuXHRcdFx0fSwgMzAwKVxuXHRcdH1cblxuXHRcdGlmKCEkJC5hcnJheXNfZXF1YWwodGhpcy55X29sZF9heGlzX3ZhbHVlcywgdGhpcy55X2F4aXNfdmFsdWVzKSB8fFxuXHRcdFx0KHRoaXMub2xkX3NwZWNpZmljX3ZhbHVlcyAmJlxuXHRcdFx0ISQkLmFycmF5c19lcXVhbCh0aGlzLm9sZF9zcGVjaWZpY192YWx1ZXMsIHRoaXMuc3BlY2lmaWNfdmFsdWVzKSkpIHtcblxuXHRcdFx0dGhpcy5tYWtlX3lfYXhpcyh0cnVlKTtcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRpZighdGhpcy51cGRhdGluZykge1xuXHRcdFx0XHRcdHRoaXMubWFrZV95X2F4aXMoKTtcblx0XHRcdFx0XHR0aGlzLm1ha2VfeV9zcGVjaWZpY3MoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgMzAwKVxuXHRcdH1cblxuXHRcdC8vIENoYW5nZSBpbiBkYXRhLCBzbyBjYWxjdWxhdGUgZGVwZW5kZW5jaWVzXG5cdFx0dGhpcy5jYWxjX3lfZGVwZW5kZW5jaWVzKCk7XG5cblx0XHR0aGlzLmFuaW1hdGVfZ3JhcGhzKCk7XG5cblx0XHQvLyBUcmlnZ2VyIGFuaW1hdGlvbiB3aXRoIHRoZSBhbmltYXRhYmxlIGVsZW1lbnRzIGluIHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZVxuXHRcdHRoaXMucnVuX2FuaW1hdGlvbigpO1xuXG5cdFx0dGhpcy51cGRhdGluZyA9IGZhbHNlO1xuXHR9XG5cblx0YWRkX2RhdGFfcG9pbnQoeV9wb2ludCwgeF9wb2ludCwgaW5kZXg9dGhpcy54Lmxlbmd0aCkge1xuXHRcdGxldCBuZXdfeSA9IHRoaXMueS5tYXAoZGF0YV9zZXQgPT4geyByZXR1cm4ge3ZhbHVlczpkYXRhX3NldC52YWx1ZXN9OyB9KTtcblx0XHRuZXdfeS5tYXAoKGQsIGkpID0+IHsgZC52YWx1ZXMuc3BsaWNlKGluZGV4LCAwLCB5X3BvaW50W2ldKTsgfSk7XG5cdFx0bGV0IG5ld194ID0gdGhpcy54LnNsaWNlKCk7XG5cdFx0bmV3X3guc3BsaWNlKGluZGV4LCAwLCB4X3BvaW50KTtcblxuXHRcdHRoaXMudXBkYXRlX3ZhbHVlcyhuZXdfeSwgbmV3X3gpO1xuXHR9XG5cblx0cmVtb3ZlX2RhdGFfcG9pbnQoaW5kZXggPSB0aGlzLngubGVuZ3RoLTEpIHtcblx0XHRpZih0aGlzLngubGVuZ3RoIDwgMykgcmV0dXJuO1xuXG5cdFx0bGV0IG5ld195ID0gdGhpcy55Lm1hcChkYXRhX3NldCA9PiB7IHJldHVybiB7dmFsdWVzOmRhdGFfc2V0LnZhbHVlc307IH0pO1xuXHRcdG5ld195Lm1hcCgoZCwgaSkgPT4geyBkLnZhbHVlcy5zcGxpY2UoaW5kZXgsIDEpOyB9KTtcblx0XHRsZXQgbmV3X3ggPSB0aGlzLnguc2xpY2UoKTtcblx0XHRuZXdfeC5zcGxpY2UoaW5kZXgsIDEpO1xuXG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKG5ld195LCBuZXdfeCk7XG5cdH1cblxuXHRydW5fYW5pbWF0aW9uKCkge1xuXHRcdGxldCBhbmltX3N2ZyA9ICQkLnJ1blNWR0FuaW1hdGlvbih0aGlzLnN2ZywgdGhpcy5lbGVtZW50c190b19hbmltYXRlKTtcblxuXHRcdGlmKHRoaXMuc3ZnLnBhcmVudE5vZGUgPT0gdGhpcy5jaGFydF93cmFwcGVyKSB7XG5cdFx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIucmVtb3ZlQ2hpbGQodGhpcy5zdmcpO1xuXHRcdFx0dGhpcy5jaGFydF93cmFwcGVyLmFwcGVuZENoaWxkKGFuaW1fc3ZnKTtcblxuXHRcdH1cblxuXHRcdC8vIFJlcGxhY2UgdGhlIG5ldyBzdmcgKGRhdGEgaGFzIGxvbmcgYmVlbiByZXBsYWNlZClcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdGlmKGFuaW1fc3ZnLnBhcmVudE5vZGUgPT0gdGhpcy5jaGFydF93cmFwcGVyKSB7XG5cdFx0XHRcdHRoaXMuY2hhcnRfd3JhcHBlci5yZW1vdmVDaGlsZChhbmltX3N2Zyk7XG5cdFx0XHRcdHRoaXMuY2hhcnRfd3JhcHBlci5hcHBlbmRDaGlsZCh0aGlzLnN2Zyk7XG5cdFx0XHR9XG5cdFx0fSwgMjAwKTtcblx0fVxuXG5cdGFuaW1hdGVfZ3JhcGhzKCkge1xuXHRcdHRoaXMueS5tYXAoKGQsIGkpID0+IHtcblx0XHRcdC8vIFByZS1wcmVwLCBlcXVpbGl6ZSBubyBvZiBwb3NpdGlvbnMgYmV0d2VlbiBvbGQgYW5kIG5ld1xuXHRcdFx0bGV0IFtvbGRfeCwgb2xkX3ksIG5ld194LCBuZXdfeV0gPSB0aGlzLmNhbGNfb2xkX2FuZF9uZXdfcG9zdGlvbnMoZCwgaSk7XG5cdFx0XHRpZih0aGlzLm5vX29mX2V4dHJhX3B0cyA+PSAwKSB7XG5cdFx0XHRcdHRoaXMubWFrZV9wYXRoICYmIHRoaXMubWFrZV9wYXRoKGQsIGksIG9sZF94LCBvbGRfeSwgZC5jb2xvciB8fCB0aGlzLmNvbG9yc1tpXSk7XG5cdFx0XHRcdHRoaXMubWFrZV9uZXdfdW5pdHNfZm9yX2RhdGFzZXQob2xkX3gsIG9sZF95LCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldLCBpLCB0aGlzLnkubGVuZ3RoKTtcblx0XHRcdH1cblx0XHRcdGQucGF0aCAmJiB0aGlzLmFuaW1hdGVfcGF0aChkLCBpLCBvbGRfeCwgb2xkX3ksIG5ld194LCBuZXdfeSk7XG5cdFx0XHR0aGlzLmFuaW1hdGVfdW5pdHMoZCwgaSwgb2xkX3gsIG9sZF95LCBuZXdfeCwgbmV3X3kpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gVE9ETzogcmVwbGFjZSB3aXRoIHJlYWwgdW5pdHNcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMueS5tYXAoKGQsIGkpID0+IHtcblx0XHRcdFx0dGhpcy5tYWtlX3BhdGggJiYgdGhpcy5tYWtlX3BhdGgoZCwgaSwgdGhpcy54X2F4aXNfcG9zaXRpb25zLCBkLnlfdG9wcywgZC5jb2xvciB8fCB0aGlzLmNvbG9yc1tpXSk7XG5cdFx0XHRcdHRoaXMubWFrZV9uZXdfdW5pdHMoZCwgaSk7XG5cdFx0XHR9KTtcblx0XHR9LCAzMDApO1xuXHR9XG5cblx0YW5pbWF0ZV9wYXRoKGQsIGksIG9sZF94LCBvbGRfeSwgbmV3X3gsIG5ld195KSB7XG5cdFx0Ly8gQW5pbWF0ZSBwYXRoXG5cdFx0Y29uc3QgbmV3X3BvaW50c19saXN0ID0gbmV3X3kubWFwKCh5LCBpKSA9PiAobmV3X3hbaV0gKyAnLCcgKyB5KSk7XG5cdFx0Y29uc3QgbmV3X3BhdGhfc3RyID0gbmV3X3BvaW50c19saXN0LmpvaW4oXCJMXCIpO1xuXG5cdFx0Y29uc3QgcGF0aF9hcmdzID0gW3t1bml0OiBkLnBhdGgsIG9iamVjdDogZCwga2V5OiAncGF0aCd9LCB7ZDpcIk1cIituZXdfcGF0aF9zdHJ9LCAyNTAsIFwiZWFzZWluXCJdO1xuXHRcdHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZS5wdXNoKHBhdGhfYXJncyk7XG5cblx0XHQvLyBBbmltYXRlIHJlZ2lvblxuXHRcdGlmKGQucmVnaW9uX3BhdGgpIHtcblx0XHRcdGxldCByZWdfc3RhcnRfcHQgPSBgMCwke3RoaXMuemVyb19saW5lfUxgO1xuXHRcdFx0bGV0IHJlZ19lbmRfcHQgPSBgTCR7dGhpcy53aWR0aH0sJHt0aGlzLnplcm9fbGluZX1gO1xuXG5cdFx0XHRjb25zdCByZWdpb25fYXJncyA9IFtcblx0XHRcdFx0e3VuaXQ6IGQucmVnaW9uX3BhdGgsIG9iamVjdDogZCwga2V5OiAncmVnaW9uX3BhdGgnfSxcblx0XHRcdFx0e2Q6XCJNXCIgKyByZWdfc3RhcnRfcHQgKyBuZXdfcGF0aF9zdHIgKyByZWdfZW5kX3B0fSxcblx0XHRcdFx0MjUwLFxuXHRcdFx0XHRcImVhc2VpblwiXG5cdFx0XHRdO1xuXHRcdFx0dGhpcy5lbGVtZW50c190b19hbmltYXRlLnB1c2gocmVnaW9uX2FyZ3MpO1xuXHRcdH1cblx0fVxuXG5cdGFuaW1hdGVfdW5pdHMoZCwgaW5kZXgsIG9sZF94LCBvbGRfeSwgbmV3X3gsIG5ld195KSB7XG5cdFx0bGV0IHR5cGUgPSB0aGlzLnVuaXRfYXJncy50eXBlO1xuXG5cdFx0ZC5zdmdfdW5pdHMubWFwKCh1bml0LCBpKSA9PiB7XG5cdFx0XHR0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUucHVzaCh0aGlzLmFuaW1hdGVbdHlwZV0oXG5cdFx0XHRcdHt1bml0OnVuaXQsIGFycmF5OmQuc3ZnX3VuaXRzLCBpbmRleDogaX0sIC8vIHVuaXQsIHdpdGggaW5mbyB0byByZXBsYWNlIHdoZXJlIGl0IGNhbWUgZnJvbSBpbiB0aGUgZGF0YVxuXHRcdFx0XHRuZXdfeFtpXSxcblx0XHRcdFx0bmV3X3lbaV0sXG5cdFx0XHRcdGluZGV4XG5cdFx0XHQpKTtcblx0XHR9KTtcblx0fVxuXG5cdGNhbGNfb2xkX2FuZF9uZXdfcG9zdGlvbnMoZCwgaSkge1xuXHRcdGxldCBvbGRfeCA9IHRoaXMueF9vbGRfYXhpc19wb3NpdGlvbnMuc2xpY2UoKTtcblx0XHRsZXQgbmV3X3ggPSB0aGlzLnhfYXhpc19wb3NpdGlvbnMuc2xpY2UoKTtcblxuXHRcdGxldCBvbGRfeSA9IHRoaXMub2xkX3lfYXhpc190b3BzW2ldLnNsaWNlKCk7XG5cdFx0bGV0IG5ld195ID0gZC55X3RvcHMuc2xpY2UoKTtcblxuXHRcdGNvbnN0IGxhc3Rfb2xkX3hfcG9zID0gb2xkX3hbb2xkX3gubGVuZ3RoIC0gMV07XG5cdFx0Y29uc3QgbGFzdF9vbGRfeV9wb3MgPSBvbGRfeVtvbGRfeS5sZW5ndGggLSAxXTtcblxuXHRcdGNvbnN0IGxhc3RfbmV3X3hfcG9zID0gbmV3X3hbbmV3X3gubGVuZ3RoIC0gMV07XG5cdFx0Y29uc3QgbGFzdF9uZXdfeV9wb3MgPSBuZXdfeVtuZXdfeS5sZW5ndGggLSAxXTtcblxuXHRcdGlmKHRoaXMubm9fb2ZfZXh0cmFfcHRzID49IDApIHtcblx0XHRcdC8vIEZpcnN0IHN1YnN0aXR1dGUgY3VycmVudCBwYXRoIHdpdGggYSBzcXVpZ2dsZWQgb25lIChsb29raW5nIHRoZSBzYW1lIGJ1dFxuXHRcdFx0Ly8gaGF2aW5nIG1vcmUgcG9pbnRzIGF0IGVuZCksXG5cdFx0XHQvLyB0aGVuIGFuaW1hdGUgdG8gc3RyZXRjaCBpdCBsYXRlciB0byBuZXcgcG9pbnRzXG5cdFx0XHQvLyAobmV3IHBvaW50cyBhbHJlYWR5IGhhdmUgbW9yZSBwb2ludHMpXG5cblx0XHRcdC8vIEhlbmNlLCB0aGUgZXh0cmEgZW5kIHBvaW50cyB3aWxsIGNvcnJlc3BvbmQgdG8gY3VycmVudChvbGQpIHBvc2l0aW9uc1xuXHRcdFx0bGV0IGZpbGxlcl94ID0gbmV3IEFycmF5KE1hdGguYWJzKHRoaXMubm9fb2ZfZXh0cmFfcHRzKSkuZmlsbChsYXN0X29sZF94X3Bvcyk7XG5cdFx0XHRsZXQgZmlsbGVyX3kgPSBuZXcgQXJyYXkoTWF0aC5hYnModGhpcy5ub19vZl9leHRyYV9wdHMpKS5maWxsKGxhc3Rfb2xkX3lfcG9zKTtcblxuXHRcdFx0b2xkX3ggPSBvbGRfeC5jb25jYXQoZmlsbGVyX3gpO1xuXHRcdFx0b2xkX3kgPSBvbGRfeS5jb25jYXQoZmlsbGVyX3kpO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIEp1c3QgbW9kaWZ5IHRoZSBuZXcgcG9pbnRzIHRvIGhhdmUgZXh0cmEgcG9pbnRzXG5cdFx0XHQvLyB3aXRoIHRoZSBzYW1lIHBvc2l0aW9uIGF0IGVuZFxuXHRcdFx0bGV0IGZpbGxlcl94ID0gbmV3IEFycmF5KE1hdGguYWJzKHRoaXMubm9fb2ZfZXh0cmFfcHRzKSkuZmlsbChsYXN0X25ld194X3Bvcyk7XG5cdFx0XHRsZXQgZmlsbGVyX3kgPSBuZXcgQXJyYXkoTWF0aC5hYnModGhpcy5ub19vZl9leHRyYV9wdHMpKS5maWxsKGxhc3RfbmV3X3lfcG9zKTtcblxuXHRcdFx0bmV3X3ggPSBuZXdfeC5jb25jYXQoZmlsbGVyX3gpO1xuXHRcdFx0bmV3X3kgPSBuZXdfeS5jb25jYXQoZmlsbGVyX3kpO1xuXHRcdH1cblxuXHRcdHJldHVybiBbb2xkX3gsIG9sZF95LCBuZXdfeCwgbmV3X3ldO1xuXHR9XG5cblx0bWFrZV9hbmltX3hfYXhpcyhoZWlnaHQsIHRleHRfc3RhcnRfYXQsIGF4aXNfbGluZV9jbGFzcykge1xuXHRcdC8vIEFuaW1hdGUgWCBBWElTIHRvIGFjY291bnQgZm9yIG1vcmUgb3IgbGVzcyBheGlzIGxpbmVzXG5cblx0XHRjb25zdCBvbGRfcG9zID0gdGhpcy54X29sZF9heGlzX3Bvc2l0aW9ucztcblx0XHRjb25zdCBuZXdfcG9zID0gdGhpcy54X2F4aXNfcG9zaXRpb25zO1xuXG5cdFx0Y29uc3Qgb2xkX3ZhbHMgPSB0aGlzLm9sZF94X3ZhbHVlcztcblx0XHRjb25zdCBuZXdfdmFscyA9IHRoaXMueDtcblxuXHRcdGNvbnN0IGxhc3RfbGluZV9wb3MgPSBvbGRfcG9zW29sZF9wb3MubGVuZ3RoIC0gMV07XG5cblx0XHRsZXQgYWRkX2FuZF9hbmltYXRlX2xpbmUgPSAodmFsdWUsIG9sZF9wb3MsIG5ld19wb3MsIGkpID0+IHtcblx0XHRcdGNvbnN0IHhfbGluZSA9IHRoaXMubWFrZV94X2xpbmUoXG5cdFx0XHRcdGhlaWdodCxcblx0XHRcdFx0dGV4dF9zdGFydF9hdCxcblx0XHRcdFx0dmFsdWUsIC8vIG5ldyB2YWx1ZVxuXHRcdFx0XHQneC12YWx1ZS10ZXh0Jyxcblx0XHRcdFx0YXhpc19saW5lX2NsYXNzLFxuXHRcdFx0XHRvbGRfcG9zIC8vIG9sZCBwb3NpdGlvblxuXHRcdFx0KTtcblx0XHRcdHRoaXMueF9heGlzX2dyb3VwLmFwcGVuZENoaWxkKHhfbGluZSk7XG5cblx0XHRcdHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZSAmJiB0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUucHVzaChbXG5cdFx0XHRcdHt1bml0OiB4X2xpbmUsIGFycmF5OiBbMF0sIGluZGV4OiAwfSxcblx0XHRcdFx0e3RyYW5zZm9ybTogYCR7IG5ld19wb3MgfSwgMGB9LFxuXHRcdFx0XHQyNTAsXG5cdFx0XHRcdFwiZWFzZWluXCIsXG5cdFx0XHRcdFwidHJhbnNsYXRlXCIsXG5cdFx0XHRcdHt0cmFuc2Zvcm06IGAkeyBvbGRfcG9zIH0sIDBgfVxuXHRcdFx0XSk7XG5cdFx0fVxuXG5cdFx0dGhpcy54X2F4aXNfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblxuXHRcdHRoaXMubWFrZV9uZXdfYXhpc19hbmltX2xpbmVzKFxuXHRcdFx0b2xkX3Bvcyxcblx0XHRcdG5ld19wb3MsXG5cdFx0XHRvbGRfdmFscyxcblx0XHRcdG5ld192YWxzLFxuXHRcdFx0bGFzdF9saW5lX3Bvcyxcblx0XHRcdGFkZF9hbmRfYW5pbWF0ZV9saW5lXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfYW5pbV95X2F4aXMoKSB7XG5cdFx0Ly8gQW5pbWF0ZSBZIEFYSVMgdG8gYWNjb3VudCBmb3IgbW9yZSBvciBsZXNzIGF4aXMgbGluZXNcblxuXHRcdGNvbnN0IG9sZF9wb3MgPSB0aGlzLnlfb2xkX2F4aXNfdmFsdWVzLm1hcCh2YWx1ZSA9PlxuXHRcdFx0dGhpcy56ZXJvX2xpbmUgLSB2YWx1ZSAqIHRoaXMubXVsdGlwbGllcik7XG5cdFx0Y29uc3QgbmV3X3BvcyA9IHRoaXMueV9heGlzX3ZhbHVlcy5tYXAodmFsdWUgPT5cblx0XHRcdHRoaXMuemVyb19saW5lIC0gdmFsdWUgKiB0aGlzLm11bHRpcGxpZXIpO1xuXG5cdFx0Y29uc3Qgb2xkX3ZhbHMgPSB0aGlzLnlfb2xkX2F4aXNfdmFsdWVzO1xuXHRcdGNvbnN0IG5ld192YWxzID0gdGhpcy55X2F4aXNfdmFsdWVzO1xuXG5cdFx0Y29uc3QgbGFzdF9saW5lX3BvcyA9IG9sZF9wb3Nbb2xkX3Bvcy5sZW5ndGggLSAxXTtcblxuXHRcdHRoaXMueV9heGlzX2dyb3VwLnRleHRDb250ZW50ID0gJyc7XG5cblx0XHR0aGlzLm1ha2VfbmV3X2F4aXNfYW5pbV9saW5lcyhcblx0XHRcdG9sZF9wb3MsXG5cdFx0XHRuZXdfcG9zLFxuXHRcdFx0b2xkX3ZhbHMsXG5cdFx0XHRuZXdfdmFscyxcblx0XHRcdGxhc3RfbGluZV9wb3MsXG5cdFx0XHR0aGlzLmFkZF9hbmRfYW5pbWF0ZV95X2xpbmUuYmluZCh0aGlzKSxcblx0XHRcdHRoaXMueV9heGlzX2dyb3VwXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfYW5pbV95X3NwZWNpZmljcygpIHtcblx0XHR0aGlzLnNwZWNpZmljX3lfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLnNwZWNpZmljX3ZhbHVlcy5tYXAoKGQsIGkpID0+IHtcblx0XHRcdHRoaXMuYWRkX2FuZF9hbmltYXRlX3lfbGluZShcblx0XHRcdFx0ZC50aXRsZSxcblx0XHRcdFx0dGhpcy5vbGRfemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMub2xkX211bHRpcGxpZXIsXG5cdFx0XHRcdHRoaXMuemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0MCxcblx0XHRcdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLFxuXHRcdFx0XHRkLmxpbmVfdHlwZSxcblx0XHRcdFx0dHJ1ZVxuXHRcdFx0KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfbmV3X2F4aXNfYW5pbV9saW5lcyhvbGRfcG9zLCBuZXdfcG9zLCBvbGRfdmFscywgbmV3X3ZhbHMsIGxhc3RfbGluZV9wb3MsIGFkZF9hbmRfYW5pbWF0ZV9saW5lLCBncm91cCkge1xuXHRcdGxldCBzdXBlcmltcG9zZWRfcG9zaXRpb25zLCBzdXBlcmltcG9zZWRfdmFsdWVzO1xuXHRcdGxldCBub19vZl9leHRyYXMgPSBuZXdfdmFscy5sZW5ndGggLSBvbGRfdmFscy5sZW5ndGg7XG5cdFx0aWYobm9fb2ZfZXh0cmFzID4gMCkge1xuXHRcdFx0Ly8gTW9yZSBheGlzIGFyZSBuZWVkZWRcblx0XHRcdC8vIEZpcnN0IG1ha2Ugb25seSB0aGUgc3VwZXJpbXBvc2VkIChzYW1lIHBvc2l0aW9uKSBvbmVzXG5cdFx0XHQvLyBBZGQgaW4gdGhlIGV4dHJhcyBhdCB0aGUgZW5kIGxhdGVyXG5cdFx0XHRzdXBlcmltcG9zZWRfcG9zaXRpb25zID0gbmV3X3Bvcy5zbGljZSgwLCBvbGRfcG9zLmxlbmd0aCk7XG5cdFx0XHRzdXBlcmltcG9zZWRfdmFsdWVzID0gbmV3X3ZhbHMuc2xpY2UoMCwgb2xkX3ZhbHMubGVuZ3RoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gQXhpcyBoYXZlIHRvIGJlIHJlZHVjZWRcblx0XHRcdC8vIEZha2UgaXQgYnkgbW92aW5nIGFsbCBjdXJyZW50IGV4dHJhIGF4aXMgdG8gdGhlIGxhc3QgcG9zaXRpb25cblx0XHRcdC8vIFlvdSdsbCBuZWVkIGZpbGxlciBwb3NpdGlvbnMgYW5kIHZhbHVlcyBpbiB0aGUgbmV3IGFycmF5c1xuXHRcdFx0Y29uc3QgZmlsbGVyX3ZhbHMgPSBuZXcgQXJyYXkoTWF0aC5hYnMobm9fb2ZfZXh0cmFzKSkuZmlsbChcIlwiKTtcblx0XHRcdHN1cGVyaW1wb3NlZF92YWx1ZXMgPSBuZXdfdmFscy5jb25jYXQoZmlsbGVyX3ZhbHMpO1xuXG5cdFx0XHRjb25zdCBmaWxsZXJfcG9zID0gbmV3IEFycmF5KE1hdGguYWJzKG5vX29mX2V4dHJhcykpLmZpbGwobGFzdF9saW5lX3Bvcyk7XG5cdFx0XHRzdXBlcmltcG9zZWRfcG9zaXRpb25zID0gbmV3X3Bvcy5jb25jYXQoZmlsbGVyX3Bvcyk7XG5cdFx0fVxuXG5cdFx0c3VwZXJpbXBvc2VkX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRhZGRfYW5kX2FuaW1hdGVfbGluZSh2YWx1ZSwgb2xkX3Bvc1tpXSwgc3VwZXJpbXBvc2VkX3Bvc2l0aW9uc1tpXSwgaSwgZ3JvdXApO1xuXHRcdH0pO1xuXG5cdFx0aWYobm9fb2ZfZXh0cmFzID4gMCkge1xuXHRcdFx0Ly8gQWRkIGluIGV4dHJhIGF4aXMgaW4gdGhlIGVuZFxuXHRcdFx0Ly8gYW5kIHRoZW4gYW5pbWF0ZSB0byBuZXcgcG9zaXRpb25zXG5cdFx0XHRjb25zdCBleHRyYV92YWx1ZXMgPSBuZXdfdmFscy5zbGljZShvbGRfdmFscy5sZW5ndGgpO1xuXHRcdFx0Y29uc3QgZXh0cmFfcG9zaXRpb25zID0gbmV3X3Bvcy5zbGljZShvbGRfcG9zLmxlbmd0aCk7XG5cblx0XHRcdGV4dHJhX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRcdGFkZF9hbmRfYW5pbWF0ZV9saW5lKHZhbHVlLCBsYXN0X2xpbmVfcG9zLCBleHRyYV9wb3NpdGlvbnNbaV0sIGksIGdyb3VwKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdG1ha2VfeF9saW5lKGhlaWdodCwgdGV4dF9zdGFydF9hdCwgcG9pbnQsIGxhYmVsX2NsYXNzLCBheGlzX2xpbmVfY2xhc3MsIHhfcG9zKSB7XG5cdFx0bGV0IGFsbG93ZWRfc3BhY2UgPSB0aGlzLmF2Z191bml0X3dpZHRoICogMS41O1xuXG5cdFx0aWYodGhpcy5nZXRfc3Ryd2lkdGgocG9pbnQpID4gYWxsb3dlZF9zcGFjZSkge1xuXHRcdFx0bGV0IGFsbG93ZWRfbGV0dGVycyA9IGFsbG93ZWRfc3BhY2UgLyA4O1xuXHRcdFx0cG9pbnQgPSBwb2ludC5zbGljZSgwLCBhbGxvd2VkX2xldHRlcnMtMykgKyBcIiAuLi5cIjtcblx0XHR9XG5cblx0XHRsZXQgbGluZSA9ICQkLmNyZWF0ZVNWRygnbGluZScsIHtcblx0XHRcdHgxOiAwLFxuXHRcdFx0eDI6IDAsXG5cdFx0XHR5MTogMCxcblx0XHRcdHkyOiBoZWlnaHRcblx0XHR9KTtcblxuXHRcdGxldCB0ZXh0ID0gJCQuY3JlYXRlU1ZHKCd0ZXh0Jywge1xuXHRcdFx0Y2xhc3NOYW1lOiBsYWJlbF9jbGFzcyxcblx0XHRcdHg6IDAsXG5cdFx0XHR5OiB0ZXh0X3N0YXJ0X2F0LFxuXHRcdFx0ZHk6ICcuNzFlbScsXG5cdFx0XHRpbm5lckhUTUw6IHBvaW50XG5cdFx0fSk7XG5cblx0XHRsZXQgeF9sZXZlbCA9ICQkLmNyZWF0ZVNWRygnZycsIHtcblx0XHRcdGNsYXNzTmFtZTogYHRpY2sgJHtheGlzX2xpbmVfY2xhc3N9YCxcblx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgkeyB4X3BvcyB9LCAwKWBcblx0XHR9KTtcblxuXHRcdHhfbGV2ZWwuYXBwZW5kQ2hpbGQobGluZSk7XG5cdFx0eF9sZXZlbC5hcHBlbmRDaGlsZCh0ZXh0KTtcblxuXHRcdHJldHVybiB4X2xldmVsO1xuXHR9XG5cblx0bWFrZV95X2xpbmUoc3RhcnRfYXQsIHdpZHRoLCB0ZXh0X2VuZF9hdCwgcG9pbnQsIGxhYmVsX2NsYXNzLCBheGlzX2xpbmVfY2xhc3MsIHlfcG9zLCBkYXJrZXI9ZmFsc2UsIGxpbmVfdHlwZT1cIlwiKSB7XG5cdFx0bGV0IGxpbmUgPSAkJC5jcmVhdGVTVkcoJ2xpbmUnLCB7XG5cdFx0XHRjbGFzc05hbWU6IGxpbmVfdHlwZSA9PT0gXCJkYXNoZWRcIiA/IFwiZGFzaGVkXCI6IFwiXCIsXG5cdFx0XHR4MTogc3RhcnRfYXQsXG5cdFx0XHR4Mjogd2lkdGgsXG5cdFx0XHR5MTogMCxcblx0XHRcdHkyOiAwXG5cdFx0fSk7XG5cblx0XHRsZXQgdGV4dCA9ICQkLmNyZWF0ZVNWRygndGV4dCcsIHtcblx0XHRcdGNsYXNzTmFtZTogbGFiZWxfY2xhc3MsXG5cdFx0XHR4OiB0ZXh0X2VuZF9hdCxcblx0XHRcdHk6IDAsXG5cdFx0XHRkeTogJy4zMmVtJyxcblx0XHRcdGlubmVySFRNTDogcG9pbnQrXCJcIlxuXHRcdH0pO1xuXG5cdFx0bGV0IHlfbGV2ZWwgPSAkJC5jcmVhdGVTVkcoJ2cnLCB7XG5cdFx0XHRjbGFzc05hbWU6IGB0aWNrICR7YXhpc19saW5lX2NsYXNzfWAsXG5cdFx0XHR0cmFuc2Zvcm06IGB0cmFuc2xhdGUoMCwgJHt5X3Bvc30pYFxuXHRcdH0pO1xuXG5cdFx0aWYoZGFya2VyKSB7XG5cdFx0XHRsaW5lLnN0eWxlLnN0cm9rZSA9IFwicmdiYSgyNywgMzEsIDM1LCAwLjYpXCI7XG5cdFx0fVxuXG5cdFx0eV9sZXZlbC5hcHBlbmRDaGlsZChsaW5lKTtcblx0XHR5X2xldmVsLmFwcGVuZENoaWxkKHRleHQpO1xuXG5cdFx0cmV0dXJuIHlfbGV2ZWw7XG5cdH1cblxuXHRhZGRfYW5kX2FuaW1hdGVfeV9saW5lKHZhbHVlLCBvbGRfcG9zLCBuZXdfcG9zLCBpLCBncm91cCwgdHlwZSwgc3BlY2lmaWM9ZmFsc2UpIHtcblx0XHRsZXQgW3dpZHRoLCB0ZXh0X2VuZF9hdCwgYXhpc19saW5lX2NsYXNzLCBzdGFydF9hdF0gPSB0aGlzLmdldF95X2F4aXNfbGluZV9wcm9wcyhzcGVjaWZpYyk7XG5cdFx0bGV0IGF4aXNfbGFiZWxfY2xhc3MgPSAhc3BlY2lmaWMgPyAneS12YWx1ZS10ZXh0JyA6ICdzcGVjaWZpYy12YWx1ZSc7XG5cdFx0dmFsdWUgPSAhc3BlY2lmaWMgPyB2YWx1ZSA6ICh2YWx1ZStcIlwiKS50b1VwcGVyQ2FzZSgpO1xuXHRcdGNvbnN0IHlfbGluZSA9IHRoaXMubWFrZV95X2xpbmUoXG5cdFx0XHRzdGFydF9hdCxcblx0XHRcdHdpZHRoLFxuXHRcdFx0dGV4dF9lbmRfYXQsXG5cdFx0XHR2YWx1ZSxcblx0XHRcdGF4aXNfbGFiZWxfY2xhc3MsXG5cdFx0XHRheGlzX2xpbmVfY2xhc3MsXG5cdFx0XHRvbGRfcG9zLCAgLy8gb2xkIHBvc2l0aW9uXG5cdFx0XHQodmFsdWUgPT09IDAgJiYgaSAhPT0gMCksIC8vIE5vbi1maXJzdCBaZXJvIGxpbmVcblx0XHRcdHR5cGVcblx0XHQpO1xuXG5cdFx0Z3JvdXAuYXBwZW5kQ2hpbGQoeV9saW5lKTtcblxuXHRcdHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZSAmJiB0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUucHVzaChbXG5cdFx0XHR7dW5pdDogeV9saW5lLCBhcnJheTogWzBdLCBpbmRleDogMH0sXG5cdFx0XHR7dHJhbnNmb3JtOiBgMCwgJHsgbmV3X3BvcyB9YH0sXG5cdFx0XHQyNTAsXG5cdFx0XHRcImVhc2VpblwiLFxuXHRcdFx0XCJ0cmFuc2xhdGVcIixcblx0XHRcdHt0cmFuc2Zvcm06IGAwLCAkeyBvbGRfcG9zIH1gfVxuXHRcdF0pO1xuXHR9XG5cblx0Z2V0X3lfYXhpc19wb2ludHMoYXJyYXkpIHtcblx0XHQvLyoqKiBXaGVyZSB0aGUgbWFnaWMgaGFwcGVucyAqKipcblxuXHRcdC8vIENhbGN1bGF0ZXMgYmVzdC1maXQgeSBpbnRlcnZhbHMgZnJvbSBnaXZlbiB2YWx1ZXNcblx0XHQvLyBhbmQgcmV0dXJucyB0aGUgaW50ZXJ2YWwgYXJyYXlcblxuXHRcdC8vIFRPRE86IEZyYWN0aW9uc1xuXG5cdFx0bGV0IG1heF9ib3VuZCwgbWluX2JvdW5kLCBwb3Nfbm9fb2ZfcGFydHMsIG5lZ19ub19vZl9wYXJ0cywgcGFydF9zaXplO1xuXG5cdFx0Ly8gQ3JpdGljYWwgdmFsdWVzXG5cdFx0bGV0IG1heF92YWwgPSBwYXJzZUludChNYXRoLm1heCguLi5hcnJheSkpO1xuXHRcdGxldCBtaW5fdmFsID0gcGFyc2VJbnQoTWF0aC5taW4oLi4uYXJyYXkpKTtcblx0XHRpZihtaW5fdmFsID49IDApIHtcblx0XHRcdG1pbl92YWwgPSAwO1xuXHRcdH1cblxuXHRcdGxldCBnZXRfcGFyYW1zID0gKHZhbHVlMSwgdmFsdWUyKSA9PiB7XG5cdFx0XHRsZXQgYm91bmQxLCBib3VuZDIsIG5vX29mX3BhcnRzXzEsIG5vX29mX3BhcnRzXzIsIGludGVydmFsX3NpemU7XG5cdFx0XHRpZigodmFsdWUxK1wiXCIpLmxlbmd0aCA8PSAxKSB7XG5cdFx0XHRcdFtib3VuZDEsIG5vX29mX3BhcnRzXzFdID0gWzEwLCA1XTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFtib3VuZDEsIG5vX29mX3BhcnRzXzFdID0gdGhpcy5jYWxjX3VwcGVyX2JvdW5kX2FuZF9ub19vZl9wYXJ0cyh2YWx1ZTEpO1xuXHRcdFx0fVxuXG5cdFx0XHRpbnRlcnZhbF9zaXplID0gYm91bmQxIC8gbm9fb2ZfcGFydHNfMTtcblx0XHRcdG5vX29mX3BhcnRzXzIgPSB0aGlzLmNhbGNfbm9fb2ZfcGFydHModmFsdWUyLCBpbnRlcnZhbF9zaXplKTtcblx0XHRcdGJvdW5kMiA9IG5vX29mX3BhcnRzXzIgKiBpbnRlcnZhbF9zaXplO1xuXG5cdFx0XHRyZXR1cm4gW2JvdW5kMSwgYm91bmQyLCBub19vZl9wYXJ0c18xLCBub19vZl9wYXJ0c18yLCBpbnRlcnZhbF9zaXplXTtcblx0XHR9XG5cblx0XHRjb25zdCBhYnNfbWluX3ZhbCA9IG1pbl92YWwgKiAtMTtcblx0XHRpZihhYnNfbWluX3ZhbCA8PSBtYXhfdmFsKSB7XG5cdFx0XHQvLyBHZXQgdGhlIHBvc2l0aXZlIHJlZ2lvbiBpbnRlcnZhbHNcblx0XHRcdC8vIHRoZW4gY2FsYyBuZWdhdGl2ZSBvbmVzIGFjY29yZGluZ2x5XG5cdFx0XHRbbWF4X2JvdW5kLCBtaW5fYm91bmQsIHBvc19ub19vZl9wYXJ0cywgbmVnX25vX29mX3BhcnRzLCBwYXJ0X3NpemVdXG5cdFx0XHRcdD0gZ2V0X3BhcmFtcyhtYXhfdmFsLCBhYnNfbWluX3ZhbCk7XG5cdFx0XHRpZihhYnNfbWluX3ZhbCA9PT0gMCkge1xuXHRcdFx0XHRtaW5fYm91bmQgPSAwOyBuZWdfbm9fb2ZfcGFydHMgPSAwO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBHZXQgdGhlIG5lZ2F0aXZlIHJlZ2lvbiBoZXJlIGZpcnN0XG5cdFx0XHRbbWluX2JvdW5kLCBtYXhfYm91bmQsIG5lZ19ub19vZl9wYXJ0cywgcG9zX25vX29mX3BhcnRzLCBwYXJ0X3NpemVdXG5cdFx0XHRcdD0gZ2V0X3BhcmFtcyhhYnNfbWluX3ZhbCwgbWF4X3ZhbCk7XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBib3RoIHJlZ2lvbiBwYXJ0cyBldmVuXG5cdFx0aWYocG9zX25vX29mX3BhcnRzICUgMiAhPT0gMCAmJiBuZWdfbm9fb2ZfcGFydHMgPiAwKSBwb3Nfbm9fb2ZfcGFydHMrKztcblx0XHRpZihuZWdfbm9fb2ZfcGFydHMgJSAyICE9PSAwKSB7XG5cdFx0XHQvLyBldmVyeSBpbmNyZWFzZSBpbiBub19vZl9wYXJ0cyBlbnRhaWxzIGFuIGluY3JlYXNlIGluIGNvcnJlc3BvbmRpbmcgYm91bmRcblx0XHRcdC8vIGV4Y2VwdCBoZXJlLCBpdCBoYXBwZW5zIGltcGxpY2l0bHkgYWZ0ZXIgZXZlcnkgY2FsY19ub19vZl9wYXJ0cygpIGNhbGxcblx0XHRcdG5lZ19ub19vZl9wYXJ0cysrO1xuXHRcdFx0bWluX2JvdW5kICs9IHBhcnRfc2l6ZTtcblx0XHR9XG5cblx0XHRsZXQgbm9fb2ZfcGFydHMgPSBwb3Nfbm9fb2ZfcGFydHMgKyBuZWdfbm9fb2ZfcGFydHM7XG5cdFx0aWYobm9fb2ZfcGFydHMgPiA1KSB7XG5cdFx0XHRub19vZl9wYXJ0cyAvPSAyO1xuXHRcdFx0cGFydF9zaXplICo9IDI7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZ2V0X2ludGVydmFscyhcblx0XHRcdCgtMSkgKiBtaW5fYm91bmQsXG5cdFx0XHRwYXJ0X3NpemUsXG5cdFx0XHRub19vZl9wYXJ0c1xuXHRcdCk7XG5cdH1cblxuXHRnZXRfaW50ZXJ2YWxzKHN0YXJ0LCBpbnRlcnZhbF9zaXplLCBjb3VudCkge1xuXHRcdGxldCBpbnRlcnZhbHMgPSBbXTtcblx0XHRmb3IodmFyIGkgPSAwOyBpIDw9IGNvdW50OyBpKyspe1xuXHRcdFx0aW50ZXJ2YWxzLnB1c2goc3RhcnQpO1xuXHRcdFx0c3RhcnQgKz0gaW50ZXJ2YWxfc2l6ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGludGVydmFscztcblx0fVxuXG5cdGNhbGNfdXBwZXJfYm91bmRfYW5kX25vX29mX3BhcnRzKG1heF92YWwpIHtcblx0XHQvLyBHaXZlbiBhIHBvc2l0aXZlIHZhbHVlLCBjYWxjdWxhdGVzIGEgbmljZS1udW1iZXIgdXBwZXIgYm91bmRcblx0XHQvLyBhbmQgYSBjb25zZXF1ZW50IG9wdGltYWwgbnVtYmVyIG9mIHBhcnRzXG5cblx0XHRjb25zdCBwYXJ0X3NpemUgPSBNYXRoLnBvdygxMCwgKChtYXhfdmFsK1wiXCIpLmxlbmd0aCAtIDEpKTtcblx0XHRjb25zdCBub19vZl9wYXJ0cyA9IHRoaXMuY2FsY19ub19vZl9wYXJ0cyhtYXhfdmFsLCBwYXJ0X3NpemUpO1xuXG5cdFx0Ly8gVXNlIGl0IHRvIGdldCBhIG5pY2UgZXZlbiB1cHBlciBib3VuZFxuXHRcdGNvbnN0IHVwcGVyX2JvdW5kID0gcGFydF9zaXplICogbm9fb2ZfcGFydHM7XG5cblx0XHRyZXR1cm4gW3VwcGVyX2JvdW5kLCBub19vZl9wYXJ0c107XG5cdH1cblxuXHRjYWxjX25vX29mX3BhcnRzKHZhbHVlLCBkaXZpc29yKSB7XG5cdFx0Ly8gdmFsdWUgc2hvdWxkIGJlIGEgcG9zaXRpdmUgbnVtYmVyLCBkaXZpc29yIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gMFxuXHRcdC8vIHJldHVybnMgYW4gZXZlbiBubyBvZiBwYXJ0c1xuXHRcdGxldCBub19vZl9wYXJ0cyA9IE1hdGguY2VpbCh2YWx1ZSAvIGRpdmlzb3IpO1xuXHRcdGlmKG5vX29mX3BhcnRzICUgMiAhPT0gMCkgbm9fb2ZfcGFydHMrKzsgLy8gTWFrZSBpdCBhbiBldmVuIG51bWJlclxuXG5cdFx0cmV0dXJuIG5vX29mX3BhcnRzO1xuXHR9XG5cblx0Z2V0X29wdGltYWxfbm9fb2ZfcGFydHMobm9fb2ZfcGFydHMpIHtcblx0XHQvLyBha2EgRGl2aWRlIGJ5IDIgaWYgdG9vIGxhcmdlXG5cdFx0cmV0dXJuIChub19vZl9wYXJ0cyA8IDUpID8gbm9fb2ZfcGFydHMgOiBub19vZl9wYXJ0cyAvIDI7XG5cdH1cblxuXHRzZXRfYXZnX3VuaXRfd2lkdGhfYW5kX3hfb2Zmc2V0KCkge1xuXHRcdC8vIFNldCB0aGUgLi4uIHlvdSBnZXQgaXRcblx0XHR0aGlzLmF2Z191bml0X3dpZHRoID0gdGhpcy53aWR0aC8odGhpcy54Lmxlbmd0aCAtIDEpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSAwO1xuXHR9XG5cblx0Z2V0X2FsbF95X3ZhbHVlcygpIHtcblx0XHRsZXQgYWxsX3ZhbHVlcyA9IFtdO1xuXG5cdFx0Ly8gQWRkIGluIGFsbCB0aGUgeSB2YWx1ZXMgaW4gdGhlIGRhdGFzZXRzXG5cdFx0dGhpcy55Lm1hcChkID0+IHtcblx0XHRcdGFsbF92YWx1ZXMgPSBhbGxfdmFsdWVzLmNvbmNhdChkLnZhbHVlcyk7XG5cdFx0fSk7XG5cblx0XHQvLyBBZGQgaW4gYWxsIHRoZSBzcGVjaWZpYyB2YWx1ZXNcblx0XHRyZXR1cm4gYWxsX3ZhbHVlcy5jb25jYXQodGhpcy5zcGVjaWZpY192YWx1ZXMubWFwKGQgPT4gZC52YWx1ZSkpO1xuXHR9XG5cblx0Y2FsY195X2RlcGVuZGVuY2llcygpIHtcblx0XHR0aGlzLnlfbWluX3RvcHMgPSBuZXcgQXJyYXkodGhpcy54X2F4aXNfcG9zaXRpb25zLmxlbmd0aCkuZmlsbCg5OTk5KTtcblx0XHR0aGlzLnkubWFwKGQgPT4ge1xuXHRcdFx0ZC55X3RvcHMgPSBkLnZhbHVlcy5tYXAoIHZhbCA9PiAkJC5mbG9hdF8yKHRoaXMuemVyb19saW5lIC0gdmFsICogdGhpcy5tdWx0aXBsaWVyKSk7XG5cdFx0XHRkLnlfdG9wcy5tYXAoICh5X3RvcCwgaSkgPT4ge1xuXHRcdFx0XHRpZih5X3RvcCA8IHRoaXMueV9taW5fdG9wc1tpXSkge1xuXHRcdFx0XHRcdHRoaXMueV9taW5fdG9wc1tpXSA9IHlfdG9wO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdGdldF9iYXJfaGVpZ2h0X2FuZF95X2F0dHIoeV90b3ApIHtcblx0XHRsZXQgaGVpZ2h0LCB5O1xuXHRcdGlmICh5X3RvcCA8PSB0aGlzLnplcm9fbGluZSkge1xuXHRcdFx0aGVpZ2h0ID0gdGhpcy56ZXJvX2xpbmUgLSB5X3RvcDtcblx0XHRcdHkgPSB5X3RvcDtcblxuXHRcdFx0Ly8gSW4gY2FzZSBvZiBpbnZpc2libGUgYmFyc1xuXHRcdFx0aWYoaGVpZ2h0ID09PSAwKSB7XG5cdFx0XHRcdGhlaWdodCA9IHRoaXMuaGVpZ2h0ICogMC4wMTtcblx0XHRcdFx0eSAtPSBoZWlnaHQ7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGhlaWdodCA9IHlfdG9wIC0gdGhpcy56ZXJvX2xpbmU7XG5cdFx0XHR5ID0gdGhpcy56ZXJvX2xpbmU7XG5cblx0XHRcdC8vIEluIGNhc2Ugb2YgaW52aXNpYmxlIGJhcnNcblx0XHRcdGlmKGhlaWdodCA9PT0gMCkge1xuXHRcdFx0XHRoZWlnaHQgPSB0aGlzLmhlaWdodCAqIDAuMDE7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtoZWlnaHQsIHldO1xuXHR9XG5cblx0c2V0dXBfdXRpbHMoKSB7XG5cdFx0dGhpcy5kcmF3ID0ge1xuXHRcdFx0J2Jhcic6ICh4LCB5X3RvcCwgYXJncywgY29sb3IsIGluZGV4LCBub19vZl9kYXRhc2V0cykgPT4ge1xuXHRcdFx0XHRsZXQgdG90YWxfd2lkdGggPSB0aGlzLmF2Z191bml0X3dpZHRoIC0gYXJncy5zcGFjZV93aWR0aDtcblx0XHRcdFx0bGV0IHN0YXJ0X3ggPSB4IC0gdG90YWxfd2lkdGgvMjtcblxuXHRcdFx0XHRsZXQgd2lkdGggPSB0b3RhbF93aWR0aCAvIG5vX29mX2RhdGFzZXRzO1xuXHRcdFx0XHRsZXQgY3VycmVudF94ID0gc3RhcnRfeCArIHdpZHRoICogaW5kZXg7XG5cblx0XHRcdFx0bGV0IFtoZWlnaHQsIHldID0gdGhpcy5nZXRfYmFyX2hlaWdodF9hbmRfeV9hdHRyKHlfdG9wKTtcblxuXHRcdFx0XHRyZXR1cm4gJCQuY3JlYXRlU1ZHKCdyZWN0Jywge1xuXHRcdFx0XHRcdGNsYXNzTmFtZTogYGJhciBtaW5pIGZpbGwgJHtjb2xvcn1gLFxuXHRcdFx0XHRcdHg6IGN1cnJlbnRfeCxcblx0XHRcdFx0XHR5OiB5LFxuXHRcdFx0XHRcdHdpZHRoOiB3aWR0aCxcblx0XHRcdFx0XHRoZWlnaHQ6IGhlaWdodFxuXHRcdFx0XHR9KTtcblxuXHRcdFx0fSxcblx0XHRcdCdkb3QnOiAoeCwgeSwgYXJncywgY29sb3IpID0+IHtcblx0XHRcdFx0cmV0dXJuICQkLmNyZWF0ZVNWRygnY2lyY2xlJywge1xuXHRcdFx0XHRcdGNsYXNzTmFtZTogYGZpbGwgJHtjb2xvcn1gLFxuXHRcdFx0XHRcdGN4OiB4LFxuXHRcdFx0XHRcdGN5OiB5LFxuXHRcdFx0XHRcdHI6IGFyZ3MucmFkaXVzXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHR0aGlzLmFuaW1hdGUgPSB7XG5cdFx0XHQnYmFyJzogKGJhcl9vYmosIHgsIHlfdG9wLCBpbmRleCkgPT4ge1xuXHRcdFx0XHRsZXQgc3RhcnQgPSB4IC0gdGhpcy5hdmdfdW5pdF93aWR0aC80O1xuXHRcdFx0XHRsZXQgd2lkdGggPSAodGhpcy5hdmdfdW5pdF93aWR0aC8yKS90aGlzLnkubGVuZ3RoO1xuXHRcdFx0XHRsZXQgW2hlaWdodCwgeV0gPSB0aGlzLmdldF9iYXJfaGVpZ2h0X2FuZF95X2F0dHIoeV90b3ApO1xuXG5cdFx0XHRcdHggPSBzdGFydCArICh3aWR0aCAqIGluZGV4KTtcblxuXHRcdFx0XHRyZXR1cm4gW2Jhcl9vYmosIHt3aWR0aDogd2lkdGgsIGhlaWdodDogaGVpZ2h0LCB4OiB4LCB5OiB5fSwgMjUwLCBcImVhc2VpblwiXTtcblx0XHRcdFx0Ly8gYmFyLmFuaW1hdGUoe2hlaWdodDogYXJncy5uZXdfaGVpZ2h0LCB5OiB5X3RvcH0sIDI1MCwgbWluYS5lYXNlaW4pO1xuXHRcdFx0fSxcblx0XHRcdCdkb3QnOiAoZG90X29iaiwgeCwgeV90b3ApID0+IHtcblx0XHRcdFx0cmV0dXJuIFtkb3Rfb2JqLCB7Y3g6IHgsIGN5OiB5X3RvcH0sIDMwMCwgXCJlYXNlaW5cIl07XG5cdFx0XHRcdC8vIGRvdC5hbmltYXRlKHtjeTogeV90b3B9LCAyNTAsIG1pbmEuZWFzZWluKTtcblx0XHRcdH1cblx0XHR9O1xuXHR9XG59XG5cbmZyYXBwZS5jaGFydC5CYXJDaGFydCA9IGNsYXNzIEJhckNoYXJ0IGV4dGVuZHMgZnJhcHBlLmNoYXJ0LkF4aXNDaGFydCB7XG5cdGNvbnN0cnVjdG9yKGFyZ3MpIHtcblx0XHRzdXBlcihhcmdzKTtcblxuXHRcdHRoaXMudHlwZSA9ICdiYXInO1xuXHRcdHRoaXMueF9heGlzX21vZGUgPSBhcmdzLnhfYXhpc19tb2RlIHx8ICd0aWNrJztcblx0XHR0aGlzLnlfYXhpc19tb2RlID0gYXJncy55X2F4aXNfbW9kZSB8fCAnc3Bhbic7XG5cdFx0dGhpcy5zZXR1cCgpO1xuXHR9XG5cblx0c2V0dXBfdmFsdWVzKCkge1xuXHRcdHN1cGVyLnNldHVwX3ZhbHVlcygpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSB0aGlzLmF2Z191bml0X3dpZHRoO1xuXHRcdHRoaXMudW5pdF9hcmdzID0ge1xuXHRcdFx0dHlwZTogJ2JhcicsXG5cdFx0XHRhcmdzOiB7XG5cdFx0XHRcdHNwYWNlX3dpZHRoOiB0aGlzLmF2Z191bml0X3dpZHRoLzIsXG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cdG1ha2Vfb3ZlcmxheSgpIHtcblx0XHQvLyBKdXN0IG1ha2Ugb25lIG91dCBvZiB0aGUgZmlyc3QgZWxlbWVudFxuXHRcdGxldCBpbmRleCA9IHRoaXMueC5sZW5ndGggLSAxO1xuXHRcdGxldCB1bml0ID0gdGhpcy55WzBdLnN2Z191bml0c1tpbmRleF07XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KGluZGV4KTtcblxuXHRcdGlmKHRoaXMub3ZlcmxheSkge1xuXHRcdFx0dGhpcy5vdmVybGF5LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5vdmVybGF5KTtcblx0XHR9XG5cblx0XHR0aGlzLm92ZXJsYXkgPSB1bml0LmNsb25lTm9kZSgpO1xuXHRcdHRoaXMub3ZlcmxheS5zdHlsZS5maWxsID0gJyMwMDAwMDAnO1xuXHRcdHRoaXMub3ZlcmxheS5zdHlsZS5vcGFjaXR5ID0gJzAuNCc7XG5cdFx0dGhpcy5kcmF3X2FyZWEuYXBwZW5kQ2hpbGQodGhpcy5vdmVybGF5KTtcblx0fVxuXG5cdGJpbmRfb3ZlcmxheSgpIHtcblx0XHQvLyBvbiBldmVudCwgdXBkYXRlIG92ZXJsYXlcblx0XHR0aGlzLnBhcmVudC5hZGRFdmVudExpc3RlbmVyKCdkYXRhLXNlbGVjdCcsIChlKSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZV9vdmVybGF5KGUuc3ZnX3VuaXQpO1xuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlX292ZXJsYXkodW5pdCkge1xuXHRcdGxldCBhdHRyaWJ1dGVzID0gW107XG5cdFx0T2JqZWN0LmtleXModW5pdC5hdHRyaWJ1dGVzKS5tYXAoaW5kZXggPT4ge1xuXHRcdFx0YXR0cmlidXRlcy5wdXNoKHVuaXQuYXR0cmlidXRlc1tpbmRleF0pO1xuXHRcdH0pO1xuXG5cdFx0YXR0cmlidXRlcy5maWx0ZXIoYXR0ciA9PiBhdHRyLnNwZWNpZmllZCkubWFwKGF0dHIgPT4ge1xuXHRcdFx0dGhpcy5vdmVybGF5LnNldEF0dHJpYnV0ZShhdHRyLm5hbWUsIGF0dHIubm9kZVZhbHVlKTtcblx0XHR9KTtcblx0fVxuXG5cdG9uX2xlZnRfYXJyb3coKSB7XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KHRoaXMuY3VycmVudF9pbmRleCAtIDEpO1xuXHR9XG5cblx0b25fcmlnaHRfYXJyb3coKSB7XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KHRoaXMuY3VycmVudF9pbmRleCArIDEpO1xuXHR9XG5cblx0c2V0X2F2Z191bml0X3dpZHRoX2FuZF94X29mZnNldCgpIHtcblx0XHR0aGlzLmF2Z191bml0X3dpZHRoID0gdGhpcy53aWR0aC8odGhpcy54Lmxlbmd0aCArIDEpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSB0aGlzLmF2Z191bml0X3dpZHRoO1xuXHR9XG59XG5cbmZyYXBwZS5jaGFydC5MaW5lQ2hhcnQgPSBjbGFzcyBMaW5lQ2hhcnQgZXh0ZW5kcyBmcmFwcGUuY2hhcnQuQXhpc0NoYXJ0IHtcblx0Y29uc3RydWN0b3IoYXJncykge1xuXHRcdHN1cGVyKGFyZ3MpO1xuXHRcdGlmKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSAhPT0gZnJhcHBlLmNoYXJ0LkxpbmVDaGFydC5wcm90b3R5cGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLnR5cGUgPSAnbGluZSc7XG5cdFx0dGhpcy5yZWdpb25fZmlsbCA9IGFyZ3MucmVnaW9uX2ZpbGw7XG5cdFx0dGhpcy54X2F4aXNfbW9kZSA9IGFyZ3MueF9heGlzX21vZGUgfHwgJ3NwYW4nO1xuXHRcdHRoaXMueV9heGlzX21vZGUgPSBhcmdzLnlfYXhpc19tb2RlIHx8ICdzcGFuJztcblxuXHRcdHRoaXMuc2V0dXAoKTtcblx0fVxuXG5cdHNldHVwX2dyYXBoX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5zZXR1cF9wYXRoX2dyb3VwcygpO1xuXHRcdHN1cGVyLnNldHVwX2dyYXBoX2NvbXBvbmVudHMoKTtcblx0fVxuXG5cdHNldHVwX3BhdGhfZ3JvdXBzKCkge1xuXHRcdHRoaXMucGF0aHNfZ3JvdXBzID0gW107XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0dGhpcy5wYXRoc19ncm91cHNbaV0gPSAkJC5jcmVhdGVTVkcoJ2cnLCB7XG5cdFx0XHRcdGNsYXNzTmFtZTogJ3BhdGgtZ3JvdXAgcGF0aC1ncm91cC0nICsgaSxcblx0XHRcdFx0aW5zaWRlOiB0aGlzLmRyYXdfYXJlYVxuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cblxuXHRzZXR1cF92YWx1ZXMoKSB7XG5cdFx0c3VwZXIuc2V0dXBfdmFsdWVzKCk7XG5cdFx0dGhpcy51bml0X2FyZ3MgPSB7XG5cdFx0XHR0eXBlOiAnZG90Jyxcblx0XHRcdGFyZ3M6IHsgcmFkaXVzOiA4IH1cblx0XHR9O1xuXHR9XG5cblx0bWFrZV9wYXRocygpIHtcblx0XHR0aGlzLnkubWFwKChkLCBpKSA9PiB7XG5cdFx0XHR0aGlzLm1ha2VfcGF0aChkLCBpLCB0aGlzLnhfYXhpc19wb3NpdGlvbnMsIGQueV90b3BzLCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfcGF0aChkLCBpLCB4X3Bvc2l0aW9ucywgeV9wb3NpdGlvbnMsIGNvbG9yKSB7XG5cdFx0Ly8gbGV0IHBvaW50c19saXN0ID0geV9wb3NpdGlvbnMubWFwKCh5LCBpKSA9PiAoeF9wb3NpdGlvbnNbaV0gKyAnLCcgKyB5KSk7XG5cdFx0Ly8gbGV0IHBvaW50c19zdHIgPSBwb2ludHNfbGlzdC5qb2luKFwiTFwiKTtcblxuXHRcdC8vIHRoaXMucGF0aHNfZ3JvdXBzW2ldLnRleHRDb250ZW50ID0gJyc7XG5cblx0XHQvLyBkLnBhdGggPSAkJC5jcmVhdGVTVkcoJ3BhdGgnLCB7XG5cdFx0Ly8gXHRpbnNpZGU6IHRoaXMucGF0aHNfZ3JvdXBzW2ldLFxuXHRcdC8vIFx0Y2xhc3NOYW1lOiBgc3Ryb2tlICR7Y29sb3J9YCxcblx0XHQvLyBcdGQ6IFwiTVwiK3BvaW50c19zdHJcblx0XHQvLyB9KTtcblxuXHRcdC8vIGlmKHRoaXMucmVnaW9uX2ZpbGwpIHtcblx0XHQvLyBcdGxldCBncmFkaWVudF9pZCA9J3BhdGgtZmlsbC1ncmFkaWVudCcgKyAnLScgKyBjb2xvcjtcblxuXHRcdC8vIFx0dGhpcy5ncmFkaWVudF9kZWYgPSAkJC5jcmVhdGVTVkcoJ2xpbmVhckdyYWRpZW50Jywge1xuXHRcdC8vIFx0XHRpbnNpZGU6IHRoaXMuc3ZnX2RlZnMsXG5cdFx0Ly8gXHRcdGlkOiBncmFkaWVudF9pZCxcblx0XHQvLyBcdFx0eDE6IDAsXG5cdFx0Ly8gXHRcdHgyOiAwLFxuXHRcdC8vIFx0XHR5MTogMCxcblx0XHQvLyBcdFx0eTI6IDFcblx0XHQvLyBcdH0pO1xuXG5cdFx0Ly8gXHRmdW5jdGlvbiBzZXRfZ3JhZGllbnRfc3RvcChncmFkX2VsZW0sIG9mZnNldCwgY29sb3IsIG9wYWNpdHkpIHtcblx0XHQvLyBcdFx0JCQuY3JlYXRlU1ZHKCdzdG9wJywge1xuXHRcdC8vIFx0XHRcdCdjbGFzc05hbWUnOiAnc3RvcC1jb2xvciAnICsgY29sb3IsXG5cdFx0Ly8gXHRcdFx0J2luc2lkZSc6IGdyYWRfZWxlbSxcblx0XHQvLyBcdFx0XHQnb2Zmc2V0Jzogb2Zmc2V0LFxuXHRcdC8vIFx0XHRcdCdzdG9wLW9wYWNpdHknOiBvcGFjaXR5XG5cdFx0Ly8gXHRcdH0pO1xuXHRcdC8vIFx0fVxuXG5cdFx0Ly8gXHRzZXRfZ3JhZGllbnRfc3RvcCh0aGlzLmdyYWRpZW50X2RlZiwgXCIwJVwiLCBjb2xvciwgMC40KTtcblx0XHQvLyBcdHNldF9ncmFkaWVudF9zdG9wKHRoaXMuZ3JhZGllbnRfZGVmLCBcIjUwJVwiLCBjb2xvciwgMC4yKTtcblx0XHQvLyBcdHNldF9ncmFkaWVudF9zdG9wKHRoaXMuZ3JhZGllbnRfZGVmLCBcIjEwMCVcIiwgY29sb3IsIDApO1xuXG5cdFx0Ly8gXHRkLnJlZ2lvbl9wYXRoID0gJCQuY3JlYXRlU1ZHKCdwYXRoJywge1xuXHRcdC8vIFx0XHRpbnNpZGU6IHRoaXMucGF0aHNfZ3JvdXBzW2ldLFxuXHRcdC8vIFx0XHRjbGFzc05hbWU6IGByZWdpb24tZmlsbGAsXG5cdFx0Ly8gXHRcdGQ6IFwiTVwiICsgYDAsJHt0aGlzLnplcm9fbGluZX1MYCArIHBvaW50c19zdHIgKyBgTCR7dGhpcy53aWR0aH0sJHt0aGlzLnplcm9fbGluZX1gLFxuXHRcdC8vIFx0fSk7XG5cblx0XHQvLyBcdGQucmVnaW9uX3BhdGguc3R5bGUuc3Ryb2tlID0gXCJub25lXCI7XG5cdFx0Ly8gXHRkLnJlZ2lvbl9wYXRoLnN0eWxlLmZpbGwgPSBgdXJsKCMke2dyYWRpZW50X2lkfSlgO1xuXHRcdC8vIH1cblx0fVxufVxuXG5mcmFwcGUuY2hhcnQuUGVyY2VudGFnZUNoYXJ0ID0gY2xhc3MgUGVyY2VudGFnZUNoYXJ0IGV4dGVuZHMgZnJhcHBlLmNoYXJ0LkZyYXBwZUNoYXJ0IHtcblx0Y29uc3RydWN0b3IoYXJncykge1xuXHRcdHN1cGVyKGFyZ3MpO1xuXHRcdHRoaXMudHlwZSA9ICdwZXJjZW50YWdlJztcblxuXHRcdHRoaXMuZ2V0X3lfbGFiZWwgPSB0aGlzLmZvcm1hdF9sYW1iZGFzLnlfbGFiZWw7XG5cdFx0dGhpcy5nZXRfeF90b29sdGlwID0gdGhpcy5mb3JtYXRfbGFtYmRhcy54X3Rvb2x0aXA7XG5cdFx0dGhpcy5nZXRfeV90b29sdGlwID0gdGhpcy5mb3JtYXRfbGFtYmRhcy55X3Rvb2x0aXA7XG5cblx0XHR0aGlzLm1heF9zbGljZXMgPSAxMDtcblx0XHR0aGlzLm1heF9sZWdlbmRfcG9pbnRzID0gNjtcblxuXHRcdHRoaXMuY29sb3JzID0gYXJncy5jb2xvcnM7XG5cblx0XHRpZighdGhpcy5jb2xvcnMgfHwgdGhpcy5jb2xvcnMubGVuZ3RoIDwgdGhpcy5kYXRhLmxhYmVscy5sZW5ndGgpIHtcblx0XHRcdHRoaXMuY29sb3JzID0gWydsaWdodC1ibHVlJywgJ2JsdWUnLCAndmlvbGV0JywgJ3JlZCcsICdvcmFuZ2UnLFxuXHRcdFx0XHQneWVsbG93JywgJ2dyZWVuJywgJ2xpZ2h0LWdyZWVuJywgJ3B1cnBsZScsICdtYWdlbnRhJ107XG5cdFx0fVxuXG5cdFx0dGhpcy5zZXR1cCgpO1xuXHR9XG5cblx0bWFrZV9jaGFydF9hcmVhKCkge1xuXHRcdHRoaXMuY2hhcnRfd3JhcHBlci5jbGFzc05hbWUgKz0gJyAnICsgJ2dyYXBoLWZvY3VzLW1hcmdpbic7XG5cdFx0dGhpcy5jaGFydF93cmFwcGVyLnN0eWxlLm1hcmdpblRvcCA9ICc0NXB4JztcblxuXHRcdHRoaXMuc3RhdHNfd3JhcHBlci5jbGFzc05hbWUgKz0gJyAnICsgJ2dyYXBoLWZvY3VzLW1hcmdpbic7XG5cdFx0dGhpcy5zdGF0c193cmFwcGVyLnN0eWxlLm1hcmdpbkJvdHRvbSA9ICczMHB4Jztcblx0XHR0aGlzLnN0YXRzX3dyYXBwZXIuc3R5bGUucGFkZGluZ1RvcCA9ICcwcHgnO1xuXHR9XG5cblx0bWFrZV9kcmF3X2FyZWEoKSB7XG5cdFx0dGhpcy5jaGFydF9kaXYgPSAkJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdGNsYXNzTmFtZTogJ2RpdicsXG5cdFx0XHRpbnNpZGU6IHRoaXMuY2hhcnRfd3JhcHBlcixcblx0XHRcdHdpZHRoOiB0aGlzLmJhc2Vfd2lkdGgsXG5cdFx0XHRoZWlnaHQ6IHRoaXMuYmFzZV9oZWlnaHRcblx0XHR9KTtcblxuXHRcdHRoaXMuY2hhcnQgPSAkJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdGNsYXNzTmFtZTogJ3Byb2dyZXNzLWNoYXJ0Jyxcblx0XHRcdGluc2lkZTogdGhpcy5jaGFydF9kaXZcblx0XHR9KTtcblx0fVxuXG5cdHNldHVwX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5wZXJjZW50YWdlX2JhciA9ICQkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0Y2xhc3NOYW1lOiAncHJvZ3Jlc3MnLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmNoYXJ0XG5cdFx0fSk7XG5cdH1cblxuXHRzZXR1cF92YWx1ZXMoKSB7XG5cdFx0dGhpcy5zbGljZV90b3RhbHMgPSBbXTtcblx0XHRsZXQgYWxsX3RvdGFscyA9IHRoaXMuZGF0YS5sYWJlbHMubWFwKChkLCBpKSA9PiB7XG5cdFx0XHRsZXQgdG90YWwgPSAwO1xuXHRcdFx0dGhpcy5kYXRhLmRhdGFzZXRzLm1hcChlID0+IHtcblx0XHRcdFx0dG90YWwgKz0gZS52YWx1ZXNbaV07XG5cdFx0XHR9KTtcblx0XHRcdHJldHVybiBbdG90YWwsIGRdO1xuXHRcdH0pLmZpbHRlcihkID0+IHsgcmV0dXJuIGRbMF0gPiAwOyB9KTsgLy8ga2VlcCBvbmx5IHBvc2l0aXZlIHJlc3VsdHNcblxuXHRcdGxldCB0b3RhbHMgPSBhbGxfdG90YWxzO1xuXG5cdFx0aWYoYWxsX3RvdGFscy5sZW5ndGggPiB0aGlzLm1heF9zbGljZXMpIHtcblx0XHRcdGFsbF90b3RhbHMuc29ydCgoYSwgYikgPT4geyByZXR1cm4gYlswXSAtIGFbMF07IH0pO1xuXG5cdFx0XHR0b3RhbHMgPSBhbGxfdG90YWxzLnNsaWNlKDAsIHRoaXMubWF4X3NsaWNlcy0xKTtcblx0XHRcdGxldCBvdGhlcnMgPSBhbGxfdG90YWxzLnNsaWNlKHRoaXMubWF4X3NsaWNlcy0xKTtcblxuXHRcdFx0bGV0IHN1bV9vZl9vdGhlcnMgPSAwO1xuXHRcdFx0b3RoZXJzLm1hcChkID0+IHtzdW1fb2Zfb3RoZXJzICs9IGRbMF19KTtcblxuXHRcdFx0dG90YWxzLnB1c2goW3N1bV9vZl9vdGhlcnMsICdSZXN0J10pO1xuXG5cdFx0XHR0aGlzLmNvbG9yc1t0aGlzLm1heF9zbGljZXMtMV0gPSAnZ3JleSc7XG5cdFx0fVxuXG5cdFx0dGhpcy5sYWJlbHMgPSBbXTtcblx0XHR0b3RhbHMubWFwKGQgPT4ge1xuXHRcdFx0dGhpcy5zbGljZV90b3RhbHMucHVzaChkWzBdKTtcblx0XHRcdHRoaXMubGFiZWxzLnB1c2goZFsxXSk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLmxlZ2VuZF90b3RhbHMgPSB0aGlzLnNsaWNlX3RvdGFscy5zbGljZSgwLCB0aGlzLm1heF9sZWdlbmRfcG9pbnRzKTtcblx0fVxuXG5cdHNldHVwX3V0aWxzKCkgeyB9XG5cblx0bWFrZV9ncmFwaF9jb21wb25lbnRzKCkge1xuXHRcdHRoaXMuZ3JhbmRfdG90YWwgPSB0aGlzLnNsaWNlX3RvdGFscy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcblx0XHR0aGlzLnNsaWNlcyA9IFtdO1xuXHRcdHRoaXMuc2xpY2VfdG90YWxzLm1hcCgodG90YWwsIGkpID0+IHtcblx0XHRcdGxldCBzbGljZSA9ICQkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0XHRjbGFzc05hbWU6IGBwcm9ncmVzcy1iYXIgYmFja2dyb3VuZCAke3RoaXMuY29sb3JzW2ldfWAsXG5cdFx0XHRcdHN0eWxlOiBgd2lkdGg6ICR7dG90YWwqMTAwL3RoaXMuZ3JhbmRfdG90YWx9JWAsXG5cdFx0XHRcdGluc2lkZTogdGhpcy5wZXJjZW50YWdlX2JhclxuXHRcdFx0fSk7XG5cdFx0XHR0aGlzLnNsaWNlcy5wdXNoKHNsaWNlKTtcblx0XHR9KTtcblx0fVxuXG5cdGJpbmRfdG9vbHRpcCgpIHtcblx0XHR0aGlzLnNsaWNlcy5tYXAoKHNsaWNlLCBpKSA9PiB7XG5cdFx0XHRzbGljZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgKCkgPT4ge1xuXHRcdFx0XHRsZXQgZ19vZmYgPSAkJC5vZmZzZXQodGhpcy5jaGFydF93cmFwcGVyKSwgcF9vZmYgPSAkJC5vZmZzZXQoc2xpY2UpO1xuXG5cdFx0XHRcdGxldCB4ID0gcF9vZmYubGVmdCAtIGdfb2ZmLmxlZnQgKyBzbGljZS5vZmZzZXRXaWR0aC8yO1xuXHRcdFx0XHRsZXQgeSA9IHBfb2ZmLnRvcCAtIGdfb2ZmLnRvcCAtIDY7XG5cdFx0XHRcdGxldCB0aXRsZSA9ICh0aGlzLmZvcm1hdHRlZF9sYWJlbHMgJiYgdGhpcy5mb3JtYXR0ZWRfbGFiZWxzLmxlbmd0aD4wXG5cdFx0XHRcdFx0PyB0aGlzLmZvcm1hdHRlZF9sYWJlbHNbaV0gOiB0aGlzLmxhYmVsc1tpXSkgKyAnOiAnO1xuXHRcdFx0XHRsZXQgcGVyY2VudCA9ICh0aGlzLnNsaWNlX3RvdGFsc1tpXSoxMDAvdGhpcy5ncmFuZF90b3RhbCkudG9GaXhlZCgxKTtcblxuXHRcdFx0XHR0aGlzLnRpcC5zZXRfdmFsdWVzKHgsIHksIHRpdGxlLCBwZXJjZW50ICsgXCIlXCIpO1xuXHRcdFx0XHR0aGlzLnRpcC5zaG93X3RpcCgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdH1cblxuXHRzaG93X3N1bW1hcnkoKSB7XG5cdFx0bGV0IHhfdmFsdWVzID0gdGhpcy5mb3JtYXR0ZWRfbGFiZWxzICYmIHRoaXMuZm9ybWF0dGVkX2xhYmVscy5sZW5ndGggPiAwXG5cdFx0XHQ/IHRoaXMuZm9ybWF0dGVkX2xhYmVscyA6IHRoaXMubGFiZWxzO1xuXHRcdHRoaXMubGVnZW5kX3RvdGFscy5tYXAoKGQsIGkpID0+IHtcblx0XHRcdGlmKGQpIHtcblx0XHRcdFx0bGV0IHN0YXRzID0gJCQuY3JlYXRlKCdkaXYnLCB7XG5cdFx0XHRcdFx0Y2xhc3NOYW1lOiAnc3RhdHMnLFxuXHRcdFx0XHRcdGluc2lkZTogdGhpcy5zdGF0c193cmFwcGVyXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzdGF0cy5pbm5lckhUTUwgPSBgPHNwYW4gY2xhc3M9XCJpbmRpY2F0b3IgJHt0aGlzLmNvbG9yc1tpXX1cIj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWRcIj4ke3hfdmFsdWVzW2ldfTo8L3NwYW4+XG5cdFx0XHRcdFx0JHtkfVxuXHRcdFx0XHQ8L3NwYW4+YDtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuXG5mcmFwcGUuY2hhcnQuSGVhdE1hcCA9IGNsYXNzIEhlYXRNYXAgZXh0ZW5kcyBmcmFwcGUuY2hhcnQuRnJhcHBlQ2hhcnQge1xuXHRjb25zdHJ1Y3Rvcih7XG5cdFx0c3RhcnQgPSAnJyxcblx0XHRkb21haW4gPSAnJyxcblx0XHRzdWJkb21haW4gPSAnJyxcblx0XHRkYXRhID0ge30sXG5cdFx0ZGlzY3JldGVfZG9tYWlucyA9IDAsXG5cdFx0Y291bnRfbGFiZWwgPSAnJ1xuXHR9KSB7XG5cdFx0c3VwZXIoYXJndW1lbnRzWzBdKTtcblxuXHRcdHRoaXMudHlwZSA9ICdoZWF0bWFwJztcblxuXHRcdHRoaXMuZG9tYWluID0gZG9tYWluO1xuXHRcdHRoaXMuc3ViZG9tYWluID0gc3ViZG9tYWluO1xuXHRcdHRoaXMuZGF0YSA9IGRhdGE7XG5cdFx0dGhpcy5kaXNjcmV0ZV9kb21haW5zID0gZGlzY3JldGVfZG9tYWlucztcblx0XHR0aGlzLmNvdW50X2xhYmVsID0gY291bnRfbGFiZWw7XG5cblx0XHRsZXQgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuXHRcdHRoaXMuc3RhcnQgPSBzdGFydCB8fCB0aGlzLmFkZF9kYXlzKHRvZGF5LCAzNjUpO1xuXG5cdFx0dGhpcy5sZWdlbmRfY29sb3JzID0gWycjZWJlZGYwJywgJyNjNmU0OGInLCAnIzdiYzk2ZicsICcjMjM5YTNiJywgJyMxOTYxMjcnXTtcblxuXHRcdHRoaXMudHJhbnNsYXRlX3ggPSAwO1xuXHRcdHRoaXMuc2V0dXAoKTtcblx0fVxuXG5cdHNldHVwX2Jhc2VfdmFsdWVzKCkge1xuXHRcdHRoaXMudG9kYXkgPSBuZXcgRGF0ZSgpO1xuXG5cdFx0aWYoIXRoaXMuc3RhcnQpIHtcblx0XHRcdHRoaXMuc3RhcnQgPSBuZXcgRGF0ZSgpO1xuXHRcdFx0dGhpcy5zdGFydC5zZXRGdWxsWWVhciggdGhpcy5zdGFydC5nZXRGdWxsWWVhcigpIC0gMSApO1xuXHRcdH1cblx0XHR0aGlzLmZpcnN0X3dlZWtfc3RhcnQgPSBuZXcgRGF0ZSh0aGlzLnN0YXJ0LnRvRGF0ZVN0cmluZygpKTtcblx0XHR0aGlzLmxhc3Rfd2Vla19zdGFydCA9IG5ldyBEYXRlKHRoaXMudG9kYXkudG9EYXRlU3RyaW5nKCkpO1xuXHRcdGlmKHRoaXMuZmlyc3Rfd2Vla19zdGFydC5nZXREYXkoKSAhPT0gNykge1xuXHRcdFx0dGhpcy5hZGRfZGF5cyh0aGlzLmZpcnN0X3dlZWtfc3RhcnQsICgtMSkgKiB0aGlzLmZpcnN0X3dlZWtfc3RhcnQuZ2V0RGF5KCkpO1xuXHRcdH1cblx0XHRpZih0aGlzLmxhc3Rfd2Vla19zdGFydC5nZXREYXkoKSAhPT0gNykge1xuXHRcdFx0dGhpcy5hZGRfZGF5cyh0aGlzLmxhc3Rfd2Vla19zdGFydCwgKC0xKSAqIHRoaXMubGFzdF93ZWVrX3N0YXJ0LmdldERheSgpKTtcblx0XHR9XG5cdFx0dGhpcy5ub19vZl9jb2xzID0gdGhpcy5nZXRfd2Vla3NfYmV0d2Vlbih0aGlzLmZpcnN0X3dlZWtfc3RhcnQgKyAnJywgdGhpcy5sYXN0X3dlZWtfc3RhcnQgKyAnJykgKyAxO1xuXHR9XG5cblx0c2V0X3dpZHRoKCkge1xuXHRcdHRoaXMuYmFzZV93aWR0aCA9ICh0aGlzLm5vX29mX2NvbHMpICogMTI7XG5cblx0XHRpZih0aGlzLmRpc2NyZXRlX2RvbWFpbnMpIHtcblx0XHRcdHRoaXMuYmFzZV93aWR0aCArPSAoMTIgKiAxMik7XG5cdFx0fVxuXHR9XG5cblx0c2V0dXBfY29tcG9uZW50cygpIHtcblx0XHR0aGlzLmRvbWFpbl9sYWJlbF9ncm91cCA9ICQkLmNyZWF0ZVNWRyhcImdcIiwge1xuXHRcdFx0Y2xhc3NOYW1lOiBcImRvbWFpbi1sYWJlbC1ncm91cCBjaGFydC1sYWJlbFwiLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmRyYXdfYXJlYVxuXHRcdH0pO1xuXHRcdHRoaXMuZGF0YV9ncm91cHMgPSAkJC5jcmVhdGVTVkcoXCJnXCIsIHtcblx0XHRcdGNsYXNzTmFtZTogXCJkYXRhLWdyb3Vwc1wiLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmRyYXdfYXJlYSxcblx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgwLCAyMClgXG5cdFx0fSk7XG5cdH1cblxuXHRzZXR1cF92YWx1ZXMoKSB7XG5cdFx0dGhpcy5kb21haW5fbGFiZWxfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLmRhdGFfZ3JvdXBzLnRleHRDb250ZW50ID0gJyc7XG5cdFx0dGhpcy5kaXN0cmlidXRpb24gPSB0aGlzLmdldF9kaXN0cmlidXRpb24odGhpcy5kYXRhLCB0aGlzLmxlZ2VuZF9jb2xvcnMpO1xuXHRcdHRoaXMubW9udGhfbmFtZXMgPSBbXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLFxuXHRcdFx0XCJKdWx5XCIsIFwiQXVndXN0XCIsIFwiU2VwdGVtYmVyXCIsIFwiT2N0b2JlclwiLCBcIk5vdmVtYmVyXCIsIFwiRGVjZW1iZXJcIlxuXHRcdF07XG5cblx0XHR0aGlzLnJlbmRlcl9hbGxfd2Vla3NfYW5kX3N0b3JlX3hfdmFsdWVzKHRoaXMubm9fb2ZfY29scyk7XG5cdH1cblxuXHRyZW5kZXJfYWxsX3dlZWtzX2FuZF9zdG9yZV94X3ZhbHVlcyhub19vZl93ZWVrcykge1xuXHRcdGxldCBjdXJyZW50X3dlZWtfc3VuZGF5ID0gbmV3IERhdGUodGhpcy5maXJzdF93ZWVrX3N0YXJ0KTtcblx0XHR0aGlzLndlZWtfY29sID0gMDtcblx0XHR0aGlzLmN1cnJlbnRfbW9udGggPSBjdXJyZW50X3dlZWtfc3VuZGF5LmdldE1vbnRoKCk7XG5cblx0XHR0aGlzLm1vbnRocyA9IFt0aGlzLmN1cnJlbnRfbW9udGggKyAnJ107XG5cdFx0dGhpcy5tb250aF93ZWVrcyA9IHt9LCB0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cyA9IFtdO1xuXHRcdHRoaXMubW9udGhfd2Vla3NbdGhpcy5jdXJyZW50X21vbnRoXSA9IDA7XG5cdFx0dGhpcy5tb250aF9zdGFydF9wb2ludHMucHVzaCgxMyk7XG5cblx0XHRmb3IodmFyIGkgPSAwOyBpIDwgbm9fb2Zfd2Vla3M7IGkrKykge1xuXHRcdFx0bGV0IGRhdGFfZ3JvdXAsIG1vbnRoX2NoYW5nZSA9IDA7XG5cdFx0XHRsZXQgZGF5ID0gbmV3IERhdGUoY3VycmVudF93ZWVrX3N1bmRheSk7XG5cblx0XHRcdFtkYXRhX2dyb3VwLCBtb250aF9jaGFuZ2VdID0gdGhpcy5nZXRfd2Vla19zcXVhcmVzX2dyb3VwKGRheSwgdGhpcy53ZWVrX2NvbCk7XG5cdFx0XHR0aGlzLmRhdGFfZ3JvdXBzLmFwcGVuZENoaWxkKGRhdGFfZ3JvdXApO1xuXHRcdFx0dGhpcy53ZWVrX2NvbCArPSAxICsgcGFyc2VJbnQodGhpcy5kaXNjcmV0ZV9kb21haW5zICYmIG1vbnRoX2NoYW5nZSk7XG5cdFx0XHR0aGlzLm1vbnRoX3dlZWtzW3RoaXMuY3VycmVudF9tb250aF0rKztcblx0XHRcdGlmKG1vbnRoX2NoYW5nZSkge1xuXHRcdFx0XHR0aGlzLmN1cnJlbnRfbW9udGggPSAodGhpcy5jdXJyZW50X21vbnRoICsgMSkgJSAxMjtcblx0XHRcdFx0dGhpcy5tb250aHMucHVzaCh0aGlzLmN1cnJlbnRfbW9udGggKyAnJyk7XG5cdFx0XHRcdHRoaXMubW9udGhfd2Vla3NbdGhpcy5jdXJyZW50X21vbnRoXSA9IDE7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmFkZF9kYXlzKGN1cnJlbnRfd2Vla19zdW5kYXksIDcpO1xuXHRcdH1cblx0XHR0aGlzLnJlbmRlcl9tb250aF9sYWJlbHMoKTtcblx0fVxuXG5cdGdldF93ZWVrX3NxdWFyZXNfZ3JvdXAoY3VycmVudF9kYXRlLCBpbmRleCkge1xuXHRcdGNvbnN0IG5vX29mX3dlZWtkYXlzID0gNztcblx0XHRjb25zdCBzcXVhcmVfc2lkZSA9IDEwO1xuXHRcdGNvbnN0IGNlbGxfcGFkZGluZyA9IDI7XG5cdFx0Y29uc3Qgc3RlcCA9IDE7XG5cblx0XHRsZXQgbW9udGhfY2hhbmdlID0gMDtcblx0XHRsZXQgd2Vla19jb2xfY2hhbmdlID0gMDtcblxuXHRcdGxldCBkYXRhX2dyb3VwID0gJCQuY3JlYXRlU1ZHKFwiZ1wiLCB7XG5cdFx0XHRjbGFzc05hbWU6IFwiZGF0YS1ncm91cFwiLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmRhdGFfZ3JvdXBzXG5cdFx0fSk7XG5cblx0XHRmb3IodmFyIHkgPSAwLCBpID0gMDsgaSA8IG5vX29mX3dlZWtkYXlzOyBpICs9IHN0ZXAsIHkgKz0gKHNxdWFyZV9zaWRlICsgY2VsbF9wYWRkaW5nKSkge1xuXHRcdFx0bGV0IGRhdGFfdmFsdWUgPSAwO1xuXHRcdFx0bGV0IGNvbG9yX2luZGV4ID0gMDtcblxuXHRcdFx0bGV0IHRpbWVzdGFtcCA9IE1hdGguZmxvb3IoY3VycmVudF9kYXRlLmdldFRpbWUoKS8xMDAwKS50b0ZpeGVkKDEpO1xuXG5cdFx0XHRpZih0aGlzLmRhdGFbdGltZXN0YW1wXSkge1xuXHRcdFx0XHRkYXRhX3ZhbHVlID0gdGhpcy5kYXRhW3RpbWVzdGFtcF07XG5cdFx0XHRcdGNvbG9yX2luZGV4ID0gdGhpcy5nZXRfbWF4X2NoZWNrcG9pbnQoZGF0YV92YWx1ZSwgdGhpcy5kaXN0cmlidXRpb24pO1xuXHRcdFx0fVxuXG5cdFx0XHRpZih0aGlzLmRhdGFbTWF0aC5yb3VuZCh0aW1lc3RhbXApXSkge1xuXHRcdFx0XHRkYXRhX3ZhbHVlID0gdGhpcy5kYXRhW01hdGgucm91bmQodGltZXN0YW1wKV07XG5cdFx0XHRcdGNvbG9yX2luZGV4ID0gdGhpcy5nZXRfbWF4X2NoZWNrcG9pbnQoZGF0YV92YWx1ZSwgdGhpcy5kaXN0cmlidXRpb24pO1xuXHRcdFx0fVxuXG5cdFx0XHRsZXQgeCA9IDEzICsgKGluZGV4ICsgd2Vla19jb2xfY2hhbmdlKSAqIDEyO1xuXG5cdFx0XHQkJC5jcmVhdGVTVkcoXCJyZWN0XCIsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAnZGF5Jyxcblx0XHRcdFx0aW5zaWRlOiBkYXRhX2dyb3VwLFxuXHRcdFx0XHR4OiB4LFxuXHRcdFx0XHR5OiB5LFxuXHRcdFx0XHR3aWR0aDogc3F1YXJlX3NpZGUsXG5cdFx0XHRcdGhlaWdodDogc3F1YXJlX3NpZGUsXG5cdFx0XHRcdGZpbGw6ICB0aGlzLmxlZ2VuZF9jb2xvcnNbY29sb3JfaW5kZXhdLFxuXHRcdFx0XHQnZGF0YS1kYXRlJzogdGhpcy5nZXRfZGRfbW1feXl5eShjdXJyZW50X2RhdGUpLFxuXHRcdFx0XHQnZGF0YS12YWx1ZSc6IGRhdGFfdmFsdWUsXG5cdFx0XHRcdCdkYXRhLWRheSc6IGN1cnJlbnRfZGF0ZS5nZXREYXkoKVxuXHRcdFx0fSk7XG5cblx0XHRcdGxldCBuZXh0X2RhdGUgPSBuZXcgRGF0ZShjdXJyZW50X2RhdGUpO1xuXHRcdFx0dGhpcy5hZGRfZGF5cyhuZXh0X2RhdGUsIDEpO1xuXHRcdFx0aWYobmV4dF9kYXRlLmdldE1vbnRoKCkgLSBjdXJyZW50X2RhdGUuZ2V0TW9udGgoKSkge1xuXHRcdFx0XHRtb250aF9jaGFuZ2UgPSAxO1xuXHRcdFx0XHRpZih0aGlzLmRpc2NyZXRlX2RvbWFpbnMpIHtcblx0XHRcdFx0XHR3ZWVrX2NvbF9jaGFuZ2UgPSAxO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5tb250aF9zdGFydF9wb2ludHMucHVzaCgxMyArIChpbmRleCArIHdlZWtfY29sX2NoYW5nZSkgKiAxMik7XG5cdFx0XHR9XG5cdFx0XHRjdXJyZW50X2RhdGUgPSBuZXh0X2RhdGU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtkYXRhX2dyb3VwLCBtb250aF9jaGFuZ2VdO1xuXHR9XG5cblx0cmVuZGVyX21vbnRoX2xhYmVscygpIHtcblx0XHQvLyB0aGlzLmZpcnN0X21vbnRoX2xhYmVsID0gMTtcblx0XHQvLyBpZiAodGhpcy5maXJzdF93ZWVrX3N0YXJ0LmdldERhdGUoKSA+IDgpIHtcblx0XHQvLyBcdHRoaXMuZmlyc3RfbW9udGhfbGFiZWwgPSAwO1xuXHRcdC8vIH1cblx0XHQvLyB0aGlzLmxhc3RfbW9udGhfbGFiZWwgPSAxO1xuXG5cdFx0Ly8gbGV0IGZpcnN0X21vbnRoID0gdGhpcy5tb250aHMuc2hpZnQoKTtcblx0XHQvLyBsZXQgZmlyc3RfbW9udGhfc3RhcnQgPSB0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cy5zaGlmdCgpO1xuXHRcdC8vIHJlbmRlciBmaXJzdCBtb250aCBpZlxuXG5cdFx0Ly8gbGV0IGxhc3RfbW9udGggPSB0aGlzLm1vbnRocy5wb3AoKTtcblx0XHQvLyBsZXQgbGFzdF9tb250aF9zdGFydCA9IHRoaXMubW9udGhfc3RhcnRfcG9pbnRzLnBvcCgpO1xuXHRcdC8vIHJlbmRlciBsYXN0IG1vbnRoIGlmXG5cblx0XHR0aGlzLm1vbnRocy5zaGlmdCgpO1xuXHRcdHRoaXMubW9udGhfc3RhcnRfcG9pbnRzLnNoaWZ0KCk7XG5cdFx0dGhpcy5tb250aHMucG9wKCk7XG5cdFx0dGhpcy5tb250aF9zdGFydF9wb2ludHMucG9wKCk7XG5cblx0XHR0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cy5tYXAoKHN0YXJ0LCBpKSA9PiB7XG5cdFx0XHRsZXQgbW9udGhfbmFtZSA9ICB0aGlzLm1vbnRoX25hbWVzW3RoaXMubW9udGhzW2ldXS5zdWJzdHJpbmcoMCwgMyk7XG5cblx0XHRcdCQkLmNyZWF0ZVNWRygndGV4dCcsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAneS12YWx1ZS10ZXh0Jyxcblx0XHRcdFx0aW5zaWRlOiB0aGlzLmRvbWFpbl9sYWJlbF9ncm91cCxcblx0XHRcdFx0eDogc3RhcnQgKyAxMixcblx0XHRcdFx0eTogMTAsXG5cdFx0XHRcdGR5OiAnLjMyZW0nLFxuXHRcdFx0XHRpbm5lckhUTUw6IG1vbnRoX25hbWVcblx0XHRcdH0pO1xuXG5cdFx0fSk7XG5cdH1cblxuXHRtYWtlX2dyYXBoX2NvbXBvbmVudHMoKSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoXG5cdFx0XHR0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCcuZ3JhcGgtc3RhdHMtY29udGFpbmVyLCAuc3ViLXRpdGxlLCAudGl0bGUnKVxuXHRcdCkubWFwKGQgPT4ge1xuXHRcdFx0ZC5zdHlsZS5kaXNwbGF5ID0gJ05vbmUnO1xuXHRcdH0pO1xuXHRcdHRoaXMuY2hhcnRfd3JhcHBlci5zdHlsZS5tYXJnaW5Ub3AgPSAnMHB4Jztcblx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIuc3R5bGUucGFkZGluZ1RvcCA9ICcwcHgnO1xuXHR9XG5cblx0YmluZF90b29sdGlwKCkge1xuXHRcdEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKFxuXHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChcIi5kYXRhLWdyb3VwIC5kYXlcIilcblx0XHQpLm1hcChlbCA9PiB7XG5cdFx0XHRlbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgKGUpID0+IHtcblx0XHRcdFx0bGV0IGNvdW50ID0gZS50YXJnZXQuZ2V0QXR0cmlidXRlKCdkYXRhLXZhbHVlJyk7XG5cdFx0XHRcdGxldCBkYXRlX3BhcnRzID0gZS50YXJnZXQuZ2V0QXR0cmlidXRlKCdkYXRhLWRhdGUnKS5zcGxpdCgnLScpO1xuXG5cdFx0XHRcdGxldCBtb250aCA9IHRoaXMubW9udGhfbmFtZXNbcGFyc2VJbnQoZGF0ZV9wYXJ0c1sxXSktMV0uc3Vic3RyaW5nKDAsIDMpO1xuXG5cdFx0XHRcdGxldCBnX29mZiA9IHRoaXMuY2hhcnRfd3JhcHBlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSwgcF9vZmYgPSBlLnRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdFx0XHRsZXQgd2lkdGggPSBwYXJzZUludChlLnRhcmdldC5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpO1xuXHRcdFx0XHRsZXQgeCA9IHBfb2ZmLmxlZnQgLSBnX29mZi5sZWZ0ICsgKHdpZHRoKzIpLzI7XG5cdFx0XHRcdGxldCB5ID0gcF9vZmYudG9wIC0gZ19vZmYudG9wIC0gKHdpZHRoKzIpLzI7XG5cdFx0XHRcdGxldCB2YWx1ZSA9IGNvdW50ICsgJyAnICsgdGhpcy5jb3VudF9sYWJlbDtcblx0XHRcdFx0bGV0IG5hbWUgPSAnIG9uICcgKyBtb250aCArICcgJyArIGRhdGVfcGFydHNbMF0gKyAnLCAnICsgZGF0ZV9wYXJ0c1syXTtcblxuXHRcdFx0XHR0aGlzLnRpcC5zZXRfdmFsdWVzKHgsIHksIG5hbWUsIHZhbHVlLCBbXSwgMSk7XG5cdFx0XHRcdHRoaXMudGlwLnNob3dfdGlwKCk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHVwZGF0ZShkYXRhKSB7XG5cdFx0dGhpcy5kYXRhID0gZGF0YTtcblx0XHR0aGlzLnNldHVwX3ZhbHVlcygpO1xuXHRcdHRoaXMuYmluZF90b29sdGlwKCk7XG5cdH1cblxuXHRnZXRfZGlzdHJpYnV0aW9uKGRhdGE9e30sIG1hcHBlcl9hcnJheSkge1xuXHRcdGxldCBkYXRhX3ZhbHVlcyA9IE9iamVjdC5rZXlzKGRhdGEpLm1hcChrZXkgPT4gZGF0YVtrZXldKTtcblx0XHRsZXQgZGF0YV9tYXhfdmFsdWUgPSBNYXRoLm1heCguLi5kYXRhX3ZhbHVlcyk7XG5cblx0XHRsZXQgZGlzdHJpYnV0aW9uX3N0ZXAgPSAxIC8gKG1hcHBlcl9hcnJheS5sZW5ndGggLSAxKTtcblx0XHRsZXQgZGlzdHJpYnV0aW9uID0gW107XG5cblx0XHRtYXBwZXJfYXJyYXkubWFwKChjb2xvciwgaSkgPT4ge1xuXHRcdFx0bGV0IGNoZWNrcG9pbnQgPSBkYXRhX21heF92YWx1ZSAqIChkaXN0cmlidXRpb25fc3RlcCAqIGkpO1xuXHRcdFx0ZGlzdHJpYnV0aW9uLnB1c2goY2hlY2twb2ludCk7XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gZGlzdHJpYnV0aW9uO1xuXHR9XG5cblx0Z2V0X21heF9jaGVja3BvaW50KHZhbHVlLCBkaXN0cmlidXRpb24pIHtcblx0XHRyZXR1cm4gZGlzdHJpYnV0aW9uLmZpbHRlcigoZCwgaSkgPT4ge1xuXHRcdFx0aWYoaSA9PT0gMSkge1xuXHRcdFx0XHRyZXR1cm4gZGlzdHJpYnV0aW9uWzBdIDwgdmFsdWU7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZCA8PSB2YWx1ZTtcblx0XHR9KS5sZW5ndGggLSAxO1xuXHR9XG5cblx0Ly8gVE9ETzogZGF0ZSB1dGlscywgbW92ZSB0aGVzZSBvdXRcblxuXHQvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTEyNTIxNjcvNjQ5NTA0M1xuXHR0cmVhdF9hc191dGMoZGF0ZV9zdHIpIHtcblx0XHRsZXQgcmVzdWx0ID0gbmV3IERhdGUoZGF0ZV9zdHIpO1xuXHRcdHJlc3VsdC5zZXRNaW51dGVzKHJlc3VsdC5nZXRNaW51dGVzKCkgLSByZXN1bHQuZ2V0VGltZXpvbmVPZmZzZXQoKSk7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdGdldF9kZF9tbV95eXl5KGRhdGUpIHtcblx0XHRsZXQgZGQgPSBkYXRlLmdldERhdGUoKTtcblx0XHRsZXQgbW0gPSBkYXRlLmdldE1vbnRoKCkgKyAxOyAvLyBnZXRNb250aCgpIGlzIHplcm8tYmFzZWRcblx0XHRyZXR1cm4gW1xuXHRcdFx0KGRkPjkgPyAnJyA6ICcwJykgKyBkZCxcblx0XHRcdChtbT45ID8gJycgOiAnMCcpICsgbW0sXG5cdFx0XHRkYXRlLmdldEZ1bGxZZWFyKClcblx0XHRdLmpvaW4oJy0nKTtcblx0fVxuXG5cdGdldF93ZWVrc19iZXR3ZWVuKHN0YXJ0X2RhdGVfc3RyLCBlbmRfZGF0ZV9zdHIpIHtcblx0XHRyZXR1cm4gTWF0aC5jZWlsKHRoaXMuZ2V0X2RheXNfYmV0d2VlbihzdGFydF9kYXRlX3N0ciwgZW5kX2RhdGVfc3RyKSAvIDcpO1xuXHR9XG5cblx0Z2V0X2RheXNfYmV0d2VlbihzdGFydF9kYXRlX3N0ciwgZW5kX2RhdGVfc3RyKSB7XG5cdFx0bGV0IG1pbGxpc2Vjb25kc19wZXJfZGF5ID0gMjQgKiA2MCAqIDYwICogMTAwMDtcblx0XHRyZXR1cm4gKHRoaXMudHJlYXRfYXNfdXRjKGVuZF9kYXRlX3N0cikgLSB0aGlzLnRyZWF0X2FzX3V0YyhzdGFydF9kYXRlX3N0cikpIC8gbWlsbGlzZWNvbmRzX3Blcl9kYXk7XG5cdH1cblxuXHQvLyBtdXRhdGVzXG5cdGFkZF9kYXlzKGRhdGUsIG51bWJlcl9vZl9kYXlzKSB7XG5cdFx0ZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpICsgbnVtYmVyX29mX2RheXMpO1xuXHR9XG5cblx0Z2V0X21vbnRoX25hbWUoKSB7fVxufVxuXG5mcmFwcGUuY2hhcnQuU3ZnVGlwID0gY2xhc3Mge1xuXHRjb25zdHJ1Y3Rvcih7XG5cdFx0cGFyZW50ID0gbnVsbFxuXHR9KSB7XG5cdFx0dGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG5cdFx0dGhpcy50aXRsZV9uYW1lID0gJyc7XG5cdFx0dGhpcy50aXRsZV92YWx1ZSA9ICcnO1xuXHRcdHRoaXMubGlzdF92YWx1ZXMgPSBbXTtcblx0XHR0aGlzLnRpdGxlX3ZhbHVlX2ZpcnN0ID0gMDtcblxuXHRcdHRoaXMueCA9IDA7XG5cdFx0dGhpcy55ID0gMDtcblxuXHRcdHRoaXMudG9wID0gMDtcblx0XHR0aGlzLmxlZnQgPSAwO1xuXG5cdFx0dGhpcy5zZXR1cCgpO1xuXHR9XG5cblx0c2V0dXAoKSB7XG5cdFx0dGhpcy5tYWtlX3Rvb2x0aXAoKTtcblx0fVxuXG5cdHJlZnJlc2goKSB7XG5cdFx0dGhpcy5maWxsKCk7XG5cdFx0dGhpcy5jYWxjX3Bvc2l0aW9uKCk7XG5cdFx0Ly8gdGhpcy5zaG93X3RpcCgpO1xuXHR9XG5cblx0bWFrZV90b29sdGlwKCkge1xuXHRcdHRoaXMuY29udGFpbmVyID0gJCQuY3JlYXRlKCdkaXYnLCB7XG5cdFx0XHRpbnNpZGU6IHRoaXMucGFyZW50LFxuXHRcdFx0Y2xhc3NOYW1lOiAnZ3JhcGgtc3ZnLXRpcCBjb21wYXJpc29uJyxcblx0XHRcdGlubmVySFRNTDogYDxzcGFuIGNsYXNzPVwidGl0bGVcIj48L3NwYW4+XG5cdFx0XHRcdDx1bCBjbGFzcz1cImRhdGEtcG9pbnQtbGlzdFwiPjwvdWw+XG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJzdmctcG9pbnRlclwiPjwvZGl2PmBcblx0XHR9KTtcblx0XHR0aGlzLmhpZGVfdGlwKCk7XG5cblx0XHR0aGlzLnRpdGxlID0gdGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvcignLnRpdGxlJyk7XG5cdFx0dGhpcy5kYXRhX3BvaW50X2xpc3QgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuZGF0YS1wb2ludC1saXN0Jyk7XG5cblx0XHR0aGlzLnBhcmVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgKCkgPT4ge1xuXHRcdFx0dGhpcy5oaWRlX3RpcCgpO1xuXHRcdH0pO1xuXHR9XG5cblx0ZmlsbCgpIHtcblx0XHRsZXQgdGl0bGU7XG5cdFx0aWYodGhpcy50aXRsZV92YWx1ZV9maXJzdCkge1xuXHRcdFx0dGl0bGUgPSBgPHN0cm9uZz4ke3RoaXMudGl0bGVfdmFsdWV9PC9zdHJvbmc+JHt0aGlzLnRpdGxlX25hbWV9YDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGl0bGUgPSBgJHt0aGlzLnRpdGxlX25hbWV9PHN0cm9uZz4ke3RoaXMudGl0bGVfdmFsdWV9PC9zdHJvbmc+YDtcblx0XHR9XG5cdFx0dGhpcy50aXRsZS5pbm5lckhUTUwgPSB0aXRsZTtcblx0XHR0aGlzLmRhdGFfcG9pbnRfbGlzdC5pbm5lckhUTUwgPSAnJztcblxuXHRcdHRoaXMubGlzdF92YWx1ZXMubWFwKChzZXQpID0+IHtcblx0XHRcdGxldCBsaSA9ICQkLmNyZWF0ZSgnbGknLCB7XG5cdFx0XHRcdGNsYXNzTmFtZTogYGJvcmRlci10b3AgJHtzZXQuY29sb3IgfHwgJ2JsYWNrJ31gLFxuXHRcdFx0XHRpbm5lckhUTUw6IGA8c3Ryb25nIHN0eWxlPVwiZGlzcGxheTogYmxvY2s7XCI+JHtzZXQudmFsdWUgPyBzZXQudmFsdWUgOiAnJyB9PC9zdHJvbmc+XG5cdFx0XHRcdFx0JHtzZXQudGl0bGUgPyBzZXQudGl0bGUgOiAnJyB9YFxuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMuZGF0YV9wb2ludF9saXN0LmFwcGVuZENoaWxkKGxpKTtcblx0XHR9KTtcblx0fVxuXG5cdGNhbGNfcG9zaXRpb24oKSB7XG5cdFx0dGhpcy50b3AgPSB0aGlzLnkgLSB0aGlzLmNvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XG5cdFx0dGhpcy5sZWZ0ID0gdGhpcy54IC0gdGhpcy5jb250YWluZXIub2Zmc2V0V2lkdGgvMjtcblx0XHRsZXQgbWF4X2xlZnQgPSB0aGlzLnBhcmVudC5vZmZzZXRXaWR0aCAtIHRoaXMuY29udGFpbmVyLm9mZnNldFdpZHRoO1xuXG5cdFx0bGV0IHBvaW50ZXIgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuc3ZnLXBvaW50ZXInKTtcblxuXHRcdGlmKHRoaXMubGVmdCA8IDApIHtcblx0XHRcdHBvaW50ZXIuc3R5bGUubGVmdCA9IGBjYWxjKDUwJSAtICR7LTEgKiB0aGlzLmxlZnR9cHgpYDtcblx0XHRcdHRoaXMubGVmdCA9IDA7XG5cdFx0fSBlbHNlIGlmKHRoaXMubGVmdCA+IG1heF9sZWZ0KSB7XG5cdFx0XHRsZXQgZGVsdGEgPSB0aGlzLmxlZnQgLSBtYXhfbGVmdDtcblx0XHRcdHBvaW50ZXIuc3R5bGUubGVmdCA9IGBjYWxjKDUwJSArICR7ZGVsdGF9cHgpYDtcblx0XHRcdHRoaXMubGVmdCA9IG1heF9sZWZ0O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwb2ludGVyLnN0eWxlLmxlZnQgPSBgNTAlYDtcblx0XHR9XG5cdH1cblxuXHRzZXRfdmFsdWVzKHgsIHksIHRpdGxlX25hbWUgPSAnJywgdGl0bGVfdmFsdWUgPSAnJywgbGlzdF92YWx1ZXMgPSBbXSwgdGl0bGVfdmFsdWVfZmlyc3QgPSAwKSB7XG5cdFx0dGhpcy50aXRsZV9uYW1lID0gdGl0bGVfbmFtZTtcblx0XHR0aGlzLnRpdGxlX3ZhbHVlID0gdGl0bGVfdmFsdWU7XG5cdFx0dGhpcy5saXN0X3ZhbHVlcyA9IGxpc3RfdmFsdWVzO1xuXHRcdHRoaXMueCA9IHg7XG5cdFx0dGhpcy55ID0geTtcblx0XHR0aGlzLnRpdGxlX3ZhbHVlX2ZpcnN0ID0gdGl0bGVfdmFsdWVfZmlyc3Q7XG5cdFx0dGhpcy5yZWZyZXNoKCk7XG5cdH1cblxuXHRoaWRlX3RpcCgpIHtcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS50b3AgPSAnMHB4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJzBweCc7XG5cdFx0dGhpcy5jb250YWluZXIuc3R5bGUub3BhY2l0eSA9ICcwJztcblx0fVxuXG5cdHNob3dfdGlwKCkge1xuXHRcdHRoaXMuY29udGFpbmVyLnN0eWxlLnRvcCA9IHRoaXMudG9wICsgJ3B4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gdGhpcy5sZWZ0ICsgJ3B4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5vcGFjaXR5ID0gJzEnO1xuXHR9XG59XG5cbi8vIEhlbHBlcnNcbmZyYXBwZS5jaGFydC51dGlscyA9IHt9O1xuJCQuZmxvYXRfMiA9IGQgPT4gcGFyc2VGbG9hdChkLnRvRml4ZWQoMikpO1xuZnVuY3Rpb24gJCQoZXhwciwgY29uKSB7XG5cdHJldHVybiB0eXBlb2YgZXhwciA9PT0gXCJzdHJpbmdcIj8gKGNvbiB8fCBkb2N1bWVudCkucXVlcnlTZWxlY3RvcihleHByKSA6IGV4cHIgfHwgbnVsbDtcbn1cblxuJCQuYXJyYXlzX2VxdWFsID0gKGFycjEsIGFycjIpID0+IHtcblx0aWYoYXJyMS5sZW5ndGggIT09IGFycjIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cdGxldCBhcmVfZXF1YWwgPSB0cnVlO1xuXHRhcnIxLm1hcCgoZCwgaSkgPT4ge1xuXHRcdGlmKGFycjJbaV0gIT09IGQpIGFyZV9lcXVhbCA9IGZhbHNlO1xuXHR9KTtcblx0cmV0dXJuIGFyZV9lcXVhbDtcbn1cblxuJCQuc2h1ZmZsZSA9IChhcnJheSkgPT4ge1xuXHQvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjQ1MDk3Ni82NDk1MDQzXG5cdC8vIEF3ZXNvbWVuZXNzOiBodHRwczovL2Jvc3Qub2Nrcy5vcmcvbWlrZS9zaHVmZmxlL1xuXG5cdHZhciBjdXJyZW50SW5kZXggPSBhcnJheS5sZW5ndGgsIHRlbXBvcmFyeVZhbHVlLCByYW5kb21JbmRleDtcblxuXHQvLyBXaGlsZSB0aGVyZSByZW1haW4gZWxlbWVudHMgdG8gc2h1ZmZsZS4uLlxuXHR3aGlsZSAoMCAhPT0gY3VycmVudEluZGV4KSB7XG5cblx0XHQvLyBQaWNrIGEgcmVtYWluaW5nIGVsZW1lbnQuLi5cblx0XHRyYW5kb21JbmRleCA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGN1cnJlbnRJbmRleCk7XG5cdFx0Y3VycmVudEluZGV4IC09IDE7XG5cblx0XHQvLyBBbmQgc3dhcCBpdCB3aXRoIHRoZSBjdXJyZW50IGVsZW1lbnQuXG5cdFx0dGVtcG9yYXJ5VmFsdWUgPSBhcnJheVtjdXJyZW50SW5kZXhdO1xuXHRcdGFycmF5W2N1cnJlbnRJbmRleF0gPSBhcnJheVtyYW5kb21JbmRleF07XG5cdFx0YXJyYXlbcmFuZG9tSW5kZXhdID0gdGVtcG9yYXJ5VmFsdWU7XG5cdH1cblxuXHRyZXR1cm4gYXJyYXk7XG5cbn1cblxuLy8gJCQuZmluZE5vZGVJbmRleCA9IChub2RlKSA9PlxuLy8ge1xuLy8gXHR2YXIgaSA9IDA7XG4vLyBcdHdoaWxlIChub2RlID0gbm9kZS5wcmV2aW91c1NpYmxpbmcpIHtcbi8vIFx0XHRpZiAobm9kZS5ub2RlVHlwZSA9PT0gMSkgeyArK2k7IH1cbi8vIFx0fVxuLy8gXHRyZXR1cm4gaTtcbi8vIH1cblxuJCQuY3JlYXRlID0gZnVuY3Rpb24odGFnLCBvKSB7XG5cdHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWcpO1xuXG5cdGZvciAodmFyIGkgaW4gbykge1xuXHRcdHZhciB2YWwgPSBvW2ldO1xuXG5cdFx0aWYgKGkgPT09IFwiaW5zaWRlXCIpIHtcblx0XHRcdCQkKHZhbCkuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKGkgPT09IFwiYXJvdW5kXCIpIHtcblx0XHRcdHZhciByZWYgPSAkJCh2YWwpO1xuXHRcdFx0cmVmLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGVsZW1lbnQsIHJlZik7XG5cdFx0XHRlbGVtZW50LmFwcGVuZENoaWxkKHJlZik7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKGkgaW4gZWxlbWVudCkge1xuXHRcdFx0ZWxlbWVudFtpXSA9IHZhbDtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRlbGVtZW50LnNldEF0dHJpYnV0ZShpLCB2YWwpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50O1xufTtcblxuJCQuY3JlYXRlU1ZHID0gZnVuY3Rpb24odGFnLCBvKSB7XG5cdHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgdGFnKTtcblxuXHRmb3IgKHZhciBpIGluIG8pIHtcblx0XHR2YXIgdmFsID0gb1tpXTtcblxuXHRcdGlmIChpID09PSBcImluc2lkZVwiKSB7XG5cdFx0XHQkJCh2YWwpLmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuXHRcdH1cblx0XHRlbHNlIGlmIChpID09PSBcImFyb3VuZFwiKSB7XG5cdFx0XHR2YXIgcmVmID0gJCQodmFsKTtcblx0XHRcdHJlZi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlbGVtZW50LCByZWYpO1xuXHRcdFx0ZWxlbWVudC5hcHBlbmRDaGlsZChyZWYpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmKGkgPT09IFwiY2xhc3NOYW1lXCIpIHsgaSA9IFwiY2xhc3NcIjsgfVxuXHRcdFx0aWYoaSA9PT0gXCJpbm5lckhUTUxcIikge1xuXHRcdFx0XHRlbGVtZW50Wyd0ZXh0Q29udGVudCddID0gdmFsO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudC5zZXRBdHRyaWJ1dGUoaSwgdmFsKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZWxlbWVudDtcbn07XG5cbiQkLnJ1blNWR0FuaW1hdGlvbiA9IChzdmdfY29udGFpbmVyLCBlbGVtZW50cykgPT4ge1xuXHQvLyBsZXQgcGFyZW50ID0gZWxlbWVudHNbMF1bMF1bJ3VuaXQnXS5wYXJlbnROb2RlO1xuXG5cdGxldCBuZXdfZWxlbWVudHMgPSBbXTtcblx0bGV0IGFuaW1fZWxlbWVudHMgPSBbXTtcblxuXHRlbGVtZW50cy5tYXAoZWxlbWVudCA9PiB7XG5cdFx0bGV0IG9iaiA9IGVsZW1lbnRbMF07XG5cdFx0bGV0IHBhcmVudCA9IG9iai51bml0LnBhcmVudE5vZGU7XG5cdFx0Ly8gbGV0IGluZGV4ID0gJCQuZmluZE5vZGVJbmRleChvYmoudW5pdCk7XG5cblx0XHRsZXQgYW5pbV9lbGVtZW50LCBuZXdfZWxlbWVudDtcblxuXHRcdGVsZW1lbnRbMF0gPSBvYmoudW5pdDtcblxuXHRcdFthbmltX2VsZW1lbnQsIG5ld19lbGVtZW50XSA9ICQkLmFuaW1hdGVTVkcoLi4uZWxlbWVudCk7XG5cblx0XHRuZXdfZWxlbWVudHMucHVzaChuZXdfZWxlbWVudCk7XG5cdFx0YW5pbV9lbGVtZW50cy5wdXNoKFthbmltX2VsZW1lbnQsIHBhcmVudF0pO1xuXG5cdFx0cGFyZW50LnJlcGxhY2VDaGlsZChhbmltX2VsZW1lbnQsIG9iai51bml0KTtcblxuXHRcdGlmKG9iai5hcnJheSkge1xuXHRcdFx0b2JqLmFycmF5W29iai5pbmRleF0gPSBuZXdfZWxlbWVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0b2JqLm9iamVjdFtvYmoua2V5XSA9IG5ld19lbGVtZW50O1xuXHRcdH1cblx0fSk7XG5cblx0bGV0IGFuaW1fc3ZnID0gc3ZnX2NvbnRhaW5lci5jbG9uZU5vZGUodHJ1ZSk7XG5cblx0YW5pbV9lbGVtZW50cy5tYXAoKGFuaW1fZWxlbWVudCwgaSkgPT4ge1xuXHRcdGFuaW1fZWxlbWVudFsxXS5yZXBsYWNlQ2hpbGQobmV3X2VsZW1lbnRzW2ldLCBhbmltX2VsZW1lbnRbMF0pO1xuXHRcdGVsZW1lbnRzW2ldWzBdID0gbmV3X2VsZW1lbnRzW2ldO1xuXHR9KTtcblxuXHRyZXR1cm4gYW5pbV9zdmc7XG59XG5cbi8vICQkLmFuaW1hdGVNb3Rpb24gPSAoZWxlbWVudCwgcHJvcHMsIGR1ciwgZWFzaW5nX3R5cGU9XCJsaW5lYXJcIilcblxuJCQuYW5pbWF0ZVNWRyA9IChlbGVtZW50LCBwcm9wcywgZHVyLCBlYXNpbmdfdHlwZT1cImxpbmVhclwiLCB0eXBlPXVuZGVmaW5lZCwgb2xkX3ZhbHVlcz17fSkgPT4ge1xuXHRsZXQgZWFzaW5nID0ge1xuXHRcdGVhc2U6IFwiMC4yNSAwLjEgMC4yNSAxXCIsXG5cdFx0bGluZWFyOiBcIjAgMCAxIDFcIixcblx0XHQvLyBlYXNlaW46IFwiMC40MiAwIDEgMVwiLFxuXHRcdGVhc2VpbjogXCIwLjEgMC44IDAuMiAxXCIsXG5cdFx0ZWFzZW91dDogXCIwIDAgMC41OCAxXCIsXG5cdFx0ZWFzZWlub3V0OiBcIjAuNDIgMCAwLjU4IDFcIlxuXHR9XG5cblx0bGV0IGFuaW1fZWxlbWVudCA9IGVsZW1lbnQuY2xvbmVOb2RlKHRydWUpO1xuXHRsZXQgbmV3X2VsZW1lbnQgPSBlbGVtZW50LmNsb25lTm9kZSh0cnVlKTtcblxuXHRmb3IodmFyIGF0dHJpYnV0ZU5hbWUgaW4gcHJvcHMpIHtcblx0XHRsZXQgYW5pbWF0ZV9lbGVtZW50O1xuXHRcdGlmKGF0dHJpYnV0ZU5hbWUgPT09ICd0cmFuc2Zvcm0nKSB7XG5cdFx0XHRhbmltYXRlX2VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCBcImFuaW1hdGVUcmFuc2Zvcm1cIik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGFuaW1hdGVfZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIFwiYW5pbWF0ZVwiKTtcblx0XHR9XG5cdFx0bGV0IGN1cnJlbnRfdmFsdWUgPSBvbGRfdmFsdWVzW2F0dHJpYnV0ZU5hbWVdIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUpO1xuXHRcdGxldCB2YWx1ZSA9IHByb3BzW2F0dHJpYnV0ZU5hbWVdO1xuXG5cdFx0bGV0IGFuaW1fYXR0ciA9IHtcblx0XHRcdGF0dHJpYnV0ZU5hbWU6IGF0dHJpYnV0ZU5hbWUsXG5cdFx0XHRmcm9tOiBjdXJyZW50X3ZhbHVlLFxuXHRcdFx0dG86IHZhbHVlLFxuXHRcdFx0YmVnaW46IFwiMHNcIixcblx0XHRcdGR1cjogZHVyLzEwMDAgKyBcInNcIixcblx0XHRcdHZhbHVlczogY3VycmVudF92YWx1ZSArIFwiO1wiICsgdmFsdWUsXG5cdFx0XHRrZXlTcGxpbmVzOiBlYXNpbmdbZWFzaW5nX3R5cGVdLFxuXHRcdFx0a2V5VGltZXM6IFwiMDsxXCIsXG5cdFx0XHRjYWxjTW9kZTogXCJzcGxpbmVcIixcblx0XHRcdGZpbGw6ICdmcmVlemUnXG5cdFx0fVxuXG5cdFx0aWYodHlwZSkge1xuXHRcdFx0YW5pbV9hdHRyW1widHlwZVwiXSA9IHR5cGU7XG5cdFx0fVxuXG5cdFx0Zm9yICh2YXIgaSBpbiBhbmltX2F0dHIpIHtcblx0XHRcdGFuaW1hdGVfZWxlbWVudC5zZXRBdHRyaWJ1dGUoaSwgYW5pbV9hdHRyW2ldKTtcblx0XHR9XG5cblx0XHRhbmltX2VsZW1lbnQuYXBwZW5kQ2hpbGQoYW5pbWF0ZV9lbGVtZW50KTtcblxuXHRcdGlmKHR5cGUpIHtcblx0XHRcdG5ld19lbGVtZW50LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lLCBgdHJhbnNsYXRlKCR7dmFsdWV9KWApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRuZXdfZWxlbWVudC5zZXRBdHRyaWJ1dGUoYXR0cmlidXRlTmFtZSwgdmFsdWUpO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBbYW5pbV9lbGVtZW50LCBuZXdfZWxlbWVudF07XG59XG5cbiQkLm9mZnNldCA9IChlbGVtZW50KSA9PiB7XG5cdGxldCByZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0cmV0dXJuIHtcblx0XHQvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNzQzNjYwMi82NDk1MDQzXG5cdFx0Ly8gcmVjdC50b3AgdmFyaWVzIHdpdGggc2Nyb2xsLCBzbyB3ZSBhZGQgd2hhdGV2ZXIgaGFzIGJlZW5cblx0XHQvLyBzY3JvbGxlZCB0byBpdCB0byBnZXQgYWJzb2x1dGUgZGlzdGFuY2UgZnJvbSBhY3R1YWwgcGFnZSB0b3Bcblx0XHR0b3A6IHJlY3QudG9wICsgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3AgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxUb3ApLFxuXHRcdGxlZnQ6IHJlY3QubGVmdCArIChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsTGVmdCB8fCBkb2N1bWVudC5ib2R5LnNjcm9sbExlZnQpXG5cdH1cbn07XG5cbiQkLmlzRWxlbWVudEluVmlld3BvcnQgPSAoZWwpID0+IHtcblx0Ly8gQWx0aG91Z2ggc3RyYWlnaHRmb3J3YXJkOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNzU1NzQzMy82NDk1MDQzXG4gICAgdmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIHJldHVybiAoXG4gICAgICAgIHJlY3QudG9wID49IDAgJiZcbiAgICAgICAgcmVjdC5sZWZ0ID49IDAgJiZcbiAgICAgICAgcmVjdC5ib3R0b20gPD0gKHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KSAmJiAvKm9yICQod2luZG93KS5oZWlnaHQoKSAqL1xuICAgICAgICByZWN0LnJpZ2h0IDw9ICh3aW5kb3cuaW5uZXJXaWR0aCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgpIC8qb3IgJCh3aW5kb3cpLndpZHRoKCkgKi9cbiAgICApO1xufVxuXG4kJC5iaW5kID0gZnVuY3Rpb24oZWxlbWVudCwgbykge1xuXHRpZiAoZWxlbWVudCkge1xuXHRcdGZvciAodmFyIGV2ZW50IGluIG8pIHtcblx0XHRcdHZhciBjYWxsYmFjayA9IG9bZXZlbnRdO1xuXG5cdFx0XHRldmVudC5zcGxpdCgvXFxzKy8pLmZvckVhY2goZnVuY3Rpb24gKGV2ZW50KSB7XG5cdFx0XHRcdGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgY2FsbGJhY2spO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59O1xuXG4kJC51bmJpbmQgPSBmdW5jdGlvbihlbGVtZW50LCBvKSB7XG5cdGlmIChlbGVtZW50KSB7XG5cdFx0Zm9yICh2YXIgZXZlbnQgaW4gbykge1xuXHRcdFx0dmFyIGNhbGxiYWNrID0gb1tldmVudF07XG5cblx0XHRcdGV2ZW50LnNwbGl0KC9cXHMrLykuZm9yRWFjaChmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGNhbGxiYWNrKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxufTtcblxuJCQuZmlyZSA9IGZ1bmN0aW9uKHRhcmdldCwgdHlwZSwgcHJvcGVydGllcykge1xuXHR2YXIgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoXCJIVE1MRXZlbnRzXCIpO1xuXG5cdGV2dC5pbml0RXZlbnQodHlwZSwgdHJ1ZSwgdHJ1ZSApO1xuXG5cdGZvciAodmFyIGogaW4gcHJvcGVydGllcykge1xuXHRcdGV2dFtqXSA9IHByb3BlcnRpZXNbal07XG5cdH1cblxuXHRyZXR1cm4gdGFyZ2V0LmRpc3BhdGNoRXZlbnQoZXZ0KTtcbn07XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsSUFBSSxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7O0FBRTlFLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLE1BQU07Q0FDaEMsV0FBVyxDQUFDO0VBQ1gsTUFBTSxHQUFHLEVBQUU7RUFDWCxNQUFNLEdBQUcsR0FBRzs7RUFFWixLQUFLLEdBQUcsRUFBRSxFQUFFLFFBQVEsR0FBRyxFQUFFOztFQUV6QixJQUFJ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LENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7RUFDaEUsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztFQUMzQixLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7O0VBRWhDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0VBQ2pDOztDQUVELGlCQUFpQixDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUU7RUFDMUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsT0FBTzs7RUFFN0IsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7RUFDekUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7RUFDcEQsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztFQUMzQixLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQzs7RUFFdkIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7RUFDakM7O0NBRUQsYUFBYSxHQUFHO0VBQ2YsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxt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 +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhcHBlLWNoYXJ0cy5taW4uanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9kb20uanMiLCIuLi9zcmMvdXRpbHMuanMiLCIuLi9zcmMvY2hhcnRzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uICQoZXhwciwgY29uKSB7XG5cdHJldHVybiB0eXBlb2YgZXhwciA9PT0gXCJzdHJpbmdcIj8gKGNvbiB8fCBkb2N1bWVudCkucXVlcnlTZWxlY3RvcihleHByKSA6IGV4cHIgfHwgbnVsbDtcbn1cblxuJC5maW5kTm9kZUluZGV4ID0gKG5vZGUpID0+XG57XG5cdHZhciBpID0gMDtcblx0d2hpbGUgKG5vZGUucHJldmlvdXNTaWJsaW5nKSB7XG5cdFx0bm9kZSA9IG5vZGUucHJldmlvdXNTaWJsaW5nO1xuXHRcdGkrKztcblx0fVxuXHRyZXR1cm4gaTtcbn07XG5cbiQuY3JlYXRlID0gKHRhZywgbykgPT4ge1xuXHR2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnKTtcblxuXHRmb3IgKHZhciBpIGluIG8pIHtcblx0XHR2YXIgdmFsID0gb1tpXTtcblxuXHRcdGlmIChpID09PSBcImluc2lkZVwiKSB7XG5cdFx0XHQkKHZhbCkuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKGkgPT09IFwiYXJvdW5kXCIpIHtcblx0XHRcdHZhciByZWYgPSAkKHZhbCk7XG5cdFx0XHRyZWYucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZWxlbWVudCwgcmVmKTtcblx0XHRcdGVsZW1lbnQuYXBwZW5kQ2hpbGQocmVmKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoaSBpbiBlbGVtZW50KSB7XG5cdFx0XHRlbGVtZW50W2ldID0gdmFsO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGVsZW1lbnQuc2V0QXR0cmlidXRlKGksIHZhbCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnQ7XG59O1xuXG4kLmNyZWF0ZVNWRyA9ICh0YWcsIG8pID0+IHtcblx0dmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCB0YWcpO1xuXG5cdGZvciAodmFyIGkgaW4gbykge1xuXHRcdHZhciB2YWwgPSBvW2ldO1xuXG5cdFx0aWYgKGkgPT09IFwiaW5zaWRlXCIpIHtcblx0XHRcdCQodmFsKS5hcHBlbmRDaGlsZChlbGVtZW50KTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoaSA9PT0gXCJhcm91bmRcIikge1xuXHRcdFx0dmFyIHJlZiA9ICQodmFsKTtcblx0XHRcdHJlZi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlbGVtZW50LCByZWYpO1xuXHRcdFx0ZWxlbWVudC5hcHBlbmRDaGlsZChyZWYpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmKGkgPT09IFwiY2xhc3NOYW1lXCIpIHsgaSA9IFwiY2xhc3NcIjsgfVxuXHRcdFx0aWYoaSA9PT0gXCJpbm5lckhUTUxcIikge1xuXHRcdFx0XHRlbGVtZW50Wyd0ZXh0Q29udGVudCddID0gdmFsO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudC5zZXRBdHRyaWJ1dGUoaSwgdmFsKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZWxlbWVudDtcbn07XG5cbiQucnVuU1ZHQW5pbWF0aW9uID0gKHN2Z19jb250YWluZXIsIGVsZW1lbnRzKSA9PiB7XG5cdC8vIGxldCBwYXJlbnQgPSBlbGVtZW50c1swXVswXVsndW5pdCddLnBhcmVudE5vZGU7XG5cblx0bGV0IG5ld19lbGVtZW50cyA9IFtdO1xuXHRsZXQgYW5pbV9lbGVtZW50cyA9IFtdO1xuXG5cdGVsZW1lbnRzLm1hcChlbGVtZW50ID0+IHtcblx0XHRsZXQgb2JqID0gZWxlbWVudFswXTtcblx0XHRsZXQgcGFyZW50ID0gb2JqLnVuaXQucGFyZW50Tm9kZTtcblx0XHQvLyBsZXQgaW5kZXggPSBsZXQgZmluZE5vZGVJbmRleChvYmoudW5pdCk7XG5cblx0XHRsZXQgYW5pbV9lbGVtZW50LCBuZXdfZWxlbWVudDtcblxuXHRcdGVsZW1lbnRbMF0gPSBvYmoudW5pdDtcblxuXHRcdFthbmltX2VsZW1lbnQsIG5ld19lbGVtZW50XSA9ICQuYW5pbWF0ZVNWRyguLi5lbGVtZW50KTtcblxuXHRcdG5ld19lbGVtZW50cy5wdXNoKG5ld19lbGVtZW50KTtcblx0XHRhbmltX2VsZW1lbnRzLnB1c2goW2FuaW1fZWxlbWVudCwgcGFyZW50XSk7XG5cblx0XHRwYXJlbnQucmVwbGFjZUNoaWxkKGFuaW1fZWxlbWVudCwgb2JqLnVuaXQpO1xuXG5cdFx0aWYob2JqLmFycmF5KSB7XG5cdFx0XHRvYmouYXJyYXlbb2JqLmluZGV4XSA9IG5ld19lbGVtZW50O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRvYmoub2JqZWN0W29iai5rZXldID0gbmV3X2VsZW1lbnQ7XG5cdFx0fVxuXHR9KTtcblxuXHRsZXQgYW5pbV9zdmcgPSBzdmdfY29udGFpbmVyLmNsb25lTm9kZSh0cnVlKTtcblxuXHRhbmltX2VsZW1lbnRzLm1hcCgoYW5pbV9lbGVtZW50LCBpKSA9PiB7XG5cdFx0YW5pbV9lbGVtZW50WzFdLnJlcGxhY2VDaGlsZChuZXdfZWxlbWVudHNbaV0sIGFuaW1fZWxlbWVudFswXSk7XG5cdFx0ZWxlbWVudHNbaV1bMF0gPSBuZXdfZWxlbWVudHNbaV07XG5cdH0pO1xuXG5cdHJldHVybiBhbmltX3N2Zztcbn07XG5cbiQuYW5pbWF0ZVNWRyA9IChlbGVtZW50LCBwcm9wcywgZHVyLCBlYXNpbmdfdHlwZT1cImxpbmVhclwiLCB0eXBlPXVuZGVmaW5lZCwgb2xkX3ZhbHVlcz17fSkgPT4ge1xuXHRsZXQgZWFzaW5nID0ge1xuXHRcdGVhc2U6IFwiMC4yNSAwLjEgMC4yNSAxXCIsXG5cdFx0bGluZWFyOiBcIjAgMCAxIDFcIixcblx0XHQvLyBlYXNlaW46IFwiMC40MiAwIDEgMVwiLFxuXHRcdGVhc2VpbjogXCIwLjEgMC44IDAuMiAxXCIsXG5cdFx0ZWFzZW91dDogXCIwIDAgMC41OCAxXCIsXG5cdFx0ZWFzZWlub3V0OiBcIjAuNDIgMCAwLjU4IDFcIlxuXHR9O1xuXG5cdGxldCBhbmltX2VsZW1lbnQgPSBlbGVtZW50LmNsb25lTm9kZSh0cnVlKTtcblx0bGV0IG5ld19lbGVtZW50ID0gZWxlbWVudC5jbG9uZU5vZGUodHJ1ZSk7XG5cblx0Zm9yKHZhciBhdHRyaWJ1dGVOYW1lIGluIHByb3BzKSB7XG5cdFx0bGV0IGFuaW1hdGVfZWxlbWVudDtcblx0XHRpZihhdHRyaWJ1dGVOYW1lID09PSAndHJhbnNmb3JtJykge1xuXHRcdFx0YW5pbWF0ZV9lbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgXCJhbmltYXRlVHJhbnNmb3JtXCIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRhbmltYXRlX2VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLCBcImFuaW1hdGVcIik7XG5cdFx0fVxuXHRcdGxldCBjdXJyZW50X3ZhbHVlID0gb2xkX3ZhbHVlc1thdHRyaWJ1dGVOYW1lXSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lKTtcblx0XHRsZXQgdmFsdWUgPSBwcm9wc1thdHRyaWJ1dGVOYW1lXTtcblxuXHRcdGxldCBhbmltX2F0dHIgPSB7XG5cdFx0XHRhdHRyaWJ1dGVOYW1lOiBhdHRyaWJ1dGVOYW1lLFxuXHRcdFx0ZnJvbTogY3VycmVudF92YWx1ZSxcblx0XHRcdHRvOiB2YWx1ZSxcblx0XHRcdGJlZ2luOiBcIjBzXCIsXG5cdFx0XHRkdXI6IGR1ci8xMDAwICsgXCJzXCIsXG5cdFx0XHR2YWx1ZXM6IGN1cnJlbnRfdmFsdWUgKyBcIjtcIiArIHZhbHVlLFxuXHRcdFx0a2V5U3BsaW5lczogZWFzaW5nW2Vhc2luZ190eXBlXSxcblx0XHRcdGtleVRpbWVzOiBcIjA7MVwiLFxuXHRcdFx0Y2FsY01vZGU6IFwic3BsaW5lXCIsXG5cdFx0XHRmaWxsOiAnZnJlZXplJ1xuXHRcdH07XG5cblx0XHRpZih0eXBlKSB7XG5cdFx0XHRhbmltX2F0dHJbXCJ0eXBlXCJdID0gdHlwZTtcblx0XHR9XG5cblx0XHRmb3IgKHZhciBpIGluIGFuaW1fYXR0cikge1xuXHRcdFx0YW5pbWF0ZV9lbGVtZW50LnNldEF0dHJpYnV0ZShpLCBhbmltX2F0dHJbaV0pO1xuXHRcdH1cblxuXHRcdGFuaW1fZWxlbWVudC5hcHBlbmRDaGlsZChhbmltYXRlX2VsZW1lbnQpO1xuXG5cdFx0aWYodHlwZSkge1xuXHRcdFx0bmV3X2VsZW1lbnQuc2V0QXR0cmlidXRlKGF0dHJpYnV0ZU5hbWUsIGB0cmFuc2xhdGUoJHt2YWx1ZX0pYCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG5ld19lbGVtZW50LnNldEF0dHJpYnV0ZShhdHRyaWJ1dGVOYW1lLCB2YWx1ZSk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIFthbmltX2VsZW1lbnQsIG5ld19lbGVtZW50XTtcbn07XG5cbiQub2Zmc2V0ID0gKGVsZW1lbnQpID0+IHtcblx0bGV0IHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXHRyZXR1cm4ge1xuXHRcdC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS83NDM2NjAyLzY0OTUwNDNcblx0XHQvLyByZWN0LnRvcCB2YXJpZXMgd2l0aCBzY3JvbGwsIHNvIHdlIGFkZCB3aGF0ZXZlciBoYXMgYmVlblxuXHRcdC8vIHNjcm9sbGVkIHRvIGl0IHRvIGdldCBhYnNvbHV0ZSBkaXN0YW5jZSBmcm9tIGFjdHVhbCBwYWdlIHRvcFxuXHRcdHRvcDogcmVjdC50b3AgKyAoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCB8fCBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCksXG5cdFx0bGVmdDogcmVjdC5sZWZ0ICsgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8IGRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdClcblx0fTtcbn07XG5cbiQuaXNFbGVtZW50SW5WaWV3cG9ydCA9IChlbCkgPT4ge1xuXHQvLyBBbHRob3VnaCBzdHJhaWdodGZvcndhcmQ6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS83NTU3NDMzLzY0OTUwNDNcblx0dmFyIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRyZXR1cm4gKFxuXHRcdHJlY3QudG9wID49IDAgJiZcbiAgICAgICAgcmVjdC5sZWZ0ID49IDAgJiZcbiAgICAgICAgcmVjdC5ib3R0b20gPD0gKHdpbmRvdy5pbm5lckhlaWdodCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KSAmJiAvKm9yICQod2luZG93KS5oZWlnaHQoKSAqL1xuICAgICAgICByZWN0LnJpZ2h0IDw9ICh3aW5kb3cuaW5uZXJXaWR0aCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgpIC8qb3IgJCh3aW5kb3cpLndpZHRoKCkgKi9cblx0KTtcbn07XG5cbiQuYmluZCA9IChlbGVtZW50LCBvKSA9PiB7XG5cdGlmIChlbGVtZW50KSB7XG5cdFx0Zm9yICh2YXIgZXZlbnQgaW4gbykge1xuXHRcdFx0dmFyIGNhbGxiYWNrID0gb1tldmVudF07XG5cblx0XHRcdGV2ZW50LnNwbGl0KC9cXHMrLykuZm9yRWFjaChmdW5jdGlvbiAoZXZlbnQpIHtcblx0XHRcdFx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBjYWxsYmFjayk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn07XG5cbiQudW5iaW5kID0gKGVsZW1lbnQsIG8pID0+IHtcblx0aWYgKGVsZW1lbnQpIHtcblx0XHRmb3IgKHZhciBldmVudCBpbiBvKSB7XG5cdFx0XHR2YXIgY2FsbGJhY2sgPSBvW2V2ZW50XTtcblxuXHRcdFx0ZXZlbnQuc3BsaXQoL1xccysvKS5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgY2FsbGJhY2spO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59O1xuXG4kLmZpcmUgPSAodGFyZ2V0LCB0eXBlLCBwcm9wZXJ0aWVzKSA9PiB7XG5cdHZhciBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudChcIkhUTUxFdmVudHNcIik7XG5cblx0ZXZ0LmluaXRFdmVudCh0eXBlLCB0cnVlLCB0cnVlICk7XG5cblx0Zm9yICh2YXIgaiBpbiBwcm9wZXJ0aWVzKSB7XG5cdFx0ZXZ0W2pdID0gcHJvcGVydGllc1tqXTtcblx0fVxuXG5cdHJldHVybiB0YXJnZXQuZGlzcGF0Y2hFdmVudChldnQpO1xufTtcbiIsImV4cG9ydCBmdW5jdGlvbiBmbG9hdF8yKGQpIHtcblx0cmV0dXJuIHBhcnNlRmxvYXQoZC50b0ZpeGVkKDIpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5c19lcXVhbChhcnIxLCBhcnIyKSB7XG5cdGlmKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuXHRsZXQgYXJlX2VxdWFsID0gdHJ1ZTtcblx0YXJyMS5tYXAoKGQsIGkpID0+IHtcblx0XHRpZihhcnIyW2ldICE9PSBkKSBhcmVfZXF1YWwgPSBmYWxzZTtcblx0fSk7XG5cdHJldHVybiBhcmVfZXF1YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaHVmZmxlKGFycmF5KSB7XG5cdC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yNDUwOTc2LzY0OTUwNDNcblx0Ly8gQXdlc29tZW5lc3M6IGh0dHBzOi8vYm9zdC5vY2tzLm9yZy9taWtlL3NodWZmbGUvXG5cblx0dmFyIGN1cnJlbnRJbmRleCA9IGFycmF5Lmxlbmd0aCwgdGVtcG9yYXJ5VmFsdWUsIHJhbmRvbUluZGV4O1xuXG5cdC8vIFdoaWxlIHRoZXJlIHJlbWFpbiBlbGVtZW50cyB0byBzaHVmZmxlLi4uXG5cdHdoaWxlICgwICE9PSBjdXJyZW50SW5kZXgpIHtcblxuXHRcdC8vIFBpY2sgYSByZW1haW5pbmcgZWxlbWVudC4uLlxuXHRcdHJhbmRvbUluZGV4ID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY3VycmVudEluZGV4KTtcblx0XHRjdXJyZW50SW5kZXggLT0gMTtcblxuXHRcdC8vIEFuZCBzd2FwIGl0IHdpdGggdGhlIGN1cnJlbnQgZWxlbWVudC5cblx0XHR0ZW1wb3JhcnlWYWx1ZSA9IGFycmF5W2N1cnJlbnRJbmRleF07XG5cdFx0YXJyYXlbY3VycmVudEluZGV4XSA9IGFycmF5W3JhbmRvbUluZGV4XTtcblx0XHRhcnJheVtyYW5kb21JbmRleF0gPSB0ZW1wb3JhcnlWYWx1ZTtcblx0fVxuXG5cdHJldHVybiBhcnJheTtcbn1cbiIsImltcG9ydCAkIGZyb20gJy4vZG9tJztcbmltcG9ydCB7IGZsb2F0XzIsIGFycmF5c19lcXVhbCB9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDaGFydCB7XG5cdGNvbnN0cnVjdG9yKHtcblx0XHRwYXJlbnQgPSBcIlwiLFxuXHRcdGhlaWdodCA9IDI0MCxcblxuXHRcdHRpdGxlID0gJycsIHN1YnRpdGxlID0gJycsXG5cblx0XHRkYXRhID0ge30sXG5cdFx0Zm9ybWF0X2xhbWJkYXMgPSB7fSxcblxuXHRcdHN1bW1hcnkgPSBbXSxcblxuXHRcdGlzX25hdmlnYWJsZSA9IDAsXG5cblx0XHR0eXBlID0gJydcblx0fSkge1xuXHRcdGlmKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSA9PT0gQ2hhcnQucHJvdG90eXBlKSB7XG5cdFx0XHRpZih0eXBlID09PSAnbGluZScpIHtcblx0XHRcdFx0cmV0dXJuIG5ldyBMaW5lQ2hhcnQoYXJndW1lbnRzWzBdKTtcblx0XHRcdH0gZWxzZSBpZih0eXBlID09PSAnYmFyJykge1xuXHRcdFx0XHRyZXR1cm4gbmV3IEJhckNoYXJ0KGFyZ3VtZW50c1swXSk7XG5cdFx0XHR9IGVsc2UgaWYodHlwZSA9PT0gJ3BlcmNlbnRhZ2UnKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgUGVyY2VudGFnZUNoYXJ0KGFyZ3VtZW50c1swXSk7XG5cdFx0XHR9IGVsc2UgaWYodHlwZSA9PT0gJ2hlYXRtYXAnKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgSGVhdE1hcChhcmd1bWVudHNbMF0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIG5ldyBMaW5lQ2hhcnQoYXJndW1lbnRzWzBdKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnJhd19jaGFydF9hcmdzID0gYXJndW1lbnRzWzBdO1xuXG5cdFx0dGhpcy5wYXJlbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHBhcmVudCk7XG5cdFx0dGhpcy50aXRsZSA9IHRpdGxlO1xuXHRcdHRoaXMuc3VidGl0bGUgPSBzdWJ0aXRsZTtcblxuXHRcdHRoaXMuZGF0YSA9IGRhdGE7XG5cdFx0dGhpcy5mb3JtYXRfbGFtYmRhcyA9IGZvcm1hdF9sYW1iZGFzO1xuXG5cdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMgPSBkYXRhLnNwZWNpZmljX3ZhbHVlcyB8fCBbXTtcblx0XHR0aGlzLnN1bW1hcnkgPSBzdW1tYXJ5O1xuXG5cdFx0dGhpcy5pc19uYXZpZ2FibGUgPSBpc19uYXZpZ2FibGU7XG5cdFx0aWYodGhpcy5pc19uYXZpZ2FibGUpIHtcblx0XHRcdHRoaXMuY3VycmVudF9pbmRleCA9IDA7XG5cdFx0fVxuXG5cdFx0dGhpcy5jaGFydF90eXBlcyA9IFsnbGluZScsICdiYXInLCAncGVyY2VudGFnZScsICdoZWF0bWFwJ107XG5cblx0XHR0aGlzLnNldF9tYXJnaW5zKGhlaWdodCk7XG5cdH1cblxuXHRnZXRfZGlmZmVyZW50X2NoYXJ0KHR5cGUpIHtcblx0XHRpZighdGhpcy5jaGFydF90eXBlcy5pbmNsdWRlcyh0eXBlKSkge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJyR7dHlwZX0nIGlzIG5vdCBhIHZhbGlkIGNoYXJ0IHR5cGUuYCk7XG5cdFx0fVxuXHRcdGlmKHR5cGUgPT09IHRoaXMudHlwZSkgcmV0dXJuO1xuXG5cdFx0Ly8gT25seSBhY3Jvc3MgY29tcGF0aWJsZSB0eXBlc1xuXHRcdGxldCBjb21wYXRpYmxlX3R5cGVzID0ge1xuXHRcdFx0YmFyOiBbJ2xpbmUnLCAncGVyY2VudGFnZSddLFxuXHRcdFx0bGluZTogWydiYXInLCAncGVyY2VudGFnZSddLFxuXHRcdFx0cGVyY2VudGFnZTogWydiYXInLCAnbGluZSddLFxuXHRcdFx0aGVhdG1hcDogW11cblx0XHR9O1xuXG5cdFx0aWYoIWNvbXBhdGlibGVfdHlwZXNbdGhpcy50eXBlXS5pbmNsdWRlcyh0eXBlKSkge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgJyR7dGhpcy50eXBlfScgY2hhcnQgY2Fubm90IGJlIGNvbnZlcnRlZCB0byBhICcke3R5cGV9JyBjaGFydC5gKTtcblx0XHR9XG5cblx0XHQvLyBPa2F5LCB0aGlzIGlzIGFudGljbGltYWN0aWNcblx0XHQvLyB0aGlzIGZ1bmN0aW9uIHdpbGwgbmVlZCB0byBhY3R1YWxseSBiZSAnY2hhbmdlX2NoYXJ0X3R5cGUodHlwZSknXG5cdFx0Ly8gdGhhdCB3aWxsIHVwZGF0ZSBvbmx5IHRoZSByZXF1aXJlZCBlbGVtZW50cywgYnV0IGZvciBub3cgLi4uXG5cdFx0cmV0dXJuIG5ldyBDaGFydCh7XG5cdFx0XHRwYXJlbnQ6IHRoaXMucmF3X2NoYXJ0X2FyZ3MucGFyZW50LFxuXHRcdFx0ZGF0YTogdGhpcy5yYXdfY2hhcnRfYXJncy5kYXRhLFxuXHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdGhlaWdodDogdGhpcy5yYXdfY2hhcnRfYXJncy5oZWlnaHRcblx0XHR9KTtcblx0fVxuXG5cdHNldF9tYXJnaW5zKGhlaWdodCkge1xuXHRcdHRoaXMuYmFzZV9oZWlnaHQgPSBoZWlnaHQ7XG5cdFx0dGhpcy5oZWlnaHQgPSBoZWlnaHQgLSA0MDtcblx0XHR0aGlzLnRyYW5zbGF0ZV94ID0gNjA7XG5cdFx0dGhpcy50cmFuc2xhdGVfeSA9IDEwO1xuXHR9XG5cblx0c2V0dXAoKSB7XG5cdFx0dGhpcy5iaW5kX3dpbmRvd19ldmVudHMoKTtcblx0XHR0aGlzLnJlZnJlc2godHJ1ZSk7XG5cdH1cblxuXHRiaW5kX3dpbmRvd19ldmVudHMoKSB7XG5cdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHRoaXMucmVmcmVzaCgpKTtcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb3JpZW50YXRpb25jaGFuZ2UnLCAoKSA9PiB0aGlzLnJlZnJlc2goKSk7XG5cdH1cblxuXHRyZWZyZXNoKGluaXQ9ZmFsc2UpIHtcblx0XHR0aGlzLnNldHVwX2Jhc2VfdmFsdWVzKCk7XG5cdFx0dGhpcy5zZXRfd2lkdGgoKTtcblxuXHRcdHRoaXMuc2V0dXBfY29udGFpbmVyKCk7XG5cdFx0dGhpcy5zZXR1cF9jb21wb25lbnRzKCk7XG5cblx0XHR0aGlzLnNldHVwX3ZhbHVlcygpO1xuXHRcdHRoaXMuc2V0dXBfdXRpbHMoKTtcblxuXHRcdHRoaXMubWFrZV9ncmFwaF9jb21wb25lbnRzKGluaXQpO1xuXHRcdHRoaXMubWFrZV90b29sdGlwKCk7XG5cblx0XHRpZih0aGlzLnN1bW1hcnkubGVuZ3RoID4gMCkge1xuXHRcdFx0dGhpcy5zaG93X2N1c3RvbV9zdW1tYXJ5KCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2hvd19zdW1tYXJ5KCk7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy5pc19uYXZpZ2FibGUpIHtcblx0XHRcdHRoaXMuc2V0dXBfbmF2aWdhdGlvbihpbml0KTtcblx0XHR9XG5cdH1cblxuXHRzZXRfd2lkdGgoKSB7XG5cdFx0bGV0IHNwZWNpYWxfdmFsdWVzX3dpZHRoID0gMDtcblx0XHR0aGlzLnNwZWNpZmljX3ZhbHVlcy5tYXAodmFsID0+IHtcblx0XHRcdGlmKHRoaXMuZ2V0X3N0cndpZHRoKHZhbC50aXRsZSkgPiBzcGVjaWFsX3ZhbHVlc193aWR0aCkge1xuXHRcdFx0XHRzcGVjaWFsX3ZhbHVlc193aWR0aCA9IHRoaXMuZ2V0X3N0cndpZHRoKHZhbC50aXRsZSkgLSA0MDtcblx0XHRcdH1cblx0XHR9KTtcblx0XHR0aGlzLmJhc2Vfd2lkdGggPSB0aGlzLnBhcmVudC5vZmZzZXRXaWR0aCAtIHNwZWNpYWxfdmFsdWVzX3dpZHRoO1xuXHRcdHRoaXMud2lkdGggPSB0aGlzLmJhc2Vfd2lkdGggLSB0aGlzLnRyYW5zbGF0ZV94ICogMjtcblx0fVxuXG5cdHNldHVwX2Jhc2VfdmFsdWVzKCkge31cblxuXHRzZXR1cF9jb250YWluZXIoKSB7XG5cdFx0dGhpcy5jb250YWluZXIgPSAkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0Y2xhc3NOYW1lOiAnY2hhcnQtY29udGFpbmVyJyxcblx0XHRcdGlubmVySFRNTDogYDxoNiBjbGFzcz1cInRpdGxlXCIgc3R5bGU9XCJtYXJnaW4tdG9wOiAxNXB4O1wiPiR7dGhpcy50aXRsZX08L2g2PlxuXHRcdFx0XHQ8aDYgY2xhc3M9XCJzdWItdGl0bGUgdXBwZXJjYXNlXCI+JHt0aGlzLnN1YnRpdGxlfTwvaDY+XG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJmcmFwcGUtY2hhcnQgZ3JhcGhpY3NcIj48L2Rpdj5cblx0XHRcdFx0PGRpdiBjbGFzcz1cImdyYXBoLXN0YXRzLWNvbnRhaW5lclwiPjwvZGl2PmBcblx0XHR9KTtcblxuXHRcdC8vIENoYXJ0IG5lZWRzIGEgZGVkaWNhdGVkIHBhcmVudCBlbGVtZW50XG5cdFx0dGhpcy5wYXJlbnQuaW5uZXJIVE1MID0gJyc7XG5cdFx0dGhpcy5wYXJlbnQuYXBwZW5kQ2hpbGQodGhpcy5jb250YWluZXIpO1xuXG5cdFx0dGhpcy5jaGFydF93cmFwcGVyID0gdGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvcignLmZyYXBwZS1jaGFydCcpO1xuXHRcdHRoaXMuc3RhdHNfd3JhcHBlciA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5ncmFwaC1zdGF0cy1jb250YWluZXInKTtcblxuXHRcdHRoaXMubWFrZV9jaGFydF9hcmVhKCk7XG5cdFx0dGhpcy5tYWtlX2RyYXdfYXJlYSgpO1xuXHR9XG5cblx0bWFrZV9jaGFydF9hcmVhKCkge1xuXHRcdHRoaXMuc3ZnID0gJC5jcmVhdGVTVkcoJ3N2ZycsIHtcblx0XHRcdGNsYXNzTmFtZTogJ2NoYXJ0Jyxcblx0XHRcdGluc2lkZTogdGhpcy5jaGFydF93cmFwcGVyLFxuXHRcdFx0d2lkdGg6IHRoaXMuYmFzZV93aWR0aCxcblx0XHRcdGhlaWdodDogdGhpcy5iYXNlX2hlaWdodFxuXHRcdH0pO1xuXG5cdFx0dGhpcy5zdmdfZGVmcyA9ICQuY3JlYXRlU1ZHKCdkZWZzJywge1xuXHRcdFx0aW5zaWRlOiB0aGlzLnN2Zyxcblx0XHR9KTtcblxuXHRcdHJldHVybiB0aGlzLnN2Zztcblx0fVxuXG5cdG1ha2VfZHJhd19hcmVhKCkge1xuXHRcdHRoaXMuZHJhd19hcmVhID0gJC5jcmVhdGVTVkcoXCJnXCIsIHtcblx0XHRcdGNsYXNzTmFtZTogdGhpcy50eXBlICsgJy1jaGFydCcsXG5cdFx0XHRpbnNpZGU6IHRoaXMuc3ZnLFxuXHRcdFx0dHJhbnNmb3JtOiBgdHJhbnNsYXRlKCR7dGhpcy50cmFuc2xhdGVfeH0sICR7dGhpcy50cmFuc2xhdGVfeX0pYFxuXHRcdH0pO1xuXHR9XG5cblx0c2V0dXBfY29tcG9uZW50cygpIHsgfVxuXG5cdG1ha2VfdG9vbHRpcCgpIHtcblx0XHR0aGlzLnRpcCA9IG5ldyBTdmdUaXAoe1xuXHRcdFx0cGFyZW50OiB0aGlzLmNoYXJ0X3dyYXBwZXIsXG5cdFx0fSk7XG5cdFx0dGhpcy5iaW5kX3Rvb2x0aXAoKTtcblx0fVxuXG5cblx0c2hvd19zdW1tYXJ5KCkge31cblx0c2hvd19jdXN0b21fc3VtbWFyeSgpIHtcblx0XHR0aGlzLnN1bW1hcnkubWFwKGQgPT4ge1xuXHRcdFx0bGV0IHN0YXRzID0gJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAnc3RhdHMnLFxuXHRcdFx0XHRpbm5lckhUTUw6IGA8c3BhbiBjbGFzcz1cImluZGljYXRvciAke2QuY29sb3J9XCI+JHtkLnRpdGxlfTogJHtkLnZhbHVlfTwvc3Bhbj5gXG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuc3RhdHNfd3JhcHBlci5hcHBlbmRDaGlsZChzdGF0cyk7XG5cdFx0fSk7XG5cdH1cblxuXHRzZXR1cF9uYXZpZ2F0aW9uKGluaXQ9ZmFsc2UpIHtcblx0XHR0aGlzLm1ha2Vfb3ZlcmxheSgpO1xuXG5cdFx0aWYoaW5pdCkge1xuXHRcdFx0dGhpcy5iaW5kX292ZXJsYXkoKTtcblxuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlKSA9PiB7XG5cdFx0XHRcdGlmKCQuaXNFbGVtZW50SW5WaWV3cG9ydCh0aGlzLmNoYXJ0X3dyYXBwZXIpKSB7XG5cdFx0XHRcdFx0ZSA9IGUgfHwgd2luZG93LmV2ZW50O1xuXG5cdFx0XHRcdFx0aWYgKGUua2V5Q29kZSA9PSAnMzcnKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9uX2xlZnRfYXJyb3coKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGUua2V5Q29kZSA9PSAnMzknKSB7XG5cdFx0XHRcdFx0XHR0aGlzLm9uX3JpZ2h0X2Fycm93KCk7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChlLmtleUNvZGUgPT0gJzM4Jykge1xuXHRcdFx0XHRcdFx0dGhpcy5vbl91cF9hcnJvdygpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZS5rZXlDb2RlID09ICc0MCcpIHtcblx0XHRcdFx0XHRcdHRoaXMub25fZG93bl9hcnJvdygpO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZS5rZXlDb2RlID09ICcxMycpIHtcblx0XHRcdFx0XHRcdHRoaXMub25fZW50ZXJfa2V5KCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHRtYWtlX292ZXJsYXkoKSB7fVxuXHRiaW5kX292ZXJsYXkoKSB7fVxuXG5cdG9uX2xlZnRfYXJyb3coKSB7fVxuXHRvbl9yaWdodF9hcnJvdygpIHt9XG5cdG9uX3VwX2Fycm93KCkge31cblx0b25fZG93bl9hcnJvdygpIHt9XG5cdG9uX2VudGVyX2tleSgpIHt9XG5cblx0Z2V0X2RhdGFfcG9pbnQoaW5kZXg9dGhpcy5jdXJyZW50X2luZGV4KSB7XG5cdFx0Ly8gY2hlY2sgZm9yIGxlbmd0aFxuXHRcdGxldCBkYXRhX3BvaW50ID0ge1xuXHRcdFx0aW5kZXg6IGluZGV4XG5cdFx0fTtcblx0XHRsZXQgeSA9IHRoaXMueVswXTtcblx0XHRbJ3N2Z191bml0cycsICd5X3RvcHMnLCAndmFsdWVzJ10ubWFwKGtleSA9PiB7XG5cdFx0XHRsZXQgZGF0YV9rZXkgPSBrZXkuc2xpY2UoMCwga2V5Lmxlbmd0aC0xKTtcblx0XHRcdGRhdGFfcG9pbnRbZGF0YV9rZXldID0geVtrZXldW2luZGV4XTtcblx0XHR9KTtcblx0XHRkYXRhX3BvaW50LmxhYmVsID0gdGhpcy54W2luZGV4XTtcblx0XHRyZXR1cm4gZGF0YV9wb2ludDtcblx0fVxuXG5cdHVwZGF0ZV9jdXJyZW50X2RhdGFfcG9pbnQoaW5kZXgpIHtcblx0XHRpZihpbmRleCA8IDApIGluZGV4ID0gMDtcblx0XHRpZihpbmRleCA+PSB0aGlzLngubGVuZ3RoKSBpbmRleCA9IHRoaXMueC5sZW5ndGggLSAxO1xuXHRcdGlmKGluZGV4ID09PSB0aGlzLmN1cnJlbnRfaW5kZXgpIHJldHVybjtcblx0XHR0aGlzLmN1cnJlbnRfaW5kZXggPSBpbmRleDtcblx0XHQkLmZpcmUodGhpcy5wYXJlbnQsIFwiZGF0YS1zZWxlY3RcIiwgdGhpcy5nZXRfZGF0YV9wb2ludCgpKTtcblx0fVxuXG5cdC8vIEhlbHBlcnNcblx0Z2V0X3N0cndpZHRoKHN0cmluZykge1xuXHRcdHJldHVybiBzdHJpbmcubGVuZ3RoICogODtcblx0fVxuXG5cdC8vIE9iamVjdHNcblx0c2V0dXBfdXRpbHMoKSB7IH1cbn1cblxuY2xhc3MgQXhpc0NoYXJ0IGV4dGVuZHMgQ2hhcnQge1xuXHRjb25zdHJ1Y3RvcihhcmdzKSB7XG5cdFx0c3VwZXIoYXJncyk7XG5cblx0XHR0aGlzLnggPSB0aGlzLmRhdGEubGFiZWxzO1xuXHRcdHRoaXMueSA9IHRoaXMuZGF0YS5kYXRhc2V0cztcblxuXHRcdHRoaXMuZ2V0X3lfbGFiZWwgPSB0aGlzLmZvcm1hdF9sYW1iZGFzLnlfbGFiZWw7XG5cdFx0dGhpcy5nZXRfeV90b29sdGlwID0gdGhpcy5mb3JtYXRfbGFtYmRhcy55X3Rvb2x0aXA7XG5cdFx0dGhpcy5nZXRfeF90b29sdGlwID0gdGhpcy5mb3JtYXRfbGFtYmRhcy54X3Rvb2x0aXA7XG5cblx0XHR0aGlzLmNvbG9ycyA9IFsnZ3JlZW4nLCAnYmx1ZScsICd2aW9sZXQnLCAncmVkJywgJ29yYW5nZScsXG5cdFx0XHQneWVsbG93JywgJ2xpZ2h0LWJsdWUnLCAnbGlnaHQtZ3JlZW4nLCAncHVycGxlJywgJ21hZ2VudGEnXTtcblxuXHRcdHRoaXMuemVyb19saW5lID0gdGhpcy5oZWlnaHQ7XG5cdH1cblxuXHRzZXR1cF92YWx1ZXMoKSB7XG5cdFx0dGhpcy5kYXRhLmRhdGFzZXRzLm1hcChkID0+IHtcblx0XHRcdGQudmFsdWVzID0gZC52YWx1ZXMubWFwKHZhbCA9PiAoIWlzTmFOKHZhbCkgPyB2YWwgOiAwKSk7XG5cdFx0fSk7XG5cdFx0dGhpcy5zZXR1cF94KCk7XG5cdFx0dGhpcy5zZXR1cF95KCk7XG5cdH1cblxuXHRzZXR1cF94KCkge1xuXHRcdHRoaXMuc2V0X2F2Z191bml0X3dpZHRoX2FuZF94X29mZnNldCgpO1xuXG5cdFx0aWYodGhpcy54X2F4aXNfcG9zaXRpb25zKSB7XG5cdFx0XHR0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zID0gIHRoaXMueF9heGlzX3Bvc2l0aW9ucy5zbGljZSgpO1xuXHRcdH1cblx0XHR0aGlzLnhfYXhpc19wb3NpdGlvbnMgPSB0aGlzLngubWFwKChkLCBpKSA9PlxuXHRcdFx0ZmxvYXRfMih0aGlzLnhfb2Zmc2V0ICsgaSAqIHRoaXMuYXZnX3VuaXRfd2lkdGgpKTtcblxuXHRcdGlmKCF0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zKSB7XG5cdFx0XHR0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zID0gdGhpcy54X2F4aXNfcG9zaXRpb25zLnNsaWNlKCk7XG5cdFx0fVxuXHR9XG5cblx0c2V0dXBfeSgpIHtcblx0XHRpZih0aGlzLnlfYXhpc192YWx1ZXMpIHtcblx0XHRcdHRoaXMueV9vbGRfYXhpc192YWx1ZXMgPSAgdGhpcy55X2F4aXNfdmFsdWVzLnNsaWNlKCk7XG5cdFx0fVxuXG5cdFx0bGV0IHZhbHVlcyA9IHRoaXMuZ2V0X2FsbF95X3ZhbHVlcygpO1xuXG5cdFx0aWYodGhpcy55X3N1bXMgJiYgdGhpcy55X3N1bXMubGVuZ3RoID4gMCkge1xuXHRcdFx0dmFsdWVzID0gdmFsdWVzLmNvbmNhdCh0aGlzLnlfc3Vtcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy55X2F4aXNfdmFsdWVzID0gdGhpcy5nZXRfeV9heGlzX3BvaW50cyh2YWx1ZXMpO1xuXG5cdFx0aWYoIXRoaXMueV9vbGRfYXhpc192YWx1ZXMpIHtcblx0XHRcdHRoaXMueV9vbGRfYXhpc192YWx1ZXMgPSB0aGlzLnlfYXhpc192YWx1ZXMuc2xpY2UoKTtcblx0XHR9XG5cblx0XHRjb25zdCB5X3B0cyA9IHRoaXMueV9heGlzX3ZhbHVlcztcblx0XHRjb25zdCB2YWx1ZV9yYW5nZSA9IHlfcHRzW3lfcHRzLmxlbmd0aC0xXSAtIHlfcHRzWzBdO1xuXG5cdFx0aWYodGhpcy5tdWx0aXBsaWVyKSB0aGlzLm9sZF9tdWx0aXBsaWVyID0gdGhpcy5tdWx0aXBsaWVyO1xuXHRcdHRoaXMubXVsdGlwbGllciA9IHRoaXMuaGVpZ2h0IC8gdmFsdWVfcmFuZ2U7XG5cdFx0aWYoIXRoaXMub2xkX211bHRpcGxpZXIpIHRoaXMub2xkX211bHRpcGxpZXIgPSB0aGlzLm11bHRpcGxpZXI7XG5cblx0XHRjb25zdCB6ZXJvX2luZGV4ID0geV9wdHMuaW5kZXhPZigwKTtcblx0XHRjb25zdCBpbnRlcnZhbCA9IHlfcHRzWzFdIC0geV9wdHNbMF07XG5cdFx0Y29uc3QgaW50ZXJ2YWxfaGVpZ2h0ID0gaW50ZXJ2YWwgKiB0aGlzLm11bHRpcGxpZXI7XG5cblx0XHRpZih0aGlzLnplcm9fbGluZSkgdGhpcy5vbGRfemVyb19saW5lID0gdGhpcy56ZXJvX2xpbmU7XG5cdFx0dGhpcy56ZXJvX2xpbmUgPSB0aGlzLmhlaWdodCAtICh6ZXJvX2luZGV4ICogaW50ZXJ2YWxfaGVpZ2h0KTtcblx0XHRpZighdGhpcy5vbGRfemVyb19saW5lKSB0aGlzLm9sZF96ZXJvX2xpbmUgPSB0aGlzLnplcm9fbGluZTtcblx0fVxuXG5cdHNldHVwX2NvbXBvbmVudHMoKSB7XG5cdFx0c3VwZXIuc2V0dXBfY29tcG9uZW50cygpO1xuXHRcdHRoaXMuc2V0dXBfbWFya2VyX2NvbXBvbmVudHMoKTtcblx0XHR0aGlzLnNldHVwX2FnZ3JlZ2F0aW9uX2NvbXBvbmVudHMoKTtcblx0XHR0aGlzLnNldHVwX2dyYXBoX2NvbXBvbmVudHMoKTtcblx0fVxuXG5cdHNldHVwX21hcmtlcl9jb21wb25lbnRzKCkge1xuXHRcdHRoaXMueV9heGlzX2dyb3VwID0gJC5jcmVhdGVTVkcoJ2cnLCB7Y2xhc3NOYW1lOiAneSBheGlzJywgaW5zaWRlOiB0aGlzLmRyYXdfYXJlYX0pO1xuXHRcdHRoaXMueF9heGlzX2dyb3VwID0gJC5jcmVhdGVTVkcoJ2cnLCB7Y2xhc3NOYW1lOiAneCBheGlzJywgaW5zaWRlOiB0aGlzLmRyYXdfYXJlYX0pO1xuXHRcdHRoaXMuc3BlY2lmaWNfeV9ncm91cCA9ICQuY3JlYXRlU1ZHKCdnJywge2NsYXNzTmFtZTogJ3NwZWNpZmljIGF4aXMnLCBpbnNpZGU6IHRoaXMuZHJhd19hcmVhfSk7XG5cdH1cblxuXHRzZXR1cF9hZ2dyZWdhdGlvbl9jb21wb25lbnRzKCkge1xuXHRcdHRoaXMuc3VtX2dyb3VwID0gJC5jcmVhdGVTVkcoJ2cnLCB7Y2xhc3NOYW1lOiAnZGF0YS1wb2ludHMnLCBpbnNpZGU6IHRoaXMuZHJhd19hcmVhfSk7XG5cdFx0dGhpcy5hdmVyYWdlX2dyb3VwID0gJC5jcmVhdGVTVkcoJ2cnLCB7Y2xhc3NOYW1lOiAnY2hhcnQtYXJlYScsIGluc2lkZTogdGhpcy5kcmF3X2FyZWF9KTtcblx0fVxuXG5cdHNldHVwX2dyYXBoX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5zdmdfdW5pdHNfZ3JvdXBzID0gW107XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0dGhpcy5zdmdfdW5pdHNfZ3JvdXBzW2ldID0gJC5jcmVhdGVTVkcoJ2cnLCB7XG5cdFx0XHRcdGNsYXNzTmFtZTogJ2RhdGEtcG9pbnRzIGRhdGEtcG9pbnRzLScgKyBpLFxuXHRcdFx0XHRpbnNpZGU6IHRoaXMuZHJhd19hcmVhXG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfZ3JhcGhfY29tcG9uZW50cyhpbml0PWZhbHNlKSB7XG5cdFx0dGhpcy5tYWtlX3lfYXhpcygpO1xuXHRcdHRoaXMubWFrZV94X2F4aXMoKTtcblx0XHR0aGlzLmRyYXdfZ3JhcGgoaW5pdCk7XG5cdFx0dGhpcy5tYWtlX3lfc3BlY2lmaWNzKCk7XG5cdH1cblxuXHQvLyBtYWtlIFZFUlRJQ0FMIGxpbmVzIGZvciB4IHZhbHVlc1xuXHRtYWtlX3hfYXhpcyhhbmltYXRlPWZhbHNlKSB7XG5cdFx0bGV0IHN0YXJ0X2F0LCBoZWlnaHQsIHRleHRfc3RhcnRfYXQsIGF4aXNfbGluZV9jbGFzcyA9ICcnO1xuXHRcdGlmKHRoaXMueF9heGlzX21vZGUgPT09ICdzcGFuJykge1x0XHQvLyBsb25nIHNwYW5uaW5nIGxpbmVzXG5cdFx0XHRzdGFydF9hdCA9IC03O1xuXHRcdFx0aGVpZ2h0ID0gdGhpcy5oZWlnaHQgKyAxNTtcblx0XHRcdHRleHRfc3RhcnRfYXQgPSB0aGlzLmhlaWdodCArIDI1O1xuXHRcdH0gZWxzZSBpZih0aGlzLnhfYXhpc19tb2RlID09PSAndGljaycpe1x0Ly8gc2hvcnQgbGFiZWwgbGluZXNcblx0XHRcdHN0YXJ0X2F0ID0gdGhpcy5oZWlnaHQ7XG5cdFx0XHRoZWlnaHQgPSA2O1xuXHRcdFx0dGV4dF9zdGFydF9hdCA9IDk7XG5cdFx0XHRheGlzX2xpbmVfY2xhc3MgPSAneC1heGlzLWxhYmVsJztcblx0XHR9XG5cblx0XHR0aGlzLnhfYXhpc19ncm91cC5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoMCwke3N0YXJ0X2F0fSlgKTtcblxuXHRcdGlmKGFuaW1hdGUpIHtcblx0XHRcdHRoaXMubWFrZV9hbmltX3hfYXhpcyhoZWlnaHQsIHRleHRfc3RhcnRfYXQsIGF4aXNfbGluZV9jbGFzcyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy54X2F4aXNfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLngubWFwKChwb2ludCwgaSkgPT4ge1xuXHRcdFx0dGhpcy54X2F4aXNfZ3JvdXAuYXBwZW5kQ2hpbGQoXG5cdFx0XHRcdHRoaXMubWFrZV94X2xpbmUoXG5cdFx0XHRcdFx0aGVpZ2h0LFxuXHRcdFx0XHRcdHRleHRfc3RhcnRfYXQsXG5cdFx0XHRcdFx0cG9pbnQsXG5cdFx0XHRcdFx0J3gtdmFsdWUtdGV4dCcsXG5cdFx0XHRcdFx0YXhpc19saW5lX2NsYXNzLFxuXHRcdFx0XHRcdHRoaXMueF9heGlzX3Bvc2l0aW9uc1tpXVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0Ly8gbWFrZSBIT1JJWk9OVEFMIGxpbmVzIGZvciB5IHZhbHVlc1xuXHRtYWtlX3lfYXhpcyhhbmltYXRlPWZhbHNlKSB7XG5cdFx0aWYoYW5pbWF0ZSkge1xuXHRcdFx0dGhpcy5tYWtlX2FuaW1feV9heGlzKCk7XG5cdFx0XHR0aGlzLm1ha2VfYW5pbV95X3NwZWNpZmljcygpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGxldCBbd2lkdGgsIHRleHRfZW5kX2F0LCBheGlzX2xpbmVfY2xhc3MsIHN0YXJ0X2F0XSA9IHRoaXMuZ2V0X3lfYXhpc19saW5lX3Byb3BzKCk7XG5cblx0XHR0aGlzLnlfYXhpc19ncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdHRoaXMueV9heGlzX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHR0aGlzLnlfYXhpc19ncm91cC5hcHBlbmRDaGlsZChcblx0XHRcdFx0dGhpcy5tYWtlX3lfbGluZShcblx0XHRcdFx0XHRzdGFydF9hdCxcblx0XHRcdFx0XHR3aWR0aCxcblx0XHRcdFx0XHR0ZXh0X2VuZF9hdCxcblx0XHRcdFx0XHR2YWx1ZSxcblx0XHRcdFx0XHQneS12YWx1ZS10ZXh0Jyxcblx0XHRcdFx0XHRheGlzX2xpbmVfY2xhc3MsXG5cdFx0XHRcdFx0dGhpcy56ZXJvX2xpbmUgLSB2YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0XHQodmFsdWUgPT09IDAgJiYgaSAhPT0gMCkgLy8gTm9uLWZpcnN0IFplcm8gbGluZVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0Z2V0X3lfYXhpc19saW5lX3Byb3BzKHNwZWNpZmljPWZhbHNlKSB7XG5cdFx0aWYoc3BlY2lmaWMpIHtcblx0XHRcdHJldHVyblt0aGlzLndpZHRoLCB0aGlzLndpZHRoICsgNSwgJ3NwZWNpZmljLXZhbHVlJywgMF07XG5cdFx0fVxuXHRcdGxldCB3aWR0aCwgdGV4dF9lbmRfYXQgPSAtOSwgYXhpc19saW5lX2NsYXNzID0gJycsIHN0YXJ0X2F0ID0gMDtcblx0XHRpZih0aGlzLnlfYXhpc19tb2RlID09PSAnc3BhbicpIHtcdFx0Ly8gbG9uZyBzcGFubmluZyBsaW5lc1xuXHRcdFx0d2lkdGggPSB0aGlzLndpZHRoICsgNjtcblx0XHRcdHN0YXJ0X2F0ID0gLTY7XG5cdFx0fSBlbHNlIGlmKHRoaXMueV9heGlzX21vZGUgPT09ICd0aWNrJyl7XHQvLyBzaG9ydCBsYWJlbCBsaW5lc1xuXHRcdFx0d2lkdGggPSAtNjtcblx0XHRcdGF4aXNfbGluZV9jbGFzcyA9ICd5LWF4aXMtbGFiZWwnO1xuXHRcdH1cblxuXHRcdHJldHVybiBbd2lkdGgsIHRleHRfZW5kX2F0LCBheGlzX2xpbmVfY2xhc3MsIHN0YXJ0X2F0XTtcblx0fVxuXG5cdGRyYXdfZ3JhcGgoaW5pdD1mYWxzZSkge1xuXHRcdGlmKGluaXQpIHtcblx0XHRcdHRoaXMuZHJhd19uZXdfZ3JhcGhfYW5kX2FuaW1hdGUoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0ZC5zdmdfdW5pdHMgPSBbXTtcblx0XHRcdHRoaXMubWFrZV9wYXRoICYmIHRoaXMubWFrZV9wYXRoKGQsIGksIHRoaXMueF9heGlzX3Bvc2l0aW9ucywgZC55X3RvcHMsIGQuY29sb3IgfHwgdGhpcy5jb2xvcnNbaV0pO1xuXHRcdFx0dGhpcy5tYWtlX25ld191bml0cyhkLCBpKTtcblx0XHR9KTtcblx0fVxuXG5cdGRyYXdfbmV3X2dyYXBoX2FuZF9hbmltYXRlKCkge1xuXHRcdGxldCBkYXRhID0gW107XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0Ly8gQW5pbTogRG9uJ3QgZHJhdyBpbml0aWFsIHZhbHVlcywgc3RvcmUgdGhlbSBhbmQgdXBkYXRlIGxhdGVyXG5cdFx0XHRkLnlfdG9wcyA9IG5ldyBBcnJheShkLnZhbHVlcy5sZW5ndGgpLmZpbGwodGhpcy56ZXJvX2xpbmUpOyAvLyBubyB2YWx1ZVxuXHRcdFx0ZGF0YS5wdXNoKHt2YWx1ZXM6IGQudmFsdWVzfSk7XG5cdFx0XHRkLnN2Z191bml0cyA9IFtdO1xuXG5cdFx0XHR0aGlzLm1ha2VfcGF0aCAmJiB0aGlzLm1ha2VfcGF0aChkLCBpLCB0aGlzLnhfYXhpc19wb3NpdGlvbnMsIGQueV90b3BzLCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblx0XHRcdHRoaXMubWFrZV9uZXdfdW5pdHMoZCwgaSk7XG5cdFx0fSk7XG5cblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdHRoaXMudXBkYXRlX3ZhbHVlcyhkYXRhKTtcblx0XHR9LCAzNTApO1xuXHR9XG5cblx0c2V0dXBfbmF2aWdhdGlvbihpbml0KSB7XG5cdFx0Ly8gSGFjazogZGVmZXIgbmF2IHRpbGwgaW5pdGlhbCB1cGRhdGVfdmFsdWVzXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRzdXBlci5zZXR1cF9uYXZpZ2F0aW9uKGluaXQpO1xuXHRcdH0sIDUwMCk7XG5cdH1cblxuXHRtYWtlX25ld191bml0cyhkLCBpKSB7XG5cdFx0dGhpcy5tYWtlX25ld191bml0c19mb3JfZGF0YXNldChcblx0XHRcdHRoaXMueF9heGlzX3Bvc2l0aW9ucyxcblx0XHRcdGQueV90b3BzLFxuXHRcdFx0ZC5jb2xvciB8fCB0aGlzLmNvbG9yc1tpXSxcblx0XHRcdGksXG5cdFx0XHR0aGlzLnkubGVuZ3RoXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfbmV3X3VuaXRzX2Zvcl9kYXRhc2V0KHhfdmFsdWVzLCB5X3ZhbHVlcywgY29sb3IsIGRhdGFzZXRfaW5kZXgsIG5vX29mX2RhdGFzZXRzLCBncm91cCwgYXJyYXksIHVuaXQpIHtcblx0XHRpZighZ3JvdXApIGdyb3VwID0gdGhpcy5zdmdfdW5pdHNfZ3JvdXBzW2RhdGFzZXRfaW5kZXhdO1xuXHRcdGlmKCFhcnJheSkgYXJyYXkgPSB0aGlzLnlbZGF0YXNldF9pbmRleF0uc3ZnX3VuaXRzO1xuXHRcdGlmKCF1bml0KSB1bml0ID0gdGhpcy51bml0X2FyZ3M7XG5cblx0XHRncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdGFycmF5Lmxlbmd0aCA9IDA7XG5cblx0XHR5X3ZhbHVlcy5tYXAoKHksIGkpID0+IHtcblx0XHRcdGxldCBkYXRhX3VuaXQgPSB0aGlzLmRyYXdbdW5pdC50eXBlXShcblx0XHRcdFx0eF92YWx1ZXNbaV0sXG5cdFx0XHRcdHksXG5cdFx0XHRcdHVuaXQuYXJncyxcblx0XHRcdFx0Y29sb3IsXG5cdFx0XHRcdGRhdGFzZXRfaW5kZXgsXG5cdFx0XHRcdG5vX29mX2RhdGFzZXRzXG5cdFx0XHQpO1xuXHRcdFx0Z3JvdXAuYXBwZW5kQ2hpbGQoZGF0YV91bml0KTtcblx0XHRcdGFycmF5LnB1c2goZGF0YV91bml0KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfeV9zcGVjaWZpY3MoKSB7XG5cdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLnRleHRDb250ZW50ID0gJyc7XG5cdFx0dGhpcy5zcGVjaWZpY192YWx1ZXMubWFwKGQgPT4ge1xuXHRcdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLmFwcGVuZENoaWxkKFxuXHRcdFx0XHR0aGlzLm1ha2VfeV9saW5lKFxuXHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0dGhpcy53aWR0aCxcblx0XHRcdFx0XHR0aGlzLndpZHRoICsgNSxcblx0XHRcdFx0XHRkLnRpdGxlLnRvVXBwZXJDYXNlKCksXG5cdFx0XHRcdFx0J3NwZWNpZmljLXZhbHVlJyxcblx0XHRcdFx0XHQnc3BlY2lmaWMtdmFsdWUnLFxuXHRcdFx0XHRcdHRoaXMuemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0XHRmYWxzZSxcblx0XHRcdFx0XHRkLmxpbmVfdHlwZVxuXHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0YmluZF90b29sdGlwKCkge1xuXHRcdC8vIFRPRE86IGNvdWxkIGJlIGluIHRvb2x0aXAgaXRzZWxmLCBhcyBpdCBpcyBhIGdpdmVuIGZ1bmN0aW9uYWxpdHkgZm9yIGl0cyBwYXJlbnRcblx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgKGUpID0+IHtcblx0XHRcdGxldCBvZmZzZXQgPSAkLm9mZnNldCh0aGlzLmNoYXJ0X3dyYXBwZXIpO1xuXHRcdFx0bGV0IHJlbFggPSBlLnBhZ2VYIC0gb2Zmc2V0LmxlZnQgLSB0aGlzLnRyYW5zbGF0ZV94O1xuXHRcdFx0bGV0IHJlbFkgPSBlLnBhZ2VZIC0gb2Zmc2V0LnRvcCAtIHRoaXMudHJhbnNsYXRlX3k7XG5cblx0XHRcdGlmKHJlbFkgPCB0aGlzLmhlaWdodCArIHRoaXMudHJhbnNsYXRlX3kgKiAyKSB7XG5cdFx0XHRcdHRoaXMubWFwX3Rvb2x0aXBfeF9wb3NpdGlvbl9hbmRfc2hvdyhyZWxYKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMudGlwLmhpZGVfdGlwKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRtYXBfdG9vbHRpcF94X3Bvc2l0aW9uX2FuZF9zaG93KHJlbFgpIHtcblx0XHRmb3IodmFyIGk9dGhpcy54X2F4aXNfcG9zaXRpb25zLmxlbmd0aCAtIDE7IGkgPj0gMCA7IGktLSkge1xuXHRcdFx0bGV0IHhfdmFsID0gdGhpcy54X2F4aXNfcG9zaXRpb25zW2ldO1xuXHRcdFx0Ly8gbGV0IGRlbHRhID0gaSA9PT0gMCA/IHRoaXMuYXZnX3VuaXRfd2lkdGggOiB4X3ZhbCAtIHRoaXMueF9heGlzX3Bvc2l0aW9uc1tpLTFdO1xuXHRcdFx0aWYocmVsWCA+IHhfdmFsIC0gdGhpcy5hdmdfdW5pdF93aWR0aC8yKSB7XG5cdFx0XHRcdGxldCB4ID0geF92YWwgKyB0aGlzLnRyYW5zbGF0ZV94O1xuXHRcdFx0XHRsZXQgeSA9IHRoaXMueV9taW5fdG9wc1tpXSArIHRoaXMudHJhbnNsYXRlX3k7XG5cblx0XHRcdFx0bGV0IHRpdGxlID0gdGhpcy54LmZvcm1hdHRlZCAmJiB0aGlzLnguZm9ybWF0dGVkLmxlbmd0aD4wXG5cdFx0XHRcdFx0PyB0aGlzLnguZm9ybWF0dGVkW2ldIDogdGhpcy54W2ldO1xuXHRcdFx0XHRsZXQgdmFsdWVzID0gdGhpcy55Lm1hcCgoc2V0LCBqKSA9PiB7XG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdHRpdGxlOiBzZXQudGl0bGUsXG5cdFx0XHRcdFx0XHR2YWx1ZTogc2V0LmZvcm1hdHRlZCA/IHNldC5mb3JtYXR0ZWRbaV0gOiBzZXQudmFsdWVzW2ldLFxuXHRcdFx0XHRcdFx0Y29sb3I6IHNldC5jb2xvciB8fCB0aGlzLmNvbG9yc1tqXSxcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQvLyBUT0RPOiB1cHNpZGUtZG93biB0b29sdGlwcyBmb3IgbmVnYXRpdmUgdmFsdWVzP1xuXHRcdFx0XHR0aGlzLnRpcC5zZXRfdmFsdWVzKHgsIHksIHRpdGxlLCAnJywgdmFsdWVzKTtcblx0XHRcdFx0dGhpcy50aXAuc2hvd190aXAoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQVBJXG5cdHNob3dfc3VtcygpIHtcblx0XHR0aGlzLnVwZGF0aW5nID0gdHJ1ZTtcblxuXHRcdHRoaXMueV9zdW1zID0gbmV3IEFycmF5KHRoaXMueF9heGlzX3Bvc2l0aW9ucy5sZW5ndGgpLmZpbGwoMCk7XG5cdFx0dGhpcy55Lm1hcChkID0+IHtcblx0XHRcdGQudmFsdWVzLm1hcCggKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRcdHRoaXMueV9zdW1zW2ldICs9IHZhbHVlO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHQvLyBSZW1ha2UgeSBheGlzLCBhbmltYXRlXG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKCk7XG5cblx0XHQvLyBUaGVuIG1ha2Ugc3VtIHVuaXRzLCBkb24ndCBhbmltYXRlXG5cdFx0dGhpcy5zdW1fdW5pdHMgPSBbXTtcblxuXHRcdHRoaXMubWFrZV9uZXdfdW5pdHNfZm9yX2RhdGFzZXQoXG5cdFx0XHR0aGlzLnhfYXhpc19wb3NpdGlvbnMsXG5cdFx0XHR0aGlzLnlfc3Vtcy5tYXAoIHZhbCA9PiBmbG9hdF8yKHRoaXMuemVyb19saW5lIC0gdmFsICogdGhpcy5tdWx0aXBsaWVyKSksXG5cdFx0XHQnbGlnaHQtZ3JleScsXG5cdFx0XHQwLFxuXHRcdFx0MSxcblx0XHRcdHRoaXMuc3VtX2dyb3VwLFxuXHRcdFx0dGhpcy5zdW1fdW5pdHNcblx0XHQpO1xuXG5cdFx0Ly8gdGhpcy5tYWtlX3BhdGggJiYgdGhpcy5tYWtlX3BhdGgoZCwgaSwgb2xkX3gsIG9sZF95LCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblxuXHRcdHRoaXMudXBkYXRpbmcgPSBmYWxzZTtcblx0fVxuXG5cdGhpZGVfc3VtcygpIHtcblx0XHRpZih0aGlzLnVwZGF0aW5nKSByZXR1cm47XG5cdFx0dGhpcy55X3N1bXMgPSBbXTtcblx0XHR0aGlzLnN1bV9ncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdHRoaXMuc3VtX3VuaXRzID0gW107XG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKCk7XG5cdH1cblxuXHRzaG93X2F2ZXJhZ2UoKSB7XG5cdFx0dGhpcy5vbGRfc3BlY2lmaWNfdmFsdWVzID0gdGhpcy5zcGVjaWZpY192YWx1ZXMuc2xpY2UoKTtcblx0XHR0aGlzLnkubWFwKChkLCBpKSA9PiB7XG5cdFx0XHRsZXQgc3VtID0gMDtcblx0XHRcdGQudmFsdWVzLm1hcChlID0+IHtzdW0rPWU7fSk7XG5cdFx0XHRsZXQgYXZlcmFnZSA9IHN1bS9kLnZhbHVlcy5sZW5ndGg7XG5cblx0XHRcdHRoaXMuc3BlY2lmaWNfdmFsdWVzLnB1c2goe1xuXHRcdFx0XHR0aXRsZTogXCJBVkdcIiArIFwiIFwiICsgKGkrMSksXG5cdFx0XHRcdGxpbmVfdHlwZTogXCJkYXNoZWRcIixcblx0XHRcdFx0dmFsdWU6IGF2ZXJhZ2UsXG5cdFx0XHRcdGF1dG86IDFcblx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKCk7XG5cdH1cblxuXHRoaWRlX2F2ZXJhZ2UoKSB7XG5cdFx0dGhpcy5vbGRfc3BlY2lmaWNfdmFsdWVzID0gdGhpcy5zcGVjaWZpY192YWx1ZXMuc2xpY2UoKTtcblxuXHRcdGxldCBpbmRpY2VzX3RvX3JlbW92ZSA9IFtdO1xuXHRcdHRoaXMuc3BlY2lmaWNfdmFsdWVzLm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0aWYoZC5hdXRvKSBpbmRpY2VzX3RvX3JlbW92ZS51bnNoaWZ0KGkpO1xuXHRcdH0pO1xuXG5cdFx0aW5kaWNlc190b19yZW1vdmUubWFwKGluZGV4ID0+IHtcblx0XHRcdHRoaXMuc3BlY2lmaWNfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLnVwZGF0ZV92YWx1ZXMoKTtcblx0fVxuXG5cdHVwZGF0ZV92YWx1ZXMobmV3X3ksIG5ld194KSB7XG5cdFx0aWYoIW5ld194KSB7XG5cdFx0XHRuZXdfeCA9IHRoaXMueDtcblx0XHR9XG5cdFx0dGhpcy5lbGVtZW50c190b19hbmltYXRlID0gW107XG5cdFx0dGhpcy51cGRhdGluZyA9IHRydWU7XG5cblx0XHR0aGlzLm9sZF94X3ZhbHVlcyA9IHRoaXMueC5zbGljZSgpO1xuXHRcdHRoaXMub2xkX3lfYXhpc190b3BzID0gdGhpcy55Lm1hcChkID0+IGQueV90b3BzLnNsaWNlKCkpO1xuXG5cdFx0dGhpcy5vbGRfeV92YWx1ZXMgPSB0aGlzLnkubWFwKGQgPT4gZC52YWx1ZXMpO1xuXG5cdFx0dGhpcy5ub19vZl9leHRyYV9wdHMgPSBuZXdfeC5sZW5ndGggLSB0aGlzLngubGVuZ3RoO1xuXG5cdFx0Ly8gSnVzdCB1cGRhdGUgdmFsdWVzIHByb3AsIHNldHVwX3gveSgpIHdpbGwgZG8gdGhlIHJlc3Rcblx0XHRpZihuZXdfeSkgdGhpcy55Lm1hcCgoZCwgaSkgPT4ge2QudmFsdWVzID0gbmV3X3lbaV0udmFsdWVzO30pO1xuXHRcdGlmKG5ld194KSB0aGlzLnggPSBuZXdfeDtcblxuXHRcdHRoaXMuc2V0dXBfeCgpO1xuXHRcdHRoaXMuc2V0dXBfeSgpO1xuXG5cdFx0Ly8gQW5pbWF0ZSBvbmx5IGlmIHBvc2l0aW9ucyBoYXZlIGNoYW5nZWRcblx0XHRpZighYXJyYXlzX2VxdWFsKHRoaXMueF9vbGRfYXhpc19wb3NpdGlvbnMsIHRoaXMueF9heGlzX3Bvc2l0aW9ucykpIHtcblx0XHRcdHRoaXMubWFrZV94X2F4aXModHJ1ZSk7XG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0aWYoIXRoaXMudXBkYXRpbmcpIHRoaXMubWFrZV94X2F4aXMoKTtcblx0XHRcdH0sIDMwMCk7XG5cdFx0fVxuXG5cdFx0aWYoIWFycmF5c19lcXVhbCh0aGlzLnlfb2xkX2F4aXNfdmFsdWVzLCB0aGlzLnlfYXhpc192YWx1ZXMpIHx8XG5cdFx0XHQodGhpcy5vbGRfc3BlY2lmaWNfdmFsdWVzICYmXG5cdFx0XHQhYXJyYXlzX2VxdWFsKHRoaXMub2xkX3NwZWNpZmljX3ZhbHVlcywgdGhpcy5zcGVjaWZpY192YWx1ZXMpKSkge1xuXG5cdFx0XHR0aGlzLm1ha2VfeV9heGlzKHRydWUpO1xuXHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdGlmKCF0aGlzLnVwZGF0aW5nKSB7XG5cdFx0XHRcdFx0dGhpcy5tYWtlX3lfYXhpcygpO1xuXHRcdFx0XHRcdHRoaXMubWFrZV95X3NwZWNpZmljcygpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCAzMDApO1xuXHRcdH1cblxuXHRcdC8vIENoYW5nZSBpbiBkYXRhLCBzbyBjYWxjdWxhdGUgZGVwZW5kZW5jaWVzXG5cdFx0dGhpcy5jYWxjX3lfZGVwZW5kZW5jaWVzKCk7XG5cblx0XHR0aGlzLmFuaW1hdGVfZ3JhcGhzKCk7XG5cblx0XHQvLyBUcmlnZ2VyIGFuaW1hdGlvbiB3aXRoIHRoZSBhbmltYXRhYmxlIGVsZW1lbnRzIGluIHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZVxuXHRcdHRoaXMucnVuX2FuaW1hdGlvbigpO1xuXG5cdFx0dGhpcy51cGRhdGluZyA9IGZhbHNlO1xuXHR9XG5cblx0YWRkX2RhdGFfcG9pbnQoeV9wb2ludCwgeF9wb2ludCwgaW5kZXg9dGhpcy54Lmxlbmd0aCkge1xuXHRcdGxldCBuZXdfeSA9IHRoaXMueS5tYXAoZGF0YV9zZXQgPT4geyByZXR1cm4ge3ZhbHVlczpkYXRhX3NldC52YWx1ZXN9OyB9KTtcblx0XHRuZXdfeS5tYXAoKGQsIGkpID0+IHsgZC52YWx1ZXMuc3BsaWNlKGluZGV4LCAwLCB5X3BvaW50W2ldKTsgfSk7XG5cdFx0bGV0IG5ld194ID0gdGhpcy54LnNsaWNlKCk7XG5cdFx0bmV3X3guc3BsaWNlKGluZGV4LCAwLCB4X3BvaW50KTtcblxuXHRcdHRoaXMudXBkYXRlX3ZhbHVlcyhuZXdfeSwgbmV3X3gpO1xuXHR9XG5cblx0cmVtb3ZlX2RhdGFfcG9pbnQoaW5kZXggPSB0aGlzLngubGVuZ3RoLTEpIHtcblx0XHRpZih0aGlzLngubGVuZ3RoIDwgMykgcmV0dXJuO1xuXG5cdFx0bGV0IG5ld195ID0gdGhpcy55Lm1hcChkYXRhX3NldCA9PiB7IHJldHVybiB7dmFsdWVzOmRhdGFfc2V0LnZhbHVlc307IH0pO1xuXHRcdG5ld195Lm1hcCgoZCkgPT4geyBkLnZhbHVlcy5zcGxpY2UoaW5kZXgsIDEpOyB9KTtcblx0XHRsZXQgbmV3X3ggPSB0aGlzLnguc2xpY2UoKTtcblx0XHRuZXdfeC5zcGxpY2UoaW5kZXgsIDEpO1xuXG5cdFx0dGhpcy51cGRhdGVfdmFsdWVzKG5ld195LCBuZXdfeCk7XG5cdH1cblxuXHRydW5fYW5pbWF0aW9uKCkge1xuXHRcdGxldCBhbmltX3N2ZyA9ICQucnVuU1ZHQW5pbWF0aW9uKHRoaXMuc3ZnLCB0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUpO1xuXG5cdFx0aWYodGhpcy5zdmcucGFyZW50Tm9kZSA9PSB0aGlzLmNoYXJ0X3dyYXBwZXIpIHtcblx0XHRcdHRoaXMuY2hhcnRfd3JhcHBlci5yZW1vdmVDaGlsZCh0aGlzLnN2Zyk7XG5cdFx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIuYXBwZW5kQ2hpbGQoYW5pbV9zdmcpO1xuXG5cdFx0fVxuXG5cdFx0Ly8gUmVwbGFjZSB0aGUgbmV3IHN2ZyAoZGF0YSBoYXMgbG9uZyBiZWVuIHJlcGxhY2VkKVxuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0aWYoYW5pbV9zdmcucGFyZW50Tm9kZSA9PSB0aGlzLmNoYXJ0X3dyYXBwZXIpIHtcblx0XHRcdFx0dGhpcy5jaGFydF93cmFwcGVyLnJlbW92ZUNoaWxkKGFuaW1fc3ZnKTtcblx0XHRcdFx0dGhpcy5jaGFydF93cmFwcGVyLmFwcGVuZENoaWxkKHRoaXMuc3ZnKTtcblx0XHRcdH1cblx0XHR9LCAyMDApO1xuXHR9XG5cblx0YW5pbWF0ZV9ncmFwaHMoKSB7XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0Ly8gUHJlLXByZXAsIGVxdWlsaXplIG5vIG9mIHBvc2l0aW9ucyBiZXR3ZWVuIG9sZCBhbmQgbmV3XG5cdFx0XHRsZXQgW29sZF94LCBvbGRfeSwgbmV3X3gsIG5ld195XSA9IHRoaXMuY2FsY19vbGRfYW5kX25ld19wb3N0aW9ucyhkLCBpKTtcblx0XHRcdGlmKHRoaXMubm9fb2ZfZXh0cmFfcHRzID49IDApIHtcblx0XHRcdFx0dGhpcy5tYWtlX3BhdGggJiYgdGhpcy5tYWtlX3BhdGgoZCwgaSwgb2xkX3gsIG9sZF95LCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblx0XHRcdFx0dGhpcy5tYWtlX25ld191bml0c19mb3JfZGF0YXNldChvbGRfeCwgb2xkX3ksIGQuY29sb3IgfHwgdGhpcy5jb2xvcnNbaV0sIGksIHRoaXMueS5sZW5ndGgpO1xuXHRcdFx0fVxuXHRcdFx0ZC5wYXRoICYmIHRoaXMuYW5pbWF0ZV9wYXRoKGQsIGksIG9sZF94LCBvbGRfeSwgbmV3X3gsIG5ld195KTtcblx0XHRcdHRoaXMuYW5pbWF0ZV91bml0cyhkLCBpLCBvbGRfeCwgb2xkX3ksIG5ld194LCBuZXdfeSk7XG5cdFx0fSk7XG5cblx0XHQvLyBUT0RPOiByZXBsYWNlIHdpdGggcmVhbCB1bml0c1xuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0XHR0aGlzLm1ha2VfcGF0aCAmJiB0aGlzLm1ha2VfcGF0aChkLCBpLCB0aGlzLnhfYXhpc19wb3NpdGlvbnMsIGQueV90b3BzLCBkLmNvbG9yIHx8IHRoaXMuY29sb3JzW2ldKTtcblx0XHRcdFx0dGhpcy5tYWtlX25ld191bml0cyhkLCBpKTtcblx0XHRcdH0pO1xuXHRcdH0sIDMwMCk7XG5cdH1cblxuXHRhbmltYXRlX3BhdGgoZCwgaSwgb2xkX3gsIG9sZF95LCBuZXdfeCwgbmV3X3kpIHtcblx0XHQvLyBBbmltYXRlIHBhdGhcblx0XHRjb25zdCBuZXdfcG9pbnRzX2xpc3QgPSBuZXdfeS5tYXAoKHksIGkpID0+IChuZXdfeFtpXSArICcsJyArIHkpKTtcblx0XHRjb25zdCBuZXdfcGF0aF9zdHIgPSBuZXdfcG9pbnRzX2xpc3Quam9pbihcIkxcIik7XG5cblx0XHRjb25zdCBwYXRoX2FyZ3MgPSBbe3VuaXQ6IGQucGF0aCwgb2JqZWN0OiBkLCBrZXk6ICdwYXRoJ30sIHtkOlwiTVwiK25ld19wYXRoX3N0cn0sIDI1MCwgXCJlYXNlaW5cIl07XG5cdFx0dGhpcy5lbGVtZW50c190b19hbmltYXRlLnB1c2gocGF0aF9hcmdzKTtcblxuXHRcdC8vIEFuaW1hdGUgcmVnaW9uXG5cdFx0aWYoZC5yZWdpb25fcGF0aCkge1xuXHRcdFx0bGV0IHJlZ19zdGFydF9wdCA9IGAwLCR7dGhpcy56ZXJvX2xpbmV9TGA7XG5cdFx0XHRsZXQgcmVnX2VuZF9wdCA9IGBMJHt0aGlzLndpZHRofSwke3RoaXMuemVyb19saW5lfWA7XG5cblx0XHRcdGNvbnN0IHJlZ2lvbl9hcmdzID0gW1xuXHRcdFx0XHR7dW5pdDogZC5yZWdpb25fcGF0aCwgb2JqZWN0OiBkLCBrZXk6ICdyZWdpb25fcGF0aCd9LFxuXHRcdFx0XHR7ZDpcIk1cIiArIHJlZ19zdGFydF9wdCArIG5ld19wYXRoX3N0ciArIHJlZ19lbmRfcHR9LFxuXHRcdFx0XHQyNTAsXG5cdFx0XHRcdFwiZWFzZWluXCJcblx0XHRcdF07XG5cdFx0XHR0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUucHVzaChyZWdpb25fYXJncyk7XG5cdFx0fVxuXHR9XG5cblx0YW5pbWF0ZV91bml0cyhkLCBpbmRleCwgb2xkX3gsIG9sZF95LCBuZXdfeCwgbmV3X3kpIHtcblx0XHRsZXQgdHlwZSA9IHRoaXMudW5pdF9hcmdzLnR5cGU7XG5cblx0XHRkLnN2Z191bml0cy5tYXAoKHVuaXQsIGkpID0+IHtcblx0XHRcdHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZS5wdXNoKHRoaXMuYW5pbWF0ZVt0eXBlXShcblx0XHRcdFx0e3VuaXQ6dW5pdCwgYXJyYXk6ZC5zdmdfdW5pdHMsIGluZGV4OiBpfSwgLy8gdW5pdCwgd2l0aCBpbmZvIHRvIHJlcGxhY2Ugd2hlcmUgaXQgY2FtZSBmcm9tIGluIHRoZSBkYXRhXG5cdFx0XHRcdG5ld194W2ldLFxuXHRcdFx0XHRuZXdfeVtpXSxcblx0XHRcdFx0aW5kZXhcblx0XHRcdCkpO1xuXHRcdH0pO1xuXHR9XG5cblx0Y2FsY19vbGRfYW5kX25ld19wb3N0aW9ucyhkLCBpKSB7XG5cdFx0bGV0IG9sZF94ID0gdGhpcy54X29sZF9heGlzX3Bvc2l0aW9ucy5zbGljZSgpO1xuXHRcdGxldCBuZXdfeCA9IHRoaXMueF9heGlzX3Bvc2l0aW9ucy5zbGljZSgpO1xuXG5cdFx0bGV0IG9sZF95ID0gdGhpcy5vbGRfeV9heGlzX3RvcHNbaV0uc2xpY2UoKTtcblx0XHRsZXQgbmV3X3kgPSBkLnlfdG9wcy5zbGljZSgpO1xuXG5cdFx0Y29uc3QgbGFzdF9vbGRfeF9wb3MgPSBvbGRfeFtvbGRfeC5sZW5ndGggLSAxXTtcblx0XHRjb25zdCBsYXN0X29sZF95X3BvcyA9IG9sZF95W29sZF95Lmxlbmd0aCAtIDFdO1xuXG5cdFx0Y29uc3QgbGFzdF9uZXdfeF9wb3MgPSBuZXdfeFtuZXdfeC5sZW5ndGggLSAxXTtcblx0XHRjb25zdCBsYXN0X25ld195X3BvcyA9IG5ld195W25ld195Lmxlbmd0aCAtIDFdO1xuXG5cdFx0aWYodGhpcy5ub19vZl9leHRyYV9wdHMgPj0gMCkge1xuXHRcdFx0Ly8gRmlyc3Qgc3Vic3RpdHV0ZSBjdXJyZW50IHBhdGggd2l0aCBhIHNxdWlnZ2xlZCBvbmUgKGxvb2tpbmcgdGhlIHNhbWUgYnV0XG5cdFx0XHQvLyBoYXZpbmcgbW9yZSBwb2ludHMgYXQgZW5kKSxcblx0XHRcdC8vIHRoZW4gYW5pbWF0ZSB0byBzdHJldGNoIGl0IGxhdGVyIHRvIG5ldyBwb2ludHNcblx0XHRcdC8vIChuZXcgcG9pbnRzIGFscmVhZHkgaGF2ZSBtb3JlIHBvaW50cylcblxuXHRcdFx0Ly8gSGVuY2UsIHRoZSBleHRyYSBlbmQgcG9pbnRzIHdpbGwgY29ycmVzcG9uZCB0byBjdXJyZW50KG9sZCkgcG9zaXRpb25zXG5cdFx0XHRsZXQgZmlsbGVyX3ggPSBuZXcgQXJyYXkoTWF0aC5hYnModGhpcy5ub19vZl9leHRyYV9wdHMpKS5maWxsKGxhc3Rfb2xkX3hfcG9zKTtcblx0XHRcdGxldCBmaWxsZXJfeSA9IG5ldyBBcnJheShNYXRoLmFicyh0aGlzLm5vX29mX2V4dHJhX3B0cykpLmZpbGwobGFzdF9vbGRfeV9wb3MpO1xuXG5cdFx0XHRvbGRfeCA9IG9sZF94LmNvbmNhdChmaWxsZXJfeCk7XG5cdFx0XHRvbGRfeSA9IG9sZF95LmNvbmNhdChmaWxsZXJfeSk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gSnVzdCBtb2RpZnkgdGhlIG5ldyBwb2ludHMgdG8gaGF2ZSBleHRyYSBwb2ludHNcblx0XHRcdC8vIHdpdGggdGhlIHNhbWUgcG9zaXRpb24gYXQgZW5kXG5cdFx0XHRsZXQgZmlsbGVyX3ggPSBuZXcgQXJyYXkoTWF0aC5hYnModGhpcy5ub19vZl9leHRyYV9wdHMpKS5maWxsKGxhc3RfbmV3X3hfcG9zKTtcblx0XHRcdGxldCBmaWxsZXJfeSA9IG5ldyBBcnJheShNYXRoLmFicyh0aGlzLm5vX29mX2V4dHJhX3B0cykpLmZpbGwobGFzdF9uZXdfeV9wb3MpO1xuXG5cdFx0XHRuZXdfeCA9IG5ld194LmNvbmNhdChmaWxsZXJfeCk7XG5cdFx0XHRuZXdfeSA9IG5ld195LmNvbmNhdChmaWxsZXJfeSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtvbGRfeCwgb2xkX3ksIG5ld194LCBuZXdfeV07XG5cdH1cblxuXHRtYWtlX2FuaW1feF9heGlzKGhlaWdodCwgdGV4dF9zdGFydF9hdCwgYXhpc19saW5lX2NsYXNzKSB7XG5cdFx0Ly8gQW5pbWF0ZSBYIEFYSVMgdG8gYWNjb3VudCBmb3IgbW9yZSBvciBsZXNzIGF4aXMgbGluZXNcblxuXHRcdGNvbnN0IG9sZF9wb3MgPSB0aGlzLnhfb2xkX2F4aXNfcG9zaXRpb25zO1xuXHRcdGNvbnN0IG5ld19wb3MgPSB0aGlzLnhfYXhpc19wb3NpdGlvbnM7XG5cblx0XHRjb25zdCBvbGRfdmFscyA9IHRoaXMub2xkX3hfdmFsdWVzO1xuXHRcdGNvbnN0IG5ld192YWxzID0gdGhpcy54O1xuXG5cdFx0Y29uc3QgbGFzdF9saW5lX3BvcyA9IG9sZF9wb3Nbb2xkX3Bvcy5sZW5ndGggLSAxXTtcblxuXHRcdGxldCBhZGRfYW5kX2FuaW1hdGVfbGluZSA9ICh2YWx1ZSwgb2xkX3BvcywgbmV3X3BvcykgPT4ge1xuXHRcdFx0Y29uc3QgeF9saW5lID0gdGhpcy5tYWtlX3hfbGluZShcblx0XHRcdFx0aGVpZ2h0LFxuXHRcdFx0XHR0ZXh0X3N0YXJ0X2F0LFxuXHRcdFx0XHR2YWx1ZSwgLy8gbmV3IHZhbHVlXG5cdFx0XHRcdCd4LXZhbHVlLXRleHQnLFxuXHRcdFx0XHRheGlzX2xpbmVfY2xhc3MsXG5cdFx0XHRcdG9sZF9wb3MgLy8gb2xkIHBvc2l0aW9uXG5cdFx0XHQpO1xuXHRcdFx0dGhpcy54X2F4aXNfZ3JvdXAuYXBwZW5kQ2hpbGQoeF9saW5lKTtcblxuXHRcdFx0dGhpcy5lbGVtZW50c190b19hbmltYXRlICYmIHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZS5wdXNoKFtcblx0XHRcdFx0e3VuaXQ6IHhfbGluZSwgYXJyYXk6IFswXSwgaW5kZXg6IDB9LFxuXHRcdFx0XHR7dHJhbnNmb3JtOiBgJHsgbmV3X3BvcyB9LCAwYH0sXG5cdFx0XHRcdDI1MCxcblx0XHRcdFx0XCJlYXNlaW5cIixcblx0XHRcdFx0XCJ0cmFuc2xhdGVcIixcblx0XHRcdFx0e3RyYW5zZm9ybTogYCR7IG9sZF9wb3MgfSwgMGB9XG5cdFx0XHRdKTtcblx0XHR9O1xuXG5cdFx0dGhpcy54X2F4aXNfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblxuXHRcdHRoaXMubWFrZV9uZXdfYXhpc19hbmltX2xpbmVzKFxuXHRcdFx0b2xkX3Bvcyxcblx0XHRcdG5ld19wb3MsXG5cdFx0XHRvbGRfdmFscyxcblx0XHRcdG5ld192YWxzLFxuXHRcdFx0bGFzdF9saW5lX3Bvcyxcblx0XHRcdGFkZF9hbmRfYW5pbWF0ZV9saW5lXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfYW5pbV95X2F4aXMoKSB7XG5cdFx0Ly8gQW5pbWF0ZSBZIEFYSVMgdG8gYWNjb3VudCBmb3IgbW9yZSBvciBsZXNzIGF4aXMgbGluZXNcblxuXHRcdGNvbnN0IG9sZF9wb3MgPSB0aGlzLnlfb2xkX2F4aXNfdmFsdWVzLm1hcCh2YWx1ZSA9PlxuXHRcdFx0dGhpcy56ZXJvX2xpbmUgLSB2YWx1ZSAqIHRoaXMubXVsdGlwbGllcik7XG5cdFx0Y29uc3QgbmV3X3BvcyA9IHRoaXMueV9heGlzX3ZhbHVlcy5tYXAodmFsdWUgPT5cblx0XHRcdHRoaXMuemVyb19saW5lIC0gdmFsdWUgKiB0aGlzLm11bHRpcGxpZXIpO1xuXG5cdFx0Y29uc3Qgb2xkX3ZhbHMgPSB0aGlzLnlfb2xkX2F4aXNfdmFsdWVzO1xuXHRcdGNvbnN0IG5ld192YWxzID0gdGhpcy55X2F4aXNfdmFsdWVzO1xuXG5cdFx0Y29uc3QgbGFzdF9saW5lX3BvcyA9IG9sZF9wb3Nbb2xkX3Bvcy5sZW5ndGggLSAxXTtcblxuXHRcdHRoaXMueV9heGlzX2dyb3VwLnRleHRDb250ZW50ID0gJyc7XG5cblx0XHR0aGlzLm1ha2VfbmV3X2F4aXNfYW5pbV9saW5lcyhcblx0XHRcdG9sZF9wb3MsXG5cdFx0XHRuZXdfcG9zLFxuXHRcdFx0b2xkX3ZhbHMsXG5cdFx0XHRuZXdfdmFscyxcblx0XHRcdGxhc3RfbGluZV9wb3MsXG5cdFx0XHR0aGlzLmFkZF9hbmRfYW5pbWF0ZV95X2xpbmUuYmluZCh0aGlzKSxcblx0XHRcdHRoaXMueV9heGlzX2dyb3VwXG5cdFx0KTtcblx0fVxuXG5cdG1ha2VfYW5pbV95X3NwZWNpZmljcygpIHtcblx0XHR0aGlzLnNwZWNpZmljX3lfZ3JvdXAudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLnNwZWNpZmljX3ZhbHVlcy5tYXAoKGQpID0+IHtcblx0XHRcdHRoaXMuYWRkX2FuZF9hbmltYXRlX3lfbGluZShcblx0XHRcdFx0ZC50aXRsZSxcblx0XHRcdFx0dGhpcy5vbGRfemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMub2xkX211bHRpcGxpZXIsXG5cdFx0XHRcdHRoaXMuemVyb19saW5lIC0gZC52YWx1ZSAqIHRoaXMubXVsdGlwbGllcixcblx0XHRcdFx0MCxcblx0XHRcdFx0dGhpcy5zcGVjaWZpY195X2dyb3VwLFxuXHRcdFx0XHRkLmxpbmVfdHlwZSxcblx0XHRcdFx0dHJ1ZVxuXHRcdFx0KTtcblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfbmV3X2F4aXNfYW5pbV9saW5lcyhvbGRfcG9zLCBuZXdfcG9zLCBvbGRfdmFscywgbmV3X3ZhbHMsIGxhc3RfbGluZV9wb3MsIGFkZF9hbmRfYW5pbWF0ZV9saW5lLCBncm91cCkge1xuXHRcdGxldCBzdXBlcmltcG9zZWRfcG9zaXRpb25zLCBzdXBlcmltcG9zZWRfdmFsdWVzO1xuXHRcdGxldCBub19vZl9leHRyYXMgPSBuZXdfdmFscy5sZW5ndGggLSBvbGRfdmFscy5sZW5ndGg7XG5cdFx0aWYobm9fb2ZfZXh0cmFzID4gMCkge1xuXHRcdFx0Ly8gTW9yZSBheGlzIGFyZSBuZWVkZWRcblx0XHRcdC8vIEZpcnN0IG1ha2Ugb25seSB0aGUgc3VwZXJpbXBvc2VkIChzYW1lIHBvc2l0aW9uKSBvbmVzXG5cdFx0XHQvLyBBZGQgaW4gdGhlIGV4dHJhcyBhdCB0aGUgZW5kIGxhdGVyXG5cdFx0XHRzdXBlcmltcG9zZWRfcG9zaXRpb25zID0gbmV3X3Bvcy5zbGljZSgwLCBvbGRfcG9zLmxlbmd0aCk7XG5cdFx0XHRzdXBlcmltcG9zZWRfdmFsdWVzID0gbmV3X3ZhbHMuc2xpY2UoMCwgb2xkX3ZhbHMubGVuZ3RoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gQXhpcyBoYXZlIHRvIGJlIHJlZHVjZWRcblx0XHRcdC8vIEZha2UgaXQgYnkgbW92aW5nIGFsbCBjdXJyZW50IGV4dHJhIGF4aXMgdG8gdGhlIGxhc3QgcG9zaXRpb25cblx0XHRcdC8vIFlvdSdsbCBuZWVkIGZpbGxlciBwb3NpdGlvbnMgYW5kIHZhbHVlcyBpbiB0aGUgbmV3IGFycmF5c1xuXHRcdFx0Y29uc3QgZmlsbGVyX3ZhbHMgPSBuZXcgQXJyYXkoTWF0aC5hYnMobm9fb2ZfZXh0cmFzKSkuZmlsbChcIlwiKTtcblx0XHRcdHN1cGVyaW1wb3NlZF92YWx1ZXMgPSBuZXdfdmFscy5jb25jYXQoZmlsbGVyX3ZhbHMpO1xuXG5cdFx0XHRjb25zdCBmaWxsZXJfcG9zID0gbmV3IEFycmF5KE1hdGguYWJzKG5vX29mX2V4dHJhcykpLmZpbGwobGFzdF9saW5lX3Bvcyk7XG5cdFx0XHRzdXBlcmltcG9zZWRfcG9zaXRpb25zID0gbmV3X3Bvcy5jb25jYXQoZmlsbGVyX3Bvcyk7XG5cdFx0fVxuXG5cdFx0c3VwZXJpbXBvc2VkX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRhZGRfYW5kX2FuaW1hdGVfbGluZSh2YWx1ZSwgb2xkX3Bvc1tpXSwgc3VwZXJpbXBvc2VkX3Bvc2l0aW9uc1tpXSwgaSwgZ3JvdXApO1xuXHRcdH0pO1xuXG5cdFx0aWYobm9fb2ZfZXh0cmFzID4gMCkge1xuXHRcdFx0Ly8gQWRkIGluIGV4dHJhIGF4aXMgaW4gdGhlIGVuZFxuXHRcdFx0Ly8gYW5kIHRoZW4gYW5pbWF0ZSB0byBuZXcgcG9zaXRpb25zXG5cdFx0XHRjb25zdCBleHRyYV92YWx1ZXMgPSBuZXdfdmFscy5zbGljZShvbGRfdmFscy5sZW5ndGgpO1xuXHRcdFx0Y29uc3QgZXh0cmFfcG9zaXRpb25zID0gbmV3X3Bvcy5zbGljZShvbGRfcG9zLmxlbmd0aCk7XG5cblx0XHRcdGV4dHJhX3ZhbHVlcy5tYXAoKHZhbHVlLCBpKSA9PiB7XG5cdFx0XHRcdGFkZF9hbmRfYW5pbWF0ZV9saW5lKHZhbHVlLCBsYXN0X2xpbmVfcG9zLCBleHRyYV9wb3NpdGlvbnNbaV0sIGksIGdyb3VwKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdG1ha2VfeF9saW5lKGhlaWdodCwgdGV4dF9zdGFydF9hdCwgcG9pbnQsIGxhYmVsX2NsYXNzLCBheGlzX2xpbmVfY2xhc3MsIHhfcG9zKSB7XG5cdFx0bGV0IGFsbG93ZWRfc3BhY2UgPSB0aGlzLmF2Z191bml0X3dpZHRoICogMS41O1xuXG5cdFx0aWYodGhpcy5nZXRfc3Ryd2lkdGgocG9pbnQpID4gYWxsb3dlZF9zcGFjZSkge1xuXHRcdFx0bGV0IGFsbG93ZWRfbGV0dGVycyA9IGFsbG93ZWRfc3BhY2UgLyA4O1xuXHRcdFx0cG9pbnQgPSBwb2ludC5zbGljZSgwLCBhbGxvd2VkX2xldHRlcnMtMykgKyBcIiAuLi5cIjtcblx0XHR9XG5cblx0XHRsZXQgbGluZSA9ICQuY3JlYXRlU1ZHKCdsaW5lJywge1xuXHRcdFx0eDE6IDAsXG5cdFx0XHR4MjogMCxcblx0XHRcdHkxOiAwLFxuXHRcdFx0eTI6IGhlaWdodFxuXHRcdH0pO1xuXG5cdFx0bGV0IHRleHQgPSAkLmNyZWF0ZVNWRygndGV4dCcsIHtcblx0XHRcdGNsYXNzTmFtZTogbGFiZWxfY2xhc3MsXG5cdFx0XHR4OiAwLFxuXHRcdFx0eTogdGV4dF9zdGFydF9hdCxcblx0XHRcdGR5OiAnLjcxZW0nLFxuXHRcdFx0aW5uZXJIVE1MOiBwb2ludFxuXHRcdH0pO1xuXG5cdFx0bGV0IHhfbGV2ZWwgPSAkLmNyZWF0ZVNWRygnZycsIHtcblx0XHRcdGNsYXNzTmFtZTogYHRpY2sgJHtheGlzX2xpbmVfY2xhc3N9YCxcblx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgkeyB4X3BvcyB9LCAwKWBcblx0XHR9KTtcblxuXHRcdHhfbGV2ZWwuYXBwZW5kQ2hpbGQobGluZSk7XG5cdFx0eF9sZXZlbC5hcHBlbmRDaGlsZCh0ZXh0KTtcblxuXHRcdHJldHVybiB4X2xldmVsO1xuXHR9XG5cblx0bWFrZV95X2xpbmUoc3RhcnRfYXQsIHdpZHRoLCB0ZXh0X2VuZF9hdCwgcG9pbnQsIGxhYmVsX2NsYXNzLCBheGlzX2xpbmVfY2xhc3MsIHlfcG9zLCBkYXJrZXI9ZmFsc2UsIGxpbmVfdHlwZT1cIlwiKSB7XG5cdFx0bGV0IGxpbmUgPSAkLmNyZWF0ZVNWRygnbGluZScsIHtcblx0XHRcdGNsYXNzTmFtZTogbGluZV90eXBlID09PSBcImRhc2hlZFwiID8gXCJkYXNoZWRcIjogXCJcIixcblx0XHRcdHgxOiBzdGFydF9hdCxcblx0XHRcdHgyOiB3aWR0aCxcblx0XHRcdHkxOiAwLFxuXHRcdFx0eTI6IDBcblx0XHR9KTtcblxuXHRcdGxldCB0ZXh0ID0gJC5jcmVhdGVTVkcoJ3RleHQnLCB7XG5cdFx0XHRjbGFzc05hbWU6IGxhYmVsX2NsYXNzLFxuXHRcdFx0eDogdGV4dF9lbmRfYXQsXG5cdFx0XHR5OiAwLFxuXHRcdFx0ZHk6ICcuMzJlbScsXG5cdFx0XHRpbm5lckhUTUw6IHBvaW50K1wiXCJcblx0XHR9KTtcblxuXHRcdGxldCB5X2xldmVsID0gJC5jcmVhdGVTVkcoJ2cnLCB7XG5cdFx0XHRjbGFzc05hbWU6IGB0aWNrICR7YXhpc19saW5lX2NsYXNzfWAsXG5cdFx0XHR0cmFuc2Zvcm06IGB0cmFuc2xhdGUoMCwgJHt5X3Bvc30pYFxuXHRcdH0pO1xuXG5cdFx0aWYoZGFya2VyKSB7XG5cdFx0XHRsaW5lLnN0eWxlLnN0cm9rZSA9IFwicmdiYSgyNywgMzEsIDM1LCAwLjYpXCI7XG5cdFx0fVxuXG5cdFx0eV9sZXZlbC5hcHBlbmRDaGlsZChsaW5lKTtcblx0XHR5X2xldmVsLmFwcGVuZENoaWxkKHRleHQpO1xuXG5cdFx0cmV0dXJuIHlfbGV2ZWw7XG5cdH1cblxuXHRhZGRfYW5kX2FuaW1hdGVfeV9saW5lKHZhbHVlLCBvbGRfcG9zLCBuZXdfcG9zLCBpLCBncm91cCwgdHlwZSwgc3BlY2lmaWM9ZmFsc2UpIHtcblx0XHRsZXQgW3dpZHRoLCB0ZXh0X2VuZF9hdCwgYXhpc19saW5lX2NsYXNzLCBzdGFydF9hdF0gPSB0aGlzLmdldF95X2F4aXNfbGluZV9wcm9wcyhzcGVjaWZpYyk7XG5cdFx0bGV0IGF4aXNfbGFiZWxfY2xhc3MgPSAhc3BlY2lmaWMgPyAneS12YWx1ZS10ZXh0JyA6ICdzcGVjaWZpYy12YWx1ZSc7XG5cdFx0dmFsdWUgPSAhc3BlY2lmaWMgPyB2YWx1ZSA6ICh2YWx1ZStcIlwiKS50b1VwcGVyQ2FzZSgpO1xuXHRcdGNvbnN0IHlfbGluZSA9IHRoaXMubWFrZV95X2xpbmUoXG5cdFx0XHRzdGFydF9hdCxcblx0XHRcdHdpZHRoLFxuXHRcdFx0dGV4dF9lbmRfYXQsXG5cdFx0XHR2YWx1ZSxcblx0XHRcdGF4aXNfbGFiZWxfY2xhc3MsXG5cdFx0XHRheGlzX2xpbmVfY2xhc3MsXG5cdFx0XHRvbGRfcG9zLCAgLy8gb2xkIHBvc2l0aW9uXG5cdFx0XHQodmFsdWUgPT09IDAgJiYgaSAhPT0gMCksIC8vIE5vbi1maXJzdCBaZXJvIGxpbmVcblx0XHRcdHR5cGVcblx0XHQpO1xuXG5cdFx0Z3JvdXAuYXBwZW5kQ2hpbGQoeV9saW5lKTtcblxuXHRcdHRoaXMuZWxlbWVudHNfdG9fYW5pbWF0ZSAmJiB0aGlzLmVsZW1lbnRzX3RvX2FuaW1hdGUucHVzaChbXG5cdFx0XHR7dW5pdDogeV9saW5lLCBhcnJheTogWzBdLCBpbmRleDogMH0sXG5cdFx0XHR7dHJhbnNmb3JtOiBgMCwgJHsgbmV3X3BvcyB9YH0sXG5cdFx0XHQyNTAsXG5cdFx0XHRcImVhc2VpblwiLFxuXHRcdFx0XCJ0cmFuc2xhdGVcIixcblx0XHRcdHt0cmFuc2Zvcm06IGAwLCAkeyBvbGRfcG9zIH1gfVxuXHRcdF0pO1xuXHR9XG5cblx0Z2V0X3lfYXhpc19wb2ludHMoYXJyYXkpIHtcblx0XHQvLyoqKiBXaGVyZSB0aGUgbWFnaWMgaGFwcGVucyAqKipcblxuXHRcdC8vIENhbGN1bGF0ZXMgYmVzdC1maXQgeSBpbnRlcnZhbHMgZnJvbSBnaXZlbiB2YWx1ZXNcblx0XHQvLyBhbmQgcmV0dXJucyB0aGUgaW50ZXJ2YWwgYXJyYXlcblxuXHRcdC8vIFRPRE86IEZyYWN0aW9uc1xuXG5cdFx0bGV0IG1heF9ib3VuZCwgbWluX2JvdW5kLCBwb3Nfbm9fb2ZfcGFydHMsIG5lZ19ub19vZl9wYXJ0cywgcGFydF9zaXplOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG5cblx0XHQvLyBDcml0aWNhbCB2YWx1ZXNcblx0XHRsZXQgbWF4X3ZhbCA9IHBhcnNlSW50KE1hdGgubWF4KC4uLmFycmF5KSk7XG5cdFx0bGV0IG1pbl92YWwgPSBwYXJzZUludChNYXRoLm1pbiguLi5hcnJheSkpO1xuXHRcdGlmKG1pbl92YWwgPj0gMCkge1xuXHRcdFx0bWluX3ZhbCA9IDA7XG5cdFx0fVxuXG5cdFx0bGV0IGdldF9wYXJhbXMgPSAodmFsdWUxLCB2YWx1ZTIpID0+IHtcblx0XHRcdGxldCBib3VuZDEsIGJvdW5kMiwgbm9fb2ZfcGFydHNfMSwgbm9fb2ZfcGFydHNfMiwgaW50ZXJ2YWxfc2l6ZTtcblx0XHRcdGlmKCh2YWx1ZTErXCJcIikubGVuZ3RoIDw9IDEpIHtcblx0XHRcdFx0W2JvdW5kMSwgbm9fb2ZfcGFydHNfMV0gPSBbMTAsIDVdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0W2JvdW5kMSwgbm9fb2ZfcGFydHNfMV0gPSB0aGlzLmNhbGNfdXBwZXJfYm91bmRfYW5kX25vX29mX3BhcnRzKHZhbHVlMSk7XG5cdFx0XHR9XG5cblx0XHRcdGludGVydmFsX3NpemUgPSBib3VuZDEgLyBub19vZl9wYXJ0c18xO1xuXHRcdFx0bm9fb2ZfcGFydHNfMiA9IHRoaXMuY2FsY19ub19vZl9wYXJ0cyh2YWx1ZTIsIGludGVydmFsX3NpemUpO1xuXHRcdFx0Ym91bmQyID0gbm9fb2ZfcGFydHNfMiAqIGludGVydmFsX3NpemU7XG5cblx0XHRcdHJldHVybiBbYm91bmQxLCBib3VuZDIsIG5vX29mX3BhcnRzXzEsIG5vX29mX3BhcnRzXzIsIGludGVydmFsX3NpemVdO1xuXHRcdH07XG5cblx0XHRjb25zdCBhYnNfbWluX3ZhbCA9IG1pbl92YWwgKiAtMTtcblx0XHRpZihhYnNfbWluX3ZhbCA8PSBtYXhfdmFsKSB7XG5cdFx0XHQvLyBHZXQgdGhlIHBvc2l0aXZlIHJlZ2lvbiBpbnRlcnZhbHNcblx0XHRcdC8vIHRoZW4gY2FsYyBuZWdhdGl2ZSBvbmVzIGFjY29yZGluZ2x5XG5cdFx0XHRbbWF4X2JvdW5kLCBtaW5fYm91bmQsIHBvc19ub19vZl9wYXJ0cywgbmVnX25vX29mX3BhcnRzLCBwYXJ0X3NpemVdXG5cdFx0XHRcdD0gZ2V0X3BhcmFtcyhtYXhfdmFsLCBhYnNfbWluX3ZhbCk7XG5cdFx0XHRpZihhYnNfbWluX3ZhbCA9PT0gMCkge1xuXHRcdFx0XHRtaW5fYm91bmQgPSAwOyBuZWdfbm9fb2ZfcGFydHMgPSAwO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBHZXQgdGhlIG5lZ2F0aXZlIHJlZ2lvbiBoZXJlIGZpcnN0XG5cdFx0XHRbbWluX2JvdW5kLCBtYXhfYm91bmQsIG5lZ19ub19vZl9wYXJ0cywgcG9zX25vX29mX3BhcnRzLCBwYXJ0X3NpemVdXG5cdFx0XHRcdD0gZ2V0X3BhcmFtcyhhYnNfbWluX3ZhbCwgbWF4X3ZhbCk7XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBib3RoIHJlZ2lvbiBwYXJ0cyBldmVuXG5cdFx0aWYocG9zX25vX29mX3BhcnRzICUgMiAhPT0gMCAmJiBuZWdfbm9fb2ZfcGFydHMgPiAwKSBwb3Nfbm9fb2ZfcGFydHMrKztcblx0XHRpZihuZWdfbm9fb2ZfcGFydHMgJSAyICE9PSAwKSB7XG5cdFx0XHQvLyBldmVyeSBpbmNyZWFzZSBpbiBub19vZl9wYXJ0cyBlbnRhaWxzIGFuIGluY3JlYXNlIGluIGNvcnJlc3BvbmRpbmcgYm91bmRcblx0XHRcdC8vIGV4Y2VwdCBoZXJlLCBpdCBoYXBwZW5zIGltcGxpY2l0bHkgYWZ0ZXIgZXZlcnkgY2FsY19ub19vZl9wYXJ0cygpIGNhbGxcblx0XHRcdG5lZ19ub19vZl9wYXJ0cysrO1xuXHRcdFx0bWluX2JvdW5kICs9IHBhcnRfc2l6ZTtcblx0XHR9XG5cblx0XHRsZXQgbm9fb2ZfcGFydHMgPSBwb3Nfbm9fb2ZfcGFydHMgKyBuZWdfbm9fb2ZfcGFydHM7XG5cdFx0aWYobm9fb2ZfcGFydHMgPiA1KSB7XG5cdFx0XHRub19vZl9wYXJ0cyAvPSAyO1xuXHRcdFx0cGFydF9zaXplICo9IDI7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZ2V0X2ludGVydmFscyhcblx0XHRcdCgtMSkgKiBtaW5fYm91bmQsXG5cdFx0XHRwYXJ0X3NpemUsXG5cdFx0XHRub19vZl9wYXJ0c1xuXHRcdCk7XG5cdH1cblxuXHRnZXRfaW50ZXJ2YWxzKHN0YXJ0LCBpbnRlcnZhbF9zaXplLCBjb3VudCkge1xuXHRcdGxldCBpbnRlcnZhbHMgPSBbXTtcblx0XHRmb3IodmFyIGkgPSAwOyBpIDw9IGNvdW50OyBpKyspe1xuXHRcdFx0aW50ZXJ2YWxzLnB1c2goc3RhcnQpO1xuXHRcdFx0c3RhcnQgKz0gaW50ZXJ2YWxfc2l6ZTtcblx0XHR9XG5cdFx0cmV0dXJuIGludGVydmFscztcblx0fVxuXG5cdGNhbGNfdXBwZXJfYm91bmRfYW5kX25vX29mX3BhcnRzKG1heF92YWwpIHtcblx0XHQvLyBHaXZlbiBhIHBvc2l0aXZlIHZhbHVlLCBjYWxjdWxhdGVzIGEgbmljZS1udW1iZXIgdXBwZXIgYm91bmRcblx0XHQvLyBhbmQgYSBjb25zZXF1ZW50IG9wdGltYWwgbnVtYmVyIG9mIHBhcnRzXG5cblx0XHRjb25zdCBwYXJ0X3NpemUgPSBNYXRoLnBvdygxMCwgKChtYXhfdmFsK1wiXCIpLmxlbmd0aCAtIDEpKTtcblx0XHRjb25zdCBub19vZl9wYXJ0cyA9IHRoaXMuY2FsY19ub19vZl9wYXJ0cyhtYXhfdmFsLCBwYXJ0X3NpemUpO1xuXG5cdFx0Ly8gVXNlIGl0IHRvIGdldCBhIG5pY2UgZXZlbiB1cHBlciBib3VuZFxuXHRcdGNvbnN0IHVwcGVyX2JvdW5kID0gcGFydF9zaXplICogbm9fb2ZfcGFydHM7XG5cblx0XHRyZXR1cm4gW3VwcGVyX2JvdW5kLCBub19vZl9wYXJ0c107XG5cdH1cblxuXHRjYWxjX25vX29mX3BhcnRzKHZhbHVlLCBkaXZpc29yKSB7XG5cdFx0Ly8gdmFsdWUgc2hvdWxkIGJlIGEgcG9zaXRpdmUgbnVtYmVyLCBkaXZpc29yIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gMFxuXHRcdC8vIHJldHVybnMgYW4gZXZlbiBubyBvZiBwYXJ0c1xuXHRcdGxldCBub19vZl9wYXJ0cyA9IE1hdGguY2VpbCh2YWx1ZSAvIGRpdmlzb3IpO1xuXHRcdGlmKG5vX29mX3BhcnRzICUgMiAhPT0gMCkgbm9fb2ZfcGFydHMrKzsgLy8gTWFrZSBpdCBhbiBldmVuIG51bWJlclxuXG5cdFx0cmV0dXJuIG5vX29mX3BhcnRzO1xuXHR9XG5cblx0Z2V0X29wdGltYWxfbm9fb2ZfcGFydHMobm9fb2ZfcGFydHMpIHtcblx0XHQvLyBha2EgRGl2aWRlIGJ5IDIgaWYgdG9vIGxhcmdlXG5cdFx0cmV0dXJuIChub19vZl9wYXJ0cyA8IDUpID8gbm9fb2ZfcGFydHMgOiBub19vZl9wYXJ0cyAvIDI7XG5cdH1cblxuXHRzZXRfYXZnX3VuaXRfd2lkdGhfYW5kX3hfb2Zmc2V0KCkge1xuXHRcdC8vIFNldCB0aGUgLi4uIHlvdSBnZXQgaXRcblx0XHR0aGlzLmF2Z191bml0X3dpZHRoID0gdGhpcy53aWR0aC8odGhpcy54Lmxlbmd0aCAtIDEpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSAwO1xuXHR9XG5cblx0Z2V0X2FsbF95X3ZhbHVlcygpIHtcblx0XHRsZXQgYWxsX3ZhbHVlcyA9IFtdO1xuXG5cdFx0Ly8gQWRkIGluIGFsbCB0aGUgeSB2YWx1ZXMgaW4gdGhlIGRhdGFzZXRzXG5cdFx0dGhpcy55Lm1hcChkID0+IHtcblx0XHRcdGFsbF92YWx1ZXMgPSBhbGxfdmFsdWVzLmNvbmNhdChkLnZhbHVlcyk7XG5cdFx0fSk7XG5cblx0XHQvLyBBZGQgaW4gYWxsIHRoZSBzcGVjaWZpYyB2YWx1ZXNcblx0XHRyZXR1cm4gYWxsX3ZhbHVlcy5jb25jYXQodGhpcy5zcGVjaWZpY192YWx1ZXMubWFwKGQgPT4gZC52YWx1ZSkpO1xuXHR9XG5cblx0Y2FsY195X2RlcGVuZGVuY2llcygpIHtcblx0XHR0aGlzLnlfbWluX3RvcHMgPSBuZXcgQXJyYXkodGhpcy54X2F4aXNfcG9zaXRpb25zLmxlbmd0aCkuZmlsbCg5OTk5KTtcblx0XHR0aGlzLnkubWFwKGQgPT4ge1xuXHRcdFx0ZC55X3RvcHMgPSBkLnZhbHVlcy5tYXAoIHZhbCA9PiBmbG9hdF8yKHRoaXMuemVyb19saW5lIC0gdmFsICogdGhpcy5tdWx0aXBsaWVyKSk7XG5cdFx0XHRkLnlfdG9wcy5tYXAoICh5X3RvcCwgaSkgPT4ge1xuXHRcdFx0XHRpZih5X3RvcCA8IHRoaXMueV9taW5fdG9wc1tpXSkge1xuXHRcdFx0XHRcdHRoaXMueV9taW5fdG9wc1tpXSA9IHlfdG9wO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdGdldF9iYXJfaGVpZ2h0X2FuZF95X2F0dHIoeV90b3ApIHtcblx0XHRsZXQgaGVpZ2h0LCB5O1xuXHRcdGlmICh5X3RvcCA8PSB0aGlzLnplcm9fbGluZSkge1xuXHRcdFx0aGVpZ2h0ID0gdGhpcy56ZXJvX2xpbmUgLSB5X3RvcDtcblx0XHRcdHkgPSB5X3RvcDtcblxuXHRcdFx0Ly8gSW4gY2FzZSBvZiBpbnZpc2libGUgYmFyc1xuXHRcdFx0aWYoaGVpZ2h0ID09PSAwKSB7XG5cdFx0XHRcdGhlaWdodCA9IHRoaXMuaGVpZ2h0ICogMC4wMTtcblx0XHRcdFx0eSAtPSBoZWlnaHQ7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGhlaWdodCA9IHlfdG9wIC0gdGhpcy56ZXJvX2xpbmU7XG5cdFx0XHR5ID0gdGhpcy56ZXJvX2xpbmU7XG5cblx0XHRcdC8vIEluIGNhc2Ugb2YgaW52aXNpYmxlIGJhcnNcblx0XHRcdGlmKGhlaWdodCA9PT0gMCkge1xuXHRcdFx0XHRoZWlnaHQgPSB0aGlzLmhlaWdodCAqIDAuMDE7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtoZWlnaHQsIHldO1xuXHR9XG5cblx0c2V0dXBfdXRpbHMoKSB7XG5cdFx0dGhpcy5kcmF3ID0ge1xuXHRcdFx0J2Jhcic6ICh4LCB5X3RvcCwgYXJncywgY29sb3IsIGluZGV4LCBub19vZl9kYXRhc2V0cykgPT4ge1xuXHRcdFx0XHRsZXQgdG90YWxfd2lkdGggPSB0aGlzLmF2Z191bml0X3dpZHRoIC0gYXJncy5zcGFjZV93aWR0aDtcblx0XHRcdFx0bGV0IHN0YXJ0X3ggPSB4IC0gdG90YWxfd2lkdGgvMjtcblxuXHRcdFx0XHRsZXQgd2lkdGggPSB0b3RhbF93aWR0aCAvIG5vX29mX2RhdGFzZXRzO1xuXHRcdFx0XHRsZXQgY3VycmVudF94ID0gc3RhcnRfeCArIHdpZHRoICogaW5kZXg7XG5cblx0XHRcdFx0bGV0IFtoZWlnaHQsIHldID0gdGhpcy5nZXRfYmFyX2hlaWdodF9hbmRfeV9hdHRyKHlfdG9wKTtcblxuXHRcdFx0XHRyZXR1cm4gJC5jcmVhdGVTVkcoJ3JlY3QnLCB7XG5cdFx0XHRcdFx0Y2xhc3NOYW1lOiBgYmFyIG1pbmkgZmlsbCAke2NvbG9yfWAsXG5cdFx0XHRcdFx0eDogY3VycmVudF94LFxuXHRcdFx0XHRcdHk6IHksXG5cdFx0XHRcdFx0d2lkdGg6IHdpZHRoLFxuXHRcdFx0XHRcdGhlaWdodDogaGVpZ2h0XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHR9LFxuXHRcdFx0J2RvdCc6ICh4LCB5LCBhcmdzLCBjb2xvcikgPT4ge1xuXHRcdFx0XHRyZXR1cm4gJC5jcmVhdGVTVkcoJ2NpcmNsZScsIHtcblx0XHRcdFx0XHRjbGFzc05hbWU6IGBmaWxsICR7Y29sb3J9YCxcblx0XHRcdFx0XHRjeDogeCxcblx0XHRcdFx0XHRjeTogeSxcblx0XHRcdFx0XHRyOiBhcmdzLnJhZGl1c1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0dGhpcy5hbmltYXRlID0ge1xuXHRcdFx0J2Jhcic6IChiYXJfb2JqLCB4LCB5X3RvcCwgaW5kZXgpID0+IHtcblx0XHRcdFx0bGV0IHN0YXJ0ID0geCAtIHRoaXMuYXZnX3VuaXRfd2lkdGgvNDtcblx0XHRcdFx0bGV0IHdpZHRoID0gKHRoaXMuYXZnX3VuaXRfd2lkdGgvMikvdGhpcy55Lmxlbmd0aDtcblx0XHRcdFx0bGV0IFtoZWlnaHQsIHldID0gdGhpcy5nZXRfYmFyX2hlaWdodF9hbmRfeV9hdHRyKHlfdG9wKTtcblxuXHRcdFx0XHR4ID0gc3RhcnQgKyAod2lkdGggKiBpbmRleCk7XG5cblx0XHRcdFx0cmV0dXJuIFtiYXJfb2JqLCB7d2lkdGg6IHdpZHRoLCBoZWlnaHQ6IGhlaWdodCwgeDogeCwgeTogeX0sIDI1MCwgXCJlYXNlaW5cIl07XG5cdFx0XHRcdC8vIGJhci5hbmltYXRlKHtoZWlnaHQ6IGFyZ3MubmV3X2hlaWdodCwgeTogeV90b3B9LCAyNTAsIG1pbmEuZWFzZWluKTtcblx0XHRcdH0sXG5cdFx0XHQnZG90JzogKGRvdF9vYmosIHgsIHlfdG9wKSA9PiB7XG5cdFx0XHRcdHJldHVybiBbZG90X29iaiwge2N4OiB4LCBjeTogeV90b3B9LCAzMDAsIFwiZWFzZWluXCJdO1xuXHRcdFx0XHQvLyBkb3QuYW5pbWF0ZSh7Y3k6IHlfdG9wfSwgMjUwLCBtaW5hLmVhc2Vpbik7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxufVxuXG5jbGFzcyBCYXJDaGFydCBleHRlbmRzIEF4aXNDaGFydCB7XG5cdGNvbnN0cnVjdG9yKGFyZ3MpIHtcblx0XHRzdXBlcihhcmdzKTtcblxuXHRcdHRoaXMudHlwZSA9ICdiYXInO1xuXHRcdHRoaXMueF9heGlzX21vZGUgPSBhcmdzLnhfYXhpc19tb2RlIHx8ICd0aWNrJztcblx0XHR0aGlzLnlfYXhpc19tb2RlID0gYXJncy55X2F4aXNfbW9kZSB8fCAnc3Bhbic7XG5cdFx0dGhpcy5zZXR1cCgpO1xuXHR9XG5cblx0c2V0dXBfdmFsdWVzKCkge1xuXHRcdHN1cGVyLnNldHVwX3ZhbHVlcygpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSB0aGlzLmF2Z191bml0X3dpZHRoO1xuXHRcdHRoaXMudW5pdF9hcmdzID0ge1xuXHRcdFx0dHlwZTogJ2JhcicsXG5cdFx0XHRhcmdzOiB7XG5cdFx0XHRcdHNwYWNlX3dpZHRoOiB0aGlzLmF2Z191bml0X3dpZHRoLzIsXG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cdG1ha2Vfb3ZlcmxheSgpIHtcblx0XHQvLyBKdXN0IG1ha2Ugb25lIG91dCBvZiB0aGUgZmlyc3QgZWxlbWVudFxuXHRcdGxldCBpbmRleCA9IHRoaXMueC5sZW5ndGggLSAxO1xuXHRcdGxldCB1bml0ID0gdGhpcy55WzBdLnN2Z191bml0c1tpbmRleF07XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KGluZGV4KTtcblxuXHRcdGlmKHRoaXMub3ZlcmxheSkge1xuXHRcdFx0dGhpcy5vdmVybGF5LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5vdmVybGF5KTtcblx0XHR9XG5cblx0XHR0aGlzLm92ZXJsYXkgPSB1bml0LmNsb25lTm9kZSgpO1xuXHRcdHRoaXMub3ZlcmxheS5zdHlsZS5maWxsID0gJyMwMDAwMDAnO1xuXHRcdHRoaXMub3ZlcmxheS5zdHlsZS5vcGFjaXR5ID0gJzAuNCc7XG5cdFx0dGhpcy5kcmF3X2FyZWEuYXBwZW5kQ2hpbGQodGhpcy5vdmVybGF5KTtcblx0fVxuXG5cdGJpbmRfb3ZlcmxheSgpIHtcblx0XHQvLyBvbiBldmVudCwgdXBkYXRlIG92ZXJsYXlcblx0XHR0aGlzLnBhcmVudC5hZGRFdmVudExpc3RlbmVyKCdkYXRhLXNlbGVjdCcsIChlKSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZV9vdmVybGF5KGUuc3ZnX3VuaXQpO1xuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlX292ZXJsYXkodW5pdCkge1xuXHRcdGxldCBhdHRyaWJ1dGVzID0gW107XG5cdFx0T2JqZWN0LmtleXModW5pdC5hdHRyaWJ1dGVzKS5tYXAoaW5kZXggPT4ge1xuXHRcdFx0YXR0cmlidXRlcy5wdXNoKHVuaXQuYXR0cmlidXRlc1tpbmRleF0pO1xuXHRcdH0pO1xuXG5cdFx0YXR0cmlidXRlcy5maWx0ZXIoYXR0ciA9PiBhdHRyLnNwZWNpZmllZCkubWFwKGF0dHIgPT4ge1xuXHRcdFx0dGhpcy5vdmVybGF5LnNldEF0dHJpYnV0ZShhdHRyLm5hbWUsIGF0dHIubm9kZVZhbHVlKTtcblx0XHR9KTtcblx0fVxuXG5cdG9uX2xlZnRfYXJyb3coKSB7XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KHRoaXMuY3VycmVudF9pbmRleCAtIDEpO1xuXHR9XG5cblx0b25fcmlnaHRfYXJyb3coKSB7XG5cdFx0dGhpcy51cGRhdGVfY3VycmVudF9kYXRhX3BvaW50KHRoaXMuY3VycmVudF9pbmRleCArIDEpO1xuXHR9XG5cblx0c2V0X2F2Z191bml0X3dpZHRoX2FuZF94X29mZnNldCgpIHtcblx0XHR0aGlzLmF2Z191bml0X3dpZHRoID0gdGhpcy53aWR0aC8odGhpcy54Lmxlbmd0aCArIDEpO1xuXHRcdHRoaXMueF9vZmZzZXQgPSB0aGlzLmF2Z191bml0X3dpZHRoO1xuXHR9XG59XG5cbmNsYXNzIExpbmVDaGFydCBleHRlbmRzIEF4aXNDaGFydCB7XG5cdGNvbnN0cnVjdG9yKGFyZ3MpIHtcblx0XHRzdXBlcihhcmdzKTtcblx0XHRpZihPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykgIT09IExpbmVDaGFydC5wcm90b3R5cGUpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLnR5cGUgPSAnbGluZSc7XG5cdFx0dGhpcy5yZWdpb25fZmlsbCA9IGFyZ3MucmVnaW9uX2ZpbGw7XG5cdFx0dGhpcy54X2F4aXNfbW9kZSA9IGFyZ3MueF9heGlzX21vZGUgfHwgJ3NwYW4nO1xuXHRcdHRoaXMueV9heGlzX21vZGUgPSBhcmdzLnlfYXhpc19tb2RlIHx8ICdzcGFuJztcblxuXHRcdHRoaXMuc2V0dXAoKTtcblx0fVxuXG5cdHNldHVwX2dyYXBoX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5zZXR1cF9wYXRoX2dyb3VwcygpO1xuXHRcdHN1cGVyLnNldHVwX2dyYXBoX2NvbXBvbmVudHMoKTtcblx0fVxuXG5cdHNldHVwX3BhdGhfZ3JvdXBzKCkge1xuXHRcdHRoaXMucGF0aHNfZ3JvdXBzID0gW107XG5cdFx0dGhpcy55Lm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0dGhpcy5wYXRoc19ncm91cHNbaV0gPSAkLmNyZWF0ZVNWRygnZycsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAncGF0aC1ncm91cCBwYXRoLWdyb3VwLScgKyBpLFxuXHRcdFx0XHRpbnNpZGU6IHRoaXMuZHJhd19hcmVhXG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHNldHVwX3ZhbHVlcygpIHtcblx0XHRzdXBlci5zZXR1cF92YWx1ZXMoKTtcblx0XHR0aGlzLnVuaXRfYXJncyA9IHtcblx0XHRcdHR5cGU6ICdkb3QnLFxuXHRcdFx0YXJnczogeyByYWRpdXM6IDggfVxuXHRcdH07XG5cdH1cblxuXHRtYWtlX3BhdGhzKCkge1xuXHRcdHRoaXMueS5tYXAoKGQsIGkpID0+IHtcblx0XHRcdHRoaXMubWFrZV9wYXRoKGQsIGksIHRoaXMueF9heGlzX3Bvc2l0aW9ucywgZC55X3RvcHMsIGQuY29sb3IgfHwgdGhpcy5jb2xvcnNbaV0pO1xuXHRcdH0pO1xuXHR9XG5cblx0bWFrZV9wYXRoKGQsIGksIHhfcG9zaXRpb25zLCB5X3Bvc2l0aW9ucywgY29sb3IpIHtcblx0XHRsZXQgcG9pbnRzX2xpc3QgPSB5X3Bvc2l0aW9ucy5tYXAoKHksIGkpID0+ICh4X3Bvc2l0aW9uc1tpXSArICcsJyArIHkpKTtcblx0XHRsZXQgcG9pbnRzX3N0ciA9IHBvaW50c19saXN0LmpvaW4oXCJMXCIpO1xuXG5cdFx0dGhpcy5wYXRoc19ncm91cHNbaV0udGV4dENvbnRlbnQgPSAnJztcblxuXHRcdGQucGF0aCA9ICQuY3JlYXRlU1ZHKCdwYXRoJywge1xuXHRcdFx0aW5zaWRlOiB0aGlzLnBhdGhzX2dyb3Vwc1tpXSxcblx0XHRcdGNsYXNzTmFtZTogYHN0cm9rZSAke2NvbG9yfWAsXG5cdFx0XHRkOiBcIk1cIitwb2ludHNfc3RyXG5cdFx0fSk7XG5cblx0XHRpZih0aGlzLnJlZ2lvbl9maWxsKSB7XG5cdFx0XHRsZXQgZ3JhZGllbnRfaWQgPSdwYXRoLWZpbGwtZ3JhZGllbnQnICsgJy0nICsgY29sb3I7XG5cblx0XHRcdHRoaXMuZ3JhZGllbnRfZGVmID0gJC5jcmVhdGVTVkcoJ2xpbmVhckdyYWRpZW50Jywge1xuXHRcdFx0XHRpbnNpZGU6IHRoaXMuc3ZnX2RlZnMsXG5cdFx0XHRcdGlkOiBncmFkaWVudF9pZCxcblx0XHRcdFx0eDE6IDAsXG5cdFx0XHRcdHgyOiAwLFxuXHRcdFx0XHR5MTogMCxcblx0XHRcdFx0eTI6IDFcblx0XHRcdH0pO1xuXG5cdFx0XHRsZXQgc2V0X2dyYWRpZW50X3N0b3AgPSAoZ3JhZF9lbGVtLCBvZmZzZXQsIGNvbG9yLCBvcGFjaXR5KSA9PiB7XG5cdFx0XHRcdCQuY3JlYXRlU1ZHKCdzdG9wJywge1xuXHRcdFx0XHRcdCdjbGFzc05hbWUnOiAnc3RvcC1jb2xvciAnICsgY29sb3IsXG5cdFx0XHRcdFx0J2luc2lkZSc6IGdyYWRfZWxlbSxcblx0XHRcdFx0XHQnb2Zmc2V0Jzogb2Zmc2V0LFxuXHRcdFx0XHRcdCdzdG9wLW9wYWNpdHknOiBvcGFjaXR5XG5cdFx0XHRcdH0pO1xuXHRcdFx0fTtcblxuXHRcdFx0c2V0X2dyYWRpZW50X3N0b3AodGhpcy5ncmFkaWVudF9kZWYsIFwiMCVcIiwgY29sb3IsIDAuNCk7XG5cdFx0XHRzZXRfZ3JhZGllbnRfc3RvcCh0aGlzLmdyYWRpZW50X2RlZiwgXCI1MCVcIiwgY29sb3IsIDAuMik7XG5cdFx0XHRzZXRfZ3JhZGllbnRfc3RvcCh0aGlzLmdyYWRpZW50X2RlZiwgXCIxMDAlXCIsIGNvbG9yLCAwKTtcblxuXHRcdFx0ZC5yZWdpb25fcGF0aCA9ICQuY3JlYXRlU1ZHKCdwYXRoJywge1xuXHRcdFx0XHRpbnNpZGU6IHRoaXMucGF0aHNfZ3JvdXBzW2ldLFxuXHRcdFx0XHRjbGFzc05hbWU6IGByZWdpb24tZmlsbGAsXG5cdFx0XHRcdGQ6IFwiTVwiICsgYDAsJHt0aGlzLnplcm9fbGluZX1MYCArIHBvaW50c19zdHIgKyBgTCR7dGhpcy53aWR0aH0sJHt0aGlzLnplcm9fbGluZX1gLFxuXHRcdFx0fSk7XG5cblx0XHRcdGQucmVnaW9uX3BhdGguc3R5bGUuc3Ryb2tlID0gXCJub25lXCI7XG5cdFx0XHRkLnJlZ2lvbl9wYXRoLnN0eWxlLmZpbGwgPSBgdXJsKCMke2dyYWRpZW50X2lkfSlgO1xuXHRcdH1cblx0fVxufVxuXG5jbGFzcyBQZXJjZW50YWdlQ2hhcnQgZXh0ZW5kcyBDaGFydCB7XG5cdGNvbnN0cnVjdG9yKGFyZ3MpIHtcblx0XHRzdXBlcihhcmdzKTtcblx0XHR0aGlzLnR5cGUgPSAncGVyY2VudGFnZSc7XG5cblx0XHR0aGlzLmdldF95X2xhYmVsID0gdGhpcy5mb3JtYXRfbGFtYmRhcy55X2xhYmVsO1xuXHRcdHRoaXMuZ2V0X3hfdG9vbHRpcCA9IHRoaXMuZm9ybWF0X2xhbWJkYXMueF90b29sdGlwO1xuXHRcdHRoaXMuZ2V0X3lfdG9vbHRpcCA9IHRoaXMuZm9ybWF0X2xhbWJkYXMueV90b29sdGlwO1xuXG5cdFx0dGhpcy5tYXhfc2xpY2VzID0gMTA7XG5cdFx0dGhpcy5tYXhfbGVnZW5kX3BvaW50cyA9IDY7XG5cblx0XHR0aGlzLmNvbG9ycyA9IGFyZ3MuY29sb3JzO1xuXG5cdFx0aWYoIXRoaXMuY29sb3JzIHx8IHRoaXMuY29sb3JzLmxlbmd0aCA8IHRoaXMuZGF0YS5sYWJlbHMubGVuZ3RoKSB7XG5cdFx0XHR0aGlzLmNvbG9ycyA9IFsnbGlnaHQtYmx1ZScsICdibHVlJywgJ3Zpb2xldCcsICdyZWQnLCAnb3JhbmdlJyxcblx0XHRcdFx0J3llbGxvdycsICdncmVlbicsICdsaWdodC1ncmVlbicsICdwdXJwbGUnLCAnbWFnZW50YSddO1xuXHRcdH1cblxuXHRcdHRoaXMuc2V0dXAoKTtcblx0fVxuXG5cdG1ha2VfY2hhcnRfYXJlYSgpIHtcblx0XHR0aGlzLmNoYXJ0X3dyYXBwZXIuY2xhc3NOYW1lICs9ICcgJyArICdncmFwaC1mb2N1cy1tYXJnaW4nO1xuXHRcdHRoaXMuY2hhcnRfd3JhcHBlci5zdHlsZS5tYXJnaW5Ub3AgPSAnNDVweCc7XG5cblx0XHR0aGlzLnN0YXRzX3dyYXBwZXIuY2xhc3NOYW1lICs9ICcgJyArICdncmFwaC1mb2N1cy1tYXJnaW4nO1xuXHRcdHRoaXMuc3RhdHNfd3JhcHBlci5zdHlsZS5tYXJnaW5Cb3R0b20gPSAnMzBweCc7XG5cdFx0dGhpcy5zdGF0c193cmFwcGVyLnN0eWxlLnBhZGRpbmdUb3AgPSAnMHB4Jztcblx0fVxuXG5cdG1ha2VfZHJhd19hcmVhKCkge1xuXHRcdHRoaXMuY2hhcnRfZGl2ID0gJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdGNsYXNzTmFtZTogJ2RpdicsXG5cdFx0XHRpbnNpZGU6IHRoaXMuY2hhcnRfd3JhcHBlcixcblx0XHRcdHdpZHRoOiB0aGlzLmJhc2Vfd2lkdGgsXG5cdFx0XHRoZWlnaHQ6IHRoaXMuYmFzZV9oZWlnaHRcblx0XHR9KTtcblxuXHRcdHRoaXMuY2hhcnQgPSAkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0Y2xhc3NOYW1lOiAncHJvZ3Jlc3MtY2hhcnQnLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmNoYXJ0X2RpdlxuXHRcdH0pO1xuXHR9XG5cblx0c2V0dXBfY29tcG9uZW50cygpIHtcblx0XHR0aGlzLnBlcmNlbnRhZ2VfYmFyID0gJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdGNsYXNzTmFtZTogJ3Byb2dyZXNzJyxcblx0XHRcdGluc2lkZTogdGhpcy5jaGFydFxuXHRcdH0pO1xuXHR9XG5cblx0c2V0dXBfdmFsdWVzKCkge1xuXHRcdHRoaXMuc2xpY2VfdG90YWxzID0gW107XG5cdFx0bGV0IGFsbF90b3RhbHMgPSB0aGlzLmRhdGEubGFiZWxzLm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0bGV0IHRvdGFsID0gMDtcblx0XHRcdHRoaXMuZGF0YS5kYXRhc2V0cy5tYXAoZSA9PiB7XG5cdFx0XHRcdHRvdGFsICs9IGUudmFsdWVzW2ldO1xuXHRcdFx0fSk7XG5cdFx0XHRyZXR1cm4gW3RvdGFsLCBkXTtcblx0XHR9KS5maWx0ZXIoZCA9PiB7IHJldHVybiBkWzBdID4gMDsgfSk7IC8vIGtlZXAgb25seSBwb3NpdGl2ZSByZXN1bHRzXG5cblx0XHRsZXQgdG90YWxzID0gYWxsX3RvdGFscztcblxuXHRcdGlmKGFsbF90b3RhbHMubGVuZ3RoID4gdGhpcy5tYXhfc2xpY2VzKSB7XG5cdFx0XHRhbGxfdG90YWxzLnNvcnQoKGEsIGIpID0+IHsgcmV0dXJuIGJbMF0gLSBhWzBdOyB9KTtcblxuXHRcdFx0dG90YWxzID0gYWxsX3RvdGFscy5zbGljZSgwLCB0aGlzLm1heF9zbGljZXMtMSk7XG5cdFx0XHRsZXQgb3RoZXJzID0gYWxsX3RvdGFscy5zbGljZSh0aGlzLm1heF9zbGljZXMtMSk7XG5cblx0XHRcdGxldCBzdW1fb2Zfb3RoZXJzID0gMDtcblx0XHRcdG90aGVycy5tYXAoZCA9PiB7c3VtX29mX290aGVycyArPSBkWzBdO30pO1xuXG5cdFx0XHR0b3RhbHMucHVzaChbc3VtX29mX290aGVycywgJ1Jlc3QnXSk7XG5cblx0XHRcdHRoaXMuY29sb3JzW3RoaXMubWF4X3NsaWNlcy0xXSA9ICdncmV5Jztcblx0XHR9XG5cblx0XHR0aGlzLmxhYmVscyA9IFtdO1xuXHRcdHRvdGFscy5tYXAoZCA9PiB7XG5cdFx0XHR0aGlzLnNsaWNlX3RvdGFscy5wdXNoKGRbMF0pO1xuXHRcdFx0dGhpcy5sYWJlbHMucHVzaChkWzFdKTtcblx0XHR9KTtcblxuXHRcdHRoaXMubGVnZW5kX3RvdGFscyA9IHRoaXMuc2xpY2VfdG90YWxzLnNsaWNlKDAsIHRoaXMubWF4X2xlZ2VuZF9wb2ludHMpO1xuXHR9XG5cblx0c2V0dXBfdXRpbHMoKSB7IH1cblxuXHRtYWtlX2dyYXBoX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5ncmFuZF90b3RhbCA9IHRoaXMuc2xpY2VfdG90YWxzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuXHRcdHRoaXMuc2xpY2VzID0gW107XG5cdFx0dGhpcy5zbGljZV90b3RhbHMubWFwKCh0b3RhbCwgaSkgPT4ge1xuXHRcdFx0bGV0IHNsaWNlID0gJC5jcmVhdGUoJ2RpdicsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiBgcHJvZ3Jlc3MtYmFyIGJhY2tncm91bmQgJHt0aGlzLmNvbG9yc1tpXX1gLFxuXHRcdFx0XHRzdHlsZTogYHdpZHRoOiAke3RvdGFsKjEwMC90aGlzLmdyYW5kX3RvdGFsfSVgLFxuXHRcdFx0XHRpbnNpZGU6IHRoaXMucGVyY2VudGFnZV9iYXJcblx0XHRcdH0pO1xuXHRcdFx0dGhpcy5zbGljZXMucHVzaChzbGljZSk7XG5cdFx0fSk7XG5cdH1cblxuXHRiaW5kX3Rvb2x0aXAoKSB7XG5cdFx0dGhpcy5zbGljZXMubWFwKChzbGljZSwgaSkgPT4ge1xuXHRcdFx0c2xpY2UuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsICgpID0+IHtcblx0XHRcdFx0bGV0IGdfb2ZmID0gJC5vZmZzZXQodGhpcy5jaGFydF93cmFwcGVyKSwgcF9vZmYgPSAkLm9mZnNldChzbGljZSk7XG5cblx0XHRcdFx0bGV0IHggPSBwX29mZi5sZWZ0IC0gZ19vZmYubGVmdCArIHNsaWNlLm9mZnNldFdpZHRoLzI7XG5cdFx0XHRcdGxldCB5ID0gcF9vZmYudG9wIC0gZ19vZmYudG9wIC0gNjtcblx0XHRcdFx0bGV0IHRpdGxlID0gKHRoaXMuZm9ybWF0dGVkX2xhYmVscyAmJiB0aGlzLmZvcm1hdHRlZF9sYWJlbHMubGVuZ3RoPjBcblx0XHRcdFx0XHQ/IHRoaXMuZm9ybWF0dGVkX2xhYmVsc1tpXSA6IHRoaXMubGFiZWxzW2ldKSArICc6ICc7XG5cdFx0XHRcdGxldCBwZXJjZW50ID0gKHRoaXMuc2xpY2VfdG90YWxzW2ldKjEwMC90aGlzLmdyYW5kX3RvdGFsKS50b0ZpeGVkKDEpO1xuXG5cdFx0XHRcdHRoaXMudGlwLnNldF92YWx1ZXMoeCwgeSwgdGl0bGUsIHBlcmNlbnQgKyBcIiVcIik7XG5cdFx0XHRcdHRoaXMudGlwLnNob3dfdGlwKCk7XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHNob3dfc3VtbWFyeSgpIHtcblx0XHRsZXQgeF92YWx1ZXMgPSB0aGlzLmZvcm1hdHRlZF9sYWJlbHMgJiYgdGhpcy5mb3JtYXR0ZWRfbGFiZWxzLmxlbmd0aCA+IDBcblx0XHRcdD8gdGhpcy5mb3JtYXR0ZWRfbGFiZWxzIDogdGhpcy5sYWJlbHM7XG5cdFx0dGhpcy5sZWdlbmRfdG90YWxzLm1hcCgoZCwgaSkgPT4ge1xuXHRcdFx0aWYoZCkge1xuXHRcdFx0XHRsZXQgc3RhdHMgPSAkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0XHRcdGNsYXNzTmFtZTogJ3N0YXRzJyxcblx0XHRcdFx0XHRpbnNpZGU6IHRoaXMuc3RhdHNfd3JhcHBlclxuXHRcdFx0XHR9KTtcblx0XHRcdFx0c3RhdHMuaW5uZXJIVE1MID0gYDxzcGFuIGNsYXNzPVwiaW5kaWNhdG9yICR7dGhpcy5jb2xvcnNbaV19XCI+XG5cdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+JHt4X3ZhbHVlc1tpXX06PC9zcGFuPlxuXHRcdFx0XHRcdCR7ZH1cblx0XHRcdFx0PC9zcGFuPmA7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn1cblxuY2xhc3MgSGVhdE1hcCBleHRlbmRzIENoYXJ0IHtcblx0Y29uc3RydWN0b3Ioe1xuXHRcdHN0YXJ0ID0gJycsXG5cdFx0ZG9tYWluID0gJycsXG5cdFx0c3ViZG9tYWluID0gJycsXG5cdFx0ZGF0YSA9IHt9LFxuXHRcdGRpc2NyZXRlX2RvbWFpbnMgPSAwLFxuXHRcdGNvdW50X2xhYmVsID0gJydcblx0fSkge1xuXHRcdHN1cGVyKGFyZ3VtZW50c1swXSk7XG5cblx0XHR0aGlzLnR5cGUgPSAnaGVhdG1hcCc7XG5cblx0XHR0aGlzLmRvbWFpbiA9IGRvbWFpbjtcblx0XHR0aGlzLnN1YmRvbWFpbiA9IHN1YmRvbWFpbjtcblx0XHR0aGlzLmRhdGEgPSBkYXRhO1xuXHRcdHRoaXMuZGlzY3JldGVfZG9tYWlucyA9IGRpc2NyZXRlX2RvbWFpbnM7XG5cdFx0dGhpcy5jb3VudF9sYWJlbCA9IGNvdW50X2xhYmVsO1xuXG5cdFx0bGV0IHRvZGF5ID0gbmV3IERhdGUoKTtcblx0XHR0aGlzLnN0YXJ0ID0gc3RhcnQgfHwgdGhpcy5hZGRfZGF5cyh0b2RheSwgMzY1KTtcblxuXHRcdHRoaXMubGVnZW5kX2NvbG9ycyA9IFsnI2ViZWRmMCcsICcjYzZlNDhiJywgJyM3YmM5NmYnLCAnIzIzOWEzYicsICcjMTk2MTI3J107XG5cblx0XHR0aGlzLnRyYW5zbGF0ZV94ID0gMDtcblx0XHR0aGlzLnNldHVwKCk7XG5cdH1cblxuXHRzZXR1cF9iYXNlX3ZhbHVlcygpIHtcblx0XHR0aGlzLnRvZGF5ID0gbmV3IERhdGUoKTtcblxuXHRcdGlmKCF0aGlzLnN0YXJ0KSB7XG5cdFx0XHR0aGlzLnN0YXJ0ID0gbmV3IERhdGUoKTtcblx0XHRcdHRoaXMuc3RhcnQuc2V0RnVsbFllYXIoIHRoaXMuc3RhcnQuZ2V0RnVsbFllYXIoKSAtIDEgKTtcblx0XHR9XG5cdFx0dGhpcy5maXJzdF93ZWVrX3N0YXJ0ID0gbmV3IERhdGUodGhpcy5zdGFydC50b0RhdGVTdHJpbmcoKSk7XG5cdFx0dGhpcy5sYXN0X3dlZWtfc3RhcnQgPSBuZXcgRGF0ZSh0aGlzLnRvZGF5LnRvRGF0ZVN0cmluZygpKTtcblx0XHRpZih0aGlzLmZpcnN0X3dlZWtfc3RhcnQuZ2V0RGF5KCkgIT09IDcpIHtcblx0XHRcdHRoaXMuYWRkX2RheXModGhpcy5maXJzdF93ZWVrX3N0YXJ0LCAoLTEpICogdGhpcy5maXJzdF93ZWVrX3N0YXJ0LmdldERheSgpKTtcblx0XHR9XG5cdFx0aWYodGhpcy5sYXN0X3dlZWtfc3RhcnQuZ2V0RGF5KCkgIT09IDcpIHtcblx0XHRcdHRoaXMuYWRkX2RheXModGhpcy5sYXN0X3dlZWtfc3RhcnQsICgtMSkgKiB0aGlzLmxhc3Rfd2Vla19zdGFydC5nZXREYXkoKSk7XG5cdFx0fVxuXHRcdHRoaXMubm9fb2ZfY29scyA9IHRoaXMuZ2V0X3dlZWtzX2JldHdlZW4odGhpcy5maXJzdF93ZWVrX3N0YXJ0ICsgJycsIHRoaXMubGFzdF93ZWVrX3N0YXJ0ICsgJycpICsgMTtcblx0fVxuXG5cdHNldF93aWR0aCgpIHtcblx0XHR0aGlzLmJhc2Vfd2lkdGggPSAodGhpcy5ub19vZl9jb2xzKSAqIDEyO1xuXG5cdFx0aWYodGhpcy5kaXNjcmV0ZV9kb21haW5zKSB7XG5cdFx0XHR0aGlzLmJhc2Vfd2lkdGggKz0gKDEyICogMTIpO1xuXHRcdH1cblx0fVxuXG5cdHNldHVwX2NvbXBvbmVudHMoKSB7XG5cdFx0dGhpcy5kb21haW5fbGFiZWxfZ3JvdXAgPSAkLmNyZWF0ZVNWRyhcImdcIiwge1xuXHRcdFx0Y2xhc3NOYW1lOiBcImRvbWFpbi1sYWJlbC1ncm91cCBjaGFydC1sYWJlbFwiLFxuXHRcdFx0aW5zaWRlOiB0aGlzLmRyYXdfYXJlYVxuXHRcdH0pO1xuXHRcdHRoaXMuZGF0YV9ncm91cHMgPSAkLmNyZWF0ZVNWRyhcImdcIiwge1xuXHRcdFx0Y2xhc3NOYW1lOiBcImRhdGEtZ3JvdXBzXCIsXG5cdFx0XHRpbnNpZGU6IHRoaXMuZHJhd19hcmVhLFxuXHRcdFx0dHJhbnNmb3JtOiBgdHJhbnNsYXRlKDAsIDIwKWBcblx0XHR9KTtcblx0fVxuXG5cdHNldHVwX3ZhbHVlcygpIHtcblx0XHR0aGlzLmRvbWFpbl9sYWJlbF9ncm91cC50ZXh0Q29udGVudCA9ICcnO1xuXHRcdHRoaXMuZGF0YV9ncm91cHMudGV4dENvbnRlbnQgPSAnJztcblx0XHR0aGlzLmRpc3RyaWJ1dGlvbiA9IHRoaXMuZ2V0X2Rpc3RyaWJ1dGlvbih0aGlzLmRhdGEsIHRoaXMubGVnZW5kX2NvbG9ycyk7XG5cdFx0dGhpcy5tb250aF9uYW1lcyA9IFtcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsXG5cdFx0XHRcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiXG5cdFx0XTtcblxuXHRcdHRoaXMucmVuZGVyX2FsbF93ZWVrc19hbmRfc3RvcmVfeF92YWx1ZXModGhpcy5ub19vZl9jb2xzKTtcblx0fVxuXG5cdHJlbmRlcl9hbGxfd2Vla3NfYW5kX3N0b3JlX3hfdmFsdWVzKG5vX29mX3dlZWtzKSB7XG5cdFx0bGV0IGN1cnJlbnRfd2Vla19zdW5kYXkgPSBuZXcgRGF0ZSh0aGlzLmZpcnN0X3dlZWtfc3RhcnQpO1xuXHRcdHRoaXMud2Vla19jb2wgPSAwO1xuXHRcdHRoaXMuY3VycmVudF9tb250aCA9IGN1cnJlbnRfd2Vla19zdW5kYXkuZ2V0TW9udGgoKTtcblxuXHRcdHRoaXMubW9udGhzID0gW3RoaXMuY3VycmVudF9tb250aCArICcnXTtcblx0XHR0aGlzLm1vbnRoX3dlZWtzID0ge30sIHRoaXMubW9udGhfc3RhcnRfcG9pbnRzID0gW107XG5cdFx0dGhpcy5tb250aF93ZWVrc1t0aGlzLmN1cnJlbnRfbW9udGhdID0gMDtcblx0XHR0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cy5wdXNoKDEzKTtcblxuXHRcdGZvcih2YXIgaSA9IDA7IGkgPCBub19vZl93ZWVrczsgaSsrKSB7XG5cdFx0XHRsZXQgZGF0YV9ncm91cCwgbW9udGhfY2hhbmdlID0gMDtcblx0XHRcdGxldCBkYXkgPSBuZXcgRGF0ZShjdXJyZW50X3dlZWtfc3VuZGF5KTtcblxuXHRcdFx0W2RhdGFfZ3JvdXAsIG1vbnRoX2NoYW5nZV0gPSB0aGlzLmdldF93ZWVrX3NxdWFyZXNfZ3JvdXAoZGF5LCB0aGlzLndlZWtfY29sKTtcblx0XHRcdHRoaXMuZGF0YV9ncm91cHMuYXBwZW5kQ2hpbGQoZGF0YV9ncm91cCk7XG5cdFx0XHR0aGlzLndlZWtfY29sICs9IDEgKyBwYXJzZUludCh0aGlzLmRpc2NyZXRlX2RvbWFpbnMgJiYgbW9udGhfY2hhbmdlKTtcblx0XHRcdHRoaXMubW9udGhfd2Vla3NbdGhpcy5jdXJyZW50X21vbnRoXSsrO1xuXHRcdFx0aWYobW9udGhfY2hhbmdlKSB7XG5cdFx0XHRcdHRoaXMuY3VycmVudF9tb250aCA9ICh0aGlzLmN1cnJlbnRfbW9udGggKyAxKSAlIDEyO1xuXHRcdFx0XHR0aGlzLm1vbnRocy5wdXNoKHRoaXMuY3VycmVudF9tb250aCArICcnKTtcblx0XHRcdFx0dGhpcy5tb250aF93ZWVrc1t0aGlzLmN1cnJlbnRfbW9udGhdID0gMTtcblx0XHRcdH1cblx0XHRcdHRoaXMuYWRkX2RheXMoY3VycmVudF93ZWVrX3N1bmRheSwgNyk7XG5cdFx0fVxuXHRcdHRoaXMucmVuZGVyX21vbnRoX2xhYmVscygpO1xuXHR9XG5cblx0Z2V0X3dlZWtfc3F1YXJlc19ncm91cChjdXJyZW50X2RhdGUsIGluZGV4KSB7XG5cdFx0Y29uc3Qgbm9fb2Zfd2Vla2RheXMgPSA3O1xuXHRcdGNvbnN0IHNxdWFyZV9zaWRlID0gMTA7XG5cdFx0Y29uc3QgY2VsbF9wYWRkaW5nID0gMjtcblx0XHRjb25zdCBzdGVwID0gMTtcblxuXHRcdGxldCBtb250aF9jaGFuZ2UgPSAwO1xuXHRcdGxldCB3ZWVrX2NvbF9jaGFuZ2UgPSAwO1xuXG5cdFx0bGV0IGRhdGFfZ3JvdXAgPSAkLmNyZWF0ZVNWRyhcImdcIiwge1xuXHRcdFx0Y2xhc3NOYW1lOiBcImRhdGEtZ3JvdXBcIixcblx0XHRcdGluc2lkZTogdGhpcy5kYXRhX2dyb3Vwc1xuXHRcdH0pO1xuXG5cdFx0Zm9yKHZhciB5ID0gMCwgaSA9IDA7IGkgPCBub19vZl93ZWVrZGF5czsgaSArPSBzdGVwLCB5ICs9IChzcXVhcmVfc2lkZSArIGNlbGxfcGFkZGluZykpIHtcblx0XHRcdGxldCBkYXRhX3ZhbHVlID0gMDtcblx0XHRcdGxldCBjb2xvcl9pbmRleCA9IDA7XG5cblx0XHRcdGxldCB0aW1lc3RhbXAgPSBNYXRoLmZsb29yKGN1cnJlbnRfZGF0ZS5nZXRUaW1lKCkvMTAwMCkudG9GaXhlZCgxKTtcblxuXHRcdFx0aWYodGhpcy5kYXRhW3RpbWVzdGFtcF0pIHtcblx0XHRcdFx0ZGF0YV92YWx1ZSA9IHRoaXMuZGF0YVt0aW1lc3RhbXBdO1xuXHRcdFx0XHRjb2xvcl9pbmRleCA9IHRoaXMuZ2V0X21heF9jaGVja3BvaW50KGRhdGFfdmFsdWUsIHRoaXMuZGlzdHJpYnV0aW9uKTtcblx0XHRcdH1cblxuXHRcdFx0aWYodGhpcy5kYXRhW01hdGgucm91bmQodGltZXN0YW1wKV0pIHtcblx0XHRcdFx0ZGF0YV92YWx1ZSA9IHRoaXMuZGF0YVtNYXRoLnJvdW5kKHRpbWVzdGFtcCldO1xuXHRcdFx0XHRjb2xvcl9pbmRleCA9IHRoaXMuZ2V0X21heF9jaGVja3BvaW50KGRhdGFfdmFsdWUsIHRoaXMuZGlzdHJpYnV0aW9uKTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IHggPSAxMyArIChpbmRleCArIHdlZWtfY29sX2NoYW5nZSkgKiAxMjtcblxuXHRcdFx0JC5jcmVhdGVTVkcoXCJyZWN0XCIsIHtcblx0XHRcdFx0Y2xhc3NOYW1lOiAnZGF5Jyxcblx0XHRcdFx0aW5zaWRlOiBkYXRhX2dyb3VwLFxuXHRcdFx0XHR4OiB4LFxuXHRcdFx0XHR5OiB5LFxuXHRcdFx0XHR3aWR0aDogc3F1YXJlX3NpZGUsXG5cdFx0XHRcdGhlaWdodDogc3F1YXJlX3NpZGUsXG5cdFx0XHRcdGZpbGw6ICB0aGlzLmxlZ2VuZF9jb2xvcnNbY29sb3JfaW5kZXhdLFxuXHRcdFx0XHQnZGF0YS1kYXRlJzogdGhpcy5nZXRfZGRfbW1feXl5eShjdXJyZW50X2RhdGUpLFxuXHRcdFx0XHQnZGF0YS12YWx1ZSc6IGRhdGFfdmFsdWUsXG5cdFx0XHRcdCdkYXRhLWRheSc6IGN1cnJlbnRfZGF0ZS5nZXREYXkoKVxuXHRcdFx0fSk7XG5cblx0XHRcdGxldCBuZXh0X2RhdGUgPSBuZXcgRGF0ZShjdXJyZW50X2RhdGUpO1xuXHRcdFx0dGhpcy5hZGRfZGF5cyhuZXh0X2RhdGUsIDEpO1xuXHRcdFx0aWYobmV4dF9kYXRlLmdldE1vbnRoKCkgLSBjdXJyZW50X2RhdGUuZ2V0TW9udGgoKSkge1xuXHRcdFx0XHRtb250aF9jaGFuZ2UgPSAxO1xuXHRcdFx0XHRpZih0aGlzLmRpc2NyZXRlX2RvbWFpbnMpIHtcblx0XHRcdFx0XHR3ZWVrX2NvbF9jaGFuZ2UgPSAxO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5tb250aF9zdGFydF9wb2ludHMucHVzaCgxMyArIChpbmRleCArIHdlZWtfY29sX2NoYW5nZSkgKiAxMik7XG5cdFx0XHR9XG5cdFx0XHRjdXJyZW50X2RhdGUgPSBuZXh0X2RhdGU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIFtkYXRhX2dyb3VwLCBtb250aF9jaGFuZ2VdO1xuXHR9XG5cblx0cmVuZGVyX21vbnRoX2xhYmVscygpIHtcblx0XHQvLyB0aGlzLmZpcnN0X21vbnRoX2xhYmVsID0gMTtcblx0XHQvLyBpZiAodGhpcy5maXJzdF93ZWVrX3N0YXJ0LmdldERhdGUoKSA+IDgpIHtcblx0XHQvLyBcdHRoaXMuZmlyc3RfbW9udGhfbGFiZWwgPSAwO1xuXHRcdC8vIH1cblx0XHQvLyB0aGlzLmxhc3RfbW9udGhfbGFiZWwgPSAxO1xuXG5cdFx0Ly8gbGV0IGZpcnN0X21vbnRoID0gdGhpcy5tb250aHMuc2hpZnQoKTtcblx0XHQvLyBsZXQgZmlyc3RfbW9udGhfc3RhcnQgPSB0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cy5zaGlmdCgpO1xuXHRcdC8vIHJlbmRlciBmaXJzdCBtb250aCBpZlxuXG5cdFx0Ly8gbGV0IGxhc3RfbW9udGggPSB0aGlzLm1vbnRocy5wb3AoKTtcblx0XHQvLyBsZXQgbGFzdF9tb250aF9zdGFydCA9IHRoaXMubW9udGhfc3RhcnRfcG9pbnRzLnBvcCgpO1xuXHRcdC8vIHJlbmRlciBsYXN0IG1vbnRoIGlmXG5cblx0XHR0aGlzLm1vbnRocy5zaGlmdCgpO1xuXHRcdHRoaXMubW9udGhfc3RhcnRfcG9pbnRzLnNoaWZ0KCk7XG5cdFx0dGhpcy5tb250aHMucG9wKCk7XG5cdFx0dGhpcy5tb250aF9zdGFydF9wb2ludHMucG9wKCk7XG5cblx0XHR0aGlzLm1vbnRoX3N0YXJ0X3BvaW50cy5tYXAoKHN0YXJ0LCBpKSA9PiB7XG5cdFx0XHRsZXQgbW9udGhfbmFtZSA9ICB0aGlzLm1vbnRoX25hbWVzW3RoaXMubW9udGhzW2ldXS5zdWJzdHJpbmcoMCwgMyk7XG5cblx0XHRcdCQuY3JlYXRlU1ZHKCd0ZXh0Jywge1xuXHRcdFx0XHRjbGFzc05hbWU6ICd5LXZhbHVlLXRleHQnLFxuXHRcdFx0XHRpbnNpZGU6IHRoaXMuZG9tYWluX2xhYmVsX2dyb3VwLFxuXHRcdFx0XHR4OiBzdGFydCArIDEyLFxuXHRcdFx0XHR5OiAxMCxcblx0XHRcdFx0ZHk6ICcuMzJlbScsXG5cdFx0XHRcdGlubmVySFRNTDogbW9udGhfbmFtZVxuXHRcdFx0fSk7XG5cblx0XHR9KTtcblx0fVxuXG5cdG1ha2VfZ3JhcGhfY29tcG9uZW50cygpIHtcblx0XHRBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChcblx0XHRcdHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoJy5ncmFwaC1zdGF0cy1jb250YWluZXIsIC5zdWItdGl0bGUsIC50aXRsZScpXG5cdFx0KS5tYXAoZCA9PiB7XG5cdFx0XHRkLnN0eWxlLmRpc3BsYXkgPSAnTm9uZSc7XG5cdFx0fSk7XG5cdFx0dGhpcy5jaGFydF93cmFwcGVyLnN0eWxlLm1hcmdpblRvcCA9ICcwcHgnO1xuXHRcdHRoaXMuY2hhcnRfd3JhcHBlci5zdHlsZS5wYWRkaW5nVG9wID0gJzBweCc7XG5cdH1cblxuXHRiaW5kX3Rvb2x0aXAoKSB7XG5cdFx0QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoXG5cdFx0XHRkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFwiLmRhdGEtZ3JvdXAgLmRheVwiKVxuXHRcdCkubWFwKGVsID0+IHtcblx0XHRcdGVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZW50ZXInLCAoZSkgPT4ge1xuXHRcdFx0XHRsZXQgY291bnQgPSBlLnRhcmdldC5nZXRBdHRyaWJ1dGUoJ2RhdGEtdmFsdWUnKTtcblx0XHRcdFx0bGV0IGRhdGVfcGFydHMgPSBlLnRhcmdldC5nZXRBdHRyaWJ1dGUoJ2RhdGEtZGF0ZScpLnNwbGl0KCctJyk7XG5cblx0XHRcdFx0bGV0IG1vbnRoID0gdGhpcy5tb250aF9uYW1lc1twYXJzZUludChkYXRlX3BhcnRzWzFdKS0xXS5zdWJzdHJpbmcoMCwgMyk7XG5cblx0XHRcdFx0bGV0IGdfb2ZmID0gdGhpcy5jaGFydF93cmFwcGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLCBwX29mZiA9IGUudGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG5cdFx0XHRcdGxldCB3aWR0aCA9IHBhcnNlSW50KGUudGFyZ2V0LmdldEF0dHJpYnV0ZSgnd2lkdGgnKSk7XG5cdFx0XHRcdGxldCB4ID0gcF9vZmYubGVmdCAtIGdfb2ZmLmxlZnQgKyAod2lkdGgrMikvMjtcblx0XHRcdFx0bGV0IHkgPSBwX29mZi50b3AgLSBnX29mZi50b3AgLSAod2lkdGgrMikvMjtcblx0XHRcdFx0bGV0IHZhbHVlID0gY291bnQgKyAnICcgKyB0aGlzLmNvdW50X2xhYmVsO1xuXHRcdFx0XHRsZXQgbmFtZSA9ICcgb24gJyArIG1vbnRoICsgJyAnICsgZGF0ZV9wYXJ0c1swXSArICcsICcgKyBkYXRlX3BhcnRzWzJdO1xuXG5cdFx0XHRcdHRoaXMudGlwLnNldF92YWx1ZXMoeCwgeSwgbmFtZSwgdmFsdWUsIFtdLCAxKTtcblx0XHRcdFx0dGhpcy50aXAuc2hvd190aXAoKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlKGRhdGEpIHtcblx0XHR0aGlzLmRhdGEgPSBkYXRhO1xuXHRcdHRoaXMuc2V0dXBfdmFsdWVzKCk7XG5cdFx0dGhpcy5iaW5kX3Rvb2x0aXAoKTtcblx0fVxuXG5cdGdldF9kaXN0cmlidXRpb24oZGF0YT17fSwgbWFwcGVyX2FycmF5KSB7XG5cdFx0bGV0IGRhdGFfdmFsdWVzID0gT2JqZWN0LmtleXMoZGF0YSkubWFwKGtleSA9PiBkYXRhW2tleV0pO1xuXHRcdGxldCBkYXRhX21heF92YWx1ZSA9IE1hdGgubWF4KC4uLmRhdGFfdmFsdWVzKTtcblxuXHRcdGxldCBkaXN0cmlidXRpb25fc3RlcCA9IDEgLyAobWFwcGVyX2FycmF5Lmxlbmd0aCAtIDEpO1xuXHRcdGxldCBkaXN0cmlidXRpb24gPSBbXTtcblxuXHRcdG1hcHBlcl9hcnJheS5tYXAoKGNvbG9yLCBpKSA9PiB7XG5cdFx0XHRsZXQgY2hlY2twb2ludCA9IGRhdGFfbWF4X3ZhbHVlICogKGRpc3RyaWJ1dGlvbl9zdGVwICogaSk7XG5cdFx0XHRkaXN0cmlidXRpb24ucHVzaChjaGVja3BvaW50KTtcblx0XHR9KTtcblxuXHRcdHJldHVybiBkaXN0cmlidXRpb247XG5cdH1cblxuXHRnZXRfbWF4X2NoZWNrcG9pbnQodmFsdWUsIGRpc3RyaWJ1dGlvbikge1xuXHRcdHJldHVybiBkaXN0cmlidXRpb24uZmlsdGVyKChkLCBpKSA9PiB7XG5cdFx0XHRpZihpID09PSAxKSB7XG5cdFx0XHRcdHJldHVybiBkaXN0cmlidXRpb25bMF0gPCB2YWx1ZTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBkIDw9IHZhbHVlO1xuXHRcdH0pLmxlbmd0aCAtIDE7XG5cdH1cblxuXHQvLyBUT0RPOiBkYXRlIHV0aWxzLCBtb3ZlIHRoZXNlIG91dFxuXG5cdC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xMTI1MjE2Ny82NDk1MDQzXG5cdHRyZWF0X2FzX3V0YyhkYXRlX3N0cikge1xuXHRcdGxldCByZXN1bHQgPSBuZXcgRGF0ZShkYXRlX3N0cik7XG5cdFx0cmVzdWx0LnNldE1pbnV0ZXMocmVzdWx0LmdldE1pbnV0ZXMoKSAtIHJlc3VsdC5nZXRUaW1lem9uZU9mZnNldCgpKTtcblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0Z2V0X2RkX21tX3l5eXkoZGF0ZSkge1xuXHRcdGxldCBkZCA9IGRhdGUuZ2V0RGF0ZSgpO1xuXHRcdGxldCBtbSA9IGRhdGUuZ2V0TW9udGgoKSArIDE7IC8vIGdldE1vbnRoKCkgaXMgemVyby1iYXNlZFxuXHRcdHJldHVybiBbXG5cdFx0XHQoZGQ+OSA/ICcnIDogJzAnKSArIGRkLFxuXHRcdFx0KG1tPjkgPyAnJyA6ICcwJykgKyBtbSxcblx0XHRcdGRhdGUuZ2V0RnVsbFllYXIoKVxuXHRcdF0uam9pbignLScpO1xuXHR9XG5cblx0Z2V0X3dlZWtzX2JldHdlZW4oc3RhcnRfZGF0ZV9zdHIsIGVuZF9kYXRlX3N0cikge1xuXHRcdHJldHVybiBNYXRoLmNlaWwodGhpcy5nZXRfZGF5c19iZXR3ZWVuKHN0YXJ0X2RhdGVfc3RyLCBlbmRfZGF0ZV9zdHIpIC8gNyk7XG5cdH1cblxuXHRnZXRfZGF5c19iZXR3ZWVuKHN0YXJ0X2RhdGVfc3RyLCBlbmRfZGF0ZV9zdHIpIHtcblx0XHRsZXQgbWlsbGlzZWNvbmRzX3Blcl9kYXkgPSAyNCAqIDYwICogNjAgKiAxMDAwO1xuXHRcdHJldHVybiAodGhpcy50cmVhdF9hc191dGMoZW5kX2RhdGVfc3RyKSAtIHRoaXMudHJlYXRfYXNfdXRjKHN0YXJ0X2RhdGVfc3RyKSkgLyBtaWxsaXNlY29uZHNfcGVyX2RheTtcblx0fVxuXG5cdC8vIG11dGF0ZXNcblx0YWRkX2RheXMoZGF0ZSwgbnVtYmVyX29mX2RheXMpIHtcblx0XHRkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBudW1iZXJfb2ZfZGF5cyk7XG5cdH1cblxuXHRnZXRfbW9udGhfbmFtZSgpIHt9XG59XG5cbmNsYXNzIFN2Z1RpcCB7XG5cdGNvbnN0cnVjdG9yKHtcblx0XHRwYXJlbnQgPSBudWxsXG5cdH0pIHtcblx0XHR0aGlzLnBhcmVudCA9IHBhcmVudDtcblx0XHR0aGlzLnRpdGxlX25hbWUgPSAnJztcblx0XHR0aGlzLnRpdGxlX3ZhbHVlID0gJyc7XG5cdFx0dGhpcy5saXN0X3ZhbHVlcyA9IFtdO1xuXHRcdHRoaXMudGl0bGVfdmFsdWVfZmlyc3QgPSAwO1xuXG5cdFx0dGhpcy54ID0gMDtcblx0XHR0aGlzLnkgPSAwO1xuXG5cdFx0dGhpcy50b3AgPSAwO1xuXHRcdHRoaXMubGVmdCA9IDA7XG5cblx0XHR0aGlzLnNldHVwKCk7XG5cdH1cblxuXHRzZXR1cCgpIHtcblx0XHR0aGlzLm1ha2VfdG9vbHRpcCgpO1xuXHR9XG5cblx0cmVmcmVzaCgpIHtcblx0XHR0aGlzLmZpbGwoKTtcblx0XHR0aGlzLmNhbGNfcG9zaXRpb24oKTtcblx0XHQvLyB0aGlzLnNob3dfdGlwKCk7XG5cdH1cblxuXHRtYWtlX3Rvb2x0aXAoKSB7XG5cdFx0dGhpcy5jb250YWluZXIgPSAkLmNyZWF0ZSgnZGl2Jywge1xuXHRcdFx0aW5zaWRlOiB0aGlzLnBhcmVudCxcblx0XHRcdGNsYXNzTmFtZTogJ2dyYXBoLXN2Zy10aXAgY29tcGFyaXNvbicsXG5cdFx0XHRpbm5lckhUTUw6IGA8c3BhbiBjbGFzcz1cInRpdGxlXCI+PC9zcGFuPlxuXHRcdFx0XHQ8dWwgY2xhc3M9XCJkYXRhLXBvaW50LWxpc3RcIj48L3VsPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwic3ZnLXBvaW50ZXJcIj48L2Rpdj5gXG5cdFx0fSk7XG5cdFx0dGhpcy5oaWRlX3RpcCgpO1xuXG5cdFx0dGhpcy50aXRsZSA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy50aXRsZScpO1xuXHRcdHRoaXMuZGF0YV9wb2ludF9saXN0ID0gdGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvcignLmRhdGEtcG9pbnQtbGlzdCcpO1xuXG5cdFx0dGhpcy5wYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsICgpID0+IHtcblx0XHRcdHRoaXMuaGlkZV90aXAoKTtcblx0XHR9KTtcblx0fVxuXG5cdGZpbGwoKSB7XG5cdFx0bGV0IHRpdGxlO1xuXHRcdGlmKHRoaXMudGl0bGVfdmFsdWVfZmlyc3QpIHtcblx0XHRcdHRpdGxlID0gYDxzdHJvbmc+JHt0aGlzLnRpdGxlX3ZhbHVlfTwvc3Ryb25nPiR7dGhpcy50aXRsZV9uYW1lfWA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRpdGxlID0gYCR7dGhpcy50aXRsZV9uYW1lfTxzdHJvbmc+JHt0aGlzLnRpdGxlX3ZhbHVlfTwvc3Ryb25nPmA7XG5cdFx0fVxuXHRcdHRoaXMudGl0bGUuaW5uZXJIVE1MID0gdGl0bGU7XG5cdFx0dGhpcy5kYXRhX3BvaW50X2xpc3QuaW5uZXJIVE1MID0gJyc7XG5cblx0XHR0aGlzLmxpc3RfdmFsdWVzLm1hcCgoc2V0KSA9PiB7XG5cdFx0XHRsZXQgbGkgPSAkLmNyZWF0ZSgnbGknLCB7XG5cdFx0XHRcdGNsYXNzTmFtZTogYGJvcmRlci10b3AgJHtzZXQuY29sb3IgfHwgJ2JsYWNrJ31gLFxuXHRcdFx0XHRpbm5lckhUTUw6IGA8c3Ryb25nIHN0eWxlPVwiZGlzcGxheTogYmxvY2s7XCI+JHtzZXQudmFsdWUgPyBzZXQudmFsdWUgOiAnJyB9PC9zdHJvbmc+XG5cdFx0XHRcdFx0JHtzZXQudGl0bGUgPyBzZXQudGl0bGUgOiAnJyB9YFxuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMuZGF0YV9wb2ludF9saXN0LmFwcGVuZENoaWxkKGxpKTtcblx0XHR9KTtcblx0fVxuXG5cdGNhbGNfcG9zaXRpb24oKSB7XG5cdFx0dGhpcy50b3AgPSB0aGlzLnkgLSB0aGlzLmNvbnRhaW5lci5vZmZzZXRIZWlnaHQ7XG5cdFx0dGhpcy5sZWZ0ID0gdGhpcy54IC0gdGhpcy5jb250YWluZXIub2Zmc2V0V2lkdGgvMjtcblx0XHRsZXQgbWF4X2xlZnQgPSB0aGlzLnBhcmVudC5vZmZzZXRXaWR0aCAtIHRoaXMuY29udGFpbmVyLm9mZnNldFdpZHRoO1xuXG5cdFx0bGV0IHBvaW50ZXIgPSB0aGlzLmNvbnRhaW5lci5xdWVyeVNlbGVjdG9yKCcuc3ZnLXBvaW50ZXInKTtcblxuXHRcdGlmKHRoaXMubGVmdCA8IDApIHtcblx0XHRcdHBvaW50ZXIuc3R5bGUubGVmdCA9IGBjYWxjKDUwJSAtICR7LTEgKiB0aGlzLmxlZnR9cHgpYDtcblx0XHRcdHRoaXMubGVmdCA9IDA7XG5cdFx0fSBlbHNlIGlmKHRoaXMubGVmdCA+IG1heF9sZWZ0KSB7XG5cdFx0XHRsZXQgZGVsdGEgPSB0aGlzLmxlZnQgLSBtYXhfbGVmdDtcblx0XHRcdHBvaW50ZXIuc3R5bGUubGVmdCA9IGBjYWxjKDUwJSArICR7ZGVsdGF9cHgpYDtcblx0XHRcdHRoaXMubGVmdCA9IG1heF9sZWZ0O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwb2ludGVyLnN0eWxlLmxlZnQgPSBgNTAlYDtcblx0XHR9XG5cdH1cblxuXHRzZXRfdmFsdWVzKHgsIHksIHRpdGxlX25hbWUgPSAnJywgdGl0bGVfdmFsdWUgPSAnJywgbGlzdF92YWx1ZXMgPSBbXSwgdGl0bGVfdmFsdWVfZmlyc3QgPSAwKSB7XG5cdFx0dGhpcy50aXRsZV9uYW1lID0gdGl0bGVfbmFtZTtcblx0XHR0aGlzLnRpdGxlX3ZhbHVlID0gdGl0bGVfdmFsdWU7XG5cdFx0dGhpcy5saXN0X3ZhbHVlcyA9IGxpc3RfdmFsdWVzO1xuXHRcdHRoaXMueCA9IHg7XG5cdFx0dGhpcy55ID0geTtcblx0XHR0aGlzLnRpdGxlX3ZhbHVlX2ZpcnN0ID0gdGl0bGVfdmFsdWVfZmlyc3Q7XG5cdFx0dGhpcy5yZWZyZXNoKCk7XG5cdH1cblxuXHRoaWRlX3RpcCgpIHtcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS50b3AgPSAnMHB4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJzBweCc7XG5cdFx0dGhpcy5jb250YWluZXIuc3R5bGUub3BhY2l0eSA9ICcwJztcblx0fVxuXG5cdHNob3dfdGlwKCkge1xuXHRcdHRoaXMuY29udGFpbmVyLnN0eWxlLnRvcCA9IHRoaXMudG9wICsgJ3B4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gdGhpcy5sZWZ0ICsgJ3B4Jztcblx0XHR0aGlzLmNvbnRhaW5lci5zdHlsZS5vcGFjaXR5ID0gJzEnO1xuXHR9XG59XG4iXSwibmFtZXMiOlsiJCIsImV4cHIiLCJjb24iLCJkb2N1bWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJmaW5kTm9kZUluZGV4Iiwibm9kZSIsImkiLCJwcmV2aW91c1NpYmxpbmciLCJjcmVhdGUiLCJ0YWciLCJvIiwiZWxlbWVudCIsImNyZWF0ZUVsZW1lbnQiLCJ2YWwiLCJhcHBlbmRDaGlsZCIsInJlZiIsInBhcmVudE5vZGUiLCJpbnNlcnRCZWZvcmUiLCJzZXRBdHRyaWJ1dGUiLCJjcmVhdGVTVkciLCJjcmVhdGVFbGVtZW50TlMiLCJydW5TVkdBbmltYXRpb24iLCJzdmdfY29udGFpbmVyIiwiZWxlbWVudHMiLCJuZXdfZWxlbWVudHMiLCJhbmltX2VsZW1lbnRzIiwibWFwIiwib2JqIiwicGFyZW50IiwidW5pdCIsImFuaW1fZWxlbWVudCIsIm5ld19lbGVtZW50IiwiYW5pbWF0ZVNWRyIsInB1c2giLCJyZXBsYWNlQ2hpbGQiLCJhcnJheSIsImluZGV4Iiwib2JqZWN0Iiwia2V5IiwiYW5pbV9zdmciLCJjbG9uZU5vZGUiLCJwcm9wcyIsImR1ciIsImVhc2luZ190eXBlIiwidHlwZSIsInVuZGVmaW5lZCIsIm9sZF92YWx1ZXMiLCJlYXNpbmciLCJhdHRyaWJ1dGVOYW1lIiwiYW5pbWF0ZV9lbGVtZW50IiwiY3VycmVudF92YWx1ZSIsImdldEF0dHJpYnV0ZSIsInZhbHVlIiwiYW5pbV9hdHRyIiwib2Zmc2V0IiwicmVjdCIsImdldEJvdW5kaW5nQ2xpZW50UmVjdCIsInRvcCIsImRvY3VtZW50RWxlbWVudCIsInNjcm9sbFRvcCIsImJvZHkiLCJsZWZ0Iiwic2Nyb2xsTGVmdCIsImlzRWxlbWVudEluVmlld3BvcnQiLCJlbCIsImJvdHRvbSIsIndpbmRvdyIsImlubmVySGVpZ2h0IiwiY2xpZW50SGVpZ2h0IiwicmlnaHQiLCJpbm5lcldpZHRoIiwiY2xpZW50V2lkdGgiLCJiaW5kIiwiZXZlbnQiLCJjYWxsYmFjayIsInNwbGl0IiwiZm9yRWFjaCIsImFkZEV2ZW50TGlzdGVuZXIiLCJ1bmJpbmQiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiZmlyZSIsInRhcmdldCIsInByb3BlcnRpZXMiLCJldnQiLCJjcmVhdGVFdmVudCIsImluaXRFdmVudCIsImoiLCJkaXNwYXRjaEV2ZW50IiwiZmxvYXRfMiIsImQiLCJwYXJzZUZsb2F0IiwidG9GaXhlZCIsImFycmF5c19lcXVhbCIsImFycjEiLCJhcnIyIiwibGVuZ3RoIiwiYXJlX2VxdWFsIiwiQ2hhcnQiLCJoZWlnaHQiLCJ0aXRsZSIsInN1YnRpdGxlIiwiZGF0YSIsImZvcm1hdF9sYW1iZGFzIiwic3VtbWFyeSIsImlzX25hdmlnYWJsZSIsIk9iamVjdCIsImdldFByb3RvdHlwZU9mIiwicHJvdG90eXBlIiwiTGluZUNoYXJ0IiwiYXJndW1lbnRzIiwiQmFyQ2hhcnQiLCJQZXJjZW50YWdlQ2hhcnQiLCJIZWF0TWFwIiwicmF3X2NoYXJ0X2FyZ3MiLCJzcGVjaWZpY192YWx1ZXMiLCJjdXJyZW50X2luZGV4IiwiY2hhcnRfdHlwZXMiLCJzZXRfbWFyZ2lucyIsImluY2x1ZGVzIiwiZXJyb3IiLCJjb21wYXRpYmxlX3R5cGVzIiwiYmFzZV9oZWlnaHQiLCJ0cmFuc2xhdGVfeCIsInRyYW5zbGF0ZV95IiwiYmluZF93aW5kb3dfZXZlbnRzIiwicmVmcmVzaCIsImluaXQiLCJzZXR1cF9iYXNlX3ZhbHVlcyIsInNldF93aWR0aCIsInNldHVwX2NvbnRhaW5lciIsInNldHVwX2NvbXBvbmVudHMiLCJzZXR1cF92YWx1ZXMiLCJzZXR1cF91dGlscyIsIm1ha2VfZ3JhcGhfY29tcG9uZW50cyIsIm1ha2VfdG9vbHRpcCIsInNob3dfY3VzdG9tX3N1bW1hcnkiLCJzaG93X3N1bW1hcnkiLCJzZXR1cF9uYXZpZ2F0aW9uIiwic3BlY2lhbF92YWx1ZXNfd2lkdGgiLCJnZXRfc3Ryd2lkdGgiLCJiYXNlX3dpZHRoIiwib2Zmc2V0V2lkdGgiLCJ3aWR0aCIsImNvbnRhaW5lciIsImlubmVySFRNTCIsImNoYXJ0X3dyYXBwZXIiLCJzdGF0c193cmFwcGVyIiwibWFrZV9jaGFydF9hcmVhIiwibWFrZV9kcmF3X2FyZWEiLCJzdmciLCJzdmdfZGVmcyIsImRyYXdfYXJlYSIsInRpcCIsIlN2Z1RpcCIsImJpbmRfdG9vbHRpcCIsInN0YXRzIiwiY29sb3IiLCJtYWtlX292ZXJsYXkiLCJiaW5kX292ZXJsYXkiLCJlIiwia2V5Q29kZSIsIm9uX2xlZnRfYXJyb3ciLCJvbl9yaWdodF9hcnJvdyIsIm9uX3VwX2Fycm93Iiwib25fZG93bl9hcnJvdyIsIm9uX2VudGVyX2tleSIsImRhdGFfcG9pbnQiLCJ5IiwiZGF0YV9rZXkiLCJzbGljZSIsImxhYmVsIiwieCIsImdldF9kYXRhX3BvaW50Iiwic3RyaW5nIiwiQXhpc0NoYXJ0IiwiYXJncyIsImxhYmVscyIsImRhdGFzZXRzIiwiZ2V0X3lfbGFiZWwiLCJ5X2xhYmVsIiwiZ2V0X3lfdG9vbHRpcCIsInlfdG9vbHRpcCIsImdldF94X3Rvb2x0aXAiLCJ4X3Rvb2x0aXAiLCJjb2xvcnMiLCJ6ZXJvX2xpbmUiLCJ2YWx1ZXMiLCJpc05hTiIsInNldHVwX3giLCJzZXR1cF95Iiwic2V0X2F2Z191bml0X3dpZHRoX2FuZF94X29mZnNldCIsInhfYXhpc19wb3NpdGlvbnMiLCJ4X29sZF9heGlzX3Bvc2l0aW9ucyIsInhfb2Zmc2V0IiwiYXZnX3VuaXRfd2lkdGgiLCJ5X2F4aXNfdmFsdWVzIiwieV9vbGRfYXhpc192YWx1ZXMiLCJnZXRfYWxsX3lfdmFsdWVzIiwieV9zdW1zIiwiY29uY2F0IiwiZ2V0X3lfYXhpc19wb2ludHMiLCJ5X3B0cyIsInZhbHVlX3JhbmdlIiwibXVsdGlwbGllciIsIm9sZF9tdWx0aXBsaWVyIiwiemVyb19pbmRleCIsImluZGV4T2YiLCJpbnRlcnZhbCIsImludGVydmFsX2hlaWdodCIsIm9sZF96ZXJvX2xpbmUiLCJzZXR1cF9tYXJrZXJfY29tcG9uZW50cyIsInNldHVwX2FnZ3JlZ2F0aW9uX2NvbXBvbmVudHMiLCJzZXR1cF9ncmFwaF9jb21wb25lbnRzIiwieV9heGlzX2dyb3VwIiwiY2xhc3NOYW1lIiwiaW5zaWRlIiwieF9heGlzX2dyb3VwIiwic3BlY2lmaWNfeV9ncm91cCIsInN1bV9ncm91cCIsImF2ZXJhZ2VfZ3JvdXAiLCJzdmdfdW5pdHNfZ3JvdXBzIiwibWFrZV95X2F4aXMiLCJtYWtlX3hfYXhpcyIsImRyYXdfZ3JhcGgiLCJtYWtlX3lfc3BlY2lmaWNzIiwiYW5pbWF0ZSIsInN0YXJ0X2F0IiwidGV4dF9zdGFydF9hdCIsImF4aXNfbGluZV9jbGFzcyIsInhfYXhpc19tb2RlIiwibWFrZV9hbmltX3hfYXhpcyIsInRleHRDb250ZW50IiwicG9pbnQiLCJtYWtlX3hfbGluZSIsIm1ha2VfYW5pbV95X2F4aXMiLCJtYWtlX2FuaW1feV9zcGVjaWZpY3MiLCJnZXRfeV9heGlzX2xpbmVfcHJvcHMiLCJ0ZXh0X2VuZF9hdCIsIm1ha2VfeV9saW5lIiwic3BlY2lmaWMiLCJ5X2F4aXNfbW9kZSIsImRyYXdfbmV3X2dyYXBoX2FuZF9hbmltYXRlIiwic3ZnX3VuaXRzIiwibWFrZV9wYXRoIiwieV90b3BzIiwibWFrZV9uZXdfdW5pdHMiLCJBcnJheSIsImZpbGwiLCJ1cGRhdGVfdmFsdWVzIiwibWFrZV9uZXdfdW5pdHNfZm9yX2RhdGFzZXQiLCJ4X3ZhbHVlcyIsInlfdmFsdWVzIiwiZGF0YXNldF9pbmRleCIsIm5vX29mX2RhdGFzZXRzIiwiZ3JvdXAiLCJ1bml0X2FyZ3MiLCJkYXRhX3VuaXQiLCJkcmF3IiwidG9VcHBlckNhc2UiLCJsaW5lX3R5cGUiLCJyZWxYIiwicGFnZVgiLCJyZWxZIiwicGFnZVkiLCJtYXBfdG9vbHRpcF94X3Bvc2l0aW9uX2FuZF9zaG93IiwiaGlkZV90aXAiLCJ4X3ZhbCIsInlfbWluX3RvcHMiLCJmb3JtYXR0ZWQiLCJzZXQiLCJzZXRfdmFsdWVzIiwic2hvd190aXAiLCJ1cGRhdGluZyIsInN1bV91bml0cyIsIm9sZF9zcGVjaWZpY192YWx1ZXMiLCJzdW0iLCJhdmVyYWdlIiwiaW5kaWNlc190b19yZW1vdmUiLCJhdXRvIiwidW5zaGlmdCIsInNwbGljZSIsIm5ld195IiwibmV3X3giLCJlbGVtZW50c190b19hbmltYXRlIiwib2xkX3hfdmFsdWVzIiwib2xkX3lfYXhpc190b3BzIiwib2xkX3lfdmFsdWVzIiwibm9fb2ZfZXh0cmFfcHRzIiwiY2FsY195X2RlcGVuZGVuY2llcyIsImFuaW1hdGVfZ3JhcGhzIiwicnVuX2FuaW1hdGlvbiIsInlfcG9pbnQiLCJ4X3BvaW50IiwiZGF0YV9zZXQiLCJyZW1vdmVDaGlsZCIsImNhbGNfb2xkX2FuZF9uZXdfcG9zdGlvbnMiLCJvbGRfeCIsIm9sZF95IiwicGF0aCIsImFuaW1hdGVfcGF0aCIsImFuaW1hdGVfdW5pdHMiLCJuZXdfcG9pbnRzX2xpc3QiLCJuZXdfcGF0aF9zdHIiLCJqb2luIiwicGF0aF9hcmdzIiwicmVnaW9uX3BhdGgiLCJyZWdfc3RhcnRfcHQiLCJyZWdfZW5kX3B0IiwicmVnaW9uX2FyZ3MiLCJsYXN0X29sZF94X3BvcyIsImxhc3Rfb2xkX3lfcG9zIiwibGFzdF9uZXdfeF9wb3MiLCJsYXN0X25ld195X3BvcyIsImZpbGxlcl94IiwiTWF0aCIsImFicyIsImZpbGxlcl95Iiwib2xkX3BvcyIsIm5ld19wb3MiLCJvbGRfdmFscyIsIm5ld192YWxzIiwibGFzdF9saW5lX3BvcyIsImFkZF9hbmRfYW5pbWF0ZV9saW5lIiwieF9saW5lIiwidHJhbnNmb3JtIiwibWFrZV9uZXdfYXhpc19hbmltX2xpbmVzIiwiYWRkX2FuZF9hbmltYXRlX3lfbGluZSIsInN1cGVyaW1wb3NlZF9wb3NpdGlvbnMiLCJzdXBlcmltcG9zZWRfdmFsdWVzIiwibm9fb2ZfZXh0cmFzIiwiZmlsbGVyX3ZhbHMiLCJmaWxsZXJfcG9zIiwiZXh0cmFfdmFsdWVzIiwiZXh0cmFfcG9zaXRpb25zIiwibGFiZWxfY2xhc3MiLCJ4X3BvcyIsImFsbG93ZWRfc3BhY2UiLCJhbGxvd2VkX2xldHRlcnMiLCJsaW5lIiwidGV4dCIsInhfbGV2ZWwiLCJ5X3BvcyIsImRhcmtlciIsInlfbGV2ZWwiLCJzdHlsZSIsInN0cm9rZSIsImF4aXNfbGFiZWxfY2xhc3MiLCJ5X2xpbmUiLCJtYXhfYm91bmQiLCJtaW5fYm91bmQiLCJwb3Nfbm9fb2ZfcGFydHMiLCJuZWdfbm9fb2ZfcGFydHMiLCJwYXJ0X3NpemUiLCJtYXhfdmFsIiwicGFyc2VJbnQiLCJtYXgiLCJtaW5fdmFsIiwibWluIiwiZ2V0X3BhcmFtcyIsInZhbHVlMSIsInZhbHVlMiIsImJvdW5kMSIsImJvdW5kMiIsIm5vX29mX3BhcnRzXzEiLCJub19vZl9wYXJ0c18yIiwiaW50ZXJ2YWxfc2l6ZSIsImNhbGNfdXBwZXJfYm91bmRfYW5kX25vX29mX3BhcnRzIiwiY2FsY19ub19vZl9wYXJ0cyIsImFic19taW5fdmFsIiwibm9fb2ZfcGFydHMiLCJnZXRfaW50ZXJ2YWxzIiwic3RhcnQiLCJjb3VudCIsImludGVydmFscyIsInBvdyIsInVwcGVyX2JvdW5kIiwiZGl2aXNvciIsImNlaWwiLCJhbGxfdmFsdWVzIiwieV90b3AiLCJ0b3RhbF93aWR0aCIsInNwYWNlX3dpZHRoIiwic3RhcnRfeCIsImN1cnJlbnRfeCIsImdldF9iYXJfaGVpZ2h0X2FuZF95X2F0dHIiLCJyYWRpdXMiLCJiYXJfb2JqIiwiZG90X29iaiIsImN4IiwiY3kiLCJzZXR1cCIsInVwZGF0ZV9jdXJyZW50X2RhdGFfcG9pbnQiLCJvdmVybGF5Iiwib3BhY2l0eSIsInVwZGF0ZV9vdmVybGF5Iiwic3ZnX3VuaXQiLCJhdHRyaWJ1dGVzIiwia2V5cyIsImZpbHRlciIsImF0dHIiLCJzcGVjaWZpZWQiLCJuYW1lIiwibm9kZVZhbHVlIiwicmVnaW9uX2ZpbGwiLCJzZXR1cF9wYXRoX2dyb3VwcyIsInBhdGhzX2dyb3VwcyIsInhfcG9zaXRpb25zIiwieV9wb3NpdGlvbnMiLCJwb2ludHNfbGlzdCIsInBvaW50c19zdHIiLCJncmFkaWVudF9pZCIsImdyYWRpZW50X2RlZiIsInNldF9ncmFkaWVudF9zdG9wIiwiZ3JhZF9lbGVtIiwibWF4X3NsaWNlcyIsIm1heF9sZWdlbmRfcG9pbnRzIiwibWFyZ2luVG9wIiwibWFyZ2luQm90dG9tIiwicGFkZGluZ1RvcCIsImNoYXJ0X2RpdiIsImNoYXJ0IiwicGVyY2VudGFnZV9iYXIiLCJzbGljZV90b3RhbHMiLCJhbGxfdG90YWxzIiwidG90YWwiLCJ0b3RhbHMiLCJzb3J0IiwiYSIsImIiLCJvdGhlcnMiLCJzdW1fb2Zfb3RoZXJzIiwibGVnZW5kX3RvdGFscyIsImdyYW5kX3RvdGFsIiwicmVkdWNlIiwic2xpY2VzIiwiZ19vZmYiLCJwX29mZiIsImZvcm1hdHRlZF9sYWJlbHMiLCJwZXJjZW50IiwiZG9tYWluIiwic3ViZG9tYWluIiwiZGlzY3JldGVfZG9tYWlucyIsImNvdW50X2xhYmVsIiwidG9kYXkiLCJEYXRlIiwiYWRkX2RheXMiLCJsZWdlbmRfY29sb3JzIiwic2V0RnVsbFllYXIiLCJnZXRGdWxsWWVhciIsImZpcnN0X3dlZWtfc3RhcnQiLCJ0b0RhdGVTdHJpbmciLCJsYXN0X3dlZWtfc3RhcnQiLCJnZXREYXkiLCJub19vZl9jb2xzIiwiZ2V0X3dlZWtzX2JldHdlZW4iLCJkb21haW5fbGFiZWxfZ3JvdXAiLCJkYXRhX2dyb3VwcyIsImRpc3RyaWJ1dGlvbiIsImdldF9kaXN0cmlidXRpb24iLCJtb250aF9uYW1lcyIsInJlbmRlcl9hbGxfd2Vla3NfYW5kX3N0b3JlX3hfdmFsdWVzIiwibm9fb2Zfd2Vla3MiLCJjdXJyZW50X3dlZWtfc3VuZGF5Iiwid2Vla19jb2wiLCJjdXJyZW50X21vbnRoIiwiZ2V0TW9udGgiLCJtb250aHMiLCJtb250aF93ZWVrcyIsIm1vbnRoX3N0YXJ0X3BvaW50cyIsImRhdGFfZ3JvdXAiLCJtb250aF9jaGFuZ2UiLCJkYXkiLCJnZXRfd2Vla19zcXVhcmVzX2dyb3VwIiwicmVuZGVyX21vbnRoX2xhYmVscyIsImN1cnJlbnRfZGF0ZSIsIm5vX29mX3dlZWtkYXlzIiwic3F1YXJlX3NpZGUiLCJjZWxsX3BhZGRpbmciLCJzdGVwIiwid2Vla19jb2xfY2hhbmdlIiwiZGF0YV92YWx1ZSIsImNvbG9yX2luZGV4IiwidGltZXN0YW1wIiwiZmxvb3IiLCJnZXRUaW1lIiwiZ2V0X21heF9jaGVja3BvaW50Iiwicm91bmQiLCJnZXRfZGRfbW1feXl5eSIsIm5leHRfZGF0ZSIsInNoaWZ0IiwicG9wIiwibW9udGhfbmFtZSIsInN1YnN0cmluZyIsImNhbGwiLCJxdWVyeVNlbGVjdG9yQWxsIiwiZGlzcGxheSIsImRhdGVfcGFydHMiLCJtb250aCIsIm1hcHBlcl9hcnJheSIsImRhdGFfdmFsdWVzIiwiZGF0YV9tYXhfdmFsdWUiLCJkaXN0cmlidXRpb25fc3RlcCIsImNoZWNrcG9pbnQiLCJkYXRlX3N0ciIsInJlc3VsdCIsInNldE1pbnV0ZXMiLCJnZXRNaW51dGVzIiwiZ2V0VGltZXpvbmVPZmZzZXQiLCJkYXRlIiwiZGQiLCJnZXREYXRlIiwibW0iLCJzdGFydF9kYXRlX3N0ciIsImVuZF9kYXRlX3N0ciIsImdldF9kYXlzX2JldHdlZW4iLCJtaWxsaXNlY29uZHNfcGVyX2RheSIsInRyZWF0X2FzX3V0YyIsIm51bWJlcl9vZl9kYXlzIiwic2V0RGF0ZSIsInRpdGxlX25hbWUiLCJ0aXRsZV92YWx1ZSIsImxpc3RfdmFsdWVzIiwidGl0bGVfdmFsdWVfZmlyc3QiLCJjYWxjX3Bvc2l0aW9uIiwiZGF0YV9wb2ludF9saXN0IiwibGkiLCJvZmZzZXRIZWlnaHQiLCJtYXhfbGVmdCIsInBvaW50ZXIiLCJkZWx0YSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQWUsU0FBU0EsQ0FBVCxDQUFXQyxJQUFYLEVBQWlCQyxHQUFqQixFQUFzQjtRQUM3QixPQUFPRCxJQUFQLEtBQWdCLFFBQWhCLEdBQTBCLENBQUNDLE9BQU9DLFFBQVIsRUFBa0JDLGFBQWxCLENBQWdDSCxJQUFoQyxDQUExQixHQUFrRUEsUUFBUSxJQUFqRjs7O0FBR0RELEVBQUVLLGFBQUYsR0FBa0IsVUFBQ0MsSUFBRCxFQUNsQjtLQUNLQyxJQUFJLENBQVI7UUFDT0QsS0FBS0UsZUFBWixFQUE2QjtTQUNyQkYsS0FBS0UsZUFBWjs7O1FBR01ELENBQVA7Q0FQRDs7QUFVQVAsRUFBRVMsTUFBRixHQUFXLFVBQUNDLEdBQUQsRUFBTUMsQ0FBTixFQUFZO0tBQ2xCQyxVQUFVVCxTQUFTVSxhQUFULENBQXVCSCxHQUF2QixDQUFkOztNQUVLLElBQUlILENBQVQsSUFBY0ksQ0FBZCxFQUFpQjtNQUNaRyxNQUFNSCxFQUFFSixDQUFGLENBQVY7O01BRUlBLE1BQU0sUUFBVixFQUFvQjtLQUNqQk8sR0FBRixFQUFPQyxXQUFQLENBQW1CSCxPQUFuQjtHQURELE1BR0ssSUFBSUwsTUFBTSxRQUFWLEVBQW9CO09BQ3BCUyxNQUFNaEIsRUFBRWMsR0FBRixDQUFWO09BQ0lHLFVBQUosQ0FBZUMsWUFBZixDQUE0Qk4sT0FBNUIsRUFBcUNJLEdBQXJDO1dBQ1FELFdBQVIsQ0FBb0JDLEdBQXBCO0dBSEksTUFLQSxJQUFJVCxLQUFLSyxPQUFULEVBQWtCO1dBQ2RMLENBQVIsSUFBYU8sR0FBYjtHQURJLE1BR0E7V0FDSUssWUFBUixDQUFxQlosQ0FBckIsRUFBd0JPLEdBQXhCOzs7O1FBSUtGLE9BQVA7Q0F0QkQ7O0FBeUJBWixFQUFFb0IsU0FBRixHQUFjLFVBQUNWLEdBQUQsRUFBTUMsQ0FBTixFQUFZO0tBQ3JCQyxVQUFVVCxTQUFTa0IsZUFBVCxDQUF5Qiw0QkFBekIsRUFBdURYLEdBQXZELENBQWQ7O01BRUssSUFBSUgsQ0FBVCxJQUFjSSxDQUFkLEVBQWlCO01BQ1pHLE1BQU1ILEVBQUVKLENBQUYsQ0FBVjs7TUFFSUEsTUFBTSxRQUFWLEVBQW9CO0tBQ2pCTyxHQUFGLEVBQU9DLFdBQVAsQ0FBbUJILE9BQW5CO0dBREQsTUFHSyxJQUFJTCxNQUFNLFFBQVYsRUFBb0I7T0FDcEJTLE1BQU1oQixFQUFFYyxHQUFGLENBQVY7T0FDSUcsVUFBSixDQUFlQyxZQUFmLENBQTRCTixPQUE1QixFQUFxQ0ksR0FBckM7V0FDUUQsV0FBUixDQUFvQkMsR0FBcEI7R0FISSxNQUtBO09BQ0RULE1BQU0sV0FBVCxFQUFzQjtRQUFNLE9BQUo7O09BQ3JCQSxNQUFNLFdBQVQsRUFBc0I7WUFDYixhQUFSLElBQXlCTyxHQUF6QjtJQURELE1BRU87WUFDRUssWUFBUixDQUFxQlosQ0FBckIsRUFBd0JPLEdBQXhCOzs7OztRQUtJRixPQUFQO0NBeEJEOztBQTJCQVosRUFBRXNCLGVBQUYsR0FBb0IsVUFBQ0MsYUFBRCxFQUFnQkMsUUFBaEIsRUFBNkI7OztLQUc1Q0MsZUFBZSxFQUFuQjtLQUNJQyxnQkFBZ0IsRUFBcEI7O1VBRVNDLEdBQVQsQ0FBYSxtQkFBVztNQUNuQkMsTUFBTWhCLFFBQVEsQ0FBUixDQUFWO01BQ0lpQixTQUFTRCxJQUFJRSxJQUFKLENBQVNiLFVBQXRCOzs7TUFHSWMscUJBQUo7TUFBa0JDLG9CQUFsQjs7VUFFUSxDQUFSLElBQWFKLElBQUlFLElBQWpCOztzQkFFOEI5QixFQUFFaUMsVUFBRiw0QkFBZ0JyQixPQUFoQixFQVRQOzs7O2NBQUE7YUFBQTs7O2VBV1ZzQixJQUFiLENBQWtCRixXQUFsQjtnQkFDY0UsSUFBZCxDQUFtQixDQUFDSCxZQUFELEVBQWVGLE1BQWYsQ0FBbkI7O1NBRU9NLFlBQVAsQ0FBb0JKLFlBQXBCLEVBQWtDSCxJQUFJRSxJQUF0Qzs7TUFFR0YsSUFBSVEsS0FBUCxFQUFjO09BQ1RBLEtBQUosQ0FBVVIsSUFBSVMsS0FBZCxJQUF1QkwsV0FBdkI7R0FERCxNQUVPO09BQ0ZNLE1BQUosQ0FBV1YsSUFBSVcsR0FBZixJQUFzQlAsV0FBdEI7O0VBbkJGOztLQXVCSVEsV0FBV2pCLGNBQWNrQixTQUFkLENBQXdCLElBQXhCLENBQWY7O2VBRWNkLEdBQWQsQ0FBa0IsVUFBQ0ksWUFBRCxFQUFleEIsQ0FBZixFQUFxQjtlQUN6QixDQUFiLEVBQWdCNEIsWUFBaEIsQ0FBNkJWLGFBQWFsQixDQUFiLENBQTdCLEVBQThDd0IsYUFBYSxDQUFiLENBQTlDO1dBQ1N4QixDQUFULEVBQVksQ0FBWixJQUFpQmtCLGFBQWFsQixDQUFiLENBQWpCO0VBRkQ7O1FBS09pQyxRQUFQO0NBcENEOztBQXVDQXhDLEVBQUVpQyxVQUFGLEdBQWUsVUFBQ3JCLE9BQUQsRUFBVThCLEtBQVYsRUFBaUJDLEdBQWpCLEVBQThFO0tBQXhEQyxXQUF3RCx1RUFBNUMsUUFBNEM7S0FBbENDLElBQWtDLHVFQUE3QkMsU0FBNkI7S0FBbEJDLFVBQWtCLHVFQUFQLEVBQU87O0tBQ3hGQyxTQUFTO1FBQ04saUJBRE07VUFFSixTQUZJOztVQUlKLGVBSkk7V0FLSCxZQUxHO2FBTUQ7RUFOWjs7S0FTSWpCLGVBQWVuQixRQUFRNkIsU0FBUixDQUFrQixJQUFsQixDQUFuQjtLQUNJVCxjQUFjcEIsUUFBUTZCLFNBQVIsQ0FBa0IsSUFBbEIsQ0FBbEI7O01BRUksSUFBSVEsYUFBUixJQUF5QlAsS0FBekIsRUFBZ0M7TUFDM0JRLHdCQUFKO01BQ0dELGtCQUFrQixXQUFyQixFQUFrQztxQkFDZjlDLFNBQVNrQixlQUFULENBQXlCLDRCQUF6QixFQUF1RCxrQkFBdkQsQ0FBbEI7R0FERCxNQUVPO3FCQUNZbEIsU0FBU2tCLGVBQVQsQ0FBeUIsNEJBQXpCLEVBQXVELFNBQXZELENBQWxCOztNQUVHOEIsZ0JBQWdCSixXQUFXRSxhQUFYLEtBQTZCckMsUUFBUXdDLFlBQVIsQ0FBcUJILGFBQXJCLENBQWpEO01BQ0lJLFFBQVFYLE1BQU1PLGFBQU4sQ0FBWjs7TUFFSUssWUFBWTtrQkFDQUwsYUFEQTtTQUVURSxhQUZTO09BR1hFLEtBSFc7VUFJUixJQUpRO1FBS1ZWLE1BQUksSUFBSixHQUFXLEdBTEQ7V0FNUFEsZ0JBQWdCLEdBQWhCLEdBQXNCRSxLQU5mO2VBT0hMLE9BQU9KLFdBQVAsQ0FQRzthQVFMLEtBUks7YUFTTCxRQVRLO1NBVVQ7R0FWUDs7TUFhR0MsSUFBSCxFQUFTO2FBQ0UsTUFBVixJQUFvQkEsSUFBcEI7OztPQUdJLElBQUl0QyxDQUFULElBQWMrQyxTQUFkLEVBQXlCO21CQUNSbkMsWUFBaEIsQ0FBNkJaLENBQTdCLEVBQWdDK0MsVUFBVS9DLENBQVYsQ0FBaEM7OztlQUdZUSxXQUFiLENBQXlCbUMsZUFBekI7O01BRUdMLElBQUgsRUFBUztlQUNJMUIsWUFBWixDQUF5QjhCLGFBQXpCLGlCQUFxREksS0FBckQ7R0FERCxNQUVPO2VBQ01sQyxZQUFaLENBQXlCOEIsYUFBekIsRUFBd0NJLEtBQXhDOzs7O1FBSUssQ0FBQ3RCLFlBQUQsRUFBZUMsV0FBZixDQUFQO0NBckREOztBQXdEQWhDLEVBQUV1RCxNQUFGLEdBQVcsVUFBQzNDLE9BQUQsRUFBYTtLQUNuQjRDLE9BQU81QyxRQUFRNkMscUJBQVIsRUFBWDtRQUNPOzs7O09BSURELEtBQUtFLEdBQUwsSUFBWXZELFNBQVN3RCxlQUFULENBQXlCQyxTQUF6QixJQUFzQ3pELFNBQVMwRCxJQUFULENBQWNELFNBQWhFLENBSkM7UUFLQUosS0FBS00sSUFBTCxJQUFhM0QsU0FBU3dELGVBQVQsQ0FBeUJJLFVBQXpCLElBQXVDNUQsU0FBUzBELElBQVQsQ0FBY0UsVUFBbEU7RUFMUDtDQUZEOztBQVdBL0QsRUFBRWdFLG1CQUFGLEdBQXdCLFVBQUNDLEVBQUQsRUFBUTs7S0FFM0JULE9BQU9TLEdBQUdSLHFCQUFILEVBQVg7O1FBR0NELEtBQUtFLEdBQUwsSUFBWSxDQUFaLElBQ01GLEtBQUtNLElBQUwsSUFBYSxDQURuQixJQUVNTixLQUFLVSxNQUFMLEtBQWdCQyxPQUFPQyxXQUFQLElBQXNCakUsU0FBU3dELGVBQVQsQ0FBeUJVLFlBQS9ELENBRk47TUFHV0MsS0FBTCxLQUFlSCxPQUFPSSxVQUFQLElBQXFCcEUsU0FBU3dELGVBQVQsQ0FBeUJhLFdBQTdELENBSlA7O0NBSkQ7O0FBWUF4RSxFQUFFeUUsSUFBRixHQUFTLFVBQUM3RCxPQUFELEVBQVVELENBQVYsRUFBZ0I7S0FDcEJDLE9BQUosRUFBYTtPQUNQLElBQUk4RCxLQUFULElBQWtCL0QsQ0FBbEIsRUFBcUI7T0FDaEJnRSxXQUFXaEUsRUFBRStELEtBQUYsQ0FBZjs7U0FFTUUsS0FBTixDQUFZLEtBQVosRUFBbUJDLE9BQW5CLENBQTJCLFVBQVVILEtBQVYsRUFBaUI7WUFDbkNJLGdCQUFSLENBQXlCSixLQUF6QixFQUFnQ0MsUUFBaEM7SUFERDs7O0NBTEg7O0FBWUEzRSxFQUFFK0UsTUFBRixHQUFXLFVBQUNuRSxPQUFELEVBQVVELENBQVYsRUFBZ0I7S0FDdEJDLE9BQUosRUFBYTtPQUNQLElBQUk4RCxLQUFULElBQWtCL0QsQ0FBbEIsRUFBcUI7T0FDaEJnRSxXQUFXaEUsRUFBRStELEtBQUYsQ0FBZjs7U0FFTUUsS0FBTixDQUFZLEtBQVosRUFBbUJDLE9BQW5CLENBQTJCLFVBQVNILEtBQVQsRUFBZ0I7WUFDbENNLG1CQUFSLENBQTRCTixLQUE1QixFQUFtQ0MsUUFBbkM7SUFERDs7O0NBTEg7O0FBWUEzRSxFQUFFaUYsSUFBRixHQUFTLFVBQUNDLE1BQUQsRUFBU3JDLElBQVQsRUFBZXNDLFVBQWYsRUFBOEI7S0FDbENDLE1BQU1qRixTQUFTa0YsV0FBVCxDQUFxQixZQUFyQixDQUFWOztLQUVJQyxTQUFKLENBQWN6QyxJQUFkLEVBQW9CLElBQXBCLEVBQTBCLElBQTFCOztNQUVLLElBQUkwQyxDQUFULElBQWNKLFVBQWQsRUFBMEI7TUFDckJJLENBQUosSUFBU0osV0FBV0ksQ0FBWCxDQUFUOzs7UUFHTUwsT0FBT00sYUFBUCxDQUFxQkosR0FBckIsQ0FBUDtDQVREOztBQ2hOTyxTQUFTSyxPQUFULENBQWlCQyxDQUFqQixFQUFvQjtRQUNuQkMsV0FBV0QsRUFBRUUsT0FBRixDQUFVLENBQVYsQ0FBWCxDQUFQOzs7QUFHRCxBQUFPLFNBQVNDLFlBQVQsQ0FBc0JDLElBQXRCLEVBQTRCQyxJQUE1QixFQUFrQztLQUNyQ0QsS0FBS0UsTUFBTCxLQUFnQkQsS0FBS0MsTUFBeEIsRUFBZ0MsT0FBTyxLQUFQO0tBQzVCQyxZQUFZLElBQWhCO01BQ0t0RSxHQUFMLENBQVMsVUFBQytELENBQUQsRUFBSW5GLENBQUosRUFBVTtNQUNmd0YsS0FBS3hGLENBQUwsTUFBWW1GLENBQWYsRUFBa0JPLFlBQVksS0FBWjtFQURuQjtRQUdPQSxTQUFQOzs7SUNQb0JDO3NCQWVqQjt5QkFiRnJFLE1BYUU7TUFiRkEsTUFhRSwrQkFiTyxFQWFQO3lCQVpGc0UsTUFZRTtNQVpGQSxNQVlFLCtCQVpPLEdBWVA7d0JBVkZDLEtBVUU7TUFWRkEsS0FVRSw4QkFWTSxFQVVOOzJCQVZVQyxRQVVWO01BVlVBLFFBVVYsaUNBVnFCLEVBVXJCO3VCQVJGQyxJQVFFO01BUkZBLElBUUUsNkJBUkssRUFRTDtpQ0FQRkMsY0FPRTtNQVBGQSxjQU9FLHVDQVBlLEVBT2Y7MEJBTEZDLE9BS0U7TUFMRkEsT0FLRSxnQ0FMUSxFQUtSOytCQUhGQyxZQUdFO01BSEZBLFlBR0UscUNBSGEsQ0FHYjt1QkFERjVELElBQ0U7TUFERkEsSUFDRSw2QkFESyxFQUNMOzs7TUFDQzZELE9BQU9DLGNBQVAsQ0FBc0IsSUFBdEIsTUFBZ0NULE1BQU1VLFNBQXpDLEVBQW9EO09BQ2hEL0QsU0FBUyxNQUFaLEVBQW9CO1dBQ1osSUFBSWdFLFNBQUosQ0FBY0MsVUFBVSxDQUFWLENBQWQsQ0FBUDtJQURELE1BRU8sSUFBR2pFLFNBQVMsS0FBWixFQUFtQjtXQUNsQixJQUFJa0UsUUFBSixDQUFhRCxVQUFVLENBQVYsQ0FBYixDQUFQO0lBRE0sTUFFQSxJQUFHakUsU0FBUyxZQUFaLEVBQTBCO1dBQ3pCLElBQUltRSxlQUFKLENBQW9CRixVQUFVLENBQVYsQ0FBcEIsQ0FBUDtJQURNLE1BRUEsSUFBR2pFLFNBQVMsU0FBWixFQUF1QjtXQUN0QixJQUFJb0UsT0FBSixDQUFZSCxVQUFVLENBQVYsQ0FBWixDQUFQO0lBRE0sTUFFQTtXQUNDLElBQUlELFNBQUosQ0FBY0MsVUFBVSxDQUFWLENBQWQsQ0FBUDs7OztPQUlHSSxjQUFMLEdBQXNCSixVQUFVLENBQVYsQ0FBdEI7O09BRUtqRixNQUFMLEdBQWMxQixTQUFTQyxhQUFULENBQXVCeUIsTUFBdkIsQ0FBZDtPQUNLdUUsS0FBTCxHQUFhQSxLQUFiO09BQ0tDLFFBQUwsR0FBZ0JBLFFBQWhCOztPQUVLQyxJQUFMLEdBQVlBLElBQVo7T0FDS0MsY0FBTCxHQUFzQkEsY0FBdEI7O09BRUtZLGVBQUwsR0FBdUJiLEtBQUthLGVBQUwsSUFBd0IsRUFBL0M7T0FDS1gsT0FBTCxHQUFlQSxPQUFmOztPQUVLQyxZQUFMLEdBQW9CQSxZQUFwQjtNQUNHLEtBQUtBLFlBQVIsRUFBc0I7UUFDaEJXLGFBQUwsR0FBcUIsQ0FBckI7OztPQUdJQyxXQUFMLEdBQW1CLENBQUMsTUFBRCxFQUFTLEtBQVQsRUFBZ0IsWUFBaEIsRUFBOEIsU0FBOUIsQ0FBbkI7O09BRUtDLFdBQUwsQ0FBaUJuQixNQUFqQjs7Ozs7c0NBR21CdEQsTUFBTTtPQUN0QixDQUFDLEtBQUt3RSxXQUFMLENBQWlCRSxRQUFqQixDQUEwQjFFLElBQTFCLENBQUosRUFBcUM7WUFDNUIyRSxLQUFSLFFBQWtCM0UsSUFBbEI7O09BRUVBLFNBQVMsS0FBS0EsSUFBakIsRUFBdUI7OztPQUduQjRFLG1CQUFtQjtTQUNqQixDQUFDLE1BQUQsRUFBUyxZQUFULENBRGlCO1VBRWhCLENBQUMsS0FBRCxFQUFRLFlBQVIsQ0FGZ0I7Z0JBR1YsQ0FBQyxLQUFELEVBQVEsTUFBUixDQUhVO2FBSWI7SUFKVjs7T0FPRyxDQUFDQSxpQkFBaUIsS0FBSzVFLElBQXRCLEVBQTRCMEUsUUFBNUIsQ0FBcUMxRSxJQUFyQyxDQUFKLEVBQWdEO1lBQ3ZDMkUsS0FBUixRQUFrQixLQUFLM0UsSUFBdkIsNENBQWdFQSxJQUFoRTs7Ozs7O1VBTU0sSUFBSXFELEtBQUosQ0FBVTtZQUNSLEtBQUtnQixjQUFMLENBQW9CckYsTUFEWjtVQUVWLEtBQUtxRixjQUFMLENBQW9CWixJQUZWO1VBR1Z6RCxJQUhVO1lBSVIsS0FBS3FFLGNBQUwsQ0FBb0JmO0lBSnRCLENBQVA7Ozs7OEJBUVdBLFFBQVE7UUFDZHVCLFdBQUwsR0FBbUJ2QixNQUFuQjtRQUNLQSxNQUFMLEdBQWNBLFNBQVMsRUFBdkI7UUFDS3dCLFdBQUwsR0FBbUIsRUFBbkI7UUFDS0MsV0FBTCxHQUFtQixFQUFuQjs7OzswQkFHTztRQUNGQyxrQkFBTDtRQUNLQyxPQUFMLENBQWEsSUFBYjs7Ozt1Q0FHb0I7OztVQUNiaEQsZ0JBQVAsQ0FBd0IsUUFBeEIsRUFBa0M7V0FBTSxNQUFLZ0QsT0FBTCxFQUFOO0lBQWxDO1VBQ09oRCxnQkFBUCxDQUF3QixtQkFBeEIsRUFBNkM7V0FBTSxNQUFLZ0QsT0FBTCxFQUFOO0lBQTdDOzs7OzRCQUdtQjtPQUFaQyxJQUFZLHVFQUFQLEtBQU87O1FBQ2RDLGlCQUFMO1FBQ0tDLFNBQUw7O1FBRUtDLGVBQUw7UUFDS0MsZ0JBQUw7O1FBRUtDLFlBQUw7UUFDS0MsV0FBTDs7UUFFS0MscUJBQUwsQ0FBMkJQLElBQTNCO1FBQ0tRLFlBQUw7O09BRUcsS0FBSy9CLE9BQUwsQ0FBYVIsTUFBYixHQUFzQixDQUF6QixFQUE0QjtTQUN0QndDLG1CQUFMO0lBREQsTUFFTztTQUNEQyxZQUFMOzs7T0FHRSxLQUFLaEMsWUFBUixFQUFzQjtTQUNoQmlDLGdCQUFMLENBQXNCWCxJQUF0Qjs7Ozs7OEJBSVU7OztPQUNQWSx1QkFBdUIsQ0FBM0I7UUFDS3hCLGVBQUwsQ0FBcUJ4RixHQUFyQixDQUF5QixlQUFPO1FBQzVCLE9BQUtpSCxZQUFMLENBQWtCOUgsSUFBSXNGLEtBQXRCLElBQStCdUMsb0JBQWxDLEVBQXdEOzRCQUNoQyxPQUFLQyxZQUFMLENBQWtCOUgsSUFBSXNGLEtBQXRCLElBQStCLEVBQXREOztJQUZGO1FBS0t5QyxVQUFMLEdBQWtCLEtBQUtoSCxNQUFMLENBQVlpSCxXQUFaLEdBQTBCSCxvQkFBNUM7UUFDS0ksS0FBTCxHQUFhLEtBQUtGLFVBQUwsR0FBa0IsS0FBS2xCLFdBQUwsR0FBbUIsQ0FBbEQ7Ozs7c0NBR21COzs7b0NBRUY7UUFDWnFCLFNBQUwsR0FBaUJoSixFQUFFUyxNQUFGLENBQVMsS0FBVCxFQUFnQjtlQUNyQixpQkFEcUI7Z0VBRTBCLEtBQUsyRixLQUEvRCx1REFDbUMsS0FBS0MsUUFEeEM7SUFGZ0IsQ0FBakI7OztRQVNLeEUsTUFBTCxDQUFZb0gsU0FBWixHQUF3QixFQUF4QjtRQUNLcEgsTUFBTCxDQUFZZCxXQUFaLENBQXdCLEtBQUtpSSxTQUE3Qjs7UUFFS0UsYUFBTCxHQUFxQixLQUFLRixTQUFMLENBQWU1SSxhQUFmLENBQTZCLGVBQTdCLENBQXJCO1FBQ0srSSxhQUFMLEdBQXFCLEtBQUtILFNBQUwsQ0FBZTVJLGFBQWYsQ0FBNkIsd0JBQTdCLENBQXJCOztRQUVLZ0osZUFBTDtRQUNLQyxjQUFMOzs7O29DQUdpQjtRQUNaQyxHQUFMLEdBQVd0SixFQUFFb0IsU0FBRixDQUFZLEtBQVosRUFBbUI7ZUFDbEIsT0FEa0I7WUFFckIsS0FBSzhILGFBRmdCO1dBR3RCLEtBQUtMLFVBSGlCO1lBSXJCLEtBQUtuQjtJQUpILENBQVg7O1FBT0s2QixRQUFMLEdBQWdCdkosRUFBRW9CLFNBQUYsQ0FBWSxNQUFaLEVBQW9CO1lBQzNCLEtBQUtrSTtJQURFLENBQWhCOztVQUlPLEtBQUtBLEdBQVo7Ozs7bUNBR2dCO1FBQ1hFLFNBQUwsR0FBaUJ4SixFQUFFb0IsU0FBRixDQUFZLEdBQVosRUFBaUI7ZUFDdEIsS0FBS3lCLElBQUwsR0FBWSxRQURVO1lBRXpCLEtBQUt5RyxHQUZvQjs4QkFHVCxLQUFLM0IsV0FBN0IsVUFBNkMsS0FBS0MsV0FBbEQ7SUFIZ0IsQ0FBakI7Ozs7cUNBT2tCOzs7aUNBRUo7UUFDVDZCLEdBQUwsR0FBVyxJQUFJQyxNQUFKLENBQVc7WUFDYixLQUFLUjtJQURILENBQVg7UUFHS1MsWUFBTDs7OztpQ0FJYzs7O3dDQUNPOzs7UUFDaEJuRCxPQUFMLENBQWE3RSxHQUFiLENBQWlCLGFBQUs7UUFDakJpSSxRQUFRNUosRUFBRVMsTUFBRixDQUFTLEtBQVQsRUFBZ0I7Z0JBQ2hCLE9BRGdCOzRDQUVVaUYsRUFBRW1FLEtBQXZDLFVBQWlEbkUsRUFBRVUsS0FBbkQsVUFBNkRWLEVBQUVyQyxLQUEvRDtLQUZXLENBQVo7V0FJSzhGLGFBQUwsQ0FBbUJwSSxXQUFuQixDQUErQjZJLEtBQS9CO0lBTEQ7Ozs7cUNBUzRCOzs7T0FBWjdCLElBQVksdUVBQVAsS0FBTzs7UUFDdkIrQixZQUFMOztPQUVHL0IsSUFBSCxFQUFTO1NBQ0hnQyxZQUFMOzthQUVTakYsZ0JBQVQsQ0FBMEIsU0FBMUIsRUFBcUMsVUFBQ2tGLENBQUQsRUFBTztTQUN4Q2hLLEVBQUVnRSxtQkFBRixDQUFzQixPQUFLa0YsYUFBM0IsQ0FBSCxFQUE4QztVQUN6Q2MsS0FBSzdGLE9BQU9PLEtBQWhCOztVQUVJc0YsRUFBRUMsT0FBRixJQUFhLElBQWpCLEVBQXVCO2NBQ2pCQyxhQUFMO09BREQsTUFFTyxJQUFJRixFQUFFQyxPQUFGLElBQWEsSUFBakIsRUFBdUI7Y0FDeEJFLGNBQUw7T0FETSxNQUVBLElBQUlILEVBQUVDLE9BQUYsSUFBYSxJQUFqQixFQUF1QjtjQUN4QkcsV0FBTDtPQURNLE1BRUEsSUFBSUosRUFBRUMsT0FBRixJQUFhLElBQWpCLEVBQXVCO2NBQ3hCSSxhQUFMO09BRE0sTUFFQSxJQUFJTCxFQUFFQyxPQUFGLElBQWEsSUFBakIsRUFBdUI7Y0FDeEJLLFlBQUw7OztLQWJIOzs7OztpQ0FvQmE7OztpQ0FDQTs7O2tDQUVDOzs7bUNBQ0M7OztnQ0FDSDs7O2tDQUNFOzs7aUNBQ0Q7OzttQ0FFMEI7T0FBMUJqSSxLQUEwQix1RUFBcEIsS0FBSytFLGFBQWU7OztPQUVwQ21ELGFBQWE7V0FDVGxJO0lBRFI7T0FHSW1JLElBQUksS0FBS0EsQ0FBTCxDQUFPLENBQVAsQ0FBUjtJQUNDLFdBQUQsRUFBYyxRQUFkLEVBQXdCLFFBQXhCLEVBQWtDN0ksR0FBbEMsQ0FBc0MsZUFBTztRQUN4QzhJLFdBQVdsSSxJQUFJbUksS0FBSixDQUFVLENBQVYsRUFBYW5JLElBQUl5RCxNQUFKLEdBQVcsQ0FBeEIsQ0FBZjtlQUNXeUUsUUFBWCxJQUF1QkQsRUFBRWpJLEdBQUYsRUFBT0YsS0FBUCxDQUF2QjtJQUZEO2NBSVdzSSxLQUFYLEdBQW1CLEtBQUtDLENBQUwsQ0FBT3ZJLEtBQVAsQ0FBbkI7VUFDT2tJLFVBQVA7Ozs7NENBR3lCbEksT0FBTztPQUM3QkEsUUFBUSxDQUFYLEVBQWNBLFFBQVEsQ0FBUjtPQUNYQSxTQUFTLEtBQUt1SSxDQUFMLENBQU81RSxNQUFuQixFQUEyQjNELFFBQVEsS0FBS3VJLENBQUwsQ0FBTzVFLE1BQVAsR0FBZ0IsQ0FBeEI7T0FDeEIzRCxVQUFVLEtBQUsrRSxhQUFsQixFQUFpQztRQUM1QkEsYUFBTCxHQUFxQi9FLEtBQXJCO0tBQ0U0QyxJQUFGLENBQU8sS0FBS3BELE1BQVosRUFBb0IsYUFBcEIsRUFBbUMsS0FBS2dKLGNBQUwsRUFBbkM7Ozs7Ozs7K0JBSVlDLFFBQVE7VUFDYkEsT0FBTzlFLE1BQVAsR0FBZ0IsQ0FBdkI7Ozs7Ozs7Z0NBSWE7Ozs7O0lBR1QrRTs7O29CQUNPQyxJQUFaLEVBQWtCOzs7b0hBQ1hBLElBRFc7O1NBR1pKLENBQUwsR0FBUyxPQUFLdEUsSUFBTCxDQUFVMkUsTUFBbkI7U0FDS1QsQ0FBTCxHQUFTLE9BQUtsRSxJQUFMLENBQVU0RSxRQUFuQjs7U0FFS0MsV0FBTCxHQUFtQixPQUFLNUUsY0FBTCxDQUFvQjZFLE9BQXZDO1NBQ0tDLGFBQUwsR0FBcUIsT0FBSzlFLGNBQUwsQ0FBb0IrRSxTQUF6QztTQUNLQyxhQUFMLEdBQXFCLE9BQUtoRixjQUFMLENBQW9CaUYsU0FBekM7O1NBRUtDLE1BQUwsR0FBYyxDQUFDLE9BQUQsRUFBVSxNQUFWLEVBQWtCLFFBQWxCLEVBQTRCLEtBQTVCLEVBQW1DLFFBQW5DLEVBQ2IsUUFEYSxFQUNILFlBREcsRUFDVyxhQURYLEVBQzBCLFFBRDFCLEVBQ29DLFNBRHBDLENBQWQ7O1NBR0tDLFNBQUwsR0FBaUIsT0FBS3ZGLE1BQXRCOzs7Ozs7aUNBR2M7UUFDVEcsSUFBTCxDQUFVNEUsUUFBVixDQUFtQnZKLEdBQW5CLENBQXVCLGFBQUs7TUFDekJnSyxNQUFGLEdBQVdqRyxFQUFFaUcsTUFBRixDQUFTaEssR0FBVCxDQUFhO1lBQVEsQ0FBQ2lLLE1BQU05SyxHQUFOLENBQUQsR0FBY0EsR0FBZCxHQUFvQixDQUE1QjtLQUFiLENBQVg7SUFERDtRQUdLK0ssT0FBTDtRQUNLQyxPQUFMOzs7OzRCQUdTOzs7UUFDSkMsK0JBQUw7O09BRUcsS0FBS0MsZ0JBQVIsRUFBMEI7U0FDcEJDLG9CQUFMLEdBQTZCLEtBQUtELGdCQUFMLENBQXNCdEIsS0FBdEIsRUFBN0I7O1FBRUlzQixnQkFBTCxHQUF3QixLQUFLcEIsQ0FBTCxDQUFPakosR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKO1dBQ2xDa0YsUUFBUSxPQUFLeUcsUUFBTCxHQUFnQjNMLElBQUksT0FBSzRMLGNBQWpDLENBRGtDO0lBQVgsQ0FBeEI7O09BR0csQ0FBQyxLQUFLRixvQkFBVCxFQUErQjtTQUN6QkEsb0JBQUwsR0FBNEIsS0FBS0QsZ0JBQUwsQ0FBc0J0QixLQUF0QixFQUE1Qjs7Ozs7NEJBSVE7T0FDTixLQUFLMEIsYUFBUixFQUF1QjtTQUNqQkMsaUJBQUwsR0FBMEIsS0FBS0QsYUFBTCxDQUFtQjFCLEtBQW5CLEVBQTFCOzs7T0FHR2lCLFNBQVMsS0FBS1csZ0JBQUwsRUFBYjs7T0FFRyxLQUFLQyxNQUFMLElBQWUsS0FBS0EsTUFBTCxDQUFZdkcsTUFBWixHQUFxQixDQUF2QyxFQUEwQzthQUNoQzJGLE9BQU9hLE1BQVAsQ0FBYyxLQUFLRCxNQUFuQixDQUFUOzs7UUFHSUgsYUFBTCxHQUFxQixLQUFLSyxpQkFBTCxDQUF1QmQsTUFBdkIsQ0FBckI7O09BRUcsQ0FBQyxLQUFLVSxpQkFBVCxFQUE0QjtTQUN0QkEsaUJBQUwsR0FBeUIsS0FBS0QsYUFBTCxDQUFtQjFCLEtBQW5CLEVBQXpCOzs7T0FHS2dDLFFBQVEsS0FBS04sYUFBbkI7T0FDTU8sY0FBY0QsTUFBTUEsTUFBTTFHLE1BQU4sR0FBYSxDQUFuQixJQUF3QjBHLE1BQU0sQ0FBTixDQUE1Qzs7T0FFRyxLQUFLRSxVQUFSLEVBQW9CLEtBQUtDLGNBQUwsR0FBc0IsS0FBS0QsVUFBM0I7UUFDZkEsVUFBTCxHQUFrQixLQUFLekcsTUFBTCxHQUFjd0csV0FBaEM7T0FDRyxDQUFDLEtBQUtFLGNBQVQsRUFBeUIsS0FBS0EsY0FBTCxHQUFzQixLQUFLRCxVQUEzQjs7T0FFbkJFLGFBQWFKLE1BQU1LLE9BQU4sQ0FBYyxDQUFkLENBQW5CO09BQ01DLFdBQVdOLE1BQU0sQ0FBTixJQUFXQSxNQUFNLENBQU4sQ0FBNUI7T0FDTU8sa0JBQWtCRCxXQUFXLEtBQUtKLFVBQXhDOztPQUVHLEtBQUtsQixTQUFSLEVBQW1CLEtBQUt3QixhQUFMLEdBQXFCLEtBQUt4QixTQUExQjtRQUNkQSxTQUFMLEdBQWlCLEtBQUt2RixNQUFMLEdBQWUyRyxhQUFhRyxlQUE3QztPQUNHLENBQUMsS0FBS0MsYUFBVCxFQUF3QixLQUFLQSxhQUFMLEdBQXFCLEtBQUt4QixTQUExQjs7OztxQ0FHTjs7UUFFYnlCLHVCQUFMO1FBQ0tDLDRCQUFMO1FBQ0tDLHNCQUFMOzs7OzRDQUd5QjtRQUNwQkMsWUFBTCxHQUFvQnROLEVBQUVvQixTQUFGLENBQVksR0FBWixFQUFpQixFQUFDbU0sV0FBVyxRQUFaLEVBQXNCQyxRQUFRLEtBQUtoRSxTQUFuQyxFQUFqQixDQUFwQjtRQUNLaUUsWUFBTCxHQUFvQnpOLEVBQUVvQixTQUFGLENBQVksR0FBWixFQUFpQixFQUFDbU0sV0FBVyxRQUFaLEVBQXNCQyxRQUFRLEtBQUtoRSxTQUFuQyxFQUFqQixDQUFwQjtRQUNLa0UsZ0JBQUwsR0FBd0IxTixFQUFFb0IsU0FBRixDQUFZLEdBQVosRUFBaUIsRUFBQ21NLFdBQVcsZUFBWixFQUE2QkMsUUFBUSxLQUFLaEUsU0FBMUMsRUFBakIsQ0FBeEI7Ozs7aURBRzhCO1FBQ3pCbUUsU0FBTCxHQUFpQjNOLEVBQUVvQixTQUFGLENBQVksR0FBWixFQUFpQixFQUFDbU0sV0FBVyxhQUFaLEVBQTJCQyxRQUFRLEtBQUtoRSxTQUF4QyxFQUFqQixDQUFqQjtRQUNLb0UsYUFBTCxHQUFxQjVOLEVBQUVvQixTQUFGLENBQVksR0FBWixFQUFpQixFQUFDbU0sV0FBVyxZQUFaLEVBQTBCQyxRQUFRLEtBQUtoRSxTQUF2QyxFQUFqQixDQUFyQjs7OzsyQ0FHd0I7OztRQUNuQnFFLGdCQUFMLEdBQXdCLEVBQXhCO1FBQ0tyRCxDQUFMLENBQU83SSxHQUFQLENBQVcsVUFBQytELENBQUQsRUFBSW5GLENBQUosRUFBVTtXQUNmc04sZ0JBQUwsQ0FBc0J0TixDQUF0QixJQUEyQlAsRUFBRW9CLFNBQUYsQ0FBWSxHQUFaLEVBQWlCO2dCQUNoQyw2QkFBNkJiLENBREc7YUFFbkMsT0FBS2lKO0tBRmEsQ0FBM0I7SUFERDs7OzswQ0FRaUM7T0FBWnpCLElBQVksdUVBQVAsS0FBTzs7UUFDNUIrRixXQUFMO1FBQ0tDLFdBQUw7UUFDS0MsVUFBTCxDQUFnQmpHLElBQWhCO1FBQ0trRyxnQkFBTDs7Ozs7OztnQ0FJMEI7OztPQUFmQyxPQUFlLHVFQUFQLEtBQU87O09BQ3RCQyxpQkFBSjtPQUFjaEksZUFBZDtPQUFzQmlJLHNCQUF0QjtPQUFxQ0Msa0JBQWtCLEVBQXZEO09BQ0csS0FBS0MsV0FBTCxLQUFxQixNQUF4QixFQUFnQzs7ZUFDcEIsQ0FBQyxDQUFaO2FBQ1MsS0FBS25JLE1BQUwsR0FBYyxFQUF2QjtvQkFDZ0IsS0FBS0EsTUFBTCxHQUFjLEVBQTlCO0lBSEQsTUFJTyxJQUFHLEtBQUttSSxXQUFMLEtBQXFCLE1BQXhCLEVBQStCOztlQUMxQixLQUFLbkksTUFBaEI7YUFDUyxDQUFUO29CQUNnQixDQUFoQjtzQkFDa0IsY0FBbEI7OztRQUdJc0gsWUFBTCxDQUFrQnRNLFlBQWxCLENBQStCLFdBQS9CLG1CQUEyRGdOLFFBQTNEOztPQUVHRCxPQUFILEVBQVk7U0FDTkssZ0JBQUwsQ0FBc0JwSSxNQUF0QixFQUE4QmlJLGFBQTlCLEVBQTZDQyxlQUE3Qzs7OztRQUlJWixZQUFMLENBQWtCZSxXQUFsQixHQUFnQyxFQUFoQztRQUNLNUQsQ0FBTCxDQUFPakosR0FBUCxDQUFXLFVBQUM4TSxLQUFELEVBQVFsTyxDQUFSLEVBQWM7V0FDbkJrTixZQUFMLENBQWtCMU0sV0FBbEIsQ0FDQyxPQUFLMk4sV0FBTCxDQUNDdkksTUFERCxFQUVDaUksYUFGRCxFQUdDSyxLQUhELEVBSUMsY0FKRCxFQUtDSixlQUxELEVBTUMsT0FBS3JDLGdCQUFMLENBQXNCekwsQ0FBdEIsQ0FORCxDQUREO0lBREQ7Ozs7Ozs7Z0NBZTBCOzs7T0FBZjJOLE9BQWUsdUVBQVAsS0FBTzs7T0FDdkJBLE9BQUgsRUFBWTtTQUNOUyxnQkFBTDtTQUNLQyxxQkFBTDs7OzsrQkFJcUQsS0FBS0MscUJBQUwsRUFQNUI7O09BT3JCOUYsS0FQcUI7T0FPZCtGLFdBUGM7T0FPRFQsZUFQQztPQU9nQkYsUUFQaEI7O1FBU3JCYixZQUFMLENBQWtCa0IsV0FBbEIsR0FBZ0MsRUFBaEM7UUFDS3BDLGFBQUwsQ0FBbUJ6SyxHQUFuQixDQUF1QixVQUFDMEIsS0FBRCxFQUFROUMsQ0FBUixFQUFjO1dBQy9CK00sWUFBTCxDQUFrQnZNLFdBQWxCLENBQ0MsT0FBS2dPLFdBQUwsQ0FDQ1osUUFERCxFQUVDcEYsS0FGRCxFQUdDK0YsV0FIRCxFQUlDekwsS0FKRCxFQUtDLGNBTEQsRUFNQ2dMLGVBTkQsRUFPQyxPQUFLM0MsU0FBTCxHQUFpQnJJLFFBQVEsT0FBS3VKLFVBUC9CLEVBUUV2SixVQUFVLENBQVYsSUFBZTlDLE1BQU0sQ0FSdkI7S0FERDtJQUREOzs7OzBDQWdCcUM7T0FBaEJ5TyxRQUFnQix1RUFBUCxLQUFPOztPQUNsQ0EsUUFBSCxFQUFhO1dBQ04sQ0FBQyxLQUFLakcsS0FBTixFQUFhLEtBQUtBLEtBQUwsR0FBYSxDQUExQixFQUE2QixnQkFBN0IsRUFBK0MsQ0FBL0MsQ0FBTjs7T0FFR0EsY0FBSjtPQUFXK0YsY0FBYyxDQUFDLENBQTFCO09BQTZCVCxrQkFBa0IsRUFBL0M7T0FBbURGLFdBQVcsQ0FBOUQ7T0FDRyxLQUFLYyxXQUFMLEtBQXFCLE1BQXhCLEVBQWdDOztZQUN2QixLQUFLbEcsS0FBTCxHQUFhLENBQXJCO2VBQ1csQ0FBQyxDQUFaO0lBRkQsTUFHTyxJQUFHLEtBQUtrRyxXQUFMLEtBQXFCLE1BQXhCLEVBQStCOztZQUM3QixDQUFDLENBQVQ7c0JBQ2tCLGNBQWxCOzs7VUFHTSxDQUFDbEcsS0FBRCxFQUFRK0YsV0FBUixFQUFxQlQsZUFBckIsRUFBc0NGLFFBQXRDLENBQVA7Ozs7K0JBR3NCOzs7T0FBWnBHLElBQVksdUVBQVAsS0FBTzs7T0FDbkJBLElBQUgsRUFBUztTQUNIbUgsMEJBQUw7OztRQUdJMUUsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7TUFDbEI0TyxTQUFGLEdBQWMsRUFBZDtZQUNLQyxTQUFMLElBQWtCLFFBQUtBLFNBQUwsQ0FBZTFKLENBQWYsRUFBa0JuRixDQUFsQixFQUFxQixRQUFLeUwsZ0JBQTFCLEVBQTRDdEcsRUFBRTJKLE1BQTlDLEVBQXNEM0osRUFBRW1FLEtBQUYsSUFBVyxRQUFLNEIsTUFBTCxDQUFZbEwsQ0FBWixDQUFqRSxDQUFsQjtZQUNLK08sY0FBTCxDQUFvQjVKLENBQXBCLEVBQXVCbkYsQ0FBdkI7SUFIRDs7OzsrQ0FPNEI7OztPQUN4QitGLE9BQU8sRUFBWDtRQUNLa0UsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7O01BRWxCOE8sTUFBRixHQUFXLElBQUlFLEtBQUosQ0FBVTdKLEVBQUVpRyxNQUFGLENBQVMzRixNQUFuQixFQUEyQndKLElBQTNCLENBQWdDLFFBQUs5RCxTQUFyQyxDQUFYLENBRm9CO1NBR2Z4SixJQUFMLENBQVUsRUFBQ3lKLFFBQVFqRyxFQUFFaUcsTUFBWCxFQUFWO01BQ0V3RCxTQUFGLEdBQWMsRUFBZDs7WUFFS0MsU0FBTCxJQUFrQixRQUFLQSxTQUFMLENBQWUxSixDQUFmLEVBQWtCbkYsQ0FBbEIsRUFBcUIsUUFBS3lMLGdCQUExQixFQUE0Q3RHLEVBQUUySixNQUE5QyxFQUFzRDNKLEVBQUVtRSxLQUFGLElBQVcsUUFBSzRCLE1BQUwsQ0FBWWxMLENBQVosQ0FBakUsQ0FBbEI7WUFDSytPLGNBQUwsQ0FBb0I1SixDQUFwQixFQUF1Qm5GLENBQXZCO0lBUEQ7O2NBVVcsWUFBTTtZQUNYa1AsYUFBTCxDQUFtQm5KLElBQW5CO0lBREQsRUFFRyxHQUZIOzs7O21DQUtnQnlCLE1BQU07Ozs7Y0FFWCxZQUFNO2dJQUNPQSxJQUF2QjtJQURELEVBRUcsR0FGSDs7OztpQ0FLY3JDLEdBQUduRixHQUFHO1FBQ2ZtUCwwQkFBTCxDQUNDLEtBQUsxRCxnQkFETixFQUVDdEcsRUFBRTJKLE1BRkgsRUFHQzNKLEVBQUVtRSxLQUFGLElBQVcsS0FBSzRCLE1BQUwsQ0FBWWxMLENBQVosQ0FIWixFQUlDQSxDQUpELEVBS0MsS0FBS2lLLENBQUwsQ0FBT3hFLE1BTFI7Ozs7NkNBUzBCMkosVUFBVUMsVUFBVS9GLE9BQU9nRyxlQUFlQyxnQkFBZ0JDLE9BQU8zTixPQUFPTixNQUFNOzs7T0FDckcsQ0FBQ2lPLEtBQUosRUFBV0EsUUFBUSxLQUFLbEMsZ0JBQUwsQ0FBc0JnQyxhQUF0QixDQUFSO09BQ1IsQ0FBQ3pOLEtBQUosRUFBV0EsUUFBUSxLQUFLb0ksQ0FBTCxDQUFPcUYsYUFBUCxFQUFzQlYsU0FBOUI7T0FDUixDQUFDck4sSUFBSixFQUFVQSxPQUFPLEtBQUtrTyxTQUFaOztTQUVKeEIsV0FBTixHQUFvQixFQUFwQjtTQUNNeEksTUFBTixHQUFlLENBQWY7O1lBRVNyRSxHQUFULENBQWEsVUFBQzZJLENBQUQsRUFBSWpLLENBQUosRUFBVTtRQUNsQjBQLFlBQVksUUFBS0MsSUFBTCxDQUFVcE8sS0FBS2UsSUFBZixFQUNmOE0sU0FBU3BQLENBQVQsQ0FEZSxFQUVmaUssQ0FGZSxFQUdmMUksS0FBS2tKLElBSFUsRUFJZm5CLEtBSmUsRUFLZmdHLGFBTGUsRUFNZkMsY0FOZSxDQUFoQjtVQVFNL08sV0FBTixDQUFrQmtQLFNBQWxCO1VBQ00vTixJQUFOLENBQVcrTixTQUFYO0lBVkQ7Ozs7cUNBY2tCOzs7UUFDYnZDLGdCQUFMLENBQXNCYyxXQUF0QixHQUFvQyxFQUFwQztRQUNLckgsZUFBTCxDQUFxQnhGLEdBQXJCLENBQXlCLGFBQUs7WUFDeEIrTCxnQkFBTCxDQUFzQjNNLFdBQXRCLENBQ0MsUUFBS2dPLFdBQUwsQ0FDQyxDQURELEVBRUMsUUFBS2hHLEtBRk4sRUFHQyxRQUFLQSxLQUFMLEdBQWEsQ0FIZCxFQUlDckQsRUFBRVUsS0FBRixDQUFRK0osV0FBUixFQUpELEVBS0MsZ0JBTEQsRUFNQyxnQkFORCxFQU9DLFFBQUt6RSxTQUFMLEdBQWlCaEcsRUFBRXJDLEtBQUYsR0FBVSxRQUFLdUosVUFQakMsRUFRQyxLQVJELEVBU0NsSCxFQUFFMEssU0FUSCxDQUREO0lBREQ7Ozs7aUNBaUJjOzs7O1FBRVRsSCxhQUFMLENBQW1CcEUsZ0JBQW5CLENBQW9DLFdBQXBDLEVBQWlELFVBQUNrRixDQUFELEVBQU87UUFDbkR6RyxTQUFTdkQsRUFBRXVELE1BQUYsQ0FBUyxRQUFLMkYsYUFBZCxDQUFiO1FBQ0ltSCxPQUFPckcsRUFBRXNHLEtBQUYsR0FBVS9NLE9BQU9PLElBQWpCLEdBQXdCLFFBQUs2RCxXQUF4QztRQUNJNEksT0FBT3ZHLEVBQUV3RyxLQUFGLEdBQVVqTixPQUFPRyxHQUFqQixHQUF1QixRQUFLa0UsV0FBdkM7O1FBRUcySSxPQUFPLFFBQUtwSyxNQUFMLEdBQWMsUUFBS3lCLFdBQUwsR0FBbUIsQ0FBM0MsRUFBOEM7YUFDeEM2SSwrQkFBTCxDQUFxQ0osSUFBckM7S0FERCxNQUVPO2FBQ0Q1RyxHQUFMLENBQVNpSCxRQUFUOztJQVJGOzs7O2tEQWErQkwsTUFBTTs7O1FBQ2pDLElBQUk5UCxJQUFFLEtBQUt5TCxnQkFBTCxDQUFzQmhHLE1BQXRCLEdBQStCLENBQXpDLEVBQTRDekYsS0FBSyxDQUFqRCxFQUFxREEsR0FBckQsRUFBMEQ7UUFDckRvUSxRQUFRLEtBQUszRSxnQkFBTCxDQUFzQnpMLENBQXRCLENBQVo7O1FBRUc4UCxPQUFPTSxRQUFRLEtBQUt4RSxjQUFMLEdBQW9CLENBQXRDLEVBQXlDO1NBQ3BDdkIsSUFBSStGLFFBQVEsS0FBS2hKLFdBQXJCO1NBQ0k2QyxJQUFJLEtBQUtvRyxVQUFMLENBQWdCclEsQ0FBaEIsSUFBcUIsS0FBS3FILFdBQWxDOztTQUVJeEIsUUFBUSxLQUFLd0UsQ0FBTCxDQUFPaUcsU0FBUCxJQUFvQixLQUFLakcsQ0FBTCxDQUFPaUcsU0FBUCxDQUFpQjdLLE1BQWpCLEdBQXdCLENBQTVDLEdBQ1QsS0FBSzRFLENBQUwsQ0FBT2lHLFNBQVAsQ0FBaUJ0USxDQUFqQixDQURTLEdBQ2EsS0FBS3FLLENBQUwsQ0FBT3JLLENBQVAsQ0FEekI7U0FFSW9MLFNBQVMsS0FBS25CLENBQUwsQ0FBTzdJLEdBQVAsQ0FBVyxVQUFDbVAsTUFBRCxFQUFNdkwsQ0FBTixFQUFZO2FBQzVCO2NBQ0N1TCxPQUFJMUssS0FETDtjQUVDMEssT0FBSUQsU0FBSixHQUFnQkMsT0FBSUQsU0FBSixDQUFjdFEsQ0FBZCxDQUFoQixHQUFtQ3VRLE9BQUluRixNQUFKLENBQVdwTCxDQUFYLENBRnBDO2NBR0N1USxPQUFJakgsS0FBSixJQUFhLFFBQUs0QixNQUFMLENBQVlsRyxDQUFaO09BSHJCO01BRFksQ0FBYjs7O1VBU0trRSxHQUFMLENBQVNzSCxVQUFULENBQW9CbkcsQ0FBcEIsRUFBdUJKLENBQXZCLEVBQTBCcEUsS0FBMUIsRUFBaUMsRUFBakMsRUFBcUN1RixNQUFyQztVQUNLbEMsR0FBTCxDQUFTdUgsUUFBVDs7Ozs7Ozs7Ozs4QkFPUzs7O1FBQ05DLFFBQUwsR0FBZ0IsSUFBaEI7O1FBRUsxRSxNQUFMLEdBQWMsSUFBSWdELEtBQUosQ0FBVSxLQUFLdkQsZ0JBQUwsQ0FBc0JoRyxNQUFoQyxFQUF3Q3dKLElBQXhDLENBQTZDLENBQTdDLENBQWQ7UUFDS2hGLENBQUwsQ0FBTzdJLEdBQVAsQ0FBVyxhQUFLO01BQ2JnSyxNQUFGLENBQVNoSyxHQUFULENBQWMsVUFBQzBCLEtBQUQsRUFBUTlDLENBQVIsRUFBYzthQUN0QmdNLE1BQUwsQ0FBWWhNLENBQVosS0FBa0I4QyxLQUFsQjtLQUREO0lBREQ7OztRQU9Lb00sYUFBTDs7O1FBR0t5QixTQUFMLEdBQWlCLEVBQWpCOztRQUVLeEIsMEJBQUwsQ0FDQyxLQUFLMUQsZ0JBRE4sRUFFQyxLQUFLTyxNQUFMLENBQVk1SyxHQUFaLENBQWlCO1dBQU84RCxRQUFRLFFBQUtpRyxTQUFMLEdBQWlCNUssTUFBTSxRQUFLOEwsVUFBcEMsQ0FBUDtJQUFqQixDQUZELEVBR0MsWUFIRCxFQUlDLENBSkQsRUFLQyxDQUxELEVBTUMsS0FBS2UsU0FOTixFQU9DLEtBQUt1RCxTQVBOOzs7O1FBWUtELFFBQUwsR0FBZ0IsS0FBaEI7Ozs7OEJBR1c7T0FDUixLQUFLQSxRQUFSLEVBQWtCO1FBQ2IxRSxNQUFMLEdBQWMsRUFBZDtRQUNLb0IsU0FBTCxDQUFlYSxXQUFmLEdBQTZCLEVBQTdCO1FBQ0swQyxTQUFMLEdBQWlCLEVBQWpCO1FBQ0t6QixhQUFMOzs7O2lDQUdjOzs7UUFDVDBCLG1CQUFMLEdBQTJCLEtBQUtoSyxlQUFMLENBQXFCdUQsS0FBckIsRUFBM0I7UUFDS0YsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7UUFDaEI2USxNQUFNLENBQVY7TUFDRXpGLE1BQUYsQ0FBU2hLLEdBQVQsQ0FBYSxhQUFLO1lBQU1xSSxDQUFMO0tBQW5CO1FBQ0lxSCxVQUFVRCxNQUFJMUwsRUFBRWlHLE1BQUYsQ0FBUzNGLE1BQTNCOztZQUVLbUIsZUFBTCxDQUFxQmpGLElBQXJCLENBQTBCO1lBQ2xCLFFBQVEsR0FBUixJQUFlM0IsSUFBRSxDQUFqQixDQURrQjtnQkFFZCxRQUZjO1lBR2xCOFEsT0FIa0I7V0FJbkI7S0FKUDtJQUxEOztRQWFLNUIsYUFBTDs7OztpQ0FHYzs7O1FBQ1QwQixtQkFBTCxHQUEyQixLQUFLaEssZUFBTCxDQUFxQnVELEtBQXJCLEVBQTNCOztPQUVJNEcsb0JBQW9CLEVBQXhCO1FBQ0tuSyxlQUFMLENBQXFCeEYsR0FBckIsQ0FBeUIsVUFBQytELENBQUQsRUFBSW5GLENBQUosRUFBVTtRQUMvQm1GLEVBQUU2TCxJQUFMLEVBQVdELGtCQUFrQkUsT0FBbEIsQ0FBMEJqUixDQUExQjtJQURaOztxQkFJa0JvQixHQUFsQixDQUFzQixpQkFBUztZQUN6QndGLGVBQUwsQ0FBcUJzSyxNQUFyQixDQUE0QnBQLEtBQTVCLEVBQW1DLENBQW5DO0lBREQ7O1FBSUtvTixhQUFMOzs7O2dDQUdhaUMsT0FBT0MsT0FBTzs7O09BQ3hCLENBQUNBLEtBQUosRUFBVztZQUNGLEtBQUsvRyxDQUFiOztRQUVJZ0gsbUJBQUwsR0FBMkIsRUFBM0I7UUFDS1gsUUFBTCxHQUFnQixJQUFoQjs7UUFFS1ksWUFBTCxHQUFvQixLQUFLakgsQ0FBTCxDQUFPRixLQUFQLEVBQXBCO1FBQ0tvSCxlQUFMLEdBQXVCLEtBQUt0SCxDQUFMLENBQU83SSxHQUFQLENBQVc7V0FBSytELEVBQUUySixNQUFGLENBQVMzRSxLQUFULEVBQUw7SUFBWCxDQUF2Qjs7UUFFS3FILFlBQUwsR0FBb0IsS0FBS3ZILENBQUwsQ0FBTzdJLEdBQVAsQ0FBVztXQUFLK0QsRUFBRWlHLE1BQVA7SUFBWCxDQUFwQjs7UUFFS3FHLGVBQUwsR0FBdUJMLE1BQU0zTCxNQUFOLEdBQWUsS0FBSzRFLENBQUwsQ0FBTzVFLE1BQTdDOzs7T0FHRzBMLEtBQUgsRUFBVSxLQUFLbEgsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7TUFBR29MLE1BQUYsR0FBVytGLE1BQU1uUixDQUFOLEVBQVNvTCxNQUFwQjtJQUF0QjtPQUNQZ0csS0FBSCxFQUFVLEtBQUsvRyxDQUFMLEdBQVMrRyxLQUFUOztRQUVMOUYsT0FBTDtRQUNLQyxPQUFMOzs7T0FHRyxDQUFDakcsYUFBYSxLQUFLb0csb0JBQWxCLEVBQXdDLEtBQUtELGdCQUE3QyxDQUFKLEVBQW9FO1NBQzlEK0IsV0FBTCxDQUFpQixJQUFqQjtlQUNXLFlBQU07U0FDYixDQUFDLFFBQUtrRCxRQUFULEVBQW1CLFFBQUtsRCxXQUFMO0tBRHBCLEVBRUcsR0FGSDs7O09BS0UsQ0FBQ2xJLGFBQWEsS0FBS3dHLGlCQUFsQixFQUFxQyxLQUFLRCxhQUExQyxDQUFELElBQ0QsS0FBSytFLG1CQUFMLElBQ0QsQ0FBQ3RMLGFBQWEsS0FBS3NMLG1CQUFsQixFQUF1QyxLQUFLaEssZUFBNUMsQ0FGRixFQUVpRTs7U0FFM0QyRyxXQUFMLENBQWlCLElBQWpCO2VBQ1csWUFBTTtTQUNiLENBQUMsUUFBS21ELFFBQVQsRUFBbUI7Y0FDYm5ELFdBQUw7Y0FDS0csZ0JBQUw7O0tBSEYsRUFLRyxHQUxIOzs7O1FBU0lnRSxtQkFBTDs7UUFFS0MsY0FBTDs7O1FBR0tDLGFBQUw7O1FBRUtsQixRQUFMLEdBQWdCLEtBQWhCOzs7O2lDQUdjbUIsU0FBU0MsU0FBOEI7T0FBckJoUSxLQUFxQix1RUFBZixLQUFLdUksQ0FBTCxDQUFPNUUsTUFBUTs7T0FDakQwTCxRQUFRLEtBQUtsSCxDQUFMLENBQU83SSxHQUFQLENBQVcsb0JBQVk7V0FBUyxFQUFDZ0ssUUFBTzJHLFNBQVMzRyxNQUFqQixFQUFQO0lBQXpCLENBQVo7U0FDTWhLLEdBQU4sQ0FBVSxVQUFDK0QsQ0FBRCxFQUFJbkYsQ0FBSixFQUFVO01BQUlvTCxNQUFGLENBQVM4RixNQUFULENBQWdCcFAsS0FBaEIsRUFBdUIsQ0FBdkIsRUFBMEIrUCxRQUFRN1IsQ0FBUixDQUExQjtJQUF0QjtPQUNJb1IsUUFBUSxLQUFLL0csQ0FBTCxDQUFPRixLQUFQLEVBQVo7U0FDTStHLE1BQU4sQ0FBYXBQLEtBQWIsRUFBb0IsQ0FBcEIsRUFBdUJnUSxPQUF2Qjs7UUFFSzVDLGFBQUwsQ0FBbUJpQyxLQUFuQixFQUEwQkMsS0FBMUI7Ozs7c0NBRzBDO09BQXpCdFAsS0FBeUIsdUVBQWpCLEtBQUt1SSxDQUFMLENBQU81RSxNQUFQLEdBQWMsQ0FBRzs7T0FDdkMsS0FBSzRFLENBQUwsQ0FBTzVFLE1BQVAsR0FBZ0IsQ0FBbkIsRUFBc0I7O09BRWxCMEwsUUFBUSxLQUFLbEgsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLG9CQUFZO1dBQVMsRUFBQ2dLLFFBQU8yRyxTQUFTM0csTUFBakIsRUFBUDtJQUF6QixDQUFaO1NBQ01oSyxHQUFOLENBQVUsVUFBQytELENBQUQsRUFBTztNQUFJaUcsTUFBRixDQUFTOEYsTUFBVCxDQUFnQnBQLEtBQWhCLEVBQXVCLENBQXZCO0lBQW5CO09BQ0lzUCxRQUFRLEtBQUsvRyxDQUFMLENBQU9GLEtBQVAsRUFBWjtTQUNNK0csTUFBTixDQUFhcFAsS0FBYixFQUFvQixDQUFwQjs7UUFFS29OLGFBQUwsQ0FBbUJpQyxLQUFuQixFQUEwQkMsS0FBMUI7Ozs7a0NBR2U7OztPQUNYblAsV0FBV3hDLEVBQUVzQixlQUFGLENBQWtCLEtBQUtnSSxHQUF2QixFQUE0QixLQUFLc0ksbUJBQWpDLENBQWY7O09BRUcsS0FBS3RJLEdBQUwsQ0FBU3JJLFVBQVQsSUFBdUIsS0FBS2lJLGFBQS9CLEVBQThDO1NBQ3hDQSxhQUFMLENBQW1CcUosV0FBbkIsQ0FBK0IsS0FBS2pKLEdBQXBDO1NBQ0tKLGFBQUwsQ0FBbUJuSSxXQUFuQixDQUErQnlCLFFBQS9COzs7O2NBS1UsWUFBTTtRQUNiQSxTQUFTdkIsVUFBVCxJQUF1QixRQUFLaUksYUFBL0IsRUFBOEM7YUFDeENBLGFBQUwsQ0FBbUJxSixXQUFuQixDQUErQi9QLFFBQS9CO2FBQ0swRyxhQUFMLENBQW1CbkksV0FBbkIsQ0FBK0IsUUFBS3VJLEdBQXBDOztJQUhGLEVBS0csR0FMSDs7OzttQ0FRZ0I7OztRQUNYa0IsQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7O2dDQUVlLFFBQUtpUyx5QkFBTCxDQUErQjlNLENBQS9CLEVBQWtDbkYsQ0FBbEMsQ0FGZjs7UUFFZmtTLEtBRmU7UUFFUkMsS0FGUTtRQUVEZixLQUZDO1FBRU1ELEtBRk47O1FBR2pCLFFBQUtNLGVBQUwsSUFBd0IsQ0FBM0IsRUFBOEI7YUFDeEI1QyxTQUFMLElBQWtCLFFBQUtBLFNBQUwsQ0FBZTFKLENBQWYsRUFBa0JuRixDQUFsQixFQUFxQmtTLEtBQXJCLEVBQTRCQyxLQUE1QixFQUFtQ2hOLEVBQUVtRSxLQUFGLElBQVcsUUFBSzRCLE1BQUwsQ0FBWWxMLENBQVosQ0FBOUMsQ0FBbEI7YUFDS21QLDBCQUFMLENBQWdDK0MsS0FBaEMsRUFBdUNDLEtBQXZDLEVBQThDaE4sRUFBRW1FLEtBQUYsSUFBVyxRQUFLNEIsTUFBTCxDQUFZbEwsQ0FBWixDQUF6RCxFQUF5RUEsQ0FBekUsRUFBNEUsUUFBS2lLLENBQUwsQ0FBT3hFLE1BQW5GOztNQUVDMk0sSUFBRixJQUFVLFFBQUtDLFlBQUwsQ0FBa0JsTixDQUFsQixFQUFxQm5GLENBQXJCLEVBQXdCa1MsS0FBeEIsRUFBK0JDLEtBQS9CLEVBQXNDZixLQUF0QyxFQUE2Q0QsS0FBN0MsQ0FBVjtZQUNLbUIsYUFBTCxDQUFtQm5OLENBQW5CLEVBQXNCbkYsQ0FBdEIsRUFBeUJrUyxLQUF6QixFQUFnQ0MsS0FBaEMsRUFBdUNmLEtBQXZDLEVBQThDRCxLQUE5QztJQVJEOzs7Y0FZVyxZQUFNO1lBQ1hsSCxDQUFMLENBQU83SSxHQUFQLENBQVcsVUFBQytELENBQUQsRUFBSW5GLENBQUosRUFBVTthQUNmNk8sU0FBTCxJQUFrQixRQUFLQSxTQUFMLENBQWUxSixDQUFmLEVBQWtCbkYsQ0FBbEIsRUFBcUIsUUFBS3lMLGdCQUExQixFQUE0Q3RHLEVBQUUySixNQUE5QyxFQUFzRDNKLEVBQUVtRSxLQUFGLElBQVcsUUFBSzRCLE1BQUwsQ0FBWWxMLENBQVosQ0FBakUsQ0FBbEI7YUFDSytPLGNBQUwsQ0FBb0I1SixDQUFwQixFQUF1Qm5GLENBQXZCO0tBRkQ7SUFERCxFQUtHLEdBTEg7Ozs7K0JBUVltRixHQUFHbkYsR0FBR2tTLE9BQU9DLE9BQU9mLE9BQU9ELE9BQU87O09BRXhDb0Isa0JBQWtCcEIsTUFBTS9QLEdBQU4sQ0FBVSxVQUFDNkksQ0FBRCxFQUFJakssQ0FBSjtXQUFXb1IsTUFBTXBSLENBQU4sSUFBVyxHQUFYLEdBQWlCaUssQ0FBNUI7SUFBVixDQUF4QjtPQUNNdUksZUFBZUQsZ0JBQWdCRSxJQUFoQixDQUFxQixHQUFyQixDQUFyQjs7T0FFTUMsWUFBWSxDQUFDLEVBQUNuUixNQUFNNEQsRUFBRWlOLElBQVQsRUFBZXJRLFFBQVFvRCxDQUF2QixFQUEwQm5ELEtBQUssTUFBL0IsRUFBRCxFQUF5QyxFQUFDbUQsR0FBRSxNQUFJcU4sWUFBUCxFQUF6QyxFQUErRCxHQUEvRCxFQUFvRSxRQUFwRSxDQUFsQjtRQUNLbkIsbUJBQUwsQ0FBeUIxUCxJQUF6QixDQUE4QitRLFNBQTlCOzs7T0FHR3ZOLEVBQUV3TixXQUFMLEVBQWtCO1FBQ2JDLHNCQUFvQixLQUFLekgsU0FBekIsTUFBSjtRQUNJMEgsbUJBQWlCLEtBQUtySyxLQUF0QixTQUErQixLQUFLMkMsU0FBeEM7O1FBRU0ySCxjQUFjLENBQ25CLEVBQUN2UixNQUFNNEQsRUFBRXdOLFdBQVQsRUFBc0I1USxRQUFRb0QsQ0FBOUIsRUFBaUNuRCxLQUFLLGFBQXRDLEVBRG1CLEVBRW5CLEVBQUNtRCxHQUFFLE1BQU15TixZQUFOLEdBQXFCSixZQUFyQixHQUFvQ0ssVUFBdkMsRUFGbUIsRUFHbkIsR0FIbUIsRUFJbkIsUUFKbUIsQ0FBcEI7U0FNS3hCLG1CQUFMLENBQXlCMVAsSUFBekIsQ0FBOEJtUixXQUE5Qjs7Ozs7Z0NBSVkzTixHQUFHckQsT0FBT29RLE9BQU9DLE9BQU9mLE9BQU9ELE9BQU87OztPQUMvQzdPLE9BQU8sS0FBS21OLFNBQUwsQ0FBZW5OLElBQTFCOztLQUVFc00sU0FBRixDQUFZeE4sR0FBWixDQUFnQixVQUFDRyxJQUFELEVBQU92QixDQUFQLEVBQWE7WUFDdkJxUixtQkFBTCxDQUF5QjFQLElBQXpCLENBQThCLFFBQUtnTSxPQUFMLENBQWFyTCxJQUFiLEVBQzdCLEVBQUNmLE1BQUtBLElBQU4sRUFBWU0sT0FBTXNELEVBQUV5SixTQUFwQixFQUErQjlNLE9BQU85QixDQUF0QyxFQUQ2QjtVQUV2QkEsQ0FBTixDQUY2QixFQUc3Qm1SLE1BQU1uUixDQUFOLENBSDZCLEVBSTdCOEIsS0FKNkIsQ0FBOUI7SUFERDs7Ozs0Q0FVeUJxRCxHQUFHbkYsR0FBRztPQUMzQmtTLFFBQVEsS0FBS3hHLG9CQUFMLENBQTBCdkIsS0FBMUIsRUFBWjtPQUNJaUgsUUFBUSxLQUFLM0YsZ0JBQUwsQ0FBc0J0QixLQUF0QixFQUFaOztPQUVJZ0ksUUFBUSxLQUFLWixlQUFMLENBQXFCdlIsQ0FBckIsRUFBd0JtSyxLQUF4QixFQUFaO09BQ0lnSCxRQUFRaE0sRUFBRTJKLE1BQUYsQ0FBUzNFLEtBQVQsRUFBWjs7T0FFTTRJLGlCQUFpQmIsTUFBTUEsTUFBTXpNLE1BQU4sR0FBZSxDQUFyQixDQUF2QjtPQUNNdU4saUJBQWlCYixNQUFNQSxNQUFNMU0sTUFBTixHQUFlLENBQXJCLENBQXZCOztPQUVNd04saUJBQWlCN0IsTUFBTUEsTUFBTTNMLE1BQU4sR0FBZSxDQUFyQixDQUF2QjtPQUNNeU4saUJBQWlCL0IsTUFBTUEsTUFBTTFMLE1BQU4sR0FBZSxDQUFyQixDQUF2Qjs7T0FFRyxLQUFLZ00sZUFBTCxJQUF3QixDQUEzQixFQUE4Qjs7Ozs7OztRQU96QjBCLFdBQVcsSUFBSW5FLEtBQUosQ0FBVW9FLEtBQUtDLEdBQUwsQ0FBUyxLQUFLNUIsZUFBZCxDQUFWLEVBQTBDeEMsSUFBMUMsQ0FBK0M4RCxjQUEvQyxDQUFmO1FBQ0lPLFdBQVcsSUFBSXRFLEtBQUosQ0FBVW9FLEtBQUtDLEdBQUwsQ0FBUyxLQUFLNUIsZUFBZCxDQUFWLEVBQTBDeEMsSUFBMUMsQ0FBK0MrRCxjQUEvQyxDQUFmOztZQUVRZCxNQUFNakcsTUFBTixDQUFha0gsUUFBYixDQUFSO1lBQ1FoQixNQUFNbEcsTUFBTixDQUFhcUgsUUFBYixDQUFSO0lBWEQsTUFhTzs7O1FBR0ZILFlBQVcsSUFBSW5FLEtBQUosQ0FBVW9FLEtBQUtDLEdBQUwsQ0FBUyxLQUFLNUIsZUFBZCxDQUFWLEVBQTBDeEMsSUFBMUMsQ0FBK0NnRSxjQUEvQyxDQUFmO1FBQ0lLLFlBQVcsSUFBSXRFLEtBQUosQ0FBVW9FLEtBQUtDLEdBQUwsQ0FBUyxLQUFLNUIsZUFBZCxDQUFWLEVBQTBDeEMsSUFBMUMsQ0FBK0NpRSxjQUEvQyxDQUFmOztZQUVROUIsTUFBTW5GLE1BQU4sQ0FBYWtILFNBQWIsQ0FBUjtZQUNRaEMsTUFBTWxGLE1BQU4sQ0FBYXFILFNBQWIsQ0FBUjs7O1VBR00sQ0FBQ3BCLEtBQUQsRUFBUUMsS0FBUixFQUFlZixLQUFmLEVBQXNCRCxLQUF0QixDQUFQOzs7O21DQUdnQnZMLFFBQVFpSSxlQUFlQyxpQkFBaUI7Ozs7O09BR2xEeUYsVUFBVSxLQUFLN0gsb0JBQXJCO09BQ004SCxVQUFVLEtBQUsvSCxnQkFBckI7O09BRU1nSSxXQUFXLEtBQUtuQyxZQUF0QjtPQUNNb0MsV0FBVyxLQUFLckosQ0FBdEI7O09BRU1zSixnQkFBZ0JKLFFBQVFBLFFBQVE5TixNQUFSLEdBQWlCLENBQXpCLENBQXRCOztPQUVJbU8sdUJBQXVCLFNBQXZCQSxvQkFBdUIsQ0FBQzlRLEtBQUQsRUFBUXlRLE9BQVIsRUFBaUJDLE9BQWpCLEVBQTZCO1FBQ2pESyxTQUFTLFFBQUsxRixXQUFMLENBQ2R2SSxNQURjLEVBRWRpSSxhQUZjLEVBR2QvSyxLQUhjO2tCQUFBLEVBS2RnTCxlQUxjLEVBTWR5RixPQU5jO0tBQWY7WUFRS3JHLFlBQUwsQ0FBa0IxTSxXQUFsQixDQUE4QnFULE1BQTlCOztZQUVLeEMsbUJBQUwsSUFBNEIsUUFBS0EsbUJBQUwsQ0FBeUIxUCxJQUF6QixDQUE4QixDQUN6RCxFQUFDSixNQUFNc1MsTUFBUCxFQUFlaFMsT0FBTyxDQUFDLENBQUQsQ0FBdEIsRUFBMkJDLE9BQU8sQ0FBbEMsRUFEeUQsRUFFekQsRUFBQ2dTLFdBQWVOLE9BQWYsUUFBRCxFQUZ5RCxFQUd6RCxHQUh5RCxFQUl6RCxRQUp5RCxFQUt6RCxXQUx5RCxFQU16RCxFQUFDTSxXQUFlUCxPQUFmLFFBQUQsRUFOeUQsQ0FBOUIsQ0FBNUI7SUFYRDs7UUFxQktyRyxZQUFMLENBQWtCZSxXQUFsQixHQUFnQyxFQUFoQzs7UUFFSzhGLHdCQUFMLENBQ0NSLE9BREQsRUFFQ0MsT0FGRCxFQUdDQyxRQUhELEVBSUNDLFFBSkQsRUFLQ0MsYUFMRCxFQU1DQyxvQkFORDs7OztxQ0FVa0I7Ozs7O09BR1pMLFVBQVUsS0FBS3pILGlCQUFMLENBQXVCMUssR0FBdkIsQ0FBMkI7V0FDMUMsUUFBSytKLFNBQUwsR0FBaUJySSxRQUFRLFFBQUt1SixVQURZO0lBQTNCLENBQWhCO09BRU1tSCxVQUFVLEtBQUszSCxhQUFMLENBQW1CekssR0FBbkIsQ0FBdUI7V0FDdEMsUUFBSytKLFNBQUwsR0FBaUJySSxRQUFRLFFBQUt1SixVQURRO0lBQXZCLENBQWhCOztPQUdNb0gsV0FBVyxLQUFLM0gsaUJBQXRCO09BQ000SCxXQUFXLEtBQUs3SCxhQUF0Qjs7T0FFTThILGdCQUFnQkosUUFBUUEsUUFBUTlOLE1BQVIsR0FBaUIsQ0FBekIsQ0FBdEI7O1FBRUtzSCxZQUFMLENBQWtCa0IsV0FBbEIsR0FBZ0MsRUFBaEM7O1FBRUs4Rix3QkFBTCxDQUNDUixPQURELEVBRUNDLE9BRkQsRUFHQ0MsUUFIRCxFQUlDQyxRQUpELEVBS0NDLGFBTEQsRUFNQyxLQUFLSyxzQkFBTCxDQUE0QjlQLElBQTVCLENBQWlDLElBQWpDLENBTkQsRUFPQyxLQUFLNkksWUFQTjs7OzswQ0FXdUI7OztRQUNsQkksZ0JBQUwsQ0FBc0JjLFdBQXRCLEdBQW9DLEVBQXBDO1FBQ0tySCxlQUFMLENBQXFCeEYsR0FBckIsQ0FBeUIsVUFBQytELENBQUQsRUFBTztZQUMxQjZPLHNCQUFMLENBQ0M3TyxFQUFFVSxLQURILEVBRUMsUUFBSzhHLGFBQUwsR0FBcUJ4SCxFQUFFckMsS0FBRixHQUFVLFFBQUt3SixjQUZyQyxFQUdDLFFBQUtuQixTQUFMLEdBQWlCaEcsRUFBRXJDLEtBQUYsR0FBVSxRQUFLdUosVUFIakMsRUFJQyxDQUpELEVBS0MsUUFBS2MsZ0JBTE4sRUFNQ2hJLEVBQUUwSyxTQU5ILEVBT0MsSUFQRDtJQUREOzs7OzJDQWF3QjBELFNBQVNDLFNBQVNDLFVBQVVDLFVBQVVDLGVBQWVDLHNCQUFzQnBFLE9BQU87T0FDdEd5RSwrQkFBSjtPQUE0QkMsNEJBQTVCO09BQ0lDLGVBQWVULFNBQVNqTyxNQUFULEdBQWtCZ08sU0FBU2hPLE1BQTlDO09BQ0cwTyxlQUFlLENBQWxCLEVBQXFCOzs7OzZCQUlLWCxRQUFRckosS0FBUixDQUFjLENBQWQsRUFBaUJvSixRQUFROU4sTUFBekIsQ0FBekI7MEJBQ3NCaU8sU0FBU3ZKLEtBQVQsQ0FBZSxDQUFmLEVBQWtCc0osU0FBU2hPLE1BQTNCLENBQXRCO0lBTEQsTUFNTzs7OztRQUlBMk8sY0FBYyxJQUFJcEYsS0FBSixDQUFVb0UsS0FBS0MsR0FBTCxDQUFTYyxZQUFULENBQVYsRUFBa0NsRixJQUFsQyxDQUF1QyxFQUF2QyxDQUFwQjswQkFDc0J5RSxTQUFTekgsTUFBVCxDQUFnQm1JLFdBQWhCLENBQXRCOztRQUVNQyxhQUFhLElBQUlyRixLQUFKLENBQVVvRSxLQUFLQyxHQUFMLENBQVNjLFlBQVQsQ0FBVixFQUFrQ2xGLElBQWxDLENBQXVDMEUsYUFBdkMsQ0FBbkI7NkJBQ3lCSCxRQUFRdkgsTUFBUixDQUFlb0ksVUFBZixDQUF6Qjs7O3VCQUdtQmpULEdBQXBCLENBQXdCLFVBQUMwQixLQUFELEVBQVE5QyxDQUFSLEVBQWM7eUJBQ2hCOEMsS0FBckIsRUFBNEJ5USxRQUFRdlQsQ0FBUixDQUE1QixFQUF3Q2lVLHVCQUF1QmpVLENBQXZCLENBQXhDLEVBQW1FQSxDQUFuRSxFQUFzRXdQLEtBQXRFO0lBREQ7O09BSUcyRSxlQUFlLENBQWxCLEVBQXFCOzs7UUFHZEcsZUFBZVosU0FBU3ZKLEtBQVQsQ0FBZXNKLFNBQVNoTyxNQUF4QixDQUFyQjtRQUNNOE8sa0JBQWtCZixRQUFRckosS0FBUixDQUFjb0osUUFBUTlOLE1BQXRCLENBQXhCOztpQkFFYXJFLEdBQWIsQ0FBaUIsVUFBQzBCLEtBQUQsRUFBUTlDLENBQVIsRUFBYzswQkFDVDhDLEtBQXJCLEVBQTRCNlEsYUFBNUIsRUFBMkNZLGdCQUFnQnZVLENBQWhCLENBQTNDLEVBQStEQSxDQUEvRCxFQUFrRXdQLEtBQWxFO0tBREQ7Ozs7OzhCQU1VNUosUUFBUWlJLGVBQWVLLE9BQU9zRyxhQUFhMUcsaUJBQWlCMkcsT0FBTztPQUMxRUMsZ0JBQWdCLEtBQUs5SSxjQUFMLEdBQXNCLEdBQTFDOztPQUVHLEtBQUt2RCxZQUFMLENBQWtCNkYsS0FBbEIsSUFBMkJ3RyxhQUE5QixFQUE2QztRQUN4Q0Msa0JBQWtCRCxnQkFBZ0IsQ0FBdEM7WUFDUXhHLE1BQU0vRCxLQUFOLENBQVksQ0FBWixFQUFld0ssa0JBQWdCLENBQS9CLElBQW9DLE1BQTVDOzs7T0FHR0MsT0FBT25WLEVBQUVvQixTQUFGLENBQVksTUFBWixFQUFvQjtRQUMxQixDQUQwQjtRQUUxQixDQUYwQjtRQUcxQixDQUgwQjtRQUkxQitFO0lBSk0sQ0FBWDs7T0FPSWlQLE9BQU9wVixFQUFFb0IsU0FBRixDQUFZLE1BQVosRUFBb0I7ZUFDbkIyVCxXQURtQjtPQUUzQixDQUYyQjtPQUczQjNHLGFBSDJCO1FBSTFCLE9BSjBCO2VBS25CSztJQUxELENBQVg7O09BUUk0RyxVQUFVclYsRUFBRW9CLFNBQUYsQ0FBWSxHQUFaLEVBQWlCO3lCQUNYaU4sZUFEVzs4QkFFTDJHLEtBQXpCO0lBRmEsQ0FBZDs7V0FLUWpVLFdBQVIsQ0FBb0JvVSxJQUFwQjtXQUNRcFUsV0FBUixDQUFvQnFVLElBQXBCOztVQUVPQyxPQUFQOzs7OzhCQUdXbEgsVUFBVXBGLE9BQU8rRixhQUFhTCxPQUFPc0csYUFBYTFHLGlCQUFpQmlILE9BQW1DO09BQTVCQyxNQUE0Qix1RUFBckIsS0FBcUI7T0FBZG5GLFNBQWMsdUVBQUosRUFBSTs7T0FDN0crRSxPQUFPblYsRUFBRW9CLFNBQUYsQ0FBWSxNQUFaLEVBQW9CO2VBQ25CZ1AsY0FBYyxRQUFkLEdBQXlCLFFBQXpCLEdBQW1DLEVBRGhCO1FBRTFCakMsUUFGMEI7UUFHMUJwRixLQUgwQjtRQUkxQixDQUowQjtRQUsxQjtJQUxNLENBQVg7O09BUUlxTSxPQUFPcFYsRUFBRW9CLFNBQUYsQ0FBWSxNQUFaLEVBQW9CO2VBQ25CMlQsV0FEbUI7T0FFM0JqRyxXQUYyQjtPQUczQixDQUgyQjtRQUkxQixPQUowQjtlQUtuQkwsUUFBTTtJQUxQLENBQVg7O09BUUkrRyxVQUFVeFYsRUFBRW9CLFNBQUYsQ0FBWSxHQUFaLEVBQWlCO3lCQUNYaU4sZUFEVztpQ0FFSGlILEtBQTNCO0lBRmEsQ0FBZDs7T0FLR0MsTUFBSCxFQUFXO1NBQ0xFLEtBQUwsQ0FBV0MsTUFBWCxHQUFvQix1QkFBcEI7OztXQUdPM1UsV0FBUixDQUFvQm9VLElBQXBCO1dBQ1FwVSxXQUFSLENBQW9CcVUsSUFBcEI7O1VBRU9JLE9BQVA7Ozs7eUNBR3NCblMsT0FBT3lRLFNBQVNDLFNBQVN4VCxHQUFHd1AsT0FBT2xOLE1BQXNCO09BQWhCbU0sUUFBZ0IsdUVBQVAsS0FBTzs7Z0NBQ3pCLEtBQUtILHFCQUFMLENBQTJCRyxRQUEzQixDQUR5Qjs7T0FDMUVqRyxLQUQwRTtPQUNuRStGLFdBRG1FO09BQ3REVCxlQURzRDtPQUNyQ0YsUUFEcUM7O09BRTNFd0gsbUJBQW1CLENBQUMzRyxRQUFELEdBQVksY0FBWixHQUE2QixnQkFBcEQ7V0FDUSxDQUFDQSxRQUFELEdBQVkzTCxLQUFaLEdBQW9CLENBQUNBLFFBQU0sRUFBUCxFQUFXOE0sV0FBWCxFQUE1QjtPQUNNeUYsU0FBUyxLQUFLN0csV0FBTCxDQUNkWixRQURjLEVBRWRwRixLQUZjLEVBR2QrRixXQUhjLEVBSWR6TCxLQUpjLEVBS2RzUyxnQkFMYyxFQU1kdEgsZUFOYyxFQU9keUYsT0FQYzthQVFILENBQVYsSUFBZXZULE1BQU0sQ0FSUjtPQUFBLENBQWY7O1NBWU1RLFdBQU4sQ0FBa0I2VSxNQUFsQjs7UUFFS2hFLG1CQUFMLElBQTRCLEtBQUtBLG1CQUFMLENBQXlCMVAsSUFBekIsQ0FBOEIsQ0FDekQsRUFBQ0osTUFBTThULE1BQVAsRUFBZXhULE9BQU8sQ0FBQyxDQUFELENBQXRCLEVBQTJCQyxPQUFPLENBQWxDLEVBRHlELEVBRXpELEVBQUNnUyxtQkFBa0JOLE9BQW5CLEVBRnlELEVBR3pELEdBSHlELEVBSXpELFFBSnlELEVBS3pELFdBTHlELEVBTXpELEVBQUNNLG1CQUFrQlAsT0FBbkIsRUFOeUQsQ0FBOUIsQ0FBNUI7Ozs7b0NBVWlCMVIsT0FBTzs7Ozs7Ozs7OztPQVFwQnlULGtCQUFKO09BQWVDLGtCQUFmO09BQTBCQyx3QkFBMUI7T0FBMkNDLHdCQUEzQztPQUE0REMsa0JBQTVELENBUndCOzs7T0FXcEJDLFVBQVVDLFNBQVN4QyxLQUFLeUMsR0FBTCwrQkFBWWhVLEtBQVosRUFBVCxDQUFkO09BQ0lpVSxVQUFVRixTQUFTeEMsS0FBSzJDLEdBQUwsK0JBQVlsVSxLQUFaLEVBQVQsQ0FBZDtPQUNHaVUsV0FBVyxDQUFkLEVBQWlCO2NBQ04sQ0FBVjs7O09BR0dFLGFBQWEsU0FBYkEsVUFBYSxDQUFDQyxNQUFELEVBQVNDLE1BQVQsRUFBb0I7UUFDaENDLGVBQUo7UUFBWUMsZUFBWjtRQUFvQkMsc0JBQXBCO1FBQW1DQyxzQkFBbkM7UUFBa0RDLHNCQUFsRDtRQUNHLENBQUNOLFNBQU8sRUFBUixFQUFZeFEsTUFBWixJQUFzQixDQUF6QixFQUE0QjtXQUFBLEdBQ0EsRUFEQTtrQkFBQSxHQUNJLENBREo7S0FBNUIsTUFFTztpQ0FDb0IsUUFBSytRLGdDQUFMLENBQXNDUCxNQUF0QyxDQURwQjs7OztXQUFBO2tCQUFBOzs7b0JBSVNFLFNBQVNFLGFBQXpCO29CQUNnQixRQUFLSSxnQkFBTCxDQUFzQlAsTUFBdEIsRUFBOEJLLGFBQTlCLENBQWhCO2FBQ1NELGdCQUFnQkMsYUFBekI7O1dBRU8sQ0FBQ0osTUFBRCxFQUFTQyxNQUFULEVBQWlCQyxhQUFqQixFQUFnQ0MsYUFBaEMsRUFBK0NDLGFBQS9DLENBQVA7SUFaRDs7T0FlTUcsY0FBY1osVUFBVSxDQUFDLENBQS9CO09BQ0dZLGVBQWVmLE9BQWxCLEVBQTJCO3NCQUl2QkssV0FBV0wsT0FBWCxFQUFvQmUsV0FBcEIsQ0FKdUI7Ozs7Ozs7YUFBQTttQkFBQTttQkFBQTthQUFBOztRQUt2QkEsZ0JBQWdCLENBQW5CLEVBQXNCO2lCQUNULENBQVosQ0FBZWpCLGtCQUFrQixDQUFsQjs7SUFOakIsTUFRTzt1QkFHSE8sV0FBV1UsV0FBWCxFQUF3QmYsT0FBeEIsQ0FIRzs7Ozs7O2FBQUE7bUJBQUE7bUJBQUE7YUFBQTs7OztPQU9KSCxrQkFBa0IsQ0FBbEIsS0FBd0IsQ0FBeEIsSUFBNkJDLGtCQUFrQixDQUFsRCxFQUFxREQ7T0FDbERDLGtCQUFrQixDQUFsQixLQUF3QixDQUEzQixFQUE4Qjs7OztpQkFJaEJDLFNBQWI7OztPQUdHaUIsY0FBY25CLGtCQUFrQkMsZUFBcEM7T0FDR2tCLGNBQWMsQ0FBakIsRUFBb0I7bUJBQ0osQ0FBZjtpQkFDYSxDQUFiOzs7VUFHTSxLQUFLQyxhQUFMLENBQ0wsQ0FBQyxDQUFGLEdBQU9yQixTQURELEVBRU5HLFNBRk0sRUFHTmlCLFdBSE0sQ0FBUDs7OztnQ0FPYUUsT0FBT04sZUFBZU8sT0FBTztPQUN0Q0MsWUFBWSxFQUFoQjtRQUNJLElBQUkvVyxJQUFJLENBQVosRUFBZUEsS0FBSzhXLEtBQXBCLEVBQTJCOVcsR0FBM0IsRUFBK0I7Y0FDcEIyQixJQUFWLENBQWVrVixLQUFmO2FBQ1NOLGFBQVQ7O1VBRU1RLFNBQVA7Ozs7bURBR2dDcEIsU0FBUzs7OztPQUluQ0QsWUFBWXRDLEtBQUs0RCxHQUFMLENBQVMsRUFBVCxFQUFjLENBQUNyQixVQUFRLEVBQVQsRUFBYWxRLE1BQWIsR0FBc0IsQ0FBcEMsQ0FBbEI7T0FDTWtSLGNBQWMsS0FBS0YsZ0JBQUwsQ0FBc0JkLE9BQXRCLEVBQStCRCxTQUEvQixDQUFwQjs7O09BR011QixjQUFjdkIsWUFBWWlCLFdBQWhDOztVQUVPLENBQUNNLFdBQUQsRUFBY04sV0FBZCxDQUFQOzs7O21DQUdnQjdULE9BQU9vVSxTQUFTOzs7T0FHNUJQLGNBQWN2RCxLQUFLK0QsSUFBTCxDQUFVclUsUUFBUW9VLE9BQWxCLENBQWxCO09BQ0dQLGNBQWMsQ0FBZCxLQUFvQixDQUF2QixFQUEwQkEsY0FKTTs7VUFNekJBLFdBQVA7Ozs7MENBR3VCQSxhQUFhOztVQUU1QkEsY0FBYyxDQUFmLEdBQW9CQSxXQUFwQixHQUFrQ0EsY0FBYyxDQUF2RDs7OztvREFHaUM7O1FBRTVCL0ssY0FBTCxHQUFzQixLQUFLcEQsS0FBTCxJQUFZLEtBQUs2QixDQUFMLENBQU81RSxNQUFQLEdBQWdCLENBQTVCLENBQXRCO1FBQ0trRyxRQUFMLEdBQWdCLENBQWhCOzs7O3FDQUdrQjtPQUNkeUwsYUFBYSxFQUFqQjs7O1FBR0tuTixDQUFMLENBQU83SSxHQUFQLENBQVcsYUFBSztpQkFDRmdXLFdBQVduTCxNQUFYLENBQWtCOUcsRUFBRWlHLE1BQXBCLENBQWI7SUFERDs7O1VBS09nTSxXQUFXbkwsTUFBWCxDQUFrQixLQUFLckYsZUFBTCxDQUFxQnhGLEdBQXJCLENBQXlCO1dBQUsrRCxFQUFFckMsS0FBUDtJQUF6QixDQUFsQixDQUFQOzs7O3dDQUdxQjs7O1FBQ2hCdU4sVUFBTCxHQUFrQixJQUFJckIsS0FBSixDQUFVLEtBQUt2RCxnQkFBTCxDQUFzQmhHLE1BQWhDLEVBQXdDd0osSUFBeEMsQ0FBNkMsSUFBN0MsQ0FBbEI7UUFDS2hGLENBQUwsQ0FBTzdJLEdBQVAsQ0FBVyxhQUFLO01BQ2IwTixNQUFGLEdBQVczSixFQUFFaUcsTUFBRixDQUFTaEssR0FBVCxDQUFjO1lBQU84RCxRQUFRLFFBQUtpRyxTQUFMLEdBQWlCNUssTUFBTSxRQUFLOEwsVUFBcEMsQ0FBUDtLQUFkLENBQVg7TUFDRXlDLE1BQUYsQ0FBUzFOLEdBQVQsQ0FBYyxVQUFDaVcsS0FBRCxFQUFRclgsQ0FBUixFQUFjO1NBQ3hCcVgsUUFBUSxRQUFLaEgsVUFBTCxDQUFnQnJRLENBQWhCLENBQVgsRUFBK0I7Y0FDekJxUSxVQUFMLENBQWdCclEsQ0FBaEIsSUFBcUJxWCxLQUFyQjs7S0FGRjtJQUZEOzs7OzRDQVV5QkEsT0FBTztPQUM1QnpSLGVBQUo7T0FBWXFFLFVBQVo7T0FDSW9OLFNBQVMsS0FBS2xNLFNBQWxCLEVBQTZCO2FBQ25CLEtBQUtBLFNBQUwsR0FBaUJrTSxLQUExQjtRQUNJQSxLQUFKOzs7UUFHR3pSLFdBQVcsQ0FBZCxFQUFpQjtjQUNQLEtBQUtBLE1BQUwsR0FBYyxJQUF2QjtVQUNLQSxNQUFMOztJQVBGLE1BU087YUFDR3lSLFFBQVEsS0FBS2xNLFNBQXRCO1FBQ0ksS0FBS0EsU0FBVDs7O1FBR0d2RixXQUFXLENBQWQsRUFBaUI7Y0FDUCxLQUFLQSxNQUFMLEdBQWMsSUFBdkI7Ozs7VUFJSyxDQUFDQSxNQUFELEVBQVNxRSxDQUFULENBQVA7Ozs7Z0NBR2E7OztRQUNSMEYsSUFBTCxHQUFZO1dBQ0osYUFBQ3RGLENBQUQsRUFBSWdOLEtBQUosRUFBVzVNLElBQVgsRUFBaUJuQixLQUFqQixFQUF3QnhILEtBQXhCLEVBQStCeU4sY0FBL0IsRUFBa0Q7U0FDcEQrSCxjQUFjLFFBQUsxTCxjQUFMLEdBQXNCbkIsS0FBSzhNLFdBQTdDO1NBQ0lDLFVBQVVuTixJQUFJaU4sY0FBWSxDQUE5Qjs7U0FFSTlPLFFBQVE4TyxjQUFjL0gsY0FBMUI7U0FDSWtJLFlBQVlELFVBQVVoUCxRQUFRMUcsS0FBbEM7O2lDQUVrQixRQUFLNFYseUJBQUwsQ0FBK0JMLEtBQS9CLENBUHNDOztTQU9uRHpSLE1BUG1EO1NBTzNDcUUsQ0FQMkM7O1lBU2pEeEssRUFBRW9CLFNBQUYsQ0FBWSxNQUFaLEVBQW9CO29DQUNFeUksS0FERjtTQUV2Qm1PLFNBRnVCO1NBR3ZCeE4sQ0FIdUI7YUFJbkJ6QixLQUptQjtjQUtsQjVDO01BTEYsQ0FBUDtLQVZVO1dBbUJKLGFBQUN5RSxDQUFELEVBQUlKLENBQUosRUFBT1EsSUFBUCxFQUFhbkIsS0FBYixFQUF1QjtZQUN0QjdKLEVBQUVvQixTQUFGLENBQVksUUFBWixFQUFzQjsyQkFDVHlJLEtBRFM7VUFFeEJlLENBRndCO1VBR3hCSixDQUh3QjtTQUl6QlEsS0FBS2tOO01BSkYsQ0FBUDs7SUFwQkY7O1FBNkJLaEssT0FBTCxHQUFlO1dBQ1AsYUFBQ2lLLE9BQUQsRUFBVXZOLENBQVYsRUFBYWdOLEtBQWIsRUFBb0J2VixLQUFwQixFQUE4QjtTQUNoQytVLFFBQVF4TSxJQUFJLFFBQUt1QixjQUFMLEdBQW9CLENBQXBDO1NBQ0lwRCxRQUFTLFFBQUtvRCxjQUFMLEdBQW9CLENBQXJCLEdBQXdCLFFBQUszQixDQUFMLENBQU94RSxNQUEzQzs7a0NBQ2tCLFFBQUtpUyx5QkFBTCxDQUErQkwsS0FBL0IsQ0FIa0I7O1NBRy9CelIsTUFIK0I7U0FHdkJxRSxDQUh1Qjs7U0FLaEM0TSxRQUFTck8sUUFBUTFHLEtBQXJCOztZQUVPLENBQUM4VixPQUFELEVBQVUsRUFBQ3BQLE9BQU9BLEtBQVIsRUFBZTVDLFFBQVFBLE1BQXZCLEVBQStCeUUsR0FBR0EsQ0FBbEMsRUFBcUNKLEdBQUdBLENBQXhDLEVBQVYsRUFBc0QsR0FBdEQsRUFBMkQsUUFBM0QsQ0FBUDs7S0FSYTtXQVdQLGFBQUM0TixPQUFELEVBQVV4TixDQUFWLEVBQWFnTixLQUFiLEVBQXVCO1lBQ3RCLENBQUNRLE9BQUQsRUFBVSxFQUFDQyxJQUFJek4sQ0FBTCxFQUFRME4sSUFBSVYsS0FBWixFQUFWLEVBQThCLEdBQTlCLEVBQW1DLFFBQW5DLENBQVA7OztJQVpGOzs7O0VBbDlCc0IxUjs7SUFxK0JsQmE7OzttQkFDT2lFLElBQVosRUFBa0I7OzttSEFDWEEsSUFEVzs7VUFHWm5JLElBQUwsR0FBWSxLQUFaO1VBQ0t5TCxXQUFMLEdBQW1CdEQsS0FBS3NELFdBQUwsSUFBb0IsTUFBdkM7VUFDS1csV0FBTCxHQUFtQmpFLEtBQUtpRSxXQUFMLElBQW9CLE1BQXZDO1VBQ0tzSixLQUFMOzs7Ozs7aUNBR2M7O1FBRVRyTSxRQUFMLEdBQWdCLEtBQUtDLGNBQXJCO1FBQ0s2RCxTQUFMLEdBQWlCO1VBQ1YsS0FEVTtVQUVWO2tCQUNRLEtBQUs3RCxjQUFMLEdBQW9COztJQUhuQzs7OztpQ0FRYzs7T0FFVjlKLFFBQVEsS0FBS3VJLENBQUwsQ0FBTzVFLE1BQVAsR0FBZ0IsQ0FBNUI7T0FDSWxFLE9BQU8sS0FBSzBJLENBQUwsQ0FBTyxDQUFQLEVBQVUyRSxTQUFWLENBQW9COU0sS0FBcEIsQ0FBWDtRQUNLbVcseUJBQUwsQ0FBK0JuVyxLQUEvQjs7T0FFRyxLQUFLb1csT0FBUixFQUFpQjtTQUNYQSxPQUFMLENBQWF4WCxVQUFiLENBQXdCc1IsV0FBeEIsQ0FBb0MsS0FBS2tHLE9BQXpDOzs7UUFHSUEsT0FBTCxHQUFlM1csS0FBS1csU0FBTCxFQUFmO1FBQ0tnVyxPQUFMLENBQWFoRCxLQUFiLENBQW1CakcsSUFBbkIsR0FBMEIsU0FBMUI7UUFDS2lKLE9BQUwsQ0FBYWhELEtBQWIsQ0FBbUJpRCxPQUFuQixHQUE2QixLQUE3QjtRQUNLbFAsU0FBTCxDQUFlekksV0FBZixDQUEyQixLQUFLMFgsT0FBaEM7Ozs7aUNBR2M7Ozs7UUFFVDVXLE1BQUwsQ0FBWWlELGdCQUFaLENBQTZCLGFBQTdCLEVBQTRDLFVBQUNrRixDQUFELEVBQU87WUFDN0MyTyxjQUFMLENBQW9CM08sRUFBRTRPLFFBQXRCO0lBREQ7Ozs7aUNBS2M5VyxNQUFNOzs7T0FDaEIrVyxhQUFhLEVBQWpCO1VBQ09DLElBQVAsQ0FBWWhYLEtBQUsrVyxVQUFqQixFQUE2QmxYLEdBQTdCLENBQWlDLGlCQUFTO2VBQzlCTyxJQUFYLENBQWdCSixLQUFLK1csVUFBTCxDQUFnQnhXLEtBQWhCLENBQWhCO0lBREQ7O2NBSVcwVyxNQUFYLENBQWtCO1dBQVFDLEtBQUtDLFNBQWI7SUFBbEIsRUFBMEN0WCxHQUExQyxDQUE4QyxnQkFBUTtZQUNoRDhXLE9BQUwsQ0FBYXRYLFlBQWIsQ0FBMEI2WCxLQUFLRSxJQUEvQixFQUFxQ0YsS0FBS0csU0FBMUM7SUFERDs7OztrQ0FLZTtRQUNWWCx5QkFBTCxDQUErQixLQUFLcFIsYUFBTCxHQUFxQixDQUFwRDs7OzttQ0FHZ0I7UUFDWG9SLHlCQUFMLENBQStCLEtBQUtwUixhQUFMLEdBQXFCLENBQXBEOzs7O29EQUdpQztRQUM1QitFLGNBQUwsR0FBc0IsS0FBS3BELEtBQUwsSUFBWSxLQUFLNkIsQ0FBTCxDQUFPNUUsTUFBUCxHQUFnQixDQUE1QixDQUF0QjtRQUNLa0csUUFBTCxHQUFnQixLQUFLQyxjQUFyQjs7OztFQWpFcUJwQjs7SUFxRWpCbEU7OztvQkFDT21FLElBQVosRUFBa0I7OztxSEFDWEEsSUFEVzs7TUFFZHRFLE9BQU9DLGNBQVAsY0FBZ0NFLFVBQVVELFNBQTdDLEVBQXdEOzs7O1VBSW5EL0QsSUFBTCxHQUFZLE1BQVo7VUFDS3VXLFdBQUwsR0FBbUJwTyxLQUFLb08sV0FBeEI7VUFDSzlLLFdBQUwsR0FBbUJ0RCxLQUFLc0QsV0FBTCxJQUFvQixNQUF2QztVQUNLVyxXQUFMLEdBQW1CakUsS0FBS2lFLFdBQUwsSUFBb0IsTUFBdkM7O1VBRUtzSixLQUFMOzs7Ozs7MkNBR3dCO1FBQ25CYyxpQkFBTDs7Ozs7c0NBSW1COzs7UUFDZEMsWUFBTCxHQUFvQixFQUFwQjtRQUNLOU8sQ0FBTCxDQUFPN0ksR0FBUCxDQUFXLFVBQUMrRCxDQUFELEVBQUluRixDQUFKLEVBQVU7WUFDZitZLFlBQUwsQ0FBa0IvWSxDQUFsQixJQUF1QlAsRUFBRW9CLFNBQUYsQ0FBWSxHQUFaLEVBQWlCO2dCQUM1QiwyQkFBMkJiLENBREM7YUFFL0IsUUFBS2lKO0tBRlMsQ0FBdkI7SUFERDs7OztpQ0FRYzs7UUFFVHdHLFNBQUwsR0FBaUI7VUFDVixLQURVO1VBRVYsRUFBRWtJLFFBQVEsQ0FBVjtJQUZQOzs7OytCQU1ZOzs7UUFDUDFOLENBQUwsQ0FBTzdJLEdBQVAsQ0FBVyxVQUFDK0QsQ0FBRCxFQUFJbkYsQ0FBSixFQUFVO1lBQ2Y2TyxTQUFMLENBQWUxSixDQUFmLEVBQWtCbkYsQ0FBbEIsRUFBcUIsUUFBS3lMLGdCQUExQixFQUE0Q3RHLEVBQUUySixNQUE5QyxFQUFzRDNKLEVBQUVtRSxLQUFGLElBQVcsUUFBSzRCLE1BQUwsQ0FBWWxMLENBQVosQ0FBakU7SUFERDs7Ozs0QkFLU21GLEdBQUduRixHQUFHZ1osYUFBYUMsYUFBYTNQLE9BQU87T0FDNUM0UCxjQUFjRCxZQUFZN1gsR0FBWixDQUFnQixVQUFDNkksQ0FBRCxFQUFJakssQ0FBSjtXQUFXZ1osWUFBWWhaLENBQVosSUFBaUIsR0FBakIsR0FBdUJpSyxDQUFsQztJQUFoQixDQUFsQjtPQUNJa1AsYUFBYUQsWUFBWXpHLElBQVosQ0FBaUIsR0FBakIsQ0FBakI7O1FBRUtzRyxZQUFMLENBQWtCL1ksQ0FBbEIsRUFBcUJpTyxXQUFyQixHQUFtQyxFQUFuQzs7S0FFRW1FLElBQUYsR0FBUzNTLEVBQUVvQixTQUFGLENBQVksTUFBWixFQUFvQjtZQUNwQixLQUFLa1ksWUFBTCxDQUFrQi9ZLENBQWxCLENBRG9COzJCQUVQc0osS0FGTztPQUd6QixNQUFJNlA7SUFIQyxDQUFUOztPQU1HLEtBQUtOLFdBQVIsRUFBcUI7UUFDaEJPLGNBQWEsdUJBQXVCLEdBQXZCLEdBQTZCOVAsS0FBOUM7O1NBRUsrUCxZQUFMLEdBQW9CNVosRUFBRW9CLFNBQUYsQ0FBWSxnQkFBWixFQUE4QjthQUN6QyxLQUFLbUksUUFEb0M7U0FFN0NvUSxXQUY2QztTQUc3QyxDQUg2QztTQUk3QyxDQUo2QztTQUs3QyxDQUw2QztTQU03QztLQU5lLENBQXBCOztRQVNJRSxvQkFBb0IsU0FBcEJBLGlCQUFvQixDQUFDQyxTQUFELEVBQVl2VyxNQUFaLEVBQW9Cc0csS0FBcEIsRUFBMkI2TyxPQUEzQixFQUF1QztPQUM1RHRYLFNBQUYsQ0FBWSxNQUFaLEVBQW9CO21CQUNOLGdCQUFnQnlJLEtBRFY7Z0JBRVRpUSxTQUZTO2dCQUdUdlcsTUFIUztzQkFJSG1WO01BSmpCO0tBREQ7O3NCQVNrQixLQUFLa0IsWUFBdkIsRUFBcUMsSUFBckMsRUFBMkMvUCxLQUEzQyxFQUFrRCxHQUFsRDtzQkFDa0IsS0FBSytQLFlBQXZCLEVBQXFDLEtBQXJDLEVBQTRDL1AsS0FBNUMsRUFBbUQsR0FBbkQ7c0JBQ2tCLEtBQUsrUCxZQUF2QixFQUFxQyxNQUFyQyxFQUE2Qy9QLEtBQTdDLEVBQW9ELENBQXBEOztNQUVFcUosV0FBRixHQUFnQmxULEVBQUVvQixTQUFGLENBQVksTUFBWixFQUFvQjthQUMzQixLQUFLa1ksWUFBTCxDQUFrQi9ZLENBQWxCLENBRDJCOzZCQUFBO1FBR2hDLGNBQVcsS0FBS21MLFNBQWhCLFVBQStCZ08sVUFBL0IsVUFBZ0QsS0FBSzNRLEtBQXJELFNBQThELEtBQUsyQyxTQUFuRTtLQUhZLENBQWhCOztNQU1Fd0gsV0FBRixDQUFjdUMsS0FBZCxDQUFvQkMsTUFBcEIsR0FBNkIsTUFBN0I7TUFDRXhDLFdBQUYsQ0FBY3VDLEtBQWQsQ0FBb0JqRyxJQUFwQixhQUFtQ21LLFdBQW5DOzs7OztFQXhGcUI1Tzs7SUE2RmxCL0Q7OzswQkFDT2dFLElBQVosRUFBa0I7OztpSUFDWEEsSUFEVzs7VUFFWm5JLElBQUwsR0FBWSxZQUFaOztVQUVLc0ksV0FBTCxHQUFtQixRQUFLNUUsY0FBTCxDQUFvQjZFLE9BQXZDO1VBQ0tHLGFBQUwsR0FBcUIsUUFBS2hGLGNBQUwsQ0FBb0JpRixTQUF6QztVQUNLSCxhQUFMLEdBQXFCLFFBQUs5RSxjQUFMLENBQW9CK0UsU0FBekM7O1VBRUt5TyxVQUFMLEdBQWtCLEVBQWxCO1VBQ0tDLGlCQUFMLEdBQXlCLENBQXpCOztVQUVLdk8sTUFBTCxHQUFjVCxLQUFLUyxNQUFuQjs7TUFFRyxDQUFDLFFBQUtBLE1BQU4sSUFBZ0IsUUFBS0EsTUFBTCxDQUFZekYsTUFBWixHQUFxQixRQUFLTSxJQUFMLENBQVUyRSxNQUFWLENBQWlCakYsTUFBekQsRUFBaUU7V0FDM0R5RixNQUFMLEdBQWMsQ0FBQyxZQUFELEVBQWUsTUFBZixFQUF1QixRQUF2QixFQUFpQyxLQUFqQyxFQUF3QyxRQUF4QyxFQUNiLFFBRGEsRUFDSCxPQURHLEVBQ00sYUFETixFQUNxQixRQURyQixFQUMrQixTQUQvQixDQUFkOzs7VUFJSThNLEtBQUw7Ozs7OztvQ0FHaUI7UUFDWnJQLGFBQUwsQ0FBbUJxRSxTQUFuQixJQUFnQyxNQUFNLG9CQUF0QztRQUNLckUsYUFBTCxDQUFtQnVNLEtBQW5CLENBQXlCd0UsU0FBekIsR0FBcUMsTUFBckM7O1FBRUs5USxhQUFMLENBQW1Cb0UsU0FBbkIsSUFBZ0MsTUFBTSxvQkFBdEM7UUFDS3BFLGFBQUwsQ0FBbUJzTSxLQUFuQixDQUF5QnlFLFlBQXpCLEdBQXdDLE1BQXhDO1FBQ0svUSxhQUFMLENBQW1Cc00sS0FBbkIsQ0FBeUIwRSxVQUF6QixHQUFzQyxLQUF0Qzs7OzttQ0FHZ0I7UUFDWEMsU0FBTCxHQUFpQnBhLEVBQUVTLE1BQUYsQ0FBUyxLQUFULEVBQWdCO2VBQ3JCLEtBRHFCO1lBRXhCLEtBQUt5SSxhQUZtQjtXQUd6QixLQUFLTCxVQUhvQjtZQUl4QixLQUFLbkI7SUFKRyxDQUFqQjs7UUFPSzJTLEtBQUwsR0FBYXJhLEVBQUVTLE1BQUYsQ0FBUyxLQUFULEVBQWdCO2VBQ2pCLGdCQURpQjtZQUVwQixLQUFLMlo7SUFGRCxDQUFiOzs7O3FDQU1rQjtRQUNiRSxjQUFMLEdBQXNCdGEsRUFBRVMsTUFBRixDQUFTLEtBQVQsRUFBZ0I7ZUFDMUIsVUFEMEI7WUFFN0IsS0FBSzRaO0lBRlEsQ0FBdEI7Ozs7aUNBTWM7OztRQUNURSxZQUFMLEdBQW9CLEVBQXBCO09BQ0lDLGFBQWEsS0FBS2xVLElBQUwsQ0FBVTJFLE1BQVYsQ0FBaUJ0SixHQUFqQixDQUFxQixVQUFDK0QsQ0FBRCxFQUFJbkYsQ0FBSixFQUFVO1FBQzNDa2EsUUFBUSxDQUFaO1lBQ0tuVSxJQUFMLENBQVU0RSxRQUFWLENBQW1CdkosR0FBbkIsQ0FBdUIsYUFBSztjQUNsQnFJLEVBQUUyQixNQUFGLENBQVNwTCxDQUFULENBQVQ7S0FERDtXQUdPLENBQUNrYSxLQUFELEVBQVEvVSxDQUFSLENBQVA7SUFMZ0IsRUFNZHFULE1BTmMsQ0FNUCxhQUFLO1dBQVNyVCxFQUFFLENBQUYsSUFBTyxDQUFkO0lBTkEsQ0FBakIsQ0FGYzs7T0FVVmdWLFNBQVNGLFVBQWI7O09BRUdBLFdBQVd4VSxNQUFYLEdBQW9CLEtBQUsrVCxVQUE1QixFQUF3QztlQUM1QlksSUFBWCxDQUFnQixVQUFDQyxDQUFELEVBQUlDLENBQUosRUFBVTtZQUFTQSxFQUFFLENBQUYsSUFBT0QsRUFBRSxDQUFGLENBQWQ7S0FBNUI7O2FBRVNKLFdBQVc5UCxLQUFYLENBQWlCLENBQWpCLEVBQW9CLEtBQUtxUCxVQUFMLEdBQWdCLENBQXBDLENBQVQ7UUFDSWUsU0FBU04sV0FBVzlQLEtBQVgsQ0FBaUIsS0FBS3FQLFVBQUwsR0FBZ0IsQ0FBakMsQ0FBYjs7UUFFSWdCLGdCQUFnQixDQUFwQjtXQUNPcFosR0FBUCxDQUFXLGFBQUs7c0JBQWtCK0QsRUFBRSxDQUFGLENBQWpCO0tBQWpCOztXQUVPeEQsSUFBUCxDQUFZLENBQUM2WSxhQUFELEVBQWdCLE1BQWhCLENBQVo7O1NBRUt0UCxNQUFMLENBQVksS0FBS3NPLFVBQUwsR0FBZ0IsQ0FBNUIsSUFBaUMsTUFBakM7OztRQUdJOU8sTUFBTCxHQUFjLEVBQWQ7VUFDT3RKLEdBQVAsQ0FBVyxhQUFLO1lBQ1Y0WSxZQUFMLENBQWtCclksSUFBbEIsQ0FBdUJ3RCxFQUFFLENBQUYsQ0FBdkI7WUFDS3VGLE1BQUwsQ0FBWS9JLElBQVosQ0FBaUJ3RCxFQUFFLENBQUYsQ0FBakI7SUFGRDs7UUFLS3NWLGFBQUwsR0FBcUIsS0FBS1QsWUFBTCxDQUFrQjdQLEtBQWxCLENBQXdCLENBQXhCLEVBQTJCLEtBQUtzUCxpQkFBaEMsQ0FBckI7Ozs7Z0NBR2E7OzswQ0FFVTs7O1FBQ2xCaUIsV0FBTCxHQUFtQixLQUFLVixZQUFMLENBQWtCVyxNQUFsQixDQUF5QixVQUFDTixDQUFELEVBQUlDLENBQUo7V0FBVUQsSUFBSUMsQ0FBZDtJQUF6QixFQUEwQyxDQUExQyxDQUFuQjtRQUNLTSxNQUFMLEdBQWMsRUFBZDtRQUNLWixZQUFMLENBQWtCNVksR0FBbEIsQ0FBc0IsVUFBQzhZLEtBQUQsRUFBUWxhLENBQVIsRUFBYztRQUMvQm1LLFFBQVExSyxFQUFFUyxNQUFGLENBQVMsS0FBVCxFQUFnQjs2Q0FDVyxRQUFLZ0wsTUFBTCxDQUFZbEwsQ0FBWixDQURYO3dCQUVWa2EsUUFBTSxHQUFOLEdBQVUsUUFBS1EsV0FBaEMsTUFGMkI7YUFHbkIsUUFBS1g7S0FIRixDQUFaO1lBS0thLE1BQUwsQ0FBWWpaLElBQVosQ0FBaUJ3SSxLQUFqQjtJQU5EOzs7O2lDQVVjOzs7UUFDVHlRLE1BQUwsQ0FBWXhaLEdBQVosQ0FBZ0IsVUFBQytJLEtBQUQsRUFBUW5LLENBQVIsRUFBYztVQUN2QnVFLGdCQUFOLENBQXVCLFlBQXZCLEVBQXFDLFlBQU07U0FDdENzVyxRQUFRcGIsRUFBRXVELE1BQUYsQ0FBUyxRQUFLMkYsYUFBZCxDQUFaO1NBQTBDbVMsUUFBUXJiLEVBQUV1RCxNQUFGLENBQVNtSCxLQUFULENBQWxEOztTQUVJRSxJQUFJeVEsTUFBTXZYLElBQU4sR0FBYXNYLE1BQU10WCxJQUFuQixHQUEwQjRHLE1BQU01QixXQUFOLEdBQWtCLENBQXBEO1NBQ0kwQixJQUFJNlEsTUFBTTNYLEdBQU4sR0FBWTBYLE1BQU0xWCxHQUFsQixHQUF3QixDQUFoQztTQUNJMEMsUUFBUSxDQUFDLFFBQUtrVixnQkFBTCxJQUF5QixRQUFLQSxnQkFBTCxDQUFzQnRWLE1BQXRCLEdBQTZCLENBQXRELEdBQ1YsUUFBS3NWLGdCQUFMLENBQXNCL2EsQ0FBdEIsQ0FEVSxHQUNpQixRQUFLMEssTUFBTCxDQUFZMUssQ0FBWixDQURsQixJQUNvQyxJQURoRDtTQUVJZ2IsVUFBVSxDQUFDLFFBQUtoQixZQUFMLENBQWtCaGEsQ0FBbEIsSUFBcUIsR0FBckIsR0FBeUIsUUFBSzBhLFdBQS9CLEVBQTRDclYsT0FBNUMsQ0FBb0QsQ0FBcEQsQ0FBZDs7YUFFSzZELEdBQUwsQ0FBU3NILFVBQVQsQ0FBb0JuRyxDQUFwQixFQUF1QkosQ0FBdkIsRUFBMEJwRSxLQUExQixFQUFpQ21WLFVBQVUsR0FBM0M7YUFDSzlSLEdBQUwsQ0FBU3VILFFBQVQ7S0FWRDtJQUREOzs7O2lDQWdCYzs7O09BQ1ZyQixXQUFXLEtBQUsyTCxnQkFBTCxJQUF5QixLQUFLQSxnQkFBTCxDQUFzQnRWLE1BQXRCLEdBQStCLENBQXhELEdBQ1osS0FBS3NWLGdCQURPLEdBQ1ksS0FBS3JRLE1BRGhDO1FBRUsrUCxhQUFMLENBQW1CclosR0FBbkIsQ0FBdUIsVUFBQytELENBQUQsRUFBSW5GLENBQUosRUFBVTtRQUM3Qm1GLENBQUgsRUFBTTtTQUNEa0UsUUFBUTVKLEVBQUVTLE1BQUYsQ0FBUyxLQUFULEVBQWdCO2lCQUNoQixPQURnQjtjQUVuQixRQUFLMEk7TUFGRixDQUFaO1dBSU1GLFNBQU4sK0JBQTRDLFFBQUt3QyxNQUFMLENBQVlsTCxDQUFaLENBQTVDLCtDQUM0Qm9QLFNBQVNwUCxDQUFULENBRDVCLDRCQUVHbUYsQ0FGSDs7SUFORjs7OztFQTFINEJROztJQXlJeEJlOzs7eUJBUUY7MEJBTkZtUSxLQU1FO01BTkZBLEtBTUUsK0JBTk0sRUFNTjsyQkFMRm9FLE1BS0U7TUFMRkEsTUFLRSxnQ0FMTyxFQUtQOzhCQUpGQyxTQUlFO01BSkZBLFNBSUUsbUNBSlUsRUFJVjt5QkFIRm5WLElBR0U7TUFIRkEsSUFHRSw4QkFISyxFQUdMO29DQUZGb1YsZ0JBRUU7TUFGRkEsZ0JBRUUseUNBRmlCLENBRWpCO2dDQURGQyxXQUNFO01BREZBLFdBQ0UscUNBRFksRUFDWjs7O2lIQUNJN1UsVUFBVSxDQUFWLENBREo7O1VBR0dqRSxJQUFMLEdBQVksU0FBWjs7VUFFSzJZLE1BQUwsR0FBY0EsTUFBZDtVQUNLQyxTQUFMLEdBQWlCQSxTQUFqQjtVQUNLblYsSUFBTCxHQUFZQSxJQUFaO1VBQ0tvVixnQkFBTCxHQUF3QkEsZ0JBQXhCO1VBQ0tDLFdBQUwsR0FBbUJBLFdBQW5COztNQUVJQyxRQUFRLElBQUlDLElBQUosRUFBWjtVQUNLekUsS0FBTCxHQUFhQSxTQUFTLFFBQUswRSxRQUFMLENBQWNGLEtBQWQsRUFBcUIsR0FBckIsQ0FBdEI7O1VBRUtHLGFBQUwsR0FBcUIsQ0FBQyxTQUFELEVBQVksU0FBWixFQUF1QixTQUF2QixFQUFrQyxTQUFsQyxFQUE2QyxTQUE3QyxDQUFyQjs7VUFFS3BVLFdBQUwsR0FBbUIsQ0FBbkI7VUFDSzRRLEtBQUw7Ozs7OztzQ0FHbUI7UUFDZHFELEtBQUwsR0FBYSxJQUFJQyxJQUFKLEVBQWI7O09BRUcsQ0FBQyxLQUFLekUsS0FBVCxFQUFnQjtTQUNWQSxLQUFMLEdBQWEsSUFBSXlFLElBQUosRUFBYjtTQUNLekUsS0FBTCxDQUFXNEUsV0FBWCxDQUF3QixLQUFLNUUsS0FBTCxDQUFXNkUsV0FBWCxLQUEyQixDQUFuRDs7UUFFSUMsZ0JBQUwsR0FBd0IsSUFBSUwsSUFBSixDQUFTLEtBQUt6RSxLQUFMLENBQVcrRSxZQUFYLEVBQVQsQ0FBeEI7UUFDS0MsZUFBTCxHQUF1QixJQUFJUCxJQUFKLENBQVMsS0FBS0QsS0FBTCxDQUFXTyxZQUFYLEVBQVQsQ0FBdkI7T0FDRyxLQUFLRCxnQkFBTCxDQUFzQkcsTUFBdEIsT0FBbUMsQ0FBdEMsRUFBeUM7U0FDbkNQLFFBQUwsQ0FBYyxLQUFLSSxnQkFBbkIsRUFBc0MsQ0FBQyxDQUFGLEdBQU8sS0FBS0EsZ0JBQUwsQ0FBc0JHLE1BQXRCLEVBQTVDOztPQUVFLEtBQUtELGVBQUwsQ0FBcUJDLE1BQXJCLE9BQWtDLENBQXJDLEVBQXdDO1NBQ2xDUCxRQUFMLENBQWMsS0FBS00sZUFBbkIsRUFBcUMsQ0FBQyxDQUFGLEdBQU8sS0FBS0EsZUFBTCxDQUFxQkMsTUFBckIsRUFBM0M7O1FBRUlDLFVBQUwsR0FBa0IsS0FBS0MsaUJBQUwsQ0FBdUIsS0FBS0wsZ0JBQUwsR0FBd0IsRUFBL0MsRUFBbUQsS0FBS0UsZUFBTCxHQUF1QixFQUExRSxJQUFnRixDQUFsRzs7Ozs4QkFHVztRQUNOdlQsVUFBTCxHQUFtQixLQUFLeVQsVUFBTixHQUFvQixFQUF0Qzs7T0FFRyxLQUFLWixnQkFBUixFQUEwQjtTQUNwQjdTLFVBQUwsSUFBb0IsS0FBSyxFQUF6Qjs7Ozs7cUNBSWlCO1FBQ2IyVCxrQkFBTCxHQUEwQnhjLEVBQUVvQixTQUFGLENBQVksR0FBWixFQUFpQjtlQUMvQixnQ0FEK0I7WUFFbEMsS0FBS29JO0lBRlksQ0FBMUI7UUFJS2lULFdBQUwsR0FBbUJ6YyxFQUFFb0IsU0FBRixDQUFZLEdBQVosRUFBaUI7ZUFDeEIsYUFEd0I7WUFFM0IsS0FBS29JLFNBRnNCOztJQUFqQixDQUFuQjs7OztpQ0FPYztRQUNUZ1Qsa0JBQUwsQ0FBd0JoTyxXQUF4QixHQUFzQyxFQUF0QztRQUNLaU8sV0FBTCxDQUFpQmpPLFdBQWpCLEdBQStCLEVBQS9CO1FBQ0trTyxZQUFMLEdBQW9CLEtBQUtDLGdCQUFMLENBQXNCLEtBQUtyVyxJQUEzQixFQUFpQyxLQUFLeVYsYUFBdEMsQ0FBcEI7UUFDS2EsV0FBTCxHQUFtQixDQUFDLFNBQUQsRUFBWSxVQUFaLEVBQXdCLE9BQXhCLEVBQWlDLE9BQWpDLEVBQTBDLEtBQTFDLEVBQWlELE1BQWpELEVBQ2xCLE1BRGtCLEVBQ1YsUUFEVSxFQUNBLFdBREEsRUFDYSxTQURiLEVBQ3dCLFVBRHhCLEVBQ29DLFVBRHBDLENBQW5COztRQUlLQyxtQ0FBTCxDQUF5QyxLQUFLUCxVQUE5Qzs7OztzREFHbUNRLGFBQWE7T0FDNUNDLHNCQUFzQixJQUFJbEIsSUFBSixDQUFTLEtBQUtLLGdCQUFkLENBQTFCO1FBQ0tjLFFBQUwsR0FBZ0IsQ0FBaEI7UUFDS0MsYUFBTCxHQUFxQkYsb0JBQW9CRyxRQUFwQixFQUFyQjs7UUFFS0MsTUFBTCxHQUFjLENBQUMsS0FBS0YsYUFBTCxHQUFxQixFQUF0QixDQUFkO1FBQ0tHLFdBQUwsR0FBbUIsRUFBbkIsRUFBdUIsS0FBS0Msa0JBQUwsR0FBMEIsRUFBakQ7UUFDS0QsV0FBTCxDQUFpQixLQUFLSCxhQUF0QixJQUF1QyxDQUF2QztRQUNLSSxrQkFBTCxDQUF3Qm5iLElBQXhCLENBQTZCLEVBQTdCOztRQUVJLElBQUkzQixJQUFJLENBQVosRUFBZUEsSUFBSXVjLFdBQW5CLEVBQWdDdmMsR0FBaEMsRUFBcUM7UUFDaEMrYyxtQkFBSjtRQUFnQkMsZUFBZSxDQUEvQjtRQUNJQyxNQUFNLElBQUkzQixJQUFKLENBQVNrQixtQkFBVCxDQUFWOztnQ0FFNkIsS0FBS1Usc0JBQUwsQ0FBNEJELEdBQTVCLEVBQWlDLEtBQUtSLFFBQXRDLENBSk87Ozs7Y0FBQTtnQkFBQTs7U0FLL0JQLFdBQUwsQ0FBaUIxYixXQUFqQixDQUE2QnVjLFVBQTdCO1NBQ0tOLFFBQUwsSUFBaUIsSUFBSTdHLFNBQVMsS0FBS3VGLGdCQUFMLElBQXlCNkIsWUFBbEMsQ0FBckI7U0FDS0gsV0FBTCxDQUFpQixLQUFLSCxhQUF0QjtRQUNHTSxZQUFILEVBQWlCO1VBQ1hOLGFBQUwsR0FBcUIsQ0FBQyxLQUFLQSxhQUFMLEdBQXFCLENBQXRCLElBQTJCLEVBQWhEO1VBQ0tFLE1BQUwsQ0FBWWpiLElBQVosQ0FBaUIsS0FBSythLGFBQUwsR0FBcUIsRUFBdEM7VUFDS0csV0FBTCxDQUFpQixLQUFLSCxhQUF0QixJQUF1QyxDQUF2Qzs7U0FFSW5CLFFBQUwsQ0FBY2lCLG1CQUFkLEVBQW1DLENBQW5DOztRQUVJVyxtQkFBTDs7Ozt5Q0FHc0JDLGNBQWN0YixPQUFPO09BQ3JDdWIsaUJBQWlCLENBQXZCO09BQ01DLGNBQWMsRUFBcEI7T0FDTUMsZUFBZSxDQUFyQjtPQUNNQyxPQUFPLENBQWI7O09BRUlSLGVBQWUsQ0FBbkI7T0FDSVMsa0JBQWtCLENBQXRCOztPQUVJVixhQUFhdGQsRUFBRW9CLFNBQUYsQ0FBWSxHQUFaLEVBQWlCO2VBQ3RCLFlBRHNCO1lBRXpCLEtBQUtxYjtJQUZHLENBQWpCOztRQUtJLElBQUlqUyxJQUFJLENBQVIsRUFBV2pLLElBQUksQ0FBbkIsRUFBc0JBLElBQUlxZCxjQUExQixFQUEwQ3JkLEtBQUt3ZCxJQUFMLEVBQVd2VCxLQUFNcVQsY0FBY0MsWUFBekUsRUFBd0Y7UUFDbkZHLGFBQWEsQ0FBakI7UUFDSUMsY0FBYyxDQUFsQjs7UUFFSUMsWUFBWXhLLEtBQUt5SyxLQUFMLENBQVdULGFBQWFVLE9BQWIsS0FBdUIsSUFBbEMsRUFBd0N6WSxPQUF4QyxDQUFnRCxDQUFoRCxDQUFoQjs7UUFFRyxLQUFLVSxJQUFMLENBQVU2WCxTQUFWLENBQUgsRUFBeUI7a0JBQ1gsS0FBSzdYLElBQUwsQ0FBVTZYLFNBQVYsQ0FBYjttQkFDYyxLQUFLRyxrQkFBTCxDQUF3QkwsVUFBeEIsRUFBb0MsS0FBS3ZCLFlBQXpDLENBQWQ7OztRQUdFLEtBQUtwVyxJQUFMLENBQVVxTixLQUFLNEssS0FBTCxDQUFXSixTQUFYLENBQVYsQ0FBSCxFQUFxQztrQkFDdkIsS0FBSzdYLElBQUwsQ0FBVXFOLEtBQUs0SyxLQUFMLENBQVdKLFNBQVgsQ0FBVixDQUFiO21CQUNjLEtBQUtHLGtCQUFMLENBQXdCTCxVQUF4QixFQUFvQyxLQUFLdkIsWUFBekMsQ0FBZDs7O1FBR0c5UixJQUFJLEtBQUssQ0FBQ3ZJLFFBQVEyYixlQUFULElBQTRCLEVBQXpDOztNQUVFNWMsU0FBRixDQUFZLE1BQVosRUFBb0I7Z0JBQ1IsS0FEUTthQUVYa2MsVUFGVztRQUdoQjFTLENBSGdCO1FBSWhCSixDQUpnQjtZQUtacVQsV0FMWTthQU1YQSxXQU5XO1dBT1osS0FBSzlCLGFBQUwsQ0FBbUJtQyxXQUFuQixDQVBZO2tCQVFOLEtBQUtNLGNBQUwsQ0FBb0JiLFlBQXBCLENBUk07bUJBU0xNLFVBVEs7aUJBVVBOLGFBQWF0QixNQUFiO0tBVmI7O1FBYUlvQyxZQUFZLElBQUk1QyxJQUFKLENBQVM4QixZQUFULENBQWhCO1NBQ0s3QixRQUFMLENBQWMyQyxTQUFkLEVBQXlCLENBQXpCO1FBQ0dBLFVBQVV2QixRQUFWLEtBQXVCUyxhQUFhVCxRQUFiLEVBQTFCLEVBQW1EO29CQUNuQyxDQUFmO1NBQ0csS0FBS3hCLGdCQUFSLEVBQTBCO3dCQUNQLENBQWxCOzs7VUFHSTJCLGtCQUFMLENBQXdCbmIsSUFBeEIsQ0FBNkIsS0FBSyxDQUFDRyxRQUFRMmIsZUFBVCxJQUE0QixFQUE5RDs7bUJBRWNTLFNBQWY7OztVQUdNLENBQUNuQixVQUFELEVBQWFDLFlBQWIsQ0FBUDs7Ozt3Q0FHcUI7Ozs7Ozs7Ozs7Ozs7Ozs7O1FBZWhCSixNQUFMLENBQVl1QixLQUFaO1FBQ0tyQixrQkFBTCxDQUF3QnFCLEtBQXhCO1FBQ0t2QixNQUFMLENBQVl3QixHQUFaO1FBQ0t0QixrQkFBTCxDQUF3QnNCLEdBQXhCOztRQUVLdEIsa0JBQUwsQ0FBd0IxYixHQUF4QixDQUE0QixVQUFDeVYsS0FBRCxFQUFRN1csQ0FBUixFQUFjO1FBQ3JDcWUsYUFBYyxRQUFLaEMsV0FBTCxDQUFpQixRQUFLTyxNQUFMLENBQVk1YyxDQUFaLENBQWpCLEVBQWlDc2UsU0FBakMsQ0FBMkMsQ0FBM0MsRUFBOEMsQ0FBOUMsQ0FBbEI7O01BRUV6ZCxTQUFGLENBQVksTUFBWixFQUFvQjtnQkFDUixjQURRO2FBRVgsUUFBS29iLGtCQUZNO1FBR2hCcEYsUUFBUSxFQUhRO1FBSWhCLEVBSmdCO1NBS2YsT0FMZTtnQkFNUndIO0tBTlo7SUFIRDs7OzswQ0FldUI7U0FDakJoWSxTQUFOLENBQWdCOEQsS0FBaEIsQ0FBc0JvVSxJQUF0QixDQUNDLEtBQUs5VixTQUFMLENBQWUrVixnQkFBZixDQUFnQyw0Q0FBaEMsQ0FERCxFQUVFcGQsR0FGRixDQUVNLGFBQUs7TUFDUjhULEtBQUYsQ0FBUXVKLE9BQVIsR0FBa0IsTUFBbEI7SUFIRDtRQUtLOVYsYUFBTCxDQUFtQnVNLEtBQW5CLENBQXlCd0UsU0FBekIsR0FBcUMsS0FBckM7UUFDSy9RLGFBQUwsQ0FBbUJ1TSxLQUFuQixDQUF5QjBFLFVBQXpCLEdBQXNDLEtBQXRDOzs7O2lDQUdjOzs7U0FDUnZULFNBQU4sQ0FBZ0I4RCxLQUFoQixDQUFzQm9VLElBQXRCLENBQ0MzZSxTQUFTNGUsZ0JBQVQsQ0FBMEIsa0JBQTFCLENBREQsRUFFRXBkLEdBRkYsQ0FFTSxjQUFNO09BQ1JtRCxnQkFBSCxDQUFvQixZQUFwQixFQUFrQyxVQUFDa0YsQ0FBRCxFQUFPO1NBQ3BDcU4sUUFBUXJOLEVBQUU5RSxNQUFGLENBQVM5QixZQUFULENBQXNCLFlBQXRCLENBQVo7U0FDSTZiLGFBQWFqVixFQUFFOUUsTUFBRixDQUFTOUIsWUFBVCxDQUFzQixXQUF0QixFQUFtQ3dCLEtBQW5DLENBQXlDLEdBQXpDLENBQWpCOztTQUVJc2EsUUFBUSxRQUFLdEMsV0FBTCxDQUFpQnpHLFNBQVM4SSxXQUFXLENBQVgsQ0FBVCxJQUF3QixDQUF6QyxFQUE0Q0osU0FBNUMsQ0FBc0QsQ0FBdEQsRUFBeUQsQ0FBekQsQ0FBWjs7U0FFSXpELFFBQVEsUUFBS2xTLGFBQUwsQ0FBbUJ6RixxQkFBbkIsRUFBWjtTQUF3RDRYLFFBQVFyUixFQUFFOUUsTUFBRixDQUFTekIscUJBQVQsRUFBaEU7O1NBRUlzRixRQUFRb04sU0FBU25NLEVBQUU5RSxNQUFGLENBQVM5QixZQUFULENBQXNCLE9BQXRCLENBQVQsQ0FBWjtTQUNJd0gsSUFBSXlRLE1BQU12WCxJQUFOLEdBQWFzWCxNQUFNdFgsSUFBbkIsR0FBMEIsQ0FBQ2lGLFFBQU0sQ0FBUCxJQUFVLENBQTVDO1NBQ0l5QixJQUFJNlEsTUFBTTNYLEdBQU4sR0FBWTBYLE1BQU0xWCxHQUFsQixHQUF3QixDQUFDcUYsUUFBTSxDQUFQLElBQVUsQ0FBMUM7U0FDSTFGLFFBQVFnVSxRQUFRLEdBQVIsR0FBYyxRQUFLc0UsV0FBL0I7U0FDSXpDLE9BQU8sU0FBU2dHLEtBQVQsR0FBaUIsR0FBakIsR0FBdUJELFdBQVcsQ0FBWCxDQUF2QixHQUF1QyxJQUF2QyxHQUE4Q0EsV0FBVyxDQUFYLENBQXpEOzthQUVLeFYsR0FBTCxDQUFTc0gsVUFBVCxDQUFvQm5HLENBQXBCLEVBQXVCSixDQUF2QixFQUEwQjBPLElBQTFCLEVBQWdDN1YsS0FBaEMsRUFBdUMsRUFBdkMsRUFBMkMsQ0FBM0M7YUFDS29HLEdBQUwsQ0FBU3VILFFBQVQ7S0FmRDtJQUhEOzs7O3lCQXVCTTFLLE1BQU07UUFDUEEsSUFBTCxHQUFZQSxJQUFaO1FBQ0s4QixZQUFMO1FBQ0t1QixZQUFMOzs7O3FDQUd1QztPQUF2QnJELElBQXVCLHVFQUFsQixFQUFrQjtPQUFkNlksWUFBYzs7T0FDbkNDLGNBQWMxWSxPQUFPb1MsSUFBUCxDQUFZeFMsSUFBWixFQUFrQjNFLEdBQWxCLENBQXNCO1dBQU8yRSxLQUFLL0QsR0FBTCxDQUFQO0lBQXRCLENBQWxCO09BQ0k4YyxpQkFBaUIxTCxLQUFLeUMsR0FBTCwrQkFBWWdKLFdBQVosRUFBckI7O09BRUlFLG9CQUFvQixLQUFLSCxhQUFhblosTUFBYixHQUFzQixDQUEzQixDQUF4QjtPQUNJMFcsZUFBZSxFQUFuQjs7Z0JBRWEvYSxHQUFiLENBQWlCLFVBQUNrSSxLQUFELEVBQVF0SixDQUFSLEVBQWM7UUFDMUJnZixhQUFhRixrQkFBa0JDLG9CQUFvQi9lLENBQXRDLENBQWpCO2lCQUNhMkIsSUFBYixDQUFrQnFkLFVBQWxCO0lBRkQ7O1VBS083QyxZQUFQOzs7O3FDQUdrQnJaLE9BQU9xWixjQUFjO1VBQ2hDQSxhQUFhM0QsTUFBYixDQUFvQixVQUFDclQsQ0FBRCxFQUFJbkYsQ0FBSixFQUFVO1FBQ2pDQSxNQUFNLENBQVQsRUFBWTtZQUNKbWMsYUFBYSxDQUFiLElBQWtCclosS0FBekI7O1dBRU1xQyxLQUFLckMsS0FBWjtJQUpNLEVBS0oyQyxNQUxJLEdBS0ssQ0FMWjs7Ozs7Ozs7OytCQVdZd1osVUFBVTtPQUNsQkMsU0FBUyxJQUFJNUQsSUFBSixDQUFTMkQsUUFBVCxDQUFiO1VBQ09FLFVBQVAsQ0FBa0JELE9BQU9FLFVBQVAsS0FBc0JGLE9BQU9HLGlCQUFQLEVBQXhDO1VBQ09ILE1BQVA7Ozs7aUNBR2NJLE1BQU07T0FDaEJDLEtBQUtELEtBQUtFLE9BQUwsRUFBVDtPQUNJQyxLQUFLSCxLQUFLM0MsUUFBTCxLQUFrQixDQUEzQixDQUZvQjtVQUdiLENBQ04sQ0FBQzRDLEtBQUcsQ0FBSCxHQUFPLEVBQVAsR0FBWSxHQUFiLElBQW9CQSxFQURkLEVBRU4sQ0FBQ0UsS0FBRyxDQUFILEdBQU8sRUFBUCxHQUFZLEdBQWIsSUFBb0JBLEVBRmQsRUFHTkgsS0FBSzVELFdBQUwsRUFITSxFQUlMakosSUFKSyxDQUlBLEdBSkEsQ0FBUDs7OztvQ0FPaUJpTixnQkFBZ0JDLGNBQWM7VUFDeEN2TSxLQUFLK0QsSUFBTCxDQUFVLEtBQUt5SSxnQkFBTCxDQUFzQkYsY0FBdEIsRUFBc0NDLFlBQXRDLElBQXNELENBQWhFLENBQVA7Ozs7bUNBR2dCRCxnQkFBZ0JDLGNBQWM7T0FDMUNFLHVCQUF1QixLQUFLLEVBQUwsR0FBVSxFQUFWLEdBQWUsSUFBMUM7VUFDTyxDQUFDLEtBQUtDLFlBQUwsQ0FBa0JILFlBQWxCLElBQWtDLEtBQUtHLFlBQUwsQ0FBa0JKLGNBQWxCLENBQW5DLElBQXdFRyxvQkFBL0U7Ozs7Ozs7MkJBSVFQLE1BQU1TLGdCQUFnQjtRQUN6QkMsT0FBTCxDQUFhVixLQUFLRSxPQUFMLEtBQWlCTyxjQUE5Qjs7OzttQ0FHZ0I7OztFQTFTSXBhOztJQTZTaEJ3RDt3QkFHRjsyQkFERjdILE1BQ0U7TUFERkEsTUFDRSxnQ0FETyxJQUNQOzs7T0FDR0EsTUFBTCxHQUFjQSxNQUFkO09BQ0syZSxVQUFMLEdBQWtCLEVBQWxCO09BQ0tDLFdBQUwsR0FBbUIsRUFBbkI7T0FDS0MsV0FBTCxHQUFtQixFQUFuQjtPQUNLQyxpQkFBTCxHQUF5QixDQUF6Qjs7T0FFSy9WLENBQUwsR0FBUyxDQUFUO09BQ0tKLENBQUwsR0FBUyxDQUFUOztPQUVLOUcsR0FBTCxHQUFXLENBQVg7T0FDS0ksSUFBTCxHQUFZLENBQVo7O09BRUt5VSxLQUFMOzs7OzswQkFHTztRQUNGaFEsWUFBTDs7Ozs0QkFHUztRQUNKaUgsSUFBTDtRQUNLb1IsYUFBTDs7Ozs7aUNBSWM7OztRQUNUNVgsU0FBTCxHQUFpQmhKLEVBQUVTLE1BQUYsQ0FBUyxLQUFULEVBQWdCO1lBQ3hCLEtBQUtvQixNQURtQjtlQUVyQiwwQkFGcUI7O0lBQWhCLENBQWpCO1FBT0s2TyxRQUFMOztRQUVLdEssS0FBTCxHQUFhLEtBQUs0QyxTQUFMLENBQWU1SSxhQUFmLENBQTZCLFFBQTdCLENBQWI7UUFDS3lnQixlQUFMLEdBQXVCLEtBQUs3WCxTQUFMLENBQWU1SSxhQUFmLENBQTZCLGtCQUE3QixDQUF2Qjs7UUFFS3lCLE1BQUwsQ0FBWWlELGdCQUFaLENBQTZCLFlBQTdCLEVBQTJDLFlBQU07WUFDM0M0TCxRQUFMO0lBREQ7Ozs7eUJBS007OztPQUNGdEssY0FBSjtPQUNHLEtBQUt1YSxpQkFBUixFQUEyQjt5QkFDUCxLQUFLRixXQUF4QixpQkFBK0MsS0FBS0QsVUFBcEQ7SUFERCxNQUVPO1lBQ0ssS0FBS0EsVUFBaEIsZ0JBQXFDLEtBQUtDLFdBQTFDOztRQUVJcmEsS0FBTCxDQUFXNkMsU0FBWCxHQUF1QjdDLEtBQXZCO1FBQ0t5YSxlQUFMLENBQXFCNVgsU0FBckIsR0FBaUMsRUFBakM7O1FBRUt5WCxXQUFMLENBQWlCL2UsR0FBakIsQ0FBcUIsVUFBQ21QLE1BQUQsRUFBUztRQUN6QmdRLEtBQUs5Z0IsRUFBRVMsTUFBRixDQUFTLElBQVQsRUFBZTtpQ0FDRXFRLE9BQUlqSCxLQUFKLElBQWEsT0FBdEMsQ0FEdUI7c0RBRXVCaUgsT0FBSXpOLEtBQUosR0FBWXlOLE9BQUl6TixLQUFoQixHQUF3QixFQUF0RSwrQkFDR3lOLE9BQUkxSyxLQUFKLEdBQVkwSyxPQUFJMUssS0FBaEIsR0FBd0IsRUFEM0I7S0FGUSxDQUFUOztZQU1LeWEsZUFBTCxDQUFxQjlmLFdBQXJCLENBQWlDK2YsRUFBakM7SUFQRDs7OztrQ0FXZTtRQUNWcGQsR0FBTCxHQUFXLEtBQUs4RyxDQUFMLEdBQVMsS0FBS3hCLFNBQUwsQ0FBZStYLFlBQW5DO1FBQ0tqZCxJQUFMLEdBQVksS0FBSzhHLENBQUwsR0FBUyxLQUFLNUIsU0FBTCxDQUFlRixXQUFmLEdBQTJCLENBQWhEO09BQ0lrWSxXQUFXLEtBQUtuZixNQUFMLENBQVlpSCxXQUFaLEdBQTBCLEtBQUtFLFNBQUwsQ0FBZUYsV0FBeEQ7O09BRUltWSxVQUFVLEtBQUtqWSxTQUFMLENBQWU1SSxhQUFmLENBQTZCLGNBQTdCLENBQWQ7O09BRUcsS0FBSzBELElBQUwsR0FBWSxDQUFmLEVBQWtCO1lBQ1QyUixLQUFSLENBQWMzUixJQUFkLG1CQUFtQyxDQUFDLENBQUQsR0FBSyxLQUFLQSxJQUE3QztTQUNLQSxJQUFMLEdBQVksQ0FBWjtJQUZELE1BR08sSUFBRyxLQUFLQSxJQUFMLEdBQVlrZCxRQUFmLEVBQXlCO1FBQzNCRSxRQUFRLEtBQUtwZCxJQUFMLEdBQVlrZCxRQUF4QjtZQUNRdkwsS0FBUixDQUFjM1IsSUFBZCxtQkFBbUNvZCxLQUFuQztTQUNLcGQsSUFBTCxHQUFZa2QsUUFBWjtJQUhNLE1BSUE7WUFDRXZMLEtBQVIsQ0FBYzNSLElBQWQ7Ozs7OzZCQUlTOEcsR0FBR0osR0FBK0U7T0FBNUVnVyxVQUE0RSx1RUFBL0QsRUFBK0Q7T0FBM0RDLFdBQTJELHVFQUE3QyxFQUE2QztPQUF6Q0MsV0FBeUMsdUVBQTNCLEVBQTJCO09BQXZCQyxpQkFBdUIsdUVBQUgsQ0FBRzs7UUFDdkZILFVBQUwsR0FBa0JBLFVBQWxCO1FBQ0tDLFdBQUwsR0FBbUJBLFdBQW5CO1FBQ0tDLFdBQUwsR0FBbUJBLFdBQW5CO1FBQ0s5VixDQUFMLEdBQVNBLENBQVQ7UUFDS0osQ0FBTCxHQUFTQSxDQUFUO1FBQ0ttVyxpQkFBTCxHQUF5QkEsaUJBQXpCO1FBQ0s3WSxPQUFMOzs7OzZCQUdVO1FBQ0xrQixTQUFMLENBQWV5TSxLQUFmLENBQXFCL1IsR0FBckIsR0FBMkIsS0FBM0I7UUFDS3NGLFNBQUwsQ0FBZXlNLEtBQWYsQ0FBcUIzUixJQUFyQixHQUE0QixLQUE1QjtRQUNLa0YsU0FBTCxDQUFleU0sS0FBZixDQUFxQmlELE9BQXJCLEdBQStCLEdBQS9COzs7OzZCQUdVO1FBQ0wxUCxTQUFMLENBQWV5TSxLQUFmLENBQXFCL1IsR0FBckIsR0FBMkIsS0FBS0EsR0FBTCxHQUFXLElBQXRDO1FBQ0tzRixTQUFMLENBQWV5TSxLQUFmLENBQXFCM1IsSUFBckIsR0FBNEIsS0FBS0EsSUFBTCxHQUFZLElBQXhDO1FBQ0trRixTQUFMLENBQWV5TSxLQUFmLENBQXFCaUQsT0FBckIsR0FBK0IsR0FBL0I7Ozs7Ozs7Ozs7OzsifQ== diff --git a/docs/assets/js/index.js b/docs/assets/js/index.js index 18a3e80..3c01309 100755 --- a/docs/assets/js/index.js +++ b/docs/assets/js/index.js @@ -141,7 +141,7 @@ let heatmap_data = { // Charts // ================================================================================ -let bar_composite_chart = new frappe.chart.FrappeChart ({ +let bar_composite_chart = new Chart ({ parent: "#chart-composite-1", data: bar_composite_data, type: 'bar', @@ -150,7 +150,7 @@ let bar_composite_chart = new frappe.chart.FrappeChart ({ // region_fill: 1 }) -let line_composite_chart = new frappe.chart.FrappeChart ({ +let line_composite_chart = new Chart ({ parent: "#chart-composite-2", data: line_composite_data, type: 'line', @@ -161,7 +161,7 @@ bar_composite_chart.parent.addEventListener('data-select', (e) => { line_composite_chart.update_values([more_line_data[e.index]]); }); -let type_chart = new frappe.chart.FrappeChart({ +let type_chart = new Chart({ parent: "#chart-types", data: type_data, type: 'bar', @@ -170,7 +170,7 @@ let type_chart = new frappe.chart.FrappeChart({ // y_axis_mode: 'tick' }); -let update_chart = new frappe.chart.FrappeChart({ +let update_chart = new Chart({ parent: "#chart-update", data: update_data, type: 'line', @@ -178,7 +178,7 @@ let update_chart = new frappe.chart.FrappeChart({ region_fill: 1 }); -let events_chart = new frappe.chart.FrappeChart({ +let events_chart = new Chart({ parent: "#chart-events", data: events_data, type: 'bar', @@ -186,14 +186,14 @@ let events_chart = new frappe.chart.FrappeChart({ is_navigable: 1, }); -let aggr_chart = new frappe.chart.FrappeChart({ +let aggr_chart = new Chart({ parent: "#chart-aggr", data: aggr_data, type: 'bar', height: 250 }); -let heatmap = new frappe.chart.FrappeChart({ +let heatmap = new Chart({ parent: "#chart-heatmap", data: heatmap_data, type: 'heatmap', @@ -226,7 +226,7 @@ Array.prototype.slice.call( let chart_update_buttons = document.querySelector('.chart-update-buttons'); chart_update_buttons.querySelector('[data-update="random"]').addEventListener("click", (e) => { - $$.shuffle(update_data_all_indices); + shuffle(update_data_all_indices); update_chart.update_values( [{values: get_update_data(update_data_all_values)}], get_update_data(update_data_all_labels) @@ -267,3 +267,25 @@ document.querySelector('[data-aggregation="average"]').addEventListener("click", e.target.innerHTML = "Show Average"; } }); + +function shuffle(array) { + // https://stackoverflow.com/a/2450976/6495043 + // Awesomeness: https://bost.ocks.org/mike/shuffle/ + + var currentIndex = array.length, temporaryValue, randomIndex; + + // While there remain elements to shuffle... + while (0 !== currentIndex) { + + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + + return array; +} diff --git a/docs/index.html b/docs/index.html index 8666583..e3f1fd5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -14,7 +14,7 @@ - + @@ -155,7 +155,9 @@ - + + + diff --git a/package-lock.json b/package-lock.json index 1d520d8..1fc2b1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,32 +4,1810 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "acorn": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.0.tgz", + "integrity": "sha1-opbhf3v658HOT34N5T0pyzIWLfA=", + "dev": true + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-external-helpers": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz", + "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.5.1", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-preset-es2016": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz", + "integrity": "sha1-+QC/k+LrwNJ235uKtZck6/2Vn4s=", + "dev": true, + "requires": { + "babel-plugin-transform-exponentiation-operator": "6.24.1" + } + }, + "babel-preset-es2017": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz", + "integrity": "sha1-WXvq37n38gi8/YoS6bKym4svFNE=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1" + } + }, + "babel-preset-latest": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-latest/-/babel-preset-latest-6.24.1.tgz", + "integrity": "sha1-Z33gaRVKdIXC0lxXfAL2JLhbheg=", + "dev": true, + "requires": { + "babel-preset-es2015": "6.24.1", + "babel-preset-es2016": "6.24.1", + "babel-preset-es2017": "6.24.1" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserslist": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.5.1.tgz", + "integrity": "sha512-jAvM2ku7YDJ+leAq3bFH1DE0Ylw+F+EQDq4GkqZfgPEqpWYw9ofQH85uKSB9r3Tv7XDbfqVtE+sdvKJW7IlPJA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000755", + "electron-to-chromium": "1.3.27" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000755", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000755.tgz", + "integrity": "sha1-nOX24GvXXsggmr6IU8O+7wIkjWU=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "electron-to-chromium": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", + "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.10.0.tgz", + "integrity": "sha512-MMVl8P/dYUFZEvolL8PYt7qc5LNdS2lwheq9BYa5Y07FblhcZqFyaUqlS8TW5QITGex21tV4Lk0a3fK8lsJIkA==", + "dev": true, + "requires": { + "ajv": "5.3.0", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.0.0", + "eslint-scope": "3.7.1", + "espree": "3.5.1", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "espree": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "dev": true, + "requires": { + "acorn": "5.1.2", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estree-walker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", + "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "external-editor": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", + "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", + "dev": true, + "requires": { + "iconv-lite": "0.4.19", + "jschardet": "1.6.0", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.0.5", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", "dev": true }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "jschardet": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", + "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==", + "dev": true + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } }, - "estree-walker": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", - "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", "dev": true }, "minimatch": { @@ -41,6 +1819,392 @@ "brace-expansion": "1.1.8" } }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, "rollup": { "version": "0.50.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.50.0.tgz", @@ -56,6 +2220,46 @@ "rollup-pluginutils": "1.5.2" } }, + "rollup-plugin-eslint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-eslint/-/rollup-plugin-eslint-4.0.0.tgz", + "integrity": "sha1-n7l8DvW8DXpU7vHygXDxl03JOOw=", + "dev": true, + "requires": { + "eslint": "4.10.0", + "rollup-pluginutils": "2.0.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz", + "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=", + "dev": true + }, + "rollup-pluginutils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz", + "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=", + "dev": true, + "requires": { + "estree-walker": "0.3.1", + "micromatch": "2.3.11" + } + } + } + }, + "rollup-plugin-node-resolve": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz", + "integrity": "sha1-i4l8TDAw1QASd7BRSyXSygloPuA=", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "builtin-modules": "1.1.1", + "is-module": "1.0.0", + "resolve": "1.5.0" + } + }, "rollup-pluginutils": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", @@ -65,6 +2269,297 @@ "estree-walker": "0.2.1", "minimatch": "3.0.4" } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.3.0", + "ajv-keywords": "2.1.0", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } } diff --git a/package.json b/package.json index 879ca80..ade9457 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,13 @@ }, "homepage": "https://github.com/frappe/charts#readme", "devDependencies": { + "babel-core": "^6.26.0", + "babel-plugin-external-helpers": "^6.22.0", + "babel-preset-env": "^1.6.1", + "babel-preset-latest": "^6.24.1", "rollup": "^0.50.0", - "rollup-plugin-babel": "^3.0.2" + "rollup-plugin-babel": "^3.0.2", + "rollup-plugin-eslint": "^4.0.0", + "rollup-plugin-node-resolve": "^3.0.0" } } diff --git a/rollup.config.js b/rollup.config.js index b1e3ca1..43d4620 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,12 +1,19 @@ // Rollup plugins +import resolve from 'rollup-plugin-node-resolve'; import babel from 'rollup-plugin-babel'; +import eslint from 'rollup-plugin-eslint'; export default { - entry: 'src/charts.js', - dest: 'dist/frappe-charts.min.js', - format: 'iife', - sourceMap: 'inline', + input: 'src/charts.js', + output: { + file: 'dist/frappe-charts.min.js', + format: 'iife', + }, + name: 'Chart', + sourcemap: 'inline', plugins: [ + resolve(), + eslint(), babel({ exclude: 'node_modules/**', }), diff --git a/src/charts.js b/src/charts.js index 9ecc827..6e02969 100644 --- a/src/charts.js +++ b/src/charts.js @@ -1,6 +1,7 @@ -let frappe = {chart:{}, chart_types:['line', 'bar', 'percentage', 'heatmap']}; +import $ from './dom'; +import { float_2, arrays_equal } from './utils'; -frappe.chart.FrappeChart = class { +export default class Chart { constructor({ parent = "", height = 240, @@ -16,17 +17,17 @@ frappe.chart.FrappeChart = class { type = '' }) { - if(Object.getPrototypeOf(this) === frappe.chart.FrappeChart.prototype) { + if(Object.getPrototypeOf(this) === Chart.prototype) { if(type === 'line') { - return new frappe.chart.LineChart(arguments[0]); + return new LineChart(arguments[0]); } else if(type === 'bar') { - return new frappe.chart.BarChart(arguments[0]); + return new BarChart(arguments[0]); } else if(type === 'percentage') { - return new frappe.chart.PercentageChart(arguments[0]); + return new PercentageChart(arguments[0]); } else if(type === 'heatmap') { - return new frappe.chart.HeatMap(arguments[0]); + return new HeatMap(arguments[0]); } else { - return new frappe.chart.LineChart(arguments[0]); + return new LineChart(arguments[0]); } } @@ -47,18 +48,13 @@ frappe.chart.FrappeChart = class { this.current_index = 0; } - $$.createSVG('svg', { - className: 'chart', - inside: parent, - width: 1000, - height: height - }); + this.chart_types = ['line', 'bar', 'percentage', 'heatmap']; this.set_margins(height); } get_different_chart(type) { - if(!frappe.chart_types.includes(type)) { + if(!this.chart_types.includes(type)) { console.error(`'${type}' is not a valid chart type.`); } if(type === this.type) return; @@ -69,16 +65,16 @@ frappe.chart.FrappeChart = class { line: ['bar', 'percentage'], percentage: ['bar', 'line'], heatmap: [] - } + }; if(!compatible_types[this.type].includes(type)) { console.error(`'${this.type}' chart cannot be converted to a '${type}' chart.`); } // Okay, this is anticlimactic - // this function will need to be 'change_chart_type(type)' + // this function will need to actually be 'change_chart_type(type)' // that will update only the required elements, but for now ... - return new frappe.chart.FrappeChart({ + return new Chart({ parent: this.raw_chart_args.parent, data: this.raw_chart_args.data, type: type, @@ -141,7 +137,7 @@ frappe.chart.FrappeChart = class { setup_base_values() {} setup_container() { - this.container = $$.create('div', { + this.container = $.create('div', { className: 'chart-container', innerHTML: `
${this.title}
${this.subtitle}
@@ -161,14 +157,14 @@ frappe.chart.FrappeChart = class { } make_chart_area() { - this.svg = $$.createSVG('svg', { + this.svg = $.createSVG('svg', { className: 'chart', inside: this.chart_wrapper, width: this.base_width, height: this.base_height }); - this.svg_defs = $$.createSVG('defs', { + this.svg_defs = $.createSVG('defs', { inside: this.svg, }); @@ -176,7 +172,7 @@ frappe.chart.FrappeChart = class { } make_draw_area() { - this.draw_area = $$.createSVG("g", { + this.draw_area = $.createSVG("g", { className: this.type + '-chart', inside: this.svg, transform: `translate(${this.translate_x}, ${this.translate_y})` @@ -186,7 +182,7 @@ frappe.chart.FrappeChart = class { setup_components() { } make_tooltip() { - this.tip = new frappe.chart.SvgTip({ + this.tip = new SvgTip({ parent: this.chart_wrapper, }); this.bind_tooltip(); @@ -196,7 +192,7 @@ frappe.chart.FrappeChart = class { show_summary() {} show_custom_summary() { this.summary.map(d => { - let stats = $$.create('div', { + let stats = $.create('div', { className: 'stats', innerHTML: `${d.title}: ${d.value}` }); @@ -211,7 +207,7 @@ frappe.chart.FrappeChart = class { this.bind_overlay(); document.addEventListener('keydown', (e) => { - if($$.isElementInViewport(this.chart_wrapper)) { + if($.isElementInViewport(this.chart_wrapper)) { e = e || window.event; if (e.keyCode == '37') { @@ -258,7 +254,7 @@ frappe.chart.FrappeChart = class { if(index >= this.x.length) index = this.x.length - 1; if(index === this.current_index) return; this.current_index = index; - $$.fire(this.parent, "data-select", this.get_data_point()); + $.fire(this.parent, "data-select", this.get_data_point()); } // Helpers @@ -270,7 +266,7 @@ frappe.chart.FrappeChart = class { setup_utils() { } } -frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { +class AxisChart extends Chart { constructor(args) { super(args); @@ -282,7 +278,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.get_x_tooltip = this.format_lambdas.x_tooltip; this.colors = ['green', 'blue', 'violet', 'red', 'orange', - 'yellow', 'light-blue', 'light-green', 'purple', 'magenta']; + 'yellow', 'light-blue', 'light-green', 'purple', 'magenta']; this.zero_line = this.height; } @@ -302,7 +298,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.x_old_axis_positions = this.x_axis_positions.slice(); } this.x_axis_positions = this.x.map((d, i) => - $$.float_2(this.x_offset + i * this.avg_unit_width)); + float_2(this.x_offset + i * this.avg_unit_width)); if(!this.x_old_axis_positions) { this.x_old_axis_positions = this.x_axis_positions.slice(); @@ -350,20 +346,20 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { } setup_marker_components() { - this.y_axis_group = $$.createSVG('g', {className: 'y axis', inside: this.draw_area}); - this.x_axis_group = $$.createSVG('g', {className: 'x axis', inside: this.draw_area}); - this.specific_y_group = $$.createSVG('g', {className: 'specific axis', inside: this.draw_area}); + this.y_axis_group = $.createSVG('g', {className: 'y axis', inside: this.draw_area}); + this.x_axis_group = $.createSVG('g', {className: 'x axis', inside: this.draw_area}); + this.specific_y_group = $.createSVG('g', {className: 'specific axis', inside: this.draw_area}); } setup_aggregation_components() { - this.sum_group = $$.createSVG('g', {className: 'data-points', inside: this.draw_area}); - this.average_group = $$.createSVG('g', {className: 'chart-area', inside: this.draw_area}); + this.sum_group = $.createSVG('g', {className: 'data-points', inside: this.draw_area}); + this.average_group = $.createSVG('g', {className: 'chart-area', inside: this.draw_area}); } setup_graph_components() { this.svg_units_groups = []; this.y.map((d, i) => { - this.svg_units_groups[i] = $$.createSVG('g', { + this.svg_units_groups[i] = $.createSVG('g', { className: 'data-points data-points-' + i, inside: this.draw_area }); @@ -546,7 +542,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { bind_tooltip() { // TODO: could be in tooltip itself, as it is a given functionality for its parent this.chart_wrapper.addEventListener('mousemove', (e) => { - let offset = $$.offset(this.chart_wrapper); + let offset = $.offset(this.chart_wrapper); let relX = e.pageX - offset.left - this.translate_x; let relY = e.pageY - offset.top - this.translate_y; @@ -573,7 +569,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { title: set.title, value: set.formatted ? set.formatted[i] : set.values[i], color: set.color || this.colors[j], - } + }; }); // TODO: upside-down tooltips for negative values? @@ -603,7 +599,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.make_new_units_for_dataset( this.x_axis_positions, - this.y_sums.map( val => $$.float_2(this.zero_line - val * this.multiplier)), + this.y_sums.map( val => float_2(this.zero_line - val * this.multiplier)), 'light-grey', 0, 1, @@ -628,7 +624,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.old_specific_values = this.specific_values.slice(); this.y.map((d, i) => { let sum = 0; - d.values.map(e => {sum+=e}); + d.values.map(e => {sum+=e;}); let average = sum/d.values.length; this.specific_values.push({ @@ -639,8 +635,6 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { }); }); - console.log(this.specific_values); - this.update_values(); } @@ -652,14 +646,10 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { if(d.auto) indices_to_remove.unshift(i); }); - console.log(indices_to_remove); - indices_to_remove.map(index => { this.specific_values.splice(index, 1); }); - console.log(this.specific_values); - this.update_values(); } @@ -685,16 +675,16 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.setup_y(); // Animate only if positions have changed - if(!$$.arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) { + if(!arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) { this.make_x_axis(true); setTimeout(() => { if(!this.updating) this.make_x_axis(); - }, 300) + }, 300); } - if(!$$.arrays_equal(this.y_old_axis_values, this.y_axis_values) || + if(!arrays_equal(this.y_old_axis_values, this.y_axis_values) || (this.old_specific_values && - !$$.arrays_equal(this.old_specific_values, this.specific_values))) { + !arrays_equal(this.old_specific_values, this.specific_values))) { this.make_y_axis(true); setTimeout(() => { @@ -702,7 +692,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { this.make_y_axis(); this.make_y_specifics(); } - }, 300) + }, 300); } // Change in data, so calculate dependencies @@ -729,7 +719,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { if(this.x.length < 3) return; let new_y = this.y.map(data_set => { return {values:data_set.values}; }); - new_y.map((d, i) => { d.values.splice(index, 1); }); + new_y.map((d) => { d.values.splice(index, 1); }); let new_x = this.x.slice(); new_x.splice(index, 1); @@ -737,7 +727,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { } run_animation() { - let anim_svg = $$.runSVGAnimation(this.svg, this.elements_to_animate); + let anim_svg = $.runSVGAnimation(this.svg, this.elements_to_animate); if(this.svg.parentNode == this.chart_wrapper) { this.chart_wrapper.removeChild(this.svg); @@ -861,7 +851,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { const last_line_pos = old_pos[old_pos.length - 1]; - let add_and_animate_line = (value, old_pos, new_pos, i) => { + let add_and_animate_line = (value, old_pos, new_pos) => { const x_line = this.make_x_line( height, text_start_at, @@ -880,7 +870,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { "translate", {transform: `${ old_pos }, 0`} ]); - } + }; this.x_axis_group.textContent = ''; @@ -922,7 +912,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { make_anim_y_specifics() { this.specific_y_group.textContent = ''; - this.specific_values.map((d, i) => { + this.specific_values.map((d) => { this.add_and_animate_y_line( d.title, this.old_zero_line - d.value * this.old_multiplier, @@ -979,14 +969,14 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { point = point.slice(0, allowed_letters-3) + " ..."; } - let line = $$.createSVG('line', { + let line = $.createSVG('line', { x1: 0, x2: 0, y1: 0, y2: height }); - let text = $$.createSVG('text', { + let text = $.createSVG('text', { className: label_class, x: 0, y: text_start_at, @@ -994,7 +984,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { innerHTML: point }); - let x_level = $$.createSVG('g', { + let x_level = $.createSVG('g', { className: `tick ${axis_line_class}`, transform: `translate(${ x_pos }, 0)` }); @@ -1006,7 +996,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { } make_y_line(start_at, width, text_end_at, point, label_class, axis_line_class, y_pos, darker=false, line_type="") { - let line = $$.createSVG('line', { + let line = $.createSVG('line', { className: line_type === "dashed" ? "dashed": "", x1: start_at, x2: width, @@ -1014,7 +1004,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { y2: 0 }); - let text = $$.createSVG('text', { + let text = $.createSVG('text', { className: label_class, x: text_end_at, y: 0, @@ -1022,7 +1012,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { innerHTML: point+"" }); - let y_level = $$.createSVG('g', { + let y_level = $.createSVG('g', { className: `tick ${axis_line_class}`, transform: `translate(0, ${y_pos})` }); @@ -1073,7 +1063,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { // TODO: Fractions - let max_bound, min_bound, pos_no_of_parts, neg_no_of_parts, part_size; + let max_bound, min_bound, pos_no_of_parts, neg_no_of_parts, part_size; // eslint-disable-line no-unused-vars // Critical values let max_val = parseInt(Math.max(...array)); @@ -1095,7 +1085,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { bound2 = no_of_parts_2 * interval_size; return [bound1, bound2, no_of_parts_1, no_of_parts_2, interval_size]; - } + }; const abs_min_val = min_val * -1; if(abs_min_val <= max_val) { @@ -1191,7 +1181,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { calc_y_dependencies() { this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999); this.y.map(d => { - d.y_tops = d.values.map( val => $$.float_2(this.zero_line - val * this.multiplier)); + d.y_tops = d.values.map( val => float_2(this.zero_line - val * this.multiplier)); d.y_tops.map( (y_top, i) => { if(y_top < this.y_min_tops[i]) { this.y_min_tops[i] = y_top; @@ -1235,7 +1225,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { let [height, y] = this.get_bar_height_and_y_attr(y_top); - return $$.createSVG('rect', { + return $.createSVG('rect', { className: `bar mini fill ${color}`, x: current_x, y: y, @@ -1245,7 +1235,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { }, 'dot': (x, y, args, color) => { - return $$.createSVG('circle', { + return $.createSVG('circle', { className: `fill ${color}`, cx: x, cy: y, @@ -1273,7 +1263,7 @@ frappe.chart.AxisChart = class AxisChart extends frappe.chart.FrappeChart { } } -frappe.chart.BarChart = class BarChart extends frappe.chart.AxisChart { +class BarChart extends AxisChart { constructor(args) { super(args); @@ -1342,10 +1332,10 @@ frappe.chart.BarChart = class BarChart extends frappe.chart.AxisChart { } } -frappe.chart.LineChart = class LineChart extends frappe.chart.AxisChart { +class LineChart extends AxisChart { constructor(args) { super(args); - if(Object.getPrototypeOf(this) !== frappe.chart.LineChart.prototype) { + if(Object.getPrototypeOf(this) !== LineChart.prototype) { return; } @@ -1365,7 +1355,7 @@ frappe.chart.LineChart = class LineChart extends frappe.chart.AxisChart { setup_path_groups() { this.paths_groups = []; this.y.map((d, i) => { - this.paths_groups[i] = $$.createSVG('g', { + this.paths_groups[i] = $.createSVG('g', { className: 'path-group path-group-' + i, inside: this.draw_area }); @@ -1387,55 +1377,55 @@ frappe.chart.LineChart = class LineChart extends frappe.chart.AxisChart { } make_path(d, i, x_positions, y_positions, color) { - // let points_list = y_positions.map((y, i) => (x_positions[i] + ',' + y)); - // let points_str = points_list.join("L"); - - // this.paths_groups[i].textContent = ''; - - // d.path = $$.createSVG('path', { - // inside: this.paths_groups[i], - // className: `stroke ${color}`, - // d: "M"+points_str - // }); - - // if(this.region_fill) { - // let gradient_id ='path-fill-gradient' + '-' + color; - - // this.gradient_def = $$.createSVG('linearGradient', { - // inside: this.svg_defs, - // id: gradient_id, - // x1: 0, - // x2: 0, - // y1: 0, - // y2: 1 - // }); - - // function set_gradient_stop(grad_elem, offset, color, opacity) { - // $$.createSVG('stop', { - // 'className': 'stop-color ' + color, - // 'inside': grad_elem, - // 'offset': offset, - // 'stop-opacity': opacity - // }); - // } - - // set_gradient_stop(this.gradient_def, "0%", color, 0.4); - // set_gradient_stop(this.gradient_def, "50%", color, 0.2); - // set_gradient_stop(this.gradient_def, "100%", color, 0); - - // d.region_path = $$.createSVG('path', { - // inside: this.paths_groups[i], - // className: `region-fill`, - // d: "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`, - // }); - - // d.region_path.style.stroke = "none"; - // d.region_path.style.fill = `url(#${gradient_id})`; - // } + let points_list = y_positions.map((y, i) => (x_positions[i] + ',' + y)); + let points_str = points_list.join("L"); + + this.paths_groups[i].textContent = ''; + + d.path = $.createSVG('path', { + inside: this.paths_groups[i], + className: `stroke ${color}`, + d: "M"+points_str + }); + + if(this.region_fill) { + let gradient_id ='path-fill-gradient' + '-' + color; + + this.gradient_def = $.createSVG('linearGradient', { + inside: this.svg_defs, + id: gradient_id, + x1: 0, + x2: 0, + y1: 0, + y2: 1 + }); + + let set_gradient_stop = (grad_elem, offset, color, opacity) => { + $.createSVG('stop', { + 'className': 'stop-color ' + color, + 'inside': grad_elem, + 'offset': offset, + 'stop-opacity': opacity + }); + }; + + set_gradient_stop(this.gradient_def, "0%", color, 0.4); + set_gradient_stop(this.gradient_def, "50%", color, 0.2); + set_gradient_stop(this.gradient_def, "100%", color, 0); + + d.region_path = $.createSVG('path', { + inside: this.paths_groups[i], + className: `region-fill`, + d: "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`, + }); + + d.region_path.style.stroke = "none"; + d.region_path.style.fill = `url(#${gradient_id})`; + } } } -frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.FrappeChart { +class PercentageChart extends Chart { constructor(args) { super(args); this.type = 'percentage'; @@ -1467,21 +1457,21 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe } make_draw_area() { - this.chart_div = $$.create('div', { + this.chart_div = $.create('div', { className: 'div', inside: this.chart_wrapper, width: this.base_width, height: this.base_height }); - this.chart = $$.create('div', { + this.chart = $.create('div', { className: 'progress-chart', inside: this.chart_div }); } setup_components() { - this.percentage_bar = $$.create('div', { + this.percentage_bar = $.create('div', { className: 'progress', inside: this.chart }); @@ -1506,7 +1496,7 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe let others = all_totals.slice(this.max_slices-1); let sum_of_others = 0; - others.map(d => {sum_of_others += d[0]}); + others.map(d => {sum_of_others += d[0];}); totals.push([sum_of_others, 'Rest']); @@ -1528,7 +1518,7 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe this.grand_total = this.slice_totals.reduce((a, b) => a + b, 0); this.slices = []; this.slice_totals.map((total, i) => { - let slice = $$.create('div', { + let slice = $.create('div', { className: `progress-bar background ${this.colors[i]}`, style: `width: ${total*100/this.grand_total}%`, inside: this.percentage_bar @@ -1540,7 +1530,7 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe bind_tooltip() { this.slices.map((slice, i) => { slice.addEventListener('mouseenter', () => { - let g_off = $$.offset(this.chart_wrapper), p_off = $$.offset(slice); + let g_off = $.offset(this.chart_wrapper), p_off = $.offset(slice); let x = p_off.left - g_off.left + slice.offsetWidth/2; let y = p_off.top - g_off.top - 6; @@ -1559,7 +1549,7 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe ? this.formatted_labels : this.labels; this.legend_totals.map((d, i) => { if(d) { - let stats = $$.create('div', { + let stats = $.create('div', { className: 'stats', inside: this.stats_wrapper }); @@ -1572,7 +1562,7 @@ frappe.chart.PercentageChart = class PercentageChart extends frappe.chart.Frappe } } -frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { +class HeatMap extends Chart { constructor({ start = '', domain = '', @@ -1627,11 +1617,11 @@ frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { } setup_components() { - this.domain_label_group = $$.createSVG("g", { + this.domain_label_group = $.createSVG("g", { className: "domain-label-group chart-label", inside: this.draw_area }); - this.data_groups = $$.createSVG("g", { + this.data_groups = $.createSVG("g", { className: "data-groups", inside: this.draw_area, transform: `translate(0, 20)` @@ -1686,7 +1676,7 @@ frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { let month_change = 0; let week_col_change = 0; - let data_group = $$.createSVG("g", { + let data_group = $.createSVG("g", { className: "data-group", inside: this.data_groups }); @@ -1709,7 +1699,7 @@ frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { let x = 13 + (index + week_col_change) * 12; - $$.createSVG("rect", { + $.createSVG("rect", { className: 'day', inside: data_group, x: x, @@ -1761,7 +1751,7 @@ frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { this.month_start_points.map((start, i) => { let month_name = this.month_names[this.months[i]].substring(0, 3); - $$.createSVG('text', { + $.createSVG('text', { className: 'y-value-text', inside: this.domain_label_group, x: start + 12, @@ -1873,7 +1863,7 @@ frappe.chart.HeatMap = class HeatMap extends frappe.chart.FrappeChart { get_month_name() {} } -frappe.chart.SvgTip = class { +class SvgTip { constructor({ parent = null }) { @@ -1903,7 +1893,7 @@ frappe.chart.SvgTip = class { } make_tooltip() { - this.container = $$.create('div', { + this.container = $.create('div', { inside: this.parent, className: 'graph-svg-tip comparison', innerHTML: ` @@ -1931,7 +1921,7 @@ frappe.chart.SvgTip = class { this.data_point_list.innerHTML = ''; this.list_values.map((set) => { - let li = $$.create('li', { + let li = $.create('li', { className: `border-top ${set.color || 'black'}`, innerHTML: `${set.value ? set.value : '' } ${set.title ? set.title : '' }` @@ -1982,259 +1972,3 @@ frappe.chart.SvgTip = class { this.container.style.opacity = '1'; } } - -// Helpers -frappe.chart.utils = {}; -$$.float_2 = d => parseFloat(d.toFixed(2)); -function $$(expr, con) { - return typeof expr === "string"? (con || document).querySelector(expr) : expr || null; -} - -$$.arrays_equal = (arr1, arr2) => { - if(arr1.length !== arr2.length) return false; - let are_equal = true; - arr1.map((d, i) => { - if(arr2[i] !== d) are_equal = false; - }); - return are_equal; -} - -$$.shuffle = (array) => { - // https://stackoverflow.com/a/2450976/6495043 - // Awesomeness: https://bost.ocks.org/mike/shuffle/ - - var currentIndex = array.length, temporaryValue, randomIndex; - - // While there remain elements to shuffle... - while (0 !== currentIndex) { - - // Pick a remaining element... - randomIndex = Math.floor(Math.random() * currentIndex); - currentIndex -= 1; - - // And swap it with the current element. - temporaryValue = array[currentIndex]; - array[currentIndex] = array[randomIndex]; - array[randomIndex] = temporaryValue; - } - - return array; - -} - -// $$.findNodeIndex = (node) => -// { -// var i = 0; -// while (node = node.previousSibling) { -// if (node.nodeType === 1) { ++i; } -// } -// return i; -// } - -$$.create = function(tag, o) { - var element = document.createElement(tag); - - for (var i in o) { - var val = o[i]; - - if (i === "inside") { - $$(val).appendChild(element); - } - else if (i === "around") { - var ref = $$(val); - ref.parentNode.insertBefore(element, ref); - element.appendChild(ref); - } - else if (i in element) { - element[i] = val; - } - else { - element.setAttribute(i, val); - } - } - - return element; -}; - -$$.createSVG = function(tag, o) { - var element = document.createElementNS("http://www.w3.org/2000/svg", tag); - - for (var i in o) { - var val = o[i]; - - if (i === "inside") { - $$(val).appendChild(element); - } - else if (i === "around") { - var ref = $$(val); - ref.parentNode.insertBefore(element, ref); - element.appendChild(ref); - } - else { - if(i === "className") { i = "class"; } - if(i === "innerHTML") { - element['textContent'] = val; - } else { - element.setAttribute(i, val); - } - } - } - - return element; -}; - -$$.runSVGAnimation = (svg_container, elements) => { - // let parent = elements[0][0]['unit'].parentNode; - - let new_elements = []; - let anim_elements = []; - - elements.map(element => { - let obj = element[0]; - let parent = obj.unit.parentNode; - // let index = $$.findNodeIndex(obj.unit); - - let anim_element, new_element; - - element[0] = obj.unit; - - [anim_element, new_element] = $$.animateSVG(...element); - - new_elements.push(new_element); - anim_elements.push([anim_element, parent]); - - parent.replaceChild(anim_element, obj.unit); - - if(obj.array) { - obj.array[obj.index] = new_element; - } else { - obj.object[obj.key] = new_element; - } - }); - - let anim_svg = svg_container.cloneNode(true); - - anim_elements.map((anim_element, i) => { - anim_element[1].replaceChild(new_elements[i], anim_element[0]); - elements[i][0] = new_elements[i]; - }); - - return anim_svg; -} - -// $$.animateMotion = (element, props, dur, easing_type="linear") - -$$.animateSVG = (element, props, dur, easing_type="linear", type=undefined, old_values={}) => { - let easing = { - ease: "0.25 0.1 0.25 1", - linear: "0 0 1 1", - // easein: "0.42 0 1 1", - easein: "0.1 0.8 0.2 1", - easeout: "0 0 0.58 1", - easeinout: "0.42 0 0.58 1" - } - - let anim_element = element.cloneNode(true); - let new_element = element.cloneNode(true); - - for(var attributeName in props) { - let animate_element; - if(attributeName === 'transform') { - animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform"); - } else { - animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate"); - } - let current_value = old_values[attributeName] || element.getAttribute(attributeName); - let value = props[attributeName]; - - let anim_attr = { - attributeName: attributeName, - from: current_value, - to: value, - begin: "0s", - dur: dur/1000 + "s", - values: current_value + ";" + value, - keySplines: easing[easing_type], - keyTimes: "0;1", - calcMode: "spline", - fill: 'freeze' - } - - if(type) { - anim_attr["type"] = type; - } - - for (var i in anim_attr) { - animate_element.setAttribute(i, anim_attr[i]); - } - - anim_element.appendChild(animate_element); - - if(type) { - new_element.setAttribute(attributeName, `translate(${value})`); - } else { - new_element.setAttribute(attributeName, value); - } - } - - return [anim_element, new_element]; -} - -$$.offset = (element) => { - let rect = element.getBoundingClientRect(); - return { - // https://stackoverflow.com/a/7436602/6495043 - // rect.top varies with scroll, so we add whatever has been - // scrolled to it to get absolute distance from actual page top - top: rect.top + (document.documentElement.scrollTop || document.body.scrollTop), - left: rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft) - } -}; - -$$.isElementInViewport = (el) => { - // Although straightforward: https://stackoverflow.com/a/7557433/6495043 - var rect = el.getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ - rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ - ); -} - -$$.bind = function(element, o) { - if (element) { - for (var event in o) { - var callback = o[event]; - - event.split(/\s+/).forEach(function (event) { - element.addEventListener(event, callback); - }); - } - } -}; - -$$.unbind = function(element, o) { - if (element) { - for (var event in o) { - var callback = o[event]; - - event.split(/\s+/).forEach(function(event) { - element.removeEventListener(event, callback); - }); - } - } -}; - -$$.fire = function(target, type, properties) { - var evt = document.createEvent("HTMLEvents"); - - evt.initEvent(type, true, true ); - - for (var j in properties) { - evt[j] = properties[j]; - } - - return target.dispatchEvent(evt); -}; diff --git a/src/dom.js b/src/dom.js new file mode 100644 index 0000000..997a4ab --- /dev/null +++ b/src/dom.js @@ -0,0 +1,219 @@ +export default function $(expr, con) { + return typeof expr === "string"? (con || document).querySelector(expr) : expr || null; +} + +$.findNodeIndex = (node) => +{ + var i = 0; + while (node.previousSibling) { + node = node.previousSibling; + i++; + } + return i; +}; + +$.create = (tag, o) => { + var element = document.createElement(tag); + + for (var i in o) { + var val = o[i]; + + if (i === "inside") { + $(val).appendChild(element); + } + else if (i === "around") { + var ref = $(val); + ref.parentNode.insertBefore(element, ref); + element.appendChild(ref); + } + else if (i in element) { + element[i] = val; + } + else { + element.setAttribute(i, val); + } + } + + return element; +}; + +$.createSVG = (tag, o) => { + var element = document.createElementNS("http://www.w3.org/2000/svg", tag); + + for (var i in o) { + var val = o[i]; + + if (i === "inside") { + $(val).appendChild(element); + } + else if (i === "around") { + var ref = $(val); + ref.parentNode.insertBefore(element, ref); + element.appendChild(ref); + } + else { + if(i === "className") { i = "class"; } + if(i === "innerHTML") { + element['textContent'] = val; + } else { + element.setAttribute(i, val); + } + } + } + + return element; +}; + +$.runSVGAnimation = (svg_container, elements) => { + // let parent = elements[0][0]['unit'].parentNode; + + let new_elements = []; + let anim_elements = []; + + elements.map(element => { + let obj = element[0]; + let parent = obj.unit.parentNode; + // let index = let findNodeIndex(obj.unit); + + let anim_element, new_element; + + element[0] = obj.unit; + + [anim_element, new_element] = $.animateSVG(...element); + + new_elements.push(new_element); + anim_elements.push([anim_element, parent]); + + parent.replaceChild(anim_element, obj.unit); + + if(obj.array) { + obj.array[obj.index] = new_element; + } else { + obj.object[obj.key] = new_element; + } + }); + + let anim_svg = svg_container.cloneNode(true); + + anim_elements.map((anim_element, i) => { + anim_element[1].replaceChild(new_elements[i], anim_element[0]); + elements[i][0] = new_elements[i]; + }); + + return anim_svg; +}; + +$.animateSVG = (element, props, dur, easing_type="linear", type=undefined, old_values={}) => { + let easing = { + ease: "0.25 0.1 0.25 1", + linear: "0 0 1 1", + // easein: "0.42 0 1 1", + easein: "0.1 0.8 0.2 1", + easeout: "0 0 0.58 1", + easeinout: "0.42 0 0.58 1" + }; + + let anim_element = element.cloneNode(true); + let new_element = element.cloneNode(true); + + for(var attributeName in props) { + let animate_element; + if(attributeName === 'transform') { + animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform"); + } else { + animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate"); + } + let current_value = old_values[attributeName] || element.getAttribute(attributeName); + let value = props[attributeName]; + + let anim_attr = { + attributeName: attributeName, + from: current_value, + to: value, + begin: "0s", + dur: dur/1000 + "s", + values: current_value + ";" + value, + keySplines: easing[easing_type], + keyTimes: "0;1", + calcMode: "spline", + fill: 'freeze' + }; + + if(type) { + anim_attr["type"] = type; + } + + for (var i in anim_attr) { + animate_element.setAttribute(i, anim_attr[i]); + } + + anim_element.appendChild(animate_element); + + if(type) { + new_element.setAttribute(attributeName, `translate(${value})`); + } else { + new_element.setAttribute(attributeName, value); + } + } + + return [anim_element, new_element]; +}; + +$.offset = (element) => { + let rect = element.getBoundingClientRect(); + return { + // https://stackoverflow.com/a/7436602/6495043 + // rect.top varies with scroll, so we add whatever has been + // scrolled to it to get absolute distance from actual page top + top: rect.top + (document.documentElement.scrollTop || document.body.scrollTop), + left: rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft) + }; +}; + +$.isElementInViewport = (el) => { + // Although straightforward: https://stackoverflow.com/a/7557433/6495043 + var rect = el.getBoundingClientRect(); + + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ + rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ + ); +}; + +$.bind = (element, o) => { + if (element) { + for (var event in o) { + var callback = o[event]; + + event.split(/\s+/).forEach(function (event) { + element.addEventListener(event, callback); + }); + } + } +}; + +$.unbind = (element, o) => { + if (element) { + for (var event in o) { + var callback = o[event]; + + event.split(/\s+/).forEach(function(event) { + element.removeEventListener(event, callback); + }); + } + } +}; + +$.fire = (target, type, properties) => { + var evt = document.createEvent("HTMLEvents"); + + evt.initEvent(type, true, true ); + + for (var j in properties) { + evt[j] = properties[j]; + } + + return target.dispatchEvent(evt); +}; diff --git a/src/scripts/test.js b/src/scripts/test.js new file mode 100644 index 0000000..e69de29 diff --git a/src/charts.css b/src/styles/charts.css similarity index 100% rename from src/charts.css rename to src/styles/charts.css diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..e27acbb --- /dev/null +++ b/src/utils.js @@ -0,0 +1,34 @@ +export function float_2(d) { + return parseFloat(d.toFixed(2)); +} + +export function arrays_equal(arr1, arr2) { + if(arr1.length !== arr2.length) return false; + let are_equal = true; + arr1.map((d, i) => { + if(arr2[i] !== d) are_equal = false; + }); + return are_equal; +} + +export function shuffle(array) { + // https://stackoverflow.com/a/2450976/6495043 + // Awesomeness: https://bost.ocks.org/mike/shuffle/ + + var currentIndex = array.length, temporaryValue, randomIndex; + + // While there remain elements to shuffle... + while (0 !== currentIndex) { + + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + + return array; +}