metamaps--metamaps/app/assets/javascripts/particles-bg.js
2017-10-15 16:09:10 -04:00

62 lines
121 KiB
JavaScript

/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
eval("'use strict';__webpack_require__(1);\nvar _particles = __webpack_require__(2);var _particles2 = _interopRequireDefault(_particles);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}\nvar particles = window.particlesJS('particles-bg', _particles2.default);\ndocument.addEventListener(\"DOMContentLoaded\", function (event) {\n window.dispatchEvent(new Event('resize'));\n});//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMC5qcyIsInNvdXJjZXMiOlsiZnJvbnRlbmQvc3JjL2hvbWVwYWdlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAncGFydGljbGVzLmpzJ1xuaW1wb3J0IGNvbmZpZyBmcm9tICcuL2hvbWUvcGFydGljbGVzLmpzb24nXG52YXIgcGFydGljbGVzID0gd2luZG93LnBhcnRpY2xlc0pTKCdwYXJ0aWNsZXMtYmcnLCBjb25maWcpXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBmdW5jdGlvbihldmVudCkgeyBcbiAgd2luZG93LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdyZXNpemUnKSlcbn0pXG5cblxuXG4vKiogV0VCUEFDSyBGT09URVIgKipcbiAqKiBmcm9udGVuZC9zcmMvaG9tZXBhZ2UuanNcbiAqKi8iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==");
/***/ },
/* 1 */
/***/ function(module, exports) {
eval("/* -----------------------------------------------\n/* Author : Vincent Garreau - vincentgarreau.com\n/* MIT license: http://opensource.org/licenses/MIT\n/* Demo / Generator : vincentgarreau.com/particles.js\n/* GitHub : github.com/VincentGarreau/particles.js\n/* How to use? : Check the GitHub README\n/* v2.0.0\n/* ----------------------------------------------- */\n\nvar pJS = function(tag_id, params){\n\n var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');\n\n /* particles.js variables with default values */\n this.pJS = {\n canvas: {\n el: canvas_el,\n w: canvas_el.offsetWidth,\n h: canvas_el.offsetHeight\n },\n particles: {\n number: {\n value: 400,\n density: {\n enable: true,\n value_area: 800\n }\n },\n color: {\n value: '#fff'\n },\n shape: {\n type: 'circle',\n stroke: {\n width: 0,\n color: '#ff0000'\n },\n polygon: {\n nb_sides: 5\n },\n image: {\n src: '',\n width: 100,\n height: 100\n }\n },\n opacity: {\n value: 1,\n random: false,\n anim: {\n enable: false,\n speed: 2,\n opacity_min: 0,\n sync: false\n }\n },\n size: {\n value: 20,\n random: false,\n anim: {\n enable: false,\n speed: 20,\n size_min: 0,\n sync: false\n }\n },\n line_linked: {\n enable: true,\n distance: 100,\n color: '#fff',\n opacity: 1,\n width: 1\n },\n move: {\n enable: true,\n speed: 2,\n direction: 'none',\n random: false,\n straight: false,\n out_mode: 'out',\n bounce: false,\n attract: {\n enable: false,\n rotateX: 3000,\n rotateY: 3000\n }\n },\n array: []\n },\n interactivity: {\n detect_on: 'canvas',\n events: {\n onhover: {\n enable: true,\n mode: 'grab'\n },\n onclick: {\n enable: true,\n mode: 'push'\n },\n resize: true\n },\n modes: {\n grab:{\n distance: 100,\n line_linked:{\n opacity: 1\n }\n },\n bubble:{\n distance: 200,\n size: 80,\n duration: 0.4\n },\n repulse:{\n distance: 200,\n duration: 0.4\n },\n push:{\n particles_nb: 4\n },\n remove:{\n particles_nb: 2\n }\n },\n mouse:{}\n },\n retina_detect: false,\n fn: {\n interact: {},\n modes: {},\n vendors:{}\n },\n tmp: {}\n };\n\n var pJS = this.pJS;\n\n /* params settings */\n if(params){\n Object.deepExtend(pJS, params);\n }\n\n pJS.tmp.obj = {\n size_value: pJS.particles.size.value,\n size_anim_speed: pJS.particles.size.anim.speed,\n move_speed: pJS.particles.move.speed,\n line_linked_distance: pJS.particles.line_linked.distance,\n line_linked_width: pJS.particles.line_linked.width,\n mode_grab_distance: pJS.interactivity.modes.grab.distance,\n mode_bubble_distance: pJS.interactivity.modes.bubble.distance,\n mode_bubble_size: pJS.interactivity.modes.bubble.size,\n mode_repulse_distance: pJS.interactivity.modes.repulse.distance\n };\n\n\n pJS.fn.retinaInit = function(){\n\n if(pJS.retina_detect && window.devicePixelRatio > 1){\n pJS.canvas.pxratio = window.devicePixelRatio; \n pJS.tmp.retina = true;\n } \n else{\n pJS.canvas.pxratio = 1;\n pJS.tmp.retina = false;\n }\n\n pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;\n pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;\n\n pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;\n pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;\n pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;\n pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;\n pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;\n pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;\n pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;\n pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;\n pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;\n\n };\n\n\n\n /* ---------- pJS functions - canvas ------------ */\n\n pJS.fn.canvasInit = function(){\n pJS.canvas.ctx = pJS.canvas.el.getContext('2d');\n };\n\n pJS.fn.canvasSize = function(){\n\n pJS.canvas.el.width = pJS.canvas.w;\n pJS.canvas.el.height = pJS.canvas.h;\n\n if(pJS && pJS.interactivity.events.resize){\n\n window.addEventListener('resize', function(){\n\n pJS.canvas.w = pJS.canvas.el.offsetWidth;\n pJS.canvas.h = pJS.canvas.el.offsetHeight;\n\n /* resize canvas */\n if(pJS.tmp.retina){\n pJS.canvas.w *= pJS.canvas.pxratio;\n pJS.canvas.h *= pJS.canvas.pxratio;\n }\n\n pJS.canvas.el.width = pJS.canvas.w;\n pJS.canvas.el.height = pJS.canvas.h;\n\n /* repaint canvas on anim disabled */\n if(!pJS.particles.move.enable){\n pJS.fn.particlesEmpty();\n pJS.fn.particlesCreate();\n pJS.fn.particlesDraw();\n pJS.fn.vendors.densityAutoParticles();\n }\n\n /* density particles enabled */\n pJS.fn.vendors.densityAutoParticles();\n\n });\n\n }\n\n };\n\n\n pJS.fn.canvasPaint = function(){\n pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);\n };\n\n pJS.fn.canvasClear = function(){\n pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);\n };\n\n\n /* --------- pJS functions - particles ----------- */\n\n pJS.fn.particle = function(color, opacity, position){\n\n /* size */\n this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;\n if(pJS.particles.size.anim.enable){\n this.size_status = false;\n this.vs = pJS.particles.size.anim.speed / 100;\n if(!pJS.particles.size.anim.sync){\n this.vs = this.vs * Math.random();\n }\n }\n\n /* position */\n this.x = position ? position.x : Math.random() * pJS.canvas.w;\n this.y = position ? position.y : Math.random() * pJS.canvas.h;\n\n /* check position - into the canvas */\n if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;\n else if(this.x < this.radius*2) this.x = this.x + this.radius;\n if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;\n else if(this.y < this.radius*2) this.y = this.y + this.radius;\n\n /* check position - avoid overlap */\n if(pJS.particles.move.bounce){\n pJS.fn.vendors.checkOverlap(this, position);\n }\n\n /* color */\n this.color = {};\n if(typeof(color.value) == 'object'){\n\n if(color.value instanceof Array){\n var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];\n this.color.rgb = hexToRgb(color_selected);\n }else{\n if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){\n this.color.rgb = {\n r: color.value.r,\n g: color.value.g,\n b: color.value.b\n }\n }\n if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){\n this.color.hsl = {\n h: color.value.h,\n s: color.value.s,\n l: color.value.l\n }\n }\n }\n\n }\n else if(color.value == 'random'){\n this.color.rgb = {\n r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),\n g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),\n b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)\n }\n }\n else if(typeof(color.value) == 'string'){\n this.color = color;\n this.color.rgb = hexToRgb(this.color.value);\n }\n\n /* opacity */\n this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;\n if(pJS.particles.opacity.anim.enable){\n this.opacity_status = false;\n this.vo = pJS.particles.opacity.anim.speed / 100;\n if(!pJS.particles.opacity.anim.sync){\n this.vo = this.vo * Math.random();\n }\n }\n\n /* animation - velocity for speed */\n var velbase = {}\n switch(pJS.particles.move.direction){\n case 'top':\n velbase = { x:0, y:-1 };\n break;\n case 'top-right':\n velbase = { x:0.5, y:-0.5 };\n break;\n case 'right':\n velbase = { x:1, y:-0 };\n break;\n case 'bottom-right':\n velbase = { x:0.5, y:0.5 };\n break;\n case 'bottom':\n velbase = { x:0, y:1 };\n break;\n case 'bottom-left':\n velbase = { x:-0.5, y:1 };\n break;\n case 'left':\n velbase = { x:-1, y:0 };\n break;\n case 'top-left':\n velbase = { x:-0.5, y:-0.5 };\n break;\n default:\n velbase = { x:0, y:0 };\n break;\n }\n\n if(pJS.particles.move.straight){\n this.vx = velbase.x;\n this.vy = velbase.y;\n if(pJS.particles.move.random){\n this.vx = this.vx * (Math.random());\n this.vy = this.vy * (Math.random());\n }\n }else{\n this.vx = velbase.x + Math.random()-0.5;\n this.vy = velbase.y + Math.random()-0.5;\n }\n\n // var theta = 2.0 * Math.PI * Math.random();\n // this.vx = Math.cos(theta);\n // this.vy = Math.sin(theta);\n\n this.vx_i = this.vx;\n this.vy_i = this.vy;\n\n \n\n /* if shape is image */\n\n var shape_type = pJS.particles.shape.type;\n if(typeof(shape_type) == 'object'){\n if(shape_type instanceof Array){\n var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];\n this.shape = shape_selected;\n }\n }else{\n this.shape = shape_type;\n }\n\n if(this.shape == 'image'){\n var sh = pJS.particles.shape;\n this.img = {\n src: sh.image.src,\n ratio: sh.image.width / sh.image.height\n }\n if(!this.img.ratio) this.img.ratio = 1;\n if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){\n pJS.fn.vendors.createSvgImg(this);\n if(pJS.tmp.pushing){\n this.img.loaded = false;\n }\n }\n }\n\n \n\n };\n\n\n pJS.fn.particle.prototype.draw = function() {\n\n var p = this;\n\n if(p.radius_bubble != undefined){\n var radius = p.radius_bubble; \n }else{\n var radius = p.radius;\n }\n\n if(p.opacity_bubble != undefined){\n var opacity = p.opacity_bubble;\n }else{\n var opacity = p.opacity;\n }\n\n if(p.color.rgb){\n var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';\n }else{\n var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';\n }\n\n pJS.canvas.ctx.fillStyle = color_value;\n pJS.canvas.ctx.beginPath();\n\n switch(p.shape){\n\n case 'circle':\n pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);\n break;\n\n case 'edge':\n pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);\n break;\n\n case 'triangle':\n pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);\n break;\n\n case 'polygon':\n pJS.fn.vendors.drawShape(\n pJS.canvas.ctx,\n p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX\n p.y - radius / (2.66/3.5), // startY\n radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength\n pJS.particles.shape.polygon.nb_sides, // sideCountNumerator\n 1 // sideCountDenominator\n );\n break;\n\n case 'star':\n pJS.fn.vendors.drawShape(\n pJS.canvas.ctx,\n p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX\n p.y - radius / (2*2.66/3.5), // startY\n radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength\n pJS.particles.shape.polygon.nb_sides, // sideCountNumerator\n 2 // sideCountDenominator\n );\n break;\n\n case 'image':\n\n function draw(){\n pJS.canvas.ctx.drawImage(\n img_obj,\n p.x-radius,\n p.y-radius,\n radius*2,\n radius*2 / p.img.ratio\n );\n }\n\n if(pJS.tmp.img_type == 'svg'){\n var img_obj = p.img.obj;\n }else{\n var img_obj = pJS.tmp.img_obj;\n }\n\n if(img_obj){\n draw();\n }\n\n break;\n\n }\n\n pJS.canvas.ctx.closePath();\n\n if(pJS.particles.shape.stroke.width > 0){\n pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;\n pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;\n pJS.canvas.ctx.stroke();\n }\n \n pJS.canvas.ctx.fill();\n \n };\n\n\n pJS.fn.particlesCreate = function(){\n for(var i = 0; i < pJS.particles.number.value; i++) {\n pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));\n }\n };\n\n pJS.fn.particlesUpdate = function(){\n\n for(var i = 0; i < pJS.particles.array.length; i++){\n\n /* the particle */\n var p = pJS.particles.array[i];\n\n // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;\n // var f = -BANG_SIZE / d;\n // if ( d < BANG_SIZE ) {\n // var t = Math.atan2( dy, dx );\n // p.vx = f * Math.cos(t);\n // p.vy = f * Math.sin(t);\n // }\n\n /* move the particle */\n if(pJS.particles.move.enable){\n var ms = pJS.particles.move.speed/2;\n p.x += p.vx * ms;\n p.y += p.vy * ms;\n }\n\n /* change opacity status */\n if(pJS.particles.opacity.anim.enable) {\n if(p.opacity_status == true) {\n if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;\n p.opacity += p.vo;\n }else {\n if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;\n p.opacity -= p.vo;\n }\n if(p.opacity < 0) p.opacity = 0;\n }\n\n /* change size */\n if(pJS.particles.size.anim.enable){\n if(p.size_status == true){\n if(p.radius >= pJS.particles.size.value) p.size_status = false;\n p.radius += p.vs;\n }else{\n if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;\n p.radius -= p.vs;\n }\n if(p.radius < 0) p.radius = 0;\n }\n\n /* change particle position if it is out of canvas */\n if(pJS.particles.move.out_mode == 'bounce'){\n var new_pos = {\n x_left: p.radius,\n x_right: pJS.canvas.w,\n y_top: p.radius,\n y_bottom: pJS.canvas.h\n }\n }else{\n var new_pos = {\n x_left: -p.radius,\n x_right: pJS.canvas.w + p.radius,\n y_top: -p.radius,\n y_bottom: pJS.canvas.h + p.radius\n }\n }\n\n if(p.x - p.radius > pJS.canvas.w){\n p.x = new_pos.x_left;\n p.y = Math.random() * pJS.canvas.h;\n }\n else if(p.x + p.radius < 0){\n p.x = new_pos.x_right;\n p.y = Math.random() * pJS.canvas.h;\n }\n if(p.y - p.radius > pJS.canvas.h){\n p.y = new_pos.y_top;\n p.x = Math.random() * pJS.canvas.w;\n }\n else if(p.y + p.radius < 0){\n p.y = new_pos.y_bottom;\n p.x = Math.random() * pJS.canvas.w;\n }\n\n /* out of canvas modes */\n switch(pJS.particles.move.out_mode){\n case 'bounce':\n if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;\n else if (p.x - p.radius < 0) p.vx = -p.vx;\n if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;\n else if (p.y - p.radius < 0) p.vy = -p.vy;\n break;\n }\n\n /* events */\n if(isInArray('grab', pJS.interactivity.events.onhover.mode)){\n pJS.fn.modes.grabParticle(p);\n }\n\n if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){\n pJS.fn.modes.bubbleParticle(p);\n }\n\n if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){\n pJS.fn.modes.repulseParticle(p);\n }\n\n /* interaction auto between particles */\n if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){\n for(var j = i + 1; j < pJS.particles.array.length; j++){\n var p2 = pJS.particles.array[j];\n\n /* link particles */\n if(pJS.particles.line_linked.enable){\n pJS.fn.interact.linkParticles(p,p2);\n }\n\n /* attract particles */\n if(pJS.particles.move.attract.enable){\n pJS.fn.interact.attractParticles(p,p2);\n }\n\n /* bounce particles */\n if(pJS.particles.move.bounce){\n pJS.fn.interact.bounceParticles(p,p2);\n }\n\n }\n }\n\n\n }\n\n };\n\n pJS.fn.particlesDraw = function(){\n\n /* clear canvas */\n pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);\n\n /* update each particles param */\n pJS.fn.particlesUpdate();\n\n /* draw each particle */\n for(var i = 0; i < pJS.particles.array.length; i++){\n var p = pJS.particles.array[i];\n p.draw();\n }\n\n };\n\n pJS.fn.particlesEmpty = function(){\n pJS.particles.array = [];\n };\n\n pJS.fn.particlesRefresh = function(){\n\n /* init all */\n cancelRequestAnimFrame(pJS.fn.checkAnimFrame);\n cancelRequestAnimFrame(pJS.fn.drawAnimFrame);\n pJS.tmp.source_svg = undefined;\n pJS.tmp.img_obj = undefined;\n pJS.tmp.count_svg = 0;\n pJS.fn.particlesEmpty();\n pJS.fn.canvasClear();\n \n /* restart */\n pJS.fn.vendors.start();\n\n };\n\n\n /* ---------- pJS functions - particles interaction ------------ */\n\n pJS.fn.interact.linkParticles = function(p1, p2){\n\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y,\n dist = Math.sqrt(dx*dx + dy*dy);\n\n /* draw a line between p1 and p2 if the distance between them is under the config distance */\n if(dist <= pJS.particles.line_linked.distance){\n\n var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;\n\n if(opacity_line > 0){ \n \n /* style */\n var color_line = pJS.particles.line_linked.color_rgb_line;\n pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';\n pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;\n //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */\n \n /* path */\n pJS.canvas.ctx.beginPath();\n pJS.canvas.ctx.moveTo(p1.x, p1.y);\n pJS.canvas.ctx.lineTo(p2.x, p2.y);\n pJS.canvas.ctx.stroke();\n pJS.canvas.ctx.closePath();\n\n }\n\n }\n\n };\n\n\n pJS.fn.interact.attractParticles = function(p1, p2){\n\n /* condensed particles */\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y,\n dist = Math.sqrt(dx*dx + dy*dy);\n\n if(dist <= pJS.particles.line_linked.distance){\n\n var ax = dx/(pJS.particles.move.attract.rotateX*1000),\n ay = dy/(pJS.particles.move.attract.rotateY*1000);\n\n p1.vx -= ax;\n p1.vy -= ay;\n\n p2.vx += ax;\n p2.vy += ay;\n\n }\n \n\n }\n\n\n pJS.fn.interact.bounceParticles = function(p1, p2){\n\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y,\n dist = Math.sqrt(dx*dx + dy*dy),\n dist_p = p1.radius+p2.radius;\n\n if(dist <= dist_p){\n p1.vx = -p1.vx;\n p1.vy = -p1.vy;\n\n p2.vx = -p2.vx;\n p2.vy = -p2.vy;\n }\n\n }\n\n\n /* ---------- pJS functions - modes events ------------ */\n\n pJS.fn.modes.pushParticles = function(nb, pos){\n\n pJS.tmp.pushing = true;\n\n for(var i = 0; i < nb; i++){\n pJS.particles.array.push(\n new pJS.fn.particle(\n pJS.particles.color,\n pJS.particles.opacity.value,\n {\n 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,\n 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h\n }\n )\n )\n if(i == nb-1){\n if(!pJS.particles.move.enable){\n pJS.fn.particlesDraw();\n }\n pJS.tmp.pushing = false;\n }\n }\n\n };\n\n\n pJS.fn.modes.removeParticles = function(nb){\n\n pJS.particles.array.splice(0, nb);\n if(!pJS.particles.move.enable){\n pJS.fn.particlesDraw();\n }\n\n };\n\n\n pJS.fn.modes.bubbleParticle = function(p){\n\n /* on hover event */\n if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){\n\n var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,\n dy_mouse = p.y - pJS.interactivity.mouse.pos_y,\n dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),\n ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;\n\n function init(){\n p.opacity_bubble = p.opacity;\n p.radius_bubble = p.radius;\n }\n\n /* mousemove - check ratio */\n if(dist_mouse <= pJS.interactivity.modes.bubble.distance){\n\n if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){\n \n /* size */\n if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){\n\n if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){\n var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);\n if(size >= 0){\n p.radius_bubble = size;\n }\n }else{\n var dif = p.radius - pJS.interactivity.modes.bubble.size,\n size = p.radius - (dif*ratio);\n if(size > 0){\n p.radius_bubble = size;\n }else{\n p.radius_bubble = 0;\n }\n }\n\n }\n\n /* opacity */\n if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){\n\n if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){\n var opacity = pJS.interactivity.modes.bubble.opacity*ratio;\n if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){\n p.opacity_bubble = opacity;\n }\n }else{\n var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;\n if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){\n p.opacity_bubble = opacity;\n }\n }\n\n }\n\n }\n\n }else{\n init();\n }\n\n\n /* mouseleave */\n if(pJS.interactivity.status == 'mouseleave'){\n init();\n }\n \n }\n\n /* on click event */\n else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){\n\n\n if(pJS.tmp.bubble_clicking){\n var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,\n dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,\n dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),\n time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;\n\n if(time_spent > pJS.interactivity.modes.bubble.duration){\n pJS.tmp.bubble_duration_end = true;\n }\n\n if(time_spent > pJS.interactivity.modes.bubble.duration*2){\n pJS.tmp.bubble_clicking = false;\n pJS.tmp.bubble_duration_end = false;\n }\n }\n\n\n function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){\n\n if(bubble_param != particles_param){\n\n if(!pJS.tmp.bubble_duration_end){\n if(dist_mouse <= pJS.interactivity.modes.bubble.distance){\n if(p_obj_bubble != undefined) var obj = p_obj_bubble;\n else var obj = p_obj;\n if(obj != bubble_param){\n var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);\n if(id == 'size') p.radius_bubble = value;\n if(id == 'opacity') p.opacity_bubble = value;\n }\n }else{\n if(id == 'size') p.radius_bubble = undefined;\n if(id == 'opacity') p.opacity_bubble = undefined;\n }\n }else{\n if(p_obj_bubble != undefined){\n var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),\n dif = bubble_param - value_tmp;\n value = bubble_param + dif;\n if(id == 'size') p.radius_bubble = value;\n if(id == 'opacity') p.opacity_bubble = value;\n }\n }\n\n }\n\n }\n\n if(pJS.tmp.bubble_clicking){\n /* size */\n process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');\n /* opacity */\n process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');\n }\n\n }\n\n };\n\n\n pJS.fn.modes.repulseParticle = function(p){\n\n if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {\n\n var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,\n dy_mouse = p.y - pJS.interactivity.mouse.pos_y,\n dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);\n\n var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},\n repulseRadius = pJS.interactivity.modes.repulse.distance,\n velocity = 100,\n repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);\n \n var pos = {\n x: p.x + normVec.x * repulseFactor,\n y: p.y + normVec.y * repulseFactor\n }\n\n if(pJS.particles.move.out_mode == 'bounce'){\n if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;\n if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;\n }else{\n p.x = pos.x;\n p.y = pos.y;\n }\n \n }\n\n\n else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {\n\n if(!pJS.tmp.repulse_finish){\n pJS.tmp.repulse_count++;\n if(pJS.tmp.repulse_count == pJS.particles.array.length){\n pJS.tmp.repulse_finish = true;\n }\n }\n\n if(pJS.tmp.repulse_clicking){\n\n var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);\n\n var dx = pJS.interactivity.mouse.click_pos_x - p.x,\n dy = pJS.interactivity.mouse.click_pos_y - p.y,\n d = dx*dx + dy*dy;\n\n var force = -repulseRadius / d * 1;\n\n function process(){\n\n var f = Math.atan2(dy,dx);\n p.vx = force * Math.cos(f);\n p.vy = force * Math.sin(f);\n\n if(pJS.particles.move.out_mode == 'bounce'){\n var pos = {\n x: p.x + p.vx,\n y: p.y + p.vy\n }\n if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;\n else if (pos.x - p.radius < 0) p.vx = -p.vx;\n if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;\n else if (pos.y - p.radius < 0) p.vy = -p.vy;\n }\n\n }\n\n // default\n if(d <= repulseRadius){\n process();\n }\n\n // bang - slow motion mode\n // if(!pJS.tmp.repulse_finish){\n // if(d <= repulseRadius){\n // process();\n // }\n // }else{\n // process();\n // }\n \n\n }else{\n\n if(pJS.tmp.repulse_clicking == false){\n\n p.vx = p.vx_i;\n p.vy = p.vy_i;\n \n }\n\n }\n\n }\n\n }\n\n\n pJS.fn.modes.grabParticle = function(p){\n\n if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){\n\n var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,\n dy_mouse = p.y - pJS.interactivity.mouse.pos_y,\n dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);\n\n /* draw a line between the cursor and the particle if the distance between them is under the config distance */\n if(dist_mouse <= pJS.interactivity.modes.grab.distance){\n\n var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;\n\n if(opacity_line > 0){\n\n /* style */\n var color_line = pJS.particles.line_linked.color_rgb_line;\n pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';\n pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;\n //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */\n \n /* path */\n pJS.canvas.ctx.beginPath();\n pJS.canvas.ctx.moveTo(p.x, p.y);\n pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);\n pJS.canvas.ctx.stroke();\n pJS.canvas.ctx.closePath();\n\n }\n\n }\n\n }\n\n };\n\n\n\n /* ---------- pJS functions - vendors ------------ */\n\n pJS.fn.vendors.eventsListeners = function(){\n\n /* events target element */\n if(pJS.interactivity.detect_on == 'window'){\n pJS.interactivity.el = window;\n }else{\n pJS.interactivity.el = pJS.canvas.el;\n }\n\n\n /* detect mouse pos - on hover / click event */\n if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){\n\n /* el on mousemove */\n pJS.interactivity.el.addEventListener('mousemove', function(e){\n\n if(pJS.interactivity.el == window){\n var pos_x = e.clientX,\n pos_y = e.clientY;\n }\n else{\n var pos_x = e.offsetX || e.clientX,\n pos_y = e.offsetY || e.clientY;\n }\n\n pJS.interactivity.mouse.pos_x = pos_x;\n pJS.interactivity.mouse.pos_y = pos_y;\n\n if(pJS.tmp.retina){\n pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;\n pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;\n }\n\n pJS.interactivity.status = 'mousemove';\n\n });\n\n /* el on onmouseleave */\n pJS.interactivity.el.addEventListener('mouseleave', function(e){\n\n pJS.interactivity.mouse.pos_x = null;\n pJS.interactivity.mouse.pos_y = null;\n pJS.interactivity.status = 'mouseleave';\n\n });\n\n }\n\n /* on click event */\n if(pJS.interactivity.events.onclick.enable){\n\n pJS.interactivity.el.addEventListener('click', function(){\n\n pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;\n pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;\n pJS.interactivity.mouse.click_time = new Date().getTime();\n\n if(pJS.interactivity.events.onclick.enable){\n\n switch(pJS.interactivity.events.onclick.mode){\n\n case 'push':\n if(pJS.particles.move.enable){\n pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);\n }else{\n if(pJS.interactivity.modes.push.particles_nb == 1){\n pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);\n }\n else if(pJS.interactivity.modes.push.particles_nb > 1){\n pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);\n }\n }\n break;\n\n case 'remove':\n pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);\n break;\n\n case 'bubble':\n pJS.tmp.bubble_clicking = true;\n break;\n\n case 'repulse':\n pJS.tmp.repulse_clicking = true;\n pJS.tmp.repulse_count = 0;\n pJS.tmp.repulse_finish = false;\n setTimeout(function(){\n pJS.tmp.repulse_clicking = false;\n }, pJS.interactivity.modes.repulse.duration*1000)\n break;\n\n }\n\n }\n\n });\n \n }\n\n\n };\n\n pJS.fn.vendors.densityAutoParticles = function(){\n\n if(pJS.particles.number.density.enable){\n\n /* calc area */\n var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;\n if(pJS.tmp.retina){\n area = area/(pJS.canvas.pxratio*2);\n }\n\n /* calc number of particles based on density area */\n var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;\n\n /* add or remove X particles */\n var missing_particles = pJS.particles.array.length - nb_particles;\n if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));\n else pJS.fn.modes.removeParticles(missing_particles);\n\n }\n\n };\n\n\n pJS.fn.vendors.checkOverlap = function(p1, position){\n for(var i = 0; i < pJS.particles.array.length; i++){\n var p2 = pJS.particles.array[i];\n\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y,\n dist = Math.sqrt(dx*dx + dy*dy);\n\n if(dist <= p1.radius + p2.radius){\n p1.x = position ? position.x : Math.random() * pJS.canvas.w;\n p1.y = position ? position.y : Math.random() * pJS.canvas.h;\n pJS.fn.vendors.checkOverlap(p1);\n }\n }\n };\n\n\n pJS.fn.vendors.createSvgImg = function(p){\n\n /* set color to svg element */\n var svgXml = pJS.tmp.source_svg,\n rgbHex = /#([0-9A-F]{3,6})/gi,\n coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {\n if(p.color.rgb){\n var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';\n }else{\n var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';\n }\n return color_value;\n });\n\n /* prepare to create img with colored svg */\n var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),\n DOMURL = window.URL || window.webkitURL || window,\n url = DOMURL.createObjectURL(svg);\n\n /* create particle img obj */\n var img = new Image();\n img.addEventListener('load', function(){\n p.img.obj = img;\n p.img.loaded = true;\n DOMURL.revokeObjectURL(url);\n pJS.tmp.count_svg++;\n });\n img.src = url;\n\n };\n\n\n pJS.fn.vendors.destroypJS = function(){\n cancelAnimationFrame(pJS.fn.drawAnimFrame);\n canvas_el.remove();\n pJSDom = null;\n };\n\n\n pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){\n\n // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/\n var sideCount = sideCountNumerator * sideCountDenominator;\n var decimalSides = sideCountNumerator / sideCountDenominator;\n var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;\n var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians\n c.save();\n c.beginPath();\n c.translate(startX, startY);\n c.moveTo(0,0);\n for (var i = 0; i < sideCount; i++) {\n c.lineTo(sideLength,0);\n c.translate(sideLength,0);\n c.rotate(interiorAngle);\n }\n //c.stroke();\n c.fill();\n c.restore();\n\n };\n\n pJS.fn.vendors.exportImg = function(){\n window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');\n };\n\n\n pJS.fn.vendors.loadImg = function(type){\n\n pJS.tmp.img_error = undefined;\n\n if(pJS.particles.shape.image.src != ''){\n\n if(type == 'svg'){\n\n var xhr = new XMLHttpRequest();\n xhr.open('GET', pJS.particles.shape.image.src);\n xhr.onreadystatechange = function (data) {\n if(xhr.readyState == 4){\n if(xhr.status == 200){\n pJS.tmp.source_svg = data.currentTarget.response;\n pJS.fn.vendors.checkBeforeDraw();\n }else{\n console.log('Error pJS - Image not found');\n pJS.tmp.img_error = true;\n }\n }\n }\n xhr.send();\n\n }else{\n\n var img = new Image();\n img.addEventListener('load', function(){\n pJS.tmp.img_obj = img;\n pJS.fn.vendors.checkBeforeDraw();\n });\n img.src = pJS.particles.shape.image.src;\n\n }\n\n }else{\n console.log('Error pJS - No image.src');\n pJS.tmp.img_error = true;\n }\n\n };\n\n\n pJS.fn.vendors.draw = function(){\n\n if(pJS.particles.shape.type == 'image'){\n\n if(pJS.tmp.img_type == 'svg'){\n\n if(pJS.tmp.count_svg >= pJS.particles.number.value){\n pJS.fn.particlesDraw();\n if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);\n else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);\n }else{\n //console.log('still loading...');\n if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);\n }\n\n }else{\n\n if(pJS.tmp.img_obj != undefined){\n pJS.fn.particlesDraw();\n if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);\n else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);\n }else{\n if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);\n }\n\n }\n\n }else{\n pJS.fn.particlesDraw();\n if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);\n else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);\n }\n\n };\n\n\n pJS.fn.vendors.checkBeforeDraw = function(){\n\n // if shape is image\n if(pJS.particles.shape.type == 'image'){\n\n if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){\n pJS.tmp.checkAnimFrame = requestAnimFrame(check);\n }else{\n //console.log('images loaded! cancel check');\n cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);\n if(!pJS.tmp.img_error){\n pJS.fn.vendors.init();\n pJS.fn.vendors.draw();\n }\n \n }\n\n }else{\n pJS.fn.vendors.init();\n pJS.fn.vendors.draw();\n }\n\n };\n\n\n pJS.fn.vendors.init = function(){\n\n /* init canvas + particles */\n pJS.fn.retinaInit();\n pJS.fn.canvasInit();\n pJS.fn.canvasSize();\n pJS.fn.canvasPaint();\n pJS.fn.particlesCreate();\n pJS.fn.vendors.densityAutoParticles();\n\n /* particles.line_linked - convert hex colors to rgb */\n pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);\n\n };\n\n\n pJS.fn.vendors.start = function(){\n\n if(isInArray('image', pJS.particles.shape.type)){\n pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);\n pJS.fn.vendors.loadImg(pJS.tmp.img_type);\n }else{\n pJS.fn.vendors.checkBeforeDraw();\n }\n\n };\n\n\n\n\n /* ---------- pJS - start ------------ */\n\n\n pJS.fn.vendors.eventsListeners();\n\n pJS.fn.vendors.start();\n \n\n\n};\n\n/* ---------- global functions - vendors ------------ */\n\nObject.deepExtend = function(destination, source) {\n for (var property in source) {\n if (source[property] && source[property].constructor &&\n source[property].constructor === Object) {\n destination[property] = destination[property] || {};\n arguments.callee(destination[property], source[property]);\n } else {\n destination[property] = source[property];\n }\n }\n return destination;\n};\n\nwindow.requestAnimFrame = (function(){\n return window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n function(callback){\n window.setTimeout(callback, 1000 / 60);\n };\n})();\n\nwindow.cancelRequestAnimFrame = ( function() {\n return window.cancelAnimationFrame ||\n window.webkitCancelRequestAnimationFrame ||\n window.mozCancelRequestAnimationFrame ||\n window.oCancelRequestAnimationFrame ||\n window.msCancelRequestAnimationFrame ||\n clearTimeout\n} )();\n\nfunction hexToRgb(hex){\n // By Tim Down - http://stackoverflow.com/a/5624139/3493650\n // Expand shorthand form (e.g. \"03F\") to full form (e.g. \"0033FF\")\n var shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n hex = hex.replace(shorthandRegex, function(m, r, g, b) {\n return r + r + g + g + b + b;\n });\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : null;\n};\n\nfunction clamp(number, min, max) {\n return Math.min(Math.max(number, min), max);\n};\n\nfunction isInArray(value, array) {\n return array.indexOf(value) > -1;\n}\n\n\n/* ---------- particles.js functions - start ------------ */\n\nwindow.pJSDom = [];\n\nwindow.particlesJS = function(tag_id, params){\n\n //console.log(params);\n\n /* no string id? so it's object params, and set the id with default id */\n if(typeof(tag_id) != 'string'){\n params = tag_id;\n tag_id = 'particles-js';\n }\n\n /* no id? set the id to default id */\n if(!tag_id){\n tag_id = 'particles-js';\n }\n\n /* pJS elements */\n var pJS_tag = document.getElementById(tag_id),\n pJS_canvas_class = 'particles-js-canvas-el',\n exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);\n\n /* remove canvas if exists into the pJS target tag */\n if(exist_canvas.length){\n while(exist_canvas.length > 0){\n pJS_tag.removeChild(exist_canvas[0]);\n }\n }\n\n /* create canvas element */\n var canvas_el = document.createElement('canvas');\n canvas_el.className = pJS_canvas_class;\n\n /* set size canvas */\n canvas_el.style.width = \"100%\";\n canvas_el.style.height = \"100%\";\n\n /* append canvas */\n var canvas = document.getElementById(tag_id).appendChild(canvas_el);\n\n /* launch particle.js */\n if(canvas != null){\n pJSDom.push(new pJS(tag_id, params));\n }\n\n};\n\nwindow.particlesJS.load = function(tag_id, path_config_json, callback){\n\n /* load json config */\n var xhr = new XMLHttpRequest();\n xhr.open('GET', path_config_json);\n xhr.onreadystatechange = function (data) {\n if(xhr.readyState == 4){\n if(xhr.status == 200){\n var params = JSON.parse(data.currentTarget.response);\n window.particlesJS(tag_id, params);\n if(callback) callback();\n }else{\n console.log('Error pJS - XMLHttpRequest status: '+xhr.status);\n console.log('Error pJS - File config not found');\n }\n }\n };\n xhr.send();\n\n};//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMS5qcyIsInNvdXJjZXMiOlsiL2hvbWUvdWJ1bnR1L3dvcmtzcGFjZS9ub2RlX21vZHVsZXMvcGFydGljbGVzLmpzL3BhcnRpY2xlcy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLyogQXV0aG9yIDogVmluY2VudCBHYXJyZWF1ICAtIHZpbmNlbnRnYXJyZWF1LmNvbVxuLyogTUlUIGxpY2Vuc2U6IGh0dHA6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVRcbi8qIERlbW8gLyBHZW5lcmF0b3IgOiB2aW5jZW50Z2FycmVhdS5jb20vcGFydGljbGVzLmpzXG4vKiBHaXRIdWIgOiBnaXRodWIuY29tL1ZpbmNlbnRHYXJyZWF1L3BhcnRpY2xlcy5qc1xuLyogSG93IHRvIHVzZT8gOiBDaGVjayB0aGUgR2l0SHViIFJFQURNRVxuLyogdjIuMC4wXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG52YXIgcEpTID0gZnVuY3Rpb24odGFnX2lkLCBwYXJhbXMpe1xuXG4gIHZhciBjYW52YXNfZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjJyt0YWdfaWQrJyA+IC5wYXJ0aWNsZXMtanMtY2FudmFzLWVsJyk7XG5cbiAgLyogcGFydGljbGVzLmpzIHZhcmlhYmxlcyB3aXRoIGRlZmF1bHQgdmFsdWVzICovXG4gIHRoaXMucEpTID0ge1xuICAgIGNhbnZhczoge1xuICAgICAgZWw6IGNhbnZhc19lbCxcbiAgICAgIHc6IGNhbnZhc19lbC5vZmZzZXRXaWR0aCxcbiAgICAgIGg6IGNhbnZhc19lbC5vZmZzZXRIZWlnaHRcbiAgICB9LFxuICAgIHBhcnRpY2xlczoge1xuICAgICAgbnVtYmVyOiB7XG4gICAgICAgIHZhbHVlOiA0MDAsXG4gICAgICAgIGRlbnNpdHk6IHtcbiAgICAgICAgICBlbmFibGU6IHRydWUsXG4gICAgICAgICAgdmFsdWVfYXJlYTogODAwXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBjb2xvcjoge1xuICAgICAgICB2YWx1ZTogJyNmZmYnXG4gICAgICB9LFxuICAgICAgc2hhcGU6IHtcbiAgICAgICAgdHlwZTogJ2NpcmNsZScsXG4gICAgICAgIHN0cm9rZToge1xuICAgICAgICAgIHdpZHRoOiAwLFxuICAgICAgICAgIGNvbG9yOiAnI2ZmMDAwMCdcbiAgICAgICAgfSxcbiAgICAgICAgcG9seWdvbjoge1xuICAgICAgICAgIG5iX3NpZGVzOiA1XG4gICAgICAgIH0sXG4gICAgICAgIGltYWdlOiB7XG4gICAgICAgICAgc3JjOiAnJyxcbiAgICAgICAgICB3aWR0aDogMTAwLFxuICAgICAgICAgIGhlaWdodDogMTAwXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvcGFjaXR5OiB7XG4gICAgICAgIHZhbHVlOiAxLFxuICAgICAgICByYW5kb206IGZhbHNlLFxuICAgICAgICBhbmltOiB7XG4gICAgICAgICAgZW5hYmxlOiBmYWxzZSxcbiAgICAgICAgICBzcGVlZDogMixcbiAgICAgICAgICBvcGFjaXR5X21pbjogMCxcbiAgICAgICAgICBzeW5jOiBmYWxzZVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgc2l6ZToge1xuICAgICAgICB2YWx1ZTogMjAsXG4gICAgICAgIHJhbmRvbTogZmFsc2UsXG4gICAgICAgIGFuaW06IHtcbiAgICAgICAgICBlbmFibGU6IGZhbHNlLFxuICAgICAgICAgIHNwZWVkOiAyMCxcbiAgICAgICAgICBzaXplX21pbjogMCxcbiAgICAgICAgICBzeW5jOiBmYWxzZVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgbGluZV9saW5rZWQ6IHtcbiAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICBkaXN0YW5jZTogMTAwLFxuICAgICAgICBjb2xvcjogJyNmZmYnLFxuICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICB3aWR0aDogMVxuICAgICAgfSxcbiAgICAgIG1vdmU6IHtcbiAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICBzcGVlZDogMixcbiAgICAgICAgZGlyZWN0aW9uOiAnbm9uZScsXG4gICAgICAgIHJhbmRvbTogZmFsc2UsXG4gICAgICAgIHN0cmFpZ2h0OiBmYWxzZSxcbiAgICAgICAgb3V0X21vZGU6ICdvdXQnLFxuICAgICAgICBib3VuY2U6IGZhbHNlLFxuICAgICAgICBhdHRyYWN0OiB7XG4gICAgICAgICAgZW5hYmxlOiBmYWxzZSxcbiAgICAgICAgICByb3RhdGVYOiAzMDAwLFxuICAgICAgICAgIHJvdGF0ZVk6IDMwMDBcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGFycmF5OiBbXVxuICAgIH0sXG4gICAgaW50ZXJhY3Rpdml0eToge1xuICAgICAgZGV0ZWN0X29uOiAnY2FudmFzJyxcbiAgICAgIGV2ZW50czoge1xuICAgICAgICBvbmhvdmVyOiB7XG4gICAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICAgIG1vZGU6ICdncmFiJ1xuICAgICAgICB9LFxuICAgICAgICBvbmNsaWNrOiB7XG4gICAgICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgICAgIG1vZGU6ICdwdXNoJ1xuICAgICAgICB9LFxuICAgICAgICByZXNpemU6IHRydWVcbiAgICAgIH0sXG4gICAgICBtb2Rlczoge1xuICAgICAgICBncmFiOntcbiAgICAgICAgICBkaXN0YW5jZTogMTAwLFxuICAgICAgICAgIGxpbmVfbGlua2VkOntcbiAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGJ1YmJsZTp7XG4gICAgICAgICAgZGlzdGFuY2U6IDIwMCxcbiAgICAgICAgICBzaXplOiA4MCxcbiAgICAgICAgICBkdXJhdGlvbjogMC40XG4gICAgICAgIH0sXG4gICAgICAgIHJlcHVsc2U6e1xuICAgICAgICAgIGRpc3RhbmNlOiAyMDAsXG4gICAgICAgICAgZHVyYXRpb246IDAuNFxuICAgICAgICB9LFxuICAgICAgICBwdXNoOntcbiAgICAgICAgICBwYXJ0aWNsZXNfbmI6IDRcbiAgICAgICAgfSxcbiAgICAgICAgcmVtb3ZlOntcbiAgICAgICAgICBwYXJ0aWNsZXNfbmI6IDJcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIG1vdXNlOnt9XG4gICAgfSxcbiAgICByZXRpbmFfZGV0ZWN0OiBmYWxzZSxcbiAgICBmbjoge1xuICAgICAgaW50ZXJhY3Q6IHt9LFxuICAgICAgbW9kZXM6IHt9LFxuICAgICAgdmVuZG9yczp7fVxuICAgIH0sXG4gICAgdG1wOiB7fVxuICB9O1xuXG4gIHZhciBwSlMgPSB0aGlzLnBKUztcblxuICAvKiBwYXJhbXMgc2V0dGluZ3MgKi9cbiAgaWYocGFyYW1zKXtcbiAgICBPYmplY3QuZGVlcEV4dGVuZChwSlMsIHBhcmFtcyk7XG4gIH1cblxuICBwSlMudG1wLm9iaiA9IHtcbiAgICBzaXplX3ZhbHVlOiBwSlMucGFydGljbGVzLnNpemUudmFsdWUsXG4gICAgc2l6ZV9hbmltX3NwZWVkOiBwSlMucGFydGljbGVzLnNpemUuYW5pbS5zcGVlZCxcbiAgICBtb3ZlX3NwZWVkOiBwSlMucGFydGljbGVzLm1vdmUuc3BlZWQsXG4gICAgbGluZV9saW5rZWRfZGlzdGFuY2U6IHBKUy5wYXJ0aWNsZXMubGluZV9saW5rZWQuZGlzdGFuY2UsXG4gICAgbGluZV9saW5rZWRfd2lkdGg6IHBKUy5wYXJ0aWNsZXMubGluZV9saW5rZWQud2lkdGgsXG4gICAgbW9kZV9ncmFiX2Rpc3RhbmNlOiBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5ncmFiLmRpc3RhbmNlLFxuICAgIG1vZGVfYnViYmxlX2Rpc3RhbmNlOiBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuZGlzdGFuY2UsXG4gICAgbW9kZV9idWJibGVfc2l6ZTogcEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLnNpemUsXG4gICAgbW9kZV9yZXB1bHNlX2Rpc3RhbmNlOiBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5yZXB1bHNlLmRpc3RhbmNlXG4gIH07XG5cblxuICBwSlMuZm4ucmV0aW5hSW5pdCA9IGZ1bmN0aW9uKCl7XG5cbiAgICBpZihwSlMucmV0aW5hX2RldGVjdCAmJiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA+IDEpe1xuICAgICAgcEpTLmNhbnZhcy5weHJhdGlvID0gd2luZG93LmRldmljZVBpeGVsUmF0aW87IFxuICAgICAgcEpTLnRtcC5yZXRpbmEgPSB0cnVlO1xuICAgIH0gXG4gICAgZWxzZXtcbiAgICAgIHBKUy5jYW52YXMucHhyYXRpbyA9IDE7XG4gICAgICBwSlMudG1wLnJldGluYSA9IGZhbHNlO1xuICAgIH1cblxuICAgIHBKUy5jYW52YXMudyA9IHBKUy5jYW52YXMuZWwub2Zmc2V0V2lkdGggKiBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgcEpTLmNhbnZhcy5oID0gcEpTLmNhbnZhcy5lbC5vZmZzZXRIZWlnaHQgKiBwSlMuY2FudmFzLnB4cmF0aW87XG5cbiAgICBwSlMucGFydGljbGVzLnNpemUudmFsdWUgPSBwSlMudG1wLm9iai5zaXplX3ZhbHVlICogcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgIHBKUy5wYXJ0aWNsZXMuc2l6ZS5hbmltLnNwZWVkID0gcEpTLnRtcC5vYmouc2l6ZV9hbmltX3NwZWVkICogcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgIHBKUy5wYXJ0aWNsZXMubW92ZS5zcGVlZCA9IHBKUy50bXAub2JqLm1vdmVfc3BlZWQgKiBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC5kaXN0YW5jZSA9IHBKUy50bXAub2JqLmxpbmVfbGlua2VkX2Rpc3RhbmNlICogcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmdyYWIuZGlzdGFuY2UgPSBwSlMudG1wLm9iai5tb2RlX2dyYWJfZGlzdGFuY2UgKiBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgcEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLmRpc3RhbmNlID0gcEpTLnRtcC5vYmoubW9kZV9idWJibGVfZGlzdGFuY2UgKiBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC53aWR0aCA9IHBKUy50bXAub2JqLmxpbmVfbGlua2VkX3dpZHRoICogcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5zaXplID0gcEpTLnRtcC5vYmoubW9kZV9idWJibGVfc2l6ZSAqIHBKUy5jYW52YXMucHhyYXRpbztcbiAgICBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5yZXB1bHNlLmRpc3RhbmNlID0gcEpTLnRtcC5vYmoubW9kZV9yZXB1bHNlX2Rpc3RhbmNlICogcEpTLmNhbnZhcy5weHJhdGlvO1xuXG4gIH07XG5cblxuXG4gIC8qIC0tLS0tLS0tLS0gcEpTIGZ1bmN0aW9ucyAtIGNhbnZhcyAtLS0tLS0tLS0tLS0gKi9cblxuICBwSlMuZm4uY2FudmFzSW5pdCA9IGZ1bmN0aW9uKCl7XG4gICAgcEpTLmNhbnZhcy5jdHggPSBwSlMuY2FudmFzLmVsLmdldENvbnRleHQoJzJkJyk7XG4gIH07XG5cbiAgcEpTLmZuLmNhbnZhc1NpemUgPSBmdW5jdGlvbigpe1xuXG4gICAgcEpTLmNhbnZhcy5lbC53aWR0aCA9IHBKUy5jYW52YXMudztcbiAgICBwSlMuY2FudmFzLmVsLmhlaWdodCA9IHBKUy5jYW52YXMuaDtcblxuICAgIGlmKHBKUyAmJiBwSlMuaW50ZXJhY3Rpdml0eS5ldmVudHMucmVzaXplKXtcblxuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGZ1bmN0aW9uKCl7XG5cbiAgICAgICAgICBwSlMuY2FudmFzLncgPSBwSlMuY2FudmFzLmVsLm9mZnNldFdpZHRoO1xuICAgICAgICAgIHBKUy5jYW52YXMuaCA9IHBKUy5jYW52YXMuZWwub2Zmc2V0SGVpZ2h0O1xuXG4gICAgICAgICAgLyogcmVzaXplIGNhbnZhcyAqL1xuICAgICAgICAgIGlmKHBKUy50bXAucmV0aW5hKXtcbiAgICAgICAgICAgIHBKUy5jYW52YXMudyAqPSBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgICAgICAgICBwSlMuY2FudmFzLmggKj0gcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHBKUy5jYW52YXMuZWwud2lkdGggPSBwSlMuY2FudmFzLnc7XG4gICAgICAgICAgcEpTLmNhbnZhcy5lbC5oZWlnaHQgPSBwSlMuY2FudmFzLmg7XG5cbiAgICAgICAgICAvKiByZXBhaW50IGNhbnZhcyBvbiBhbmltIGRpc2FibGVkICovXG4gICAgICAgICAgaWYoIXBKUy5wYXJ0aWNsZXMubW92ZS5lbmFibGUpe1xuICAgICAgICAgICAgcEpTLmZuLnBhcnRpY2xlc0VtcHR5KCk7XG4gICAgICAgICAgICBwSlMuZm4ucGFydGljbGVzQ3JlYXRlKCk7XG4gICAgICAgICAgICBwSlMuZm4ucGFydGljbGVzRHJhdygpO1xuICAgICAgICAgICAgcEpTLmZuLnZlbmRvcnMuZGVuc2l0eUF1dG9QYXJ0aWNsZXMoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgLyogZGVuc2l0eSBwYXJ0aWNsZXMgZW5hYmxlZCAqL1xuICAgICAgICBwSlMuZm4udmVuZG9ycy5kZW5zaXR5QXV0b1BhcnRpY2xlcygpO1xuXG4gICAgICB9KTtcblxuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLmNhbnZhc1BhaW50ID0gZnVuY3Rpb24oKXtcbiAgICBwSlMuY2FudmFzLmN0eC5maWxsUmVjdCgwLCAwLCBwSlMuY2FudmFzLncsIHBKUy5jYW52YXMuaCk7XG4gIH07XG5cbiAgcEpTLmZuLmNhbnZhc0NsZWFyID0gZnVuY3Rpb24oKXtcbiAgICBwSlMuY2FudmFzLmN0eC5jbGVhclJlY3QoMCwgMCwgcEpTLmNhbnZhcy53LCBwSlMuY2FudmFzLmgpO1xuICB9O1xuXG5cbiAgLyogLS0tLS0tLS0tIHBKUyBmdW5jdGlvbnMgLSBwYXJ0aWNsZXMgLS0tLS0tLS0tLS0gKi9cblxuICBwSlMuZm4ucGFydGljbGUgPSBmdW5jdGlvbihjb2xvciwgb3BhY2l0eSwgcG9zaXRpb24pe1xuXG4gICAgLyogc2l6ZSAqL1xuICAgIHRoaXMucmFkaXVzID0gKHBKUy5wYXJ0aWNsZXMuc2l6ZS5yYW5kb20gPyBNYXRoLnJhbmRvbSgpIDogMSkgKiBwSlMucGFydGljbGVzLnNpemUudmFsdWU7XG4gICAgaWYocEpTLnBhcnRpY2xlcy5zaXplLmFuaW0uZW5hYmxlKXtcbiAgICAgIHRoaXMuc2l6ZV9zdGF0dXMgPSBmYWxzZTtcbiAgICAgIHRoaXMudnMgPSBwSlMucGFydGljbGVzLnNpemUuYW5pbS5zcGVlZCAvIDEwMDtcbiAgICAgIGlmKCFwSlMucGFydGljbGVzLnNpemUuYW5pbS5zeW5jKXtcbiAgICAgICAgdGhpcy52cyA9IHRoaXMudnMgKiBNYXRoLnJhbmRvbSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qIHBvc2l0aW9uICovXG4gICAgdGhpcy54ID0gcG9zaXRpb24gPyBwb3NpdGlvbi54IDogTWF0aC5yYW5kb20oKSAqIHBKUy5jYW52YXMudztcbiAgICB0aGlzLnkgPSBwb3NpdGlvbiA/IHBvc2l0aW9uLnkgOiBNYXRoLnJhbmRvbSgpICogcEpTLmNhbnZhcy5oO1xuXG4gICAgLyogY2hlY2sgcG9zaXRpb24gIC0gaW50byB0aGUgY2FudmFzICovXG4gICAgaWYodGhpcy54ID4gcEpTLmNhbnZhcy53IC0gdGhpcy5yYWRpdXMqMikgdGhpcy54ID0gdGhpcy54IC0gdGhpcy5yYWRpdXM7XG4gICAgZWxzZSBpZih0aGlzLnggPCB0aGlzLnJhZGl1cyoyKSB0aGlzLnggPSB0aGlzLnggKyB0aGlzLnJhZGl1cztcbiAgICBpZih0aGlzLnkgPiBwSlMuY2FudmFzLmggLSB0aGlzLnJhZGl1cyoyKSB0aGlzLnkgPSB0aGlzLnkgLSB0aGlzLnJhZGl1cztcbiAgICBlbHNlIGlmKHRoaXMueSA8IHRoaXMucmFkaXVzKjIpIHRoaXMueSA9IHRoaXMueSArIHRoaXMucmFkaXVzO1xuXG4gICAgLyogY2hlY2sgcG9zaXRpb24gLSBhdm9pZCBvdmVybGFwICovXG4gICAgaWYocEpTLnBhcnRpY2xlcy5tb3ZlLmJvdW5jZSl7XG4gICAgICBwSlMuZm4udmVuZG9ycy5jaGVja092ZXJsYXAodGhpcywgcG9zaXRpb24pO1xuICAgIH1cblxuICAgIC8qIGNvbG9yICovXG4gICAgdGhpcy5jb2xvciA9IHt9O1xuICAgIGlmKHR5cGVvZihjb2xvci52YWx1ZSkgPT0gJ29iamVjdCcpe1xuXG4gICAgICBpZihjb2xvci52YWx1ZSBpbnN0YW5jZW9mIEFycmF5KXtcbiAgICAgICAgdmFyIGNvbG9yX3NlbGVjdGVkID0gY29sb3IudmFsdWVbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcEpTLnBhcnRpY2xlcy5jb2xvci52YWx1ZS5sZW5ndGgpXTtcbiAgICAgICAgdGhpcy5jb2xvci5yZ2IgPSBoZXhUb1JnYihjb2xvcl9zZWxlY3RlZCk7XG4gICAgICB9ZWxzZXtcbiAgICAgICAgaWYoY29sb3IudmFsdWUuciAhPSB1bmRlZmluZWQgJiYgY29sb3IudmFsdWUuZyAhPSB1bmRlZmluZWQgJiYgY29sb3IudmFsdWUuYiAhPSB1bmRlZmluZWQpe1xuICAgICAgICAgIHRoaXMuY29sb3IucmdiID0ge1xuICAgICAgICAgICAgcjogY29sb3IudmFsdWUucixcbiAgICAgICAgICAgIGc6IGNvbG9yLnZhbHVlLmcsXG4gICAgICAgICAgICBiOiBjb2xvci52YWx1ZS5iXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKGNvbG9yLnZhbHVlLmggIT0gdW5kZWZpbmVkICYmIGNvbG9yLnZhbHVlLnMgIT0gdW5kZWZpbmVkICYmIGNvbG9yLnZhbHVlLmwgIT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICB0aGlzLmNvbG9yLmhzbCA9IHtcbiAgICAgICAgICAgIGg6IGNvbG9yLnZhbHVlLmgsXG4gICAgICAgICAgICBzOiBjb2xvci52YWx1ZS5zLFxuICAgICAgICAgICAgbDogY29sb3IudmFsdWUubFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfVxuICAgIGVsc2UgaWYoY29sb3IudmFsdWUgPT0gJ3JhbmRvbScpe1xuICAgICAgdGhpcy5jb2xvci5yZ2IgPSB7XG4gICAgICAgIHI6IChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoMjU1IC0gMCArIDEpKSArIDApLFxuICAgICAgICBnOiAoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKDI1NSAtIDAgKyAxKSkgKyAwKSxcbiAgICAgICAgYjogKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqICgyNTUgLSAwICsgMSkpICsgMClcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZih0eXBlb2YoY29sb3IudmFsdWUpID09ICdzdHJpbmcnKXtcbiAgICAgIHRoaXMuY29sb3IgPSBjb2xvcjtcbiAgICAgIHRoaXMuY29sb3IucmdiID0gaGV4VG9SZ2IodGhpcy5jb2xvci52YWx1ZSk7XG4gICAgfVxuXG4gICAgLyogb3BhY2l0eSAqL1xuICAgIHRoaXMub3BhY2l0eSA9IChwSlMucGFydGljbGVzLm9wYWNpdHkucmFuZG9tID8gTWF0aC5yYW5kb20oKSA6IDEpICogcEpTLnBhcnRpY2xlcy5vcGFjaXR5LnZhbHVlO1xuICAgIGlmKHBKUy5wYXJ0aWNsZXMub3BhY2l0eS5hbmltLmVuYWJsZSl7XG4gICAgICB0aGlzLm9wYWNpdHlfc3RhdHVzID0gZmFsc2U7XG4gICAgICB0aGlzLnZvID0gcEpTLnBhcnRpY2xlcy5vcGFjaXR5LmFuaW0uc3BlZWQgLyAxMDA7XG4gICAgICBpZighcEpTLnBhcnRpY2xlcy5vcGFjaXR5LmFuaW0uc3luYyl7XG4gICAgICAgIHRoaXMudm8gPSB0aGlzLnZvICogTWF0aC5yYW5kb20oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBhbmltYXRpb24gLSB2ZWxvY2l0eSBmb3Igc3BlZWQgKi9cbiAgICB2YXIgdmVsYmFzZSA9IHt9XG4gICAgc3dpdGNoKHBKUy5wYXJ0aWNsZXMubW92ZS5kaXJlY3Rpb24pe1xuICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgdmVsYmFzZSA9IHsgeDowLCB5Oi0xIH07XG4gICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RvcC1yaWdodCc6XG4gICAgICAgIHZlbGJhc2UgPSB7IHg6MC41LCB5Oi0wLjUgfTtcbiAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICB2ZWxiYXNlID0geyB4OjEsIHk6LTAgfTtcbiAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYm90dG9tLXJpZ2h0JzpcbiAgICAgICAgdmVsYmFzZSA9IHsgeDowLjUsIHk6MC41IH07XG4gICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSc6XG4gICAgICAgIHZlbGJhc2UgPSB7IHg6MCwgeToxIH07XG4gICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbS1sZWZ0JzpcbiAgICAgICAgdmVsYmFzZSA9IHsgeDotMC41LCB5OjEgfTtcbiAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbGVmdCc6XG4gICAgICAgIHZlbGJhc2UgPSB7IHg6LTEsIHk6MCB9O1xuICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0b3AtbGVmdCc6XG4gICAgICAgIHZlbGJhc2UgPSB7IHg6LTAuNSwgeTotMC41IH07XG4gICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZlbGJhc2UgPSB7IHg6MCwgeTowIH07XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZihwSlMucGFydGljbGVzLm1vdmUuc3RyYWlnaHQpe1xuICAgICAgdGhpcy52eCA9IHZlbGJhc2UueDtcbiAgICAgIHRoaXMudnkgPSB2ZWxiYXNlLnk7XG4gICAgICBpZihwSlMucGFydGljbGVzLm1vdmUucmFuZG9tKXtcbiAgICAgICAgdGhpcy52eCA9IHRoaXMudnggKiAoTWF0aC5yYW5kb20oKSk7XG4gICAgICAgIHRoaXMudnkgPSB0aGlzLnZ5ICogKE1hdGgucmFuZG9tKCkpO1xuICAgICAgfVxuICAgIH1lbHNle1xuICAgICAgdGhpcy52eCA9IHZlbGJhc2UueCArIE1hdGgucmFuZG9tKCktMC41O1xuICAgICAgdGhpcy52eSA9IHZlbGJhc2UueSArIE1hdGgucmFuZG9tKCktMC41O1xuICAgIH1cblxuICAgIC8vIHZhciB0aGV0YSA9IDIuMCAqIE1hdGguUEkgKiBNYXRoLnJhbmRvbSgpO1xuICAgIC8vIHRoaXMudnggPSBNYXRoLmNvcyh0aGV0YSk7XG4gICAgLy8gdGhpcy52eSA9IE1hdGguc2luKHRoZXRhKTtcblxuICAgIHRoaXMudnhfaSA9IHRoaXMudng7XG4gICAgdGhpcy52eV9pID0gdGhpcy52eTtcblxuICAgIFxuXG4gICAgLyogaWYgc2hhcGUgaXMgaW1hZ2UgKi9cblxuICAgIHZhciBzaGFwZV90eXBlID0gcEpTLnBhcnRpY2xlcy5zaGFwZS50eXBlO1xuICAgIGlmKHR5cGVvZihzaGFwZV90eXBlKSA9PSAnb2JqZWN0Jyl7XG4gICAgICBpZihzaGFwZV90eXBlIGluc3RhbmNlb2YgQXJyYXkpe1xuICAgICAgICB2YXIgc2hhcGVfc2VsZWN0ZWQgPSBzaGFwZV90eXBlW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHNoYXBlX3R5cGUubGVuZ3RoKV07XG4gICAgICAgIHRoaXMuc2hhcGUgPSBzaGFwZV9zZWxlY3RlZDtcbiAgICAgIH1cbiAgICB9ZWxzZXtcbiAgICAgIHRoaXMuc2hhcGUgPSBzaGFwZV90eXBlO1xuICAgIH1cblxuICAgIGlmKHRoaXMuc2hhcGUgPT0gJ2ltYWdlJyl7XG4gICAgICB2YXIgc2ggPSBwSlMucGFydGljbGVzLnNoYXBlO1xuICAgICAgdGhpcy5pbWcgPSB7XG4gICAgICAgIHNyYzogc2guaW1hZ2Uuc3JjLFxuICAgICAgICByYXRpbzogc2guaW1hZ2Uud2lkdGggLyBzaC5pbWFnZS5oZWlnaHRcbiAgICAgIH1cbiAgICAgIGlmKCF0aGlzLmltZy5yYXRpbykgdGhpcy5pbWcucmF0aW8gPSAxO1xuICAgICAgaWYocEpTLnRtcC5pbWdfdHlwZSA9PSAnc3ZnJyAmJiBwSlMudG1wLnNvdXJjZV9zdmcgIT0gdW5kZWZpbmVkKXtcbiAgICAgICAgcEpTLmZuLnZlbmRvcnMuY3JlYXRlU3ZnSW1nKHRoaXMpO1xuICAgICAgICBpZihwSlMudG1wLnB1c2hpbmcpe1xuICAgICAgICAgIHRoaXMuaW1nLmxvYWRlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgXG5cbiAgfTtcblxuXG4gIHBKUy5mbi5wYXJ0aWNsZS5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHAgPSB0aGlzO1xuXG4gICAgaWYocC5yYWRpdXNfYnViYmxlICE9IHVuZGVmaW5lZCl7XG4gICAgICB2YXIgcmFkaXVzID0gcC5yYWRpdXNfYnViYmxlOyBcbiAgICB9ZWxzZXtcbiAgICAgIHZhciByYWRpdXMgPSBwLnJhZGl1cztcbiAgICB9XG5cbiAgICBpZihwLm9wYWNpdHlfYnViYmxlICE9IHVuZGVmaW5lZCl7XG4gICAgICB2YXIgb3BhY2l0eSA9IHAub3BhY2l0eV9idWJibGU7XG4gICAgfWVsc2V7XG4gICAgICB2YXIgb3BhY2l0eSA9IHAub3BhY2l0eTtcbiAgICB9XG5cbiAgICBpZihwLmNvbG9yLnJnYil7XG4gICAgICB2YXIgY29sb3JfdmFsdWUgPSAncmdiYSgnK3AuY29sb3IucmdiLnIrJywnK3AuY29sb3IucmdiLmcrJywnK3AuY29sb3IucmdiLmIrJywnK29wYWNpdHkrJyknO1xuICAgIH1lbHNle1xuICAgICAgdmFyIGNvbG9yX3ZhbHVlID0gJ2hzbGEoJytwLmNvbG9yLmhzbC5oKycsJytwLmNvbG9yLmhzbC5zKyclLCcrcC5jb2xvci5oc2wubCsnJSwnK29wYWNpdHkrJyknO1xuICAgIH1cblxuICAgIHBKUy5jYW52YXMuY3R4LmZpbGxTdHlsZSA9IGNvbG9yX3ZhbHVlO1xuICAgIHBKUy5jYW52YXMuY3R4LmJlZ2luUGF0aCgpO1xuXG4gICAgc3dpdGNoKHAuc2hhcGUpe1xuXG4gICAgICBjYXNlICdjaXJjbGUnOlxuICAgICAgICBwSlMuY2FudmFzLmN0eC5hcmMocC54LCBwLnksIHJhZGl1cywgMCwgTWF0aC5QSSAqIDIsIGZhbHNlKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdlZGdlJzpcbiAgICAgICAgcEpTLmNhbnZhcy5jdHgucmVjdChwLngtcmFkaXVzLCBwLnktcmFkaXVzLCByYWRpdXMqMiwgcmFkaXVzKjIpO1xuICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3RyaWFuZ2xlJzpcbiAgICAgICAgcEpTLmZuLnZlbmRvcnMuZHJhd1NoYXBlKHBKUy5jYW52YXMuY3R4LCBwLngtcmFkaXVzLCBwLnkrcmFkaXVzIC8gMS42NiwgcmFkaXVzKjIsIDMsIDIpO1xuICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3BvbHlnb24nOlxuICAgICAgICBwSlMuZm4udmVuZG9ycy5kcmF3U2hhcGUoXG4gICAgICAgICAgcEpTLmNhbnZhcy5jdHgsXG4gICAgICAgICAgcC54IC0gcmFkaXVzIC8gKHBKUy5wYXJ0aWNsZXMuc2hhcGUucG9seWdvbi5uYl9zaWRlcy8zLjUpLCAvLyBzdGFydFhcbiAgICAgICAgICBwLnkgLSByYWRpdXMgLyAoMi42Ni8zLjUpLCAvLyBzdGFydFlcbiAgICAgICAgICByYWRpdXMqMi42NiAvIChwSlMucGFydGljbGVzLnNoYXBlLnBvbHlnb24ubmJfc2lkZXMvMyksIC8vIHNpZGVMZW5ndGhcbiAgICAgICAgICBwSlMucGFydGljbGVzLnNoYXBlLnBvbHlnb24ubmJfc2lkZXMsIC8vIHNpZGVDb3VudE51bWVyYXRvclxuICAgICAgICAgIDEgLy8gc2lkZUNvdW50RGVub21pbmF0b3JcbiAgICAgICAgKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdzdGFyJzpcbiAgICAgICAgcEpTLmZuLnZlbmRvcnMuZHJhd1NoYXBlKFxuICAgICAgICAgIHBKUy5jYW52YXMuY3R4LFxuICAgICAgICAgIHAueCAtIHJhZGl1cyoyIC8gKHBKUy5wYXJ0aWNsZXMuc2hhcGUucG9seWdvbi5uYl9zaWRlcy80KSwgLy8gc3RhcnRYXG4gICAgICAgICAgcC55IC0gcmFkaXVzIC8gKDIqMi42Ni8zLjUpLCAvLyBzdGFydFlcbiAgICAgICAgICByYWRpdXMqMioyLjY2IC8gKHBKUy5wYXJ0aWNsZXMuc2hhcGUucG9seWdvbi5uYl9zaWRlcy8zKSwgLy8gc2lkZUxlbmd0aFxuICAgICAgICAgIHBKUy5wYXJ0aWNsZXMuc2hhcGUucG9seWdvbi5uYl9zaWRlcywgLy8gc2lkZUNvdW50TnVtZXJhdG9yXG4gICAgICAgICAgMiAvLyBzaWRlQ291bnREZW5vbWluYXRvclxuICAgICAgICApO1xuICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2ltYWdlJzpcblxuICAgICAgICBmdW5jdGlvbiBkcmF3KCl7XG4gICAgICAgICAgcEpTLmNhbnZhcy5jdHguZHJhd0ltYWdlKFxuICAgICAgICAgICAgaW1nX29iaixcbiAgICAgICAgICAgIHAueC1yYWRpdXMsXG4gICAgICAgICAgICBwLnktcmFkaXVzLFxuICAgICAgICAgICAgcmFkaXVzKjIsXG4gICAgICAgICAgICByYWRpdXMqMiAvIHAuaW1nLnJhdGlvXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHBKUy50bXAuaW1nX3R5cGUgPT0gJ3N2Zycpe1xuICAgICAgICAgIHZhciBpbWdfb2JqID0gcC5pbWcub2JqO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICB2YXIgaW1nX29iaiA9IHBKUy50bXAuaW1nX29iajtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGltZ19vYmope1xuICAgICAgICAgIGRyYXcoKTtcbiAgICAgICAgfVxuXG4gICAgICBicmVhaztcblxuICAgIH1cblxuICAgIHBKUy5jYW52YXMuY3R4LmNsb3NlUGF0aCgpO1xuXG4gICAgaWYocEpTLnBhcnRpY2xlcy5zaGFwZS5zdHJva2Uud2lkdGggPiAwKXtcbiAgICAgIHBKUy5jYW52YXMuY3R4LnN0cm9rZVN0eWxlID0gcEpTLnBhcnRpY2xlcy5zaGFwZS5zdHJva2UuY29sb3I7XG4gICAgICBwSlMuY2FudmFzLmN0eC5saW5lV2lkdGggPSBwSlMucGFydGljbGVzLnNoYXBlLnN0cm9rZS53aWR0aDtcbiAgICAgIHBKUy5jYW52YXMuY3R4LnN0cm9rZSgpO1xuICAgIH1cbiAgICBcbiAgICBwSlMuY2FudmFzLmN0eC5maWxsKCk7XG4gICAgXG4gIH07XG5cblxuICBwSlMuZm4ucGFydGljbGVzQ3JlYXRlID0gZnVuY3Rpb24oKXtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcEpTLnBhcnRpY2xlcy5udW1iZXIudmFsdWU7IGkrKykge1xuICAgICAgcEpTLnBhcnRpY2xlcy5hcnJheS5wdXNoKG5ldyBwSlMuZm4ucGFydGljbGUocEpTLnBhcnRpY2xlcy5jb2xvciwgcEpTLnBhcnRpY2xlcy5vcGFjaXR5LnZhbHVlKSk7XG4gICAgfVxuICB9O1xuXG4gIHBKUy5mbi5wYXJ0aWNsZXNVcGRhdGUgPSBmdW5jdGlvbigpe1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBKUy5wYXJ0aWNsZXMuYXJyYXkubGVuZ3RoOyBpKyspe1xuXG4gICAgICAvKiB0aGUgcGFydGljbGUgKi9cbiAgICAgIHZhciBwID0gcEpTLnBhcnRpY2xlcy5hcnJheVtpXTtcblxuICAgICAgLy8gdmFyIGQgPSAoIGR4ID0gcEpTLmludGVyYWN0aXZpdHkubW91c2UuY2xpY2tfcG9zX3ggLSBwLnggKSAqIGR4ICsgKCBkeSA9IHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLmNsaWNrX3Bvc195IC0gcC55ICkgKiBkeTtcbiAgICAgIC8vIHZhciBmID0gLUJBTkdfU0laRSAvIGQ7XG4gICAgICAvLyBpZiAoIGQgPCBCQU5HX1NJWkUgKSB7XG4gICAgICAvLyAgICAgdmFyIHQgPSBNYXRoLmF0YW4yKCBkeSwgZHggKTtcbiAgICAgIC8vICAgICBwLnZ4ID0gZiAqIE1hdGguY29zKHQpO1xuICAgICAgLy8gICAgIHAudnkgPSBmICogTWF0aC5zaW4odCk7XG4gICAgICAvLyB9XG5cbiAgICAgIC8qIG1vdmUgdGhlIHBhcnRpY2xlICovXG4gICAgICBpZihwSlMucGFydGljbGVzLm1vdmUuZW5hYmxlKXtcbiAgICAgICAgdmFyIG1zID0gcEpTLnBhcnRpY2xlcy5tb3ZlLnNwZWVkLzI7XG4gICAgICAgIHAueCArPSBwLnZ4ICogbXM7XG4gICAgICAgIHAueSArPSBwLnZ5ICogbXM7XG4gICAgICB9XG5cbiAgICAgIC8qIGNoYW5nZSBvcGFjaXR5IHN0YXR1cyAqL1xuICAgICAgaWYocEpTLnBhcnRpY2xlcy5vcGFjaXR5LmFuaW0uZW5hYmxlKSB7XG4gICAgICAgIGlmKHAub3BhY2l0eV9zdGF0dXMgPT0gdHJ1ZSkge1xuICAgICAgICAgIGlmKHAub3BhY2l0eSA+PSBwSlMucGFydGljbGVzLm9wYWNpdHkudmFsdWUpIHAub3BhY2l0eV9zdGF0dXMgPSBmYWxzZTtcbiAgICAgICAgICBwLm9wYWNpdHkgKz0gcC52bztcbiAgICAgICAgfWVsc2Uge1xuICAgICAgICAgIGlmKHAub3BhY2l0eSA8PSBwSlMucGFydGljbGVzLm9wYWNpdHkuYW5pbS5vcGFjaXR5X21pbikgcC5vcGFjaXR5X3N0YXR1cyA9IHRydWU7XG4gICAgICAgICAgcC5vcGFjaXR5IC09IHAudm87XG4gICAgICAgIH1cbiAgICAgICAgaWYocC5vcGFjaXR5IDwgMCkgcC5vcGFjaXR5ID0gMDtcbiAgICAgIH1cblxuICAgICAgLyogY2hhbmdlIHNpemUgKi9cbiAgICAgIGlmKHBKUy5wYXJ0aWNsZXMuc2l6ZS5hbmltLmVuYWJsZSl7XG4gICAgICAgIGlmKHAuc2l6ZV9zdGF0dXMgPT0gdHJ1ZSl7XG4gICAgICAgICAgaWYocC5yYWRpdXMgPj0gcEpTLnBhcnRpY2xlcy5zaXplLnZhbHVlKSBwLnNpemVfc3RhdHVzID0gZmFsc2U7XG4gICAgICAgICAgcC5yYWRpdXMgKz0gcC52cztcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgaWYocC5yYWRpdXMgPD0gcEpTLnBhcnRpY2xlcy5zaXplLmFuaW0uc2l6ZV9taW4pIHAuc2l6ZV9zdGF0dXMgPSB0cnVlO1xuICAgICAgICAgIHAucmFkaXVzIC09IHAudnM7XG4gICAgICAgIH1cbiAgICAgICAgaWYocC5yYWRpdXMgPCAwKSBwLnJhZGl1cyA9IDA7XG4gICAgICB9XG5cbiAgICAgIC8qIGNoYW5nZSBwYXJ0aWNsZSBwb3NpdGlvbiBpZiBpdCBpcyBvdXQgb2YgY2FudmFzICovXG4gICAgICBpZihwSlMucGFydGljbGVzLm1vdmUub3V0X21vZGUgPT0gJ2JvdW5jZScpe1xuICAgICAgICB2YXIgbmV3X3BvcyA9IHtcbiAgICAgICAgICB4X2xlZnQ6IHAucmFkaXVzLFxuICAgICAgICAgIHhfcmlnaHQ6ICBwSlMuY2FudmFzLncsXG4gICAgICAgICAgeV90b3A6IHAucmFkaXVzLFxuICAgICAgICAgIHlfYm90dG9tOiBwSlMuY2FudmFzLmhcbiAgICAgICAgfVxuICAgICAgfWVsc2V7XG4gICAgICAgIHZhciBuZXdfcG9zID0ge1xuICAgICAgICAgIHhfbGVmdDogLXAucmFkaXVzLFxuICAgICAgICAgIHhfcmlnaHQ6IHBKUy5jYW52YXMudyArIHAucmFkaXVzLFxuICAgICAgICAgIHlfdG9wOiAtcC5yYWRpdXMsXG4gICAgICAgICAgeV9ib3R0b206IHBKUy5jYW52YXMuaCArIHAucmFkaXVzXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYocC54IC0gcC5yYWRpdXMgPiBwSlMuY2FudmFzLncpe1xuICAgICAgICBwLnggPSBuZXdfcG9zLnhfbGVmdDtcbiAgICAgICAgcC55ID0gTWF0aC5yYW5kb20oKSAqIHBKUy5jYW52YXMuaDtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYocC54ICsgcC5yYWRpdXMgPCAwKXtcbiAgICAgICAgcC54ID0gbmV3X3Bvcy54X3JpZ2h0O1xuICAgICAgICBwLnkgPSBNYXRoLnJhbmRvbSgpICogcEpTLmNhbnZhcy5oO1xuICAgICAgfVxuICAgICAgaWYocC55IC0gcC5yYWRpdXMgPiBwSlMuY2FudmFzLmgpe1xuICAgICAgICBwLnkgPSBuZXdfcG9zLnlfdG9wO1xuICAgICAgICBwLnggPSBNYXRoLnJhbmRvbSgpICogcEpTLmNhbnZhcy53O1xuICAgICAgfVxuICAgICAgZWxzZSBpZihwLnkgKyBwLnJhZGl1cyA8IDApe1xuICAgICAgICBwLnkgPSBuZXdfcG9zLnlfYm90dG9tO1xuICAgICAgICBwLnggPSBNYXRoLnJhbmRvbSgpICogcEpTLmNhbnZhcy53O1xuICAgICAgfVxuXG4gICAgICAvKiBvdXQgb2YgY2FudmFzIG1vZGVzICovXG4gICAgICBzd2l0Y2gocEpTLnBhcnRpY2xlcy5tb3ZlLm91dF9tb2RlKXtcbiAgICAgICAgY2FzZSAnYm91bmNlJzpcbiAgICAgICAgICBpZiAocC54ICsgcC5yYWRpdXMgPiBwSlMuY2FudmFzLncpIHAudnggPSAtcC52eDtcbiAgICAgICAgICBlbHNlIGlmIChwLnggLSBwLnJhZGl1cyA8IDApIHAudnggPSAtcC52eDtcbiAgICAgICAgICBpZiAocC55ICsgcC5yYWRpdXMgPiBwSlMuY2FudmFzLmgpIHAudnkgPSAtcC52eTtcbiAgICAgICAgICBlbHNlIGlmIChwLnkgLSBwLnJhZGl1cyA8IDApIHAudnkgPSAtcC52eTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8qIGV2ZW50cyAqL1xuICAgICAgaWYoaXNJbkFycmF5KCdncmFiJywgcEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uaG92ZXIubW9kZSkpe1xuICAgICAgICBwSlMuZm4ubW9kZXMuZ3JhYlBhcnRpY2xlKHApO1xuICAgICAgfVxuXG4gICAgICBpZihpc0luQXJyYXkoJ2J1YmJsZScsIHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLm1vZGUpIHx8IGlzSW5BcnJheSgnYnViYmxlJywgcEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2subW9kZSkpe1xuICAgICAgICBwSlMuZm4ubW9kZXMuYnViYmxlUGFydGljbGUocCk7XG4gICAgICB9XG5cbiAgICAgIGlmKGlzSW5BcnJheSgncmVwdWxzZScsIHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLm1vZGUpIHx8IGlzSW5BcnJheSgncmVwdWxzZScsIHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmNsaWNrLm1vZGUpKXtcbiAgICAgICAgcEpTLmZuLm1vZGVzLnJlcHVsc2VQYXJ0aWNsZShwKTtcbiAgICAgIH1cblxuICAgICAgLyogaW50ZXJhY3Rpb24gYXV0byBiZXR3ZWVuIHBhcnRpY2xlcyAqL1xuICAgICAgaWYocEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC5lbmFibGUgfHwgcEpTLnBhcnRpY2xlcy5tb3ZlLmF0dHJhY3QuZW5hYmxlKXtcbiAgICAgICAgZm9yKHZhciBqID0gaSArIDE7IGogPCBwSlMucGFydGljbGVzLmFycmF5Lmxlbmd0aDsgaisrKXtcbiAgICAgICAgICB2YXIgcDIgPSBwSlMucGFydGljbGVzLmFycmF5W2pdO1xuXG4gICAgICAgICAgLyogbGluayBwYXJ0aWNsZXMgKi9cbiAgICAgICAgICBpZihwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLmVuYWJsZSl7XG4gICAgICAgICAgICBwSlMuZm4uaW50ZXJhY3QubGlua1BhcnRpY2xlcyhwLHAyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvKiBhdHRyYWN0IHBhcnRpY2xlcyAqL1xuICAgICAgICAgIGlmKHBKUy5wYXJ0aWNsZXMubW92ZS5hdHRyYWN0LmVuYWJsZSl7XG4gICAgICAgICAgICBwSlMuZm4uaW50ZXJhY3QuYXR0cmFjdFBhcnRpY2xlcyhwLHAyKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvKiBib3VuY2UgcGFydGljbGVzICovXG4gICAgICAgICAgaWYocEpTLnBhcnRpY2xlcy5tb3ZlLmJvdW5jZSl7XG4gICAgICAgICAgICBwSlMuZm4uaW50ZXJhY3QuYm91bmNlUGFydGljbGVzKHAscDIpO1xuICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgICB9XG5cblxuICAgIH1cblxuICB9O1xuXG4gIHBKUy5mbi5wYXJ0aWNsZXNEcmF3ID0gZnVuY3Rpb24oKXtcblxuICAgIC8qIGNsZWFyIGNhbnZhcyAqL1xuICAgIHBKUy5jYW52YXMuY3R4LmNsZWFyUmVjdCgwLCAwLCBwSlMuY2FudmFzLncsIHBKUy5jYW52YXMuaCk7XG5cbiAgICAvKiB1cGRhdGUgZWFjaCBwYXJ0aWNsZXMgcGFyYW0gKi9cbiAgICBwSlMuZm4ucGFydGljbGVzVXBkYXRlKCk7XG5cbiAgICAvKiBkcmF3IGVhY2ggcGFydGljbGUgKi9cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcEpTLnBhcnRpY2xlcy5hcnJheS5sZW5ndGg7IGkrKyl7XG4gICAgICB2YXIgcCA9IHBKUy5wYXJ0aWNsZXMuYXJyYXlbaV07XG4gICAgICBwLmRyYXcoKTtcbiAgICB9XG5cbiAgfTtcblxuICBwSlMuZm4ucGFydGljbGVzRW1wdHkgPSBmdW5jdGlvbigpe1xuICAgIHBKUy5wYXJ0aWNsZXMuYXJyYXkgPSBbXTtcbiAgfTtcblxuICBwSlMuZm4ucGFydGljbGVzUmVmcmVzaCA9IGZ1bmN0aW9uKCl7XG5cbiAgICAvKiBpbml0IGFsbCAqL1xuICAgIGNhbmNlbFJlcXVlc3RBbmltRnJhbWUocEpTLmZuLmNoZWNrQW5pbUZyYW1lKTtcbiAgICBjYW5jZWxSZXF1ZXN0QW5pbUZyYW1lKHBKUy5mbi5kcmF3QW5pbUZyYW1lKTtcbiAgICBwSlMudG1wLnNvdXJjZV9zdmcgPSB1bmRlZmluZWQ7XG4gICAgcEpTLnRtcC5pbWdfb2JqID0gdW5kZWZpbmVkO1xuICAgIHBKUy50bXAuY291bnRfc3ZnID0gMDtcbiAgICBwSlMuZm4ucGFydGljbGVzRW1wdHkoKTtcbiAgICBwSlMuZm4uY2FudmFzQ2xlYXIoKTtcbiAgICBcbiAgICAvKiByZXN0YXJ0ICovXG4gICAgcEpTLmZuLnZlbmRvcnMuc3RhcnQoKTtcblxuICB9O1xuXG5cbiAgLyogLS0tLS0tLS0tLSBwSlMgZnVuY3Rpb25zIC0gcGFydGljbGVzIGludGVyYWN0aW9uIC0tLS0tLS0tLS0tLSAqL1xuXG4gIHBKUy5mbi5pbnRlcmFjdC5saW5rUGFydGljbGVzID0gZnVuY3Rpb24ocDEsIHAyKXtcblxuICAgIHZhciBkeCA9IHAxLnggLSBwMi54LFxuICAgICAgICBkeSA9IHAxLnkgLSBwMi55LFxuICAgICAgICBkaXN0ID0gTWF0aC5zcXJ0KGR4KmR4ICsgZHkqZHkpO1xuXG4gICAgLyogZHJhdyBhIGxpbmUgYmV0d2VlbiBwMSBhbmQgcDIgaWYgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlbSBpcyB1bmRlciB0aGUgY29uZmlnIGRpc3RhbmNlICovXG4gICAgaWYoZGlzdCA8PSBwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLmRpc3RhbmNlKXtcblxuICAgICAgdmFyIG9wYWNpdHlfbGluZSA9IHBKUy5wYXJ0aWNsZXMubGluZV9saW5rZWQub3BhY2l0eSAtIChkaXN0IC8gKDEvcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC5vcGFjaXR5KSkgLyBwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLmRpc3RhbmNlO1xuXG4gICAgICBpZihvcGFjaXR5X2xpbmUgPiAwKXsgICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLyogc3R5bGUgKi9cbiAgICAgICAgdmFyIGNvbG9yX2xpbmUgPSBwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLmNvbG9yX3JnYl9saW5lO1xuICAgICAgICBwSlMuY2FudmFzLmN0eC5zdHJva2VTdHlsZSA9ICdyZ2JhKCcrY29sb3JfbGluZS5yKycsJytjb2xvcl9saW5lLmcrJywnK2NvbG9yX2xpbmUuYisnLCcrb3BhY2l0eV9saW5lKycpJztcbiAgICAgICAgcEpTLmNhbnZhcy5jdHgubGluZVdpZHRoID0gcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC53aWR0aDtcbiAgICAgICAgLy9wSlMuY2FudmFzLmN0eC5saW5lQ2FwID0gJ3JvdW5kJzsgLyogcGVyZm9ybWFuY2UgaXNzdWUgKi9cbiAgICAgICAgXG4gICAgICAgIC8qIHBhdGggKi9cbiAgICAgICAgcEpTLmNhbnZhcy5jdHguYmVnaW5QYXRoKCk7XG4gICAgICAgIHBKUy5jYW52YXMuY3R4Lm1vdmVUbyhwMS54LCBwMS55KTtcbiAgICAgICAgcEpTLmNhbnZhcy5jdHgubGluZVRvKHAyLngsIHAyLnkpO1xuICAgICAgICBwSlMuY2FudmFzLmN0eC5zdHJva2UoKTtcbiAgICAgICAgcEpTLmNhbnZhcy5jdHguY2xvc2VQYXRoKCk7XG5cbiAgICAgIH1cblxuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLmludGVyYWN0LmF0dHJhY3RQYXJ0aWNsZXMgID0gZnVuY3Rpb24ocDEsIHAyKXtcblxuICAgIC8qIGNvbmRlbnNlZCBwYXJ0aWNsZXMgKi9cbiAgICB2YXIgZHggPSBwMS54IC0gcDIueCxcbiAgICAgICAgZHkgPSBwMS55IC0gcDIueSxcbiAgICAgICAgZGlzdCA9IE1hdGguc3FydChkeCpkeCArIGR5KmR5KTtcblxuICAgIGlmKGRpc3QgPD0gcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC5kaXN0YW5jZSl7XG5cbiAgICAgIHZhciBheCA9IGR4LyhwSlMucGFydGljbGVzLm1vdmUuYXR0cmFjdC5yb3RhdGVYKjEwMDApLFxuICAgICAgICAgIGF5ID0gZHkvKHBKUy5wYXJ0aWNsZXMubW92ZS5hdHRyYWN0LnJvdGF0ZVkqMTAwMCk7XG5cbiAgICAgIHAxLnZ4IC09IGF4O1xuICAgICAgcDEudnkgLT0gYXk7XG5cbiAgICAgIHAyLnZ4ICs9IGF4O1xuICAgICAgcDIudnkgKz0gYXk7XG5cbiAgICB9XG4gICAgXG5cbiAgfVxuXG5cbiAgcEpTLmZuLmludGVyYWN0LmJvdW5jZVBhcnRpY2xlcyA9IGZ1bmN0aW9uKHAxLCBwMil7XG5cbiAgICB2YXIgZHggPSBwMS54IC0gcDIueCxcbiAgICAgICAgZHkgPSBwMS55IC0gcDIueSxcbiAgICAgICAgZGlzdCA9IE1hdGguc3FydChkeCpkeCArIGR5KmR5KSxcbiAgICAgICAgZGlzdF9wID0gcDEucmFkaXVzK3AyLnJhZGl1cztcblxuICAgIGlmKGRpc3QgPD0gZGlzdF9wKXtcbiAgICAgIHAxLnZ4ID0gLXAxLnZ4O1xuICAgICAgcDEudnkgPSAtcDEudnk7XG5cbiAgICAgIHAyLnZ4ID0gLXAyLnZ4O1xuICAgICAgcDIudnkgPSAtcDIudnk7XG4gICAgfVxuXG4gIH1cblxuXG4gIC8qIC0tLS0tLS0tLS0gcEpTIGZ1bmN0aW9ucyAtIG1vZGVzIGV2ZW50cyAtLS0tLS0tLS0tLS0gKi9cblxuICBwSlMuZm4ubW9kZXMucHVzaFBhcnRpY2xlcyA9IGZ1bmN0aW9uKG5iLCBwb3Mpe1xuXG4gICAgcEpTLnRtcC5wdXNoaW5nID0gdHJ1ZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuYjsgaSsrKXtcbiAgICAgIHBKUy5wYXJ0aWNsZXMuYXJyYXkucHVzaChcbiAgICAgICAgbmV3IHBKUy5mbi5wYXJ0aWNsZShcbiAgICAgICAgICBwSlMucGFydGljbGVzLmNvbG9yLFxuICAgICAgICAgIHBKUy5wYXJ0aWNsZXMub3BhY2l0eS52YWx1ZSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICAneCc6IHBvcyA/IHBvcy5wb3NfeCA6IE1hdGgucmFuZG9tKCkgKiBwSlMuY2FudmFzLncsXG4gICAgICAgICAgICAneSc6IHBvcyA/IHBvcy5wb3NfeSA6IE1hdGgucmFuZG9tKCkgKiBwSlMuY2FudmFzLmhcbiAgICAgICAgICB9XG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIGlmKGkgPT0gbmItMSl7XG4gICAgICAgIGlmKCFwSlMucGFydGljbGVzLm1vdmUuZW5hYmxlKXtcbiAgICAgICAgICBwSlMuZm4ucGFydGljbGVzRHJhdygpO1xuICAgICAgICB9XG4gICAgICAgIHBKUy50bXAucHVzaGluZyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLm1vZGVzLnJlbW92ZVBhcnRpY2xlcyA9IGZ1bmN0aW9uKG5iKXtcblxuICAgIHBKUy5wYXJ0aWNsZXMuYXJyYXkuc3BsaWNlKDAsIG5iKTtcbiAgICBpZighcEpTLnBhcnRpY2xlcy5tb3ZlLmVuYWJsZSl7XG4gICAgICBwSlMuZm4ucGFydGljbGVzRHJhdygpO1xuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLm1vZGVzLmJ1YmJsZVBhcnRpY2xlID0gZnVuY3Rpb24ocCl7XG5cbiAgICAvKiBvbiBob3ZlciBldmVudCAqL1xuICAgIGlmKHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLmVuYWJsZSAmJiBpc0luQXJyYXkoJ2J1YmJsZScsIHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLm1vZGUpKXtcblxuICAgICAgdmFyIGR4X21vdXNlID0gcC54IC0gcEpTLmludGVyYWN0aXZpdHkubW91c2UucG9zX3gsXG4gICAgICAgICAgZHlfbW91c2UgPSBwLnkgLSBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeSxcbiAgICAgICAgICBkaXN0X21vdXNlID0gTWF0aC5zcXJ0KGR4X21vdXNlKmR4X21vdXNlICsgZHlfbW91c2UqZHlfbW91c2UpLFxuICAgICAgICAgIHJhdGlvID0gMSAtIGRpc3RfbW91c2UgLyBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuZGlzdGFuY2U7XG5cbiAgICAgIGZ1bmN0aW9uIGluaXQoKXtcbiAgICAgICAgcC5vcGFjaXR5X2J1YmJsZSA9IHAub3BhY2l0eTtcbiAgICAgICAgcC5yYWRpdXNfYnViYmxlID0gcC5yYWRpdXM7XG4gICAgICB9XG5cbiAgICAgIC8qIG1vdXNlbW92ZSAtIGNoZWNrIHJhdGlvICovXG4gICAgICBpZihkaXN0X21vdXNlIDw9IHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5kaXN0YW5jZSl7XG5cbiAgICAgICAgaWYocmF0aW8gPj0gMCAmJiBwSlMuaW50ZXJhY3Rpdml0eS5zdGF0dXMgPT0gJ21vdXNlbW92ZScpe1xuICAgICAgICAgIFxuICAgICAgICAgIC8qIHNpemUgKi9cbiAgICAgICAgICBpZihwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuc2l6ZSAhPSBwSlMucGFydGljbGVzLnNpemUudmFsdWUpe1xuXG4gICAgICAgICAgICBpZihwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuc2l6ZSA+IHBKUy5wYXJ0aWNsZXMuc2l6ZS52YWx1ZSl7XG4gICAgICAgICAgICAgIHZhciBzaXplID0gcC5yYWRpdXMgKyAocEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLnNpemUqcmF0aW8pO1xuICAgICAgICAgICAgICBpZihzaXplID49IDApe1xuICAgICAgICAgICAgICAgIHAucmFkaXVzX2J1YmJsZSA9IHNpemU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICB2YXIgZGlmID0gcC5yYWRpdXMgLSBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuc2l6ZSxcbiAgICAgICAgICAgICAgICAgIHNpemUgPSBwLnJhZGl1cyAtIChkaWYqcmF0aW8pO1xuICAgICAgICAgICAgICBpZihzaXplID4gMCl7XG4gICAgICAgICAgICAgICAgcC5yYWRpdXNfYnViYmxlID0gc2l6ZTtcbiAgICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgcC5yYWRpdXNfYnViYmxlID0gMDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLyogb3BhY2l0eSAqL1xuICAgICAgICAgIGlmKHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5vcGFjaXR5ICE9IHBKUy5wYXJ0aWNsZXMub3BhY2l0eS52YWx1ZSl7XG5cbiAgICAgICAgICAgIGlmKHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5vcGFjaXR5ID4gcEpTLnBhcnRpY2xlcy5vcGFjaXR5LnZhbHVlKXtcbiAgICAgICAgICAgICAgdmFyIG9wYWNpdHkgPSBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUub3BhY2l0eSpyYXRpbztcbiAgICAgICAgICAgICAgaWYob3BhY2l0eSA+IHAub3BhY2l0eSAmJiBvcGFjaXR5IDw9IHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5vcGFjaXR5KXtcbiAgICAgICAgICAgICAgICBwLm9wYWNpdHlfYnViYmxlID0gb3BhY2l0eTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gcC5vcGFjaXR5IC0gKHBKUy5wYXJ0aWNsZXMub3BhY2l0eS52YWx1ZS1wSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUub3BhY2l0eSkqcmF0aW87XG4gICAgICAgICAgICAgIGlmKG9wYWNpdHkgPCBwLm9wYWNpdHkgJiYgb3BhY2l0eSA+PSBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUub3BhY2l0eSl7XG4gICAgICAgICAgICAgICAgcC5vcGFjaXR5X2J1YmJsZSA9IG9wYWNpdHk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIH1cblxuICAgICAgICB9XG5cbiAgICAgIH1lbHNle1xuICAgICAgICBpbml0KCk7XG4gICAgICB9XG5cblxuICAgICAgLyogbW91c2VsZWF2ZSAqL1xuICAgICAgaWYocEpTLmludGVyYWN0aXZpdHkuc3RhdHVzID09ICdtb3VzZWxlYXZlJyl7XG4gICAgICAgIGluaXQoKTtcbiAgICAgIH1cbiAgICBcbiAgICB9XG5cbiAgICAvKiBvbiBjbGljayBldmVudCAqL1xuICAgIGVsc2UgaWYocEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2suZW5hYmxlICYmIGlzSW5BcnJheSgnYnViYmxlJywgcEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2subW9kZSkpe1xuXG5cbiAgICAgIGlmKHBKUy50bXAuYnViYmxlX2NsaWNraW5nKXtcbiAgICAgICAgdmFyIGR4X21vdXNlID0gcC54IC0gcEpTLmludGVyYWN0aXZpdHkubW91c2UuY2xpY2tfcG9zX3gsXG4gICAgICAgICAgICBkeV9tb3VzZSA9IHAueSAtIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLmNsaWNrX3Bvc195LFxuICAgICAgICAgICAgZGlzdF9tb3VzZSA9IE1hdGguc3FydChkeF9tb3VzZSpkeF9tb3VzZSArIGR5X21vdXNlKmR5X21vdXNlKSxcbiAgICAgICAgICAgIHRpbWVfc3BlbnQgPSAobmV3IERhdGUoKS5nZXRUaW1lKCkgLSBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5jbGlja190aW1lKS8xMDAwO1xuXG4gICAgICAgIGlmKHRpbWVfc3BlbnQgPiBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuZHVyYXRpb24pe1xuICAgICAgICAgIHBKUy50bXAuYnViYmxlX2R1cmF0aW9uX2VuZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aW1lX3NwZW50ID4gcEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLmR1cmF0aW9uKjIpe1xuICAgICAgICAgIHBKUy50bXAuYnViYmxlX2NsaWNraW5nID0gZmFsc2U7XG4gICAgICAgICAgcEpTLnRtcC5idWJibGVfZHVyYXRpb25fZW5kID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuXG4gICAgICBmdW5jdGlvbiBwcm9jZXNzKGJ1YmJsZV9wYXJhbSwgcGFydGljbGVzX3BhcmFtLCBwX29ial9idWJibGUsIHBfb2JqLCBpZCl7XG5cbiAgICAgICAgaWYoYnViYmxlX3BhcmFtICE9IHBhcnRpY2xlc19wYXJhbSl7XG5cbiAgICAgICAgICBpZighcEpTLnRtcC5idWJibGVfZHVyYXRpb25fZW5kKXtcbiAgICAgICAgICAgIGlmKGRpc3RfbW91c2UgPD0gcEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLmRpc3RhbmNlKXtcbiAgICAgICAgICAgICAgaWYocF9vYmpfYnViYmxlICE9IHVuZGVmaW5lZCkgdmFyIG9iaiA9IHBfb2JqX2J1YmJsZTtcbiAgICAgICAgICAgICAgZWxzZSB2YXIgb2JqID0gcF9vYmo7XG4gICAgICAgICAgICAgIGlmKG9iaiAhPSBidWJibGVfcGFyYW0pe1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHBfb2JqIC0gKHRpbWVfc3BlbnQgKiAocF9vYmogLSBidWJibGVfcGFyYW0pIC8gcEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLmR1cmF0aW9uKTtcbiAgICAgICAgICAgICAgICBpZihpZCA9PSAnc2l6ZScpIHAucmFkaXVzX2J1YmJsZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmKGlkID09ICdvcGFjaXR5JykgcC5vcGFjaXR5X2J1YmJsZSA9IHZhbHVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICAgaWYoaWQgPT0gJ3NpemUnKSBwLnJhZGl1c19idWJibGUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgIGlmKGlkID09ICdvcGFjaXR5JykgcC5vcGFjaXR5X2J1YmJsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgIGlmKHBfb2JqX2J1YmJsZSAhPSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICB2YXIgdmFsdWVfdG1wID0gcF9vYmogLSAodGltZV9zcGVudCAqIChwX29iaiAtIGJ1YmJsZV9wYXJhbSkgLyBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5idWJibGUuZHVyYXRpb24pLFxuICAgICAgICAgICAgICAgICAgZGlmID0gYnViYmxlX3BhcmFtIC0gdmFsdWVfdG1wO1xuICAgICAgICAgICAgICAgICAgdmFsdWUgPSBidWJibGVfcGFyYW0gKyBkaWY7XG4gICAgICAgICAgICAgIGlmKGlkID09ICdzaXplJykgcC5yYWRpdXNfYnViYmxlID0gdmFsdWU7XG4gICAgICAgICAgICAgIGlmKGlkID09ICdvcGFjaXR5JykgcC5vcGFjaXR5X2J1YmJsZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICB9XG5cbiAgICAgIH1cblxuICAgICAgaWYocEpTLnRtcC5idWJibGVfY2xpY2tpbmcpe1xuICAgICAgICAvKiBzaXplICovXG4gICAgICAgIHByb2Nlc3MocEpTLmludGVyYWN0aXZpdHkubW9kZXMuYnViYmxlLnNpemUsIHBKUy5wYXJ0aWNsZXMuc2l6ZS52YWx1ZSwgcC5yYWRpdXNfYnViYmxlLCBwLnJhZGl1cywgJ3NpemUnKTtcbiAgICAgICAgLyogb3BhY2l0eSAqL1xuICAgICAgICBwcm9jZXNzKHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmJ1YmJsZS5vcGFjaXR5LCBwSlMucGFydGljbGVzLm9wYWNpdHkudmFsdWUsIHAub3BhY2l0eV9idWJibGUsIHAub3BhY2l0eSwgJ29wYWNpdHknKTtcbiAgICAgIH1cblxuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLm1vZGVzLnJlcHVsc2VQYXJ0aWNsZSA9IGZ1bmN0aW9uKHApe1xuXG4gICAgaWYocEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uaG92ZXIuZW5hYmxlICYmIGlzSW5BcnJheSgncmVwdWxzZScsIHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLm1vZGUpICYmIHBKUy5pbnRlcmFjdGl2aXR5LnN0YXR1cyA9PSAnbW91c2Vtb3ZlJykge1xuXG4gICAgICB2YXIgZHhfbW91c2UgPSBwLnggLSBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeCxcbiAgICAgICAgICBkeV9tb3VzZSA9IHAueSAtIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLnBvc195LFxuICAgICAgICAgIGRpc3RfbW91c2UgPSBNYXRoLnNxcnQoZHhfbW91c2UqZHhfbW91c2UgKyBkeV9tb3VzZSpkeV9tb3VzZSk7XG5cbiAgICAgIHZhciBub3JtVmVjID0ge3g6IGR4X21vdXNlL2Rpc3RfbW91c2UsIHk6IGR5X21vdXNlL2Rpc3RfbW91c2V9LFxuICAgICAgICAgIHJlcHVsc2VSYWRpdXMgPSBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5yZXB1bHNlLmRpc3RhbmNlLFxuICAgICAgICAgIHZlbG9jaXR5ID0gMTAwLFxuICAgICAgICAgIHJlcHVsc2VGYWN0b3IgPSBjbGFtcCgoMS9yZXB1bHNlUmFkaXVzKSooLTEqTWF0aC5wb3coZGlzdF9tb3VzZS9yZXB1bHNlUmFkaXVzLDIpKzEpKnJlcHVsc2VSYWRpdXMqdmVsb2NpdHksIDAsIDUwKTtcbiAgICAgIFxuICAgICAgdmFyIHBvcyA9IHtcbiAgICAgICAgeDogcC54ICsgbm9ybVZlYy54ICogcmVwdWxzZUZhY3RvcixcbiAgICAgICAgeTogcC55ICsgbm9ybVZlYy55ICogcmVwdWxzZUZhY3RvclxuICAgICAgfVxuXG4gICAgICBpZihwSlMucGFydGljbGVzLm1vdmUub3V0X21vZGUgPT0gJ2JvdW5jZScpe1xuICAgICAgICBpZihwb3MueCAtIHAucmFkaXVzID4gMCAmJiBwb3MueCArIHAucmFkaXVzIDwgcEpTLmNhbnZhcy53KSBwLnggPSBwb3MueDtcbiAgICAgICAgaWYocG9zLnkgLSBwLnJhZGl1cyA+IDAgJiYgcG9zLnkgKyBwLnJhZGl1cyA8IHBKUy5jYW52YXMuaCkgcC55ID0gcG9zLnk7XG4gICAgICB9ZWxzZXtcbiAgICAgICAgcC54ID0gcG9zLng7XG4gICAgICAgIHAueSA9IHBvcy55O1xuICAgICAgfVxuICAgIFxuICAgIH1cblxuXG4gICAgZWxzZSBpZihwSlMuaW50ZXJhY3Rpdml0eS5ldmVudHMub25jbGljay5lbmFibGUgJiYgaXNJbkFycmF5KCdyZXB1bHNlJywgcEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2subW9kZSkpIHtcblxuICAgICAgaWYoIXBKUy50bXAucmVwdWxzZV9maW5pc2gpe1xuICAgICAgICBwSlMudG1wLnJlcHVsc2VfY291bnQrKztcbiAgICAgICAgaWYocEpTLnRtcC5yZXB1bHNlX2NvdW50ID09IHBKUy5wYXJ0aWNsZXMuYXJyYXkubGVuZ3RoKXtcbiAgICAgICAgICBwSlMudG1wLnJlcHVsc2VfZmluaXNoID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihwSlMudG1wLnJlcHVsc2VfY2xpY2tpbmcpe1xuXG4gICAgICAgIHZhciByZXB1bHNlUmFkaXVzID0gTWF0aC5wb3cocEpTLmludGVyYWN0aXZpdHkubW9kZXMucmVwdWxzZS5kaXN0YW5jZS82LCAzKTtcblxuICAgICAgICB2YXIgZHggPSBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5jbGlja19wb3NfeCAtIHAueCxcbiAgICAgICAgICAgIGR5ID0gcEpTLmludGVyYWN0aXZpdHkubW91c2UuY2xpY2tfcG9zX3kgLSBwLnksXG4gICAgICAgICAgICBkID0gZHgqZHggKyBkeSpkeTtcblxuICAgICAgICB2YXIgZm9yY2UgPSAtcmVwdWxzZVJhZGl1cyAvIGQgKiAxO1xuXG4gICAgICAgIGZ1bmN0aW9uIHByb2Nlc3MoKXtcblxuICAgICAgICAgIHZhciBmID0gTWF0aC5hdGFuMihkeSxkeCk7XG4gICAgICAgICAgcC52eCA9IGZvcmNlICogTWF0aC5jb3MoZik7XG4gICAgICAgICAgcC52eSA9IGZvcmNlICogTWF0aC5zaW4oZik7XG5cbiAgICAgICAgICBpZihwSlMucGFydGljbGVzLm1vdmUub3V0X21vZGUgPT0gJ2JvdW5jZScpe1xuICAgICAgICAgICAgdmFyIHBvcyA9IHtcbiAgICAgICAgICAgICAgeDogcC54ICsgcC52eCxcbiAgICAgICAgICAgICAgeTogcC55ICsgcC52eVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBvcy54ICsgcC5yYWRpdXMgPiBwSlMuY2FudmFzLncpIHAudnggPSAtcC52eDtcbiAgICAgICAgICAgIGVsc2UgaWYgKHBvcy54IC0gcC5yYWRpdXMgPCAwKSBwLnZ4ID0gLXAudng7XG4gICAgICAgICAgICBpZiAocG9zLnkgKyBwLnJhZGl1cyA+IHBKUy5jYW52YXMuaCkgcC52eSA9IC1wLnZ5O1xuICAgICAgICAgICAgZWxzZSBpZiAocG9zLnkgLSBwLnJhZGl1cyA8IDApIHAudnkgPSAtcC52eTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRlZmF1bHRcbiAgICAgICAgaWYoZCA8PSByZXB1bHNlUmFkaXVzKXtcbiAgICAgICAgICBwcm9jZXNzKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBiYW5nIC0gc2xvdyBtb3Rpb24gbW9kZVxuICAgICAgICAvLyBpZighcEpTLnRtcC5yZXB1bHNlX2ZpbmlzaCl7XG4gICAgICAgIC8vICAgaWYoZCA8PSByZXB1bHNlUmFkaXVzKXtcbiAgICAgICAgLy8gICAgIHByb2Nlc3MoKTtcbiAgICAgICAgLy8gICB9XG4gICAgICAgIC8vIH1lbHNle1xuICAgICAgICAvLyAgIHByb2Nlc3MoKTtcbiAgICAgICAgLy8gfVxuICAgICAgICBcblxuICAgICAgfWVsc2V7XG5cbiAgICAgICAgaWYocEpTLnRtcC5yZXB1bHNlX2NsaWNraW5nID09IGZhbHNlKXtcblxuICAgICAgICAgIHAudnggPSBwLnZ4X2k7XG4gICAgICAgICAgcC52eSA9IHAudnlfaTtcbiAgICAgICAgXG4gICAgICAgIH1cblxuICAgICAgfVxuXG4gICAgfVxuXG4gIH1cblxuXG4gIHBKUy5mbi5tb2Rlcy5ncmFiUGFydGljbGUgPSBmdW5jdGlvbihwKXtcblxuICAgIGlmKHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmhvdmVyLmVuYWJsZSAmJiBwSlMuaW50ZXJhY3Rpdml0eS5zdGF0dXMgPT0gJ21vdXNlbW92ZScpe1xuXG4gICAgICB2YXIgZHhfbW91c2UgPSBwLnggLSBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeCxcbiAgICAgICAgICBkeV9tb3VzZSA9IHAueSAtIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLnBvc195LFxuICAgICAgICAgIGRpc3RfbW91c2UgPSBNYXRoLnNxcnQoZHhfbW91c2UqZHhfbW91c2UgKyBkeV9tb3VzZSpkeV9tb3VzZSk7XG5cbiAgICAgIC8qIGRyYXcgYSBsaW5lIGJldHdlZW4gdGhlIGN1cnNvciBhbmQgdGhlIHBhcnRpY2xlIGlmIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZW0gaXMgdW5kZXIgdGhlIGNvbmZpZyBkaXN0YW5jZSAqL1xuICAgICAgaWYoZGlzdF9tb3VzZSA8PSBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5ncmFiLmRpc3RhbmNlKXtcblxuICAgICAgICB2YXIgb3BhY2l0eV9saW5lID0gcEpTLmludGVyYWN0aXZpdHkubW9kZXMuZ3JhYi5saW5lX2xpbmtlZC5vcGFjaXR5IC0gKGRpc3RfbW91c2UgLyAoMS9wSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5ncmFiLmxpbmVfbGlua2VkLm9wYWNpdHkpKSAvIHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLmdyYWIuZGlzdGFuY2U7XG5cbiAgICAgICAgaWYob3BhY2l0eV9saW5lID4gMCl7XG5cbiAgICAgICAgICAvKiBzdHlsZSAqL1xuICAgICAgICAgIHZhciBjb2xvcl9saW5lID0gcEpTLnBhcnRpY2xlcy5saW5lX2xpbmtlZC5jb2xvcl9yZ2JfbGluZTtcbiAgICAgICAgICBwSlMuY2FudmFzLmN0eC5zdHJva2VTdHlsZSA9ICdyZ2JhKCcrY29sb3JfbGluZS5yKycsJytjb2xvcl9saW5lLmcrJywnK2NvbG9yX2xpbmUuYisnLCcrb3BhY2l0eV9saW5lKycpJztcbiAgICAgICAgICBwSlMuY2FudmFzLmN0eC5saW5lV2lkdGggPSBwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLndpZHRoO1xuICAgICAgICAgIC8vcEpTLmNhbnZhcy5jdHgubGluZUNhcCA9ICdyb3VuZCc7IC8qIHBlcmZvcm1hbmNlIGlzc3VlICovXG4gICAgICAgICAgXG4gICAgICAgICAgLyogcGF0aCAqL1xuICAgICAgICAgIHBKUy5jYW52YXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgIHBKUy5jYW52YXMuY3R4Lm1vdmVUbyhwLngsIHAueSk7XG4gICAgICAgICAgcEpTLmNhbnZhcy5jdHgubGluZVRvKHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLnBvc194LCBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeSk7XG4gICAgICAgICAgcEpTLmNhbnZhcy5jdHguc3Ryb2tlKCk7XG4gICAgICAgICAgcEpTLmNhbnZhcy5jdHguY2xvc2VQYXRoKCk7XG5cbiAgICAgICAgfVxuXG4gICAgICB9XG5cbiAgICB9XG5cbiAgfTtcblxuXG5cbiAgLyogLS0tLS0tLS0tLSBwSlMgZnVuY3Rpb25zIC0gdmVuZG9ycyAtLS0tLS0tLS0tLS0gKi9cblxuICBwSlMuZm4udmVuZG9ycy5ldmVudHNMaXN0ZW5lcnMgPSBmdW5jdGlvbigpe1xuXG4gICAgLyogZXZlbnRzIHRhcmdldCBlbGVtZW50ICovXG4gICAgaWYocEpTLmludGVyYWN0aXZpdHkuZGV0ZWN0X29uID09ICd3aW5kb3cnKXtcbiAgICAgIHBKUy5pbnRlcmFjdGl2aXR5LmVsID0gd2luZG93O1xuICAgIH1lbHNle1xuICAgICAgcEpTLmludGVyYWN0aXZpdHkuZWwgPSBwSlMuY2FudmFzLmVsO1xuICAgIH1cblxuXG4gICAgLyogZGV0ZWN0IG1vdXNlIHBvcyAtIG9uIGhvdmVyIC8gY2xpY2sgZXZlbnQgKi9cbiAgICBpZihwSlMuaW50ZXJhY3Rpdml0eS5ldmVudHMub25ob3Zlci5lbmFibGUgfHwgcEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2suZW5hYmxlKXtcblxuICAgICAgLyogZWwgb24gbW91c2Vtb3ZlICovXG4gICAgICBwSlMuaW50ZXJhY3Rpdml0eS5lbC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKXtcblxuICAgICAgICBpZihwSlMuaW50ZXJhY3Rpdml0eS5lbCA9PSB3aW5kb3cpe1xuICAgICAgICAgIHZhciBwb3NfeCA9IGUuY2xpZW50WCxcbiAgICAgICAgICAgICAgcG9zX3kgPSBlLmNsaWVudFk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICB2YXIgcG9zX3ggPSBlLm9mZnNldFggfHwgZS5jbGllbnRYLFxuICAgICAgICAgICAgICBwb3NfeSA9IGUub2Zmc2V0WSB8fCBlLmNsaWVudFk7XG4gICAgICAgIH1cblxuICAgICAgICBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeCA9IHBvc194O1xuICAgICAgICBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeSA9IHBvc195O1xuXG4gICAgICAgIGlmKHBKUy50bXAucmV0aW5hKXtcbiAgICAgICAgICBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeCAqPSBwSlMuY2FudmFzLnB4cmF0aW87XG4gICAgICAgICAgcEpTLmludGVyYWN0aXZpdHkubW91c2UucG9zX3kgKj0gcEpTLmNhbnZhcy5weHJhdGlvO1xuICAgICAgICB9XG5cbiAgICAgICAgcEpTLmludGVyYWN0aXZpdHkuc3RhdHVzID0gJ21vdXNlbW92ZSc7XG5cbiAgICAgIH0pO1xuXG4gICAgICAvKiBlbCBvbiBvbm1vdXNlbGVhdmUgKi9cbiAgICAgIHBKUy5pbnRlcmFjdGl2aXR5LmVsLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBmdW5jdGlvbihlKXtcblxuICAgICAgICBwSlMuaW50ZXJhY3Rpdml0eS5tb3VzZS5wb3NfeCA9IG51bGw7XG4gICAgICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLnBvc195ID0gbnVsbDtcbiAgICAgICAgcEpTLmludGVyYWN0aXZpdHkuc3RhdHVzID0gJ21vdXNlbGVhdmUnO1xuXG4gICAgICB9KTtcblxuICAgIH1cblxuICAgIC8qIG9uIGNsaWNrIGV2ZW50ICovXG4gICAgaWYocEpTLmludGVyYWN0aXZpdHkuZXZlbnRzLm9uY2xpY2suZW5hYmxlKXtcblxuICAgICAgcEpTLmludGVyYWN0aXZpdHkuZWwuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbigpe1xuXG4gICAgICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLmNsaWNrX3Bvc194ID0gcEpTLmludGVyYWN0aXZpdHkubW91c2UucG9zX3g7XG4gICAgICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLmNsaWNrX3Bvc195ID0gcEpTLmludGVyYWN0aXZpdHkubW91c2UucG9zX3k7XG4gICAgICAgIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlLmNsaWNrX3RpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuICAgICAgICBpZihwSlMuaW50ZXJhY3Rpdml0eS5ldmVudHMub25jbGljay5lbmFibGUpe1xuXG4gICAgICAgICAgc3dpdGNoKHBKUy5pbnRlcmFjdGl2aXR5LmV2ZW50cy5vbmNsaWNrLm1vZGUpe1xuXG4gICAgICAgICAgICBjYXNlICdwdXNoJzpcbiAgICAgICAgICAgICAgaWYocEpTLnBhcnRpY2xlcy5tb3ZlLmVuYWJsZSl7XG4gICAgICAgICAgICAgICAgcEpTLmZuLm1vZGVzLnB1c2hQYXJ0aWNsZXMocEpTLmludGVyYWN0aXZpdHkubW9kZXMucHVzaC5wYXJ0aWNsZXNfbmIsIHBKUy5pbnRlcmFjdGl2aXR5Lm1vdXNlKTtcbiAgICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgaWYocEpTLmludGVyYWN0aXZpdHkubW9kZXMucHVzaC5wYXJ0aWNsZXNfbmIgPT0gMSl7XG4gICAgICAgICAgICAgICAgICBwSlMuZm4ubW9kZXMucHVzaFBhcnRpY2xlcyhwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5wdXNoLnBhcnRpY2xlc19uYiwgcEpTLmludGVyYWN0aXZpdHkubW91c2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKHBKUy5pbnRlcmFjdGl2aXR5Lm1vZGVzLnB1c2gucGFydGljbGVzX25iID4gMSl7XG4gICAgICAgICAgICAgICAgICBwSlMuZm4ubW9kZXMucHVzaFBhcnRpY2xlcyhwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5wdXNoLnBhcnRpY2xlc19uYik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAncmVtb3ZlJzpcbiAgICAgICAgICAgICAgcEpTLmZuLm1vZGVzLnJlbW92ZVBhcnRpY2xlcyhwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5yZW1vdmUucGFydGljbGVzX25iKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlICdidWJibGUnOlxuICAgICAgICAgICAgICBwSlMudG1wLmJ1YmJsZV9jbGlja2luZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSAncmVwdWxzZSc6XG4gICAgICAgICAgICAgIHBKUy50bXAucmVwdWxzZV9jbGlja2luZyA9IHRydWU7XG4gICAgICAgICAgICAgIHBKUy50bXAucmVwdWxzZV9jb3VudCA9IDA7XG4gICAgICAgICAgICAgIHBKUy50bXAucmVwdWxzZV9maW5pc2ggPSBmYWxzZTtcbiAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgIHBKUy50bXAucmVwdWxzZV9jbGlja2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgICB9LCBwSlMuaW50ZXJhY3Rpdml0eS5tb2Rlcy5yZXB1bHNlLmR1cmF0aW9uKjEwMDApXG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIH1cblxuICAgICAgICB9XG5cbiAgICAgIH0pO1xuICAgICAgICBcbiAgICB9XG5cblxuICB9O1xuXG4gIHBKUy5mbi52ZW5kb3JzLmRlbnNpdHlBdXRvUGFydGljbGVzID0gZnVuY3Rpb24oKXtcblxuICAgIGlmKHBKUy5wYXJ0aWNsZXMubnVtYmVyLmRlbnNpdHkuZW5hYmxlKXtcblxuICAgICAgLyogY2FsYyBhcmVhICovXG4gICAgICB2YXIgYXJlYSA9IHBKUy5jYW52YXMuZWwud2lkdGggKiBwSlMuY2FudmFzLmVsLmhlaWdodCAvIDEwMDA7XG4gICAgICBpZihwSlMudG1wLnJldGluYSl7XG4gICAgICAgIGFyZWEgPSBhcmVhLyhwSlMuY2FudmFzLnB4cmF0aW8qMik7XG4gICAgICB9XG5cbiAgICAgIC8qIGNhbGMgbnVtYmVyIG9mIHBhcnRpY2xlcyBiYXNlZCBvbiBkZW5zaXR5IGFyZWEgKi9cbiAgICAgIHZhciBuYl9wYXJ0aWNsZXMgPSBhcmVhICogcEpTLnBhcnRpY2xlcy5udW1iZXIudmFsdWUgLyBwSlMucGFydGljbGVzLm51bWJlci5kZW5zaXR5LnZhbHVlX2FyZWE7XG5cbiAgICAgIC8qIGFkZCBvciByZW1vdmUgWCBwYXJ0aWNsZXMgKi9cbiAgICAgIHZhciBtaXNzaW5nX3BhcnRpY2xlcyA9IHBKUy5wYXJ0aWNsZXMuYXJyYXkubGVuZ3RoIC0gbmJfcGFydGljbGVzO1xuICAgICAgaWYobWlzc2luZ19wYXJ0aWNsZXMgPCAwKSBwSlMuZm4ubW9kZXMucHVzaFBhcnRpY2xlcyhNYXRoLmFicyhtaXNzaW5nX3BhcnRpY2xlcykpO1xuICAgICAgZWxzZSBwSlMuZm4ubW9kZXMucmVtb3ZlUGFydGljbGVzKG1pc3NpbmdfcGFydGljbGVzKTtcblxuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMuY2hlY2tPdmVybGFwID0gZnVuY3Rpb24ocDEsIHBvc2l0aW9uKXtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcEpTLnBhcnRpY2xlcy5hcnJheS5sZW5ndGg7IGkrKyl7XG4gICAgICB2YXIgcDIgPSBwSlMucGFydGljbGVzLmFycmF5W2ldO1xuXG4gICAgICB2YXIgZHggPSBwMS54IC0gcDIueCxcbiAgICAgICAgICBkeSA9IHAxLnkgLSBwMi55LFxuICAgICAgICAgIGRpc3QgPSBNYXRoLnNxcnQoZHgqZHggKyBkeSpkeSk7XG5cbiAgICAgIGlmKGRpc3QgPD0gcDEucmFkaXVzICsgcDIucmFkaXVzKXtcbiAgICAgICAgcDEueCA9IHBvc2l0aW9uID8gcG9zaXRpb24ueCA6IE1hdGgucmFuZG9tKCkgKiBwSlMuY2FudmFzLnc7XG4gICAgICAgIHAxLnkgPSBwb3NpdGlvbiA/IHBvc2l0aW9uLnkgOiBNYXRoLnJhbmRvbSgpICogcEpTLmNhbnZhcy5oO1xuICAgICAgICBwSlMuZm4udmVuZG9ycy5jaGVja092ZXJsYXAocDEpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuXG4gIHBKUy5mbi52ZW5kb3JzLmNyZWF0ZVN2Z0ltZyA9IGZ1bmN0aW9uKHApe1xuXG4gICAgLyogc2V0IGNvbG9yIHRvIHN2ZyBlbGVtZW50ICovXG4gICAgdmFyIHN2Z1htbCA9IHBKUy50bXAuc291cmNlX3N2ZyxcbiAgICAgICAgcmdiSGV4ID0gLyMoWzAtOUEtRl17Myw2fSkvZ2ksXG4gICAgICAgIGNvbG9yZWRTdmdYbWwgPSBzdmdYbWwucmVwbGFjZShyZ2JIZXgsIGZ1bmN0aW9uIChtLCByLCBnLCBiKSB7XG4gICAgICAgICAgaWYocC5jb2xvci5yZ2Ipe1xuICAgICAgICAgICAgdmFyIGNvbG9yX3ZhbHVlID0gJ3JnYmEoJytwLmNvbG9yLnJnYi5yKycsJytwLmNvbG9yLnJnYi5nKycsJytwLmNvbG9yLnJnYi5iKycsJytwLm9wYWNpdHkrJyknO1xuICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgdmFyIGNvbG9yX3ZhbHVlID0gJ2hzbGEoJytwLmNvbG9yLmhzbC5oKycsJytwLmNvbG9yLmhzbC5zKyclLCcrcC5jb2xvci5oc2wubCsnJSwnK3Aub3BhY2l0eSsnKSc7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBjb2xvcl92YWx1ZTtcbiAgICAgICAgfSk7XG5cbiAgICAvKiBwcmVwYXJlIHRvIGNyZWF0ZSBpbWcgd2l0aCBjb2xvcmVkIHN2ZyAqL1xuICAgIHZhciBzdmcgPSBuZXcgQmxvYihbY29sb3JlZFN2Z1htbF0sIHt0eXBlOiAnaW1hZ2Uvc3ZnK3htbDtjaGFyc2V0PXV0Zi04J30pLFxuICAgICAgICBET01VUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkwgfHwgd2luZG93LFxuICAgICAgICB1cmwgPSBET01VUkwuY3JlYXRlT2JqZWN0VVJMKHN2Zyk7XG5cbiAgICAvKiBjcmVhdGUgcGFydGljbGUgaW1nIG9iaiAqL1xuICAgIHZhciBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICBpbWcuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGZ1bmN0aW9uKCl7XG4gICAgICBwLmltZy5vYmogPSBpbWc7XG4gICAgICBwLmltZy5sb2FkZWQgPSB0cnVlO1xuICAgICAgRE9NVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuICAgICAgcEpTLnRtcC5jb3VudF9zdmcrKztcbiAgICB9KTtcbiAgICBpbWcuc3JjID0gdXJsO1xuXG4gIH07XG5cblxuICBwSlMuZm4udmVuZG9ycy5kZXN0cm95cEpTID0gZnVuY3Rpb24oKXtcbiAgICBjYW5jZWxBbmltYXRpb25GcmFtZShwSlMuZm4uZHJhd0FuaW1GcmFtZSk7XG4gICAgY2FudmFzX2VsLnJlbW92ZSgpO1xuICAgIHBKU0RvbSA9IG51bGw7XG4gIH07XG5cblxuICBwSlMuZm4udmVuZG9ycy5kcmF3U2hhcGUgPSBmdW5jdGlvbihjLCBzdGFydFgsIHN0YXJ0WSwgc2lkZUxlbmd0aCwgc2lkZUNvdW50TnVtZXJhdG9yLCBzaWRlQ291bnREZW5vbWluYXRvcil7XG5cbiAgICAvLyBCeSBQcm9ncmFtbWluZyBUaG9tYXMgLSBodHRwczovL3Byb2dyYW1taW5ndGhvbWFzLndvcmRwcmVzcy5jb20vMjAxMy8wNC8wMy9uLXNpZGVkLXNoYXBlcy9cbiAgICB2YXIgc2lkZUNvdW50ID0gc2lkZUNvdW50TnVtZXJhdG9yICogc2lkZUNvdW50RGVub21pbmF0b3I7XG4gICAgdmFyIGRlY2ltYWxTaWRlcyA9IHNpZGVDb3VudE51bWVyYXRvciAvIHNpZGVDb3VudERlbm9taW5hdG9yO1xuICAgIHZhciBpbnRlcmlvckFuZ2xlRGVncmVlcyA9ICgxODAgKiAoZGVjaW1hbFNpZGVzIC0gMikpIC8gZGVjaW1hbFNpZGVzO1xuICAgIHZhciBpbnRlcmlvckFuZ2xlID0gTWF0aC5QSSAtIE1hdGguUEkgKiBpbnRlcmlvckFuZ2xlRGVncmVlcyAvIDE4MDsgLy8gY29udmVydCB0byByYWRpYW5zXG4gICAgYy5zYXZlKCk7XG4gICAgYy5iZWdpblBhdGgoKTtcbiAgICBjLnRyYW5zbGF0ZShzdGFydFgsIHN0YXJ0WSk7XG4gICAgYy5tb3ZlVG8oMCwwKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpZGVDb3VudDsgaSsrKSB7XG4gICAgICBjLmxpbmVUbyhzaWRlTGVuZ3RoLDApO1xuICAgICAgYy50cmFuc2xhdGUoc2lkZUxlbmd0aCwwKTtcbiAgICAgIGMucm90YXRlKGludGVyaW9yQW5nbGUpO1xuICAgIH1cbiAgICAvL2Muc3Ryb2tlKCk7XG4gICAgYy5maWxsKCk7XG4gICAgYy5yZXN0b3JlKCk7XG5cbiAgfTtcblxuICBwSlMuZm4udmVuZG9ycy5leHBvcnRJbWcgPSBmdW5jdGlvbigpe1xuICAgIHdpbmRvdy5vcGVuKHBKUy5jYW52YXMuZWwudG9EYXRhVVJMKCdpbWFnZS9wbmcnKSwgJ19ibGFuaycpO1xuICB9O1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMubG9hZEltZyA9IGZ1bmN0aW9uKHR5cGUpe1xuXG4gICAgcEpTLnRtcC5pbWdfZXJyb3IgPSB1bmRlZmluZWQ7XG5cbiAgICBpZihwSlMucGFydGljbGVzLnNoYXBlLmltYWdlLnNyYyAhPSAnJyl7XG5cbiAgICAgIGlmKHR5cGUgPT0gJ3N2Zycpe1xuXG4gICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgeGhyLm9wZW4oJ0dFVCcsIHBKUy5wYXJ0aWNsZXMuc2hhcGUuaW1hZ2Uuc3JjKTtcbiAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgaWYoeGhyLnJlYWR5U3RhdGUgPT0gNCl7XG4gICAgICAgICAgICBpZih4aHIuc3RhdHVzID09IDIwMCl7XG4gICAgICAgICAgICAgIHBKUy50bXAuc291cmNlX3N2ZyA9IGRhdGEuY3VycmVudFRhcmdldC5yZXNwb25zZTtcbiAgICAgICAgICAgICAgcEpTLmZuLnZlbmRvcnMuY2hlY2tCZWZvcmVEcmF3KCk7XG4gICAgICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0Vycm9yIHBKUyAtIEltYWdlIG5vdCBmb3VuZCcpO1xuICAgICAgICAgICAgICBwSlMudG1wLmltZ19lcnJvciA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHhoci5zZW5kKCk7XG5cbiAgICAgIH1lbHNle1xuXG4gICAgICAgIHZhciBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgaW1nLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbigpe1xuICAgICAgICAgIHBKUy50bXAuaW1nX29iaiA9IGltZztcbiAgICAgICAgICBwSlMuZm4udmVuZG9ycy5jaGVja0JlZm9yZURyYXcoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGltZy5zcmMgPSBwSlMucGFydGljbGVzLnNoYXBlLmltYWdlLnNyYztcblxuICAgICAgfVxuXG4gICAgfWVsc2V7XG4gICAgICBjb25zb2xlLmxvZygnRXJyb3IgcEpTIC0gTm8gaW1hZ2Uuc3JjJyk7XG4gICAgICBwSlMudG1wLmltZ19lcnJvciA9IHRydWU7XG4gICAgfVxuXG4gIH07XG5cblxuICBwSlMuZm4udmVuZG9ycy5kcmF3ID0gZnVuY3Rpb24oKXtcblxuICAgIGlmKHBKUy5wYXJ0aWNsZXMuc2hhcGUudHlwZSA9PSAnaW1hZ2UnKXtcblxuICAgICAgaWYocEpTLnRtcC5pbWdfdHlwZSA9PSAnc3ZnJyl7XG5cbiAgICAgICAgaWYocEpTLnRtcC5jb3VudF9zdmcgPj0gcEpTLnBhcnRpY2xlcy5udW1iZXIudmFsdWUpe1xuICAgICAgICAgIHBKUy5mbi5wYXJ0aWNsZXNEcmF3KCk7XG4gICAgICAgICAgaWYoIXBKUy5wYXJ0aWNsZXMubW92ZS5lbmFibGUpIGNhbmNlbFJlcXVlc3RBbmltRnJhbWUocEpTLmZuLmRyYXdBbmltRnJhbWUpO1xuICAgICAgICAgIGVsc2UgcEpTLmZuLmRyYXdBbmltRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHBKUy5mbi52ZW5kb3JzLmRyYXcpO1xuICAgICAgICB9ZWxzZXtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKCdzdGlsbCBsb2FkaW5nLi4uJyk7XG4gICAgICAgICAgaWYoIXBKUy50bXAuaW1nX2Vycm9yKSBwSlMuZm4uZHJhd0FuaW1GcmFtZSA9IHJlcXVlc3RBbmltRnJhbWUocEpTLmZuLnZlbmRvcnMuZHJhdyk7XG4gICAgICAgIH1cblxuICAgICAgfWVsc2V7XG5cbiAgICAgICAgaWYocEpTLnRtcC5pbWdfb2JqICE9IHVuZGVmaW5lZCl7XG4gICAgICAgICAgcEpTLmZuLnBhcnRpY2xlc0RyYXcoKTtcbiAgICAgICAgICBpZighcEpTLnBhcnRpY2xlcy5tb3ZlLmVuYWJsZSkgY2FuY2VsUmVxdWVzdEFuaW1GcmFtZShwSlMuZm4uZHJhd0FuaW1GcmFtZSk7XG4gICAgICAgICAgZWxzZSBwSlMuZm4uZHJhd0FuaW1GcmFtZSA9IHJlcXVlc3RBbmltRnJhbWUocEpTLmZuLnZlbmRvcnMuZHJhdyk7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIGlmKCFwSlMudG1wLmltZ19lcnJvcikgcEpTLmZuLmRyYXdBbmltRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHBKUy5mbi52ZW5kb3JzLmRyYXcpO1xuICAgICAgICB9XG5cbiAgICAgIH1cblxuICAgIH1lbHNle1xuICAgICAgcEpTLmZuLnBhcnRpY2xlc0RyYXcoKTtcbiAgICAgIGlmKCFwSlMucGFydGljbGVzLm1vdmUuZW5hYmxlKSBjYW5jZWxSZXF1ZXN0QW5pbUZyYW1lKHBKUy5mbi5kcmF3QW5pbUZyYW1lKTtcbiAgICAgIGVsc2UgcEpTLmZuLmRyYXdBbmltRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHBKUy5mbi52ZW5kb3JzLmRyYXcpO1xuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMuY2hlY2tCZWZvcmVEcmF3ID0gZnVuY3Rpb24oKXtcblxuICAgIC8vIGlmIHNoYXBlIGlzIGltYWdlXG4gICAgaWYocEpTLnBhcnRpY2xlcy5zaGFwZS50eXBlID09ICdpbWFnZScpe1xuXG4gICAgICBpZihwSlMudG1wLmltZ190eXBlID09ICdzdmcnICYmIHBKUy50bXAuc291cmNlX3N2ZyA9PSB1bmRlZmluZWQpe1xuICAgICAgICBwSlMudG1wLmNoZWNrQW5pbUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZShjaGVjayk7XG4gICAgICB9ZWxzZXtcbiAgICAgICAgLy9jb25zb2xlLmxvZygnaW1hZ2VzIGxvYWRlZCEgY2FuY2VsIGNoZWNrJyk7XG4gICAgICAgIGNhbmNlbFJlcXVlc3RBbmltRnJhbWUocEpTLnRtcC5jaGVja0FuaW1GcmFtZSk7XG4gICAgICAgIGlmKCFwSlMudG1wLmltZ19lcnJvcil7XG4gICAgICAgICAgcEpTLmZuLnZlbmRvcnMuaW5pdCgpO1xuICAgICAgICAgIHBKUy5mbi52ZW5kb3JzLmRyYXcoKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgIH1cblxuICAgIH1lbHNle1xuICAgICAgcEpTLmZuLnZlbmRvcnMuaW5pdCgpO1xuICAgICAgcEpTLmZuLnZlbmRvcnMuZHJhdygpO1xuICAgIH1cblxuICB9O1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMuaW5pdCA9IGZ1bmN0aW9uKCl7XG5cbiAgICAvKiBpbml0IGNhbnZhcyArIHBhcnRpY2xlcyAqL1xuICAgIHBKUy5mbi5yZXRpbmFJbml0KCk7XG4gICAgcEpTLmZuLmNhbnZhc0luaXQoKTtcbiAgICBwSlMuZm4uY2FudmFzU2l6ZSgpO1xuICAgIHBKUy5mbi5jYW52YXNQYWludCgpO1xuICAgIHBKUy5mbi5wYXJ0aWNsZXNDcmVhdGUoKTtcbiAgICBwSlMuZm4udmVuZG9ycy5kZW5zaXR5QXV0b1BhcnRpY2xlcygpO1xuXG4gICAgLyogcGFydGljbGVzLmxpbmVfbGlua2VkIC0gY29udmVydCBoZXggY29sb3JzIHRvIHJnYiAqL1xuICAgIHBKUy5wYXJ0aWNsZXMubGluZV9saW5rZWQuY29sb3JfcmdiX2xpbmUgPSBoZXhUb1JnYihwSlMucGFydGljbGVzLmxpbmVfbGlua2VkLmNvbG9yKTtcblxuICB9O1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMuc3RhcnQgPSBmdW5jdGlvbigpe1xuXG4gICAgaWYoaXNJbkFycmF5KCdpbWFnZScsIHBKUy5wYXJ0aWNsZXMuc2hhcGUudHlwZSkpe1xuICAgICAgcEpTLnRtcC5pbWdfdHlwZSA9IHBKUy5wYXJ0aWNsZXMuc2hhcGUuaW1hZ2Uuc3JjLnN1YnN0cihwSlMucGFydGljbGVzLnNoYXBlLmltYWdlLnNyYy5sZW5ndGggLSAzKTtcbiAgICAgIHBKUy5mbi52ZW5kb3JzLmxvYWRJbWcocEpTLnRtcC5pbWdfdHlwZSk7XG4gICAgfWVsc2V7XG4gICAgICBwSlMuZm4udmVuZG9ycy5jaGVja0JlZm9yZURyYXcoKTtcbiAgICB9XG5cbiAgfTtcblxuXG5cblxuICAvKiAtLS0tLS0tLS0tIHBKUyAtIHN0YXJ0IC0tLS0tLS0tLS0tLSAqL1xuXG5cbiAgcEpTLmZuLnZlbmRvcnMuZXZlbnRzTGlzdGVuZXJzKCk7XG5cbiAgcEpTLmZuLnZlbmRvcnMuc3RhcnQoKTtcbiAgXG5cblxufTtcblxuLyogLS0tLS0tLS0tLSBnbG9iYWwgZnVuY3Rpb25zIC0gdmVuZG9ycyAtLS0tLS0tLS0tLS0gKi9cblxuT2JqZWN0LmRlZXBFeHRlbmQgPSBmdW5jdGlvbihkZXN0aW5hdGlvbiwgc291cmNlKSB7XG4gIGZvciAodmFyIHByb3BlcnR5IGluIHNvdXJjZSkge1xuICAgIGlmIChzb3VyY2VbcHJvcGVydHldICYmIHNvdXJjZVtwcm9wZXJ0eV0uY29uc3RydWN0b3IgJiZcbiAgICAgc291cmNlW3Byb3BlcnR5XS5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0KSB7XG4gICAgICBkZXN0aW5hdGlvbltwcm9wZXJ0eV0gPSBkZXN0aW5hdGlvbltwcm9wZXJ0eV0gfHwge307XG4gICAgICBhcmd1bWVudHMuY2FsbGVlKGRlc3RpbmF0aW9uW3Byb3BlcnR5XSwgc291cmNlW3Byb3BlcnR5XSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlc3RpbmF0aW9uW3Byb3BlcnR5XSA9IHNvdXJjZVtwcm9wZXJ0eV07XG4gICAgfVxuICB9XG4gIHJldHVybiBkZXN0aW5hdGlvbjtcbn07XG5cbndpbmRvdy5yZXF1ZXN0QW5pbUZyYW1lID0gKGZ1bmN0aW9uKCl7XG4gIHJldHVybiAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lICAgIHx8XG4gICAgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgICB8fFxuICAgIHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZSAgICAgfHxcbiAgICBmdW5jdGlvbihjYWxsYmFjayl7XG4gICAgICB3aW5kb3cuc2V0VGltZW91dChjYWxsYmFjaywgMTAwMCAvIDYwKTtcbiAgICB9O1xufSkoKTtcblxud2luZG93LmNhbmNlbFJlcXVlc3RBbmltRnJhbWUgPSAoIGZ1bmN0aW9uKCkge1xuICByZXR1cm4gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lICAgICAgICAgfHxcbiAgICB3aW5kb3cud2Via2l0Q2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93Lm1vekNhbmNlbFJlcXVlc3RBbmltYXRpb25GcmFtZSAgICB8fFxuICAgIHdpbmRvdy5vQ2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lICAgICAgfHxcbiAgICB3aW5kb3cubXNDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgICAgIHx8XG4gICAgY2xlYXJUaW1lb3V0XG59ICkoKTtcblxuZnVuY3Rpb24gaGV4VG9SZ2IoaGV4KXtcbiAgLy8gQnkgVGltIERvd24gLSBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS81NjI0MTM5LzM0OTM2NTBcbiAgLy8gRXhwYW5kIHNob3J0aGFuZCBmb3JtIChlLmcuIFwiMDNGXCIpIHRvIGZ1bGwgZm9ybSAoZS5nLiBcIjAwMzNGRlwiKVxuICB2YXIgc2hvcnRoYW5kUmVnZXggPSAvXiM/KFthLWZcXGRdKShbYS1mXFxkXSkoW2EtZlxcZF0pJC9pO1xuICBoZXggPSBoZXgucmVwbGFjZShzaG9ydGhhbmRSZWdleCwgZnVuY3Rpb24obSwgciwgZywgYikge1xuICAgICByZXR1cm4gciArIHIgKyBnICsgZyArIGIgKyBiO1xuICB9KTtcbiAgdmFyIHJlc3VsdCA9IC9eIz8oW2EtZlxcZF17Mn0pKFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkkL2kuZXhlYyhoZXgpO1xuICByZXR1cm4gcmVzdWx0ID8ge1xuICAgICAgcjogcGFyc2VJbnQocmVzdWx0WzFdLCAxNiksXG4gICAgICBnOiBwYXJzZUludChyZXN1bHRbMl0sIDE2KSxcbiAgICAgIGI6IHBhcnNlSW50KHJlc3VsdFszXSwgMTYpXG4gIH0gOiBudWxsO1xufTtcblxuZnVuY3Rpb24gY2xhbXAobnVtYmVyLCBtaW4sIG1heCkge1xuICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgobnVtYmVyLCBtaW4pLCBtYXgpO1xufTtcblxuZnVuY3Rpb24gaXNJbkFycmF5KHZhbHVlLCBhcnJheSkge1xuICByZXR1cm4gYXJyYXkuaW5kZXhPZih2YWx1ZSkgPiAtMTtcbn1cblxuXG4vKiAtLS0tLS0tLS0tIHBhcnRpY2xlcy5qcyBmdW5jdGlvbnMgLSBzdGFydCAtLS0tLS0tLS0tLS0gKi9cblxud2luZG93LnBKU0RvbSA9IFtdO1xuXG53aW5kb3cucGFydGljbGVzSlMgPSBmdW5jdGlvbih0YWdfaWQsIHBhcmFtcyl7XG5cbiAgLy9jb25zb2xlLmxvZyhwYXJhbXMpO1xuXG4gIC8qIG5vIHN0cmluZyBpZD8gc28gaXQncyBvYmplY3QgcGFyYW1zLCBhbmQgc2V0IHRoZSBpZCB3aXRoIGRlZmF1bHQgaWQgKi9cbiAgaWYodHlwZW9mKHRhZ19pZCkgIT0gJ3N0cmluZycpe1xuICAgIHBhcmFtcyA9IHRhZ19pZDtcbiAgICB0YWdfaWQgPSAncGFydGljbGVzLWpzJztcbiAgfVxuXG4gIC8qIG5vIGlkPyBzZXQgdGhlIGlkIHRvIGRlZmF1bHQgaWQgKi9cbiAgaWYoIXRhZ19pZCl7XG4gICAgdGFnX2lkID0gJ3BhcnRpY2xlcy1qcyc7XG4gIH1cblxuICAvKiBwSlMgZWxlbWVudHMgKi9cbiAgdmFyIHBKU190YWcgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YWdfaWQpLFxuICAgICAgcEpTX2NhbnZhc19jbGFzcyA9ICdwYXJ0aWNsZXMtanMtY2FudmFzLWVsJyxcbiAgICAgIGV4aXN0X2NhbnZhcyA9IHBKU190YWcuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShwSlNfY2FudmFzX2NsYXNzKTtcblxuICAvKiByZW1vdmUgY2FudmFzIGlmIGV4aXN0cyBpbnRvIHRoZSBwSlMgdGFyZ2V0IHRhZyAqL1xuICBpZihleGlzdF9jYW52YXMubGVuZ3RoKXtcbiAgICB3aGlsZShleGlzdF9jYW52YXMubGVuZ3RoID4gMCl7XG4gICAgICBwSlNfdGFnLnJlbW92ZUNoaWxkKGV4aXN0X2NhbnZhc1swXSk7XG4gICAgfVxuICB9XG5cbiAgLyogY3JlYXRlIGNhbnZhcyBlbGVtZW50ICovXG4gIHZhciBjYW52YXNfZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgY2FudmFzX2VsLmNsYXNzTmFtZSA9IHBKU19jYW52YXNfY2xhc3M7XG5cbiAgLyogc2V0IHNpemUgY2FudmFzICovXG4gIGNhbnZhc19lbC5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICBjYW52YXNfZWwuc3R5bGUuaGVpZ2h0ID0gXCIxMDAlXCI7XG5cbiAgLyogYXBwZW5kIGNhbnZhcyAqL1xuICB2YXIgY2FudmFzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFnX2lkKS5hcHBlbmRDaGlsZChjYW52YXNfZWwpO1xuXG4gIC8qIGxhdW5jaCBwYXJ0aWNsZS5qcyAqL1xuICBpZihjYW52YXMgIT0gbnVsbCl7XG4gICAgcEpTRG9tLnB1c2gobmV3IHBKUyh0YWdfaWQsIHBhcmFtcykpO1xuICB9XG5cbn07XG5cbndpbmRvdy5wYXJ0aWNsZXNKUy5sb2FkID0gZnVuY3Rpb24odGFnX2lkLCBwYXRoX2NvbmZpZ19qc29uLCBjYWxsYmFjayl7XG5cbiAgLyogbG9hZCBqc29uIGNvbmZpZyAqL1xuICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gIHhoci5vcGVuKCdHRVQnLCBwYXRoX2NvbmZpZ19qc29uKTtcbiAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgaWYoeGhyLnJlYWR5U3RhdGUgPT0gNCl7XG4gICAgICBpZih4aHIuc3RhdHVzID09IDIwMCl7XG4gICAgICAgIHZhciBwYXJhbXMgPSBKU09OLnBhcnNlKGRhdGEuY3VycmVudFRhcmdldC5yZXNwb25zZSk7XG4gICAgICAgIHdpbmRvdy5wYXJ0aWNsZXNKUyh0YWdfaWQsIHBhcmFtcyk7XG4gICAgICAgIGlmKGNhbGxiYWNrKSBjYWxsYmFjaygpO1xuICAgICAgfWVsc2V7XG4gICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciBwSlMgLSBYTUxIdHRwUmVxdWVzdCBzdGF0dXM6ICcreGhyLnN0YXR1cyk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciBwSlMgLSBGaWxlIGNvbmZpZyBub3QgZm91bmQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHhoci5zZW5kKCk7XG5cbn07XG5cblxuLyoqKioqKioqKioqKioqKioqXG4gKiogV0VCUEFDSyBGT09URVJcbiAqKiAuL34vcGFydGljbGVzLmpzL3BhcnRpY2xlcy5qc1xuICoqIG1vZHVsZSBpZCA9IDFcbiAqKiBtb2R1bGUgY2h1bmtzID0gMFxuICoqLyJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==");
/***/ },
/* 2 */
/***/ function(module, exports) {
eval("module.exports = {\n\t\"particles\": {\n\t\t\"number\": {\n\t\t\t\"value\": 20,\n\t\t\t\"density\": {\n\t\t\t\t\"enable\": true,\n\t\t\t\t\"value_area\": 800\n\t\t\t}\n\t\t},\n\t\t\"color\": {\n\t\t\t\"value\": [\n\t\t\t\t\"#4fc4a8\",\n\t\t\t\t\"#a354cd\",\n\t\t\t\t\"#4FC059\",\n\t\t\t\t\"#4fb5c0\",\n\t\t\t\t\"#00BCD4\",\n\t\t\t\t\"#dab539\",\n\t\t\t\t\"#AAB0FB\",\n\t\t\t\t\"#c04f4f\"\n\t\t\t]\n\t\t},\n\t\t\"shape\": {\n\t\t\t\"type\": \"circle\",\n\t\t\t\"image\": {\n\t\t\t\t\"src\": \"\",\n\t\t\t\t\"width\": 30,\n\t\t\t\t\"height\": 30\n\t\t\t}\n\t\t},\n\t\t\"opacity\": {\n\t\t\t\"value\": 0.5,\n\t\t\t\"random\": false,\n\t\t\t\"anim\": {\n\t\t\t\t\"enable\": false,\n\t\t\t\t\"speed\": 1,\n\t\t\t\t\"opacity_min\": 0.1,\n\t\t\t\t\"sync\": false\n\t\t\t}\n\t\t},\n\t\t\"size\": {\n\t\t\t\"value\": 20,\n\t\t\t\"random\": true,\n\t\t\t\"anim\": {\n\t\t\t\t\"enable\": true,\n\t\t\t\t\"speed\": 10,\n\t\t\t\t\"size_min\": 5,\n\t\t\t\t\"sync\": false\n\t\t\t}\n\t\t},\n\t\t\"line_linked\": {\n\t\t\t\"enable\": true,\n\t\t\t\"distance\": 300,\n\t\t\t\"color\": \"#AEA9FD\",\n\t\t\t\"opacity\": 0.5,\n\t\t\t\"width\": 3\n\t\t},\n\t\t\"move\": {\n\t\t\t\"enable\": true,\n\t\t\t\"speed\": 4,\n\t\t\t\"direction\": \"none\",\n\t\t\t\"random\": true,\n\t\t\t\"out_mode\": \"out\",\n\t\t\t\"bounce\": false,\n\t\t\t\"attract\": {\n\t\t\t\t\"enable\": true,\n\t\t\t\t\"rotateX\": 2000,\n\t\t\t\t\"rotateY\": 2000\n\t\t\t}\n\t\t}\n\t},\n\t\"interactivity\": {\n\t\t\"detect_on\": \"canvas\",\n\t\t\"events\": {\n\t\t\t\"onhover\": {\n\t\t\t\t\"enable\": false,\n\t\t\t\t\"mode\": \"repulse\"\n\t\t\t},\n\t\t\t\"onclick\": {\n\t\t\t\t\"enable\": false\n\t\t\t},\n\t\t\t\"resize\": true\n\t\t},\n\t\t\"modes\": {\n\t\t\t\"grab\": {\n\t\t\t\t\"distance\": 800,\n\t\t\t\t\"line_linked\": {\n\t\t\t\t\t\"opacity\": 1\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"bubble\": {\n\t\t\t\t\"distance\": 800,\n\t\t\t\t\"size\": 80,\n\t\t\t\t\"duration\": 2,\n\t\t\t\t\"opacity\": 8,\n\t\t\t\t\"speed\": 3\n\t\t\t},\n\t\t\t\"repulse\": {\n\t\t\t\t\"distance\": 400,\n\t\t\t\t\"duration\": 0.4\n\t\t\t},\n\t\t\t\"push\": {\n\t\t\t\t\"particles_nb\": 4\n\t\t\t},\n\t\t\t\"remove\": {\n\t\t\t\t\"particles_nb\": 2\n\t\t\t}\n\t\t}\n\t},\n\t\"retina_detect\": true\n};//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMi5qcyIsInNvdXJjZXMiOlsiL2hvbWUvdWJ1bnR1L3dvcmtzcGFjZS9mcm9udGVuZC9zcmMvaG9tZS9wYXJ0aWNsZXMuanNvbiJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IHtcblx0XCJwYXJ0aWNsZXNcIjoge1xuXHRcdFwibnVtYmVyXCI6IHtcblx0XHRcdFwidmFsdWVcIjogMjAsXG5cdFx0XHRcImRlbnNpdHlcIjoge1xuXHRcdFx0XHRcImVuYWJsZVwiOiB0cnVlLFxuXHRcdFx0XHRcInZhbHVlX2FyZWFcIjogODAwXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRcImNvbG9yXCI6IHtcblx0XHRcdFwidmFsdWVcIjogW1xuXHRcdFx0XHRcIiM0ZmM0YThcIixcblx0XHRcdFx0XCIjYTM1NGNkXCIsXG5cdFx0XHRcdFwiIzRGQzA1OVwiLFxuXHRcdFx0XHRcIiM0ZmI1YzBcIixcblx0XHRcdFx0XCIjMDBCQ0Q0XCIsXG5cdFx0XHRcdFwiI2RhYjUzOVwiLFxuXHRcdFx0XHRcIiNBQUIwRkJcIixcblx0XHRcdFx0XCIjYzA0ZjRmXCJcblx0XHRcdF1cblx0XHR9LFxuXHRcdFwic2hhcGVcIjoge1xuXHRcdFx0XCJ0eXBlXCI6IFwiY2lyY2xlXCIsXG5cdFx0XHRcImltYWdlXCI6IHtcblx0XHRcdFx0XCJzcmNcIjogXCJcIixcblx0XHRcdFx0XCJ3aWR0aFwiOiAzMCxcblx0XHRcdFx0XCJoZWlnaHRcIjogMzBcblx0XHRcdH1cblx0XHR9LFxuXHRcdFwib3BhY2l0eVwiOiB7XG5cdFx0XHRcInZhbHVlXCI6IDAuNSxcblx0XHRcdFwicmFuZG9tXCI6IGZhbHNlLFxuXHRcdFx0XCJhbmltXCI6IHtcblx0XHRcdFx0XCJlbmFibGVcIjogZmFsc2UsXG5cdFx0XHRcdFwic3BlZWRcIjogMSxcblx0XHRcdFx0XCJvcGFjaXR5X21pblwiOiAwLjEsXG5cdFx0XHRcdFwic3luY1wiOiBmYWxzZVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0XCJzaXplXCI6IHtcblx0XHRcdFwidmFsdWVcIjogMjAsXG5cdFx0XHRcInJhbmRvbVwiOiB0cnVlLFxuXHRcdFx0XCJhbmltXCI6IHtcblx0XHRcdFx0XCJlbmFibGVcIjogdHJ1ZSxcblx0XHRcdFx0XCJzcGVlZFwiOiAxMCxcblx0XHRcdFx0XCJzaXplX21pblwiOiA1LFxuXHRcdFx0XHRcInN5bmNcIjogZmFsc2Vcblx0XHRcdH1cblx0XHR9LFxuXHRcdFwibGluZV9saW5rZWRcIjoge1xuXHRcdFx0XCJlbmFibGVcIjogdHJ1ZSxcblx0XHRcdFwiZGlzdGFuY2VcIjogMzAwLFxuXHRcdFx0XCJjb2xvclwiOiBcIiNBRUE5RkRcIixcblx0XHRcdFwib3BhY2l0eVwiOiAwLjUsXG5cdFx0XHRcIndpZHRoXCI6IDNcblx0XHR9LFxuXHRcdFwibW92ZVwiOiB7XG5cdFx0XHRcImVuYWJsZVwiOiB0cnVlLFxuXHRcdFx0XCJzcGVlZFwiOiA0LFxuXHRcdFx0XCJkaXJlY3Rpb25cIjogXCJub25lXCIsXG5cdFx0XHRcInJhbmRvbVwiOiB0cnVlLFxuXHRcdFx0XCJvdXRfbW9kZVwiOiBcIm91dFwiLFxuXHRcdFx0XCJib3VuY2VcIjogZmFsc2UsXG5cdFx0XHRcImF0dHJhY3RcIjoge1xuXHRcdFx0XHRcImVuYWJsZVwiOiB0cnVlLFxuXHRcdFx0XHRcInJvdGF0ZVhcIjogMjAwMCxcblx0XHRcdFx0XCJyb3RhdGVZXCI6IDIwMDBcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdFwiaW50ZXJhY3Rpdml0eVwiOiB7XG5cdFx0XCJkZXRlY3Rfb25cIjogXCJjYW52YXNcIixcblx0XHRcImV2ZW50c1wiOiB7XG5cdFx0XHRcIm9uaG92ZXJcIjoge1xuXHRcdFx0XHRcImVuYWJsZVwiOiBmYWxzZSxcblx0XHRcdFx0XCJtb2RlXCI6IFwicmVwdWxzZVwiXG5cdFx0XHR9LFxuXHRcdFx0XCJvbmNsaWNrXCI6IHtcblx0XHRcdFx0XCJlbmFibGVcIjogZmFsc2Vcblx0XHRcdH0sXG5cdFx0XHRcInJlc2l6ZVwiOiB0cnVlXG5cdFx0fSxcblx0XHRcIm1vZGVzXCI6IHtcblx0XHRcdFwiZ3JhYlwiOiB7XG5cdFx0XHRcdFwiZGlzdGFuY2VcIjogODAwLFxuXHRcdFx0XHRcImxpbmVfbGlua2VkXCI6IHtcblx0XHRcdFx0XHRcIm9wYWNpdHlcIjogMVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0XCJidWJibGVcIjoge1xuXHRcdFx0XHRcImRpc3RhbmNlXCI6IDgwMCxcblx0XHRcdFx0XCJzaXplXCI6IDgwLFxuXHRcdFx0XHRcImR1cmF0aW9uXCI6IDIsXG5cdFx0XHRcdFwib3BhY2l0eVwiOiA4LFxuXHRcdFx0XHRcInNwZWVkXCI6IDNcblx0XHRcdH0sXG5cdFx0XHRcInJlcHVsc2VcIjoge1xuXHRcdFx0XHRcImRpc3RhbmNlXCI6IDQwMCxcblx0XHRcdFx0XCJkdXJhdGlvblwiOiAwLjRcblx0XHRcdH0sXG5cdFx0XHRcInB1c2hcIjoge1xuXHRcdFx0XHRcInBhcnRpY2xlc19uYlwiOiA0XG5cdFx0XHR9LFxuXHRcdFx0XCJyZW1vdmVcIjoge1xuXHRcdFx0XHRcInBhcnRpY2xlc19uYlwiOiAyXG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXHRcInJldGluYV9kZXRlY3RcIjogdHJ1ZVxufTtcblxuXG4vKioqKioqKioqKioqKioqKipcbiAqKiBXRUJQQUNLIEZPT1RFUlxuICoqIC4vZnJvbnRlbmQvc3JjL2hvbWUvcGFydGljbGVzLmpzb25cbiAqKiBtb2R1bGUgaWQgPSAyXG4gKiogbW9kdWxlIGNodW5rcyA9IDBcbiAqKi8iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=");
/***/ }
/******/ ]);