diff --git a/firebase.json b/firebase.json index 7b215fe..6c68d5b 100644 --- a/firebase.json +++ b/firebase.json @@ -19,7 +19,7 @@ }, { "source": "/benchmark3", - "destination": "/banchmark3.html", + "destination": "/benchmark3.html", "type": 301 } ] diff --git a/public/benchmark3.html b/public/benchmark3.html index e2940cf..eeae5e4 100644 --- a/public/benchmark3.html +++ b/public/benchmark3.html @@ -45,7 +45,7 @@ @font-face { font-family: 'NoPixel'; - src: url('shattered_sword_assets3/fonts/NoPixel.ttf'); + src: url('shattered_sword_assets/fonts/NoPixel.ttf'); } diff --git a/public/bundle2.js b/public/bundle2.js index 7681f03..7efb914 100644 --- a/public/bundle2.js +++ b/public/bundle2.js @@ -11491,11 +11491,11 @@ class WeaponTemplateRegistry extends Registry_1.default { const rm = ResourceManager_1.default.getInstance(); //TODO - // Load sprites for each weapon - //rm.image("something", "shattered_sword_assets2/sprites/something.png"); - rm.image("knife", "shattered_sword_assets2/sprites/knife.png"); + //rm.image("something", "shattered_sword_assets/sprites/something.png"); + rm.image("knife", "shattered_sword_assets/sprites/knife.png"); // Load spritesheets - //rm.spritesheet("weapon anim", "shattered_sword_assets2/spritesheets/weapon anim.json"); - rm.spritesheet("slice", "shattered_sword_assets2/spritesheets/slice.json"); + //rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json"); + rm.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); // Register default types //this.registerItem("itemtype", itemTypefile); this.registerItem("slice", Slice_1.default); @@ -11553,15 +11553,15 @@ class GameLevel extends Scene_1.default { //can load player sprite here //can load enemy sprite here // Load the scene info - this.load.object("weaponData", "shattered_sword_assets2/data/weaponData.json"); + this.load.object("weaponData", "shattered_sword_assets/data/weaponData.json"); // Load in the enemy info - //this.load.object("enemyData", "shattered_sword_assets2/data/enemy.json"); + //this.load.object("enemyData", "shattered_sword_assets/data/enemy.json"); // Load in item info - //this.load.object("itemData", "shattered_sword_assets2/data/items.json"); - this.load.image("knife", "shattered_sword_assets2/sprites/knife.png"); - this.load.spritesheet("slice", "shattered_sword_assets2/spritesheets/slice.json"); - this.load.image("inventorySlot", "shattered_sword_assets2/sprites/inventory.png"); - this.load.spritesheet("test_dummy", "shattered_sword_assets2/spritesheets/test_dummy.json"); + //this.load.object("itemData", "shattered_sword_assets/data/items.json"); + this.load.image("knife", "shattered_sword_assets/sprites/knife.png"); + this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); + this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png"); + this.load.spritesheet("test_dummy", "shattered_sword_assets/spritesheets/test_dummy.json"); } startScene() { // Do the game level standard initializations @@ -11978,7 +11978,7 @@ const Levels_1 = require("./Levels"); class MainMenu extends Scene_1.default { loadScene() { // Load the menu song - //this.load.audio("menu", "shattered_sword_assets2/music/menu.mp3"); + //this.load.audio("menu", "shattered_sword_assets/music/menu.mp3"); } //TODO startScene() { @@ -11990,7 +11990,7 @@ class MainMenu extends Scene_1.default { // console.log(this.save.getLevel()); // this.save.setLevel(10); // console.log(this.save.getLevel()); - // this.rmg = new RandomMapGenerator("shattered_sword_assets2/jsons/forest_template.json", 114514); + // this.rmg = new RandomMapGenerator("shattered_sword_assets/jsons/forest_template.json", 114514); // this.rmg.getMap(); // Scene has started, so start playing music //this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "menu", loop: true, holdReference: true}); @@ -12295,7 +12295,7 @@ class SceneWithStory extends Scene_1.default { let event = this.receiver.getNextEvent(); // Testing code if (event.type === "loadStory" && this.currentMode === Mode.GAME_MODE) { - this.storyLoader("shattered_sword_assets2/jsons/story.json"); + this.storyLoader("shattered_sword_assets/jsons/story.json"); } } // Testing code @@ -12316,15 +12316,15 @@ class Tutorial extends GameLevel_1.default { loadScene() { super.loadScene(); // Load resources - // this.load.tilemap("forest1", "shattered_sword_assets2/tilemaps/Tutorial.json"); + // this.load.tilemap("forest1", "shattered_sword_assets/tilemaps/Tutorial.json"); // let map = localStorage.getItem("map"); this.randomSeed = Math.floor(Math.random() * 10000000000); - let rmg = new RandomMapGenerator_1.default("shattered_sword_assets2/jsons/forest_template.json", this.randomSeed); + let rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/forest_template.json", this.randomSeed); this.map = rmg.getMap(); this.load.tilemapFromObject("forest1", this.map); - this.load.spritesheet("player", "shattered_sword_assets2/spritesheets/Hiro.json"); + this.load.spritesheet("player", "shattered_sword_assets/spritesheets/Hiro.json"); // TODO - change when done testing - this.load.spritesheet("slice", "shattered_sword_assets2/spritesheets/slice.json"); + this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); //load music here } startScene() { diff --git a/public/bundle3.js b/public/bundle3.js new file mode 100644 index 0000000..059c789 --- /dev/null +++ b/public/bundle3.js @@ -0,0 +1,14181 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) { + var thisPos = stack.indexOf(this) + ~thisPos ? stack.splice(thisPos + 1) : stack.push(this) + ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key) + if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value) + } + else stack.push(value) + + return replacer == null ? value : replacer.call(this, key, value) + } +} + +},{}],2:[function(require,module,exports){ +/* + * random-seed + * https://github.com/skratchdot/random-seed + * + * This code was originally written by Steve Gibson and can be found here: + * + * https://www.grc.com/otg/uheprng.htm + * + * It was slightly modified for use in node, to pass jshint, and a few additional + * helper functions were added. + * + * Copyright (c) 2013 skratchdot + * Dual Licensed under the MIT license and the original GRC copyright/license + * included below. + */ +/* ============================================================================ + Gibson Research Corporation + UHEPRNG - Ultra High Entropy Pseudo-Random Number Generator + ============================================================================ + LICENSE AND COPYRIGHT: THIS CODE IS HEREBY RELEASED INTO THE PUBLIC DOMAIN + Gibson Research Corporation releases and disclaims ALL RIGHTS AND TITLE IN + THIS CODE OR ANY DERIVATIVES. Anyone may be freely use it for any purpose. + ============================================================================ + This is GRC's cryptographically strong PRNG (pseudo-random number generator) + for JavaScript. It is driven by 1536 bits of entropy, stored in an array of + 48, 32-bit JavaScript variables. Since many applications of this generator, + including ours with the "Off The Grid" Latin Square generator, may require + the deteriministic re-generation of a sequence of PRNs, this PRNG's initial + entropic state can be read and written as a static whole, and incrementally + evolved by pouring new source entropy into the generator's internal state. + ---------------------------------------------------------------------------- + ENDLESS THANKS are due Johannes Baagoe for his careful development of highly + robust JavaScript implementations of JS PRNGs. This work was based upon his + JavaScript "Alea" PRNG which is based upon the extremely robust Multiply- + With-Carry (MWC) PRNG invented by George Marsaglia. MWC Algorithm References: + http://www.GRC.com/otg/Marsaglia_PRNGs.pdf + http://www.GRC.com/otg/Marsaglia_MWC_Generators.pdf + ---------------------------------------------------------------------------- + The quality of this algorithm's pseudo-random numbers have been verified by + multiple independent researchers. It handily passes the fermilab.ch tests as + well as the "diehard" and "dieharder" test suites. For individuals wishing + to further verify the quality of this algorithm's pseudo-random numbers, a + 256-megabyte file of this algorithm's output may be downloaded from GRC.com, + and a Microsoft Windows scripting host (WSH) version of this algorithm may be + downloaded and run from the Windows command prompt to generate unique files + of any size: + The Fermilab "ENT" tests: http://fourmilab.ch/random/ + The 256-megabyte sample PRN file at GRC: https://www.GRC.com/otg/uheprng.bin + The Windows scripting host version: https://www.GRC.com/otg/wsh-uheprng.js + ---------------------------------------------------------------------------- + Qualifying MWC multipliers are: 187884, 686118, 898134, 1104375, 1250205, + 1460910 and 1768863. (We use the largest one that's < 2^21) + ============================================================================ */ +'use strict'; +var stringify = require('json-stringify-safe'); + +/* ============================================================================ +This is based upon Johannes Baagoe's carefully designed and efficient hash +function for use with JavaScript. It has a proven "avalanche" effect such +that every bit of the input affects every bit of the output 50% of the time, +which is good. See: http://baagoe.com/en/RandomMusings/hash/avalanche.xhtml +============================================================================ +*/ +var Mash = function () { + var n = 0xefc8249d; + var mash = function (data) { + if (data) { + data = data.toString(); + for (var i = 0; i < data.length; i++) { + n += data.charCodeAt(i); + var h = 0.02519603282416938 * n; + n = h >>> 0; + h -= n; + h *= n; + n = h >>> 0; + h -= n; + n += h * 0x100000000; // 2^32 + } + return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 + } else { + n = 0xefc8249d; + } + }; + return mash; +}; + +var uheprng = function (seed) { + return (function () { + var o = 48; // set the 'order' number of ENTROPY-holding 32-bit values + var c = 1; // init the 'carry' used by the multiply-with-carry (MWC) algorithm + var p = o; // init the 'phase' (max-1) of the intermediate variable pointer + var s = new Array(o); // declare our intermediate variables array + var i; // general purpose local + var j; // general purpose local + var k = 0; // general purpose local + + // when our "uheprng" is initially invoked our PRNG state is initialized from the + // browser's own local PRNG. This is okay since although its generator might not + // be wonderful, it's useful for establishing large startup entropy for our usage. + var mash = new Mash(); // get a pointer to our high-performance "Mash" hash + + // fill the array with initial mash hash values + for (i = 0; i < o; i++) { + s[i] = mash(Math.random()); + } + + // this PRIVATE (internal access only) function is the heart of the multiply-with-carry + // (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a + // 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default + // [0-1] return function, and by the random 'string(n)' function which returns 'n' + // characters from 33 to 126. + var rawprng = function () { + if (++p >= o) { + p = 0; + } + var t = 1768863 * s[p] + c * 2.3283064365386963e-10; // 2^-32 + return s[p] = t - (c = t | 0); + }; + + // this EXPORTED function is the default function returned by this library. + // The values returned are integers in the range from 0 to range-1. We first + // obtain two 32-bit fractions (from rawprng) to synthesize a single high + // resolution 53-bit prng (0 to <1), then we multiply this by the caller's + // "range" param and take the "floor" to return a equally probable integer. + var random = function (range) { + return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16)); // 2^-53 + }; + + // this EXPORTED function 'string(n)' returns a pseudo-random string of + // 'n' printable characters ranging from chr(33) to chr(126) inclusive. + random.string = function (count) { + var i; + var s = ''; + for (i = 0; i < count; i++) { + s += String.fromCharCode(33 + random(94)); + } + return s; + }; + + // this PRIVATE "hash" function is used to evolve the generator's internal + // entropy state. It is also called by the EXPORTED addEntropy() function + // which is used to pour entropy into the PRNG. + var hash = function () { + var args = Array.prototype.slice.call(arguments); + for (i = 0; i < args.length; i++) { + for (j = 0; j < o; j++) { + s[j] -= mash(args[i]); + if (s[j] < 0) { + s[j] += 1; + } + } + } + }; + + // this EXPORTED "clean string" function removes leading and trailing spaces and non-printing + // control characters, including any embedded carriage-return (CR) and line-feed (LF) characters, + // from any string it is handed. this is also used by the 'hashstring' function (below) to help + // users always obtain the same EFFECTIVE uheprng seeding key. + random.cleanString = function (inStr) { + inStr = inStr.replace(/(^\s*)|(\s*$)/gi, ''); // remove any/all leading spaces + inStr = inStr.replace(/[\x00-\x1F]/gi, ''); // remove any/all control characters + inStr = inStr.replace(/\n /, '\n'); // remove any/all trailing spaces + return inStr; // return the cleaned up result + }; + + // this EXPORTED "hash string" function hashes the provided character string after first removing + // any leading or trailing spaces and ignoring any embedded carriage returns (CR) or Line Feeds (LF) + random.hashString = function (inStr) { + inStr = random.cleanString(inStr); + mash(inStr); // use the string to evolve the 'mash' state + for (i = 0; i < inStr.length; i++) { // scan through the characters in our string + k = inStr.charCodeAt(i); // get the character code at the location + for (j = 0; j < o; j++) { // "mash" it into the UHEPRNG state + s[j] -= mash(k); + if (s[j] < 0) { + s[j] += 1; + } + } + } + }; + + // this EXPORTED function allows you to seed the random generator. + random.seed = function (seed) { + if (typeof seed === 'undefined' || seed === null) { + seed = Math.random(); + } + if (typeof seed !== 'string') { + seed = stringify(seed, function (key, value) { + if (typeof value === 'function') { + return (value).toString(); + } + return value; + }); + } + random.initState(); + random.hashString(seed); + }; + + // this handy exported function is used to add entropy to our uheprng at any time + random.addEntropy = function ( /* accept zero or more arguments */ ) { + var args = []; + for (i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + hash((k++) + (new Date().getTime()) + args.join('') + Math.random()); + }; + + // if we want to provide a deterministic startup context for our PRNG, + // but without directly setting the internal state variables, this allows + // us to initialize the mash hash and PRNG's internal state before providing + // some hashing input + random.initState = function () { + mash(); // pass a null arg to force mash hash to init + for (i = 0; i < o; i++) { + s[i] = mash(' '); // fill the array with initial mash hash values + } + c = 1; // init our multiply-with-carry carry + p = o; // init our phase + }; + + // we use this (optional) exported function to signal the JavaScript interpreter + // that we're finished using the "Mash" hash function so that it can free up the + // local "instance variables" is will have been maintaining. It's not strictly + // necessary, of course, but it's good JavaScript citizenship. + random.done = function () { + mash = null; + }; + + // if we called "uheprng" with a seed value, then execute random.seed() before returning + if (typeof seed !== 'undefined') { + random.seed(seed); + } + + // Returns a random integer between 0 (inclusive) and range (exclusive) + random.range = function (range) { + return random(range); + }; + + // Returns a random float between 0 (inclusive) and 1 (exclusive) + random.random = function () { + return random(Number.MAX_VALUE - 1) / Number.MAX_VALUE; + }; + + // Returns a random float between min (inclusive) and max (exclusive) + random.floatBetween = function (min, max) { + return random.random() * (max - min) + min; + }; + + // Returns a random integer between min (inclusive) and max (inclusive) + random.intBetween = function (min, max) { + return Math.floor(random.random() * (max - min + 1)) + min; + }; + + // when our main outer "uheprng" function is called, after setting up our + // initial variables and entropic state, we return an "instance pointer" + // to the internal anonymous function which can then be used to access + // the uheprng's various exported functions. As with the ".done" function + // above, we should set the returned value to 'null' once we're finished + // using any of these functions. + return random; + }()); +}; + +// Modification for use in node: +uheprng.create = function (seed) { + return new uheprng(seed); +}; +module.exports = uheprng; + +},{"json-stringify-safe":1}],3:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +/** + * A manager class for all of the AI in a scene. + * Keeps a list of registered actors and handles AI generation for actors. + */ +class AIManager { + constructor() { + this.actors = new Array(); + this.registeredAI = new Map_1.default(); + } + /** + * Registers an actor with the AIManager + * @param actor The actor to register + */ + registerActor(actor) { + this.actors.push(actor); + } + removeActor(actor) { + let index = this.actors.indexOf(actor); + if (index !== -1) { + this.actors.splice(index, 1); + } + } + /** + * Registers an AI with the AIManager for use later on + * @param name The name of the AI to register + * @param constr The constructor for the AI + */ + registerAI(name, constr) { + this.registeredAI.add(name, constr); + } + /** + * Generates an AI instance from its name + * @param name The name of the AI to add + * @returns A new AI instance + */ + generateAI(name) { + if (this.registeredAI.has(name)) { + return new (this.registeredAI.get(name))(); + } + else { + throw `Cannot create AI with name ${name}, no AI with that name is registered`; + } + } + update(deltaT) { + // Run the ai for every active actor + this.actors.forEach(actor => { if (actor.aiActive) + actor.ai.update(deltaT); }); + } +} +exports.default = AIManager; + +},{"../DataTypes/Map":10}],4:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const StateMachine_1 = require("../DataTypes/State/StateMachine"); +/** + * A version of a @reference[StateMachine] that is configured to work as an AI controller for a @reference[GameNode] + */ +class StateMachineAI extends StateMachine_1.default { + // @implemented + initializeAI(owner, config) { } + // @implemented + destroy() { + // Get rid of our reference to the owner + delete this.owner; + this.receiver.destroy(); + } + // @implemented + activate(options) { } +} +exports.default = StateMachineAI; + +},{"../DataTypes/State/StateMachine":21}],5:[function(require,module,exports){ +"use strict"; +// @ignorePage +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A placeholder function for No Operation. Does nothing + */ +const NullFunc = () => { }; +exports.default = NullFunc; + +},{}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A linked-list for the edges in a @reference[Graph]. + */ +class EdgeNode { + /** + * Creates a new EdgeNode + * @param index The index of the node this edge connects to + * @param weight The weight of this edge + */ + constructor(index, weight) { + this.y = index; + this.next = null; + this.weight = weight ? weight : 1; + } +} +exports.default = EdgeNode; + +},{}],7:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MAX_V = void 0; +const EdgeNode_1 = require("./EdgeNode"); +exports.MAX_V = 100; +/** + * An implementation of a graph data structure using edge lists. Inspired by The Algorithm Design Manual. + */ +class Graph { + /** + * Constructs a new graph + * @param directed Whether or not this graph is directed + */ + constructor(directed = false) { + this.directed = directed; + this.weighted = false; + this.numVertices = 0; + this.numEdges = 0; + this.edges = new Array(exports.MAX_V); + this.degree = new Array(exports.MAX_V); + } + /** Adds a node to this graph and returns the index of it + * @returns The index of the new node + */ + addNode() { + this.numVertices++; + return this.numVertices; + } + /** Adds an edge between node x and y, with an optional weight + * @param x The index of the start of the edge + * @param y The index of the end of the edge + * @param weight The optional weight of the new edge + */ + addEdge(x, y, weight) { + let edge = new EdgeNode_1.default(y, weight); + if (this.edges[x]) { + edge.next = this.edges[x]; + } + this.edges[x] = edge; + if (!this.directed) { + edge = new EdgeNode_1.default(x, weight); + if (this.edges[y]) { + edge.next = this.edges[y]; + } + this.edges[y] = edge; + } + this.numEdges += 1; + } + /** + * Checks whether or not an edge exists between two nodes. + * This check is directional if this is a directed graph. + * @param x The first node + * @param y The second node + * @returns true if an edge exists, false otherwise + */ + edgeExists(x, y) { + let edge = this.edges[x]; + while (edge !== null) { + if (edge.y === y) { + return true; + } + edge = edge.next; + } + } + /** + * Gets the edge list associated with node x + * @param x The index of the node + * @returns The head of a linked-list of edges + */ + getEdges(x) { + return this.edges[x]; + } + /** + * Gets the degree associated with node x + * @param x The index of the node + */ + getDegree(x) { + return this.degree[x]; + } + /** + * Converts the specifed node into a string + * @param index The index of the node to convert to a string + * @returns The string representation of the node: "Node x" + */ + nodeToString(index) { + return "Node " + index; + } + /** + * Converts the Graph into a string format + * @returns The graph as a string + */ + toString() { + let retval = ""; + for (let i = 0; i < this.numVertices; i++) { + let edge = this.edges[i]; + let edgeStr = ""; + while (edge !== undefined && edge !== null) { + edgeStr += edge.y.toString(); + if (this.weighted) { + edgeStr += " (" + edge.weight + ")"; + } + if (edge.next !== null) { + edgeStr += ", "; + } + edge = edge.next; + } + retval += this.nodeToString(i) + ": " + edgeStr + "\n"; + } + return retval; + } +} +exports.default = Graph; + +},{"./EdgeNode":6}],8:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Graph_1 = require("./Graph"); +/** + * An extension of Graph that has nodes with positions in 2D space. + * This is a weighted graph (though not inherently directd) +*/ +class PositionGraph extends Graph_1.default { + /** + * Createes a new PositionGraph + * @param directed Whether or not this graph is directed + */ + constructor(directed = false) { + super(directed); + this.debugRender = () => { + // for(let point of this.positions){ + // ctx.fillRect((point.x - origin.x - 4)*zoom, (point.y - origin.y - 4)*zoom, 8, 8); + // } + }; + this.positions = new Array(Graph_1.MAX_V); + } + /** + * Adds a positioned node to this graph + * @param position The position of the node to add + * @returns The index of the added node + */ + addPositionedNode(position) { + this.positions[this.numVertices] = position; + return this.addNode(); + } + /** + * Changes the position of a node. + * Automatically adjusts the weights of the graph tied to this node. + * As such, be warned that this function has an O(n + m) running time, and use it sparingly. + * @param index The index of the node + * @param position The new position of the node + */ + setNodePosition(index, position) { + this.positions[index] = position; + // Recalculate all weights associated with this index + for (let i = 0; i < this.numEdges; i++) { + let edge = this.edges[i]; + while (edge !== null) { + // If this node is on either side of the edge, recalculate weight + if (i === index || edge.y === index) { + edge.weight = this.positions[i].distanceTo(this.positions[edge.y]); + } + edge = edge.next; + } + } + } + /** + * Gets the position of a node + * @param index The index of the node + * @returns The position of the node + */ + getNodePosition(index) { + return this.positions[index]; + } + /** + * Adds an edge to this graph between node x and y. + * Automatically calculates the weight of the edge as the distance between the nodes. + * @param x The beginning of the edge + * @param y The end of the edge + */ + addEdge(x, y) { + if (!this.positions[x] || !this.positions[y]) { + throw "Can't add edge to un-positioned node!"; + } + // Weight is the distance between the nodes + let weight = this.positions[x].distanceTo(this.positions[y]); + super.addEdge(x, y, weight); + } + // @override + nodeToString(index) { + return "Node " + index + " - " + this.positions[index].toString(); + } +} +exports.default = PositionGraph; + +},{"./Graph":7}],9:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isRegion = void 0; +function isRegion(arg) { + return arg && arg.size && arg.scale && arg.boundary; +} +exports.isRegion = isRegion; + +},{}],10:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Associates strings with elements of type T + */ +class Map { + /** Creates a new map */ + constructor() { + this.map = {}; + } + /** + * Adds a value T stored at a key. + * @param key The key of the item to be stored + * @param value The item to be stored + */ + add(key, value) { + this.map[key] = value; + } + /** + * Get the value associated with a key. + * @param key The key of the item + * @returns The item at the key or undefined + */ + get(key) { + return this.map[key]; + } + /** + * An alias of add. Sets the value stored at key to the new specified value + * @param key The key of the item to be stored + * @param value The item to be stored + */ + set(key, value) { + this.add(key, value); + } + /** + * Returns true if there is a value stored at the specified key, false otherwise. + * @param key The key to check + * @returns A boolean representing whether or not there is an item at the given key. + */ + has(key) { + return this.map[key] !== undefined; + } + /** + * Returns an array of all of the keys in this map. + * @returns An array containing all keys in the map. + */ + keys() { + return Object.keys(this.map); + } + // @implemented + forEach(func) { + Object.keys(this.map).forEach(key => func(key)); + } + /** + * Deletes an item associated with a key + * @param key The key at which to delete an item + */ + delete(key) { + delete this.map[key]; + } + // @implemented + clear() { + this.forEach(key => delete this.map[key]); + } + /** + * Converts this map to a string representation. + * @returns The string representation of this map. + */ + toString() { + let str = ""; + this.forEach((key) => str += key + " -> " + this.get(key).toString() + "\n"); + return str; + } +} +exports.default = Map; + +},{}],11:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("./Vec2"); +/** A 4x4 matrix0 */ +class Mat4x4 { + constructor() { + this.mat = new Float32Array([ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + ]); + } + // Static members + static get IDENTITY() { + return new Mat4x4().identity(); + } + static get ZERO() { + return new Mat4x4().zero(); + } + // Accessors + set _00(x) { + this.mat[0] = x; + } + set(col, row, value) { + if (col < 0 || col > 3 || row < 0 || row > 3) { + throw `Error - index (${col}, ${row}) is out of bounds for Mat4x4`; + } + this.mat[row * 4 + col] = value; + return this; + } + get(col, row) { + return this.mat[row * 4 + col]; + } + setAll(...items) { + this.mat.set(items); + return this; + } + identity() { + return this.setAll(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + } + zero() { + return this.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + /** + * Makes this Mat4x4 a rotation matrix of the specified number of radians ccw + * @param zRadians The number of radians to rotate + * @returns this Mat4x4 + */ + rotate(zRadians) { + return this.setAll(Math.cos(zRadians), -Math.sin(zRadians), 0, 0, Math.sin(zRadians), Math.cos(zRadians), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + } + /** + * Turns this Mat4x4 into a translation matrix of the specified translation + * @param translation The translation in x and y + * @returns this Mat4x4 + */ + translate(translation) { + // If translation is a vec, get its array + if (translation instanceof Vec2_1.default) { + translation = translation.toArray(); + } + return this.setAll(1, 0, 0, translation[0], 0, 1, 0, translation[1], 0, 0, 1, 0, 0, 0, 0, 1); + } + scale(scale) { + // Make sure scale is a float32Array + if (scale instanceof Vec2_1.default) { + scale = scale.toArray(); + } + else if (!(scale instanceof Float32Array)) { + scale = new Float32Array([scale, scale]); + } + return this.setAll(scale[0], 0, 0, 0, 0, scale[1], 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + } + /** + * Returns a new Mat4x4 that represents the right side multiplication THIS x OTHER + * @param other The other Mat4x4 to multiply by + * @returns a new Mat4x4 containing the product of these two Mat4x4s + */ + mult(other, out) { + let temp = new Float32Array(16); + for (let i = 0; i < 4; i++) { + for (let j = 0; j < 4; j++) { + let value = 0; + for (let k = 0; k < 4; k++) { + value += this.get(k, i) * other.get(j, k); + } + temp[j * 4 + i] = value; + } + } + if (out !== undefined) { + return out.setAll(...temp); + } + else { + return new Mat4x4().setAll(...temp); + } + } + /** + * Multiplies all given matricies in order. e.g. MULT(A, B, C) -> A*B*C + * @param mats A list of Mat4x4s to multiply in order + * @returns A new Mat4x4 holding the result of the operation + */ + static MULT(...mats) { + // Create a new array + let temp = Mat4x4.IDENTITY; + // Multiply by every array in order, in place + for (let i = 0; i < mats.length; i++) { + temp.mult(mats[i], temp); + } + return temp; + } + toArray() { + return this.mat; + } + toString() { + return `|${this.mat[0].toFixed(2)}, ${this.mat[1].toFixed(2)}, ${this.mat[2].toFixed(2)}, ${this.mat[3].toFixed(2)}|\n` + + `|${this.mat[4].toFixed(2)}, ${this.mat[5].toFixed(2)}, ${this.mat[6].toFixed(2)}, ${this.mat[7].toFixed(2)}|\n` + + `|${this.mat[8].toFixed(2)}, ${this.mat[9].toFixed(2)}, ${this.mat[10].toFixed(2)}, ${this.mat[11].toFixed(2)}|\n` + + `|${this.mat[12].toFixed(2)}, ${this.mat[13].toFixed(2)}, ${this.mat[14].toFixed(2)}, ${this.mat[15].toFixed(2)}|`; + } +} +exports.default = Mat4x4; + +},{"./Vec2":24}],12:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A class that contains the area of overlap of two colliding objects to allow for sorting by the physics system. + */ +class AreaCollision { + /** + * Creates a new AreaCollision object + * @param area The area of the collision + * @param collider The other collider + */ + constructor(area, collider, other, type, tile) { + this.area = area; + this.collider = collider; + this.other = other; + this.type = type; + this.tile = tile; + } +} +exports.default = AreaCollision; + +},{}],13:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../Vec2"); +/** + * An object representing the data collected from a physics hit between two geometric objects. + * Inspired by the helpful collision documentation @link(here)(https://noonat.github.io/intersect/). + */ +class Hit { + constructor() { + /** The near times of the collision */ + this.nearTimes = Vec2_1.default.ZERO; + /** The position of the collision */ + this.pos = Vec2_1.default.ZERO; + /** The overlap distance of the hit */ + this.delta = Vec2_1.default.ZERO; + /** The normal vector of the hit */ + this.normal = Vec2_1.default.ZERO; + } +} +exports.default = Hit; + +},{"../Vec2":24}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A FIFO queue with elements of type T + */ +class Queue { + /** + * Constructs a new queue + * @param maxElements The maximum size of the stack + */ + constructor(maxElements = 100) { + this.MAX_ELEMENTS = maxElements; + this.q = new Array(this.MAX_ELEMENTS); + this.head = 0; + this.tail = 0; + this.size = 0; + } + /** + * Adds an item to the back of the queue + * @param item The item to add to the back of the queue + */ + enqueue(item) { + if ((this.tail + 1) % this.MAX_ELEMENTS === this.head) { + throw new Error("Queue full - cannot add element"); + } + this.size += 1; + this.q[this.tail] = item; + this.tail = (this.tail + 1) % this.MAX_ELEMENTS; + } + /** + * Retrieves an item from the front of the queue + * @returns The item at the front of the queue + */ + dequeue() { + if (this.head === this.tail) { + throw new Error("Queue empty - cannot remove element"); + } + this.size -= 1; + let item = this.q[this.head]; + // Now delete the item + delete this.q[this.head]; + this.head = (this.head + 1) % this.MAX_ELEMENTS; + return item; + } + /** + * Returns the item at the front of the queue, but does not remove it + * @returns The item at the front of the queue + */ + peekNext() { + if (this.head === this.tail) { + throw "Queue empty - cannot get element"; + } + let item = this.q[this.head]; + return item; + } + /** + * Returns true if the queue has items in it, false otherwise + * @returns A boolean representing whether or not this queue has items + */ + hasItems() { + return this.head !== this.tail; + } + /** + * Returns the number of elements in the queue. + * @returns The size of the queue + */ + getSize() { + return this.size; + } + // @implemented + clear() { + this.forEach((item, index) => delete this.q[index]); + this.size = 0; + this.head = this.tail; + } + // @implemented + forEach(func) { + let i = this.head; + while (i !== this.tail) { + func(this.q[i], i); + i = (i + 1) % this.MAX_ELEMENTS; + } + } + /** + * Converts this queue into a string format + * @returns A string representing this queue + */ + toString() { + let retval = ""; + this.forEach((item, index) => { + let str = item.toString(); + if (index !== 0) { + str += " -> "; + } + retval = str + retval; + }); + return "Top -> " + retval; + } +} +exports.default = Queue; + +},{}],15:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** A container for info about a webGL shader program */ +class WebGLProgramType { + /** + * Deletes this shader program + */ + delete(gl) { + // Clean up all aspects of this program + if (this.program) { + gl.deleteProgram(this.program); + } + if (this.vertexShader) { + gl.deleteShader(this.vertexShader); + } + if (this.fragmentShader) { + gl.deleteShader(this.fragmentShader); + } + } +} +exports.default = WebGLProgramType; + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Shape_1 = require("./Shape"); +const Vec2_1 = require("../Vec2"); +const MathUtils_1 = require("../../Utils/MathUtils"); +const Circle_1 = require("./Circle"); +const Hit_1 = require("../Physics/Hit"); +/** + * An Axis-Aligned Bounding Box. In other words, a rectangle that is always aligned to the x-y grid. + * Inspired by the helpful collision documentation @link(here)(https://noonat.github.io/intersect/). + */ +class AABB extends Shape_1.default { + /** + * Creates a new AABB + * @param center The center of the AABB + * @param halfSize The half size of the AABB - The distance from the center to an edge in x and y + */ + constructor(center, halfSize) { + super(); + this.center = center ? center : new Vec2_1.default(0, 0); + this.halfSize = halfSize ? halfSize : new Vec2_1.default(0, 0); + } + /** Returns a point representing the top left corner of the AABB */ + get topLeft() { + return new Vec2_1.default(this.left, this.top); + } + /** Returns a point representing the top right corner of the AABB */ + get topRight() { + return new Vec2_1.default(this.right, this.top); + } + /** Returns a point representing the bottom left corner of the AABB */ + get bottomLeft() { + return new Vec2_1.default(this.left, this.bottom); + } + /** Returns a point representing the bottom right corner of the AABB */ + get bottomRight() { + return new Vec2_1.default(this.right, this.bottom); + } + // @override + getBoundingRect() { + return this.clone(); + } + // @override + getBoundingCircle() { + let r = Math.max(this.hw, this.hh); + return new Circle_1.default(this.center.clone(), r); + } + // @deprecated + getHalfSize() { + return this.halfSize; + } + // @deprecated + setHalfSize(halfSize) { + this.halfSize = halfSize; + } + // TODO - move these all to the Shape class + /** + * A simple boolean check of whether this AABB contains a point + * @param point The point to check + * @returns A boolean representing whether this AABB contains the specified point + */ + containsPoint(point) { + return point.x >= this.x - this.hw && point.x <= this.x + this.hw + && point.y >= this.y - this.hh && point.y <= this.y + this.hh; + } + /** + * A simple boolean check of whether this AABB contains a point + * @param point The point to check + * @returns A boolean representing whether this AABB contains the specified point + */ + intersectPoint(point) { + let dx = point.x - this.x; + let px = this.hw - Math.abs(dx); + if (px <= 0) { + return false; + } + let dy = point.y - this.y; + let py = this.hh - Math.abs(dy); + if (py <= 0) { + return false; + } + return true; + } + /** + * A boolean check of whether this AABB contains a point with soft left and top boundaries. + * In other words, if the top left is (0, 0), the point (0, 0) is not in the AABB + * @param point The point to check + * @returns A boolean representing whether this AABB contains the specified point + */ + containsPointSoft(point) { + return point.x > this.x - this.hw && point.x <= this.x + this.hw + && point.y > this.y - this.hh && point.y <= this.y + this.hh; + } + /** + * Returns the data from the intersection of this AABB with a line segment from a point in a direction + * @param point The point that the line segment starts from + * @param delta The direction and distance of the segment + * @param padding Pads the AABB to make it wider for the intersection test + * @returns The Hit object representing the intersection, or null if there was no intersection + */ + intersectSegment(point, delta, padding) { + let paddingX = padding ? padding.x : 0; + let paddingY = padding ? padding.y : 0; + let scaleX = 1 / delta.x; + let scaleY = 1 / delta.y; + let signX = MathUtils_1.default.sign(scaleX); + let signY = MathUtils_1.default.sign(scaleY); + let tnearx = scaleX * (this.x - signX * (this.hw + paddingX) - point.x); + let tneary = scaleY * (this.y - signY * (this.hh + paddingY) - point.y); + let tfarx = scaleX * (this.x + signX * (this.hw + paddingX) - point.x); + let tfary = scaleY * (this.y + signY * (this.hh + paddingY) - point.y); + if (tnearx > tfary || tneary > tfarx) { + // We aren't colliding - we clear one axis before intersecting another + return null; + } + let tnear = Math.max(tnearx, tneary); + // Double check for NaNs + if (tnearx !== tnearx) { + tnear = tneary; + } + else if (tneary !== tneary) { + tnear = tnearx; + } + let tfar = Math.min(tfarx, tfary); + if (tnear === -Infinity) { + return null; + } + if (tnear >= 1 || tfar <= 0) { + return null; + } + // We are colliding + let hit = new Hit_1.default(); + hit.time = MathUtils_1.default.clamp01(tnear); + hit.nearTimes.x = tnearx; + hit.nearTimes.y = tneary; + if (tnearx > tneary) { + // We hit on the left or right size + hit.normal.x = -signX; + hit.normal.y = 0; + } + else if (Math.abs(tnearx - tneary) < 0.0001) { + // We hit on the corner + hit.normal.x = -signX; + hit.normal.y = -signY; + hit.normal.normalize(); + } + else { + // We hit on the top or bottom + hit.normal.x = 0; + hit.normal.y = -signY; + } + hit.delta.x = (1.0 - hit.time) * -delta.x; + hit.delta.y = (1.0 - hit.time) * -delta.y; + hit.pos.x = point.x + delta.x * hit.time; + hit.pos.y = point.y + delta.y * hit.time; + return hit; + } + // @override + overlaps(other) { + if (other instanceof AABB) { + return this.overlapsAABB(other); + } + throw "Overlap not defined between these shapes."; + } + /** + * A simple boolean check of whether this AABB overlaps another + * @param other The other AABB to check against + * @returns True if this AABB overlaps the other, false otherwise + */ + overlapsAABB(other) { + let dx = other.x - this.x; + let px = this.hw + other.hw - Math.abs(dx); + if (px <= 0) { + return false; + } + let dy = other.y - this.y; + let py = this.hh + other.hh - Math.abs(dy); + if (py <= 0) { + return false; + } + return true; + } + /** + * Determines whether these AABBs are JUST touching - not overlapping. + * Vec2.x is -1 if the other is to the left, 1 if to the right. + * Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom. + * @param other The other AABB to check + * @returns The collision sides stored in a Vec2 if the AABBs are touching, null otherwise + */ + touchesAABB(other) { + let dx = other.x - this.x; + let px = this.hw + other.hw - Math.abs(dx); + let dy = other.y - this.y; + let py = this.hh + other.hh - Math.abs(dy); + // If one axis is just touching and the other is overlapping, true + if ((px === 0 && py >= 0) || (py === 0 && px >= 0)) { + let ret = new Vec2_1.default(); + if (px === 0) { + ret.x = other.x < this.x ? -1 : 1; + } + if (py === 0) { + ret.y = other.y < this.y ? -1 : 1; + } + return ret; + } + else { + return null; + } + } + /** + * Determines whether these AABBs are JUST touching - not overlapping. + * Also, if they are only touching corners, they are considered not touching. + * Vec2.x is -1 if the other is to the left, 1 if to the right. + * Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom. + * @param other The other AABB to check + * @returns The side of the touch, stored as a Vec2, or null if there is no touch + */ + touchesAABBWithoutCorners(other) { + let dx = other.x - this.x; + let px = this.hw + other.hw - Math.abs(dx); + let dy = other.y - this.y; + let py = this.hh + other.hh - Math.abs(dy); + // If one axis is touching, and the other is strictly overlapping + if ((px === 0 && py > 0) || (py === 0 && px > 0)) { + let ret = new Vec2_1.default(); + if (px === 0) { + ret.x = other.x < this.x ? -1 : 1; + } + else { + ret.y = other.y < this.y ? -1 : 1; + } + return ret; + } + else { + return null; + } + } + /** + * Calculates the area of the overlap between this AABB and another + * @param other The other AABB + * @returns The area of the overlap between the AABBs + */ + overlapArea(other) { + let leftx = Math.max(this.x - this.hw, other.x - other.hw); + let rightx = Math.min(this.x + this.hw, other.x + other.hw); + let dx = rightx - leftx; + let lefty = Math.max(this.y - this.hh, other.y - other.hh); + let righty = Math.min(this.y + this.hh, other.y + other.hh); + let dy = righty - lefty; + if (dx < 0 || dy < 0) + return 0; + return dx * dy; + } + /** + * Moves and resizes this rect from its current position to the position specified + * @param velocity The movement of the rect from its position + * @param fromPosition A position specified to be the starting point of sweeping + * @param halfSize The halfSize of the sweeping rect + */ + sweep(velocity, fromPosition, halfSize) { + if (!fromPosition) { + fromPosition = this.center; + } + if (!halfSize) { + halfSize = this.halfSize; + } + let centerX = fromPosition.x + velocity.x / 2; + let centerY = fromPosition.y + velocity.y / 2; + let minX = Math.min(fromPosition.x - halfSize.x, fromPosition.x + velocity.x - halfSize.x); + let minY = Math.min(fromPosition.y - halfSize.y, fromPosition.y + velocity.y - halfSize.y); + this.center.set(centerX, centerY); + this.halfSize.set(centerX - minX, centerY - minY); + } + // @override + clone() { + return new AABB(this.center.clone(), this.halfSize.clone()); + } + /** + * Converts this AABB to a string format + * @returns (center: (x, y), halfSize: (x, y)) + */ + toString() { + return "(center: " + this.center.toString() + ", half-size: " + this.halfSize.toString() + ")"; + } +} +exports.default = AABB; + +},{"../../Utils/MathUtils":102,"../Physics/Hit":13,"../Vec2":24,"./Circle":17,"./Shape":18}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../Vec2"); +const AABB_1 = require("./AABB"); +const Shape_1 = require("./Shape"); +/** + * A Circle + */ +class Circle extends Shape_1.default { + /** + * Creates a new Circle + * @param center The center of the circle + * @param radius The radius of the circle + */ + constructor(center, radius) { + super(); + this._center = center ? center : new Vec2_1.default(0, 0); + this.radius = radius ? radius : 0; + } + get center() { + return this._center; + } + set center(center) { + this._center = center; + } + get halfSize() { + return new Vec2_1.default(this.radius, this.radius); + } + get r() { + return this.radius; + } + set r(radius) { + this.radius = radius; + } + // @override + /** + * A simple boolean check of whether this AABB contains a point + * @param point The point to check + * @returns A boolean representing whether this AABB contains the specified point + */ + containsPoint(point) { + return this.center.distanceSqTo(point) <= this.radius * this.radius; + } + // @override + getBoundingRect() { + return new AABB_1.default(this._center.clone(), new Vec2_1.default(this.radius, this.radius)); + } + // @override + getBoundingCircle() { + return this.clone(); + } + // @override + overlaps(other) { + throw new Error("Method not implemented."); + } + // @override + clone() { + return new Circle(this._center.clone(), this.radius); + } + toString() { + return "(center: " + this.center.toString() + ", radius: " + this.radius + ")"; + } +} +exports.default = Circle; + +},{"../Vec2":24,"./AABB":16,"./Shape":18}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../Vec2"); +const AABB_1 = require("./AABB"); +/** + * An abstract Shape class that acts as an interface for better interactions with subclasses. + */ +class Shape { + get x() { + return this.center.x; + } + get y() { + return this.center.y; + } + get hw() { + return this.halfSize.x; + } + get hh() { + return this.halfSize.y; + } + get top() { + return this.y - this.hh; + } + get bottom() { + return this.y + this.hh; + } + get left() { + return this.x - this.hw; + } + get right() { + return this.x + this.hw; + } + static getTimeOfCollision(A, velA, B, velB) { + if (A instanceof AABB_1.default && B instanceof AABB_1.default) { + return Shape.getTimeOfCollision_AABB_AABB(A, velA, B, velB); + } + } + static getTimeOfCollision_AABB_AABB(A, velA, B, velB) { + let posSmaller = A.center; + let posLarger = B.center; + let sizeSmaller = A.halfSize; + let sizeLarger = B.halfSize; + let firstContact = new Vec2_1.default(0, 0); + let lastContact = new Vec2_1.default(0, 0); + let collidingX = false; + let collidingY = false; + // Sort by position + if (posLarger.x < posSmaller.x) { + // Swap, because smaller is further right than larger + let temp; + temp = sizeSmaller; + sizeSmaller = sizeLarger; + sizeLarger = temp; + temp = posSmaller; + posSmaller = posLarger; + posLarger = temp; + temp = velA; + velA = velB; + velB = temp; + } + // A is left, B is right + firstContact.x = Infinity; + lastContact.x = Infinity; + if (posLarger.x - sizeLarger.x >= posSmaller.x + sizeSmaller.x) { + // If we aren't currently colliding + let relVel = velA.x - velB.x; + if (relVel > 0) { + // If they are moving towards each other + firstContact.x = ((posLarger.x - sizeLarger.x) - (posSmaller.x + sizeSmaller.x)) / (relVel); + lastContact.x = ((posLarger.x + sizeLarger.x) - (posSmaller.x - sizeSmaller.x)) / (relVel); + } + } + else { + collidingX = true; + } + if (posLarger.y < posSmaller.y) { + // Swap, because smaller is further up than larger + let temp; + temp = sizeSmaller; + sizeSmaller = sizeLarger; + sizeLarger = temp; + temp = posSmaller; + posSmaller = posLarger; + posLarger = temp; + temp = velA; + velA = velB; + velB = temp; + } + // A is top, B is bottom + firstContact.y = Infinity; + lastContact.y = Infinity; + if (posLarger.y - sizeLarger.y >= posSmaller.y + sizeSmaller.y) { + // If we aren't currently colliding + let relVel = velA.y - velB.y; + if (relVel > 0) { + // If they are moving towards each other + firstContact.y = ((posLarger.y - sizeLarger.y) - (posSmaller.y + sizeSmaller.y)) / (relVel); + lastContact.y = ((posLarger.y + sizeLarger.y) - (posSmaller.y - sizeSmaller.y)) / (relVel); + } + } + else { + collidingY = true; + } + return [firstContact, lastContact, collidingX, collidingY]; + } +} +exports.default = Shape; + +},{"../Vec2":24,"./AABB":16}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * A LIFO stack with items of type T + */ +class Stack { + /** + * Constructs a new stack + * @param maxElements The maximum size of the stack + */ + constructor(maxElements = 100) { + this.MAX_ELEMENTS = maxElements; + this.stack = new Array(this.MAX_ELEMENTS); + this.head = -1; + } + /** + * Adds an item to the top of the stack + * @param item The new item to add to the stack + */ + push(item) { + if (this.head + 1 === this.MAX_ELEMENTS) { + throw "Stack full - cannot add element"; + } + this.head += 1; + this.stack[this.head] = item; + } + /** + * Removes an item from the top of the stack + * @returns The item at the top of the stack + */ + pop() { + if (this.head === -1) { + throw "Stack empty - cannot remove element"; + } + this.head -= 1; + return this.stack[this.head + 1]; + } + /** + * Returns the element currently at the top of the stack + * @returns The item at the top of the stack + */ + peek() { + if (this.head === -1) { + throw "Stack empty - cannot get element"; + } + return this.stack[this.head]; + } + /** Returns true if this stack is empty + * @returns A boolean that represents whether or not the stack is empty + */ + isEmpty() { + return this.head === -1; + } + // @implemented + clear() { + this.forEach((item, index) => delete this.stack[index]); + this.head = -1; + } + /** + * Returns the number of items currently in the stack + * @returns The number of items in the stack + */ + size() { + return this.head + 1; + } + // @implemented + forEach(func) { + let i = 0; + while (i <= this.head) { + func(this.stack[i], i); + i += 1; + } + } + /** + * Converts this stack into a string format + * @returns A string representing this stack + */ + toString() { + let retval = ""; + this.forEach((item, index) => { + let str = item.toString(); + if (index !== 0) { + str += " -> "; + } + retval = str + retval; + }); + return "Top -> " + retval; + } +} +exports.default = Stack; + +},{}],20:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Emitter_1 = require("../../Events/Emitter"); +/** + * An abstract implementation of a state for a @reference[StateMachine]. + * This class should be extended to allow for custom state behaviors. + */ +class State { + /** + * Constructs a new State + * @param parent The parent StateMachine of this state + */ + constructor(parent) { + this.parent = parent; + this.emitter = new Emitter_1.default(); + } + /** + * Tells the state machine that this state has ended, and makes it transition to the new state specified + * @param stateName The name of the state to transition to + */ + finished(stateName) { + this.parent.changeState(stateName); + } +} +exports.default = State; + +},{"../../Events/Emitter":27}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Stack_1 = require("../Stack"); +const Map_1 = require("../Map"); +const Receiver_1 = require("../../Events/Receiver"); +const Emitter_1 = require("../../Events/Emitter"); +/** + * An implementation of a Push Down Automata State machine. States can also be hierarchical + * for more flexibility, as described in @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/state.html). + */ +class StateMachine { + /** + * Creates a new StateMachine + */ + constructor() { + this.stack = new Stack_1.default(); + this.stateMap = new Map_1.default(); + this.receiver = new Receiver_1.default(); + this.emitter = new Emitter_1.default(); + this.emitEventOnStateChange = false; + } + /** + * Sets the activity state of this state machine + * @param flag True if you want to set this machine running, false otherwise + */ + setActive(flag) { + this.active = flag; + } + /** + * Makes this state machine emit an event any time its state changes + * @param stateChangeEventName The name of the event to emit + */ + setEmitEventOnStateChange(stateChangeEventName) { + this.emitEventOnStateChange = true; + this.stateChangeEventName = stateChangeEventName; + } + /** + * Stops this state machine from emitting events on state change. + */ + cancelEmitEventOnStateChange() { + this.emitEventOnStateChange = false; + } + /** + * Initializes this state machine with an initial state and sets it running + * @param initialState The name of initial state of the state machine + */ + initialize(initialState, options) { + this.stack.push(this.stateMap.get(initialState)); + this.currentState = this.stack.peek(); + this.currentState.onEnter(options); + this.setActive(true); + } + /** + * Adds a state to this state machine + * @param stateName The name of the state to add + * @param state The state to add + */ + addState(stateName, state) { + this.stateMap.add(stateName, state); + } + /** + * Changes the state of this state machine to the provided string + * @param state The string name of the state to change to + */ + changeState(state) { + // Exit the current state + let options = this.currentState.onExit(); + // Make sure the correct state is at the top of the stack + if (state === "previous") { + // Pop the current state off the stack + this.stack.pop(); + } + else { + // Retrieve the new state from the statemap and put it at the top of the stack + this.stack.pop(); + this.stack.push(this.stateMap.get(state)); + } + // Retreive the new state from the stack + this.currentState = this.stack.peek(); + // Emit an event if turned on + if (this.emitEventOnStateChange) { + this.emitter.fireEvent(this.stateChangeEventName, { state: this.currentState }); + } + // Enter the new state + this.currentState.onEnter(options); + } + /** + * Handles input. This happens at the very beginning of this state machine's update cycle. + * @param event The game event to process + */ + handleEvent(event) { + if (this.active) { + this.currentState.handleInput(event); + } + } + // @implemented + update(deltaT) { + // Distribute events + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + this.handleEvent(event); + } + // Delegate the update to the current state + this.currentState.update(deltaT); + } +} +exports.default = StateMachine; + +},{"../../Events/Emitter":27,"../../Events/Receiver":31,"../Map":10,"../Stack":19}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TiledCollectionTile = exports.TiledObject = exports.TiledLayerData = exports.TiledTilesetData = exports.TiledLayerProperty = exports.TiledTilemapData = void 0; +// @ignorePage +/** + * a representation of Tiled's tilemap data + */ +class TiledTilemapData { +} +exports.TiledTilemapData = TiledTilemapData; +/** + * A representation of a custom layer property in a Tiled tilemap + */ +class TiledLayerProperty { +} +exports.TiledLayerProperty = TiledLayerProperty; +/** + * A representation of a tileset in a Tiled tilemap + */ +class TiledTilesetData { +} +exports.TiledTilesetData = TiledTilesetData; +/** + * A representation of a layer in a Tiled tilemap + */ +class TiledLayerData { +} +exports.TiledLayerData = TiledLayerData; +class TiledObject { + ; +} +exports.TiledObject = TiledObject; +class TiledCollectionTile { +} +exports.TiledCollectionTile = TiledCollectionTile; + +},{}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const Vec2_1 = require("../Vec2"); +/** + * The data representation of a Tileset for the game engine. This represents one image, + * with a startIndex if required (as it is with Tiled using two images in one tilset). + */ +class Tileset { + // TODO: Change this to be more general and work with other tileset formats + constructor(tilesetData) { + // Defer handling of the data to a helper class + this.initFromTiledData(tilesetData); + } + /** + * Initialize the tileset from the data from a Tiled json file + * @param tiledData The parsed object from a Tiled json file + */ + initFromTiledData(tiledData) { + this.numRows = tiledData.tilecount / tiledData.columns; + this.numCols = tiledData.columns; + this.startIndex = tiledData.firstgid; + this.endIndex = this.startIndex + tiledData.tilecount - 1; + this.tileSize = new Vec2_1.default(tiledData.tilewidth, tiledData.tilewidth); + this.imageKey = tiledData.image; + this.imageSize = new Vec2_1.default(tiledData.imagewidth, tiledData.imageheight); + } + /** + * Gets the image key associated with this tilemap + * @returns The image key of this tilemap + */ + getImageKey() { + return this.imageKey; + } + /** + * Returns a Vec2 containing the left and top offset from the image origin for this tile. + * @param tileIndex The index of the tile from startIndex to endIndex of this tileset + * @returns A Vec2 containing the offset for the specified tile. + */ + getImageOffsetForTile(tileIndex) { + // Get the true index + let index = tileIndex - this.startIndex; + let row = Math.floor(index / this.numCols); + let col = index % this.numCols; + let width = this.tileSize.x; + let height = this.tileSize.y; + // Calculate the position to start a crop in the tileset image + let left = col * width; + let top = row * height; + return new Vec2_1.default(left, top); + } + /** + * Gets the start index + * @returns The start index + */ + getStartIndex() { + return this.startIndex; + } + /** + * Gets the tile set + * @returns A Vec2 containing the tile size + */ + getTileSize() { + return this.tileSize; + } + /** + * Gets the number of rows in the tileset + * @returns The number of rows + */ + getNumRows() { + return this.numRows; + } + /** + * Gets the number of columns in the tilset + * @returns The number of columns + */ + getNumCols() { + return this.numCols; + } + getTileCount() { + return this.endIndex - this.startIndex + 1; + } + /** + * Checks whether or not this tilset contains the specified tile index. This is used for rendering. + * @param tileIndex The index of the tile to check + * @returns A boolean representing whether or not this tilset uses the specified index + */ + hasTile(tileIndex) { + return tileIndex >= this.startIndex && tileIndex <= this.endIndex; + } + /** + * Render a singular tile with index tileIndex from the tileset located at position dataIndex + * @param ctx The rendering context + * @param tileIndex The value of the tile to render + * @param dataIndex The index of the tile in the data array + * @param worldSize The size of the world + * @param origin The viewport origin in the current layer + * @param scale The scale of the tilemap + */ + renderTile(ctx, tileIndex, dataIndex, maxCols, origin, scale, zoom) { + let image = ResourceManager_1.default.getInstance().getImage(this.imageKey); + // Get the true index + let index = tileIndex - this.startIndex; + let row = Math.floor(index / this.numCols); + let col = index % this.numCols; + let width = this.tileSize.x; + let height = this.tileSize.y; + // Calculate the position to start a crop in the tileset image + let left = col * width; + let top = row * height; + // Calculate the position in the world to render the tile + let x = Math.floor((dataIndex % maxCols) * width * scale.x); + let y = Math.floor(Math.floor(dataIndex / maxCols) * height * scale.y); + ctx.drawImage(image, left, top, width, height, Math.floor((x - origin.x) * zoom), Math.floor((y - origin.y) * zoom), Math.ceil(width * scale.x * zoom), Math.ceil(height * scale.y * zoom)); + } +} +exports.default = Tileset; + +},{"../../ResourceManager/ResourceManager":83,"../Vec2":24}],24:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("../Utils/MathUtils"); +/** + * A two-dimensional vector (x, y) + */ +class Vec2 { + /** + * Creates a new Vec2 + * @param x The x value of the vector + * @param y The y value of the vector + */ + constructor(x = 0, y = 0) { + /** + * When this vector changes its value, do something + */ + this.onChange = () => { }; + this.vec = new Float32Array(2); + this.vec[0] = x; + this.vec[1] = y; + } + // Expose x and y with getters and setters + get x() { + return this.vec[0]; + } + set x(x) { + this.vec[0] = x; + if (this.onChange) { + this.onChange(); + } + } + get y() { + return this.vec[1]; + } + set y(y) { + this.vec[1] = y; + if (this.onChange) { + this.onChange(); + } + } + static get ZERO() { + return new Vec2(0, 0); + } + static get INF() { + return new Vec2(Infinity, Infinity); + } + static get UP() { + return new Vec2(0, -1); + } + static get DOWN() { + return new Vec2(0, 1); + } + static get LEFT() { + return new Vec2(-1, 0); + } + static get RIGHT() { + return new Vec2(1, 0); + } + /** + * The squared magnitude of the vector. This tends to be faster, so use it in situations where taking the + * square root doesn't matter, like for comparing distances. + * @returns The squared magnitude of the vector + */ + magSq() { + return this.x * this.x + this.y * this.y; + } + /** + * The magnitude of the vector. + * @returns The magnitude of the vector. + */ + mag() { + return Math.sqrt(this.magSq()); + } + /** + * Divdes x and y by the magnitude to obtain the unit vector in the direction of this vector. + * @returns This vector as a unit vector. + */ + normalize() { + if (this.x === 0 && this.y === 0) + return this; + let mag = this.mag(); + this.x /= mag; + this.y /= mag; + return this; + } + /** + * Works like normalize(), but returns a new Vec2 + * @returns A new vector that is the unit vector for this one + */ + normalized() { + if (this.isZero()) { + return this; + } + let mag = this.mag(); + return new Vec2(this.x / mag, this.y / mag); + } + /** + * Sets the x and y elements of this vector to zero. + * @returns This vector, with x and y set to zero. + */ + zero() { + return this.set(0, 0); + } + /** + * Sets the vector's x and y based on the angle provided. Goes counter clockwise. + * @param angle The angle in radians + * @param radius The magnitude of the vector at the specified angle + * @returns This vector. + */ + setToAngle(angle, radius = 1) { + this.x = MathUtils_1.default.floorToPlace(Math.cos(angle) * radius, 5); + this.y = MathUtils_1.default.floorToPlace(-Math.sin(angle) * radius, 5); + return this; + } + /** + * Returns a vector that point from this vector to another one + * @param other The vector to point to + * @returns A new Vec2 that points from this vector to the one provided + */ + vecTo(other) { + return new Vec2(other.x - this.x, other.y - this.y); + } + /** + * Returns a vector containing the direction from this vector to another + * @param other The vector to point to + * @returns A new Vec2 that points from this vector to the one provided. This new Vec2 will be a unit vector. + */ + dirTo(other) { + return this.vecTo(other).normalize(); + } + /** + * Keeps the vector's direction, but sets its magnitude to be the provided magnitude + * @param magnitude The magnitude the vector should be + * @returns This vector with its magnitude set to the new magnitude + */ + scaleTo(magnitude) { + return this.normalize().scale(magnitude); + } + /** + * Scales x and y by the number provided, or if two number are provided, scales them individually. + * @param factor The scaling factor for the vector, or for only the x-component if yFactor is provided + * @param yFactor The scaling factor for the y-component of the vector + * @returns This vector after scaling + */ + scale(factor, yFactor = null) { + if (yFactor !== null) { + this.x *= factor; + this.y *= yFactor; + return this; + } + this.x *= factor; + this.y *= factor; + return this; + } + /** + * Returns a scaled version of this vector without modifying it. + * @param factor The scaling factor for the vector, or for only the x-component if yFactor is provided + * @param yFactor The scaling factor for the y-component of the vector + * @returns A new vector that has the values of this vector after scaling + */ + scaled(factor, yFactor = null) { + return this.clone().scale(factor, yFactor); + } + /** + * Rotates the vector counter-clockwise by the angle amount specified + * @param angle The angle to rotate by in radians + * @returns This vector after rotation. + */ + rotateCCW(angle) { + let cs = Math.cos(angle); + let sn = Math.sin(angle); + let tempX = this.x * cs - this.y * sn; + let tempY = this.x * sn + this.y * cs; + this.x = tempX; + this.y = tempY; + return this; + } + /** + * Sets the vectors coordinates to be the ones provided + * @param x The new x value for this vector + * @param y The new y value for this vector + * @returns This vector + */ + set(x, y) { + this.x = x; + this.y = y; + return this; + } + /** + * Copies the values of the other Vec2 into this one. + * @param other The Vec2 to copy + * @returns This vector with its values set to the vector provided + */ + copy(other) { + return this.set(other.x, other.y); + } + /** + * Adds this vector the another vector + * @param other The Vec2 to add to this one + * @returns This vector after adding the one provided + */ + add(other) { + this.x += other.x; + this.y += other.y; + return this; + } + /** + * Increments the fields of this vector. Both are incremented with a, if only a is provided. + * @param a The first number to increment by + * @param b The second number to increment by + * @returnss This vector after incrementing + */ + inc(a, b) { + if (b === undefined) { + this.x += a; + this.y += a; + } + else { + this.x += a; + this.y += b; + } + return this; + } + /** + * Subtracts another vector from this vector + * @param other The Vec2 to subtract from this one + * @returns This vector after subtracting the one provided + */ + sub(other) { + this.x -= other.x; + this.y -= other.y; + return this; + } + /** + * Multiplies this vector with another vector element-wise. In other words, this.x *= other.x and this.y *= other.y + * @param other The Vec2 to multiply this one by + * @returns This vector after multiplying its components by this one + */ + mult(other) { + this.x *= other.x; + this.y *= other.y; + return this; + } + /** + * Divides this vector with another vector element-wise. In other words, this.x /= other.x and this.y /= other.y + * @param other The vector to divide this one by + * @returns This vector after division + */ + div(other) { + if (other.x === 0 || other.y === 0) + throw "Divide by zero error"; + this.x /= other.x; + this.y /= other.y; + return this; + } + /** + * Does an element wise remainder operation on this vector. this.x %= other.x and this.y %= other.y + * @param other The other vector + * @returns this vector + */ + remainder(other) { + this.x = this.x % other.x; + this.y = this.y % other.y; + return this; + } + /** + * Returns the squared distance between this vector and another vector + * @param other The vector to compute distance squared to + * @returns The squared distance between this vector and the one provided + */ + distanceSqTo(other) { + return (this.x - other.x) * (this.x - other.x) + (this.y - other.y) * (this.y - other.y); + } + /** + * Returns the distance between this vector and another vector + * @param other The vector to compute distance to + * @returns The distance between this vector and the one provided + */ + distanceTo(other) { + return Math.sqrt(this.distanceSqTo(other)); + } + /** + * Returns the dot product of this vector and another + * @param other The vector to compute the dot product with + * @returns The dot product of this vector and the one provided. + */ + dot(other) { + return this.x * other.x + this.y * other.y; + } + /** + * Returns the angle counter-clockwise in radians from this vector to another vector + * @param other The vector to compute the angle to + * @returns The angle, rotating CCW, from this vector to the other vector + */ + angleToCCW(other) { + let dot = this.dot(other); + let det = this.x * other.y - this.y * other.x; + let angle = -Math.atan2(det, dot); + if (angle < 0) { + angle += 2 * Math.PI; + } + return angle; + } + /** + * Returns a string representation of this vector rounded to 1 decimal point + * @returns This vector as a string + */ + toString() { + return this.toFixed(); + } + /** + * Returns a string representation of this vector rounded to the specified number of decimal points + * @param numDecimalPoints The number of decimal points to create a string to + * @returns This vector as a string + */ + toFixed(numDecimalPoints = 1) { + return "(" + this.x.toFixed(numDecimalPoints) + ", " + this.y.toFixed(numDecimalPoints) + ")"; + } + /** + * Returns a new vector with the same coordinates as this one. + * @returns A new Vec2 with the same values as this one + */ + clone() { + return new Vec2(this.x, this.y); + } + /** + * Returns true if this vector and other have the EXACT same x and y (not assured to be safe for floats) + * @param other The vector to check against + * @returns A boolean representing the equality of the two vectors + */ + strictEquals(other) { + return this.x === other.x && this.y === other.y; + } + /** + * Returns true if this vector and other have the same x and y + * @param other The vector to check against + * @returns A boolean representing the equality of the two vectors + */ + equals(other) { + let xEq = Math.abs(this.x - other.x) < 0.0000001; + let yEq = Math.abs(this.y - other.y) < 0.0000001; + return xEq && yEq; + } + /** + * Returns true if this vector is the zero vector exactly (not assured to be safe for floats). + * @returns A boolean representing the equality of this vector and the zero vector + */ + strictIsZero() { + return this.x === 0 && this.y === 0; + } + /** + * Returns true if this x and y for this vector are both zero. + * @returns A boolean representing the equality of this vector and the zero vector + */ + isZero() { + return Math.abs(this.x) < 0.0000001 && Math.abs(this.y) < 0.0000001; + } + /** + * Sets the function that is called whenever this vector is changed. + * @param f The function to be called + */ + setOnChange(f) { + this.onChange = f; + } + toArray() { + return this.vec; + } + /** + * Performs linear interpolation between two vectors + * @param a The first vector + * @param b The second vector + * @param t The time of the lerp, with 0 being vector A, and 1 being vector B + * @returns A new Vec2 representing the lerp between vector a and b. + */ + static lerp(a, b, t) { + return new Vec2(MathUtils_1.default.lerp(a.x, b.x, t), MathUtils_1.default.lerp(a.y, b.y, t)); + } +} +exports.default = Vec2; +Vec2.ZERO_STATIC = new Vec2(0, 0); + +},{"../Utils/MathUtils":102}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +const Vec2_1 = require("../DataTypes/Vec2"); +const Color_1 = require("../Utils/Color"); +/** + * A util class for rendering Debug messages to the canvas. + */ +class Debug { + /** + * Add a message to display on the debug screen + * @param id A unique ID for this message + * @param messages The messages to print to the debug screen + */ + static log(id, ...messages) { + // let message = ""; + // for(let i = 0; i < messages.length; i++){ + // message += messages[i].toString(); + // } + // Join all messages with spaces + let message = messages.map((m) => m.toString()).join(" "); + this.logMessages.add(id, message); + } + /** + * Deletes a a key from the log and stops it from keeping up space on the screen + * @param id The id of the log item to clear + */ + static clearLogItem(id) { + this.logMessages.delete(id); + } + /** + * Sets the list of nodes to render with the debugger + * @param nodes The new list of nodes + */ + static setNodes(nodes) { + this.nodes = nodes; + } + /** + * Draws a box at the specified position + * @param center The center of the box + * @param halfSize The dimensions of the box + * @param filled A boolean for whether or not the box is filled + * @param color The color of the box to draw + */ + static drawBox(center, halfSize, filled, color) { + let alpha = this.debugRenderingContext.globalAlpha; + this.debugRenderingContext.globalAlpha = color.a; + if (filled) { + this.debugRenderingContext.fillStyle = color.toString(); + this.debugRenderingContext.fillRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x * 2, halfSize.y * 2); + } + else { + let lineWidth = 2; + this.debugRenderingContext.lineWidth = lineWidth; + this.debugRenderingContext.strokeStyle = color.toString(); + this.debugRenderingContext.strokeRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x * 2, halfSize.y * 2); + } + this.debugRenderingContext.globalAlpha = alpha; + } + /** + * Draws a circle at the specified position + * @param center The center of the circle + * @param radius The dimensions of the box + * @param filled A boolean for whether or not the circle is filled + * @param color The color of the circle + */ + static drawCircle(center, radius, filled, color) { + let alpha = this.debugRenderingContext.globalAlpha; + this.debugRenderingContext.globalAlpha = color.a; + if (filled) { + this.debugRenderingContext.fillStyle = color.toString(); + this.debugRenderingContext.beginPath(); + this.debugRenderingContext.arc(center.x, center.y, radius, 0, 2 * Math.PI); + this.debugRenderingContext.closePath(); + this.debugRenderingContext.fill(); + } + else { + let lineWidth = 2; + this.debugRenderingContext.lineWidth = lineWidth; + this.debugRenderingContext.strokeStyle = color.toString(); + this.debugRenderingContext.beginPath(); + this.debugRenderingContext.arc(center.x, center.y, radius, 0, 2 * Math.PI); + this.debugRenderingContext.closePath(); + this.debugRenderingContext.stroke(); + } + this.debugRenderingContext.globalAlpha = alpha; + } + /** + * Draws a ray at the specified position + * @param from The starting position of the ray + * @param to The ending position of the ray + * @param color The color of the ray + */ + static drawRay(from, to, color) { + this.debugRenderingContext.lineWidth = 2; + this.debugRenderingContext.strokeStyle = color.toString(); + this.debugRenderingContext.beginPath(); + this.debugRenderingContext.moveTo(from.x, from.y); + this.debugRenderingContext.lineTo(to.x, to.y); + this.debugRenderingContext.closePath(); + this.debugRenderingContext.stroke(); + } + /** + * Draws a point at the specified position + * @param pos The position of the point + * @param color The color of the point + */ + static drawPoint(pos, color) { + let pointSize = 6; + this.debugRenderingContext.fillStyle = color.toString(); + this.debugRenderingContext.fillRect(pos.x - pointSize / 2, pos.y - pointSize / 2, pointSize, pointSize); + } + /** + * Sets the default rendering color for text for the debugger + * @param color The color to render the text + */ + static setDefaultTextColor(color) { + this.defaultTextColor = color; + } + /** + * Performs any necessary setup operations on the Debug canvas + * @param canvas The debug canvas + * @param width The desired width of the canvas + * @param height The desired height of the canvas + * @returns The rendering context extracted from the canvas + */ + static initializeDebugCanvas(canvas, width, height) { + canvas.width = width; + canvas.height = height; + this.debugCanvasSize = new Vec2_1.default(width, height); + this.debugRenderingContext = canvas.getContext("2d"); + return this.debugRenderingContext; + } + /** Clears the debug canvas */ + static clearCanvas() { + this.debugRenderingContext.clearRect(0, 0, this.debugCanvasSize.x, this.debugCanvasSize.y); + } + /** Renders the text and nodes sent to the Debug system */ + static render() { + this.renderText(); + this.renderNodes(); + } + /** Renders the text sent to the Debug canvas */ + static renderText() { + let y = 20; + this.debugRenderingContext.font = "20px Arial"; + this.debugRenderingContext.fillStyle = this.defaultTextColor.toString(); + // Draw all of the text + this.logMessages.forEach((key) => { + this.debugRenderingContext.fillText(this.logMessages.get(key), 10, y); + y += 30; + }); + } + /** Renders the nodes registered with the debug canvas */ + static renderNodes() { + if (this.nodes) { + this.nodes.forEach(node => { + node.debugRender(); + }); + } + } +} +exports.default = Debug; +/** A map of log messages to display on the screen */ +Debug.logMessages = new Map_1.default(); +/** The rendering color for text */ +Debug.defaultTextColor = Color_1.default.WHITE; + +},{"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Utils/Color":99}],26:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Color_1 = require("../Utils/Color"); +// @ignorePage +class Stats extends Object { + static initStats() { + let canvas = document.getElementById("stats-canvas"); + canvas.width = this.CANVAS_WIDTH; + canvas.height = this.CANVAS_HEIGHT; + this.ctx = canvas.getContext("2d"); + this.statsDiv = document.getElementById("stats-display"); + this.prevfps = new Array(); + this.prevClearTimes = new Array(); + this.SGClearTimes = new Array(); + this.avgSGClearTime = 0; + this.prevFillTimes = new Array(); + this.SGFillTimes = new Array(); + this.avgSGFillTime = 0; + this.prevUpdateTimes = new Array(); + this.SGUpdateTimes = new Array(); + this.avgSGUpdateTime = 0; + this.prevQueryTimes = new Array(); + this.SGQueryTimes = new Array(); + this.avgSGQueryTime = 0; + let clearTime = document.createElement("span"); + clearTime.setAttribute("id", "sgclear"); + let fillTime = document.createElement("span"); + fillTime.setAttribute("id", "sgfill"); + let updateTime = document.createElement("span"); + updateTime.setAttribute("id", "sgupdate"); + let queryTime = document.createElement("span"); + queryTime.setAttribute("id", "sgquery"); + let br1 = document.createElement("br"); + let br2 = document.createElement("br"); + let br3 = document.createElement("br"); + this.statsDiv.append(clearTime, br1, fillTime, br2, updateTime, br3, queryTime); + this.graphChoices = document.getElementById("chart-option"); + let option1 = document.createElement("option"); + option1.value = "prevfps"; + option1.label = "FPS"; + let option2 = document.createElement("option"); + option2.value = "prevClearTimes"; + option2.label = "Clear Time"; + let option3 = document.createElement("option"); + option3.value = "prevFillTimes"; + option3.label = "Fill time"; + let option4 = document.createElement("option"); + option4.value = "prevUpdateTimes"; + option4.label = "Update time"; + let option5 = document.createElement("option"); + option5.value = "prevQueryTimes"; + option5.label = "Query Time"; + let optionAll = document.createElement("option"); + optionAll.value = "all"; + optionAll.label = "All"; + this.graphChoices.append(option1, option2, option3, option4, option5, optionAll); + } + static updateFPS(fps) { + this.prevfps.push(fps); + if (this.prevfps.length > Stats.NUM_POINTS) { + this.prevfps.shift(); + } + if (this.SGClearTimes.length > 0) { + this.prevClearTimes.push(this.avgSGClearTime); + if (this.prevClearTimes.length > this.NUM_POINTS) { + this.prevClearTimes.shift(); + } + } + if (this.SGFillTimes.length > 0) { + this.prevFillTimes.push(this.avgSGFillTime); + if (this.prevFillTimes.length > this.NUM_POINTS) { + this.prevFillTimes.shift(); + } + } + if (this.SGUpdateTimes.length > 0) { + this.prevUpdateTimes.push(this.avgSGUpdateTime); + if (this.prevUpdateTimes.length > this.NUM_POINTS) { + this.prevUpdateTimes.shift(); + } + } + if (this.SGQueryTimes.length > 0) { + this.prevQueryTimes.push(this.avgSGQueryTime); + if (this.prevQueryTimes.length > this.NUM_POINTS) { + this.prevQueryTimes.shift(); + } + } + this.updateSGStats(); + } + static log(key, data) { + if (key === "sgclear") { + this.SGClearTimes.push(data); + if (this.SGClearTimes.length > 100) { + this.SGClearTimes.shift(); + } + } + else if (key === "sgfill") { + this.SGFillTimes.push(data); + if (this.SGFillTimes.length > 100) { + this.SGFillTimes.shift(); + } + } + else if (key === "sgupdate") { + this.SGUpdateTimes.push(data); + if (this.SGUpdateTimes.length > 100) { + this.SGUpdateTimes.shift(); + } + } + else if (key === "sgquery") { + this.SGQueryTimes.push(data); + if (this.SGQueryTimes.length > 1000) { + this.SGQueryTimes.shift(); + } + } + } + static render() { + // Display stats + this.drawCharts(); + } + static drawCharts() { + this.ctx.clearRect(0, 0, this.CANVAS_WIDTH, this.CANVAS_HEIGHT); + let paramString = this.graphChoices.value; + if (paramString === "prevfps" || paramString === "all") { + let param = this.prevfps; + let color = Color_1.default.BLUE.toString(); + this.drawChart(param, color); + } + if (paramString === "prevClearTimes" || paramString === "all") { + let param = this.prevClearTimes; + let color = Color_1.default.RED.toString(); + this.drawChart(param, color); + } + if (paramString === "prevFillTimes" || paramString === "all") { + let param = this.prevFillTimes; + let color = Color_1.default.GREEN.toString(); + this.drawChart(param, color); + } + if (paramString === "prevUpdateTimes" || paramString === "all") { + let param = this.prevUpdateTimes; + let color = Color_1.default.CYAN.toString(); + this.drawChart(param, color); + } + if (paramString === "prevQueryTimes" || paramString === "all") { + let param = this.prevQueryTimes; + let color = Color_1.default.ORANGE.toString(); + this.drawChart(param, color); + } + } + static drawChart(param, color) { + this.ctx.strokeStyle = Color_1.default.BLACK.toString(); + this.ctx.beginPath(); + this.ctx.moveTo(10, 10); + this.ctx.lineTo(10, this.CANVAS_HEIGHT - 10); + this.ctx.closePath(); + this.ctx.stroke(); + this.ctx.beginPath(); + this.ctx.moveTo(10, this.CANVAS_HEIGHT - 10); + this.ctx.lineTo(this.CANVAS_WIDTH - 10, this.CANVAS_HEIGHT - 10); + this.ctx.closePath(); + this.ctx.stroke(); + let max = Math.max(...param); + let prevX = 10; + let prevY = this.CANVAS_HEIGHT - 10 - param[0] / max * (this.CANVAS_HEIGHT - 20); + this.ctx.strokeStyle = color; + for (let i = 1; i < param.length; i++) { + let fps = param[i]; + let x = 10 + i * (this.CANVAS_WIDTH - 20) / this.NUM_POINTS; + let y = this.CANVAS_HEIGHT - 10 - fps / max * (this.CANVAS_HEIGHT - 20); + this.ctx.beginPath(); + this.ctx.moveTo(prevX, prevY); + this.ctx.lineTo(x, y); + this.ctx.closePath(); + this.ctx.stroke(); + prevX = x; + prevY = y; + } + } + static updateSGStats() { + if (this.SGClearTimes.length > 0) { + this.avgSGClearTime = this.SGClearTimes.reduce((acc, val) => acc + val) / this.SGClearTimes.length; + } + if (this.SGFillTimes.length > 0) { + this.avgSGFillTime = this.SGFillTimes.reduce((acc, val) => acc + val) / this.SGFillTimes.length; + } + if (this.SGUpdateTimes.length > 0) { + this.avgSGUpdateTime = this.SGUpdateTimes.reduce((acc, val) => acc + val) / this.SGUpdateTimes.length; + } + if (this.SGQueryTimes.length > 0) { + this.avgSGQueryTime = this.SGQueryTimes.reduce((acc, val) => acc + val) / this.SGQueryTimes.length; + } + document.getElementById("sgclear").innerHTML = "Avg SG clear time: " + this.avgSGClearTime; + document.getElementById("sgfill").innerHTML = "Avg SG fill time: " + this.avgSGFillTime; + document.getElementById("sgupdate").innerHTML = "Avg SG update time: " + this.avgSGUpdateTime; + document.getElementById("sgquery").innerHTML = "Avg SG query time: " + this.avgSGQueryTime; + } +} +exports.default = Stats; +Stats.NUM_POINTS = 60; +Stats.CANVAS_WIDTH = 300; +Stats.CANVAS_HEIGHT = 300; + +},{"../Utils/Color":99}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EventQueue_1 = require("./EventQueue"); +const GameEvent_1 = require("./GameEvent"); +/** + * An event emitter object other systems can use to hook into the EventQueue. + * Provides an easy interface for firing off events. + */ +class Emitter { + /** Creates a new Emitter */ + constructor() { + this.eventQueue = EventQueue_1.default.getInstance(); + } + /** + * Emit and event of type eventType with the data packet data + * @param eventType The name of the event to fire off + * @param data A @reference[Map] or record containing any data about the event + */ + fireEvent(eventType, data = null) { + this.eventQueue.addEvent(new GameEvent_1.default(eventType, data)); + } +} +exports.default = Emitter; + +},{"./EventQueue":28,"./GameEvent":29}],28:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Queue_1 = require("../DataTypes/Queue"); +const Map_1 = require("../DataTypes/Map"); +const GameEventType_1 = require("./GameEventType"); +/** + * The main event system of the game engine. + * Events are sent to the EventQueue, which handles distribution to any systems that are listening for those events. + * This allows for handling of input without having classes directly hook into javascript event handles, + * and allows otherwise separate classes to communicate with each other cleanly, such as a Player object + * requesting a sound be played by the audio system. + * + * The distribution of @reference[GameEvent]s happens as follows: + * + * Events are recieved throughout a frame and are queued up by the EventQueue. + * At the beginning of the next frame, events are sent out to any receivers that are hooked into the event type. + * @reference[Receiver]s are then free to process events as they see fit. + * + * Overall, the EventQueue can be considered as something similar to an email server, + * and the @reference[Receiver]s can be considered as the client inboxes. + * + * See @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/event-queue.html) for more discussion on EventQueues + */ +class EventQueue { + constructor() { + this.MAX_SIZE = 100; + this.q = new Queue_1.default(this.MAX_SIZE); + this.receivers = new Map_1.default(); + } + /** Retrieves the instance of the Singleton EventQueue */ + static getInstance() { + if (this.instance === null) { + this.instance = new EventQueue(); + } + return this.instance; + } + /** Adds an event to the EventQueue. + * This is exposed to the rest of the game engine through the @reference[Emitter] class */ + addEvent(event) { + this.q.enqueue(event); + } + /** + * Associates a receiver with a type of event. Every time this event appears in the future, + * it will be given to the receiver (and any others watching that type). + * This is exposed to the rest of the game engine through the @reference[Receiver] class + * @param receiver The event receiver + * @param type The type or types of events to subscribe to + */ + subscribe(receiver, type) { + if (type instanceof Array) { + // If it is an array, subscribe to all event types + for (let t of type) { + this.addListener(receiver, t); + } + } + else { + this.addListener(receiver, type); + } + } + /** + * Unsubscribes the specified receiver from all events, or from whatever events are provided + * @param receiver The receiver to unsubscribe + * @param keys The events to unsubscribe from. If none are provided, unsubscribe from all + */ + unsubscribe(receiver, ...events) { + this.receivers.forEach(eventName => { + // If keys were provided, only continue if this key is one of them + if (events.length > 0 && events.indexOf(eventName) === -1) + return; + // Find the index of our receiver for this key + let index = this.receivers.get(eventName).indexOf(receiver); + // If an index was found, remove the receiver + if (index !== -1) { + this.receivers.get(eventName).splice(index, 1); + } + }); + } + // Associate the receiver and the type + addListener(receiver, type) { + if (this.receivers.has(type)) { + this.receivers.get(type).push(receiver); + } + else { + this.receivers.add(type, [receiver]); + } + } + update(deltaT) { + while (this.q.hasItems()) { + // Retrieve each event + let event = this.q.dequeue(); + // If a receiver has this event type, send it the event + if (this.receivers.has(event.type)) { + for (let receiver of this.receivers.get(event.type)) { + receiver.receive(event); + } + } + // If a receiver is subscribed to all events, send it the event + if (this.receivers.has(GameEventType_1.GameEventType.ALL)) { + for (let receiver of this.receivers.get(GameEventType_1.GameEventType.ALL)) { + receiver.receive(event); + } + } + } + } +} +exports.default = EventQueue; +EventQueue.instance = null; + +},{"../DataTypes/Map":10,"../DataTypes/Queue":14,"./GameEventType":30}],29:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +/** + * A representation of an in-game event that is passed through the @reference[EventQueue] + */ +class GameEvent { + /** + * Creates a new GameEvent. + * This is handled implicitly through the @reference[Emitter] class + * @param type The type of the GameEvent + * @param data The data contained by the GameEvent + */ + constructor(type, data = null) { + // Parse the game event data + if (data === null) { + this.data = new Map_1.default(); + } + else if (!(data instanceof Map_1.default)) { + // data is a raw object, unpack + this.data = new Map_1.default(); + for (let key in data) { + this.data.add(key, data[key]); + } + } + else { + this.data = data; + } + this.type = type; + this.time = Date.now(); + } + /** + * Checks the type of the GameEvent + * @param type The type to check + * @returns True if the GameEvent is the specified type, false otherwise. + */ + isType(type) { + return this.type === type; + } + /** + * Returns this GameEvent as a string + * @returns The string representation of the GameEvent + */ + toString() { + return this.type + ": @" + this.time; + } +} +exports.default = GameEvent; + +},{"../DataTypes/Map":10}],30:[function(require,module,exports){ +"use strict"; +// @ignorePage +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GameEventType = void 0; +var GameEventType; +(function (GameEventType) { + /** + * Mouse Down event. Has data: {position: Vec2 - Mouse Position} + */ + GameEventType["MOUSE_DOWN"] = "mouse_down"; + /** + * Mouse Up event. Has data: {position: Vec2 - Mouse Position} + */ + GameEventType["MOUSE_UP"] = "mouse_up"; + /** + * Mouse Move event. Has data: {position: Vec2 - Mouse Position} + */ + GameEventType["MOUSE_MOVE"] = "mouse_move"; + /** + * Key Down event. Has data: {key: string - The key that is down} + */ + GameEventType["KEY_DOWN"] = "key_down"; + /** + * Key Up event. Has data: {key: string - The key that is up} + */ + GameEventType["KEY_UP"] = "key_up"; + /** + * Canvas Blur event. Has data: {} + */ + GameEventType["CANVAS_BLUR"] = "canvas_blur"; + /** + * Mouse wheel up event. Has data: {} + */ + GameEventType["WHEEL_UP"] = "wheel_up"; + /** + * Mouse wheel down event. Has data: {} + */ + GameEventType["WHEEL_DOWN"] = "wheel_down"; + /** + * Start Recording event. Has data: {} + */ + GameEventType["START_RECORDING"] = "start_recording"; + /** + * Stop Recording event. Has data: {} + */ + GameEventType["STOP_RECORDING"] = "stop_recording"; + /** + * Play Recording event. Has data: {} + */ + GameEventType["PLAY_RECORDING"] = "play_recording"; + /** + * Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean } + */ + GameEventType["PLAY_SOUND"] = "play_sound"; + /** + * Play Sound event. Has data: {key: string} + */ + GameEventType["STOP_SOUND"] = "stop_sound"; + /** + * Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean, channel: AudioChannelType } + */ + GameEventType["PLAY_SFX"] = "play_sfx"; + /** + * Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean } + */ + GameEventType["PLAY_MUSIC"] = "play_music"; + /** + * Mute audio channel event. Has data: {channel: AudioChannelType} + */ + GameEventType["MUTE_CHANNEL"] = "mute_channel"; + /** + * Unmute audio channel event. Has data: {channel: AudioChannelType} + */ + GameEventType["UNMUTE_CHANNEL"] = "unmute_channel"; + /** + * Encompasses all event types. Used for receivers only. + */ + GameEventType["ALL"] = "all"; +})(GameEventType = exports.GameEventType || (exports.GameEventType = {})); + +},{}],31:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Queue_1 = require("../DataTypes/Queue"); +const EventQueue_1 = require("./EventQueue"); +/** + * Receives subscribed events from the EventQueue. + */ +class Receiver { + /** Creates a new Receiver */ + constructor() { + this.MAX_SIZE = 100; + this.q = new Queue_1.default(this.MAX_SIZE); + } + destroy() { + EventQueue_1.default.getInstance().unsubscribe(this); + } + /** + * Adds these types of events to this receiver's queue every update. + * @param eventTypes The types of events this receiver will be subscribed to + */ + subscribe(eventTypes) { + EventQueue_1.default.getInstance().subscribe(this, eventTypes); + this.q.clear(); + } + /** + * Adds an event to the queue of this reciever. This is used by the @reference[EventQueue] to distribute events + * @param event The event to receive + */ + receive(event) { + try { + this.q.enqueue(event); + } + catch (e) { + console.warn("Receiver overflow for event " + event.toString()); + throw e; + } + } + /** + * Retrieves the next event from the receiver's queue + * @returns The next GameEvent + */ + getNextEvent() { + return this.q.dequeue(); + } + /** + * Looks at the next event in the receiver's queue, but doesn't remove it from the queue + * @returns The next GameEvent + */ + peekNextEvent() { + return this.q.peekNext(); + } + /** + * Returns true if the receiver has any events in its queue + * @returns True if the receiver has another event, false otherwise + */ + hasNextEvent() { + return this.q.hasItems(); + } + /** + * Ignore all events this frame + */ + ignoreEvents() { + this.q.clear(); + } +} +exports.default = Receiver; + +},{"../DataTypes/Queue":14,"./EventQueue":28}],32:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Receiver_1 = require("../Events/Receiver"); +const Map_1 = require("../DataTypes/Map"); +const Vec2_1 = require("../DataTypes/Vec2"); +const EventQueue_1 = require("../Events/EventQueue"); +const GameEventType_1 = require("../Events/GameEventType"); +/** + * Receives input events from the @reference[EventQueue] and allows for easy access of information about input by other systems + */ +class Input { + /** + * Initializes the Input object + * @param viewport A reference to the viewport of the game + */ + static initialize(viewport, keyMap) { + Input.viewport = viewport; + Input.mousePressed = false; + Input.mouseJustPressed = false; + Input.receiver = new Receiver_1.default(); + Input.keyJustPressed = new Map_1.default(); + Input.keyPressed = new Map_1.default(); + Input.mousePosition = new Vec2_1.default(0, 0); + Input.mousePressPosition = new Vec2_1.default(0, 0); + Input.scrollDirection = 0; + Input.justScrolled = false; + Input.keysDisabled = false; + Input.mouseDisabled = false; + // Initialize the keymap + Input.keyMap = new Map_1.default(); + // Add all keys to the keymap + for (let entry in keyMap) { + let name = keyMap[entry].name; + let keys = keyMap[entry].keys; + Input.keyMap.add(name, keys); + } + Input.eventQueue = EventQueue_1.default.getInstance(); + // Subscribe to all input events + Input.eventQueue.subscribe(Input.receiver, [GameEventType_1.GameEventType.MOUSE_DOWN, GameEventType_1.GameEventType.MOUSE_UP, GameEventType_1.GameEventType.MOUSE_MOVE, + GameEventType_1.GameEventType.KEY_DOWN, GameEventType_1.GameEventType.KEY_UP, GameEventType_1.GameEventType.CANVAS_BLUR, GameEventType_1.GameEventType.WHEEL_UP, GameEventType_1.GameEventType.WHEEL_DOWN]); + } + static update(deltaT) { + // Reset the justPressed values to false + Input.mouseJustPressed = false; + Input.keyJustPressed.forEach((key) => Input.keyJustPressed.set(key, false)); + Input.justScrolled = false; + Input.scrollDirection = 0; + while (Input.receiver.hasNextEvent()) { + let event = Input.receiver.getNextEvent(); + // Handle each event type + if (event.type === GameEventType_1.GameEventType.MOUSE_DOWN) { + Input.mouseJustPressed = true; + Input.mousePressed = true; + Input.mousePressPosition = event.data.get("position"); + Input.mouseButtonPressed = event.data.get("button"); + } + if (event.type === GameEventType_1.GameEventType.MOUSE_UP) { + Input.mousePressed = false; + } + if (event.type === GameEventType_1.GameEventType.MOUSE_MOVE) { + Input.mousePosition = event.data.get("position"); + } + if (event.type === GameEventType_1.GameEventType.KEY_DOWN) { + let key = event.data.get("key"); + // Handle space bar + if (key === " ") { + key = "space"; + } + if (!Input.keyPressed.get(key)) { + Input.keyJustPressed.set(key, true); + Input.keyPressed.set(key, true); + } + } + if (event.type === GameEventType_1.GameEventType.KEY_UP) { + let key = event.data.get("key"); + // Handle space bar + if (key === " ") { + key = "space"; + } + Input.keyPressed.set(key, false); + } + if (event.type === GameEventType_1.GameEventType.CANVAS_BLUR) { + Input.clearKeyPresses(); + } + if (event.type === GameEventType_1.GameEventType.WHEEL_UP) { + Input.scrollDirection = -1; + Input.justScrolled = true; + } + else if (event.type === GameEventType_1.GameEventType.WHEEL_DOWN) { + Input.scrollDirection = 1; + Input.justScrolled = true; + } + } + } + static clearKeyPresses() { + Input.keyJustPressed.forEach((key) => Input.keyJustPressed.set(key, false)); + Input.keyPressed.forEach((key) => Input.keyPressed.set(key, false)); + } + /** + * Returns whether or not a key was newly pressed Input frame. + * If the key is still pressed from last frame and wasn't re-pressed, Input will return false. + * @param key The key + * @returns True if the key was just pressed, false otherwise + */ + static isKeyJustPressed(key) { + if (Input.keysDisabled) + return false; + if (Input.keyJustPressed.has(key)) { + return Input.keyJustPressed.get(key); + } + else { + return false; + } + } + /** + * Returns an array of all of the keys that are newly pressed Input frame. + * If a key is still pressed from last frame and wasn't re-pressed, it will not be in Input list. + * @returns An array of all of the newly pressed keys. + */ + static getKeysJustPressed() { + if (Input.keysDisabled) + return []; + let keys = Array(); + Input.keyJustPressed.forEach(key => { + if (Input.keyJustPressed.get(key)) { + keys.push(key); + } + }); + return keys; + } + /** + * Returns whether or not a key is being pressed. + * @param key The key + * @returns True if the key is currently pressed, false otherwise + */ + static isKeyPressed(key) { + if (Input.keysDisabled) + return false; + if (Input.keyPressed.has(key)) { + return Input.keyPressed.get(key); + } + else { + return false; + } + } + /** + * Changes the binding of an input name to keys + * @param inputName The name of the input + * @param keys The corresponding keys + */ + static changeKeyBinding(inputName, keys) { + Input.keyMap.set(inputName, keys); + } + /** + * Clears all key bindings + */ + static clearAllKeyBindings() { + Input.keyMap.clear(); + } + /** + * Returns whether or not an input was just pressed this frame + * @param inputName The name of the input + * @returns True if the input was just pressed, false otherwise + */ + static isJustPressed(inputName) { + if (Input.keysDisabled) + return false; + if (Input.keyMap.has(inputName)) { + const keys = Input.keyMap.get(inputName); + let justPressed = false; + for (let key of keys) { + justPressed = justPressed || Input.isKeyJustPressed(key); + } + return justPressed; + } + else { + return false; + } + } + /** + * Returns whether or not an input is currently pressed + * @param inputName The name of the input + * @returns True if the input is pressed, false otherwise + */ + static isPressed(inputName) { + if (Input.keysDisabled) + return false; + if (Input.keyMap.has(inputName)) { + const keys = Input.keyMap.get(inputName); + let pressed = false; + for (let key of keys) { + pressed = pressed || Input.isKeyPressed(key); + } + return pressed; + } + else { + return false; + } + } + /** + * + * Returns whether or not the mouse was newly pressed Input frame. + * @param mouseButton Optionally specify which mouse click you want to know was pressed. + * 0 for left click, 1 for middle click, 2 for right click. + * @returns True if the mouse was just pressed, false otherwise + */ + static isMouseJustPressed(mouseButton) { + if (mouseButton !== undefined) { + return Input.mouseJustPressed && !Input.mouseDisabled && mouseButton == this.mouseButtonPressed; + } + return Input.mouseJustPressed && !Input.mouseDisabled; + } + /** + * Returns whether or not the mouse is currently pressed + * @param mouseButton Optionally specify which mouse click you want to know was pressed. + * 0 for left click, 1 for middle click, 2 for right click. + * @returns True if the mouse is currently pressed, false otherwise + */ + static isMousePressed(mouseButton) { + if (mouseButton !== undefined) { + return Input.mousePressed && !Input.mouseDisabled && mouseButton == this.mouseButtonPressed; + } + return Input.mousePressed && !Input.mouseDisabled; + } + /** + * Returns whether the user scrolled or not + * @returns True if the user just scrolled Input frame, false otherwise + */ + static didJustScroll() { + return Input.justScrolled && !Input.mouseDisabled; + } + /** + * Gets the direction of the scroll + * @returns -1 if the user scrolled up, 1 if they scrolled down + */ + static getScrollDirection() { + return Input.scrollDirection; + } + /** + * Gets the position of the player's mouse + * @returns The mouse position stored as a Vec2 + */ + static getMousePosition() { + return Input.mousePosition.scaled(1 / this.viewport.getZoomLevel()); + } + /** + * Gets the position of the player's mouse in the game world, + * taking into consideration the scrolling of the viewport + * @returns The mouse position stored as a Vec2 + */ + static getGlobalMousePosition() { + return Input.mousePosition.clone().scale(1 / this.viewport.getZoomLevel()).add(Input.viewport.getOrigin()); + } + /** + * Gets the position of the last mouse press + * @returns The mouse position stored as a Vec2 + */ + static getMousePressPosition() { + return Input.getMousePosition(); + } + /** + * Gets the position of the last mouse press in the game world, + * taking into consideration the scrolling of the viewport + * @returns The mouse position stored as a Vec2 + */ + static getGlobalMousePressPosition() { + return Input.mousePressPosition.clone().add(Input.viewport.getOrigin()); + } + /** + * Disables all keypress and mouse click inputs + */ + static disableInput() { + Input.keysDisabled = true; + Input.mouseDisabled = true; + } + /** + * Enables all keypress and mouse click inputs + */ + static enableInput() { + Input.keysDisabled = false; + Input.mouseDisabled = false; + } +} +exports.default = Input; + +},{"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Events/EventQueue":28,"../Events/GameEventType":30,"../Events/Receiver":31}],33:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EventQueue_1 = require("../Events/EventQueue"); +const Vec2_1 = require("../DataTypes/Vec2"); +const GameEvent_1 = require("../Events/GameEvent"); +const GameEventType_1 = require("../Events/GameEventType"); +/** + * Handles communication with the web browser to receive asynchronous events and send them to the @reference[EventQueue] + */ +class InputHandler { + /** + * Creates a new InputHandler + * @param canvas The game canvas + */ + constructor(canvas) { + this.handleMouseDown = (event, canvas) => { + let pos = this.getMousePosition(event, canvas); + let button = event.button; + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_DOWN, { position: pos, button: button }); + this.eventQueue.addEvent(gameEvent); + }; + this.handleMouseUp = (event, canvas) => { + let pos = this.getMousePosition(event, canvas); + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_UP, { position: pos }); + this.eventQueue.addEvent(gameEvent); + }; + this.handleMouseMove = (event, canvas) => { + let pos = this.getMousePosition(event, canvas); + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.MOUSE_MOVE, { position: pos }); + this.eventQueue.addEvent(gameEvent); + }; + this.handleKeyDown = (event) => { + let key = this.getKey(event); + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.KEY_DOWN, { key: key }); + this.eventQueue.addEvent(gameEvent); + }; + this.handleKeyUp = (event) => { + let key = this.getKey(event); + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.KEY_UP, { key: key }); + this.eventQueue.addEvent(gameEvent); + }; + this.handleBlur = (event) => { + let gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.CANVAS_BLUR, {}); + this.eventQueue.addEvent(gameEvent); + }; + this.handleContextMenu = (event) => { + event.preventDefault(); + event.stopPropagation(); + }; + this.handleWheel = (event) => { + event.preventDefault(); + event.stopPropagation(); + let gameEvent; + if (event.deltaY < 0) { + gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.WHEEL_UP, {}); + } + else { + gameEvent = new GameEvent_1.default(GameEventType_1.GameEventType.WHEEL_DOWN, {}); + } + this.eventQueue.addEvent(gameEvent); + }; + this.eventQueue = EventQueue_1.default.getInstance(); + canvas.onmousedown = (event) => this.handleMouseDown(event, canvas); + canvas.onmouseup = (event) => this.handleMouseUp(event, canvas); + canvas.oncontextmenu = this.handleContextMenu; + canvas.onmousemove = (event) => this.handleMouseMove(event, canvas); + document.onkeydown = this.handleKeyDown; + document.onkeyup = this.handleKeyUp; + document.onblur = this.handleBlur; + document.oncontextmenu = this.handleBlur; + document.onwheel = this.handleWheel; + } + getKey(keyEvent) { + return keyEvent.key.toLowerCase(); + } + getMousePosition(mouseEvent, canvas) { + let rect = canvas.getBoundingClientRect(); + let x = mouseEvent.clientX - rect.left; + let y = mouseEvent.clientY - rect.top; + return new Vec2_1.default(x, y); + } +} +exports.default = InputHandler; + +},{"../DataTypes/Vec2":24,"../Events/EventQueue":28,"../Events/GameEvent":29,"../Events/GameEventType":30}],34:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// @ignorePage +/** + * Sets up the environment of the game engine + */ +class EnvironmentInitializer { + static setup() { + CanvasRenderingContext2D.prototype.roundedRect = function (x, y, w, h, r) { + // Clamp the radius between 0 and the min of the width or height + if (r < 0) + r = 0; + if (r > Math.min(w, h)) + r = Math.min(w, h); + // Draw the rounded rect + this.beginPath(); + // Top + this.moveTo(x + r, y); + this.lineTo(x + w - r, y); + this.arcTo(x + w, y, x + w, y + r, r); + // Right + this.lineTo(x + w, y + h - r); + this.arcTo(x + w, y + h, x + w - r, y + h, r); + // Bottom + this.lineTo(x + r, y + h); + this.arcTo(x, y + h, x, y + h - r, r); + // Left + this.lineTo(x, y + r); + this.arcTo(x, y, x + r, y, r); + this.closePath(); + }; + CanvasRenderingContext2D.prototype.strokeRoundedRect = function (x, y, w, h, r) { + this.roundedRect(x, y, w, h, r); + this.stroke(); + }; + CanvasRenderingContext2D.prototype.fillRoundedRect = function (x, y, w, h, r) { + this.roundedRect(x, y, w, h, r); + this.fill(); + }; + } +} +exports.default = EnvironmentInitializer; + +},{}],35:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const GameLoop_1 = require("./GameLoop"); +const Debug_1 = require("../Debug/Debug"); +const Stats_1 = require("../Debug/Stats"); +/** + * A game loop with a fixed update time and a variable render time. + * Every frame, the game updates until all time since the last frame has been processed. + * If too much time has passed, such as if the last update was too slow, + * or if the browser was put into the background, the loop will panic and discard time. + * A render happens at the end of every frame. This happens as fast as possible unless specified. + * A loop of this type allows for deterministic behavior - No matter what the frame rate is, the update should behave the same, + * as it is occuring in a fixed interval. + */ +class FixedUpdateGameLoop extends GameLoop_1.default { + constructor() { + super(); + /** + * The main loop of the game. Updates until the current time is reached. Renders once + * @param timestamp The current time in ms + */ + this.doFrame = (timestamp) => { + // If a pause was executed, stop doing the loop. + if (this.paused) { + return; + } + // Request animation frame to prepare for another update or render + window.requestAnimationFrame((t) => this.doFrame(t)); + // If we are trying to render too soon, do nothing. + if (timestamp < this.lastFrameTime + this.minFrameDelay) { + return; + } + // A frame is actually happening + this.startFrame(timestamp); + // Update while there is still time to make up. If we do too many update steps, panic and exit the loop. + this.numUpdateSteps = 0; + let panic = false; + while (this.frameDelta >= this.updateTimestep) { + // Do an update + this._doUpdate(this.updateTimestep / 1000); + // Remove the update step time from the time we have to process + this.frameDelta -= this.updateTimestep; + // Increment steps and check if we've done too many + this.numUpdateSteps++; + if (this.numUpdateSteps > 100) { + panic = true; + break; + } + } + // Updates are done, render + this._doRender(); + // Wrap up the frame + this.finishFrame(panic); + }; + this.maxUpdateFPS = 60; + this.updateTimestep = Math.floor(1000 / this.maxUpdateFPS); + this.frameDelta = 0; + this.lastFrameTime = 0; + this.minFrameDelay = 0; + this.frame = 0; + this.fps = this.maxUpdateFPS; // Initialize the fps to the max allowed fps + this.fpsUpdateInterval = 1000; + this.lastFpsUpdate = 0; + this.framesSinceLastFpsUpdate = 0; + this.started = false; + this.paused = false; + this.running = false; + this.numUpdateSteps = 0; + } + getFPS() { + return 0; + } + /** + * Updates the frame count and sum of time for the framerate of the game + * @param timestep The current time in ms + */ + updateFPS(timestamp) { + this.fps = 0.9 * this.framesSinceLastFpsUpdate * 1000 / (timestamp - this.lastFpsUpdate) + (1 - 0.9) * this.fps; + this.lastFpsUpdate = timestamp; + this.framesSinceLastFpsUpdate = 0; + Debug_1.default.log("fps", "FPS: " + this.fps.toFixed(1)); + Stats_1.default.updateFPS(this.fps); + } + /** + * Changes the maximum allowed physics framerate of the game + * @param initMax The max framerate + */ + setMaxUpdateFPS(initMax) { + this.maxUpdateFPS = initMax; + this.updateTimestep = Math.floor(1000 / this.maxUpdateFPS); + } + /** + * Sets the maximum rendering framerate + * @param maxFPS The max framerate + */ + setMaxFPS(maxFPS) { + this.minFrameDelay = 1000 / maxFPS; + } + /** + * This function is called when the game loop panics, i.e. it tries to process too much time in an entire frame. + * This will reset the amount of time back to zero. + * @returns The amount of time we are discarding from processing. + */ + resetFrameDelta() { + let oldFrameDelta = this.frameDelta; + this.frameDelta = 0; + return oldFrameDelta; + } + /** + * Starts up the game loop and calls the first requestAnimationFrame + */ + start() { + if (!this.started) { + this.started = true; + window.requestAnimationFrame((timestamp) => this.doFirstFrame(timestamp)); + } + } + pause() { + this.paused = true; + } + resume() { + this.paused = false; + } + /** + * The first game frame - initializes the first frame time and begins the render + * @param timestamp The current time in ms + */ + doFirstFrame(timestamp) { + this.running = true; + this._doRender(); + this.lastFrameTime = timestamp; + this.lastFpsUpdate = timestamp; + this.framesSinceLastFpsUpdate = 0; + window.requestAnimationFrame((t) => this.doFrame(t)); + } + /** + * Handles any processing that needs to be done at the start of the frame + * @param timestamp The time of the frame in ms + */ + startFrame(timestamp) { + // Update the amount of time we need our update to process + this.frameDelta += timestamp - this.lastFrameTime; + // Set the new time of the last frame + this.lastFrameTime = timestamp; + // Update the estimate of the framerate + if (timestamp > this.lastFpsUpdate + this.fpsUpdateInterval) { + this.updateFPS(timestamp); + } + // Increment the number of frames + this.frame++; + this.framesSinceLastFpsUpdate++; + } + /** + * Wraps up the frame and handles the panic state if there is one + * @param panic Whether or not the loop panicked + */ + finishFrame(panic) { + if (panic) { + var discardedTime = Math.round(this.resetFrameDelta()); + console.warn('Main loop panicked, probably because the browser tab was put in the background. Discarding ' + discardedTime + 'ms'); + } + } +} +exports.default = FixedUpdateGameLoop; + +},{"../Debug/Debug":25,"../Debug/Stats":26,"./GameLoop":37}],36:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EventQueue_1 = require("../Events/EventQueue"); +const Input_1 = require("../Input/Input"); +const InputHandler_1 = require("../Input/InputHandler"); +const Recorder_1 = require("../Playback/Recorder"); +const Debug_1 = require("../Debug/Debug"); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +const Viewport_1 = require("../SceneGraph/Viewport"); +const SceneManager_1 = require("../Scene/SceneManager"); +const AudioManager_1 = require("../Sound/AudioManager"); +const Stats_1 = require("../Debug/Stats"); +const CanvasRenderer_1 = require("../Rendering/CanvasRenderer"); +const Color_1 = require("../Utils/Color"); +const GameOptions_1 = require("./GameOptions"); +const FixedUpdateGameLoop_1 = require("./FixedUpdateGameLoop"); +const EnvironmentInitializer_1 = require("./EnvironmentInitializer"); +const Vec2_1 = require("../DataTypes/Vec2"); +const RegistryManager_1 = require("../Registry/RegistryManager"); +const WebGLRenderer_1 = require("../Rendering/WebGLRenderer"); +/** + * The main loop of the game engine. + * Handles the update order, and initializes all subsystems. + * The Game manages the update cycle, and requests animation frames to render to the browser. + */ +class Game { + /** + * Creates a new Game + * @param options The options for Game initialization + */ + constructor(options) { + // Before anything else, build the environment + EnvironmentInitializer_1.default.setup(); + // Typecast the config object to a GameConfig object + this.gameOptions = GameOptions_1.default.parse(options); + this.showDebug = this.gameOptions.showDebug; + this.showStats = this.gameOptions.showStats; + // Create an instance of a game loop + this.loop = new FixedUpdateGameLoop_1.default(); + // Get the game canvas and give it a background color + this.GAME_CANVAS = document.getElementById("game-canvas"); + this.DEBUG_CANVAS = document.getElementById("debug-canvas"); + // Give the canvas a size and get the rendering context + this.WIDTH = this.gameOptions.canvasSize.x; + this.HEIGHT = this.gameOptions.canvasSize.y; + // This step MUST happen before the resource manager does anything + if (this.gameOptions.useWebGL) { + this.renderingManager = new WebGLRenderer_1.default(); + } + else { + this.renderingManager = new CanvasRenderer_1.default(); + } + this.initializeGameWindow(); + this.ctx = this.renderingManager.initializeCanvas(this.GAME_CANVAS, this.WIDTH, this.HEIGHT); + this.clearColor = new Color_1.default(this.gameOptions.clearColor.r, this.gameOptions.clearColor.g, this.gameOptions.clearColor.b); + // Initialize debugging and stats + Debug_1.default.initializeDebugCanvas(this.DEBUG_CANVAS, this.WIDTH, this.HEIGHT); + Stats_1.default.initStats(); + if (this.gameOptions.showStats) { + // Find the stats output and make it no longer hidden + document.getElementById("stats").hidden = false; + } + // Size the viewport to the game canvas + const canvasSize = new Vec2_1.default(this.WIDTH, this.HEIGHT); + this.viewport = new Viewport_1.default(canvasSize, this.gameOptions.zoomLevel); + // Initialize all necessary game subsystems + this.eventQueue = EventQueue_1.default.getInstance(); + this.inputHandler = new InputHandler_1.default(this.GAME_CANVAS); + Input_1.default.initialize(this.viewport, this.gameOptions.inputs); + this.recorder = new Recorder_1.default(); + this.resourceManager = ResourceManager_1.default.getInstance(); + this.sceneManager = new SceneManager_1.default(this.viewport, this.renderingManager); + this.audioManager = AudioManager_1.default.getInstance(); + } + /** + * Set up the game window that holds the canvases + */ + initializeGameWindow() { + const gameWindow = document.getElementById("game-window"); + // Set the height of the game window + gameWindow.style.width = this.WIDTH + "px"; + gameWindow.style.height = this.HEIGHT + "px"; + } + /** + * Retreives the SceneManager from the Game + * @returns The SceneManager + */ + getSceneManager() { + return this.sceneManager; + } + /** + * Starts the game + */ + start(InitialScene, options) { + // Set the update function of the loop + this.loop.doUpdate = (deltaT) => this.update(deltaT); + // Set the render function of the loop + this.loop.doRender = () => this.render(); + // Preload registry items + RegistryManager_1.default.preload(); + // Load the items with the resource manager + this.resourceManager.loadResourcesFromQueue(() => { + // When we're done loading, start the loop + console.log("Finished Preload - loading first scene"); + this.sceneManager.changeToScene(InitialScene, {}, options); + this.loop.start(); + }); + } + /** + * Updates all necessary subsystems of the game. Defers scene updates to the sceneManager + * @param deltaT The time sine the last update + */ + update(deltaT) { + try { + // Handle all events that happened since the start of the last loop + this.eventQueue.update(deltaT); + // Update the input data structures so game objects can see the input + Input_1.default.update(deltaT); + // Update the recording of the game + this.recorder.update(deltaT); + // Update all scenes + this.sceneManager.update(deltaT); + // Update all sounds + this.audioManager.update(deltaT); + // Load or unload any resources if needed + this.resourceManager.update(deltaT); + } + catch (e) { + this.loop.pause(); + console.warn("Uncaught Error in Update - Crashing gracefully"); + console.error(e); + } + } + /** + * Clears the canvas and defers scene rendering to the sceneManager. Renders the debug canvas + */ + render() { + try { + // Clear the canvases + Debug_1.default.clearCanvas(); + this.renderingManager.clear(this.clearColor); + this.sceneManager.render(); + // Hacky debug mode + if (Input_1.default.isKeyJustPressed("g")) { + this.showDebug = !this.showDebug; + } + // Debug render + if (this.showDebug) { + Debug_1.default.render(); + } + if (this.showStats) { + Stats_1.default.render(); + } + } + catch (e) { + this.loop.pause(); + console.warn("Uncaught Error in Render - Crashing gracefully"); + console.error(e); + } + } +} +exports.default = Game; + +},{"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Debug/Stats":26,"../Events/EventQueue":28,"../Input/Input":32,"../Input/InputHandler":33,"../Playback/Recorder":62,"../Registry/RegistryManager":65,"../Rendering/CanvasRenderer":71,"../Rendering/WebGLRenderer":76,"../ResourceManager/ResourceManager":83,"../Scene/SceneManager":91,"../SceneGraph/Viewport":95,"../Sound/AudioManager":96,"../Utils/Color":99,"./EnvironmentInitializer":34,"./FixedUpdateGameLoop":35,"./GameOptions":38}],37:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const NullFunc_1 = require("../DataTypes/Functions/NullFunc"); +/** + * The main game loop of the game. Keeps track of fps and handles scheduling of updates and rendering. + * This class is left abstract, so that a subclass can handle exactly how the loop is scheduled. + * For an example of different types of game loop scheduling, check out @link(Game Programming Patterns)(https://gameprogrammingpatterns.com/game-loop.html) + */ +class GameLoop { + constructor() { + /** The function to call when an update occurs */ + this._doUpdate = NullFunc_1.default; + /** The function to call when a render occurs */ + this._doRender = NullFunc_1.default; + } + set doUpdate(update) { + this._doUpdate = update; + } + set doRender(render) { + this._doRender = render; + } +} +exports.default = GameLoop; + +},{"../DataTypes/Functions/NullFunc":5}],38:[function(require,module,exports){ +"use strict"; +// @ignorePage +Object.defineProperty(exports, "__esModule", { value: true }); +/** The options for initializing the @reference[GameLoop] */ +class GameOptions { + /** + * Parses the data in the raw options object + * @param options The game options as a Record + * @returns A version of the options converted to a GameOptions object + */ + static parse(options) { + let gOpt = new GameOptions(); + gOpt.canvasSize = options.canvasSize ? options.canvasSize : { x: 800, y: 600 }; + gOpt.zoomLevel = options.zoomLevel ? options.zoomLevel : 1; + gOpt.clearColor = options.clearColor ? options.clearColor : { r: 255, g: 255, b: 255 }; + gOpt.inputs = options.inputs ? options.inputs : []; + gOpt.showDebug = !!options.showDebug; + gOpt.showStats = !!options.showStats; + gOpt.useWebGL = !!options.useWebGL; + return gOpt; + } +} +exports.default = GameOptions; + +},{}],39:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const GameNode_1 = require("./GameNode"); +const Vec2_1 = require("../DataTypes/Vec2"); +const AABB_1 = require("../DataTypes/Shapes/AABB"); +const Debug_1 = require("../Debug/Debug"); +const Color_1 = require("../Utils/Color"); +/** + * The representation of an object in the game world that can be drawn to the screen + */ +class CanvasNode extends GameNode_1.default { + constructor() { + super(); + /** A flag for whether or not the CanvasNode is visible */ + this.visible = true; + this._size = new Vec2_1.default(0, 0); + this._size.setOnChange(() => this.sizeChanged()); + this._scale = new Vec2_1.default(1, 1); + this._scale.setOnChange(() => this.scaleChanged()); + this._boundary = new AABB_1.default(); + this.updateBoundary(); + this._hasCustomShader = false; + } + get alpha() { + return this._alpha; + } + set alpha(a) { + this._alpha = a; + } + get size() { + return this._size; + } + set size(size) { + this._size = size; + // Enter as a lambda to bind "this" + this._size.setOnChange(() => this.sizeChanged()); + this.sizeChanged(); + } + get scale() { + return this._scale; + } + set scale(scale) { + this._scale = scale; + // Enter as a lambda to bind "this" + this._scale.setOnChange(() => this.scaleChanged()); + this.scaleChanged(); + } + set scaleX(value) { + this.scale.x = value; + } + set scaleY(value) { + this.scale.y = value; + } + get hasCustomShader() { + return this._hasCustomShader; + } + get customShaderKey() { + return this._customShaderKey; + } + // @override + positionChanged() { + super.positionChanged(); + this.updateBoundary(); + } + /** Called if the size vector is changed or replaced. */ + sizeChanged() { + this.updateBoundary(); + } + /** Called if the scale vector is changed or replaced */ + scaleChanged() { + this.updateBoundary(); + } + // @docIgnore + /** Called if the position, size, or scale of the CanvasNode is changed. Updates the boundary. */ + updateBoundary() { + this._boundary.center.set(this.position.x, this.position.y); + this._boundary.halfSize.set(this.size.x * this.scale.x / 2, this.size.y * this.scale.y / 2); + } + get boundary() { + return this._boundary; + } + get sizeWithZoom() { + let zoom = this.scene.getViewScale(); + return this.boundary.halfSize.clone().scaled(zoom, zoom); + } + /** + * Adds a custom shader to this CanvasNode + * @param key The registry key of the ShaderType + */ + useCustomShader(key) { + this._hasCustomShader = true; + this._customShaderKey = key; + } + /** + * Returns true if the point (x, y) is inside of this canvas object + * @param x The x position of the point + * @param y The y position of the point + * @returns A flag representing whether or not this node contains the point. + */ + contains(x, y) { + return this._boundary.containsPoint(new Vec2_1.default(x, y)); + } + // @implemented + debugRender() { + Debug_1.default.drawBox(this.relativePosition, this.sizeWithZoom, false, Color_1.default.BLUE); + super.debugRender(); + } +} +exports.default = CanvasNode; + +},{"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Utils/Color":99,"./GameNode":40}],40:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TweenableProperties = void 0; +const Vec2_1 = require("../DataTypes/Vec2"); +const Receiver_1 = require("../Events/Receiver"); +const Emitter_1 = require("../Events/Emitter"); +const Region_1 = require("../DataTypes/Interfaces/Region"); +const AABB_1 = require("../DataTypes/Shapes/AABB"); +const TweenController_1 = require("../Rendering/Animations/TweenController"); +const Debug_1 = require("../Debug/Debug"); +const Color_1 = require("../Utils/Color"); +const Circle_1 = require("../DataTypes/Shapes/Circle"); +/** + * The representation of an object in the game world. + * To construct GameNodes, see the @reference[Scene] documentation. + */ +class GameNode { + // Constructor docs are ignored, as the user should NOT create new GameNodes with a raw constructor + constructor() { + /*---------- PHYSICAL ----------*/ + this.hasPhysics = false; + this.moving = false; + this.frozen = false; + this.onGround = false; + this.onWall = false; + this.onCeiling = false; + this.active = false; + this.isColliding = false; + this.pathfinding = false; + this._position = new Vec2_1.default(0, 0); + this._position.setOnChange(() => this.positionChanged()); + this.receiver = new Receiver_1.default(); + this.emitter = new Emitter_1.default(); + this.tweens = new TweenController_1.default(this); + this.rotation = 0; + } + destroy() { + this.tweens.destroy(); + this.receiver.destroy(); + if (this.hasPhysics) { + this.removePhysics(); + } + if (this._ai) { + this._ai.destroy(); + delete this._ai; + this.scene.getAIManager().removeActor(this); + } + this.scene.remove(this); + this.layer.removeNode(this); + } + /*---------- POSITIONED ----------*/ + get position() { + return this._position; + } + set position(pos) { + this._position = pos; + this._position.setOnChange(() => this.positionChanged()); + this.positionChanged(); + } + get relativePosition() { + return this.inRelativeCoordinates(this.position); + } + /** + * Converts a point to coordinates relative to the zoom and origin of this node + * @param point The point to conver + * @returns A new Vec2 representing the point in relative coordinates + */ + inRelativeCoordinates(point) { + let origin = this.scene.getViewTranslation(this); + let zoom = this.scene.getViewScale(); + return point.clone().sub(origin).scale(zoom); + } + /*---------- UNIQUE ----------*/ + get id() { + return this._id; + } + set id(id) { + // id can only be set once + if (this._id === undefined) { + this._id = id; + } + else { + throw "Attempted to assign id to object that already has id."; + } + } + /*---------- PHYSICAL ----------*/ + // @implemented + /** + * @param velocity The velocity with which to move the object. + */ + move(velocity) { + if (this.frozen) + return; + this.moving = true; + this._velocity = velocity; + } + ; + moveOnPath(speed, path) { + if (this.frozen) + return; + this.path = path; + let dir = path.getMoveDirection(this); + this.moving = true; + this.pathfinding = true; + this._velocity = dir.scale(speed); + } + // @implemented + /** + * @param velocity The velocity with which the object will move. + */ + finishMove() { + this.moving = false; + this.position.add(this._velocity); + if (this.pathfinding) { + this.path.handlePathProgress(this); + this.path = null; + this.pathfinding = false; + } + } + // @implemented + /** + * @param collisionShape The collider for this object. If this has a region (implements Region), + * it will be used when no collision shape is specified (or if collision shape is null). + * @param isCollidable Whether this is collidable or not. True by default. + * @param isStatic Whether this is static or not. False by default + */ + addPhysics(collisionShape, colliderOffset, isCollidable = true, isStatic = false) { + // Initialize the physics variables + this.hasPhysics = true; + this.moving = false; + this.onGround = false; + this.onWall = false; + this.onCeiling = false; + this.active = true; + this.isCollidable = isCollidable; + this.isStatic = isStatic; + this.isTrigger = false; + this.triggerMask = 0; + this.triggerEnters = new Array(32); + this.triggerExits = new Array(32); + this._velocity = Vec2_1.default.ZERO; + this.sweptRect = new AABB_1.default(); + this.collidedWithTilemap = false; + this.group = -1; // The default group, collides with everything + // Set the collision shape if provided, or simply use the the region if there is one. + if (collisionShape) { + this.collisionShape = collisionShape; + this.collisionShape.center = this.position; + } + else if (Region_1.isRegion(this)) { + // If the gamenode has a region and no other is specified, use that + this.collisionShape = this.boundary.clone(); + } + else { + throw "No collision shape specified for physics object."; + } + // If we were provided with a collider offset, set it. Otherwise there is no offset, so use the zero vector + if (colliderOffset) { + this.colliderOffset = colliderOffset; + } + else { + this.colliderOffset = Vec2_1.default.ZERO; + } + // Initialize the swept rect + this.sweptRect = this.collisionShape.getBoundingRect(); + // Register the object with physics + this.scene.getPhysicsManager().registerObject(this); + } + /** Removes this object from the physics system */ + removePhysics() { + // Remove this from the physics manager + this.scene.getPhysicsManager().deregisterObject(this); + // Nullify all physics fields + this.hasPhysics = false; + this.moving = false; + this.onGround = false; + this.onWall = false; + this.onCeiling = false; + this.active = false; + this.isCollidable = false; + this.isStatic = false; + this.isTrigger = false; + this.triggerMask = 0; + this.triggerEnters = null; + this.triggerExits = null; + this._velocity = Vec2_1.default.ZERO; + this.sweptRect = null; + this.collidedWithTilemap = false; + this.group = -1; + this.collisionShape = null; + this.colliderOffset = Vec2_1.default.ZERO; + this.sweptRect = null; + } + /** Disables physics movement for this node */ + freeze() { + this.frozen = true; + } + /** Reenables physics movement for this node */ + unfreeze() { + this.frozen = false; + } + /** Prevents this object from participating in all collisions and triggers. It can still move. */ + disablePhysics() { + this.active = false; + } + /** Enables this object to participate in collisions and triggers. This is only necessary if disablePhysics was called */ + enablePhysics() { + this.active = true; + } + /** + * Sets the collider for this GameNode + * @param collider The new collider to use + */ + setCollisionShape(collider) { + this.collisionShape = collider; + this.collisionShape.center.copy(this.position); + } + // @implemented + /** + * Sets this object to be a trigger for a specific group + * @param group The name of the group that activates the trigger + * @param onEnter The name of the event to send when this trigger is activated + * @param onExit The name of the event to send when this trigger stops being activated + */ + setTrigger(group, onEnter, onExit) { + // Make this object a trigger + this.isTrigger = true; + // Get the number of the physics layer + let layerNumber = this.scene.getPhysicsManager().getGroupNumber(group); + if (layerNumber === 0) { + console.warn(`Trigger for GameNode ${this.id} not set - group "${group}" was not recognized by the physics manager.`); + return; + } + // Add this to the trigger mask + this.triggerMask |= layerNumber; + // Layer numbers are bits, so get which bit it is + let index = Math.log2(layerNumber); + // Set the event names + this.triggerEnters[index] = onEnter; + this.triggerExits[index] = onExit; + } + ; + // @implemented + /** + * @param group The physics group this node should belong to + */ + setGroup(group) { + this.scene.getPhysicsManager().setGroup(this, group); + } + // @implemened + getLastVelocity() { + return this._velocity; + } + /*---------- ACTOR ----------*/ + get ai() { + return this._ai; + } + set ai(ai) { + if (!this._ai) { + // If we haven't been previously had an ai, register us with the ai manager + this.scene.getAIManager().registerActor(this); + } + this._ai = ai; + this.aiActive = true; + } + // @implemented + addAI(ai, options, type) { + if (!this._ai) { + this.scene.getAIManager().registerActor(this); + } + if (typeof ai === "string") { + this._ai = this.scene.getAIManager().generateAI(ai); + } + else { + this._ai = new ai(); + } + // Question, how much do we want different type of AI to be handled the same, i.e. should GoapAI and AI similar methods and signatures for the sake of unity + this._ai.initializeAI(this, options); + this.aiActive = true; + } + // @implemented + setAIActive(active, options) { + this.aiActive = active; + if (this.aiActive) { + this.ai.activate(options); + } + } + /*---------- TWEENABLE PROPERTIES ----------*/ + set positionX(value) { + this.position.x = value; + } + set positionY(value) { + this.position.y = value; + } + /*---------- GAME NODE ----------*/ + /** + * Sets the scene for this object. + * @param scene The scene this object belongs to. + */ + setScene(scene) { + this.scene = scene; + } + /** + * Gets the scene this object is in. + * @returns The scene this object belongs to + */ + getScene() { + return this.scene; + } + /** + * Sets the layer of this object. + * @param layer The layer this object will be on. + */ + setLayer(layer) { + this.layer = layer; + } + /** + * Returns the layer this object is on. + * @returns This layer this object is on. + */ + getLayer() { + return this.layer; + } + /** Called if the position vector is modified or replaced */ + positionChanged() { + if (this.collisionShape) { + if (this.colliderOffset) { + this.collisionShape.center = this.position.clone().add(this.colliderOffset); + } + else { + this.collisionShape.center = this.position.clone(); + } + } + } + ; + /** + * Updates this GameNode + * @param deltaT The timestep of the update. + */ + update(deltaT) { + // Defer event handling to AI. + while (this.receiver.hasNextEvent()) { + this._ai.handleEvent(this.receiver.getNextEvent()); + } + } + // @implemented + debugRender() { + // Draw the position of this GameNode + Debug_1.default.drawPoint(this.relativePosition, Color_1.default.BLUE); + // If velocity is not zero, draw a vector for it + if (this._velocity && !this._velocity.isZero()) { + Debug_1.default.drawRay(this.relativePosition, this._velocity.clone().scaleTo(20).add(this.relativePosition), Color_1.default.BLUE); + } + // If this has a collider, draw it + if (this.collisionShape) { + let color = this.isColliding ? Color_1.default.RED : Color_1.default.GREEN; + if (this.isTrigger) { + color = Color_1.default.MAGENTA; + } + color.a = 0.2; + if (this.collisionShape instanceof AABB_1.default) { + Debug_1.default.drawBox(this.inRelativeCoordinates(this.collisionShape.center), this.collisionShape.halfSize.scaled(this.scene.getViewScale()), true, color); + } + else if (this.collisionShape instanceof Circle_1.default) { + Debug_1.default.drawCircle(this.inRelativeCoordinates(this.collisionShape.center), this.collisionShape.hw * this.scene.getViewScale(), true, color); + } + } + } +} +exports.default = GameNode; +var TweenableProperties; +(function (TweenableProperties) { + TweenableProperties["posX"] = "positionX"; + TweenableProperties["posY"] = "positionY"; + TweenableProperties["scaleX"] = "scaleX"; + TweenableProperties["scaleY"] = "scaleY"; + TweenableProperties["rotation"] = "rotation"; + TweenableProperties["alpha"] = "alpha"; +})(TweenableProperties = exports.TweenableProperties || (exports.TweenableProperties = {})); + +},{"../DataTypes/Interfaces/Region":9,"../DataTypes/Shapes/AABB":16,"../DataTypes/Shapes/Circle":17,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Events/Emitter":27,"../Events/Receiver":31,"../Rendering/Animations/TweenController":69,"../Utils/Color":99}],41:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const CanvasNode_1 = require("./CanvasNode"); +const Color_1 = require("../Utils/Color"); +/** + * The representation of a game object that doesn't rely on any resources to render - it is drawn to the screen by the canvas + */ +class Graphic extends CanvasNode_1.default { + constructor() { + super(); + this.color = Color_1.default.RED; + } + get alpha() { + return this.color.a; + } + set alpha(a) { + this.color.a = a; + } + // @deprecated + /** + * Sets the color of the Graphic. DEPRECATED + * @param color The new color of the Graphic. + */ + setColor(color) { + this.color = color; + } + set colorR(r) { + this.color.r = r; + } + get colorR() { + return this.color.r; + } + set colorG(g) { + this.color.g = g; + } + get colorG() { + return this.color.g; + } + set colorB(b) { + this.color.b = b; + } + get colorB() { + return this.color.b; + } +} +exports.default = Graphic; + +},{"../Utils/Color":99,"./CanvasNode":39}],42:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GraphicType = void 0; +var GraphicType; +(function (GraphicType) { + GraphicType["POINT"] = "POINT"; + GraphicType["RECT"] = "RECT"; + GraphicType["LINE"] = "LINE"; + GraphicType["PARTICLE"] = "PARTICLE"; +})(GraphicType = exports.GraphicType || (exports.GraphicType = {})); + +},{}],43:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Graphic_1 = require("../Graphic"); +class Line extends Graphic_1.default { + constructor(start, end) { + super(); + this.start = start; + this.end = end; + this.thickness = 2; + // Does this really have a meaning for lines? + this.size.set(5, 5); + } + set start(pos) { + this.position = pos; + } + get start() { + return this.position; + } + set end(pos) { + this._end = pos; + } + get end() { + return this._end; + } +} +exports.default = Line; + +},{"../Graphic":41}],44:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Point_1 = require("./Point"); +/** + * - Position X +- Velocity (speed and direction) X +- Color X +- Lifetime +- Age can be handled as lifetime +- Shape X +- Size X +- Transparency X + */ +class Particle extends Point_1.default { + constructor(position, size, mass) { + // Are we making this a circle? + super(position); + this.inUse = false; + this.mass = mass; + } + setParticleActive(lifetime, position) { + this.age = lifetime; + this.inUse = true; + this.visible = true; + this.position = position; + } + decrementAge(decay) { + this.age -= decay; + } + setParticleInactive() { + this.inUse = false; + this.visible = false; + } + set velY(y) { + this.vel.y = y; + } + get velY() { + return this.vel.y; + } +} +exports.default = Particle; + +},{"./Point":45}],45:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Graphic_1 = require("../Graphic"); +/** A basic point to be drawn on the screen. */ +class Point extends Graphic_1.default { + constructor(position) { + // Are we making this a circle? + super(); + this.position = position; + this.size.set(5, 5); + } +} +exports.default = Point; + +},{"../Graphic":41}],46:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Graphic_1 = require("../Graphic"); +const Color_1 = require("../../Utils/Color"); +/** A basic rectangle to be drawn on the screen. */ +class Rect extends Graphic_1.default { + constructor(position, size) { + super(); + this.position = position; + this.size = size; + this.borderColor = Color_1.default.TRANSPARENT; + this.borderWidth = 0; + this.fillWidth = null; + } + /** + * Sets the border color of this rectangle + * @param color The border color + */ + setBorderColor(color) { + this.borderColor = color; + } + // @deprecated + getBorderColor() { + return this.borderColor; + } + /** + * Sets the border width of this rectangle + * @param width The width of the rectangle in pixels + */ + setBorderWidth(width) { + this.borderWidth = width; + } + getBorderWidth() { + return this.borderWidth; + } +} +exports.default = Rect; + +},{"../../Utils/Color":99,"../Graphic":41}],47:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Sprite_1 = require("./Sprite"); +const AnimationManager_1 = require("../../Rendering/Animations/AnimationManager"); +const Vec2_1 = require("../../DataTypes/Vec2"); +/** An sprite with specified animation frames. */ +class AnimatedSprite extends Sprite_1.default { + constructor(spritesheet) { + super(spritesheet.name); + this.numCols = spritesheet.columns; + this.numRows = spritesheet.rows; + // Set the size of the sprite to the sprite size specified by the spritesheet + this.size.set(spritesheet.spriteWidth, spritesheet.spriteHeight); + this.animation = new AnimationManager_1.default(this); + // Add the animations to the animated sprite + for (let animation of spritesheet.animations) { + this.animation.add(animation.name, animation); + } + } + get cols() { + return this.numCols; + } + get rows() { + return this.numRows; + } + /** + * Gets the image offset for the current index of animation + * @param index The index we're at in the animation + * @returns A Vec2 containing the image offset + */ + getAnimationOffset(index) { + return new Vec2_1.default((index % this.numCols) * this.size.x, Math.floor(index / this.numCols) * this.size.y); + } +} +exports.default = AnimatedSprite; + +},{"../../DataTypes/Vec2":24,"../../Rendering/Animations/AnimationManager":66,"./Sprite":48}],48:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const CanvasNode_1 = require("../CanvasNode"); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const Vec2_1 = require("../../DataTypes/Vec2"); +/** + * The representation of a sprite - an in-game image + */ +class Sprite extends CanvasNode_1.default { + constructor(imageId) { + super(); + this.imageId = imageId; + let image = ResourceManager_1.default.getInstance().getImage(this.imageId); + this.size = new Vec2_1.default(image.width, image.height); + this.imageOffset = Vec2_1.default.ZERO; + this.invertX = false; + this.invertY = false; + } + /** + * Sets the offset of the sprite from (0, 0) in the image's coordinates + * @param offset The offset of the sprite from (0, 0) in image coordinates + */ + setImageOffset(offset) { + this.imageOffset = offset; + } +} +exports.default = Sprite; + +},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83,"../CanvasNode":39}],49:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../DataTypes/Vec2"); +const CanvasNode_1 = require("./CanvasNode"); +/** + * The representation of a tilemap - this can consist of a combination of tilesets in one layer + */ +class Tilemap extends CanvasNode_1.default { + // TODO: Make this no longer be specific to Tiled + constructor(tilemapData, layer, tilesets, scale) { + super(); + this.tilesets = tilesets; + this.tileSize = new Vec2_1.default(0, 0); + this.name = layer.name; + let tilecount = 0; + for (let tileset of tilesets) { + tilecount += tileset.getTileCount() + 1; + } + this.collisionMap = new Array(tilecount); + for (let i = 0; i < this.collisionMap.length; i++) { + this.collisionMap[i] = false; + } + // Defer parsing of the data to child classes - this allows for isometric vs. orthographic tilemaps and handling of Tiled data or other data + this.parseTilemapData(tilemapData, layer); + this.scale.set(scale.x, scale.y); + } + /** + * Returns an array of the tilesets associated with this tilemap + * @returns An array of all of the tilesets assocaited with this tilemap. + */ + getTilesets() { + return this.tilesets; + } + /** + * Returns the size of tiles in this tilemap as they appear in the game world after scaling + * @returns A vector containing the size of tiles in this tilemap as they appear in the game world after scaling. + */ + getTileSize() { + return this.tileSize.scaled(this.scale.x, this.scale.y); + } + /** + * Gets the tile size taking zoom into account + * @returns The tile size with zoom + */ + getTileSizeWithZoom() { + let zoom = this.scene.getViewScale(); + return this.getTileSize().scale(zoom); + } + /** + * Adds this tilemap to the physics system + */ + addPhysics() { + this.hasPhysics = true; + this.active = true; + this.group = -1; + this.scene.getPhysicsManager().registerTilemap(this); + } +} +exports.default = Tilemap; + +},{"../DataTypes/Vec2":24,"./CanvasNode":39}],50:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Tilemap_1 = require("../Tilemap"); +const Vec2_1 = require("../../DataTypes/Vec2"); +const Debug_1 = require("../../Debug/Debug"); +const Color_1 = require("../../Utils/Color"); +/** + * The representation of an orthogonal tilemap - i.e. a top down or platformer tilemap + */ +class OrthogonalTilemap extends Tilemap_1.default { + // @override + parseTilemapData(tilemapData, layer) { + // The size of the tilemap in local space + this.numCols = tilemapData.width; + this.numRows = tilemapData.height; + // The size of tiles + this.tileSize.set(tilemapData.tilewidth, tilemapData.tileheight); + // The size of the tilemap on the canvas + this.size.set(this.numCols * this.tileSize.x, this.numRows * this.tileSize.y); + this.position.copy(this.size.scaled(0.5)); + this.data = layer.data; + this.visible = layer.visible; + // Whether the tilemap is collidable or not + this.isCollidable = false; + if (layer.properties) { + for (let item of layer.properties) { + if (item.name === "Collidable") { + this.isCollidable = item.value; + // Set all tiles besides "empty: 0" to be collidable + for (let i = 1; i < this.collisionMap.length; i++) { + this.collisionMap[i] = true; + } + } + } + } + } + /** + * Gets the dimensions of the tilemap + * @returns A Vec2 containing the number of columns and the number of rows in the tilemap. + */ + getDimensions() { + return new Vec2_1.default(this.numCols, this.numRows); + } + /** + * Gets the data value of the tile at the specified world position + * @param worldCoords The coordinates in world space + * @returns The data value of the tile + */ + getTileAtWorldPosition(worldCoords) { + let localCoords = this.getColRowAt(worldCoords); + return this.getTileAtRowCol(localCoords); + } + /** + * Get the tile at the specified row and column + * @param rowCol The coordinates in tilemap space + * @returns The data value of the tile + */ + getTileAtRowCol(rowCol) { + if (rowCol.x < 0 || rowCol.x >= this.numCols || rowCol.y < 0 || rowCol.y >= this.numRows) { + return -1; + } + return this.data[rowCol.y * this.numCols + rowCol.x]; + } + /** + * Gets the world position of the tile at the specified index + * @param index The index of the tile + * @returns A Vec2 containing the world position of the tile + */ + getTileWorldPosition(index) { + // Get the local position + let col = index % this.numCols; + let row = Math.floor(index / this.numCols); + // Get the world position + let x = col * this.tileSize.x * this.scale.x; + let y = row * this.tileSize.y * this.scale.y; + return new Vec2_1.default(x, y); + } + /** + * Gets the data value of the tile at the specified index + * @param index The index of the tile + * @returns The data value of the tile + */ + getTile(index) { + return this.data[index]; + } + // @override + setTile(index, type) { + this.data[index] = type; + } + /** + * Sets the tile at the specified row and column + * @param rowCol The position of the tile in tilemap space + * @param type The new data value of the tile + */ + setTileAtRowCol(rowCol, type) { + let index = rowCol.y * this.numCols + rowCol.x; + this.setTile(index, type); + } + /** + * Returns true if the tile at the specified row and column of the tilemap is collidable + * @param indexOrCol The index of the tile or the column it is in + * @param row The row the tile is in + * @returns A flag representing whether or not the tile is collidable. + */ + isTileCollidable(indexOrCol, row) { + // The value of the tile + let tile = 0; + if (row) { + // We have a column and a row + tile = this.getTileAtRowCol(new Vec2_1.default(indexOrCol, row)); + if (tile < 0) { + return false; + } + } + else { + if (indexOrCol < 0 || indexOrCol >= this.data.length) { + // Tiles that don't exist aren't collidable + return false; + } + // We have an index + tile = this.getTile(indexOrCol); + } + return this.collisionMap[tile]; + } + /** + * Takes in world coordinates and returns the row and column of the tile at that position + * @param worldCoords The coordinates of the potential tile in world space + * @returns A Vec2 containing the coordinates of the potential tile in tilemap space + */ + getColRowAt(worldCoords) { + let col = Math.floor(worldCoords.x / this.tileSize.x / this.scale.x); + let row = Math.floor(worldCoords.y / this.tileSize.y / this.scale.y); + return new Vec2_1.default(col, row); + } + // @override + update(deltaT) { } + // @override + debugRender() { + // Half of the tile size + let zoomedHalfTileSize = this.getTileSizeWithZoom().scaled(0.5); + let halfTileSize = this.getTileSize().scaled(0.5); + // The center of the top left tile + let topLeft = this.position.clone().sub(this.size.scaled(0.5)); + // A vec to store the center + let center = Vec2_1.default.ZERO; + for (let col = 0; col < this.numCols; col++) { + // Calculate the x-position + center.x = topLeft.x + col * 2 * halfTileSize.x + halfTileSize.x; + for (let row = 0; row < this.numRows; row++) { + if (this.isCollidable && this.isTileCollidable(col, row)) { + // Calculate the y-position + center.y = topLeft.y + row * 2 * halfTileSize.y + halfTileSize.y; + // Draw a box for this tile + Debug_1.default.drawBox(this.inRelativeCoordinates(center), zoomedHalfTileSize, false, Color_1.default.BLUE); + } + } + } + } +} +exports.default = OrthogonalTilemap; + +},{"../../DataTypes/Vec2":24,"../../Debug/Debug":25,"../../Utils/Color":99,"../Tilemap":49}],51:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const CanvasNode_1 = require("./CanvasNode"); +const Color_1 = require("../Utils/Color"); +const Vec2_1 = require("../DataTypes/Vec2"); +const Input_1 = require("../Input/Input"); +/** + * The representation of a UIElement - the parent class of things like buttons + */ +class UIElement extends CanvasNode_1.default { + constructor(position) { + super(); + this.position = position; + this.backgroundColor = new Color_1.default(0, 0, 0, 0); + this.borderColor = new Color_1.default(0, 0, 0, 0); + this.borderRadius = 5; + this.borderWidth = 1; + this.padding = Vec2_1.default.ZERO; + this.onClick = null; + this.onClickEventId = null; + this.onRelease = null; + this.onReleaseEventId = null; + this.onEnter = null; + this.onEnterEventId = null; + this.onLeave = null; + this.onLeaveEventId = null; + this.isClicked = false; + this.isEntered = false; + } + // @deprecated + setBackgroundColor(color) { + this.backgroundColor = color; + } + // @deprecated + setPadding(padding) { + this.padding.copy(padding); + } + update(deltaT) { + super.update(deltaT); + // See of this object was just clicked + if (Input_1.default.isMouseJustPressed()) { + let clickPos = Input_1.default.getMousePressPosition(); + if (this.contains(clickPos.x, clickPos.y) && this.visible && !this.layer.isHidden()) { + this.isClicked = true; + if (this.onClick !== null) { + this.onClick(); + } + if (this.onClickEventId !== null) { + let data = {}; + this.emitter.fireEvent(this.onClickEventId, data); + } + } + } + // If the mouse wasn't just pressed, then we definitely weren't clicked + if (!Input_1.default.isMousePressed()) { + if (this.isClicked) { + this.isClicked = false; + } + } + // Check if the mouse is hovering over this element + let mousePos = Input_1.default.getMousePosition(); + if (mousePos && this.contains(mousePos.x, mousePos.y)) { + this.isEntered = true; + if (this.onEnter !== null) { + this.onEnter(); + } + if (this.onEnterEventId !== null) { + let data = {}; + this.emitter.fireEvent(this.onEnterEventId, data); + } + } + else if (this.isEntered) { + this.isEntered = false; + if (this.onLeave !== null) { + this.onLeave(); + } + if (this.onLeaveEventId !== null) { + let data = {}; + this.emitter.fireEvent(this.onLeaveEventId, data); + } + } + else if (this.isClicked) { + // If mouse is dragged off of element while down, it is not clicked anymore + this.isClicked = false; + } + } + /** + * Overridable method for calculating background color - useful for elements that want to be colored on different after certain events + * @returns The background color of the UIElement + */ + calculateBackgroundColor() { + return this.backgroundColor; + } + /** + * Overridable method for calculating border color - useful for elements that want to be colored on different after certain events + * @returns The border color of the UIElement + */ + calculateBorderColor() { + return this.borderColor; + } +} +exports.default = UIElement; + +},{"../DataTypes/Vec2":24,"../Input/Input":32,"../Utils/Color":99,"./CanvasNode":39}],52:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Label_1 = require("./Label"); +const Color_1 = require("../../Utils/Color"); +/** A clickable button UIElement */ +class Button extends Label_1.default { + constructor(position, text) { + super(position, text); + this.backgroundColor = new Color_1.default(150, 75, 203); + this.borderColor = new Color_1.default(41, 46, 30); + this.textColor = new Color_1.default(255, 255, 255); + } + // @override + calculateBackgroundColor() { + // Change the background color if clicked or hovered + if (this.isEntered && !this.isClicked) { + return this.backgroundColor.lighten(); + } + else if (this.isClicked) { + return this.backgroundColor.darken(); + } + else { + return this.backgroundColor; + } + } +} +exports.default = Button; + +},{"../../Utils/Color":99,"./Label":53}],53:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HAlign = exports.VAlign = void 0; +const Vec2_1 = require("../../DataTypes/Vec2"); +const Color_1 = require("../../Utils/Color"); +const UIElement_1 = require("../UIElement"); +/** A basic text-containing label */ +class Label extends UIElement_1.default { + constructor(position, text) { + super(position); + this.text = text; + this.textColor = new Color_1.default(0, 0, 0, 1); + this.font = "Arial"; + this.fontSize = 30; + this.hAlign = "center"; + this.vAlign = "center"; + this.sizeAssigned = false; + } + // @deprecated + setText(text) { + this.text = text; + } + // @deprecated + setTextColor(color) { + this.textColor = color; + } + /** + * Gets a string containg the font details for rendering + * @returns A string containing the font details + */ + getFontString() { + return this.fontSize + "px " + this.font; + } + /** + * Overridable method for calculating text color - useful for elements that want to be colored on different after certain events + * @returns a string containg the text color + */ + calculateTextColor() { + return this.textColor.toStringRGBA(); + } + /** + * Uses the canvas to calculate the width of the text + * @param ctx The rendering context + * @returns A number representing the rendered text width + */ + calculateTextWidth(ctx) { + ctx.font = this.fontSize + "px " + this.font; + return ctx.measureText(this.text).width; + } + setHAlign(align) { + this.hAlign = align; + } + setVAlign(align) { + this.vAlign = align; + } + /** + * Calculate the offset of the text - this is used for rendering text with different alignments + * @param ctx The rendering context + * @returns The offset of the text in a Vec2 + */ + calculateTextOffset(ctx) { + let textWidth = this.calculateTextWidth(ctx); + let offset = new Vec2_1.default(0, 0); + let hDiff = this.size.x - textWidth; + if (this.hAlign === HAlign.CENTER) { + offset.x = hDiff / 2; + } + else if (this.hAlign === HAlign.RIGHT) { + offset.x = hDiff; + } + if (this.vAlign === VAlign.TOP) { + ctx.textBaseline = "top"; + offset.y = 0; + } + else if (this.vAlign === VAlign.BOTTOM) { + ctx.textBaseline = "bottom"; + offset.y = this.size.y; + } + else { + ctx.textBaseline = "middle"; + offset.y = this.size.y / 2; + } + return offset; + } + sizeChanged() { + super.sizeChanged(); + this.sizeAssigned = true; + } + /** + * Automatically sizes the element to the text within it + * @param ctx The rendering context + */ + autoSize(ctx) { + let width = this.calculateTextWidth(ctx); + let height = this.fontSize; + this.size.set(width + this.padding.x * 2, height + this.padding.y * 2); + this.sizeAssigned = true; + } + /** + * Initially assigns a size to the UIElement if none is provided + * @param ctx The rendering context + */ + handleInitialSizing(ctx) { + if (!this.sizeAssigned) { + this.autoSize(ctx); + } + } + /** On the next render, size this element to it's current text using its current font size */ + sizeToText() { + this.sizeAssigned = false; + } +} +exports.default = Label; +var VAlign; +(function (VAlign) { + VAlign["TOP"] = "top"; + VAlign["CENTER"] = "center"; + VAlign["BOTTOM"] = "bottom"; +})(VAlign = exports.VAlign || (exports.VAlign = {})); +var HAlign; +(function (HAlign) { + HAlign["LEFT"] = "left"; + HAlign["CENTER"] = "center"; + HAlign["RIGHT"] = "right"; +})(HAlign = exports.HAlign || (exports.HAlign = {})); + +},{"../../DataTypes/Vec2":24,"../../Utils/Color":99,"../UIElement":51}],54:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../DataTypes/Vec2"); +const Input_1 = require("../../Input/Input"); +const Color_1 = require("../../Utils/Color"); +const MathUtils_1 = require("../../Utils/MathUtils"); +const UIElement_1 = require("../UIElement"); +/** A slider UIElement */ +class Slider extends UIElement_1.default { + constructor(position, initValue) { + super(position); + this.value = initValue; + this.nibColor = Color_1.default.RED; + this.sliderColor = Color_1.default.BLACK; + this.backgroundColor = Color_1.default.TRANSPARENT; + this.borderColor = Color_1.default.TRANSPARENT; + this.nibSize = new Vec2_1.default(10, 20); + // Set a default size + this.size.set(200, 20); + } + /** + * Retrieves the value of the slider + * @returns The value of the slider + */ + getValue() { + return this.value; + } + /** A method called in response to the value changing */ + valueChanged() { + if (this.onValueChange) { + this.onValueChange(this.value); + } + if (this.onValueChangeEventId) { + this.emitter.fireEvent(this.onValueChangeEventId, { target: this, value: this.value }); + } + } + update(deltaT) { + super.update(deltaT); + if (this.isClicked) { + let val = MathUtils_1.default.invLerp(this.position.x - this.size.x / 2, this.position.x + this.size.x / 2, Input_1.default.getMousePosition().x); + this.value = MathUtils_1.default.clamp01(val); + this.valueChanged(); + } + } +} +exports.default = Slider; + +},{"../../DataTypes/Vec2":24,"../../Input/Input":32,"../../Utils/Color":99,"../../Utils/MathUtils":102,"../UIElement":51}],55:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Color_1 = require("../../Utils/Color"); +const Label_1 = require("./Label"); +const Input_1 = require("../../Input/Input"); +/** A text input UIElement */ +class TextInput extends Label_1.default { + constructor(position) { + super(position, ""); + this.focused = false; + this.cursorCounter = 0; + // Give a default size to the x only + this.size.set(200, this.fontSize); + this.hAlign = "left"; + this.borderColor = Color_1.default.BLACK; + this.backgroundColor = Color_1.default.WHITE; + } + update(deltaT) { + super.update(deltaT); + if (Input_1.default.isMouseJustPressed()) { + let clickPos = Input_1.default.getMousePressPosition(); + if (this.contains(clickPos.x, clickPos.y)) { + this.focused = true; + this.cursorCounter = 30; + } + else { + this.focused = false; + } + } + if (this.focused) { + let keys = Input_1.default.getKeysJustPressed(); + let nums = "1234567890"; + let specialChars = "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?"; + let letters = "qwertyuiopasdfghjklzxcvbnm"; + let mask = nums + specialChars + letters; + keys = keys.filter(key => mask.includes(key)); + let shiftPressed = Input_1.default.isKeyPressed("shift"); + let backspacePressed = Input_1.default.isKeyJustPressed("backspace"); + let spacePressed = Input_1.default.isKeyJustPressed("space"); + if (backspacePressed) { + this.text = this.text.substring(0, this.text.length - 1); + } + else if (spacePressed) { + this.text += " "; + } + else if (keys.length > 0) { + if (shiftPressed) { + this.text += keys[0].toUpperCase(); + } + else { + this.text += keys[0]; + } + } + } + } +} +exports.default = TextInput; + +},{"../../Input/Input":32,"../../Utils/Color":99,"./Label":53}],56:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UIElementType = void 0; +var UIElementType; +(function (UIElementType) { + UIElementType["BUTTON"] = "BUTTON"; + UIElementType["LABEL"] = "LABEL"; + UIElementType["SLIDER"] = "SLIDER"; + UIElementType["TEXT_INPUT"] = "TEXTINPUT"; +})(UIElementType = exports.UIElementType || (exports.UIElementType = {})); + +},{}],57:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +/** + * The manager class for navigation. + * Handles all navigable entities, such and allows them to be accessed by outside systems by requesting a path + * from one position to another. + */ +class NavigationManager { + constructor() { + this.navigableEntities = new Map_1.default(); + } + /** + * Adds a navigable entity to the NavigationManager + * @param navName The name of the navigable entitry + * @param nav The actual Navigable instance + */ + addNavigableEntity(navName, nav) { + this.navigableEntities.add(navName, nav); + } + /** + * Gets a path frome one point to another using a specified Navigable object + * @param navName The name of the registered Navigable object + * @param fromPosition The starting position of navigation + * @param toPosition The ending position of Navigation + * @param direct If true, go direct from fromPosition to toPosition, don't use NavMesh + * @returns A NavigationPath containing the route to take over the Navigable entity to get between the provided positions. + */ + getPath(navName, fromPosition, toPosition, direct) { + let nav = this.navigableEntities.get(navName); + return nav.getNavigationPath(fromPosition.clone(), toPosition.clone(), direct); + } +} +exports.default = NavigationManager; + +},{"../DataTypes/Map":10}],58:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../DataTypes/Vec2"); +/** + * A path that AIs can follow. Uses finishMove() in Physical to determine progress on the route + */ +class NavigationPath { + /** + * Constructs a new NavigationPath + * @param path The path of nodes to take + */ + constructor(path) { + this.path = path; + this.currentMoveDirection = Vec2_1.default.ZERO; + this.distanceThreshold = 4; + } + /** + * Returns the status of navigation along this NavigationPath + * @returns True if the node has reached the end of the path, false otherwise + */ + isDone() { + return this.path.isEmpty(); + } + /** + * Gets the movement direction in the current position along the path + * @param node The node to move along the path + * @returns The movement direction as a Vec2 + */ + getMoveDirection(node) { + // Return direction to next point in the nav + return node.position.dirTo(this.path.peek()); + } + /** + * Updates this NavigationPath to the current state of the GameNode + * @param node The node moving along the path + */ + handlePathProgress(node) { + if (node.position.distanceSqTo(this.path.peek()) < this.distanceThreshold * this.distanceThreshold) { + // We've reached our node, move on to the next destination + this.path.pop(); + } + } + toString() { + return this.path.toString(); + } +} +exports.default = NavigationPath; + +},{"../DataTypes/Vec2":24}],59:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Stack_1 = require("../DataTypes/Stack"); +const GraphUtils_1 = require("../Utils/GraphUtils"); +const NavigationPath_1 = require("./NavigationPath"); +/** + * An implementation of a Navmesh. Navmeshes are graphs in the game world along which nodes can move. + */ +class Navmesh { + /** + * Creates a new Navmesh from the points in the speecified graph + * @param graph The graph to construct a navmesh from + */ + constructor(graph) { + this.graph = graph; + } + // @implemented + getNavigationPath(fromPosition, toPosition, direct) { + let start = this.getClosestNode(fromPosition); + let end = this.getClosestNode(toPosition); + let pathStack = new Stack_1.default(this.graph.numVertices); + // Push the final position and the final position in the graph + pathStack.push(toPosition.clone()); + if (direct) { + return new NavigationPath_1.default(pathStack); + } + pathStack.push(this.graph.positions[end]); + let parent = GraphUtils_1.default.djikstra(this.graph, start); + // Add all parents along the path + let i = end; + while (parent[i] !== -1) { + pathStack.push(this.graph.positions[parent[i]]); + i = parent[i]; + } + return new NavigationPath_1.default(pathStack); + } + /** + * Gets the closest node in this Navmesh to the specified position + * @param position The position to query + * @returns The index of the closest node in the Navmesh to the position + */ + getClosestNode(position) { + let n = this.graph.numVertices; + let i = 1; + let index = 0; + let dist = position.distanceSqTo(this.graph.positions[0]); + while (i < n) { + let d = position.distanceSqTo(this.graph.positions[i]); + if (d < dist) { + dist = d; + index = i; + } + i++; + } + return index; + } +} +exports.default = Navmesh; + +},{"../DataTypes/Stack":19,"../Utils/GraphUtils":101,"./NavigationPath":58}],60:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const PhysicsManager_1 = require("./PhysicsManager"); +const Vec2_1 = require("../DataTypes/Vec2"); +const AABB_1 = require("../DataTypes/Shapes/AABB"); +const OrthogonalTilemap_1 = require("../Nodes/Tilemaps/OrthogonalTilemap"); +const AreaCollision_1 = require("../DataTypes/Physics/AreaCollision"); +/** + * ALGORITHM: + * In an effort to keep things simple and working effectively, each dynamic node will resolve its + * collisions considering the rest of the world as static. + * + * Collision detecting will happen first. This can be considered a broad phase, but it is not especially + * efficient, as it does not need to be for this game engine. Every dynamic node is checked against every + * other node for collision area. If collision area is non-zero (meaning the current node sweeps into another), + * it is added to a list of hits. + * + * INITIALIZATION: + * - Physics constants are reset + * - Swept shapes are recalculated. If a node isn't moving, it is skipped. + * + * COLLISION DETECTION: + * - For a node, collision area will be calculated using the swept AABB of the node against every other AABB in a static state + * - These collisions will be sorted by area in descending order + * + * COLLISION RESOLUTION: + * - For each hit, time of collision is calculated using a swept line through the AABB of the static node expanded + * with minkowski sums (discretely, but the concept is there) + * - The collision is resolved based on the near time of the collision (from method of separated axes) + * - X is resolved by near x, Y by near y. + * - There is some fudging to allow for sliding along walls of separate colliders. Sorting by area also helps with this. + * - Corner to corner collisions are resolve to favor x-movement. This is in consideration of platformers, to give + * the player some help with jumps + * + * Pros: + * - Everything happens with a consistent time. There is a distinct before and after for each resolution. + * - No back-tracking needs to be done. Once we resolve a node, it is definitively resolved. + * + * Cons: + * - Nodes that are processed early have movement priority over other nodes. This can lead to some undesirable interactions. + */ +class BasicPhysicsManager extends PhysicsManager_1.default { + constructor(options) { + super(); + this.staticNodes = new Array(); + this.dynamicNodes = new Array(); + this.tilemaps = new Array(); + this.collisionMasks = new Array(32); + // Parse options + this.parseOptions(options); + } + /** + * Parses the options for constructing the physics manager + * @param options A record of options + */ + parseOptions(options) { + if (options.groupNames !== undefined && options.collisions !== undefined) { + for (let i = 0; i < options.groupNames.length; i++) { + let group = options.groupNames[i]; + // Register the group name and number + this.groupNames[i] = group; + this.groupMap.set(group, 1 << i); + let collisionMask = 0; + for (let j = 0; j < options.collisions[i].length; j++) { + if (options.collisions[i][j]) { + collisionMask |= 1 << j; + } + } + this.collisionMasks[i] = collisionMask; + } + } + } + // @override + registerObject(node) { + if (node.isStatic) { + // Static and not collidable + this.staticNodes.push(node); + } + else { + // Dynamic and not collidable + this.dynamicNodes.push(node); + } + } + // @override + deregisterObject(node) { + if (node.isStatic) { + // Remove the node from the static list + const index = this.staticNodes.indexOf(node); + this.staticNodes.splice(index, 1); + } + else { + // Remove the node from the dynamic list + const index = this.dynamicNodes.indexOf(node); + this.dynamicNodes.splice(index, 1); + } + } + // @override + registerTilemap(tilemap) { + this.tilemaps.push(tilemap); + } + // @override + deregisterTilemap(tilemap) { + const index = this.tilemaps.indexOf(tilemap); + this.tilemaps.splice(index, 1); + } + // @override + update(deltaT) { + for (let node of this.dynamicNodes) { + /*---------- INITIALIZATION PHASE ----------*/ + // Clear frame dependent boolean values for each node + node.onGround = false; + node.onCeiling = false; + node.onWall = false; + node.collidedWithTilemap = false; + node.isColliding = false; + // If this node is not active, don't process it + if (!node.active) { + continue; + } + // Update the swept shapes of each node + if (node.moving) { + // If moving, reflect that in the swept shape + node.sweptRect.sweep(node._velocity, node.collisionShape.center, node.collisionShape.halfSize); + } + else { + // If our node isn't moving, don't bother to check it (other nodes will detect if they run into it) + node._velocity.zero(); + continue; + } + /*---------- DETECTION PHASE ----------*/ + // Gather a set of overlaps + let overlaps = new Array(); + let groupIndex = node.group === -1 ? -1 : Math.log2(node.group); + // First, check this node against every static node (order doesn't actually matter here, since we sort anyways) + for (let other of this.staticNodes) { + // Ignore inactive nodes + if (!other.active) + continue; + let collider = other.collisionShape.getBoundingRect(); + let area = node.sweptRect.overlapArea(collider); + if (area > 0) { + // We had a collision + overlaps.push(new AreaCollision_1.default(area, collider, other, "GameNode", null)); + } + } + // Then, check it against every dynamic node + for (let other of this.dynamicNodes) { + // Ignore ourselves + if (node === other) + continue; + // Ignore inactive nodes + if (!other.active) + continue; + let collider = other.collisionShape.getBoundingRect(); + let area = node.sweptRect.overlapArea(collider); + if (area > 0) { + // We had a collision + overlaps.push(new AreaCollision_1.default(area, collider, other, "GameNode", null)); + } + } + // Lastly, gather a set of AABBs from the tilemap. + // This step involves the most extra work, so it is abstracted into a method + for (let tilemap of this.tilemaps) { + // Ignore inactive tilemaps + if (!tilemap.active) + continue; + if (tilemap instanceof OrthogonalTilemap_1.default) { + this.collideWithOrthogonalTilemap(node, tilemap, overlaps); + } + } + // Sort the overlaps by area + overlaps = overlaps.sort((a, b) => b.area - a.area); + // Keep track of hits to use later + let hits = []; + /*---------- RESOLUTION PHASE ----------*/ + // For every overlap, determine if we need to collide with it and when + for (let overlap of overlaps) { + // Ignore nodes we don't interact with + if (groupIndex !== -1 && overlap.other.group !== -1 && ((this.collisionMasks[groupIndex] & overlap.other.group) === 0)) + continue; + // Do a swept line test on the static AABB with this AABB size as padding (this is basically using a minkowski sum!) + // Start the sweep at the position of this node with a delta of _velocity + const point = node.collisionShape.center; + const delta = node._velocity; + const padding = node.collisionShape.halfSize; + const otherAABB = overlap.collider; + const hit = otherAABB.intersectSegment(node.collisionShape.center, node._velocity, node.collisionShape.halfSize); + overlap.hit = hit; + if (hit !== null) { + hits.push(hit); + // We got a hit, resolve with the time inside of the hit + let tnearx = hit.nearTimes.x; + let tneary = hit.nearTimes.y; + // Allow edge clipping (edge overlaps don't count, only area overlaps) + // Importantly don't allow both cases to be true. Then we clip through corners. Favor x to help players land jumps + if (tnearx < 1.0 && (point.y === otherAABB.top - padding.y || point.y === otherAABB.bottom + padding.y) && delta.x !== 0) { + tnearx = 1.0; + } + else if (tneary < 1.0 && (point.x === otherAABB.left - padding.x || point.x === otherAABB.right + padding.x) && delta.y !== 0) { + tneary = 1.0; + } + if (hit.nearTimes.x >= 0 && hit.nearTimes.x < 1) { + // Any tilemap objects that made it here are collidable + if (overlap.type === "Tilemap" || overlap.other.isCollidable) { + node._velocity.x = node._velocity.x * tnearx; + node.isColliding = true; + } + } + if (hit.nearTimes.y >= 0 && hit.nearTimes.y < 1) { + // Any tilemap objects that made it here are collidable + if (overlap.type === "Tilemap" || overlap.other.isCollidable) { + node._velocity.y = node._velocity.y * tneary; + node.isColliding = true; + } + } + } + } + /*---------- INFORMATION/TRIGGER PHASE ----------*/ + // Check if we ended up on the ground, ceiling or wall + // Also check for triggers + for (let overlap of overlaps) { + // Check for a trigger. If we care about the trigger, react + if (overlap.other.isTrigger && (overlap.other.triggerMask & node.group) && node.group != -1) { + // Get the bit that this group is represented by + let index = Math.floor(Math.log2(node.group)); + // Extract the triggerEnter event name + this.emitter.fireEvent(overlap.other.triggerEnters[index], { + node: node.id, + other: overlap.other.id + }); + } + // Ignore collision sides for nodes we don't interact with + if (groupIndex !== -1 && overlap.other.group !== -1 && ((this.collisionMasks[groupIndex] & overlap.other.group) === 0)) + continue; + // Only check for direction if the overlap was collidable + if (overlap.type === "Tilemap" || overlap.other.isCollidable) { + let collisionSide = overlap.collider.touchesAABBWithoutCorners(node.collisionShape.getBoundingRect()); + if (collisionSide !== null) { + // If we touch, not including corner cases, check the collision normal + if (overlap.hit !== null) { + // If we hit a tilemap, keep track of it + if (overlap.type == "Tilemap") { + node.collidedWithTilemap = true; + } + if (collisionSide.y === -1) { + // Node is on top of overlap, so onGround + node.onGround = true; + } + else if (collisionSide.y === 1) { + // Node is on bottom of overlap, so onCeiling + node.onCeiling = true; + } + else { + // Node wasn't touching on y, so it is touching on x + node.onWall = true; + } + } + } + } + } + // Resolve the collision with the node, and move it + node.finishMove(); + } + } + /** + * Handles a collision between this node and an orthogonal tilemap + * @param node The node + * @param tilemap The tilemap the node may be colliding with + * @param overlaps The list of overlaps + */ + collideWithOrthogonalTilemap(node, tilemap, overlaps) { + // Get the min and max x and y coordinates of the moving node + let min = new Vec2_1.default(node.sweptRect.left, node.sweptRect.top); + let max = new Vec2_1.default(node.sweptRect.right, node.sweptRect.bottom); + // Convert the min/max x/y to the min and max row/col in the tilemap array + let minIndex = tilemap.getColRowAt(min); + let maxIndex = tilemap.getColRowAt(max); + let tileSize = tilemap.getTileSize(); + // Loop over all possible tiles (which isn't many in the scope of the velocity per frame) + for (let col = minIndex.x; col <= maxIndex.x; col++) { + for (let row = minIndex.y; row <= maxIndex.y; row++) { + if (tilemap.isTileCollidable(col, row)) { + // Get the position of this tile + let tilePos = new Vec2_1.default(col * tileSize.x + tileSize.x / 2, row * tileSize.y + tileSize.y / 2); + // Create a new collider for this tile + let collider = new AABB_1.default(tilePos, tileSize.scaled(1 / 2)); + // Calculate collision area between the node and the tile + let area = node.sweptRect.overlapArea(collider); + if (area > 0) { + // We had a collision + overlaps.push(new AreaCollision_1.default(area, collider, tilemap, "Tilemap", new Vec2_1.default(col, row))); + } + } + } + } + } +} +exports.default = BasicPhysicsManager; + +},{"../DataTypes/Physics/AreaCollision":12,"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Nodes/Tilemaps/OrthogonalTilemap":50,"./PhysicsManager":61}],61:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Receiver_1 = require("../Events/Receiver"); +const Emitter_1 = require("../Events/Emitter"); +const Map_1 = require("../DataTypes/Map"); +/** + * An abstract physics manager. + * This class exposes functions for subclasses to implement that should allow for a working physics system to be created. + */ +class PhysicsManager { + constructor() { + this.receiver = new Receiver_1.default(); + this.emitter = new Emitter_1.default(); + // The creation and implementation of layers is deferred to the subclass + this.groupMap = new Map_1.default(); + this.groupNames = new Array(); + } + destroy() { + this.receiver.destroy(); + } + /** + * Sets the physics layer of the GameNode + * @param node The GameNode + * @param group The group that the GameNode should be on + */ + setGroup(node, group) { + node.group = this.groupMap.get(group); + } + /** + * Retrieves the layer number associated with the provided name + * @param layer The name of the layer + * @returns The layer number, or 0 if there is not a layer with that name registered + */ + getGroupNumber(group) { + if (this.groupMap.has(group)) { + return this.groupMap.get(group); + } + else { + return 0; + } + } + /** + * Gets all group names associated with the number provided + * @param groups A mask of groups + * @returns All groups contained in the mask + */ + getGroupNames(groups) { + if (groups === -1) { + return [PhysicsManager.DEFAULT_GROUP]; + } + else { + let g = 1; + let names = []; + for (let i = 0; i < 32; i++) { + if (g & groups) { + // This group is in the groups number + names.push(this.groupNames[i]); + } + // Shift the bit over + g = g << 1; + } + } + } +} +exports.default = PhysicsManager; +/** The default group name */ +PhysicsManager.DEFAULT_GROUP = "Default"; + +},{"../DataTypes/Map":10,"../Events/Emitter":27,"../Events/Receiver":31}],62:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Queue_1 = require("../DataTypes/Queue"); +const Receiver_1 = require("../Events/Receiver"); +const EventQueue_1 = require("../Events/EventQueue"); +const GameEventType_1 = require("../Events/GameEventType"); +// @ignorePage +class Recorder { + constructor() { + this.receiver = new Receiver_1.default(); + this.log = new Queue_1.default(1000); + this.recording = false; + this.playing = false; + this.frame = 0; + this.eventQueue = EventQueue_1.default.getInstance(); + this.eventQueue.subscribe(this.receiver, "all"); + } + update(deltaT) { + if (this.recording) { + this.frame += 1; + } + if (this.playing) { + // If playing, ignore events, just feed the record to the event queue + this.receiver.ignoreEvents(); + /* + While there is a next item, and while it should occur in this frame, + send the event. i.e., while current_frame * current_delta_t is greater + than recorded_frame * recorded_delta_t + */ + while (this.log.hasItems() + && this.log.peekNext().frame * this.log.peekNext().delta < this.frame * deltaT) { + let event = this.log.dequeue().event; + console.log(event); + this.eventQueue.addEvent(event); + } + if (!this.log.hasItems()) { + this.playing = false; + } + this.frame += 1; + } + else { + // If not playing, handle events + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + if (event.type === GameEventType_1.GameEventType.STOP_RECORDING) { + this.recording = false; + } + if (this.recording) { + this.log.enqueue(new LogItem(this.frame, deltaT, event)); + } + if (event.type === GameEventType_1.GameEventType.START_RECORDING) { + this.log.clear(); + this.recording = true; + this.frame = 0; + } + if (event.type === GameEventType_1.GameEventType.PLAY_RECORDING) { + this.frame = 0; + this.recording = false; + this.playing = true; + } + } + } + } +} +exports.default = Recorder; +class LogItem { + constructor(frame, deltaT, event) { + this.frame = frame; + this.delta = deltaT; + this.event = event; + } +} + +},{"../DataTypes/Queue":14,"../Events/EventQueue":28,"../Events/GameEventType":30,"../Events/Receiver":31}],63:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../../DataTypes/Map"); +/** */ +class Registry extends Map_1.default { +} +exports.default = Registry; + +},{"../../DataTypes/Map":10}],64:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const LabelShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/LabelShaderType"); +const PointShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/PointShaderType"); +const RectShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/RectShaderType"); +const SpriteShaderType_1 = require("../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType"); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const Registry_1 = require("./Registry"); +/** + * A registry that handles shaders + */ +class ShaderRegistry extends Registry_1.default { + constructor() { + super(...arguments); + this.registryItems = new Array(); + } + /** + * Preloads all built-in shaders + */ + preload() { + // Get the resourceManager and queue all built-in shaders for preloading + const rm = ResourceManager_1.default.getInstance(); + // Queue a load for the point shader + this.registerAndPreloadItem(ShaderRegistry.POINT_SHADER, PointShaderType_1.default, "builtin/shaders/point.vshader", "builtin/shaders/point.fshader"); + // Queue a load for the rect shader + this.registerAndPreloadItem(ShaderRegistry.RECT_SHADER, RectShaderType_1.default, "builtin/shaders/rect.vshader", "builtin/shaders/rect.fshader"); + // Queue a load for the sprite shader + this.registerAndPreloadItem(ShaderRegistry.SPRITE_SHADER, SpriteShaderType_1.default, "builtin/shaders/sprite.vshader", "builtin/shaders/sprite.fshader"); + // Queue a load for the label shader + this.registerAndPreloadItem(ShaderRegistry.LABEL_SHADER, LabelShaderType_1.default, "builtin/shaders/label.vshader", "builtin/shaders/label.fshader"); + // Queue a load for any preloaded items + for (let item of this.registryItems) { + const shader = new item.constr(item.key); + shader.initBufferObject(); + this.add(item.key, shader); + // Load if desired + if (item.preload !== undefined) { + rm.shader(item.key, item.preload.vshaderLocation, item.preload.fshaderLocation); + } + } + } + /** + * Registers a shader in the registry and loads it before the game begins + * @param key The key you wish to assign to the shader + * @param constr The constructor of the ShaderType + * @param vshaderLocation The location of the vertex shader + * @param fshaderLocation the location of the fragment shader + */ + registerAndPreloadItem(key, constr, vshaderLocation, fshaderLocation) { + let shaderPreload = new ShaderPreload(); + shaderPreload.vshaderLocation = vshaderLocation; + shaderPreload.fshaderLocation = fshaderLocation; + let registryItem = new ShaderRegistryItem(); + registryItem.key = key; + registryItem.constr = constr; + registryItem.preload = shaderPreload; + this.registryItems.push(registryItem); + } + /** + * Registers a shader in the registry. NOTE: If you use this, you MUST load the shader before use. + * If you wish to preload the shader, use registerAndPreloadItem() + * @param key The key you wish to assign to the shader + * @param constr The constructor of the ShaderType + */ + registerItem(key, constr) { + let registryItem = new ShaderRegistryItem(); + registryItem.key = key; + registryItem.constr = constr; + this.registryItems.push(registryItem); + } +} +exports.default = ShaderRegistry; +// Shader names +ShaderRegistry.POINT_SHADER = "point"; +ShaderRegistry.RECT_SHADER = "rect"; +ShaderRegistry.SPRITE_SHADER = "sprite"; +ShaderRegistry.LABEL_SHADER = "label"; +class ShaderRegistryItem { +} +class ShaderPreload { +} + +},{"../../Rendering/WebGLRendering/ShaderTypes/LabelShaderType":78,"../../Rendering/WebGLRendering/ShaderTypes/PointShaderType":79,"../../Rendering/WebGLRendering/ShaderTypes/RectShaderType":81,"../../Rendering/WebGLRendering/ShaderTypes/SpriteShaderType":82,"../../ResourceManager/ResourceManager":83,"./Registry":63}],65:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +const ShaderRegistry_1 = require("./Registries/ShaderRegistry"); +/** + * The Registry is the system's way of converting classes and types into string + * representations for use elsewhere in the application. + * It allows classes to be accessed without explicitly using constructors in code, + * and for resources to be loaded at Game creation time. + */ +class RegistryManager { + static preload() { + this.shaders.preload(); + this.registries.forEach((key) => this.registries.get(key).preload()); + } + static addCustomRegistry(name, registry) { + this.registries.add(name, registry); + } + static getRegistry(key) { + return this.registries.get(key); + } +} +exports.default = RegistryManager; +RegistryManager.shaders = new ShaderRegistry_1.default(); +/** Additional custom registries to add to the registry manager */ +RegistryManager.registries = new Map_1.default(); + +},{"../DataTypes/Map":10,"./Registries/ShaderRegistry":64}],66:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../../DataTypes/Map"); +const Emitter_1 = require("../../Events/Emitter"); +const AnimationTypes_1 = require("./AnimationTypes"); +/** + * An animation manager class for an animated CanvasNode. + * This class keeps track of the possible animations, as well as the current animation state, + * and abstracts all interactions with playing, pausing, and stopping animations as well as + * creating new animations from the CanvasNode. + */ +class AnimationManager { + /** + * Creates a new AnimationManager + * @param owner The owner of the AnimationManager + */ + constructor(owner) { + this.owner = owner; + this.animationState = AnimationTypes_1.AnimationState.STOPPED; + this.currentAnimation = ""; + this.currentFrame = 0; + this.frameProgress = 0; + this.loop = false; + this.animations = new Map_1.default(); + this.onEndEvent = null; + this.emitter = new Emitter_1.default(); + } + /** + * Add an animation to this sprite + * @param key The unique key of the animation + * @param animation The animation data + */ + add(key, animation) { + this.animations.add(key, animation); + } + /** + * Gets the index specified by the current animation and current frame + * @returns The index in the current animation + */ + getIndex() { + if (this.animations.has(this.currentAnimation)) { + return this.animations.get(this.currentAnimation).frames[this.currentFrame].index; + } + else { + // No current animation, warn the user + console.warn(`Animation index was requested, but the current animation: ${this.currentAnimation} was invalid`); + return 0; + } + } + /** + * Determines whether the specified animation is currently playing + * @param key The key of the animation to check + * @returns true if the specified animation is playing, false otherwise + */ + isPlaying(key) { + return this.currentAnimation === key && this.animationState === AnimationTypes_1.AnimationState.PLAYING; + } + /** + * Retrieves the current animation index and advances the animation frame + * @returns The index of the animation frame + */ + getIndexAndAdvanceAnimation() { + // If we aren't playing, we won't be advancing the animation + if (!(this.animationState === AnimationTypes_1.AnimationState.PLAYING)) { + return this.getIndex(); + } + if (this.animations.has(this.currentAnimation)) { + let currentAnimation = this.animations.get(this.currentAnimation); + let index = currentAnimation.frames[this.currentFrame].index; + // Advance the animation + this.frameProgress += 1; + if (this.frameProgress >= currentAnimation.frames[this.currentFrame].duration) { + // We have been on this frame for its whole duration, go to the next one + this.frameProgress = 0; + this.currentFrame += 1; + if (this.currentFrame >= currentAnimation.frames.length) { + // We have reached the end of this animation + if (this.loop) { + this.currentFrame = 0; + this.frameProgress = 0; + } + else { + this.endCurrentAnimation(); + } + } + } + // Return the current index + return index; + } + else { + // No current animation, can't advance. Warn the user + console.warn(`Animation index and advance was requested, but the current animation (${this.currentAnimation}) in node with id: ${this.owner.id} was invalid`); + return 0; + } + } + /** Ends the current animation and fires any necessary events, as well as starting any new animations */ + endCurrentAnimation() { + this.currentFrame = 0; + this.animationState = AnimationTypes_1.AnimationState.STOPPED; + if (this.onEndEvent !== null) { + this.emitter.fireEvent(this.onEndEvent, { owner: this.owner.id, animation: this.currentAnimation }); + } + // If there is a pending animation, play it + if (this.pendingAnimation !== null) { + this.play(this.pendingAnimation, this.pendingLoop, this.pendingOnEnd); + } + } + /** + * Plays the specified animation. Does not restart it if it is already playing + * @param animation The name of the animation to play + * @param loop Whether or not to loop the animation. False by default + * @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false. + */ + playIfNotAlready(animation, loop, onEnd) { + if (this.currentAnimation !== animation) { + this.play(animation, loop, onEnd); + } + } + /** + * Plays the specified animation + * @param animation The name of the animation to play + * @param loop Whether or not to loop the animation. False by default + * @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false. + */ + play(animation, loop, onEnd) { + this.currentAnimation = animation; + this.currentFrame = 0; + this.frameProgress = 0; + this.animationState = AnimationTypes_1.AnimationState.PLAYING; + // If loop arg was provided, use that + if (loop !== undefined) { + this.loop = loop; + } + else { + // Otherwise, use what the json file specified + this.loop = this.animations.get(animation).repeat; + } + if (onEnd !== undefined) { + this.onEndEvent = onEnd; + } + else { + this.onEndEvent = null; + } + // Reset pending animation + this.pendingAnimation = null; + } + /** + * Queues a single animation to be played after the current one. Does NOT stack. + * Queueing additional animations past 1 will just replace the queued animation + * @param animation The animation to queue + * @param loop Whether or not the loop the queued animation + * @param onEnd The event to fire when the queued animation ends + */ + queue(animation, loop = false, onEnd) { + this.pendingAnimation = animation; + this.pendingLoop = loop; + if (onEnd !== undefined) { + this.pendingOnEnd = onEnd; + } + else { + this.pendingOnEnd = null; + } + } + /** Pauses the current animation */ + pause() { + this.animationState = AnimationTypes_1.AnimationState.PAUSED; + } + /** Resumes the current animation if possible */ + resume() { + if (this.animationState === AnimationTypes_1.AnimationState.PAUSED) { + this.animationState = AnimationTypes_1.AnimationState.PLAYING; + } + } + /** Stops the current animation. The animation cannot be resumed after this. */ + stop() { + this.animationState = AnimationTypes_1.AnimationState.STOPPED; + } +} +exports.default = AnimationManager; + +},{"../../DataTypes/Map":10,"../../Events/Emitter":27,"./AnimationTypes":67}],67:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TweenData = exports.TweenEffect = exports.AnimationData = exports.AnimationState = void 0; +// @ignorePage +var AnimationState; +(function (AnimationState) { + AnimationState[AnimationState["STOPPED"] = 0] = "STOPPED"; + AnimationState[AnimationState["PAUSED"] = 1] = "PAUSED"; + AnimationState[AnimationState["PLAYING"] = 2] = "PLAYING"; +})(AnimationState = exports.AnimationState || (exports.AnimationState = {})); +class AnimationData { + constructor() { + this.repeat = false; + } +} +exports.AnimationData = AnimationData; +class TweenEffect { +} +exports.TweenEffect = TweenEffect; +class TweenData { +} +exports.TweenData = TweenData; + +},{}],68:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ParticleSystemManager { + constructor() { + this.particleSystems = new Array(); + } + static getInstance() { + if (ParticleSystemManager.instance === null) { + ParticleSystemManager.instance = new ParticleSystemManager(); + } + return ParticleSystemManager.instance; + } + registerParticleSystem(system) { + this.particleSystems.push(system); + } + deregisterParticleSystem(system) { + let index = this.particleSystems.indexOf(system); + this.particleSystems.splice(index, 1); + } + clearParticleSystems() { + this.particleSystems = new Array(); + } + update(deltaT) { + for (let particleSystem of this.particleSystems) { + particleSystem.update(deltaT); + } + } +} +exports.default = ParticleSystemManager; +ParticleSystemManager.instance = null; + +},{}],69:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../../DataTypes/Map"); +const AnimationTypes_1 = require("./AnimationTypes"); +const EaseFunctions_1 = require("../../Utils/EaseFunctions"); +const MathUtils_1 = require("../../Utils/MathUtils"); +const TweenManager_1 = require("./TweenManager"); +const Emitter_1 = require("../../Events/Emitter"); +/** + * A manager for the tweens of a GameNode. + * Tweens are short animations played by interpolating between two properties using an easing function. + * For a good visual representation of easing functions, check out @link(https://easings.net/)(https://easings.net/). + * Multiple tween can be played at the same time, as long as they don't change the same property. + * This allows for some interesting polishes or animations that may be very difficult to do with sprite work alone + * - especially pixel art (such as rotations or scaling). + */ +class TweenController { + /** + * Creates a new TweenController + * @param owner The owner of the TweenController + */ + constructor(owner) { + this.owner = owner; + this.tweens = new Map_1.default(); + this.emitter = new Emitter_1.default(); + // Give ourselves to the TweenManager + TweenManager_1.default.getInstance().registerTweenController(this); + } + /** + * Destroys this TweenController + */ + destroy() { + // Only the gamenode and the tween manager should have a reference to this + delete this.owner.tweens; + TweenManager_1.default.getInstance().deregisterTweenController(this); + } + /** + * Add a tween to this game node + * @param key The name of the tween + * @param tween The data of the tween + */ + add(key, tween) { + let typedTween = tween; + // Initialize members that we need (and the user didn't provide) + typedTween.progress = 0; + typedTween.elapsedTime = 0; + typedTween.animationState = AnimationTypes_1.AnimationState.STOPPED; + this.tweens.add(key, typedTween); + } + /** + * Play a tween with a certain name + * @param key The name of the tween to play + * @param loop Whether or not the tween should loop + */ + play(key, loop) { + if (this.tweens.has(key)) { + let tween = this.tweens.get(key); + // Set loop if needed + if (loop !== undefined) { + tween.loop = loop; + } + // Set the initial values + for (let effect of tween.effects) { + if (effect.resetOnComplete) { + effect.initialValue = this.owner[effect.property]; + } + } + // Start the tween running + tween.animationState = AnimationTypes_1.AnimationState.PLAYING; + tween.elapsedTime = 0; + tween.progress = 0; + tween.reversing = false; + } + else { + console.warn(`Tried to play tween "${key}" on node with id ${this.owner.id}, but no such tween exists`); + } + } + /** + * Pauses a playing tween. Does not affect tweens that are stopped. + * @param key The name of the tween to pause. + */ + pause(key) { + if (this.tweens.has(key)) { + this.tweens.get(key).animationState = AnimationTypes_1.AnimationState.PAUSED; + } + } + /** + * Resumes a paused tween. + * @param key The name of the tween to resume + */ + resume(key) { + if (this.tweens.has(key)) { + let tween = this.tweens.get(key); + if (tween.animationState === AnimationTypes_1.AnimationState.PAUSED) + tween.animationState = AnimationTypes_1.AnimationState.PLAYING; + } + } + /** + * Stops a currently playing tween + * @param key The key of the tween + */ + stop(key) { + if (this.tweens.has(key)) { + let tween = this.tweens.get(key); + tween.animationState = AnimationTypes_1.AnimationState.STOPPED; + // Return to the initial values + for (let effect of tween.effects) { + if (effect.resetOnComplete) { + this.owner[effect.property] = effect.initialValue; + } + } + } + } + /** + * The natural stop of a currently playing tween + * @param key The key of the tween + */ + end(key) { + this.stop(key); + if (this.tweens.has(key)) { + // Get the tween + let tween = this.tweens.get(key); + // If it has an onEnd, send an event + if (tween.onEnd) { + let data = { key: key, node: this.owner.id }; + // If it has onEnd event data, add each entry, as long as the key is not named 'key' or 'node' + if (tween.onEndData) { + Object.keys(tween.onEndData).forEach(key => { + if (key !== "key" && key !== "node") { + data[key] = tween.onEndData[key]; + } + }); + } + this.emitter.fireEvent(tween.onEnd, data); + } + } + } + /** + * Stops all currently playing tweens + */ + stopAll() { + this.tweens.forEach(key => this.stop(key)); + } + update(deltaT) { + this.tweens.forEach(key => { + let tween = this.tweens.get(key); + if (tween.animationState === AnimationTypes_1.AnimationState.PLAYING) { + // Update the progress of the tween + tween.elapsedTime += deltaT * 1000; + // If we're past the startDelay, do the tween + if (tween.elapsedTime >= tween.startDelay) { + if (!tween.reversing && tween.elapsedTime >= tween.startDelay + tween.duration) { + // If we're over time, stop the tween, loop, or reverse + if (tween.reverseOnComplete) { + // If we're over time and can reverse, do so + tween.reversing = true; + } + else if (tween.loop) { + // If we can't reverse and can loop, do so + tween.elapsedTime -= tween.duration; + } + else { + // We aren't looping and can't reverse, so stop + this.end(key); + } + } + // Check for the end of reversing + if (tween.reversing && tween.elapsedTime >= tween.startDelay + 2 * tween.duration) { + if (tween.loop) { + tween.reversing = false; + tween.elapsedTime -= 2 * tween.duration; + } + else { + this.end(key); + } + } + // Update the progress, make sure it is between 0 and 1. Errors from this should never be large + if (tween.reversing) { + tween.progress = MathUtils_1.default.clamp01((2 * tween.duration - (tween.elapsedTime - tween.startDelay)) / tween.duration); + } + else { + tween.progress = MathUtils_1.default.clamp01((tween.elapsedTime - tween.startDelay) / tween.duration); + } + for (let effect of tween.effects) { + // Get the value from the ease function that corresponds to our progress + let ease = EaseFunctions_1.default[effect.ease](tween.progress); + // Use the value to lerp the property + let value = MathUtils_1.default.lerp(effect.start, effect.end, ease); + // Assign the value of the property + this.owner[effect.property] = value; + } + } + } + }); + } +} +exports.default = TweenController; + +},{"../../DataTypes/Map":10,"../../Events/Emitter":27,"../../Utils/EaseFunctions":100,"../../Utils/MathUtils":102,"./AnimationTypes":67,"./TweenManager":70}],70:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class TweenManager { + constructor() { + this.tweenControllers = new Array(); + } + static getInstance() { + if (TweenManager.instance === null) { + TweenManager.instance = new TweenManager(); + } + return TweenManager.instance; + } + registerTweenController(controller) { + this.tweenControllers.push(controller); + } + deregisterTweenController(controller) { + let index = this.tweenControllers.indexOf(controller); + this.tweenControllers.splice(index, 1); + } + clearTweenControllers() { + this.tweenControllers = new Array(); + } + update(deltaT) { + for (let tweenController of this.tweenControllers) { + tweenController.update(deltaT); + } + } +} +exports.default = TweenManager; +TweenManager.instance = null; + +},{}],71:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Graphic_1 = require("../Nodes/Graphic"); +const Point_1 = require("../Nodes/Graphics/Point"); +const Rect_1 = require("../Nodes/Graphics/Rect"); +const Sprite_1 = require("../Nodes/Sprites/Sprite"); +const OrthogonalTilemap_1 = require("../Nodes/Tilemaps/OrthogonalTilemap"); +const UIElement_1 = require("../Nodes/UIElement"); +const GraphicRenderer_1 = require("./CanvasRendering/GraphicRenderer"); +const RenderingManager_1 = require("./RenderingManager"); +const TilemapRenderer_1 = require("./CanvasRendering/TilemapRenderer"); +const UIElementRenderer_1 = require("./CanvasRendering/UIElementRenderer"); +const Label_1 = require("../Nodes/UIElements/Label"); +const Button_1 = require("../Nodes/UIElements/Button"); +const Slider_1 = require("../Nodes/UIElements/Slider"); +const TextInput_1 = require("../Nodes/UIElements/TextInput"); +const AnimatedSprite_1 = require("../Nodes/Sprites/AnimatedSprite"); +const Vec2_1 = require("../DataTypes/Vec2"); +const Line_1 = require("../Nodes/Graphics/Line"); +/** + * An implementation of the RenderingManager class using CanvasRenderingContext2D. + */ +class CanvasRenderer extends RenderingManager_1.default { + constructor() { + super(); + } + // @override + setScene(scene) { + this.scene = scene; + this.graphicRenderer.setScene(scene); + this.tilemapRenderer.setScene(scene); + this.uiElementRenderer.setScene(scene); + } + // @override + initializeCanvas(canvas, width, height) { + canvas.width = width; + canvas.height = height; + this.worldSize = new Vec2_1.default(width, height); + this.ctx = canvas.getContext("2d"); + this.graphicRenderer = new GraphicRenderer_1.default(this.ctx); + this.tilemapRenderer = new TilemapRenderer_1.default(this.ctx); + this.uiElementRenderer = new UIElementRenderer_1.default(this.ctx); + // For crisp pixel art + this.ctx.imageSmoothingEnabled = false; + return this.ctx; + } + // @override + render(visibleSet, tilemaps, uiLayers) { + // Sort by depth, then by visible set by y-value + visibleSet.sort((a, b) => { + if (a.getLayer().getDepth() === b.getLayer().getDepth()) { + return (a.boundary.bottom) - (b.boundary.bottom); + } + else { + return a.getLayer().getDepth() - b.getLayer().getDepth(); + } + }); + let tilemapIndex = 0; + let tilemapLength = tilemaps.length; + let visibleSetIndex = 0; + let visibleSetLength = visibleSet.length; + while (tilemapIndex < tilemapLength || visibleSetIndex < visibleSetLength) { + // Check conditions where we've already reached the edge of one list + if (tilemapIndex >= tilemapLength) { + // Only render the remaining visible set + let node = visibleSet[visibleSetIndex++]; + if (node.visible) { + this.renderNode(node); + } + continue; + } + if (visibleSetIndex >= visibleSetLength) { + // Only render tilemaps + this.renderTilemap(tilemaps[tilemapIndex++]); + continue; + } + // Render whichever is further down + if (tilemaps[tilemapIndex].getLayer().getDepth() <= visibleSet[visibleSetIndex].getLayer().getDepth()) { + this.renderTilemap(tilemaps[tilemapIndex++]); + } + else { + let node = visibleSet[visibleSetIndex++]; + if (node.visible) { + this.renderNode(node); + } + } + } + // Render the uiLayers on top of everything else + let sortedUILayers = new Array(); + uiLayers.forEach(key => sortedUILayers.push(uiLayers.get(key))); + sortedUILayers = sortedUILayers.sort((ui1, ui2) => ui1.getDepth() - ui2.getDepth()); + sortedUILayers.forEach(uiLayer => { + if (!uiLayer.isHidden()) + uiLayer.getItems().forEach(node => { + if (node.visible) { + this.renderNode(node); + } + }); + }); + } + /** + * Renders a specified CanvasNode + * @param node The CanvasNode to render + */ + renderNode(node) { + // Calculate the origin of the viewport according to this sprite + this.origin = this.scene.getViewTranslation(node); + // Get the zoom level of the scene + this.zoom = this.scene.getViewScale(); + // Move the canvas to the position of the node and rotate + let xScale = 1; + let yScale = 1; + if (node instanceof Sprite_1.default) { + xScale = node.invertX ? -1 : 1; + yScale = node.invertY ? -1 : 1; + } + this.ctx.setTransform(xScale, 0, 0, yScale, (node.position.x - this.origin.x) * this.zoom, (node.position.y - this.origin.y) * this.zoom); + this.ctx.rotate(-node.rotation); + let globalAlpha = this.ctx.globalAlpha; + // if(node instanceof Rect){ + // Debug.log("node" + node.id, "Node" + node.id + " Alpha: " + node.alpha); + // } + this.ctx.globalAlpha = node.alpha; + if (node instanceof AnimatedSprite_1.default) { + this.renderAnimatedSprite(node); + } + else if (node instanceof Sprite_1.default) { + this.renderSprite(node); + } + else if (node instanceof Graphic_1.default) { + this.renderGraphic(node); + } + else if (node instanceof UIElement_1.default) { + this.renderUIElement(node); + } + this.ctx.globalAlpha = globalAlpha; + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + } + // @override + renderSprite(sprite) { + // Get the image from the resource manager + let image = this.resourceManager.getImage(sprite.imageId); + /* + Coordinates in the space of the image: + image crop start -> x, y + image crop size -> w, h + Coordinates in the space of the world + image draw start -> x, y + image draw size -> w, h + */ + this.ctx.drawImage(image, sprite.imageOffset.x, sprite.imageOffset.y, sprite.size.x, sprite.size.y, (-sprite.size.x * sprite.scale.x / 2) * this.zoom, (-sprite.size.y * sprite.scale.y / 2) * this.zoom, sprite.size.x * sprite.scale.x * this.zoom, sprite.size.y * sprite.scale.y * this.zoom); + } + // @override + renderAnimatedSprite(sprite) { + // Get the image from the resource manager + let image = this.resourceManager.getImage(sprite.imageId); + let animationIndex = sprite.animation.getIndexAndAdvanceAnimation(); + let animationOffset = sprite.getAnimationOffset(animationIndex); + /* + Coordinates in the space of the image: + image crop start -> x, y + image crop size -> w, h + Coordinates in the space of the world (given we moved) + image draw start -> -w/2, -h/2 + image draw size -> w, h + */ + this.ctx.drawImage(image, sprite.imageOffset.x + animationOffset.x, sprite.imageOffset.y + animationOffset.y, sprite.size.x, sprite.size.y, (-sprite.size.x * sprite.scale.x / 2) * this.zoom, (-sprite.size.y * sprite.scale.y / 2) * this.zoom, sprite.size.x * sprite.scale.x * this.zoom, sprite.size.y * sprite.scale.y * this.zoom); + } + // @override + renderGraphic(graphic) { + if (graphic instanceof Point_1.default) { + this.graphicRenderer.renderPoint(graphic, this.zoom); + } + else if (graphic instanceof Line_1.default) { + this.graphicRenderer.renderLine(graphic, this.origin, this.zoom); + } + else if (graphic instanceof Rect_1.default) { + this.graphicRenderer.renderRect(graphic, this.zoom); + } + } + // @override + renderTilemap(tilemap) { + if (tilemap instanceof OrthogonalTilemap_1.default) { + this.tilemapRenderer.renderOrthogonalTilemap(tilemap); + } + } + // @override + renderUIElement(uiElement) { + if (uiElement instanceof Label_1.default) { + this.uiElementRenderer.renderLabel(uiElement); + } + else if (uiElement instanceof Button_1.default) { + this.uiElementRenderer.renderButton(uiElement); + } + else if (uiElement instanceof Slider_1.default) { + this.uiElementRenderer.renderSlider(uiElement); + } + else if (uiElement instanceof TextInput_1.default) { + this.uiElementRenderer.renderTextInput(uiElement); + } + } + clear(clearColor) { + this.ctx.clearRect(0, 0, this.worldSize.x, this.worldSize.y); + this.ctx.fillStyle = clearColor.toString(); + this.ctx.fillRect(0, 0, this.worldSize.x, this.worldSize.y); + } +} +exports.default = CanvasRenderer; + +},{"../DataTypes/Vec2":24,"../Nodes/Graphic":41,"../Nodes/Graphics/Line":43,"../Nodes/Graphics/Point":45,"../Nodes/Graphics/Rect":46,"../Nodes/Sprites/AnimatedSprite":47,"../Nodes/Sprites/Sprite":48,"../Nodes/Tilemaps/OrthogonalTilemap":50,"../Nodes/UIElement":51,"../Nodes/UIElements/Button":52,"../Nodes/UIElements/Label":53,"../Nodes/UIElements/Slider":54,"../Nodes/UIElements/TextInput":55,"./CanvasRendering/GraphicRenderer":72,"./CanvasRendering/TilemapRenderer":73,"./CanvasRendering/UIElementRenderer":74,"./RenderingManager":75}],72:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +/** + * A utility class to help the @reference[CanvasRenderer] render @reference[Graphic]s + */ +class GraphicRenderer { + constructor(ctx) { + this.resourceManager = ResourceManager_1.default.getInstance(); + this.ctx = ctx; + } + /** + * Sets the scene of this GraphicRenderer + * @param scene The current scene + */ + setScene(scene) { + this.scene = scene; + } + /** + * Renders a point + * @param point The point to render + * @param zoom The zoom level + */ + renderPoint(point, zoom) { + this.ctx.fillStyle = point.color.toStringRGBA(); + this.ctx.fillRect((-point.size.x / 2) * zoom, (-point.size.y / 2) * zoom, point.size.x * zoom, point.size.y * zoom); + } + renderLine(line, origin, zoom) { + this.ctx.strokeStyle = line.color.toStringRGBA(); + this.ctx.lineWidth = line.thickness; + this.ctx.beginPath(); + this.ctx.moveTo(0, 0); + this.ctx.lineTo((line.end.x - line.start.x) * zoom, (line.end.y - line.start.y) * zoom); + this.ctx.closePath(); + this.ctx.stroke(); + } + /** + * Renders a rect + * @param rect The rect to render + * @param zoom The zoom level + */ + renderRect(rect, zoom) { + // Draw the interior of the rect + if (rect.color.a !== 0) { + this.ctx.fillStyle = rect.color.toStringRGB(); + if (rect.fillWidth !== null) { + this.ctx.fillRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.fillWidth * zoom, rect.size.y * zoom); + } + else { + this.ctx.fillRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.size.x * zoom, rect.size.y * zoom); + } + } + // Draw the border of the rect if it isn't transparent + if (rect.borderColor.a !== 0) { + this.ctx.strokeStyle = rect.getBorderColor().toStringRGB(); + this.ctx.lineWidth = rect.getBorderWidth(); + this.ctx.strokeRect((-rect.size.x / 2) * zoom, (-rect.size.y / 2) * zoom, rect.size.x * zoom, rect.size.y * zoom); + } + } +} +exports.default = GraphicRenderer; + +},{"../../ResourceManager/ResourceManager":83}],73:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const Vec2_1 = require("../../DataTypes/Vec2"); +/** + * A utility class for the @reference[CanvasRenderer] to render @reference[Tilemap]s + */ +class TilemapRenderer { + constructor(ctx) { + this.resourceManager = ResourceManager_1.default.getInstance(); + this.ctx = ctx; + } + /** + * Sets the scene of this TilemapRenderer + * @param scene The current scene + */ + setScene(scene) { + this.scene = scene; + } + /** + * Renders an orthogonal tilemap + * @param tilemap The tilemap to render + */ + renderOrthogonalTilemap(tilemap) { + let previousAlpha = this.ctx.globalAlpha; + this.ctx.globalAlpha = tilemap.getLayer().getAlpha(); + let origin = this.scene.getViewTranslation(tilemap); + let size = this.scene.getViewport().getHalfSize(); + let zoom = this.scene.getViewScale(); + let bottomRight = origin.clone().add(size.scaled(2 * zoom)); + if (tilemap.visible) { + let minColRow = tilemap.getColRowAt(origin); + let maxColRow = tilemap.getColRowAt(bottomRight); + for (let x = minColRow.x; x <= maxColRow.x; x++) { + for (let y = minColRow.y; y <= maxColRow.y; y++) { + // Get the tile at this position + let tile = tilemap.getTileAtRowCol(new Vec2_1.default(x, y)); + // Extract the rot/flip parameters if there are any + const mask = (0xE << 28); + const rotFlip = ((mask & tile) >> 28) & 0xF; + tile = tile & ~mask; + // Find the tileset that owns this tile index and render + for (let tileset of tilemap.getTilesets()) { + if (tileset.hasTile(tile)) { + this.renderTile(tileset, tile, x, y, origin, tilemap.scale, zoom, rotFlip); + } + } + } + } + } + this.ctx.globalAlpha = previousAlpha; + } + /** + * Renders a tile + * @param tileset The tileset this tile belongs to + * @param tileIndex The index of the tile + * @param tilemapRow The row of the tile in the tilemap + * @param tilemapCol The column of the tile in the tilemap + * @param origin The origin of the viewport + * @param scale The scale of the tilemap + * @param zoom The zoom level of the viewport + */ + renderTile(tileset, tileIndex, tilemapRow, tilemapCol, origin, scale, zoom, rotFlip) { + let image = this.resourceManager.getImage(tileset.getImageKey()); + // Get the true index + let index = tileIndex - tileset.getStartIndex(); + // Get the row and col of the tile in image space + let row = Math.floor(index / tileset.getNumCols()); + let col = index % tileset.getNumCols(); + let width = tileset.getTileSize().x; + let height = tileset.getTileSize().y; + // Calculate the position to start a crop in the tileset image + let left = col * width; + let top = row * height; + // Calculate the position in the world to render the tile + let x = Math.floor(tilemapRow * width * scale.x); + let y = Math.floor(tilemapCol * height * scale.y); + let worldX = Math.floor((x - origin.x) * zoom); + let worldY = Math.floor((y - origin.y) * zoom); + let worldWidth = Math.ceil(width * scale.x * zoom); + let worldHeight = Math.ceil(height * scale.y * zoom); + if (rotFlip !== 0) { + let scaleX = 1; + let scaleY = 1; + let shearX = 0; + let shearY = 0; + // Flip on the x-axis + if (rotFlip & 8) { + scaleX = -1; + } + // Flip on the y-axis + if (rotFlip & 4) { + scaleY = -1; + } + // Flip over the line y=x + if (rotFlip & 2) { + shearX = scaleY; + shearY = scaleX; + scaleX = 0; + scaleY = 0; + } + this.ctx.setTransform(scaleX, shearX, shearY, scaleY, worldX + worldWidth / 2, worldY + worldHeight / 2); + // Render the tile + this.ctx.drawImage(image, left, top, width, height, -worldWidth / 2, -worldHeight / 2, worldWidth, worldHeight); + if (rotFlip !== 0) { + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + } + } + else { + // No rotations, don't do the calculations, just render the tile + // Render the tile + this.ctx.drawImage(image, left, top, width, height, worldX, worldY, worldWidth, worldHeight); + } + } +} +exports.default = TilemapRenderer; + +},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83}],74:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../DataTypes/Vec2"); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const MathUtils_1 = require("../../Utils/MathUtils"); +/** + * A utility class to help the @reference[CanvasRenderer] render @reference[UIElement]s + */ +class UIElementRenderer { + constructor(ctx) { + this.resourceManager = ResourceManager_1.default.getInstance(); + this.ctx = ctx; + } + /** + * Sets the scene of this UIElementRenderer + * @param scene The current scene + */ + setScene(scene) { + this.scene = scene; + } + /** + * Renders a label + * @param label The label to render + */ + renderLabel(label) { + // // If the size is unassigned (by the user or automatically) assign it + // label.handleInitialSizing(this.ctx); + // // Grab the global alpha so we can adjust it for this render + // let previousAlpha = this.ctx.globalAlpha; + // // Get the font and text position in label + // this.ctx.font = label.getFontString(); + // let offset = label.calculateTextOffset(this.ctx); + // // Stroke and fill a rounded rect and give it text + // this.ctx.globalAlpha = label.backgroundColor.a; + // this.ctx.fillStyle = label.calculateBackgroundColor().toStringRGBA(); + // this.ctx.fillRoundedRect(-label.size.x/2, -label.size.y/2, + // label.size.x, label.size.y, label.borderRadius); + // this.ctx.strokeStyle = label.calculateBorderColor().toStringRGBA(); + // this.ctx.globalAlpha = label.borderColor.a; + // this.ctx.lineWidth = label.borderWidth; + // this.ctx.strokeRoundedRect(-label.size.x/2, -label.size.y/2, + // label.size.x, label.size.y, label.borderRadius); + // this.ctx.fillStyle = label.calculateTextColor(); + // this.ctx.globalAlpha = label.textColor.a; + // this.ctx.fillText(label.text, offset.x - label.size.x/2, offset.y - label.size.y/2); + // this.ctx.globalAlpha = previousAlpha; + // If the size is unassigned (by the user or automatically) assign it + let lines = label.text.split('\n'); + let tempText = label.text; + if (lines.length > 1) { + let max = 0; + let maxLengthIndex = 0; + for (let i = 0; i < lines.length; i++) { + if (lines[i].length > max) { + max = lines[i].length; + maxLengthIndex = i; + } + } + label.text = lines[maxLengthIndex]; + } + label.handleInitialSizing(this.ctx); + // Grab the global alpha so we can adjust it for this render + let previousAlpha = this.ctx.globalAlpha; + // Get the font and text position in label + this.ctx.font = label.getFontString(); + let offset = label.calculateTextOffset(this.ctx); + // Stroke and fill a rounded rect and give it text + this.ctx.globalAlpha = label.backgroundColor.a; + this.ctx.fillStyle = label.calculateBackgroundColor().toStringRGBA(); + this.ctx.fillRoundedRect(-label.size.x / 2, -label.size.y / 2, label.size.x, label.size.y, label.borderRadius); + this.ctx.strokeStyle = label.calculateBorderColor().toStringRGBA(); + this.ctx.globalAlpha = label.borderColor.a; + this.ctx.lineWidth = label.borderWidth; + this.ctx.strokeRoundedRect(-label.size.x / 2, -label.size.y / 2, label.size.x, label.size.y + ((lines.length - 1) * label.fontSize), label.borderRadius); + this.ctx.fillStyle = label.calculateTextColor(); + this.ctx.globalAlpha = label.textColor.a; + if (lines.length === 1) { + this.ctx.fillText(label.text, offset.x - label.size.x / 2, (offset.y - label.size.y / 2)); + } + else { + for (let i = 0; i < lines.length; i++) { + let additionalY = i * (label.size.y / 2 + (label.fontSize === 40 ? 20 : 10)); + label.text = lines[i]; + offset = label.calculateTextOffset(this.ctx); + this.ctx.fillText(lines[i], (offset.x - label.size.x / 2), (offset.y - label.size.y / 2 + additionalY)); + } + } + this.ctx.globalAlpha = previousAlpha; + label.text = tempText; + } + /** + * Renders a button + * @param button The button to render + */ + renderButton(button) { + this.renderLabel(button); + } + /** + * Renders a slider + * @param slider The slider to render + */ + renderSlider(slider) { + // Grab the global alpha so we can adjust it for this render + let previousAlpha = this.ctx.globalAlpha; + this.ctx.globalAlpha = slider.getLayer().getAlpha(); + // Calcualate the slider size + let sliderSize = new Vec2_1.default(slider.size.x, 2); + // Draw the slider + this.ctx.fillStyle = slider.sliderColor.toString(); + this.ctx.fillRoundedRect(-sliderSize.x / 2, -sliderSize.y / 2, sliderSize.x, sliderSize.y, slider.borderRadius); + // Calculate the nib size and position + let x = MathUtils_1.default.lerp(-slider.size.x / 2, slider.size.x / 2, slider.getValue()); + // Draw the nib + this.ctx.fillStyle = slider.nibColor.toString(); + this.ctx.fillRoundedRect(x - slider.nibSize.x / 2, -slider.nibSize.y / 2, slider.nibSize.x, slider.nibSize.y, slider.borderRadius); + // Reset the alpha + this.ctx.globalAlpha = previousAlpha; + } + /** + * Renders a textInput + * @param textInput The textInput to render + */ + renderTextInput(textInput) { + // Show a cursor sometimes + if (textInput.focused && textInput.cursorCounter % 60 > 30) { + textInput.text += "|"; + } + this.renderLabel(textInput); + if (textInput.focused) { + if (textInput.cursorCounter % 60 > 30) { + textInput.text = textInput.text.substring(0, textInput.text.length - 1); + } + textInput.cursorCounter += 1; + if (textInput.cursorCounter >= 60) { + textInput.cursorCounter = 0; + } + } + } +} +exports.default = UIElementRenderer; + +},{"../../DataTypes/Vec2":24,"../../ResourceManager/ResourceManager":83,"../../Utils/MathUtils":102}],75:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +/** + * An abstract framework to put all rendering in once place in the application + */ +class RenderingManager { + constructor() { + this.resourceManager = ResourceManager_1.default.getInstance(); + } + /** + * Sets the scene currently being rendered + * @param scene The current Scene + */ + setScene(scene) { + this.scene = scene; + } +} +exports.default = RenderingManager; + +},{"../ResourceManager/ResourceManager":83}],76:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../DataTypes/Vec2"); +const Graphic_1 = require("../Nodes/Graphic"); +const Point_1 = require("../Nodes/Graphics/Point"); +const Rect_1 = require("../Nodes/Graphics/Rect"); +const AnimatedSprite_1 = require("../Nodes/Sprites/AnimatedSprite"); +const Sprite_1 = require("../Nodes/Sprites/Sprite"); +const UIElement_1 = require("../Nodes/UIElement"); +const Label_1 = require("../Nodes/UIElements/Label"); +const ShaderRegistry_1 = require("../Registry/Registries/ShaderRegistry"); +const RegistryManager_1 = require("../Registry/RegistryManager"); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +const ParallaxLayer_1 = require("../Scene/Layers/ParallaxLayer"); +const RenderingManager_1 = require("./RenderingManager"); +class WebGLRenderer extends RenderingManager_1.default { + initializeCanvas(canvas, width, height) { + canvas.width = width; + canvas.height = height; + this.worldSize = Vec2_1.default.ZERO; + this.worldSize.x = width; + this.worldSize.y = height; + // Get the WebGL context + this.gl = canvas.getContext("webgl"); + this.gl.viewport(0, 0, canvas.width, canvas.height); + this.gl.disable(this.gl.DEPTH_TEST); + this.gl.enable(this.gl.BLEND); + this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); + this.gl.enable(this.gl.CULL_FACE); + // Tell the resource manager we're using WebGL + ResourceManager_1.default.getInstance().useWebGL(true, this.gl); + // Show the text canvas and get its context + let textCanvas = document.getElementById("text-canvas"); + textCanvas.hidden = false; + this.textCtx = textCanvas.getContext("2d"); + // Size the text canvas to be the same as the game canvas + textCanvas.height = height; + textCanvas.width = width; + return this.gl; + } + render(visibleSet, tilemaps, uiLayers) { + for (let node of visibleSet) { + this.renderNode(node); + } + uiLayers.forEach(key => { + if (!uiLayers.get(key).isHidden()) + uiLayers.get(key).getItems().forEach(node => this.renderNode(node)); + }); + } + clear(color) { + this.gl.clearColor(color.r, color.g, color.b, color.a); + this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + this.textCtx.clearRect(0, 0, this.worldSize.x, this.worldSize.y); + } + renderNode(node) { + // Calculate the origin of the viewport according to this sprite + this.origin = this.scene.getViewTranslation(node); + // Get the zoom level of the scene + this.zoom = this.scene.getViewScale(); + if (node.hasCustomShader) { + // If the node has a custom shader, render using that + this.renderCustom(node); + } + else if (node instanceof Graphic_1.default) { + this.renderGraphic(node); + } + else if (node instanceof Sprite_1.default) { + if (node instanceof AnimatedSprite_1.default) { + this.renderAnimatedSprite(node); + } + else { + this.renderSprite(node); + } + } + else if (node instanceof UIElement_1.default) { + this.renderUIElement(node); + } + } + renderSprite(sprite) { + let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.SPRITE_SHADER); + let options = this.addOptions(shader.getOptions(sprite), sprite); + shader.render(this.gl, options); + } + renderAnimatedSprite(sprite) { + let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.SPRITE_SHADER); + let options = this.addOptions(shader.getOptions(sprite), sprite); + shader.render(this.gl, options); + } + renderGraphic(graphic) { + if (graphic instanceof Point_1.default) { + let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.POINT_SHADER); + let options = this.addOptions(shader.getOptions(graphic), graphic); + shader.render(this.gl, options); + } + else if (graphic instanceof Rect_1.default) { + let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.RECT_SHADER); + let options = this.addOptions(shader.getOptions(graphic), graphic); + shader.render(this.gl, options); + } + } + renderTilemap(tilemap) { + throw new Error("Method not implemented."); + } + renderUIElement(uiElement) { + if (uiElement instanceof Label_1.default) { + let shader = RegistryManager_1.default.shaders.get(ShaderRegistry_1.default.LABEL_SHADER); + let options = this.addOptions(shader.getOptions(uiElement), uiElement); + shader.render(this.gl, options); + this.textCtx.setTransform(1, 0, 0, 1, (uiElement.position.x - this.origin.x) * this.zoom, (uiElement.position.y - this.origin.y) * this.zoom); + this.textCtx.rotate(-uiElement.rotation); + let globalAlpha = this.textCtx.globalAlpha; + this.textCtx.globalAlpha = uiElement.alpha; + // Render text + this.textCtx.font = uiElement.getFontString(); + let offset = uiElement.calculateTextOffset(this.textCtx); + this.textCtx.fillStyle = uiElement.calculateTextColor(); + this.textCtx.globalAlpha = uiElement.textColor.a; + this.textCtx.fillText(uiElement.text, offset.x - uiElement.size.x / 2, offset.y - uiElement.size.y / 2); + this.textCtx.globalAlpha = globalAlpha; + this.textCtx.setTransform(1, 0, 0, 1, 0, 0); + } + } + renderCustom(node) { + let shader = RegistryManager_1.default.shaders.get(node.customShaderKey); + let options = this.addOptions(shader.getOptions(node), node); + shader.render(this.gl, options); + } + addOptions(options, node) { + // Give the shader access to the world size + options.worldSize = this.worldSize; + // Adjust the origin position to the parallax + let layer = node.getLayer(); + let parallax = new Vec2_1.default(1, 1); + if (layer instanceof ParallaxLayer_1.default) { + parallax = layer.parallax; + } + options.origin = this.origin.clone().mult(parallax); + return options; + } +} +exports.default = WebGLRenderer; + +},{"../DataTypes/Vec2":24,"../Nodes/Graphic":41,"../Nodes/Graphics/Point":45,"../Nodes/Graphics/Rect":46,"../Nodes/Sprites/AnimatedSprite":47,"../Nodes/Sprites/Sprite":48,"../Nodes/UIElement":51,"../Nodes/UIElements/Label":53,"../Registry/Registries/ShaderRegistry":64,"../Registry/RegistryManager":65,"../ResourceManager/ResourceManager":83,"../Scene/Layers/ParallaxLayer":88,"./RenderingManager":75}],77:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +/** + * A wrapper class for WebGL shaders. + * This class is a singleton, and there is only one for each shader type. + * All objects that use this shader type will refer to and modify this same type. + */ +class ShaderType { + constructor(programKey) { + this.programKey = programKey; + this.resourceManager = ResourceManager_1.default.getInstance(); + } + /** + * Extracts the options from the CanvasNode and gives them to the render function + * @param node The node to get options from + * @returns An object containing the options that should be passed to the render function + */ + getOptions(node) { return {}; } +} +exports.default = ShaderType; + +},{"../../ResourceManager/ResourceManager":83}],78:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Mat4x4_1 = require("../../../DataTypes/Mat4x4"); +const Vec2_1 = require("../../../DataTypes/Vec2"); +const ResourceManager_1 = require("../../../ResourceManager/ResourceManager"); +const QuadShaderType_1 = require("./QuadShaderType"); +/** */ +class LabelShaderType extends QuadShaderType_1.default { + constructor(programKey) { + super(programKey); + this.resourceManager = ResourceManager_1.default.getInstance(); + } + initBufferObject() { + this.bufferObjectKey = "label"; + this.resourceManager.createBuffer(this.bufferObjectKey); + } + render(gl, options) { + const backgroundColor = options.backgroundColor.toWebGL(); + const borderColor = options.borderColor.toWebGL(); + const program = this.resourceManager.getShaderProgram(this.programKey); + const buffer = this.resourceManager.getBuffer(this.bufferObjectKey); + gl.useProgram(program); + const vertexData = this.getVertices(options.size.x, options.size.y); + const FSIZE = vertexData.BYTES_PER_ELEMENT; + // Bind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); + // Attributes + const a_Position = gl.getAttribLocation(program, "a_Position"); + gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE); + gl.enableVertexAttribArray(a_Position); + // Uniforms + const u_BackgroundColor = gl.getUniformLocation(program, "u_BackgroundColor"); + gl.uniform4fv(u_BackgroundColor, backgroundColor); + const u_BorderColor = gl.getUniformLocation(program, "u_BorderColor"); + gl.uniform4fv(u_BorderColor, borderColor); + const u_MaxSize = gl.getUniformLocation(program, "u_MaxSize"); + gl.uniform2f(u_MaxSize, -vertexData[0], vertexData[1]); + // Get transformation matrix + // We want a square for our rendering space, so get the maximum dimension of our quad + let maxDimension = Math.max(options.size.x, options.size.y); + const u_BorderWidth = gl.getUniformLocation(program, "u_BorderWidth"); + gl.uniform1f(u_BorderWidth, options.borderWidth / maxDimension); + const u_BorderRadius = gl.getUniformLocation(program, "u_BorderRadius"); + gl.uniform1f(u_BorderRadius, options.borderRadius / maxDimension); + // The size of the rendering space will be a square with this maximum dimension + let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y); + // Center our translations around (0, 0) + const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension; + const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension; + // Create our transformation matrix + this.translation.translate(new Float32Array([translateX, translateY])); + this.scale.scale(size); + this.rotation.rotate(options.rotation); + let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation); + // Pass the translation matrix to our shader + const u_Transform = gl.getUniformLocation(program, "u_Transform"); + gl.uniformMatrix4fv(u_Transform, false, transformation.toArray()); + // Draw the quad + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + } + /** + * The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension + * @param w The width of the quad in pixels + * @param h The height of the quad in pixels + * @returns An array of the vertices of the quad + */ + getVertices(w, h) { + let x, y; + if (h > w) { + y = 0.5; + x = w / (2 * h); + } + else { + x = 0.5; + y = h / (2 * w); + } + return new Float32Array([ + -x, y, + -x, -y, + x, y, + x, -y + ]); + } + getOptions(rect) { + let options = { + position: rect.position, + backgroundColor: rect.calculateBackgroundColor(), + borderColor: rect.calculateBorderColor(), + borderWidth: rect.borderWidth, + borderRadius: rect.borderRadius, + size: rect.size, + rotation: rect.rotation + }; + return options; + } +} +exports.default = LabelShaderType; + +},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],79:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const RenderingUtils_1 = require("../../../Utils/RenderingUtils"); +const ShaderType_1 = require("../ShaderType"); +class PointShaderType extends ShaderType_1.default { + constructor(programKey) { + super(programKey); + } + initBufferObject() { + this.bufferObjectKey = "point"; + this.resourceManager.createBuffer(this.bufferObjectKey); + } + render(gl, options) { + let position = RenderingUtils_1.default.toWebGLCoords(options.position, options.origin, options.worldSize); + let color = RenderingUtils_1.default.toWebGLColor(options.color); + const program = this.resourceManager.getShaderProgram(this.programKey); + const buffer = this.resourceManager.getBuffer(this.bufferObjectKey); + gl.useProgram(program); + const vertexData = position; + const FSIZE = vertexData.BYTES_PER_ELEMENT; + // Bind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); + // Attributes + const a_Position = gl.getAttribLocation(program, "a_Position"); + gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE); + gl.enableVertexAttribArray(a_Position); + // Uniforms + const u_Color = gl.getUniformLocation(program, "u_Color"); + gl.uniform4fv(u_Color, color); + const u_PointSize = gl.getUniformLocation(program, "u_PointSize"); + gl.uniform1f(u_PointSize, options.pointSize); + gl.drawArrays(gl.POINTS, 0, 1); + } + getOptions(point) { + let options = { + position: point.position, + color: point.color, + pointSize: point.size, + }; + return options; + } +} +exports.default = PointShaderType; + +},{"../../../Utils/RenderingUtils":103,"../ShaderType":77}],80:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Mat4x4_1 = require("../../../DataTypes/Mat4x4"); +const ShaderType_1 = require("../ShaderType"); +/** Represents any WebGL objects that have a quad mesh (i.e. a rectangular game object composed of only two triangles) */ +class QuadShaderType extends ShaderType_1.default { + constructor(programKey) { + super(programKey); + this.scale = Mat4x4_1.default.IDENTITY; + this.rotation = Mat4x4_1.default.IDENTITY; + this.translation = Mat4x4_1.default.IDENTITY; + } +} +exports.default = QuadShaderType; + +},{"../../../DataTypes/Mat4x4":11,"../ShaderType":77}],81:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Mat4x4_1 = require("../../../DataTypes/Mat4x4"); +const Vec2_1 = require("../../../DataTypes/Vec2"); +const ResourceManager_1 = require("../../../ResourceManager/ResourceManager"); +const QuadShaderType_1 = require("./QuadShaderType"); +/** */ +class RectShaderType extends QuadShaderType_1.default { + constructor(programKey) { + super(programKey); + this.resourceManager = ResourceManager_1.default.getInstance(); + } + initBufferObject() { + this.bufferObjectKey = "rect"; + this.resourceManager.createBuffer(this.bufferObjectKey); + } + render(gl, options) { + const color = options.color.toWebGL(); + const program = this.resourceManager.getShaderProgram(this.programKey); + const buffer = this.resourceManager.getBuffer(this.bufferObjectKey); + gl.useProgram(program); + const vertexData = this.getVertices(options.size.x, options.size.y); + const FSIZE = vertexData.BYTES_PER_ELEMENT; + // Bind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); + // Attributes + const a_Position = gl.getAttribLocation(program, "a_Position"); + gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 2 * FSIZE, 0 * FSIZE); + gl.enableVertexAttribArray(a_Position); + // Uniforms + const u_Color = gl.getUniformLocation(program, "u_Color"); + gl.uniform4fv(u_Color, color); + // Get transformation matrix + // We want a square for our rendering space, so get the maximum dimension of our quad + let maxDimension = Math.max(options.size.x, options.size.y); + // The size of the rendering space will be a square with this maximum dimension + let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y); + // Center our translations around (0, 0) + const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension; + const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension; + // Create our transformation matrix + this.translation.translate(new Float32Array([translateX, translateY])); + this.scale.scale(size); + this.rotation.rotate(options.rotation); + let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation); + // Pass the translation matrix to our shader + const u_Transform = gl.getUniformLocation(program, "u_Transform"); + gl.uniformMatrix4fv(u_Transform, false, transformation.toArray()); + // Draw the quad + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + } + /* + So as it turns out, WebGL has an issue with non-square quads. + It doesn't like when you don't have a 1-1 scale, and rotations are entirely messed up if this is not the case. + To solve this, I used the scale of the LARGEST dimension of the quad to make a square, then adjusted the vertex coordinates inside of that. + A diagram of the solution follows. + + There is a bounding square for the quad with dimensions hxh (in this case, since height is the largest dimension). + The offset in the vertical direction is therefore 0.5, as it is normally. + However, the offset in the horizontal direction is not so straightforward, but isn't conceptually hard. + All we really have to do is a range change from [0, height/2] to [0, 0.5], where our value is t = width/2, and 0 <= t <= height/2. + + So now we have our rect, in a space scaled with respect to the largest dimension. + Rotations work as you would expect, even for long rectangles. + + 0.5 + __ __ __ __ __ __ __ + | |88888888888| | + | |88888888888| | + | |88888888888| | + -0.5|_ _|88888888888|_ _|0.5 + | |88888888888| | + | |88888888888| | + | |88888888888| | + |___|88888888888|___| + -0.5 + + The getVertices function below does as described, and converts the range + */ + /** + * The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension + * @param w The width of the quad in pixels + * @param h The height of the quad in pixels + * @returns An array of the vertices of the quad + */ + getVertices(w, h) { + let x, y; + if (h > w) { + y = 0.5; + x = w / (2 * h); + } + else { + x = 0.5; + y = h / (2 * w); + } + return new Float32Array([ + -x, y, + -x, -y, + x, y, + x, -y + ]); + } + getOptions(rect) { + let options = { + position: rect.position, + color: rect.color, + size: rect.size, + rotation: rect.rotation + }; + return options; + } +} +exports.default = RectShaderType; + +},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],82:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Mat4x4_1 = require("../../../DataTypes/Mat4x4"); +const Vec2_1 = require("../../../DataTypes/Vec2"); +const AnimatedSprite_1 = require("../../../Nodes/Sprites/AnimatedSprite"); +const ResourceManager_1 = require("../../../ResourceManager/ResourceManager"); +const QuadShaderType_1 = require("./QuadShaderType"); +/** A shader for sprites and animated sprites */ +class SpriteShaderType extends QuadShaderType_1.default { + constructor(programKey) { + super(programKey); + this.resourceManager = ResourceManager_1.default.getInstance(); + } + initBufferObject() { + this.bufferObjectKey = "sprite"; + this.resourceManager.createBuffer(this.bufferObjectKey); + } + render(gl, options) { + const program = this.resourceManager.getShaderProgram(this.programKey); + const buffer = this.resourceManager.getBuffer(this.bufferObjectKey); + const texture = this.resourceManager.getTexture(options.imageKey); + gl.useProgram(program); + const vertexData = this.getVertices(options.size.x, options.size.y, options.scale); + const FSIZE = vertexData.BYTES_PER_ELEMENT; + // Bind the buffer + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW); + // Attributes + const a_Position = gl.getAttribLocation(program, "a_Position"); + gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 4 * FSIZE, 0 * FSIZE); + gl.enableVertexAttribArray(a_Position); + const a_TexCoord = gl.getAttribLocation(program, "a_TexCoord"); + gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, 4 * FSIZE, 2 * FSIZE); + gl.enableVertexAttribArray(a_TexCoord); + // Uniforms + // Get transformation matrix + // We want a square for our rendering space, so get the maximum dimension of our quad + let maxDimension = Math.max(options.size.x, options.size.y); + // The size of the rendering space will be a square with this maximum dimension + let size = new Vec2_1.default(maxDimension, maxDimension).scale(2 / options.worldSize.x, 2 / options.worldSize.y); + // Center our translations around (0, 0) + const translateX = (options.position.x - options.origin.x - options.worldSize.x / 2) / maxDimension; + const translateY = -(options.position.y - options.origin.y - options.worldSize.y / 2) / maxDimension; + // Create our transformation matrix + this.translation.translate(new Float32Array([translateX, translateY])); + this.scale.scale(size); + this.rotation.rotate(options.rotation); + let transformation = Mat4x4_1.default.MULT(this.translation, this.scale, this.rotation); + // Pass the translation matrix to our shader + const u_Transform = gl.getUniformLocation(program, "u_Transform"); + gl.uniformMatrix4fv(u_Transform, false, transformation.toArray()); + // Set up our sampler with our assigned texture unit + const u_Sampler = gl.getUniformLocation(program, "u_Sampler"); + gl.uniform1i(u_Sampler, texture); + // Pass in texShift + const u_texShift = gl.getUniformLocation(program, "u_texShift"); + gl.uniform2fv(u_texShift, options.texShift); + // Pass in texScale + const u_texScale = gl.getUniformLocation(program, "u_texScale"); + gl.uniform2fv(u_texScale, options.texScale); + // Draw the quad + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); + } + /** + * The rendering space always has to be a square, so make sure its square w.r.t to the largest dimension + * @param w The width of the quad in pixels + * @param h The height of the quad in pixels + * @returns An array of the vertices of the quad + */ + getVertices(w, h, scale) { + let x, y; + if (h > w) { + y = 0.5; + x = w / (2 * h); + } + else { + x = 0.5; + y = h / (2 * w); + } + // Scale the rendering space if needed + x *= scale[0]; + y *= scale[1]; + return new Float32Array([ + -x, y, 0.0, 0.0, + -x, -y, 0.0, 1.0, + x, y, 1.0, 0.0, + x, -y, 1.0, 1.0 + ]); + } + getOptions(sprite) { + let texShift; + let texScale; + if (sprite instanceof AnimatedSprite_1.default) { + let animationIndex = sprite.animation.getIndexAndAdvanceAnimation(); + let offset = sprite.getAnimationOffset(animationIndex); + texShift = new Float32Array([offset.x / (sprite.cols * sprite.size.x), offset.y / (sprite.rows * sprite.size.y)]); + texScale = new Float32Array([1 / (sprite.cols), 1 / (sprite.rows)]); + } + else { + texShift = new Float32Array([0, 0]); + texScale = new Float32Array([1, 1]); + } + let options = { + position: sprite.position, + rotation: sprite.rotation, + size: sprite.size, + scale: sprite.scale.toArray(), + imageKey: sprite.imageId, + texShift, + texScale + }; + return options; + } +} +exports.default = SpriteShaderType; + +},{"../../../DataTypes/Mat4x4":11,"../../../DataTypes/Vec2":24,"../../../Nodes/Sprites/AnimatedSprite":47,"../../../ResourceManager/ResourceManager":83,"./QuadShaderType":80}],83:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Map_1 = require("../DataTypes/Map"); +const Queue_1 = require("../DataTypes/Queue"); +const StringUtils_1 = require("../Utils/StringUtils"); +const AudioManager_1 = require("../Sound/AudioManager"); +const WebGLProgramType_1 = require("../DataTypes/Rendering/WebGLProgramType"); +/** + * The resource manager for the game engine. + * The resource manager interfaces with the loadable assets of a game such as images, data files, + * and sounds, which are all found in the dist folder. + * This class controls loading and updates the @reference[Scene] with the loading progress, so that the scene does + * not start before all necessary assets are loaded. + */ +class ResourceManager { + constructor() { + this.loading = false; + this.justLoaded = false; + this.loadonly_imagesLoaded = 0; + this.loadonly_imagesToLoad = 0; + this.loadonly_imageLoadingQueue = new Queue_1.default(); + this.images = new Map_1.default(); + this.loadonly_spritesheetsLoaded = 0; + this.loadonly_spritesheetsToLoad = 0; + this.loadonly_spritesheetLoadingQueue = new Queue_1.default(); + this.spritesheets = new Map_1.default(); + this.loadonly_tilemapsLoaded = 0; + this.loadonly_tilemapsToLoad = 0; + this.loadonly_tilemapLoadingQueue = new Queue_1.default(); + this.tilemaps = new Map_1.default(); + this.loadonly_audioLoaded = 0; + this.loadonly_audioToLoad = 0; + this.loadonly_audioLoadingQueue = new Queue_1.default(); + this.audioBuffers = new Map_1.default(); + this.loadonly_jsonLoaded = 0; + this.loadonly_jsonToLoad = 0; + this.loadonly_jsonLoadingQueue = new Queue_1.default(); + this.jsonObjects = new Map_1.default(); + this.loadonly_gl_ShaderProgramsLoaded = 0; + this.loadonly_gl_ShaderProgramsToLoad = 0; + this.loadonly_gl_ShaderLoadingQueue = new Queue_1.default(); + this.gl_ShaderPrograms = new Map_1.default(); + this.gl_Textures = new Map_1.default(); + this.gl_NextTextureID = 0; + this.gl_Buffers = new Map_1.default(); + this.resourcesToUnload = new Array(); + this.resourcesToKeep = new Array(); + this.loadonly_tilemapObjectToLoad = 0; + this.loadonly_tilemapObjectToLoad = 0; + this.loadonly_tilemapObjectLoadingQueue = new Queue_1.default(); + } + ; + /* ######################################## SINGLETON ########################################*/ + /** + * Returns the current instance of this class or a new instance if none exist + * @returns The resource manager + */ + static getInstance() { + if (!this.instance) { + this.instance = new ResourceManager(); + } + return this.instance; + } + /* ######################################## PUBLIC FUNCTION ########################################*/ + /** + * Activates or deactivates the use of WebGL + * @param flag True if WebGL should be used, false otherwise + * @param gl The instance of the graphics context, if applicable + */ + useWebGL(flag, gl) { + this.gl_WebGLActive = flag; + if (this.gl_WebGLActive) { + this.gl = gl; + } + } + /** + * Loads an image from file + * @param key The key to associate the loaded image with + * @param path The path to the image to load + */ + image(key, path) { + this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path }); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepImage(key) { + this.keepResource(key, ResourceType.IMAGE); + } + /** + * Retrieves a loaded image + * @param key The key of the loaded image + * @returns The image element associated with this key + */ + getImage(key) { + let image = this.images.get(key); + // if (image === undefined) { + // throw `There is no image associated with key "${key}"` + // } + return image; + } + /** + * Loads a spritesheet from file + * @param key The key to associate the loaded spritesheet with + * @param path The path to the spritesheet to load + */ + spritesheet(key, path) { + this.loadonly_spritesheetLoadingQueue.enqueue({ key: key, path: path }); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepSpritesheet(key) { + this.keepResource(key, ResourceType.SPRITESHEET); + } + /** + * Retrieves a loaded spritesheet + * @param key The key of the spritesheet to load + * @returns The loaded Spritesheet + */ + getSpritesheet(key) { + return this.spritesheets.get(key); + } + /** + * Loads an audio file + * @param key The key to associate with the loaded audio file + * @param path The path to the audio file to load + */ + audio(key, path) { + this.loadonly_audioLoadingQueue.enqueue({ key: key, path: path }); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepAudio(key) { + this.keepResource(key, ResourceType.AUDIO); + } + /** + * Retrieves a loaded audio file + * @param key The key of the audio file to load + * @returns The AudioBuffer created from the loaded audio fle + */ + getAudio(key) { + return this.audioBuffers.get(key); + } + /** + * Load a tilemap from a json file. Automatically loads related images + * @param key The key to associate with the loaded tilemap + * @param path The path to the tilemap to load + */ + tilemap(key, path) { + this.loadonly_tilemapLoadingQueue.enqueue({ key: key, path: path }); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepTilemap(key) { + this.keepResource(key, ResourceType.TILEMAP); + } + /** + * Retreives a loaded tilemap + * @param key The key of the loaded tilemap + * @returns The tilemap data associated with the key + */ + getTilemap(key) { + return this.tilemaps.get(key); + } + /** + * Loads an object from a json file. + * @param key The key to associate with the loaded object + * @param path The path to the json file to load + */ + object(key, path) { + this.loadonly_jsonLoadingQueue.enqueue({ key: key, path: path }); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepObject(key) { + this.keepResource(key, ResourceType.JSON); + } + /** + * Retreives a loaded object + * @param key The key of the loaded object + * @returns The object data associated with the key + */ + getObject(key) { + return this.jsonObjects.get(key); + } + /* ######################################## LOAD FUNCTION ########################################*/ + /** + * Loads all resources currently in the queue + * @param callback The function to cal when the resources are finished loading + */ + loadResourcesFromQueue(callback) { + this.loadonly_typesToLoad = 5; + this.loading = true; + // Load everything in the queues. Tilemaps have to come before images because they will add new images to the queue + this.loadTilemapObjectFromQueue(() => { + console.log("Loaded TilemapObjects"); + this.loadTilemapsFromQueue(() => { + console.log("Loaded Tilemaps"); + this.loadSpritesheetsFromQueue(() => { + console.log("Loaded Spritesheets"); + this.loadImagesFromQueue(() => { + console.log("Loaded Images"); + this.loadAudioFromQueue(() => { + console.log("Loaded Audio"); + this.loadObjectsFromQueue(() => { + console.log("Loaded Objects"); + if (this.gl_WebGLActive) { + this.gl_LoadShadersFromQueue(() => { + console.log("Loaded Shaders"); + this.finishLoading(callback); + }); + } + else { + this.finishLoading(callback); + } + }); + }); + }); + }); + }); + }); + } + finishLoading(callback) { + // Done loading + this.loading = false; + this.justLoaded = true; + callback(); + } + /* ######################################## UNLOAD FUNCTION ########################################*/ + keepResource(key, type) { + console.log("Keep resource..."); + for (let i = 0; i < this.resourcesToUnload.length; i++) { + let resource = this.resourcesToUnload[i]; + if (resource.key === key && resource.resourceType === type) { + console.log("Found resource " + key + " of type " + type + ". Keeping."); + let resourceToMove = this.resourcesToUnload.splice(i, 1); + this.resourcesToKeep.push(...resourceToMove); + return; + } + } + } + /** + * Deletes references to all resources in the resource manager + */ + unloadAllResources() { + this.loading = false; + this.justLoaded = false; + for (let resource of this.resourcesToUnload) { + // Unload the resource + this.unloadResource(resource); + } + } + unloadResource(resource) { + // Delete the resource itself + switch (resource.resourceType) { + case ResourceType.IMAGE: + this.images.delete(resource.key); + if (this.gl_WebGLActive) { + this.gl_Textures.delete(resource.key); + } + break; + case ResourceType.TILEMAP: + this.tilemaps.delete(resource.key); + break; + case ResourceType.SPRITESHEET: + this.spritesheets.delete(resource.key); + break; + case ResourceType.AUDIO: + this.audioBuffers.delete(resource.key); + break; + case ResourceType.JSON: + this.jsonObjects.delete(resource.key); + break; + /*case ResourceType.SHADER: + this.gl_ShaderPrograms.get(resource.key).delete(this.gl); + this.gl_ShaderPrograms.delete(resource.key); + break;*/ + } + // Delete any dependencies + for (let dependency of resource.dependencies) { + this.unloadResource(dependency); + } + } + /* ######################################## WORK FUNCTIONS ########################################*/ + /** + * Loads all tilemaps currently in the tilemap loading queue + * @param onFinishLoading The function to call when loading is complete + */ + loadTilemapsFromQueue(onFinishLoading) { + this.loadonly_tilemapsToLoad = this.loadonly_tilemapLoadingQueue.getSize(); + this.loadonly_tilemapsLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_tilemapsToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_tilemapLoadingQueue.hasItems()) { + let tilemap = this.loadonly_tilemapLoadingQueue.dequeue(); + this.loadTilemap(tilemap.key, tilemap.path, onFinishLoading); + } + } + /** + * Loads a singular tilemap + * @param key The key of the tilemap + * @param pathToTilemapJSON The path to the tilemap JSON file + * @param callbackIfLast The function to call if this is the last tilemap to load + */ + loadTilemap(key, pathToTilemapJSON, callbackIfLast) { + this.loadTextFile(pathToTilemapJSON, (fileText) => { + let tilemapObject = JSON.parse(fileText); + // We can parse the object later - it's much faster than loading + this.tilemaps.add(key, tilemapObject); + let resource = new ResourceReference(key, ResourceType.TILEMAP); + // Grab the tileset images we need to load and add them to the imageloading queue + for (let tileset of tilemapObject.tilesets) { + if (tileset.image) { + let key = tileset.image; + let path = StringUtils_1.default.getPathFromFilePath(pathToTilemapJSON) + key; + this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true }); + // Add this image as a dependency to the tilemap + resource.addDependency(new ResourceReference(key, ResourceType.IMAGE)); + } + else if (tileset.tiles) { + for (let tile of tileset.tiles) { + let key = tile.image; + let path = StringUtils_1.default.getPathFromFilePath(pathToTilemapJSON) + key; + this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true }); + // Add this image as a dependency to the tilemap + resource.addDependency(new ResourceReference(key, ResourceType.IMAGE)); + } + } + } + // Add the resource reference to the list of resource to unload + this.resourcesToUnload.push(resource); + // Finish loading + this.finishLoadingTilemap(callbackIfLast); + }); + } + /** + * Finish loading a tilemap. Calls the callback function if this is the last tilemap being loaded + * @param callback The function to call if this is the last tilemap to load + */ + finishLoadingTilemap(callback) { + this.loadonly_tilemapsLoaded += 1; + if (this.loadonly_tilemapsLoaded === this.loadonly_tilemapsToLoad) { + // We're done loading tilemaps + callback(); + } + } + /** + * Loads all spritesheets currently in the spritesheet loading queue + * @param onFinishLoading The function to call when the spritesheets are done loading + */ + loadSpritesheetsFromQueue(onFinishLoading) { + this.loadonly_spritesheetsToLoad = this.loadonly_spritesheetLoadingQueue.getSize(); + this.loadonly_spritesheetsLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_spritesheetsToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_spritesheetLoadingQueue.hasItems()) { + let spritesheet = this.loadonly_spritesheetLoadingQueue.dequeue(); + this.loadSpritesheet(spritesheet.key, spritesheet.path, onFinishLoading); + } + } + /** + * Loads a singular spritesheet + * @param key The key of the spritesheet to load + * @param pathToSpritesheetJSON The path to the spritesheet JSON file + * @param callbackIfLast The function to call if this is the last spritesheet + */ + loadSpritesheet(key, pathToSpritesheetJSON, callbackIfLast) { + this.loadTextFile(pathToSpritesheetJSON, (fileText) => { + let spritesheet = JSON.parse(fileText); + // We can parse the object later - it's much faster than loading + this.spritesheets.add(key, spritesheet); + let resource = new ResourceReference(key, ResourceType.SPRITESHEET); + // Grab the image we need to load and add it to the imageloading queue + let path = StringUtils_1.default.getPathFromFilePath(pathToSpritesheetJSON) + spritesheet.spriteSheetImage; + this.loadonly_imageLoadingQueue.enqueue({ key: spritesheet.name, path: path, isDependency: true }); + resource.addDependency(new ResourceReference(spritesheet.name, ResourceType.IMAGE)); + this.resourcesToUnload.push(resource); + // Finish loading + this.finishLoadingSpritesheet(callbackIfLast); + }); + } + /** + * Finish loading a spritesheet. Calls the callback function if this is the last spritesheet being loaded + * @param callback The function to call if this is the last spritesheet to load + */ + finishLoadingSpritesheet(callback) { + this.loadonly_spritesheetsLoaded += 1; + if (this.loadonly_spritesheetsLoaded === this.loadonly_spritesheetsToLoad) { + // We're done loading spritesheets + callback(); + } + } + /** + * Loads all images currently in the image loading queue + * @param onFinishLoading The function to call when there are no more images to load + */ + loadImagesFromQueue(onFinishLoading) { + this.loadonly_imagesToLoad = this.loadonly_imageLoadingQueue.getSize(); + this.loadonly_imagesLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_imagesToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_imageLoadingQueue.hasItems()) { + let image = this.loadonly_imageLoadingQueue.dequeue(); + this.loadImage(image.key, image.path, image.isDependency, onFinishLoading); + } + } + /** + * Loads a singular image + * @param key The key of the image to load + * @param path The path to the image to load + * @param callbackIfLast The function to call if this is the last image + */ + loadImage(key, path, isDependency, callbackIfLast) { + var image = new Image(); + image.onload = () => { + // Add to loaded images + this.images.add(key, image); + // If not a dependency, push it to the unload list. Otherwise it's managed by something else + if (!isDependency) { + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.IMAGE)); + } + // If WebGL is active, create a texture + if (this.gl_WebGLActive) { + this.createWebGLTexture(key, image); + } + // Finish image load + this.finishLoadingImage(callbackIfLast); + }; + image.src = path; + } + /** + * Finish loading an image. If this is the last image, it calls the callback function + * @param callback The function to call if this is the last image + */ + finishLoadingImage(callback) { + this.loadonly_imagesLoaded += 1; + if (this.loadonly_imagesLoaded === this.loadonly_imagesToLoad) { + // We're done loading images + callback(); + } + } + /** + * Loads all audio currently in the tilemap loading queue + * @param onFinishLoading The function to call when tilemaps are done loading + */ + loadAudioFromQueue(onFinishLoading) { + this.loadonly_audioToLoad = this.loadonly_audioLoadingQueue.getSize(); + this.loadonly_audioLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_audioToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_audioLoadingQueue.hasItems()) { + let audio = this.loadonly_audioLoadingQueue.dequeue(); + this.loadAudio(audio.key, audio.path, onFinishLoading); + } + } + /** + * Load a singular audio file + * @param key The key to the audio file to load + * @param path The path to the audio file to load + * @param callbackIfLast The function to call if this is the last audio file to load + */ + loadAudio(key, path, callbackIfLast) { + let audioCtx = AudioManager_1.default.getInstance().getAudioContext(); + let request = new XMLHttpRequest(); + request.open('GET', path, true); + request.responseType = 'arraybuffer'; + request.onload = () => { + audioCtx.decodeAudioData(request.response, (buffer) => { + // Add to list of audio buffers + this.audioBuffers.add(key, buffer); + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.AUDIO)); + // Finish loading sound + this.finishLoadingAudio(callbackIfLast); + }, (error) => { + throw "Error loading sound"; + }); + }; + request.send(); + } + /** + * Finish loading an audio file. Calls the callback functon if this is the last audio sample being loaded. + * @param callback The function to call if this is the last audio file to load + */ + finishLoadingAudio(callback) { + this.loadonly_audioLoaded += 1; + if (this.loadonly_audioLoaded === this.loadonly_audioToLoad) { + // We're done loading audio + callback(); + } + } + /** + * Loads all objects currently in the object loading queue + * @param onFinishLoading The function to call when there are no more objects to load + */ + loadObjectsFromQueue(onFinishLoading) { + this.loadonly_jsonToLoad = this.loadonly_jsonLoadingQueue.getSize(); + this.loadonly_jsonLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_jsonToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_jsonLoadingQueue.hasItems()) { + let obj = this.loadonly_jsonLoadingQueue.dequeue(); + this.loadObject(obj.key, obj.path, onFinishLoading); + } + } + /** + * Loads a singular object + * @param key The key of the object to load + * @param path The path to the object to load + * @param callbackIfLast The function to call if this is the last object + */ + loadObject(key, path, callbackIfLast) { + this.loadTextFile(path, (fileText) => { + let obj = JSON.parse(fileText); + this.jsonObjects.add(key, obj); + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.JSON)); + this.finishLoadingObject(callbackIfLast); + }); + } + /** + * Finish loading an object. If this is the last object, it calls the callback function + * @param callback The function to call if this is the last object + */ + finishLoadingObject(callback) { + this.loadonly_jsonLoaded += 1; + if (this.loadonly_jsonLoaded === this.loadonly_jsonToLoad) { + // We're done loading objects + callback(); + } + } + /* ########## WEBGL SPECIFIC FUNCTIONS ########## */ + getTexture(key) { + return this.gl_Textures.get(key); + } + getShaderProgram(key) { + return this.gl_ShaderPrograms.get(key).program; + } + getBuffer(key) { + return this.gl_Buffers.get(key); + } + createWebGLTexture(imageKey, image) { + // Get the texture ID + const textureID = this.getTextureID(this.gl_NextTextureID); + // Create the texture + const texture = this.gl.createTexture(); + // Set up the texture + // Enable texture0 + this.gl.activeTexture(textureID); + // Bind our texture to texture 0 + this.gl.bindTexture(this.gl.TEXTURE_2D, texture); + // Set the texture parameters + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); + // Set the texture image + this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image); + // Add the texture to our map with the same key as the image + this.gl_Textures.add(imageKey, this.gl_NextTextureID); + // Increment the key + this.gl_NextTextureID += 1; + } + getTextureID(id) { + // Start with 9 cases - this can be expanded if needed, but for the best performance, + // Textures should be stitched into an atlas + switch (id) { + case 0: return this.gl.TEXTURE0; + case 1: return this.gl.TEXTURE1; + case 2: return this.gl.TEXTURE2; + case 3: return this.gl.TEXTURE3; + case 4: return this.gl.TEXTURE4; + case 5: return this.gl.TEXTURE5; + case 6: return this.gl.TEXTURE6; + case 7: return this.gl.TEXTURE7; + case 8: return this.gl.TEXTURE8; + default: return this.gl.TEXTURE9; + } + } + createBuffer(key) { + if (this.gl_WebGLActive) { + let buffer = this.gl.createBuffer(); + this.gl_Buffers.add(key, buffer); + } + } + /** + * Enqueues loading of a new shader program + * @param key The key of the shader program + * @param vShaderFilepath + * @param fShaderFilepath + */ + shader(key, vShaderFilepath, fShaderFilepath) { + let splitPath = vShaderFilepath.split("."); + let end = splitPath[splitPath.length - 1]; + if (end !== "vshader") { + throw `${vShaderFilepath} is not a valid vertex shader - must end in ".vshader`; + } + splitPath = fShaderFilepath.split("."); + end = splitPath[splitPath.length - 1]; + if (end !== "fshader") { + throw `${fShaderFilepath} is not a valid vertex shader - must end in ".fshader`; + } + let paths = new KeyPath_Shader(); + paths.key = key; + paths.vpath = vShaderFilepath; + paths.fpath = fShaderFilepath; + this.loadonly_gl_ShaderLoadingQueue.enqueue(paths); + } + /** + * Tells the resource manager to keep this resource + * @param key The key of the resource + */ + keepShader(key) { + this.keepResource(key, ResourceType.IMAGE); + } + gl_LoadShadersFromQueue(onFinishLoading) { + this.loadonly_gl_ShaderProgramsToLoad = this.loadonly_gl_ShaderLoadingQueue.getSize(); + this.loadonly_gl_ShaderProgramsLoaded = 0; + // If webGL isn'active or there are no items to load, we're finished + if (!this.gl_WebGLActive || this.loadonly_gl_ShaderProgramsToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_gl_ShaderLoadingQueue.hasItems()) { + let shader = this.loadonly_gl_ShaderLoadingQueue.dequeue(); + this.gl_LoadShader(shader.key, shader.vpath, shader.fpath, onFinishLoading); + } + } + gl_LoadShader(key, vpath, fpath, callbackIfLast) { + this.loadTextFile(vpath, (vFileText) => { + const vShader = vFileText; + this.loadTextFile(fpath, (fFileText) => { + const fShader = fFileText; + // Extract the program and shaders + const [shaderProgram, vertexShader, fragmentShader] = this.createShaderProgram(vShader, fShader); + // Create a wrapper type + const programWrapper = new WebGLProgramType_1.default(); + programWrapper.program = shaderProgram; + programWrapper.vertexShader = vertexShader; + programWrapper.fragmentShader = fragmentShader; + // Add to our map + this.gl_ShaderPrograms.add(key, programWrapper); + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.SHADER)); + // Finish loading + this.gl_FinishLoadingShader(callbackIfLast); + }); + }); + } + gl_FinishLoadingShader(callback) { + this.loadonly_gl_ShaderProgramsLoaded += 1; + if (this.loadonly_gl_ShaderProgramsLoaded === this.loadonly_gl_ShaderProgramsToLoad) { + // We're done loading shaders + callback(); + } + } + createShaderProgram(vShaderSource, fShaderSource) { + const vertexShader = this.loadVertexShader(vShaderSource); + const fragmentShader = this.loadFragmentShader(fShaderSource); + if (vertexShader === null || fragmentShader === null) { + // We had a problem intializing - error + return null; + } + // Create a shader program + const program = this.gl.createProgram(); + if (!program) { + // Error creating + console.warn("Failed to create program"); + return null; + } + // Attach our vertex and fragment shader + this.gl.attachShader(program, vertexShader); + this.gl.attachShader(program, fragmentShader); + // Link + this.gl.linkProgram(program); + if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) { + // Error linking + const error = this.gl.getProgramInfoLog(program); + console.warn("Failed to link program: " + error); + // Clean up + this.gl.deleteProgram(program); + this.gl.deleteShader(vertexShader); + this.gl.deleteShader(fragmentShader); + return null; + } + // We successfully create a program + return [program, vertexShader, fragmentShader]; + } + loadVertexShader(shaderSource) { + // Create a new vertex shader + return this.loadShader(this.gl.VERTEX_SHADER, shaderSource); + } + loadFragmentShader(shaderSource) { + // Create a new fragment shader + return this.loadShader(this.gl.FRAGMENT_SHADER, shaderSource); + } + loadShader(type, shaderSource) { + const shader = this.gl.createShader(type); + // If we couldn't create the shader, error + if (shader === null) { + console.warn("Unable to create shader"); + return null; + } + // Add the source to the shader and compile + this.gl.shaderSource(shader, shaderSource); + this.gl.compileShader(shader); + // Make sure there were no errors during this process + if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) { + // Not compiled - error + const error = this.gl.getShaderInfoLog(shader); + console.warn("Failed to compile shader: " + error); + // Clean up + this.gl.deleteShader(shader); + return null; + } + // Sucess, so return the shader + return shader; + } + /* ########## GENERAL LOADING FUNCTIONS ########## */ + loadTextFile(textFilePath, callback) { + let xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', textFilePath, true); + xobj.onreadystatechange = function () { + if ((xobj.readyState == 4) && (xobj.status == 200)) { + callback(xobj.responseText); + } + }; + xobj.send(null); + } + /* ########## LOADING BAR INFO ########## */ + getLoadPercent() { + return (this.loadonly_tilemapsLoaded / this.loadonly_tilemapsToLoad + + this.loadonly_spritesheetsLoaded / this.loadonly_spritesheetsToLoad + + this.loadonly_imagesLoaded / this.loadonly_imagesToLoad + + this.loadonly_audioLoaded / this.loadonly_audioToLoad) + / this.loadonly_typesToLoad; + } + // Customized funtions below + // These funtions are NOT well tested!!! + // Only used for shattered sword specific purpose!!! + // Use them carefully!!! + tilemapFromObject(key, tilemap) { + this.loadonly_tilemapObjectLoadingQueue.enqueue({ key: key, map: tilemap }); + } + loadTilemapObjectFromQueue(onFinishLoading) { + this.loadonly_tilemapObjectToLoad = this.loadonly_tilemapObjectLoadingQueue.getSize(); + this.loadonly_tilemapObjectLoaded = 0; + // If no items to load, we're finished + if (this.loadonly_tilemapObjectToLoad === 0) { + onFinishLoading(); + return; + } + while (this.loadonly_tilemapObjectLoadingQueue.hasItems()) { + let map = this.loadonly_tilemapObjectLoadingQueue.dequeue(); + this.loadTilemapFromObject(map.key, map.map, onFinishLoading); + } + } + loadTilemapFromObject(key, tiledMap, callbackIfLast) { + // We can parse the object later - it's much faster than loading + this.tilemaps.add(key, tiledMap); + let resource = new ResourceReference(key, ResourceType.TILEMAP); + // Grab the tileset images we need to load and add them to the imageloading queue + for (let tileset of tiledMap.tilesets) { + if (tileset.image) { + let key = tileset.image; + let path = key; + this.loadonly_imageLoadingQueue.enqueue({ key: key, path: path, isDependency: true }); + // Add this image as a dependency to the tilemap + resource.addDependency(new ResourceReference(key, ResourceType.IMAGE)); + } + } + // Add the resource reference to the list of resource to unload + this.resourcesToUnload.push(resource); + this.finishLoadingTilemapObject(callbackIfLast); + } + finishLoadingTilemapObject(callback) { + this.loadonly_tilemapObjectLoaded += 1; + if (this.loadonly_tilemapObjectLoaded === this.loadonly_tilemapObjectToLoad) { + // We're done loading tilemaps + callback(); + } + } + singleImage(key, path, callbackIfLast) { + var image = new Image(); + image.onload = () => { + // Add to loaded images + this.images.add(key, image); + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.IMAGE)); + // If WebGL is active, create a texture + if (this.gl_WebGLActive) { + this.createWebGLTexture(key, image); + } + // Finish image load + this.finishLoadingSingleObject(callbackIfLast); + }; + image.src = path; + } + singleAudio(key, path, callbackIfLast) { + let audioCtx = AudioManager_1.default.getInstance().getAudioContext(); + let request = new XMLHttpRequest(); + request.open('GET', path, true); + request.responseType = 'arraybuffer'; + request.onload = () => { + audioCtx.decodeAudioData(request.response, (buffer) => { + // Add to list of audio buffers + this.audioBuffers.add(key, buffer); + this.resourcesToUnload.push(new ResourceReference(key, ResourceType.AUDIO)); + // Finish loading sound + this.finishLoadingSingleObject(callbackIfLast); + }, (error) => { + throw "Error loading sound"; + }); + }; + request.send(); + } + finishLoadingSingleObject(callback) { + callback(); + } + update(deltaT) { + if (this.loading) { + if (this.onLoadProgress) { + this.onLoadProgress(this.getLoadPercent()); + } + } + else if (this.justLoaded) { + this.justLoaded = false; + if (this.onLoadComplete) { + this.onLoadComplete(); + } + } + } +} +exports.default = ResourceManager; +/** + * A class representing a reference to a resource. + * This is used for the exemption list to assure assets and their dependencies don't get + * destroyed if they are still needed. + */ +class ResourceReference { + constructor(key, resourceType) { + this.key = key; + this.resourceType = resourceType; + this.dependencies = new Array(); + } + addDependency(resource) { + this.dependencies.push(resource); + } +} +var ResourceType; +(function (ResourceType) { + ResourceType["IMAGE"] = "IMAGE"; + ResourceType["TILEMAP"] = "TILEMAP"; + ResourceType["SPRITESHEET"] = "SPRITESHEET"; + ResourceType["AUDIO"] = "AUDIO"; + ResourceType["JSON"] = "JSON"; + ResourceType["SHADER"] = "SHADER"; +})(ResourceType || (ResourceType = {})); +/** + * A pair representing a key and the path of the resource to load + */ +class KeyPathPair { + constructor() { + this.isDependency = false; + } +} +class KeyMapPair { +} +class KeyPath_Shader { +} + +},{"../DataTypes/Map":10,"../DataTypes/Queue":14,"../DataTypes/Rendering/WebGLProgramType":15,"../Sound/AudioManager":96,"../Utils/StringUtils":104}],84:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Sprite_1 = require("../../Nodes/Sprites/Sprite"); +const AnimatedSprite_1 = require("../../Nodes/Sprites/AnimatedSprite"); +const GraphicTypes_1 = require("../../Nodes/Graphics/GraphicTypes"); +const UIElementTypes_1 = require("../../Nodes/UIElements/UIElementTypes"); +const Point_1 = require("../../Nodes/Graphics/Point"); +const Vec2_1 = require("../../DataTypes/Vec2"); +const Button_1 = require("../../Nodes/UIElements/Button"); +const Label_1 = require("../../Nodes/UIElements/Label"); +const Slider_1 = require("../../Nodes/UIElements/Slider"); +const TextInput_1 = require("../../Nodes/UIElements/TextInput"); +const Rect_1 = require("../../Nodes/Graphics/Rect"); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const Line_1 = require("../../Nodes/Graphics/Line"); +const Particle_1 = require("../../Nodes/Graphics/Particle"); +// @ignorePage +/** + * A factory that abstracts adding @reference[CanvasNode]s to the @reference[Scene]. + * Access methods in this factory through Scene.add.[methodName](). + */ +class CanvasNodeFactory { + constructor() { + /** + * Adds an instance of a UIElement to the current scene - i.e. any class that extends UIElement + * @param type The type of UIElement to add + * @param layerName The layer to add the UIElement to + * @param options Any additional arguments to feed to the constructor + * @returns A new UIElement + */ + this.addUIElement = (type, layerName, options) => { + // Get the layer + let layer = this.scene.getLayer(layerName); + let instance; + switch (type) { + case UIElementTypes_1.UIElementType.BUTTON: + instance = this.buildButton(options); + break; + case UIElementTypes_1.UIElementType.LABEL: + instance = this.buildLabel(options); + break; + case UIElementTypes_1.UIElementType.SLIDER: + instance = this.buildSlider(options); + break; + case UIElementTypes_1.UIElementType.TEXT_INPUT: + instance = this.buildTextInput(options); + break; + default: + throw `UIElementType '${type}' does not exist, or is registered incorrectly.`; + } + instance.setScene(this.scene); + instance.id = this.scene.generateId(); + this.scene.getSceneGraph().addNode(instance); + // Add instance to layer + layer.addNode(instance); + return instance; + }; + /** + * Adds a sprite to the current scene + * @param key The key of the image the sprite will represent + * @param layerName The layer on which to add the sprite + * @returns A new Sprite + */ + this.addSprite = (key, layerName) => { + let layer = this.scene.getLayer(layerName); + let instance = new Sprite_1.default(key); + // Add instance to scene + instance.setScene(this.scene); + instance.id = this.scene.generateId(); + if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) { + this.scene.getSceneGraph().addNode(instance); + } + // Add instance to layer + layer.addNode(instance); + return instance; + }; + /** + * Adds an AnimatedSprite to the current scene + * @param key The key of the image the sprite will represent + * @param layerName The layer on which to add the sprite + * @returns A new AnimatedSprite + */ + this.addAnimatedSprite = (key, layerName) => { + let layer = this.scene.getLayer(layerName); + let spritesheet = this.resourceManager.getSpritesheet(key); + let instance = new AnimatedSprite_1.default(spritesheet); + // Add instance fo scene + instance.setScene(this.scene); + instance.id = this.scene.generateId(); + if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) { + this.scene.getSceneGraph().addNode(instance); + } + // Add instance to layer + layer.addNode(instance); + return instance; + }; + /** + * Adds a new graphic element to the current Scene + * @param type The type of graphic to add + * @param layerName The layer on which to add the graphic + * @param options Any additional arguments to send to the graphic constructor + * @returns A new Graphic + */ + this.addGraphic = (type, layerName, options) => { + // Get the layer + let layer = this.scene.getLayer(layerName); + let instance; + switch (type) { + case GraphicTypes_1.GraphicType.POINT: + instance = this.buildPoint(options); + break; + case GraphicTypes_1.GraphicType.LINE: + instance = this.buildLine(options); + break; + case GraphicTypes_1.GraphicType.RECT: + instance = this.buildRect(options); + break; + case GraphicTypes_1.GraphicType.PARTICLE: + instance = this.buildParticle(options); + break; + default: + throw `GraphicType '${type}' does not exist, or is registered incorrectly.`; + } + // Add instance to scene + instance.setScene(this.scene); + instance.id = this.scene.generateId(); + if (!(this.scene.isParallaxLayer(layerName) || this.scene.isUILayer(layerName))) { + this.scene.getSceneGraph().addNode(instance); + } + // Add instance to layer + layer.addNode(instance); + return instance; + }; + } + init(scene) { + this.scene = scene; + this.resourceManager = ResourceManager_1.default.getInstance(); + } + /* ---------- BUILDERS ---------- */ + buildButton(options) { + this.checkIfPropExists("Button", options, "position", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Button", options, "text", "string"); + return new Button_1.default(options.position, options.text); + } + buildLabel(options) { + this.checkIfPropExists("Label", options, "position", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Label", options, "text", "string"); + return new Label_1.default(options.position, options.text); + } + buildSlider(options) { + this.checkIfPropExists("Slider", options, "position", Vec2_1.default, "Vec2"); + let initValue = 0; + if (options.value !== undefined) { + initValue = options.value; + } + return new Slider_1.default(options.position, initValue); + } + buildTextInput(options) { + this.checkIfPropExists("TextInput", options, "position", Vec2_1.default, "Vec2"); + return new TextInput_1.default(options.position); + } + buildPoint(options) { + this.checkIfPropExists("Point", options, "position", Vec2_1.default, "Vec2"); + return new Point_1.default(options.position); + } + buildParticle(options) { + this.checkIfPropExists("Particle", options, "position", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Particle", options, "size", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Particle", options, "mass", "number", "number"); + //Changed for testing + return new Particle_1.default(options.position, options.size, options.mass); + } + buildLine(options) { + this.checkIfPropExists("Line", options, "start", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Line", options, "end", Vec2_1.default, "Vec2"); + return new Line_1.default(options.start, options.end); + } + buildRect(options) { + this.checkIfPropExists("Rect", options, "position", Vec2_1.default, "Vec2"); + this.checkIfPropExists("Rect", options, "size", Vec2_1.default, "Vec2"); + return new Rect_1.default(options.position, options.size); + } + /* ---------- ERROR HANDLING ---------- */ + checkIfPropExists(objectName, options, prop, type, typeName) { + if (!options || options[prop] === undefined) { + // Check that the options object has the property + throw `${objectName} object requires argument ${prop} of type ${typeName}, but none was provided.`; + } + else { + // Check that the property has the correct type + if ((typeof type) === "string") { + if (!(typeof options[prop] === type)) { + throw `${objectName} object requires argument ${prop} of type ${type}, but provided ${prop} was not of type ${type}.`; + } + } + else if (type instanceof Function) { + // If type is a constructor, check against that + if (!(options[prop] instanceof type)) { + throw `${objectName} object requires argument ${prop} of type ${typeName}, but provided ${prop} was not of type ${typeName}.`; + } + } + else { + throw `${objectName} object requires argument ${prop} of type ${typeName}, but provided ${prop} was not of type ${typeName}.`; + } + } + } +} +exports.default = CanvasNodeFactory; + +},{"../../DataTypes/Vec2":24,"../../Nodes/Graphics/GraphicTypes":42,"../../Nodes/Graphics/Line":43,"../../Nodes/Graphics/Particle":44,"../../Nodes/Graphics/Point":45,"../../Nodes/Graphics/Rect":46,"../../Nodes/Sprites/AnimatedSprite":47,"../../Nodes/Sprites/Sprite":48,"../../Nodes/UIElements/Button":52,"../../Nodes/UIElements/Label":53,"../../Nodes/UIElements/Slider":54,"../../Nodes/UIElements/TextInput":55,"../../Nodes/UIElements/UIElementTypes":56,"../../ResourceManager/ResourceManager":83}],85:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const CanvasNodeFactory_1 = require("./CanvasNodeFactory"); +const TilemapFactory_1 = require("./TilemapFactory"); +/** + * The manager of all factories used for adding @reference[GameNode]s to the @reference[Scene]. + */ +class FactoryManager { + constructor(scene, tilemaps) { + // Constructors are called here to allow assignment of their functions to functions in this class + this.canvasNodeFactory = new CanvasNodeFactory_1.default(); + this.tilemapFactory = new TilemapFactory_1.default(); + this.canvasNodeFactory.init(scene); + this.tilemapFactory.init(scene, tilemaps); + } + // Expose all of the factories through the factory manager + /** + * Adds an instance of a UIElement to the current scene - i.e. any class that extends UIElement + * @param type The type of UIElement to add + * @param layerName The layer to add the UIElement to + * @param options Any additional arguments to feed to the constructor + * @returns A new UIElement + */ + uiElement(type, layerName, options) { + return this.canvasNodeFactory.addUIElement(type, layerName, options); + } + /** + * Adds a sprite to the current scene + * @param key The key of the image the sprite will represent + * @param layerName The layer on which to add the sprite + * @returns A new Sprite + */ + sprite(key, layerName) { + return this.canvasNodeFactory.addSprite(key, layerName); + } + /** + * Adds an AnimatedSprite to the current scene + * @param key The key of the image the sprite will represent + * @param layerName The layer on which to add the sprite + * @returns A new AnimatedSprite + */ + animatedSprite(key, layerName) { + return this.canvasNodeFactory.addAnimatedSprite(key, layerName); + } + /** + * Adds a new graphic element to the current Scene + * @param type The type of graphic to add + * @param layerName The layer on which to add the graphic + * @param options Any additional arguments to send to the graphic constructor + * @returns A new Graphic + */ + graphic(type, layerName, options) { + return this.canvasNodeFactory.addGraphic(type, layerName, options); + } + /** + * Adds a tilemap to the scene + * @param key The key of the loaded tilemap to load + * @param constr The constructor of the desired tilemap + * @param args Additional arguments to send to the tilemap constructor + * @returns An array of Layers, each of which contains a layer of the tilemap as its own Tilemap instance. + */ + tilemap(key, scale) { + return this.tilemapFactory.add(key, scale); + } +} +exports.default = FactoryManager; + +},{"./CanvasNodeFactory":84,"./TilemapFactory":86}],86:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../../ResourceManager/ResourceManager"); +const OrthogonalTilemap_1 = require("../../Nodes/Tilemaps/OrthogonalTilemap"); +const Tileset_1 = require("../../DataTypes/Tilesets/Tileset"); +const Vec2_1 = require("../../DataTypes/Vec2"); +const PositionGraph_1 = require("../../DataTypes/Graphs/PositionGraph"); +const Navmesh_1 = require("../../Pathfinding/Navmesh"); +// @ignorePage +/** + * A factory that abstracts adding @reference[Tilemap]s to the @reference[Scene]. + * Access methods in this factory through Scene.add.[methodName](). + */ +class TilemapFactory { + constructor() { + // TODO - This is specifically catered to Tiled tilemaps right now. In the future, + // it would be good to have a "parseTilemap" function that would convert the tilemap + // data into a standard format. This could allow for support from other programs + // or the development of an internal level builder tool + /** + * Adds a tilemap to the scene + * @param key The key of the loaded tilemap to load + * @param constr The constructor of the desired tilemap + * @param args Additional arguments to send to the tilemap constructor + * @returns An array of Layers, each of which contains a layer of the tilemap as its own Tilemap instance. + */ + this.add = (key, scale = new Vec2_1.default(1, 1)) => { + // Get Tilemap Data + let tilemapData = this.resourceManager.getTilemap(key); + // Set the constructor for this tilemap to either be orthographic or isometric + let constr; + if (tilemapData.orientation === "orthographic") { + constr = OrthogonalTilemap_1.default; + } + else { + // No isometric tilemap support right now, so Orthographic tilemap + constr = OrthogonalTilemap_1.default; + } + // Initialize the return value array + let sceneLayers = new Array(); + // Create all of the tilesets for this tilemap + let tilesets = new Array(); + let collectionTiles = new Array(); + for (let tileset of tilemapData.tilesets) { + if (tileset.image) { + // If this is a standard tileset and not a collection, create a tileset for it. + // TODO - We are ignoring collection tilesets for now. This is likely not a great idea in practice, + // as theoretically someone could want to use one for a standard tilemap. We are assuming for now + // that we only want to use them for object layers + tilesets.push(new Tileset_1.default(tileset)); + } + else { + tileset.tiles.forEach(tile => tile.id += tileset.firstgid); + collectionTiles.push(...tileset.tiles); + } + } + // Loop over the layers of the tilemap and create tiledlayers or object layers + for (let layer of tilemapData.layers) { + let sceneLayer; + let isParallaxLayer = false; + let depth = 0; + if (layer.properties) { + for (let prop of layer.properties) { + if (prop.name === "Parallax") { + isParallaxLayer = prop.value; + } + else if (prop.name === "Depth") { + depth = prop.value; + } + } + } + if (isParallaxLayer) { + sceneLayer = this.scene.addParallaxLayer(layer.name, new Vec2_1.default(1, 1), depth); + } + else { + sceneLayer = this.scene.addLayer(layer.name, depth); + } + if (layer.type === "tilelayer") { + // Create a new tilemap object for the layer + let tilemap = new constr(tilemapData, layer, tilesets, scale); + tilemap.id = this.scene.generateId(); + tilemap.setScene(this.scene); + // Add tilemap to scene + this.tilemaps.push(tilemap); + sceneLayer.addNode(tilemap); + // Register tilemap with physics if it's collidable + if (tilemap.isCollidable) { + tilemap.addPhysics(); + if (layer.properties) { + for (let item of layer.properties) { + if (item.name === "Group") { + tilemap.setGroup(item.value); + } + } + } + } + } + else { + let isNavmeshPoints = false; + let navmeshName; + let edges; + if (layer.properties) { + for (let prop of layer.properties) { + if (prop.name === "NavmeshPoints") { + isNavmeshPoints = true; + } + else if (prop.name === "name") { + navmeshName = prop.value; + } + else if (prop.name === "edges") { + edges = prop.value; + } + } + } + if (isNavmeshPoints) { + let g = new PositionGraph_1.default(); + for (let obj of layer.objects) { + g.addPositionedNode(new Vec2_1.default(obj.x, obj.y)); + } + for (let edge of edges) { + g.addEdge(edge.from, edge.to); + } + this.scene.getNavigationManager().addNavigableEntity(navmeshName, new Navmesh_1.default(g)); + continue; + } + // Layer is an object layer, so add each object as a sprite to a new layer + for (let obj of layer.objects) { + // Check if obj is collidable + let hasPhysics = false; + let isCollidable = false; + let isTrigger = false; + let onEnter = null; + let onExit = null; + let triggerGroup = null; + let group = ""; + if (obj.properties) { + for (let prop of obj.properties) { + if (prop.name === "HasPhysics") { + hasPhysics = prop.value; + } + else if (prop.name === "Collidable") { + isCollidable = prop.value; + } + else if (prop.name === "Group") { + group = prop.value; + } + else if (prop.name === "IsTrigger") { + isTrigger = prop.value; + } + else if (prop.name === "TriggerGroup") { + triggerGroup = prop.value; + } + else if (prop.name === "TriggerOnEnter") { + onEnter = prop.value; + } + else if (prop.name === "TriggerOnExit") { + onExit = prop.value; + } + } + } + let sprite; + // Check if obj is a tile from a tileset + for (let tileset of tilesets) { + if (tileset.hasTile(obj.gid)) { + // The object is a tile from this set + let imageKey = tileset.getImageKey(); + let offset = tileset.getImageOffsetForTile(obj.gid); + sprite = this.scene.add.sprite(imageKey, layer.name); + let size = tileset.getTileSize().clone(); + sprite.position.set((obj.x + size.x / 2) * scale.x, (obj.y - size.y / 2) * scale.y); + sprite.setImageOffset(offset); + sprite.size.copy(size); + sprite.scale.set(scale.x, scale.y); + } + } + // Not in a tileset, must correspond to a collection + if (!sprite) { + for (let tile of collectionTiles) { + if (obj.gid === tile.id) { + let imageKey = tile.image; + sprite = this.scene.add.sprite(imageKey, layer.name); + sprite.position.set((obj.x + tile.imagewidth / 2) * scale.x, (obj.y - tile.imageheight / 2) * scale.y); + sprite.scale.set(scale.x, scale.y); + } + } + } + // Now we have sprite. Associate it with our physics object if there is one + if (hasPhysics) { + // Make the sprite a static physics object + sprite.addPhysics(sprite.boundary.clone(), Vec2_1.default.ZERO, isCollidable, true); + sprite.setGroup(group); + if (isTrigger && triggerGroup !== null) { + sprite.setTrigger(triggerGroup, onEnter, onExit); + } + } + } + } + // Update the return value + sceneLayers.push(sceneLayer); + } + return sceneLayers; + }; + } + init(scene, tilemaps) { + this.scene = scene; + this.tilemaps = tilemaps; + this.resourceManager = ResourceManager_1.default.getInstance(); + } +} +exports.default = TilemapFactory; + +},{"../../DataTypes/Graphs/PositionGraph":8,"../../DataTypes/Tilesets/Tileset":23,"../../DataTypes/Vec2":24,"../../Nodes/Tilemaps/OrthogonalTilemap":50,"../../Pathfinding/Navmesh":59,"../../ResourceManager/ResourceManager":83}],87:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("../Utils/MathUtils"); +/** + * A layer in the scene. Layers are used for sorting @reference[GameNode]s by depth. + */ +class Layer { + /** + * Creates a new layer. To do this in a game, use the addLayer() method in @refrence[Scene] + * @param scene The scene to add the layer to + * @param name The name of the layer + */ + constructor(scene, name) { + this.scene = scene; + this.name = name; + this.paused = false; + this.hidden = false; + this.alpha = 1; + this.items = new Array(); + this.ySort = false; + this.depth = 0; + } + /** + * Retreives the name of the layer + * @returns The name of the layer + */ + getName() { + return this.name; + } + /** + * Pauses/Unpauses the layer. Affects all elements in this layer + * @param pauseValue True if the layer should be paused, false if not + */ + setPaused(pauseValue) { + this.paused = pauseValue; + } + /** + * Returns whether or not the layer is paused + */ + isPaused() { + return this.paused; + } + /** + * Sets the opacity of the layer + * @param alpha The new opacity value in the range [0, 1] + */ + setAlpha(alpha) { + this.alpha = MathUtils_1.default.clamp(alpha, 0, 1); + } + /** + * Gets the opacity of the layer + * @returns The opacity + */ + getAlpha() { + return this.alpha; + } + /** + * Sets the layer's hidden value. If hidden, a layer will not be rendered, but will still update + * @param hidden The hidden value of the layer + */ + setHidden(hidden) { + this.hidden = hidden; + } + /** + * Returns the hideen value of the lyaer + * @returns True if the scene is hidden, false otherwise + */ + isHidden() { + return this.hidden; + } + /** Pauses this scene and hides it */ + disable() { + this.paused = true; + this.hidden = true; + } + /** Unpauses this layer and makes it visible */ + enable() { + this.paused = false; + this.hidden = false; + } + /** + * Sets whether or not the scene will ySort automatically. + * ySorting means that CanvasNodes on this layer will have their depth sorted depending on their y-value. + * This means that if an object is "higher" in the scene, it will sort behind objects that are "lower". + * This is useful for 3/4 view games, or similar situations, where you sometimes want to be in front of objects, + * and other times want to be behind the same objects. + * @param ySort True if ySorting should be active, false if not + */ + setYSort(ySort) { + this.ySort = ySort; + } + /** + * Gets the ySort status of the scene + * @returns True if ySorting is occurring, false otherwise + */ + getYSort() { + return this.ySort; + } + /** + * Sets the depth of the layer compared to other layers. A larger number means the layer will be closer to the screen. + * @param depth The depth of the layer. + */ + setDepth(depth) { + this.depth = depth; + } + /** + * Retrieves the depth of the layer. + * @returns The depth + */ + getDepth() { + return this.depth; + } + /** + * Adds a node to this layer + * @param node The node to add to this layer. + */ + addNode(node) { + this.items.push(node); + node.setLayer(this); + } + /** + * Removes a node from this layer + * @param node The node to remove + * @returns true if the node was removed, false otherwise + */ + removeNode(node) { + // Find and remove the node + let index = this.items.indexOf(node); + if (index !== -1) { + this.items.splice(index, 1); + node.setLayer(undefined); + } + } + /** + * Retreives all GameNodes from this layer + * @returns an Array that contains all of the GameNodes in this layer. + */ + getItems() { + return this.items; + } +} +exports.default = Layer; + +},{"../Utils/MathUtils":102}],88:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Layer_1 = require("../Layer"); +/** + * An extension of a Layer that has a parallax value. + */ +class ParallaxLayer extends Layer_1.default { + /** + * Creates a new ParallaxLayer. + * Use addParallaxLayer() in @reference[Scene] to add a layer of this type to your game. + * @param scene The Scene to add this ParallaxLayer to + * @param name The name of the ParallaxLayer + * @param parallax The parallax level + */ + constructor(scene, name, parallax) { + super(scene, name); + this.parallax = parallax; + } +} +exports.default = ParallaxLayer; + +},{"../Layer":87}],89:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../DataTypes/Vec2"); +const ParallaxLayer_1 = require("./ParallaxLayer"); +/** + * A Layer strictly to be used for managing UIElements. + * This is intended to be a Layer that always stays in the same place, + * and thus renders things like a HUD or an inventory without taking into consideration the \reference[Viewport] scroll. + */ +class UILayer extends ParallaxLayer_1.default { + /** + * Creates a new UILayer. + * Use addUILayer() in @reference[Scene] to add a layer of this type to your game. + * @param scene The Scene to add this UILayer to + * @param name The name of the UILayer + */ + constructor(scene, name) { + super(scene, name, Vec2_1.default.ZERO); + } +} +exports.default = UILayer; + +},{"../../DataTypes/Vec2":24,"./ParallaxLayer":88}],90:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Layer_1 = require("./Layer"); +const Vec2_1 = require("../DataTypes/Vec2"); +const BasicPhysicsManager_1 = require("../Physics/BasicPhysicsManager"); +const SceneGraphArray_1 = require("../SceneGraph/SceneGraphArray"); +const FactoryManager_1 = require("./Factories/FactoryManager"); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +const Receiver_1 = require("../Events/Receiver"); +const Emitter_1 = require("../Events/Emitter"); +const NavigationManager_1 = require("../Pathfinding/NavigationManager"); +const AIManager_1 = require("../AI/AIManager"); +const Map_1 = require("../DataTypes/Map"); +const ParallaxLayer_1 = require("./Layers/ParallaxLayer"); +const UILayer_1 = require("./Layers/UILayer"); +const CanvasNode_1 = require("../Nodes/CanvasNode"); +const SceneOptions_1 = require("./SceneOptions"); +const Debug_1 = require("../Debug/Debug"); +const TimerManager_1 = require("../Timing/TimerManager"); +const TweenManager_1 = require("../Rendering/Animations/TweenManager"); +const ParticleSystemManager_1 = require("../Rendering/Animations/ParticleSystemManager"); +/** + * Scenes are the main container in the game engine. + * Your main scene is the current level or menu of the game, and will contain all of the GameNodes needed. + * Scenes provide an easy way to load assets, add assets to the game world, and unload assets, + * and have lifecycle methods exposed for these functions. + */ +class Scene { + /** + * Creates a new Scene. To add a new Scene in your game, use changeToScene() in @reference[SceneManager] + * @param viewport The viewport of the game + * @param sceneManager The SceneManager that owns this Scene + * @param renderingManager The RenderingManager that will handle this Scene's rendering + * @param game The instance of the Game + * @param options The options for Scene initialization + */ + constructor(viewport, sceneManager, renderingManager, options) { + this.sceneOptions = SceneOptions_1.default.parse(options === undefined ? {} : options); + this.worldSize = new Vec2_1.default(500, 500); + this.viewport = viewport; + this.viewport.setBounds(0, 0, 2560, 1280); + this.running = false; + this.sceneManager = sceneManager; + this.receiver = new Receiver_1.default(); + this.emitter = new Emitter_1.default(); + this.tilemaps = new Array(); + this.sceneGraph = new SceneGraphArray_1.default(this.viewport, this); + this.layers = new Map_1.default(); + this.uiLayers = new Map_1.default(); + this.parallaxLayers = new Map_1.default(); + this.physicsManager = new BasicPhysicsManager_1.default(this.sceneOptions.physics); + this.navManager = new NavigationManager_1.default(); + this.aiManager = new AIManager_1.default(); + this.renderingManager = renderingManager; + this.add = new FactoryManager_1.default(this, this.tilemaps); + this.load = ResourceManager_1.default.getInstance(); + this.resourceManager = this.load; + // Get the timer manager and clear any existing timers + TimerManager_1.default.getInstance().clearTimers(); + } + /** A lifecycle method that gets called immediately after a new scene is created, before anything else. */ + initScene(init) { } + /** A lifecycle method that gets called when a new scene is created. Load all files you wish to access in the scene here. */ + loadScene() { } + /** A lifecycle method called strictly after loadScene(). Create any game objects you wish to use in the scene here. */ + startScene() { } + /** + * A lifecycle method called every frame of the game. This is where you can dynamically do things like add in new enemies + * @param delta The time this frame represents + */ + updateScene(deltaT) { } + /** A lifecycle method that gets called on scene destruction. Specify which files you no longer need for garbage collection. */ + unloadScene() { } + update(deltaT) { + this.updateScene(deltaT); + // Do time updates + TimerManager_1.default.getInstance().update(deltaT); + // Do all AI updates + this.aiManager.update(deltaT); + // Update all physics objects + this.physicsManager.update(deltaT); + // Update all canvas objects + this.sceneGraph.update(deltaT); + // Update all tilemaps + this.tilemaps.forEach(tilemap => { + if (!tilemap.getLayer().isPaused()) { + tilemap.update(deltaT); + } + }); + // Update all tweens + TweenManager_1.default.getInstance().update(deltaT); + // Update all particle systems + ParticleSystemManager_1.default.getInstance().update(deltaT); + // Update viewport + this.viewport.update(deltaT); + } + /** + * Collects renderable sets and coordinates with the RenderingManager to draw the Scene + */ + render() { + // Get the visible set of nodes + let visibleSet = this.sceneGraph.getVisibleSet(); + // Add parallax layer items to the visible set (we're rendering them all for now) + this.parallaxLayers.forEach(key => { + let pLayer = this.parallaxLayers.get(key); + for (let node of pLayer.getItems()) { + if (node instanceof CanvasNode_1.default) { + visibleSet.push(node); + } + } + }); + // Send the visible set, tilemaps, and uiLayers to the renderer + this.renderingManager.render(visibleSet, this.tilemaps, this.uiLayers); + let nodes = this.sceneGraph.getAllNodes(); + this.tilemaps.forEach(tilemap => tilemap.visible ? nodes.push(tilemap) : 0); + Debug_1.default.setNodes(nodes); + } + /** + * Sets the scene as running or not + * @param running True if the Scene should be running, false if not + */ + setRunning(running) { + this.running = running; + } + /** + * Returns whether or not the Scene is running + * @returns True if the scene is running, false otherwise + */ + isRunning() { + return this.running; + } + /** + * Removes a node from this Scene + * @param node The node to remove + */ + remove(node) { + // Remove from the scene graph + if (node instanceof CanvasNode_1.default) { + this.sceneGraph.removeNode(node); + } + } + /** Destroys this scene and all nodes in it */ + destroy() { + for (let node of this.sceneGraph.getAllNodes()) { + node.destroy(); + } + for (let tilemap of this.tilemaps) { + tilemap.destroy(); + } + this.receiver.destroy(); + delete this.sceneGraph; + delete this.physicsManager; + delete this.navManager; + delete this.aiManager; + delete this.receiver; + } + /** + * Adds a new layer to the scene and returns it + * @param name The name of the new layer + * @param depth The depth of the layer + * @returns The newly created Layer + */ + addLayer(name, depth) { + if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) { + throw `Layer with name ${name} already exists`; + } + let layer = new Layer_1.default(this, name); + this.layers.add(name, layer); + if (depth) { + layer.setDepth(depth); + } + return layer; + } + /** + * Adds a new parallax layer to this scene and returns it + * @param name The name of the parallax layer + * @param parallax The parallax level + * @param depth The depth of the layer + * @returns The newly created ParallaxLayer + */ + addParallaxLayer(name, parallax, depth) { + if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) { + throw `Layer with name ${name} already exists`; + } + let layer = new ParallaxLayer_1.default(this, name, parallax); + this.parallaxLayers.add(name, layer); + if (depth) { + layer.setDepth(depth); + } + return layer; + } + /** + * Adds a new UILayer to the scene + * @param name The name of the new UIlayer + * @returns The newly created UILayer + */ + addUILayer(name) { + if (this.layers.has(name) || this.parallaxLayers.has(name) || this.uiLayers.has(name)) { + throw `Layer with name ${name} already exists`; + } + let layer = new UILayer_1.default(this, name); + this.uiLayers.add(name, layer); + return layer; + } + /** + * Gets a layer from the scene by name if it exists. + * This can be a Layer or any of its subclasses + * @param name The name of the layer + * @returns The Layer found with that name + */ + getLayer(name) { + if (this.layers.has(name)) { + return this.layers.get(name); + } + else if (this.parallaxLayers.has(name)) { + return this.parallaxLayers.get(name); + } + else if (this.uiLayers.has(name)) { + return this.uiLayers.get(name); + } + else { + throw `Requested layer ${name} does not exist.`; + } + } + /** + * Returns true if this layer is a ParallaxLayer + * @param name The name of the layer + * @returns True if this layer is a ParallaxLayer + */ + isParallaxLayer(name) { + return this.parallaxLayers.has(name); + } + /** + * Returns true if this layer is a UILayer + * @param name The name of the layer + * @returns True if this layer is ParallaxLayer + */ + isUILayer(name) { + return this.uiLayers.has(name); + } + /** + * Returns the translation of this node with respect to camera space (due to the viewport moving). + * This value is affected by the parallax level of the @reference[Layer] the node is on. + * @param node The node to check the viewport with respect to + * @returns A Vec2 containing the translation of viewport with respect to this node. + */ + getViewTranslation(node) { + let layer = node.getLayer(); + if (layer instanceof ParallaxLayer_1.default || layer instanceof UILayer_1.default) { + return this.viewport.getOrigin().mult(layer.parallax); + } + else { + return this.viewport.getOrigin(); + } + } + /** + * Returns the scale level of the view + * @returns The zoom level of the viewport + */ + getViewScale() { + return this.viewport.getZoomLevel(); + } + /** + * Returns the Viewport associated with this scene + * @returns The current Viewport + */ + getViewport() { + return this.viewport; + } + /** + * Gets the world size of this Scene + * @returns The world size in a Vec2 + */ + getWorldSize() { + return this.worldSize; + } + /** + * Gets the SceneGraph associated with this Scene + * @returns The SceneGraph + */ + getSceneGraph() { + return this.sceneGraph; + } + /** + * Gets the PhysicsManager associated with this Scene + * @returns The PhysicsManager + */ + getPhysicsManager() { + return this.physicsManager; + } + /** + * Gets the NavigationManager associated with this Scene + * @returns The NavigationManager + */ + getNavigationManager() { + return this.navManager; + } + /** + * Gets the AIManager associated with this Scene + * @returns The AIManager + */ + getAIManager() { + return this.aiManager; + } + /** + * Generates an ID for a GameNode + * @returns The new ID + */ + generateId() { + return this.sceneManager.generateId(); + } + /** + * Retrieves a Tilemap in this Scene + * @param name The name of the Tilemap + * @returns The Tilemap, if one this name exists, otherwise null + */ + getTilemap(name) { + for (let tilemap of this.tilemaps) { + if (tilemap.name === name) { + return tilemap; + } + } + return null; + } +} +exports.default = Scene; + +},{"../AI/AIManager":3,"../DataTypes/Map":10,"../DataTypes/Vec2":24,"../Debug/Debug":25,"../Events/Emitter":27,"../Events/Receiver":31,"../Nodes/CanvasNode":39,"../Pathfinding/NavigationManager":57,"../Physics/BasicPhysicsManager":60,"../Rendering/Animations/ParticleSystemManager":68,"../Rendering/Animations/TweenManager":70,"../ResourceManager/ResourceManager":83,"../SceneGraph/SceneGraphArray":94,"../Timing/TimerManager":98,"./Factories/FactoryManager":85,"./Layer":87,"./Layers/ParallaxLayer":88,"./Layers/UILayer":89,"./SceneOptions":92}],91:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +/** + * The SceneManager acts as an interface to create Scenes, and handles the lifecycle methods of Scenes. + * It gives Scenes access to information they need from the @reference[Game] class while keeping a layer of separation. + */ +class SceneManager { + /** + * Creates a new SceneManager + * @param viewport The Viewport of the game + * @param game The Game instance + * @param renderingManager The RenderingManager of the game + */ + constructor(viewport, renderingManager) { + this.resourceManager = ResourceManager_1.default.getInstance(); + this.viewport = viewport; + this.renderingManager = renderingManager; + this.idCounter = 0; + this.pendingScene = null; + } + /** + * Add a scene as the main scene. + * Use this method if you've created a subclass of Scene, and you want to add it as the main Scene. + * @param constr The constructor of the scene to add + * @param init An object to pass to the init function of the new scene + */ + changeToScene(constr, init, options) { + console.log("Creating the new scene - change is pending until next update"); + this.pendingScene = new constr(this.viewport, this, this.renderingManager, options); + this.pendingSceneInit = init; + } + doSceneChange() { + console.log("Performing scene change"); + this.viewport.setCenter(this.viewport.getHalfSize().x, this.viewport.getHalfSize().y); + if (this.currentScene) { + console.log("Unloading old scene"); + this.currentScene.unloadScene(); + console.log("Destroying old scene"); + this.currentScene.destroy(); + } + console.log("Unloading old resources..."); + this.resourceManager.unloadAllResources(); + // Make the pending scene the current one + this.currentScene = this.pendingScene; + // Make the pending scene null + this.pendingScene = null; + // Init the scene + this.currentScene.initScene(this.pendingSceneInit); + // Enqueue all scene asset loads + this.currentScene.loadScene(); + // Load all assets + console.log("Starting Scene Load"); + this.resourceManager.loadResourcesFromQueue(() => { + console.log("Starting Scene"); + this.currentScene.startScene(); + this.currentScene.setRunning(true); + }); + this.renderingManager.setScene(this.currentScene); + } + /** + * Generates a unique ID + * @returns A new ID + */ + generateId() { + return this.idCounter++; + } + /** + * Renders the current Scene + */ + render() { + if (this.currentScene) { + this.currentScene.render(); + } + } + /** + * Updates the current Scene + * @param deltaT The timestep of the Scene + */ + update(deltaT) { + if (this.pendingScene !== null) { + this.doSceneChange(); + } + if (this.currentScene && this.currentScene.isRunning()) { + this.currentScene.update(deltaT); + } + } +} +exports.default = SceneManager; + +},{"../ResourceManager/ResourceManager":83}],92:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// @ignorePage +/** + * The options to give a @reference[Scene] for initialization + */ +class SceneOptions { + static parse(options) { + let sOpt = new SceneOptions(); + if (options.physics === undefined) { + sOpt.physics = { groups: undefined, collisions: undefined }; + } + else { + sOpt.physics = options.physics; + } + return sOpt; + } +} +exports.default = SceneOptions; + +},{}],93:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../DataTypes/Vec2"); +/** + * An abstract interface of a SceneGraph. + * Exposes methods for use by other code, but leaves the implementation up to the subclasses. + * The SceneGraph manages the positions of all GameNodes, and can easily prune a visible set for rendering. + */ +class SceneGraph { + /** + * Creates a new SceneGraph + * @param viewport The viewport + * @param scene The Scene this SceneGraph belongs to + */ + constructor(viewport, scene) { + this.viewport = viewport; + this.scene = scene; + this.nodeMap = new Array(); + this.idCounter = 0; + } + /** + * Add a node to the SceneGraph + * @param node The CanvasNode to add to the SceneGraph + * @returns The SceneGraph ID of this newly added CanvasNode + */ + addNode(node) { + this.nodeMap[node.id] = node; + this.addNodeSpecific(node, this.idCounter); + this.idCounter += 1; + return this.idCounter - 1; + } + ; + /** + * Removes a node from the SceneGraph + * @param node The node to remove + */ + removeNode(node) { + // Find and remove node in O(n) + this.nodeMap[node.id] = undefined; + this.removeNodeSpecific(node, node.id); + } + ; + /** + * Get a specific node using its id + * @param id The id of the CanvasNode to retrieve + * @returns The node with this ID + */ + getNode(id) { + return this.nodeMap[id]; + } + /** + * Returns the nodes at specific coordinates + * @param vecOrX The x-coordinate of the position, or the coordinates in a Vec2 + * @param y The y-coordinate of the position + * @returns An array of nodes found at the position provided + */ + getNodesAt(vecOrX, y = null) { + if (vecOrX instanceof Vec2_1.default) { + return this.getNodesAtCoords(vecOrX.x, vecOrX.y); + } + else { + return this.getNodesAtCoords(vecOrX, y); + } + } + /** + * Returns all nodes in the SceneGraph + * @returns An Array containing all nodes in the SceneGraph + */ + getAllNodes() { + let arr = new Array(); + for (let i = 0; i < this.nodeMap.length; i++) { + if (this.nodeMap[i] !== undefined) { + arr.push(this.nodeMap[i]); + } + } + return arr; + } +} +exports.default = SceneGraph; + +},{"../DataTypes/Vec2":24}],94:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const SceneGraph_1 = require("./SceneGraph"); +const Stats_1 = require("../Debug/Stats"); +/** + * An implementation of a SceneGraph that simply stored CanvasNodes in an array. + */ +class SceneGraphArray extends SceneGraph_1.default { + /** + * Creates a new SceneGraphArray + * @param viewport The Viewport + * @param scene The Scene this SceneGraph belongs to + */ + constructor(viewport, scene) { + super(viewport, scene); + this.nodeList = new Array(); + } + // @override + addNodeSpecific(node, id) { + this.nodeList.push(node); + } + // @override + removeNodeSpecific(node, id) { + let index = this.nodeList.indexOf(node); + if (index > -1) { + this.nodeList.splice(index, 1); + } + } + // @override + getNodesAtCoords(x, y) { + let results = []; + for (let node of this.nodeList) { + if (node.contains(x, y)) { + results.push(node); + } + } + return results; + } + // @override + getNodesInRegion(boundary) { + let t0 = performance.now(); + let results = []; + for (let node of this.nodeList) { + if (boundary.overlaps(node.boundary)) { + results.push(node); + } + } + let t1 = performance.now(); + Stats_1.default.log("sgquery", (t1 - t0)); + return results; + } + update(deltaT) { + let t0 = performance.now(); + for (let node of this.nodeList) { + if (!node.getLayer().isPaused()) { + node.update(deltaT); + } + } + let t1 = performance.now(); + Stats_1.default.log("sgupdate", (t1 - t0)); + } + render(ctx) { } + // @override + getVisibleSet() { + let visibleSet = new Array(); + for (let node of this.nodeList) { + if (!node.getLayer().isHidden() && node.visible && this.viewport.includes(node)) { + visibleSet.push(node); + } + } + return visibleSet; + } +} +exports.default = SceneGraphArray; + +},{"../Debug/Stats":26,"./SceneGraph":93}],95:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../DataTypes/Vec2"); +const MathUtils_1 = require("../Utils/MathUtils"); +const Queue_1 = require("../DataTypes/Queue"); +const AABB_1 = require("../DataTypes/Shapes/AABB"); +const Input_1 = require("../Input/Input"); +const ParallaxLayer_1 = require("../Scene/Layers/ParallaxLayer"); +const UILayer_1 = require("../Scene/Layers/UILayer"); +/** + * The viewport of the game. Corresponds to the visible window displayed in the browser. + * The viewport keeps track of its position in the game world, and can act as a camera to follow objects. + */ +class Viewport { + constructor(canvasSize, zoomLevel) { + /** The amount that is zoomed in or out. */ + this.ZOOM_FACTOR = 1.2; + this.view = new AABB_1.default(Vec2_1.default.ZERO, Vec2_1.default.ZERO); + this.boundary = new AABB_1.default(Vec2_1.default.ZERO, Vec2_1.default.ZERO); + this.lastPositions = new Queue_1.default(); + this.smoothingFactor = 10; + this.scrollZoomEnabled = false; + this.canvasSize = Vec2_1.default.ZERO; + this.focus = Vec2_1.default.ZERO; + // Set the size of the canvas + this.setCanvasSize(canvasSize); + // Set the size of the viewport + this.setSize(canvasSize); + this.setZoomLevel(zoomLevel); + // Set the center (and make the viewport stay there) + this.setCenter(this.view.halfSize.clone()); + this.setFocus(this.view.halfSize.clone()); + } + /** Enables the viewport to zoom in and out */ + enableZoom() { + this.scrollZoomEnabled = true; + } + /** + * Returns the position of the viewport + * @returns The center of the viewport as a Vec2 + */ + getCenter() { + return this.view.center; + } + /** + * Returns a new Vec2 with the origin of the viewport + * @returns The top left cornder of the Vieport as a Vec2 + */ + getOrigin() { + return new Vec2_1.default(this.view.left, this.view.top); + } + /** + * Returns the region visible to this viewport + * @returns The AABB containing the region visible to the viewport + */ + getView() { + return this.view; + } + /** + * Set the position of the viewport + * @param vecOrX The new position or the x-coordinate of the new position + * @param y The y-coordinate of the new position + */ + setCenter(vecOrX, y = null) { + let pos; + if (vecOrX instanceof Vec2_1.default) { + pos = vecOrX; + } + else { + pos = new Vec2_1.default(vecOrX, y); + } + this.view.center = pos; + } + /** + * Returns the size of the viewport as a Vec2 + * @returns The half-size of the viewport as a Vec2 + */ + getHalfSize() { + return this.view.getHalfSize(); + } + /** + * Sets the size of the viewport + * @param vecOrX The new width of the viewport or the new size as a Vec2 + * @param y The new height of the viewport + */ + setSize(vecOrX, y = null) { + if (vecOrX instanceof Vec2_1.default) { + this.view.setHalfSize(vecOrX.scaled(1 / 2)); + } + else { + this.view.setHalfSize(new Vec2_1.default(vecOrX / 2, y / 2)); + } + } + /** + * Sets the half-size of the viewport + * @param vecOrX The new half-width of the viewport or the new half-size as a Vec2 + * @param y The new height of the viewport + */ + setHalfSize(vecOrX, y = null) { + if (vecOrX instanceof Vec2_1.default) { + this.view.setHalfSize(vecOrX.clone()); + } + else { + this.view.setHalfSize(new Vec2_1.default(vecOrX, y)); + } + } + /** + * Updates the viewport with the size of the current Canvas + * @param vecOrX The width of the canvas, or the canvas size as a Vec2 + * @param y The height of the canvas + */ + setCanvasSize(vecOrX, y = null) { + if (vecOrX instanceof Vec2_1.default) { + this.canvasSize = vecOrX.clone(); + } + else { + this.canvasSize = new Vec2_1.default(vecOrX, y); + } + } + /** + * Sets the zoom level of the viewport + * @param zoom The zoom level + */ + setZoomLevel(zoom) { + this.view.halfSize.copy(this.canvasSize.scaled(1 / zoom / 2)); + } + /** + * Gets the zoom level of the viewport + * @returns The zoom level + */ + getZoomLevel() { + return this.canvasSize.x / this.view.hw / 2; + } + /** + * Sets the smoothing factor for the viewport movement. + * @param smoothingFactor The smoothing factor for the viewport + */ + setSmoothingFactor(smoothingFactor) { + if (smoothingFactor < 1) + smoothingFactor = 1; + this.smoothingFactor = smoothingFactor; + } + /** + * Tells the viewport to focus on a point. Overidden by "following". + * @param focus The point the viewport should focus on + */ + setFocus(focus) { + this.focus.copy(focus); + } + /** + * Returns true if the CanvasNode is inside of the viewport + * @param node The node to check + * @returns True if the node is currently visible in the viewport, false if not + */ + includes(node) { + let parallax = node.getLayer() instanceof ParallaxLayer_1.default || node.getLayer() instanceof UILayer_1.default ? node.getLayer().parallax : new Vec2_1.default(1, 1); + let center = this.view.center.clone(); + this.view.center.mult(parallax); + let overlaps = this.view.overlaps(node.boundary); + this.view.center = center; + return overlaps; + } + // TODO: Put some error handling on this for trying to make the bounds too small for the viewport + // TODO: This should probably be done automatically, or should consider the aspect ratio or something + /** + * Sets the bounds of the viewport + * @param lowerX The left edge of the viewport + * @param lowerY The top edge of the viewport + * @param upperX The right edge of the viewport + * @param upperY The bottom edge of the viewport + */ + setBounds(lowerX, lowerY, upperX, upperY) { + let hwidth = (upperX - lowerX) / 2; + let hheight = (upperY - lowerY) / 2; + let x = lowerX + hwidth; + let y = lowerY + hheight; + this.boundary.center.set(x, y); + this.boundary.halfSize.set(hwidth, hheight); + } + /** + * Make the viewport follow the specified GameNode + * @param node The GameNode to follow + */ + follow(node) { + this.following = node; + } + updateView() { + if (this.lastPositions.getSize() > this.smoothingFactor) { + this.lastPositions.dequeue(); + } + // Get the average of the last 10 positions + let pos = Vec2_1.default.ZERO; + this.lastPositions.forEach(position => pos.add(position)); + pos.scale(1 / this.lastPositions.getSize()); + // Set this position either to the object or to its bounds + pos.x = MathUtils_1.default.clamp(pos.x, this.boundary.left + this.view.hw, this.boundary.right - this.view.hw); + pos.y = MathUtils_1.default.clamp(pos.y, this.boundary.top + this.view.hh, this.boundary.bottom - this.view.hh); + // Assure there are no lines in the tilemap + pos.x = Math.floor(pos.x); + pos.y = Math.floor(pos.y); + this.view.center.copy(pos); + } + update(deltaT) { + // If zoom is enabled + if (this.scrollZoomEnabled) { + if (Input_1.default.didJustScroll()) { + let currentSize = this.view.getHalfSize().clone(); + if (Input_1.default.getScrollDirection() < 0) { + // Zoom in + currentSize.scale(1 / this.ZOOM_FACTOR); + } + else { + // Zoom out + currentSize.scale(this.ZOOM_FACTOR); + } + if (currentSize.x > this.boundary.hw) { + let factor = this.boundary.hw / currentSize.x; + currentSize.x = this.boundary.hw; + currentSize.y *= factor; + } + if (currentSize.y > this.boundary.hh) { + let factor = this.boundary.hh / currentSize.y; + currentSize.y = this.boundary.hh; + currentSize.x *= factor; + } + this.view.setHalfSize(currentSize); + } + } + // If viewport is following an object + if (this.following) { + // Update our list of previous positions + this.lastPositions.enqueue(this.following.position.clone()); + } + else { + this.lastPositions.enqueue(this.focus); + } + this.updateView(); + } +} +exports.default = Viewport; + +},{"../DataTypes/Queue":14,"../DataTypes/Shapes/AABB":16,"../DataTypes/Vec2":24,"../Input/Input":32,"../Scene/Layers/ParallaxLayer":88,"../Scene/Layers/UILayer":89,"../Utils/MathUtils":102}],96:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MAX_AUDIO_CHANNELS = exports.AudioChannelType = void 0; +const Map_1 = require("../DataTypes/Map"); +const Receiver_1 = require("../Events/Receiver"); +const ResourceManager_1 = require("../ResourceManager/ResourceManager"); +const GameEventType_1 = require("../Events/GameEventType"); +/** + * Manages any sounds or music needed for the game. + * Through the EventQueue, exposes interface to play sounds so GameNodes can activate sounds without + * needing direct references to the audio system + */ +class AudioManager { + constructor() { + this.initAudio(); + this.receiver = new Receiver_1.default(); + this.receiver.subscribe([ + GameEventType_1.GameEventType.PLAY_SOUND, + GameEventType_1.GameEventType.STOP_SOUND, + GameEventType_1.GameEventType.PLAY_MUSIC, + GameEventType_1.GameEventType.PLAY_SFX, + GameEventType_1.GameEventType.MUTE_CHANNEL, + GameEventType_1.GameEventType.UNMUTE_CHANNEL + ]); + this.currentSounds = new Map_1.default(); + this.gainNodes = new Array(exports.MAX_AUDIO_CHANNELS); + this.initGainNodes(); + } + /** + * Get the instance of the AudioManager class or create a new one if none exists + * @returns The AudioManager + */ + static getInstance() { + if (!this.instance) { + this.instance = new AudioManager(); + } + return this.instance; + } + /** + * Initializes the webAudio context + */ + initAudio() { + try { + window.AudioContext = window.AudioContext; // || window.webkitAudioContext; + this.audioCtx = new AudioContext(); + console.log('Web Audio API successfully loaded'); + } + catch (e) { + console.warn('Web Audio API is not supported in this browser'); + } + } + initGainNodes() { + for (let i = 0; i < exports.MAX_AUDIO_CHANNELS; i++) { + this.gainNodes[i] = this.audioCtx.createGain(); + } + } + /** + * Returns the current audio context + * @returns The AudioContext + */ + getAudioContext() { + return this.audioCtx; + } + /* + According to the MDN, create a new sound for every call: + + An AudioBufferSourceNode can only be played once; after each call to start(), you have to create a new node + if you want to play the same sound again. Fortunately, these nodes are very inexpensive to create, and the + actual AudioBuffers can be reused for multiple plays of the sound. Indeed, you can use these nodes in a + "fire and forget" manner: create the node, call start() to begin playing the sound, and don't even bother to + hold a reference to it. It will automatically be garbage-collected at an appropriate time, which won't be + until sometime after the sound has finished playing. + */ + /** + * Creates a new sound from the key of a loaded audio file + * @param key The key of the loaded audio file to create a new sound for + * @returns The newly created AudioBuffer + */ + createSound(key, holdReference, channel, options) { + // Get audio buffer + let buffer = ResourceManager_1.default.getInstance().getAudio(key); + // Create a sound source + var source = this.audioCtx.createBufferSource(); + // Tell the source which sound to play + source.buffer = buffer; + // Add any additional nodes + const nodes = [source]; + // Do any additional nodes here? + // Of course, there aren't any supported yet... + // Add the gain node for this channel + nodes.push(this.gainNodes[channel]); + // Connect any nodes along the path + for (let i = 1; i < nodes.length; i++) { + nodes[i - 1].connect(nodes[i]); + } + // Connect the source to the context's destination + nodes[nodes.length - 1].connect(this.audioCtx.destination); + return source; + } + /** + * Play the sound specified by the key + * @param key The key of the sound to play + * @param loop A boolean for whether or not to loop the sound + * @param holdReference A boolean for whether or not we want to hold on to a reference of the audio node. This is good for playing music on a loop that will eventually need to be stopped. + */ + playSound(key, loop, holdReference, channel, options) { + let sound = this.createSound(key, holdReference, channel, options); + if (loop) { + sound.loop = true; + } + // Add a reference of the new sound to a map. This will allow us to stop a looping or long sound at a later time + if (holdReference) { + this.currentSounds.add(key, sound); + } + sound.start(); + } + /** + * Stop the sound specified by the key + */ + stopSound(key) { + let sound = this.currentSounds.get(key); + if (sound) { + sound.stop(); + this.currentSounds.delete(key); + } + } + muteChannel(channel) { + this.gainNodes[channel].gain.setValueAtTime(0, this.audioCtx.currentTime); + } + unmuteChannel(channel) { + this.gainNodes[channel].gain.setValueAtTime(1, this.audioCtx.currentTime); + } + /** + * Sets the volume of a channel using the GainNode for that channel. For more + * information on GainNodes, see https://developer.mozilla.org/en-US/docs/Web/API/GainNode + * @param channel The audio channel to set the volume for + * @param volume The volume of the channel. 0 is muted. Values below zero will be set to zero. + */ + static setVolume(channel, volume) { + if (volume < 0) { + volume = 0; + } + const am = AudioManager.getInstance(); + am.gainNodes[channel].gain.setValueAtTime(volume, am.audioCtx.currentTime); + } + /** + * Returns the GainNode for this channel. + * Learn more about GainNodes here https://developer.mozilla.org/en-US/docs/Web/API/GainNode + * DON'T USE THIS UNLESS YOU KNOW WHAT YOU'RE DOING + * @param channel The channel + * @returns The GainNode for the specified channel + */ + getChannelGainNode(channel) { + return this.gainNodes[channel]; + } + update(deltaT) { + // Play each audio clip requested + // TODO - Add logic to merge sounds if there are multiple of the same key + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + if (event.type === GameEventType_1.GameEventType.PLAY_SOUND || event.type === GameEventType_1.GameEventType.PLAY_MUSIC || event.type === GameEventType_1.GameEventType.PLAY_SFX) { + let soundKey = event.data.get("key"); + let loop = event.data.get("loop"); + let holdReference = event.data.get("holdReference"); + let channel = AudioChannelType.DEFAULT; + if (event.type === GameEventType_1.GameEventType.PLAY_MUSIC) { + channel = AudioChannelType.MUSIC; + } + else if (GameEventType_1.GameEventType.PLAY_SFX) { + channel = AudioChannelType.SFX; + } + else if (event.data.has("channel")) { + channel = event.data.get("channel"); + } + this.playSound(soundKey, loop, holdReference, channel, event.data); + } + if (event.type === GameEventType_1.GameEventType.STOP_SOUND) { + let soundKey = event.data.get("key"); + this.stopSound(soundKey); + } + if (event.type === GameEventType_1.GameEventType.MUTE_CHANNEL) { + this.muteChannel(event.data.get("channel")); + } + if (event.type === GameEventType_1.GameEventType.UNMUTE_CHANNEL) { + this.unmuteChannel(event.data.get("channel")); + } + } + } +} +exports.default = AudioManager; +var AudioChannelType; +(function (AudioChannelType) { + AudioChannelType[AudioChannelType["DEFAULT"] = 0] = "DEFAULT"; + AudioChannelType[AudioChannelType["SFX"] = 1] = "SFX"; + AudioChannelType[AudioChannelType["MUSIC"] = 2] = "MUSIC"; + AudioChannelType[AudioChannelType["CUSTOM_1"] = 3] = "CUSTOM_1"; + AudioChannelType[AudioChannelType["CUSTOM_2"] = 4] = "CUSTOM_2"; + AudioChannelType[AudioChannelType["CUSTOM_3"] = 5] = "CUSTOM_3"; + AudioChannelType[AudioChannelType["CUSTOM_4"] = 6] = "CUSTOM_4"; + AudioChannelType[AudioChannelType["CUSTOM_5"] = 7] = "CUSTOM_5"; + AudioChannelType[AudioChannelType["CUSTOM_6"] = 8] = "CUSTOM_6"; + AudioChannelType[AudioChannelType["CUSTOM_7"] = 9] = "CUSTOM_7"; + AudioChannelType[AudioChannelType["CUSTOM_8"] = 10] = "CUSTOM_8"; + AudioChannelType[AudioChannelType["CUSTOM_9"] = 11] = "CUSTOM_9"; +})(AudioChannelType = exports.AudioChannelType || (exports.AudioChannelType = {})); +exports.MAX_AUDIO_CHANNELS = 12; + +},{"../DataTypes/Map":10,"../Events/GameEventType":30,"../Events/Receiver":31,"../ResourceManager/ResourceManager":83}],97:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TimerState = void 0; +const sword_enums_1 = require("../../shattered_sword/sword_enums"); +const InputWrapper_1 = require("../../shattered_sword/Tools/InputWrapper"); +const MathUtils_1 = require("../Utils/MathUtils"); +const TimerManager_1 = require("./TimerManager"); +/** */ +class Timer { + constructor(time, onEnd, loop = false) { + // Register this timer + TimerManager_1.default.getInstance().addTimer(this); + this.totalTime = time; + this.timeLeft = 0; + this.onEnd = onEnd; + this.loop = loop; + this.state = TimerState.STOPPED; + this.numRuns = 0; + } + isStopped() { + return this.state === TimerState.STOPPED; + } + isPaused() { + return this.state === TimerState.PAUSED; + } + /** + * Returns whether or not this timer has been run before + * @returns true if it has been run at least once (after the latest reset), and false otherwise + */ + hasRun() { + return this.numRuns > 0; + } + start(time) { + if (time !== undefined) { + this.totalTime = time; + } + this.state = TimerState.ACTIVE; + this.timeLeft = this.totalTime; + } + /** Resets this timer. Sets the progress back to zero, and sets the number of runs back to zero */ + reset() { + this.timeLeft = this.totalTime; + this.numRuns = 0; + } + pause() { + this.state = TimerState.PAUSED; + } + update(deltaT) { + if (this.state === TimerState.ACTIVE && InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) { + this.timeLeft -= deltaT * 1000; + if (this.timeLeft <= 0) { + this.timeLeft = MathUtils_1.default.clampLow0(this.timeLeft); + this.end(); + } + } + } + end() { + // Update the state + this.state = TimerState.STOPPED; + this.numRuns += 1; + // Call the end function if there is one + if (this.onEnd) { + this.onEnd(); + } + // Loop if we want to + if (this.loop) { + this.state = TimerState.ACTIVE; + this.timeLeft = this.totalTime; + } + } + toString() { + return "Timer: " + this.state + " - Time Left: " + this.timeLeft + "ms of " + this.totalTime + "ms"; + } +} +exports.default = Timer; +var TimerState; +(function (TimerState) { + TimerState["ACTIVE"] = "ACTIVE"; + TimerState["PAUSED"] = "PAUSED"; + TimerState["STOPPED"] = "STOPPED"; +})(TimerState = exports.TimerState || (exports.TimerState = {})); + +},{"../../shattered_sword/Tools/InputWrapper":140,"../../shattered_sword/sword_enums":144,"../Utils/MathUtils":102,"./TimerManager":98}],98:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class TimerManager { + constructor() { + this.timers = new Array(); + } + static getInstance() { + if (!this.instance) { + this.instance = new TimerManager(); + } + return this.instance; + } + addTimer(timer) { + this.timers.push(timer); + } + clearTimers() { + this.timers = new Array(); + } + update(deltaT) { + this.timers.forEach(timer => timer.update(deltaT)); + } +} +exports.default = TimerManager; + +},{}],99:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("./MathUtils"); +// TODO: This should be moved to the datatypes folder +/** + * A Color util class that keeps track of colors like a vector, but can be converted into a string format + */ +class Color { + /** + * Creates a new color + * @param r Red + * @param g Green + * @param b Blue + * @param a Alpha + */ + constructor(r = 0, g = 0, b = 0, a = 1) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + /** + * Transparent color + * @returns rgba(0, 0, 0, 0) + */ + static get TRANSPARENT() { + return new Color(0, 0, 0, 0); + } + /** + * Red color + * @returns rgb(255, 0, 0) + */ + static get RED() { + return new Color(255, 0, 0, 1); + } + /** + * Green color + * @returns rgb(0, 255, 0) + */ + static get GREEN() { + return new Color(0, 255, 0, 1); + } + /** + * Blue color + * @returns rgb(0, 0, 255) + */ + static get BLUE() { + return new Color(0, 0, 255, 1); + } + /** + * Yellow color + * @returns rgb(255, 255, 0) + */ + static get YELLOW() { + return new Color(255, 255, 0, 1); + } + /** + * Magenta color + * @returns rgb(255, 0, 255) + */ + static get MAGENTA() { + return new Color(255, 0, 255, 1); + } + /** + * Cyan color + * @returns rgb(0, 255, 255) + */ + static get CYAN() { + return new Color(0, 255, 255, 1); + } + /** + * White color + * @returns rgb(255, 255, 255) + */ + static get WHITE() { + return new Color(255, 255, 255, 1); + } + /** + * Black color + * @returns rgb(0, 0, 0) + */ + static get BLACK() { + return new Color(0, 0, 0, 1); + } + /** + * Orange color + * @returns rgb(255, 100, 0) + */ + static get ORANGE() { + return new Color(255, 100, 0, 1); + } + /** + * Sets the color to the values provided + * @param r Red + * @param g Green + * @param b Blue + * @param a Alpha + */ + set(r, g, b, a = 1) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + /** + * Returns a new color slightly lighter than the current color + * @returns A new lighter Color + */ + lighten() { + return new Color(MathUtils_1.default.clamp(this.r + 40, 0, 255), MathUtils_1.default.clamp(this.g + 40, 0, 255), MathUtils_1.default.clamp(this.b + 40, 0, 255), MathUtils_1.default.clamp(this.a + 10, 0, 255)); + } + /** + * Returns a new color slightly darker than the current color + * @returns A new darker Color + */ + darken() { + return new Color(MathUtils_1.default.clamp(this.r - 40, 0, 255), MathUtils_1.default.clamp(this.g - 40, 0, 255), MathUtils_1.default.clamp(this.b - 40, 0, 255), MathUtils_1.default.clamp(this.a + 10, 0, 255)); + } + /** + * Returns this color as an array + * @returns [r, g, b, a] + */ + toArray() { + return [this.r, this.g, this.b, this.a]; + } + /** + * Returns the color as a string of the form #RRGGBB + * @returns #RRGGBB + */ + toString() { + return "#" + MathUtils_1.default.toHex(this.r, 2) + MathUtils_1.default.toHex(this.g, 2) + MathUtils_1.default.toHex(this.b, 2); + } + /** + * Returns the color as a string of the form rgb(r, g, b) + * @returns rgb(r, g, b) + */ + toStringRGB() { + return "rgb(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ")"; + } + /** + * Returns the color as a string of the form rgba(r, g, b, a) + * @returns rgba(r, g, b, a) + */ + toStringRGBA() { + if (this.a === 0) { + return this.toStringRGB(); + } + return "rgba(" + this.r.toString() + ", " + this.g.toString() + ", " + this.b.toString() + ", " + this.a.toString() + ")"; + } + /** + * Turns this color into a float32Array and changes color range to [0.0, 1.0] + * @returns a Float32Array containing the color + */ + toWebGL() { + return new Float32Array([ + this.r / 255, + this.g / 255, + this.b / 255, + this.a + ]); + } + static fromStringHex(str) { + let i = 0; + if (str.charAt(0) == "#") + i += 1; + let r = MathUtils_1.default.fromHex(str.substring(i, i + 2)); + let g = MathUtils_1.default.fromHex(str.substring(i + 2, i + 4)); + let b = MathUtils_1.default.fromHex(str.substring(i + 4, i + 6)); + return new Color(r, g, b); + } +} +exports.default = Color; + +},{"./MathUtils":102}],100:[function(require,module,exports){ +"use strict"; +// @ignorePage +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EaseFunctionType = void 0; +class EaseFunctions { + static easeInOutSine(x) { + return -(Math.cos(Math.PI * x) - 1) / 2; + } + static easeOutInSine(x) { + return x < 0.5 ? -Math.cos(Math.PI * (x + 0.5)) / 2 : -Math.cos(Math.PI * (x - 0.5)) / 2 + 1; + } + static easeOutSine(x) { + return Math.sin((x * Math.PI) / 2); + } + static easeInSine(x) { + return 1 - Math.cos((x * Math.PI) / 2); + } + static easeInOutQuint(x) { + return x < 0.5 ? 16 * x * x * x * x * x : 1 - Math.pow(-2 * x + 2, 5) / 2; + } + static easeInOutQuad(x) { + return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2; + } + static easeOutInQuad(x) { + return x < 0.5 ? this.easeOutIn_OutPow(x, 2) : this.easeOutIn_InPow(x, 2); + } + static easeOutIn_OutPow(x, pow) { + return 0.5 - Math.pow(-2 * x + 1, pow) / 2; + } + static easeOutIn_InPow(x, pow) { + return 0.5 + Math.pow(2 * x - 1, pow) / 2; + } +} +exports.default = EaseFunctions; +var EaseFunctionType; +(function (EaseFunctionType) { + // SINE + EaseFunctionType["IN_OUT_SINE"] = "easeInOutSine"; + EaseFunctionType["OUT_IN_SINE"] = "easeOutInSine"; + EaseFunctionType["IN_SINE"] = "easeInSine"; + EaseFunctionType["OUT_SINE"] = "easeOutSine"; + // QUAD + EaseFunctionType["IN_OUT_QUAD"] = "easeInOutQuad"; + EaseFunctionType["OUT_IN_QUAD"] = "easeOutInQuad"; + // QUINT + EaseFunctionType["IN_OUT_QUINT"] = "easeInOutQuint"; +})(EaseFunctionType = exports.EaseFunctionType || (exports.EaseFunctionType = {})); + +},{}],101:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** A class to provides some utility functions for graphs */ +class GraphUtils { + /** + * An implementation of Djikstra's shortest path algorithm based on the one described in The Algorithm Design Manual. + * @param g The graph + * @param start The number to start the shortest path from + * @returns An array containing the parent of each node of the Graph in the shortest path. + */ + static djikstra(g, start) { + let i; // Counter + let p; // Pointer to edgenode + let inTree = new Array(g.numVertices); + let distance = new Array(g.numVertices); + let parent = new Array(g.numVertices); + let v; // Current vertex to process + let w; // Candidate for next vertex + let weight; // Edge weight + let dist; // Best current distance from start + for (i = 0; i < g.numVertices; i++) { + inTree[i] = false; + distance[i] = Infinity; + parent[i] = -1; + } + distance[start] = 0; + v = start; + while (!inTree[v]) { + inTree[v] = true; + p = g.edges[v]; + while (p !== null) { + w = p.y; + weight = p.weight; + if (distance[w] > distance[v] + weight) { + distance[w] = distance[v] + weight; + parent[w] = v; + } + p = p.next; + } + v = 0; + dist = Infinity; + for (i = 0; i <= g.numVertices; i++) { + if (!inTree[i] && dist > distance[i]) { + dist = distance; + v = i; + } + } + } + return parent; + } +} +exports.default = GraphUtils; + +},{}],102:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** A class containing some utility functions for math operations */ +class MathUtils { + /** + * Returns the sign of the value provided + * @param x The value to extract the sign from + * @returns -1 if the number is less than 0, 1 otherwise + */ + static sign(x) { + return x < 0 ? -1 : 1; + } + /** + * Returns whether or not x is between a and b + * @param a The min bound + * @param b The max bound + * @param x The value to check + * @param exclusive Whether or not a and b are exclusive bounds + * @returns True if x is between a and b, false otherwise + */ + static between(a, b, x, exclusive) { + if (exclusive) { + return (a < x) && (x < b); + } + else { + return (a <= x) && (x <= b); + } + } + /** + * Clamps the value x to the range [min, max], rounding up or down if needed + * @param x The value to be clamped + * @param min The min of the range + * @param max The max of the range + * @returns x, if it is between min and max, or min/max if it exceeds their bounds + */ + static clamp(x, min, max) { + if (x < min) + return min; + if (x > max) + return max; + return x; + } + /** + * Clamps the value x to the range between 0 and 1 + * @param x The value to be clamped + * @returns x, if it is between 0 and 1, or 0/1 if it exceeds their bounds + */ + static clamp01(x) { + return MathUtils.clamp(x, 0, 1); + } + /** + * Clamps the lower end of the value of x to the range to min + * @param x The value to be clamped + * @param min The minimum allowed value of x + * @returns x, if it is greater than min, otherwise min + */ + static clampLow(x, min) { + return x < min ? min : x; + } + /** + * Clamps the lower end of the value of x to zero + * @param x The value to be clamped + * @returns x, if it is greater than 0, otherwise 0 + */ + static clampLow0(x) { + return MathUtils.clampLow(x, 0); + } + static clampMagnitude(v, m) { + if (v.magSq() > m * m) { + return v.scaleTo(m); + } + else { + return v; + } + } + static changeRange(x, min, max, newMin, newMax) { + return this.lerp(newMin, newMax, this.invLerp(min, max, x)); + } + /** + * Linear Interpolation + * @param a The first value for the interpolation bound + * @param b The second value for the interpolation bound + * @param t The time we are interpolating to + * @returns The value between a and b at time t + */ + static lerp(a, b, t) { + return a + t * (b - a); + } + /** + * Inverse Linear Interpolation. Finds the time at which a value between a and b would occur + * @param a The first value for the interpolation bound + * @param b The second value for the interpolation bound + * @param value The current value + * @returns The time at which the current value occurs between a and b + */ + static invLerp(a, b, value) { + return (value - a) / (b - a); + } + /** + * Cuts off decimal points of a number after a specified place + * @param num The number to floor + * @param place The last decimal place of the new number + * @returns The floored number + */ + static floorToPlace(num, place) { + if (place === 0) { + return Math.floor(num); + } + let factor = 10; + while (place > 1) { + factor != 10; + place--; + } + return Math.floor(num * factor) / factor; + } + /** + * Returns a number from a hex string + * @param str the string containing the hex number + * @returns the number in decimal represented by the hex string + */ + static fromHex(str) { + return parseInt(str, 16); + } + /** + * Returns the number as a hexadecimal + * @param num The number to convert to hex + * @param minLength The length of the returned hex string (adds zero padding if needed) + * @returns The hex representation of the number as a string + */ + static toHex(num, minLength = null) { + let factor = 1; + while (factor * 16 < num) { + factor *= 16; + } + let hexStr = ""; + while (factor >= 1) { + let digit = Math.floor(num / factor); + hexStr += MathUtils.toHexDigit(digit); + num -= digit * factor; + factor /= 16; + } + if (minLength !== null) { + while (hexStr.length < minLength) { + hexStr = "0" + hexStr; + } + } + return hexStr; + } + /** + * Converts a digit to hexadecimal. In this case, a digit is between 0 and 15 inclusive + * @param num The digit to convert to hexadecimal + * @returns The hex representation of the digit as a string + */ + static toHexDigit(num) { + if (num < 10) { + return "" + num; + } + else { + return String.fromCharCode(65 + num - 10); + } + } +} +exports.default = MathUtils; + +},{}],103:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("./MathUtils"); +class RenderingUtils { + static toWebGLCoords(point, origin, worldSize) { + return new Float32Array([ + MathUtils_1.default.changeRange(point.x, origin.x, origin.x + worldSize.x, -1, 1), + MathUtils_1.default.changeRange(point.y, origin.y, origin.y + worldSize.y, 1, -1) + ]); + } + static toWebGLScale(size, worldSize) { + return new Float32Array([ + 2 * size.x / worldSize.x, + 2 * size.y / worldSize.y, + ]); + } + static toWebGLColor(color) { + return new Float32Array([ + MathUtils_1.default.changeRange(color.r, 0, 255, 0, 1), + MathUtils_1.default.changeRange(color.g, 0, 255, 0, 1), + MathUtils_1.default.changeRange(color.b, 0, 255, 0, 1), + color.a + ]); + } +} +exports.default = RenderingUtils; + +},{"./MathUtils":102}],104:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** Some utility functions for dealing with strings */ +class StringUtils { + /** + * Extracts the path from a filepath that includes the file + * @param filePath the filepath to extract the path from + * @returns The path portion of the filepath provided + */ + static getPathFromFilePath(filePath) { + let splitPath = filePath.split("/"); + splitPath.pop(); + splitPath.push(""); + return splitPath.join("/"); + } +} +exports.default = StringUtils; + +},{}],105:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Game_1 = require("./Wolfie2D/Loop/Game"); +const RegistryManager_1 = require("./Wolfie2D/Registry/RegistryManager"); +const WeaponRegistry_1 = require("./shattered_sword/Registry/WeaponRegistry"); +const WeaponTypeRegistry_1 = require("./shattered_sword/Registry/WeaponTypeRegistry"); +const SplashScreen_1 = require("./shattered_sword/Scenes/SplashScreen"); +// The main function is your entrypoint into Wolfie2D. Specify your first scene and any options here. +(function main() { + // Run any tests + runTests(); + // Set up options for our game + let options = { + canvasSize: { x: 1280, y: 720 }, + //canvasSize: {x: window.innerWidth, y: window.innerHeight}, // The size of the game + clearColor: { r: 0, g: 0, b: 0 }, + inputs: [ + { name: "left", keys: ["a", "arrowleft"] }, + { name: "right", keys: ["d", "arrowright"] }, + { name: "up", keys: ["w", "arrowup"] }, + { name: "down", keys: ["s", "arrowdown"] }, + { name: "jump", keys: ["z", "space"] }, + { name: "attack", keys: ["j", "x", "enter"] }, + { name: "dash", keys: ["k", "c"] }, + { name: "skill", keys: ["l", "v"] }, + { name: "inventory", keys: ["i", "b"] }, + { name: "pause", keys: ["escape"] }, + { name: "tab", keys: ["tab"] }, + { name: "buff1", keys: ["1"] }, + { name: "buff2", keys: ["2"] }, + { name: "buff3", keys: ["3"] } + ], + useWebGL: false, + showDebug: false // Whether to show debug messages. You can change this to true if you want + }; + // Set up custom registries + let weaponTemplateRegistry = new WeaponRegistry_1.default(); + RegistryManager_1.default.addCustomRegistry("weaponTemplates", weaponTemplateRegistry); + let weaponTypeRegistry = new WeaponTypeRegistry_1.default(); + RegistryManager_1.default.addCustomRegistry("weaponTypes", weaponTypeRegistry); + // Create a game with the options specified + const game = new Game_1.default(options); + // Start our game + game.start(SplashScreen_1.default, {}); + //TODO - change to splash screen once available + //game.start(SplashScreen,{}); +})(); +function runTests() { } +; + +},{"./Wolfie2D/Loop/Game":36,"./Wolfie2D/Registry/RegistryManager":65,"./shattered_sword/Registry/WeaponRegistry":129,"./shattered_sword/Registry/WeaponTypeRegistry":130,"./shattered_sword/Scenes/SplashScreen":137}],106:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.EnemyStates = void 0; +const StateMachineAI_1 = require("../../Wolfie2D/AI/StateMachineAI"); +const AABB_1 = require("../../Wolfie2D/DataTypes/Shapes/AABB"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const Patrol_1 = require("./EnemyStates/Patrol"); +const Alert_1 = require("./EnemyStates/Alert"); +const SlimeAttack_1 = require("./EnemyStates/SlimeAttack"); +const sword_enums_1 = require("../sword_enums"); +const sword_enums_2 = require("../sword_enums"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +const Timer_1 = require("../../Wolfie2D/Timing/Timer"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +class EnemyAI extends StateMachineAI_1.default { + constructor() { + super(...arguments); + /** The default movement speed of this AI */ + this.speed = 20; + this.maxSpeed = 40; + this.velocity = Vec2_1.default.ZERO; + this.exp_val = 100; //exp value to give player when this dies + this.poisonCounter = 0; + this.burnCounter = 0; + this.bleedCounter = 0; + this.isAttaking = false; + } + initializeAI(owner, options) { + this.owner = owner; + //add states + // Patrol mode + this.addState(EnemyStates.PATROL, new Patrol_1.default(this, owner)); + this.addState(EnemyStates.ALERT, new Alert_1.default(this, owner)); + this.addState(EnemyStates.ATTACK, new SlimeAttack_1.default(this, owner)); + this.maxHealth = options.health; + this.CURRENT_HP = options.health; + this.player = options.player; + this.exp_val = options.exp; + //TODO - get correct tilemap + this.tilemap = this.owner.getScene().getLayer("Wall").getItems()[0]; + // Initialize to the default state + this.initialize(EnemyStates.PATROL); + this.direction = 1; //default moving to the right + //TODO - dots every 1 sec? can change + this.burnTimer = new Timer_1.default(1000); + this.bleedTimer = new Timer_1.default(1000); + this.poisonTimer = new Timer_1.default(1000); + this.attackTimer = new Timer_1.default(2500); + this.damageTimer = new Timer_1.default(400); + } + damage(damage) { + // enemy already dead, do not send new event + if (this.CURRENT_HP <= 0) { + return; + } + console.log(damage + " damage taken, " + this.CURRENT_HP + " hp left"); + this.CURRENT_HP -= damage; + //TODO - + if (!this.isAttaking) { + this.owner.animation.play("HURT", false); + } + console.log(damage + " damage taken, " + this.CURRENT_HP + " hp left"); + // If health goes below 0, disable AI and fire enemyDied event + if (this.CURRENT_HP <= 0) { + this.owner.setAIActive(false, {}); + this.owner.isCollidable = false; + this.owner.visible = false; + if (this.healthBar) { + this.healthBar.destroy(); + this.healthBar = undefined; + } + if (this.poisonStat) { + this.poisonStat.destroy(); + this.poisonStat = undefined; + } + if (this.burnStat) { + this.burnStat.destroy(); + this.burnStat = undefined; + } + if (this.bleedStat) { + this.bleedStat.destroy(); + this.bleedStat = undefined; + } + this.emitter.fireEvent(sword_enums_2.Player_Events.ENEMY_KILLED, { owner: this.owner.id, ai: this }); + } + this.damageTimer.start(); + } + collideWithPlayer(player) { + player.damage(10); + } + canAttack(position) { + return this.attackTimer.isStopped() && this.owner.position.distanceTo(position) <= 32; + } + //TODO - need to modify for side view + isPlayerVisible(pos) { + //Check ifplayer is visible, taking into account walls + // Get the new player location + let start = this.owner.position.clone(); + let delta = pos.clone().sub(start); + if (delta.mag() >= 640) { + return null; + } + // Iterate through the tilemap region until we find a collision + let minX = Math.min(start.x, pos.x); + let maxX = Math.max(start.x, pos.x); + let minY = Math.min(start.y, pos.y); + let maxY = Math.max(start.y, pos.y); + // Get the wall tilemap + let walls = this.tilemap; + let minIndex = walls.getColRowAt(new Vec2_1.default(minX, minY)); + let maxIndex = walls.getColRowAt(new Vec2_1.default(maxX, maxY)); + let tileSize = walls.getTileSize(); + for (let col = minIndex.x; col <= maxIndex.x; col++) { + for (let row = minIndex.y; row <= maxIndex.y; row++) { + if (walls.isTileCollidable(col, row)) { + // Get the position of this tile + let tilePos = new Vec2_1.default(col * tileSize.x + tileSize.x / 2, row * tileSize.y + tileSize.y / 2); + // Create a collider for this tile + let collider = new AABB_1.default(tilePos, tileSize.scaled(1 / 2)); + let hit = collider.intersectSegment(start, delta, Vec2_1.default.ZERO); + if (hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(pos)) { + // We hit a wall, we can't see the player + //console.log("player not visible") + return null; + } + } + } + } + return pos; + } + /** + * gets the position of the player + * @returns position of the player if visible, else null + */ + getPlayerPosition() { + return this.isPlayerVisible(this.player.position); + } + update(deltaT) { + if (InputWrapper_1.default.getState() != sword_enums_1.GameState.GAMING) { + this.owner.animation.pause(); + return; + } + this.owner.animation.resume(); + super.update(deltaT); + if (this.burnTimer.isStopped() && this.burnCounter > 0) { + this.burnCounter--; + this.burnTimer.start(); + this.damage(12 + this.player._ai.extraDotDmg); + } + if (this.poisonTimer.isStopped() && this.poisonCounter > 0) { + this.poisonCounter--; + this.poisonTimer.start(); + this.damage(Math.round(this.CURRENT_HP / 20) + this.player._ai.extraDotDmg); + } + if (this.bleedTimer.isStopped() && this.bleedCounter > 0) { + this.bleedCounter--; + this.bleedTimer.start(); + this.damage(3 + Math.round(this.CURRENT_HP / 33) + this.player._ai.extraDotDmg); + } + if (this.healthBar) { + this.healthBar.position = this.owner.collisionShape.center.clone().add(new Vec2_1.default(0, -(this.owner.collisionShape.hh + 5))); + this.healthBar.fillWidth = this.CURRENT_HP / this.maxHealth * this.owner.collisionShape.hw * 3; + if (this.CURRENT_HP / this.maxHealth >= 2 / 3) { + this.healthBar.color = Color_1.default.GREEN; + } + else if (this.CURRENT_HP / this.maxHealth >= 1 / 3) { + this.healthBar.color = Color_1.default.YELLOW; + } + else { + this.healthBar.color = Color_1.default.RED; + } + } + if (this.poisonStat) { + this.poisonStat.position = this.owner.collisionShape.center.clone().add(new Vec2_1.default(-(this.owner.collisionShape.hw) * 1.5 + 10, -(this.owner.collisionShape.hh + 15))); + this.poisonStat.visible = this.poisonCounter > 0; + } + if (this.burnStat) { + this.burnStat.position = this.poisonStat.position.clone().add(new Vec2_1.default(15, 0)); + this.burnStat.visible = this.burnCounter > 0; + } + if (this.bleedStat) { + this.bleedStat.position = this.poisonStat.position.clone().add(new Vec2_1.default(30, 0)); + this.bleedStat.visible = this.bleedCounter > 0; + } + if (this.owner.position.y > this.tilemap.getDimensions().y * this.tilemap.getTileSize().y) { + this.CURRENT_HP = -1; + this.emitter.fireEvent(sword_enums_2.Player_Events.ENEMY_KILLED, { owner: this.owner.id, ai: this }); + } + } +} +exports.default = EnemyAI; +var EnemyStates; +(function (EnemyStates) { + EnemyStates["PATROL"] = "patrol"; + EnemyStates["ALERT"] = "alert"; + EnemyStates["ATTACK"] = "attack"; +})(EnemyStates = exports.EnemyStates || (exports.EnemyStates = {})); + +},{"../../Wolfie2D/AI/StateMachineAI":4,"../../Wolfie2D/DataTypes/Shapes/AABB":16,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Timing/Timer":97,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"../sword_enums":144,"./EnemyStates/Alert":107,"./EnemyStates/Patrol":110,"./EnemyStates/SlimeAttack":111}],107:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("../EnemyAI"); +const EnemyState_1 = require("./EnemyState"); +class Alert extends EnemyState_1.default { + onEnter(options) { + this.owner.animation.playIfNotAlready("WALK", true); + } + update(deltaT) { + let position = this.parent.getPlayerPosition(); + if (position) { + this.parent.velocity.x = this.parent.maxSpeed * Math.sign(position.x - this.owner.position.x); + this.parent.direction = this.parent.velocity.x >= 0 ? 1 : -1; + if (this.parent.canAttack(position)) { + this.finished(EnemyAI_1.EnemyStates.ATTACK); + } + } + else { + this.parent.velocity.x = 0; + this.finished(EnemyAI_1.EnemyStates.PATROL); + } + if (!this.canWalk()) { + this.parent.velocity.x = 0; + } + this.owner.invertX = this.parent.direction === 1 ? true : false; + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return null; + } +} +exports.default = Alert; + +},{"../EnemyAI":106,"./EnemyState":109}],108:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyState_1 = require("./EnemyState"); +class Attack extends EnemyState_1.default { + onEnter(options) { + this.parent.attackTimer.start(); + this.parent.velocity.x = 0; + this.parent.isAttaking = true; + this.charged = this.owner.id + "charged"; + this.attacked = this.owner.id + "attacked"; + // TODO replace DYING with CHARGING + this.owner.animation.play("CHARGE", false, this.charged); + this.receiver.subscribe(this.charged); + this.receiver.subscribe(this.attacked); + } + update(deltaT) { + super.update(deltaT); + } + onExit() { + this.parent.isAttaking = false; + this.owner.animation.stop(); + return null; + } +} +exports.default = Attack; + +},{"./EnemyState":109}],109:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const State_1 = require("../../../Wolfie2D/DataTypes/State/State"); +const Vec2_1 = require("../../../Wolfie2D/DataTypes/Vec2"); +const Receiver_1 = require("../../../Wolfie2D/Events/Receiver"); +class EnemyState extends State_1.default { + constructor(parent, owner) { + super(parent); + this.gravity = 1500; //TODO - can change later + this.owner = owner; + this.receiver = new Receiver_1.default(); + } + handleInput(event) { } + canWalk() { + let collision = this.owner.collisionShape; + let colrow = this.parent.tilemap.getColRowAt(collision.center.clone().add(new Vec2_1.default(this.parent.direction * (collision.hw + 2)))); + return !this.parent.tilemap.isTileCollidable(colrow.x, colrow.y) && this.parent.tilemap.isTileCollidable(colrow.x, colrow.y + 1); + } + update(deltaT) { + if (!this.parent.damageTimer.isStopped() && !this.parent.isAttaking) { + this.parent.velocity.x = 0; + } + // Do gravity + this.parent.velocity.y += this.gravity * deltaT; + this.owner.move(this.parent.velocity.scaled(deltaT)); + } +} +exports.default = EnemyState; + +},{"../../../Wolfie2D/DataTypes/State/State":20,"../../../Wolfie2D/DataTypes/Vec2":24,"../../../Wolfie2D/Events/Receiver":31}],110:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("../EnemyAI"); +const EnemyState_1 = require("./EnemyState"); +class Patrol extends EnemyState_1.default { + onEnter(options) { + this.owner.animation.playIfNotAlready("IDLE", true); + } + update(deltaT) { + if (!this.canWalk()) { + this.parent.direction *= -1; + } + //move + this.parent.velocity.x = this.parent.direction * this.parent.speed; + this.owner.invertX = this.parent.direction === 1 ? true : false; + if (this.parent.getPlayerPosition()) { + this.finished(EnemyAI_1.EnemyStates.ALERT); + } + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return null; + } +} +exports.default = Patrol; + +},{"../EnemyAI":106,"./EnemyState":109}],111:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("../EnemyAI"); +const Attack_1 = require("./Attack"); +class SlimeAttack extends Attack_1.default { + onEnter(options) { + } + update(deltaT) { + this.finished(EnemyAI_1.EnemyStates.ALERT); + } + onExit() { + return null; + } +} +exports.default = SlimeAttack; + +},{"../EnemyAI":106,"./Attack":108}],112:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("../EnemyAI"); +const Attack_1 = require("./Attack"); +class SnakeAttack extends Attack_1.default { + update(deltaT) { + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent().type; + switch (event) { + case this.charged: + this.owner.animation.play("ATTACK", false, this.attacked); + this.owner.collisionShape.halfSize.x += 3.5; + break; + case this.attacked: + this.owner.collisionShape.halfSize.x -= 3.5; + this.finished(EnemyAI_1.EnemyStates.ALERT); + break; + } + } + this.owner.invertX = this.parent.direction === 1 ? true : false; + } +} +exports.default = SnakeAttack; + +},{"../EnemyAI":106,"./Attack":108}],113:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("./EnemyAI"); +const SlimeAttack_1 = require("./EnemyStates/SlimeAttack"); +class SlimeAI extends EnemyAI_1.default { + initializeAI(owner, options) { + super.initializeAI(owner, options); + this.addState(EnemyAI_1.EnemyStates.ATTACK, new SlimeAttack_1.default(this, owner)); + } +} +exports.default = SlimeAI; + +},{"./EnemyAI":106,"./EnemyStates/SlimeAttack":111}],114:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const EnemyAI_1 = require("./EnemyAI"); +const SnakeAttack_1 = require("./EnemyStates/SnakeAttack"); +class SnakeAI extends EnemyAI_1.default { + initializeAI(owner, options) { + super.initializeAI(owner, options); + this.addState(EnemyAI_1.EnemyStates.ATTACK, new SnakeAttack_1.default(this, owner)); + } +} +exports.default = SnakeAI; + +},{"./EnemyAI":106,"./EnemyStates/SnakeAttack":112}],115:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class BattleManager { + handleInteraction(attackerType, weapon, user) { + //may be unneeded since we are controlling the player - + //we determine enemy collision there + if (attackerType === "player") { + // Check for collisions with enemies + if (this.enemies.length != 0) { + for (let enemy of this.enemies) { + if (weapon.hits(enemy.owner)) { + let player = this.players[0]; + if (player.fullHpBonus) { + enemy.damage(Math.round(weapon.type.damage * this.players[0].CURRENT_ATK / 10)); + } + else { + enemy.damage(Math.round(weapon.type.damage * this.players[0].CURRENT_ATK / 100)); + } + //console.log("enemy took dmg"); + //add checking for each onhit buff here + //DOTS + if (player.hasBleed) { + enemy.bleedCounter += 3; + } + if (player.hasPoison) { + enemy.poisonCounter = 5; + } + if (player.hasBurn) { + enemy.burnCounter = 5; + } + if (player.hasLifesteal) { + player.addHealth(Math.round(weapon.type.damage * player.CURRENT_ATK / 100 * player.lifestealratio)); + } + } + } + } + } + else { + // Check for collision with player + for (let player of this.players) { + if (weapon.hits(player.owner)) { + player.damage(weapon.type.damage, user); + if (player.hasShield) { + player.addShield(weapon.type.damage * .5); //half of dmg taken is converted to shield + } + } + } + } + } + setPlayers(player) { + this.players = player; + } + setEnemies(enemies) { + this.enemies = enemies; + } + addEnemy(enemy) { + this.enemies.push(enemy); + } + removeEnemy(enemy) { + this.enemies = this.enemies.filter(item => item !== enemy); + if (this.enemies.length == 0) { + this.enemies = new Array(); + } + return this.enemies; + } +} +exports.default = BattleManager; + +},{}],116:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const GraphicTypes_1 = require("../../Wolfie2D/Nodes/Graphics/GraphicTypes"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +class InventoryManager { + constructor(scene, size, inventorySlot, position, padding, slotLayer, itemLayer) { + this.items = new Array(size); + this.inventorySlots = new Array(size); + this.padding = padding; + this.position = position; + this.currentSlot = 0; + // Add layers + this.slotLayer = slotLayer; + scene.addUILayer(this.slotLayer).setDepth(100); + this.itemLayer = itemLayer; + scene.addUILayer(this.itemLayer).setDepth(101); + // Create the inventory slots + for (let i = 0; i < size; i++) { + this.inventorySlots[i] = scene.add.sprite(inventorySlot, this.slotLayer); + } + this.slotSize = this.inventorySlots[0].size.clone(); + // Position the inventory slots + for (let i = 0; i < size; i++) { + this.inventorySlots[i].position.set(position.x + i * (this.slotSize.x + this.padding), position.y); + } + // Add a rect for the selected slot + this.selectedSlot = scene.add.graphic(GraphicTypes_1.GraphicType.RECT, slotLayer, { position: this.position.clone(), size: this.slotSize.clone().inc(-2) }); + this.selectedSlot.color = Color_1.default.WHITE; + this.selectedSlot.color.a = 0.2; + } + getItem() { + return this.items[this.currentSlot]; + } + /** + * Changes the currently selected slot + */ + changeSlot(slot) { + this.currentSlot = slot; + this.selectedSlot.position.copy(this.inventorySlots[slot].position); + } + /** + * Gets the currently selected slot + */ + getSlot() { + return this.currentSlot; + } + /** + * Adds an item to the currently selected slot + */ + addItem(item) { + if (!this.items[this.currentSlot]) { + // Add the item to the inventory + this.items[this.currentSlot] = item; + // Update the gui + item.moveSprite(new Vec2_1.default(this.position.x + this.currentSlot * (this.slotSize.x + this.padding), this.position.y), this.itemLayer); + return true; + } + // Failed to add item, something was already in the slot + return false; + } + /** + * Removes and returns an item from the the currently selected slot, if possible + */ + removeItem() { + let item = this.items[this.currentSlot]; + this.items[this.currentSlot] = null; + if (item) { + return item; + } + else { + return null; + } + } + setActive(active) { + if (active) { + this.inventorySlots.forEach(slot => slot.alpha = 1.0); + } + else { + this.inventorySlots.forEach(slot => slot.alpha = 0.5); + } + } +} +exports.default = InventoryManager; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":42,"../../Wolfie2D/Utils/Color":99}],117:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class Item { + constructor(sprite) { + this.sprite = sprite; + } + moveSprite(position, layer) { + // Change the layer if needed + if (layer) { + let currentLayer = this.sprite.getLayer(); + currentLayer.removeNode(this.sprite); + let newLayer = this.sprite.getScene().getLayer(layer); + newLayer.addNode(this.sprite); + this.sprite.setLayer(newLayer); + } + // Move the sprite + this.sprite.position.copy(position); + } +} +exports.default = Item; + +},{}],118:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//TODO import Vec2 from "../../../Wolfie2D/DataTypes/Vec2"; +const Emitter_1 = require("../../../Wolfie2D/Events/Emitter"); +const Timer_1 = require("../../../Wolfie2D/Timing/Timer"); +const Item_1 = require("./Item"); +class Weapon extends Item_1.default { + constructor(sprite, type, battleManager) { + super(sprite); + this.cooldown = 0; + // Set the weapon type + this.type = type.clone(); + // Keep a reference to the sprite of this weapon + this.sprite = sprite; + // Create an event emitter + this.emitter = new Emitter_1.default(); + // Save a reference to the battler manager + this.battleManager = battleManager; + // Create the cooldown timer + this.cooldownTimer = new Timer_1.default(type.cooldown); + this.cooldown = type.cooldown; + this.EXTRA_DAMAGE = 0; + this.EXTRA_RANGE = 0; + } + // @override + /** + * Uses this weapon in the specified direction. + * This only works if the cooldown timer has ended + */ + use(user, userType, direction) { + // If the cooldown timer is still running, we can't use the weapon + if (!this.cooldownTimer.isStopped()) { + return false; + } + // Rely on the weapon type to create any necessary assets + this.assets = this.type.createRequiredAssets(this.sprite.getScene()); + // Do a type specific weapon animation + this.type.doAnimation(user, direction, this.EXTRA_RANGE, ...this.assets); + // Apply damage + this.battleManager.handleInteraction(userType, this, user); + // Reset the cooldown timer + this.cooldownTimer.start(); + return true; + } + /** + * A check for whether or not this weapon hit a node + */ + hits(node) { + return this.type.hits(node, ...this.assets); + } +} +exports.default = Weapon; + +},{"../../../Wolfie2D/Events/Emitter":27,"../../../Wolfie2D/Timing/Timer":97,"./Item":117}],119:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../../../Wolfie2D/DataTypes/Vec2"); +const WeaponType_1 = require("./WeaponType"); +class Slice extends WeaponType_1.default { + initialize(options) { + this.damage = options.damage; + this.cooldown = options.cooldown; + this.displayName = options.displayName; + this.spriteKey = options.spriteKey; + this.useVolume = options.useVolume; + } + doAnimation(attacker, direction, extraRange, sliceSprite) { + // Rotate this with the game node + // TODO - need to rotate the anim properly + //sliceSprite.rotation = attacker.rotation; + //sliceSprite.rotation = (attacker).invertX? .5* Math.PI : 1.5 * Math.PI; + sliceSprite.invertX = attacker.invertX; + //TODO- + //4 to scale up the default sprite - may be different later depending on atk anim + sliceSprite.scaleX = 2 * (1 + extraRange); //might have to add extra range to y as well + sliceSprite.scaleY = 2; + // Move the slice out from the player + //scale = num of pixels between center of sprite and atk anim + sliceSprite.position = attacker.position.clone().add(direction.scaled(32)); + sliceSprite.position = sliceSprite.position.add(new Vec2_1.default(0, 16)); //make it go down a bit + // Play the slice animation w/o loop, but queue the normal animation + sliceSprite.animation.play("SLICE"); + sliceSprite.animation.queue("NORMAL", true); + } + createRequiredAssets(scene) { + let slice = scene.add.animatedSprite("slice", "primary"); + slice.animation.play("NORMAL", true); + return [slice]; + } + hits(node, sliceSprite) { + return sliceSprite.boundary.overlaps(node.collisionShape); + } + clone() { + let newType = new Slice(); + newType.initialize({ damage: this.damage, cooldown: this.cooldown, displayName: this.displayName, spriteKey: this.spriteKey, useVolume: this.useVolume }); + return newType; + } +} +exports.default = Slice; + +},{"../../../../Wolfie2D/DataTypes/Vec2":24,"./WeaponType":120}],120:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class WeaponType { +} +exports.default = WeaponType; + +},{}],121:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BuffCategory = exports.Buff = exports.BuffType = exports.PlayerStates = exports.PlayerType = void 0; +const StateMachineAI_1 = require("../../Wolfie2D/AI/StateMachineAI"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const sword_enums_1 = require("../sword_enums"); +const Fall_1 = require("./PlayerStates/Fall"); +const Idle_1 = require("./PlayerStates/Idle"); +const InAir_1 = require("./PlayerStates/InAir"); +const Jump_1 = require("./PlayerStates/Jump"); +const Walk_1 = require("./PlayerStates/Walk"); +const Debug_1 = require("../../Wolfie2D/Debug/Debug"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +const Timer_1 = require("../../Wolfie2D/Timing/Timer"); +const PlayerState_1 = require("./PlayerStates/PlayerState"); +const GameEventType_1 = require("../../Wolfie2D/Events/GameEventType"); +var PlayerType; +(function (PlayerType) { + PlayerType["PLATFORMER"] = "platformer"; + PlayerType["TOPDOWN"] = "topdown"; +})(PlayerType = exports.PlayerType || (exports.PlayerType = {})); +var PlayerStates; +(function (PlayerStates) { + PlayerStates["IDLE"] = "idle"; + PlayerStates["WALK"] = "walk"; + PlayerStates["JUMP"] = "jump"; + PlayerStates["FALL"] = "fall"; + PlayerStates["PREVIOUS"] = "previous"; +})(PlayerStates = exports.PlayerStates || (exports.PlayerStates = {})); +var BuffType; +(function (BuffType) { + BuffType["FLAT_ATK"] = "attack"; + BuffType["PERCENT_ATK"] = "percent_attack"; + BuffType["DEF"] = "defence"; + BuffType["FLAT_HEALTH"] = "health"; + BuffType["PERCENT_HEALTH"] = "percent_health"; + BuffType["SPEED"] = "speed"; + BuffType["RANGE"] = "range"; + BuffType["ATKSPEED"] = "attackspeed"; + BuffType["POISON"] = "poison"; + BuffType["BLEED"] = "bleed"; + BuffType["BURN"] = "burn"; + BuffType["EXTRA_DOT"] = "extradot"; + BuffType["SHIELD"] = "shield"; + BuffType["SHIELD_DMG"] = "shielddmg"; + BuffType["LIFESTEAL"] = "lifesteal"; + BuffType["LIFESTEALBUFF"] = "lifestealbuff"; + BuffType["EXTRALIFE"] = "extralife"; + BuffType["ONESHOT"] = "oneshot"; + BuffType["FULLHPBONUSDMG"] = "fullhpbonusdmg"; +})(BuffType = exports.BuffType || (exports.BuffType = {})); +class Buff { +} +exports.Buff = Buff; +//TODO - need better names +var BuffCategory; +(function (BuffCategory) { + BuffCategory["ATTACK"] = "ATTACK"; + BuffCategory["DOT"] = "DOT"; + BuffCategory["SHIELD"] = "SHIELD"; + BuffCategory["HEALTH"] = "HEALTH"; + BuffCategory["EXTRA"] = "EXTRA"; +})(BuffCategory = exports.BuffCategory || (exports.BuffCategory = {})); +//TODO - discuss max stats during refinement, unused for now +class PlayerController extends StateMachineAI_1.default { + constructor() { + super(...arguments); + this.velocity = Vec2_1.default.ZERO; + //will need to discuss redundant stats + this.speed = 200; + this.MIN_SPEED = 200; + this.MAX_SPEED = 300; + this.BASE_HP = 100; + this.MAX_HP = 100; + this.CURRENT_HP = 100; + this.BASE_ATK = 100; + this.CURRENT_ATK = 100; + this.damage_multiplier = 1; + this.CURRENT_EXP = 0; + this.MAX_EXP = 100; + this.CURRENT_SHIELD = 0; + this.MAX_SHIELD = 20; + this.invincible = false; + this.level = 1; + this.godMode = false; + //for doublejumps maybe = # of jumps in air allowed + this.MAX_airjumps = 1; + this.airjumps = 0; + //add to current_buffs later + this.hasBleed = false; + this.hasPoison = false; + this.hasBurn = false; + this.hasShield = false; + this.shieldDamage = 1; + this.hasLifesteal = false; + this.lifestealratio = 0; //percent of damage to steal + this.hasOneShot = false; + this.extraDotDmg = 0; + this.lives = 1; + this.cooldownMultiplier = 1; + this.fullHpBonus = false; + this.poisonCounter = 0; + this.burnCounter = 0; + this.bleedCounter = 0; + this.enemiesKilled = 0; + } + //TODO - get the correct tilemap + initializeAI(owner, options) { + this.owner = owner; + this.initializePlatformer(); + this.tilemap = this.owner.getScene().getTilemap(options.tilemap); + this.inventory = options.inventory; + this.lookDirection = new Vec2_1.default(); + //i frame timer + PlayerController.invincibilityTimer = new Timer_1.default(2000); + //initialize the buff pool - each has same weight at first + PlayerController.buffPool = new Array(); + for (let i = 0; i < 4; i++) { + PlayerController.buffPool.push(BuffCategory.ATTACK); + PlayerController.buffPool.push(BuffCategory.EXTRA); + PlayerController.buffPool.push(BuffCategory.DOT); + PlayerController.buffPool.push(BuffCategory.SHIELD); + PlayerController.buffPool.push(BuffCategory.HEALTH); + } + //initialize dot timers + this.burnTimer = new Timer_1.default(1000); + this.bleedTimer = new Timer_1.default(1000); + this.poisonTimer = new Timer_1.default(1000); + //to test the buffs + //this.addBuff( {type:BuffType.HEALTH, value:1} ); + //this.addBuff({type:BuffType.BURN, value:1, category:BuffCategory.DOT}); + //this.addBuff({type:BuffType.BLEED, value:1, category:BuffCategory.DOT}); + //this.addBuff({type:BuffType.POISON, value:1, category:BuffCategory.DOT}); + } + initializePlatformer() { + this.speed = 400; + let idle = new Idle_1.default(this, this.owner); + this.addState(PlayerStates.IDLE, idle); + let walk = new Walk_1.default(this, this.owner); + this.addState(PlayerStates.WALK, walk); + let jump = new Jump_1.default(this, this.owner); + this.addState(PlayerStates.JUMP, jump); + let fall = new Fall_1.default(this, this.owner); + this.addState(PlayerStates.FALL, fall); + this.initialize(PlayerStates.IDLE); + } + changeState(stateName) { + // If we jump or fall, push the state so we can go back to our current state later + // unless we're going from jump to fall or something + if ((stateName === PlayerStates.JUMP || stateName === PlayerStates.FALL) && !(this.stack.peek() instanceof InAir_1.default)) { + this.stack.push(this.stateMap.get(stateName)); + } + super.changeState(stateName); + } + update(deltaT) { + super.update(deltaT); + if (PlayerController.invincibilityTimer.isStopped()) { + this.invincible = false; + } + if (this.currentState instanceof Jump_1.default) { + Debug_1.default.log("playerstate", "Player State: Jump"); + } + else if (this.currentState instanceof Walk_1.default) { + Debug_1.default.log("playerstate", "Player State: Walk"); + } + else if (this.currentState instanceof Idle_1.default) { + Debug_1.default.log("playerstate", "Player State: Idle"); + } + else if (this.currentState instanceof Fall_1.default) { + Debug_1.default.log("playerstate", "Player State: Fall"); + } + Debug_1.default.log("player speed", "player speed: x: " + this.velocity.x + ", y:" + this.velocity.y); + Debug_1.default.log("player Coords:", "Player Coords:" + this.owner.position); + //testing the attacks here, may be moved to another place later + if (InputWrapper_1.default.isAttackJustPressed()) { + let item = this.inventory.getItem(); + this.owner.animation.play("ATTACK", true); + //TODO - get proper look direction + this.lookDirection.x = this.owner.invertX ? -1 : 1; + // If there is an item in the current slot, use it + if (item) { + item.use(this.owner, "player", this.lookDirection); + } + } + //check dot effects + if (this.burnTimer.isStopped() && this.burnCounter > 0) { + this.burnCounter--; + this.burnTimer.start(); + this.damage(5); + } + if (this.poisonTimer.isStopped() && this.poisonCounter > 0) { + this.poisonCounter--; + this.poisonTimer.start(); + this.damage(Math.round(this.CURRENT_HP / 33)); + } + if (this.bleedTimer.isStopped() && this.bleedCounter > 0) { + this.bleedCounter--; + this.bleedTimer.start(); + this.damage(2 + Math.round(this.CURRENT_HP / 50)); + } + } + // TODO - figure out attacker + damage(damage, attacker) { + if (this.godMode) { + //console.log("godmode"); + return; + } + if (!this.invincible && PlayerState_1.default.dashTimer.isStopped()) { + //console.log("take damage"); + //i frame here + PlayerController.invincibilityTimer.start(); + this.invincible = true; + //shield absorbs the damage and sends dmg back to attacker + if (this.CURRENT_SHIELD > 0) { + let newshield = Math.max(0, this.CURRENT_SHIELD - damage); //calculate the new shield value + if (attacker !== undefined) { + attacker._ai.damage((this.CURRENT_SHIELD - newshield) * this.shieldDamage); //damage the attacker the dmg taken to shield + } + this.CURRENT_SHIELD = newshield; //update shield value + } + else { + //i frame here + PlayerController.invincibilityTimer.start(); + this.invincible = true; + //console.log("hurt anim"); + this.owner.animation.play("HURT"); + damage *= this.damage_multiplier; + damage = parseFloat(damage.toPrecision(2)); + this.CURRENT_HP -= damage; + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "hurt", loop: false, holdReference: false }); + //if player has shield buff give them shield when damaged + if (this.hasShield) { + this.CURRENT_SHIELD += damage * .5; + } + } + } + else { + //console.log("player is invincible"); + } + if (this.CURRENT_HP <= 0) { + this.lives--; + this.owner.animation.play("DYING"); + this.owner.animation.queue("DEAD", true, sword_enums_1.Player_Events.PLAYER_KILLED); + this.emitter.fireEvent(sword_enums_1.Player_Events.PLAYER_KILLED); + } + } + /** + * gives the player a certain amount of shield + * @param shield amount of shield to add to player + */ + addShield(shield) { + this.CURRENT_SHIELD = (this.CURRENT_SHIELD + shield) % this.MAX_SHIELD; + } + /** + * gives health to the player + * @param health health to give player + */ + addHealth(health) { + this.CURRENT_HP += health; + if (this.CURRENT_HP > this.MAX_HP) { + this.CURRENT_HP = this.MAX_HP; + } + } + /** + * gives the player exp + * @param exp amount of exp to give the player + */ + giveExp(exp) { + this.CURRENT_EXP += exp; + //if > than max exp level up (give buff) + if (this.CURRENT_EXP >= this.MAX_EXP) { + this.CURRENT_EXP -= this.MAX_EXP; + this.MAX_EXP += 50; //increase max exp needed for level up + this.level++; + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "level_up", loop: false, holdReference: false }); + this.emitter.fireEvent(sword_enums_1.Player_Events.GIVE_REGULAR_BUFF); + } + } + /** + * generates an array of regular buffs + * @param val optional value to give buff + * @returns array of three buffs + */ + generateRegularBuffs(val) { + //random number from 5 to 15 if no value given + let num = Math.floor(Math.random() * 10) + 5; + num = Math.round(num); + if (typeof val !== 'undefined') { + num = val; + } + let buffs = new Array(); + buffs.push({ type: BuffType.FLAT_ATK, value: num, category: BuffCategory.EXTRA }, { type: BuffType.SPEED, value: num, category: BuffCategory.EXTRA }, { type: BuffType.FLAT_HEALTH, value: num, category: BuffCategory.SHIELD }, { type: BuffType.RANGE, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease range \nby " + num + "%" }, { type: BuffType.ATKSPEED, value: num, category: BuffCategory.ATTACK }); + //shuffle pool of buffs + buffs.sort(() => 0.5 - Math.random()); + // Get sub-array of first 3 elements after shuffled + let selected = buffs.slice(0, 3); //3 buff categories + return selected; + } + /** + * generates an array of special buffs + * @param val optional value to give the buff + * @returns array of 3 Buffs + */ + generateSpecialBuffs(val) { + //shuffle pool of buff categories + PlayerController.buffPool.sort(() => 0.5 - Math.random()); + // Get sub-array of first 3 elements after shuffled + let shuffled = PlayerController.buffPool.slice(0, 3); //3 buff categories + //random number from 5 to 15 if no value given + let num = Math.floor(Math.random() * 10) + 5; + num = Math.round(num); + if (typeof val !== 'undefined') { + num = val; + } + //TODO - implement better buff genertion - some buffs dont want multiple of + let attackBuffs = [ + { type: BuffType.PERCENT_ATK, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease Attack \nby" + num + "%" } + ]; + let dotBuffs = []; + if (!this.hasBleed) { + dotBuffs.push({ type: BuffType.BLEED, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply Bleed" }); + } + if (!this.hasBurn) { + dotBuffs.push({ type: BuffType.BURN, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply Burn" }); + } + if (!this.hasPoison) { + dotBuffs.push({ type: BuffType.POISON, value: 1, category: BuffCategory.DOT, string: "\n\nYour hits \napply poison" }); + } + //only add extra dot if at least one dot is acquired + for (let i = dotBuffs.length; i < 3; i++) { + dotBuffs.push({ type: BuffType.EXTRA_DOT, value: num, category: BuffCategory.DOT, string: "\n\nIncrease your \nDOT damage" }); + } + let shieldBuffs = [ + { type: BuffType.PERCENT_HEALTH, value: num / 100, category: BuffCategory.SHIELD, string: "\n\nIncrease max hp \nby " + num + "%" }, + ]; + //if player doesnt have shield buff, give them the option, otherwise give buff shield option + if (!this.hasShield) { + shieldBuffs.push({ type: BuffType.SHIELD, value: 1, category: BuffCategory.SHIELD, string: "\n\nGain Shield \nWhen Damaged \n Shields return \nthe damage taken \nto attacker" }); + } + else { + shieldBuffs.push({ type: BuffType.SHIELD_DMG, value: num, category: BuffCategory.SHIELD, string: "\n\nIncrease damage \nreturned by shield" }); + } + let healthBuffs = [ + { type: BuffType.DEF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nDecrease damage \ntaken by " + num + "%" } + ]; + if (!this.fullHpBonus) { + healthBuffs.push({ type: BuffType.FULLHPBONUSDMG, value: 1, category: BuffCategory.HEALTH, string: "\n\nDeal 10x damage \n when at full HP" }); + } + if (!this.hasLifesteal) { + healthBuffs.push({ type: BuffType.LIFESTEAL, value: 1, category: BuffCategory.HEALTH, string: "\n\nGain lifesteal" }); + } + else { + healthBuffs.push({ type: BuffType.LIFESTEALBUFF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nIncrease Lifesteal \nstrength by " + num + "%" }); + } + let extraBuffs = [ + { type: BuffType.EXTRALIFE, value: 1, category: BuffCategory.EXTRA, string: "\n\nGain an \nExtra Life" }, + ]; + if (!this.hasOneShot) { //only add oneshot buff if it isnt already included + extraBuffs.push({ type: BuffType.ONESHOT, value: 1, category: BuffCategory.EXTRA, string: "\n\nYour hits hurt \n100x more but \nyour max health \nis set to 1 " }); + } + ; + let selected = new Array(); + while (shuffled.length != 0) { + let cat = shuffled.pop(); + switch (cat) { + case BuffCategory.ATTACK: + attackBuffs.sort(() => 0.5 - Math.random()); + if (attackBuffs.length == 0) { + selected.push({ type: BuffType.PERCENT_HEALTH, value: num / 100, category: BuffCategory.ATTACK, string: "\n\nIncrease attack \nby" + num + "%" }); + } + else { + selected.push(attackBuffs.pop()); + } + break; + case BuffCategory.DOT: + dotBuffs.sort(() => 0.5 - Math.random()); + if (dotBuffs.length == 0) { + selected.push({ type: BuffType.EXTRA_DOT, value: num, category: BuffCategory.DOT, string: "\n\nIncrease your \nDOT damage" }); + } + else { + selected.push(dotBuffs.pop()); + } + break; + case BuffCategory.EXTRA: + extraBuffs.sort(() => 0.5 - Math.random()); + if (extraBuffs.length == 0) { + selected.push({ type: BuffType.EXTRALIFE, value: 1, category: BuffCategory.EXTRA, string: "\n\nGain an \nExtra Life" }); + } + else { + selected.push(extraBuffs.pop()); + } + break; + case BuffCategory.HEALTH: + healthBuffs.sort(() => 0.5 - Math.random()); + if (healthBuffs.length == 0) { + selected.push({ type: BuffType.DEF, value: num / 100, category: BuffCategory.HEALTH, string: "\n\nDecrease damage\n taken by " + num + "%" }); + } + else { + selected.push(healthBuffs.pop()); + } + break; + case BuffCategory.SHIELD: + shieldBuffs.sort(() => 0.5 - Math.random()); + if (shieldBuffs.length == 0) { + selected.push({ type: BuffType.FLAT_HEALTH, value: num, category: BuffCategory.SHIELD }); + } + else { + selected.push(shieldBuffs.pop()); + } + break; + } + } + return selected; + } + /** + * Add given buff to the player + * @param buff Given buff + * @param init whether or not this is being used during the initialization of the player + */ + addBuff(buff, init) { + //add buff to array of applied buffs if not being used to init + if (init === undefined) { + //increase weight of selected buff category + PlayerController.buffPool.push(buff.category); + PlayerController.appliedBuffs.push(buff); + } + else if (!init) { + //increase weight of selected buff category + PlayerController.buffPool.push(buff.category); + PlayerController.appliedBuffs.push(buff); + } + // TODO + let item = this.inventory.getItem(); + switch (buff.type) { + case BuffType.FLAT_HEALTH: + //this.CURRENT_BUFFS.hp += buff.value; + this.CURRENT_HP += buff.value; + this.MAX_HP += buff.value; + break; + case BuffType.PERCENT_HEALTH: + this.CURRENT_HP *= (1 + buff.value); + this.MAX_HP *= (1 + buff.value); + this.CURRENT_HP = Math.round(this.CURRENT_HP); + this.MAX_HP = Math.round(this.MAX_HP); + break; + case BuffType.FLAT_ATK: + this.CURRENT_ATK += buff.value; + break; + case BuffType.PERCENT_ATK: + this.CURRENT_ATK *= buff.value; + this.CURRENT_ATK = Math.round(this.CURRENT_ATK); + break; + case BuffType.SPEED: + this.speed += buff.value; + break; + case BuffType.DEF: + this.damage_multiplier *= (1 - buff.value); + break; + case BuffType.RANGE: + if (item) { + item.EXTRA_RANGE += buff.value; + } + break; + case BuffType.BLEED: + this.hasBleed = true; + break; + case BuffType.BURN: + this.hasBurn = true; + break; + case BuffType.POISON: + this.hasPoison = true; + break; + case BuffType.EXTRA_DOT: + this.extraDotDmg += buff.value; + break; + case BuffType.SHIELD: + this.hasShield = true; + break; + case BuffType.ATKSPEED: + if (item) { + this.cooldownMultiplier -= buff.value; + //reduce cooldowntimer + item.cooldownTimer = new Timer_1.default(item.cooldown * this.cooldownMultiplier); + } + break; + case BuffType.SHIELD_DMG: + this.shieldDamage += buff.value; + break; + case BuffType.EXTRALIFE: + this.lives++; + break; + case BuffType.LIFESTEAL: + this.hasLifesteal = true; + this.lifestealratio = .2; //20% lifesteal + break; + case BuffType.LIFESTEALBUFF: + this.lifestealratio += buff.value; + break; + case BuffType.ONESHOT: + this.MAX_HP = 1; + this.CURRENT_HP = 1; + this.CURRENT_ATK *= 100; + break; + case BuffType.FULLHPBONUSDMG: + this.fullHpBonus = true; + break; + } + } + /** + * + * @returns record of the player stats + */ + getStats() { + let stats = {}; + stats.CURRENT_HP = this.CURRENT_HP; + stats.CURRENT_ATK = this.CURRENT_ATK; + stats.CURRENT_SHIELD = this.CURRENT_SHIELD; + stats.CURRENT_EXP = this.CURRENT_EXP; + return; + } + toString() { + let s = "HP: " + this.CURRENT_HP + "/" + this.MAX_HP + + "\nATK: " + this.CURRENT_ATK + + "\nSpeed: " + this.speed + + "\nDamage Ratio: " + this.damage_multiplier + + "\nEnemies Killed: " + this.enemiesKilled + + "\nSword Effects:" + + (this.hasBleed ? "\n Bleed," : " ") + + (this.hasBurn ? " Burn," : "") + + (this.hasPoison ? " Poison," : "") + + (this.hasShield ? " Shield," : "") + + (this.fullHpBonus ? " FullHealth deal x10 Dmg" : "") + + (this.hasLifesteal ? " Lifesteal," : "") + + (this.hasOneShot ? " Atk x 100, maxhp set to 1" : ""); + return s; + } +} +exports.default = PlayerController; +PlayerController.buffPool = new Array(); +PlayerController.appliedBuffs = new Array(); + +},{"../../Wolfie2D/AI/StateMachineAI":4,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Debug/Debug":25,"../../Wolfie2D/Events/GameEventType":30,"../../Wolfie2D/Timing/Timer":97,"../Tools/InputWrapper":140,"../sword_enums":144,"./PlayerStates/Fall":122,"./PlayerStates/Idle":123,"./PlayerStates/InAir":124,"./PlayerStates/Jump":125,"./PlayerStates/PlayerState":127,"./PlayerStates/Walk":128}],122:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const InAir_1 = require("./InAir"); +const InputWrapper_1 = require("../../Tools/InputWrapper"); +const PlayerState_1 = require("./PlayerState"); +class Fall extends InAir_1.default { + onEnter(options) { + // this.owner.animation.play("FALL", true); + } + update(deltaT) { + if (!PlayerState_1.default.dashTimer.isStopped()) { + this.owner.animation.playIfNotAlready("DASH"); + } + else { + if (this.parent.invincible) { + this.owner.animation.playIfNotAlready("HURT"); + } + else { + this.owner.animation.playIfNotAlready("FALL", true); + } + } + //TODO - testing doublejump, may have to move to InAir instead + // If we jump, move to the Jump state, give a burst of upwards velocity + if (this.parent.airjumps > 0 && InputWrapper_1.default.isJumpJustPressed()) { + this.parent.airjumps--; + this.finished("jump"); + this.parent.velocity.y = -600; // basically jump height + } + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return {}; + } +} +exports.default = Fall; + +},{"../../Tools/InputWrapper":140,"./InAir":124,"./PlayerState":127}],123:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const PlayerController_1 = require("../PlayerController"); +const OnGround_1 = require("./OnGround"); +const PlayerState_1 = require("./PlayerState"); +class Idle extends OnGround_1.default { + onEnter(options) { + this.parent.speed = this.parent.MIN_SPEED; + } + update(deltaT) { + //("idle anim"); + if (!PlayerState_1.default.dashTimer.isStopped()) { + console.log("Playing dash"); + this.owner.animation.playIfNotAlready("DASH"); + } + else { + this.owner.animation.playIfNotAlready("IDLE", true); + } + let dir = this.getInputDirection(); + if (!dir.isZero() && dir.y === 0) { + this.finished(PlayerController_1.PlayerStates.WALK); + } + this.parent.velocity.x = 0; + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return {}; + } +} +exports.default = Idle; + +},{"../PlayerController":121,"./OnGround":126,"./PlayerState":127}],124:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils"); +const PlayerController_1 = require("../PlayerController"); +const PlayerState_1 = require("./PlayerState"); +class InAir extends PlayerState_1.default { + update(deltaT) { + super.update(deltaT); + let dir = this.getInputDirection(); + if (dir.x !== 0) { + this.owner.invertX = MathUtils_1.default.sign(dir.x) < 0; + } + this.parent.velocity.x += dir.x * (this.parent.speed) / 3.5 - 0.3 * this.parent.velocity.x; + if (this.owner.onGround) { + this.finished(PlayerController_1.PlayerStates.PREVIOUS); + } + } +} +exports.default = InAir; + +},{"../../../Wolfie2D/Utils/MathUtils":102,"../PlayerController":121,"./PlayerState":127}],125:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const GameEventType_1 = require("../../../Wolfie2D/Events/GameEventType"); +const InputWrapper_1 = require("../../Tools/InputWrapper"); +const PlayerController_1 = require("../PlayerController"); +const InAir_1 = require("./InAir"); +const PlayerState_1 = require("./PlayerState"); +class Jump extends InAir_1.default { + onEnter(options) { + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "jump", loop: false, holdReference: false }); + } + update(deltaT) { + if (!PlayerState_1.default.dashTimer.isStopped()) { + this.owner.animation.playIfNotAlready("DASH"); + } + else { + if (this.parent.invincible) { + this.owner.animation.playIfNotAlready("HURT"); + } + else { + this.owner.animation.playIfNotAlready("JUMP", true); + } + } + if (this.owner.onCeiling) { + this.parent.velocity.y = 0; + } + //TODO - testing doublejump, may have to move to InAir instead + // If we jump, move to the Jump state, give a burst of upwards velocity + if (this.parent.airjumps > 0 && InputWrapper_1.default.isJumpJustPressed()) { + this.parent.airjumps--; + this.finished("jump"); + this.parent.velocity.y = -600; // basically jump height + } + // If we're falling, go to the fall state + if (this.parent.velocity.y >= 0) { + this.finished(PlayerController_1.PlayerStates.FALL); + } + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return {}; + } +} +exports.default = Jump; + +},{"../../../Wolfie2D/Events/GameEventType":30,"../../Tools/InputWrapper":140,"../PlayerController":121,"./InAir":124,"./PlayerState":127}],126:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const MathUtils_1 = require("../../../Wolfie2D/Utils/MathUtils"); +const sword_enums_1 = require("../../sword_enums"); +const InputWrapper_1 = require("../../Tools/InputWrapper"); +const PlayerState_1 = require("./PlayerState"); +class OnGround extends PlayerState_1.default { + onEnter(options) { } + update(deltaT) { + //reset airjumps + this.parent.airjumps = this.parent.MAX_airjumps; + if (this.parent.velocity.y > 0) { + this.parent.velocity.y = 0; + } + let direction = this.getInputDirection(); + if (direction.x !== 0) { + this.owner.invertX = MathUtils_1.default.sign(direction.x) < 0; + } + // If we jump, move to the Jump state, give a burst of upwards velocity + if (InputWrapper_1.default.isJumpJustPressed()) { + this.finished("jump"); + this.parent.velocity.y = -600; // basically jump height + } + else if (!this.owner.onGround && InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) { + this.finished("fall"); + } + super.update(deltaT); + } + onExit() { + return {}; + } +} +exports.default = OnGround; + +},{"../../../Wolfie2D/Utils/MathUtils":102,"../../Tools/InputWrapper":140,"../../sword_enums":144,"./PlayerState":127}],127:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const State_1 = require("../../../Wolfie2D/DataTypes/State/State"); +const Vec2_1 = require("../../../Wolfie2D/DataTypes/Vec2"); +const Timer_1 = require("../../../Wolfie2D/Timing/Timer"); +const sword_enums_1 = require("../../sword_enums"); +const InputWrapper_1 = require("../../Tools/InputWrapper"); +class PlayerState extends State_1.default { + constructor(parent, owner) { + super(parent); + this.gravity = 1500; //TODO - can change later + this.owner = owner; + this.positionTimer = new Timer_1.default(250); + this.positionTimer.start(); + PlayerState.dashTimer = new Timer_1.default(100); + PlayerState.dashCoolDownTimer = new Timer_1.default(600); + } + handleInput(event) { + } + doDash() { + if (PlayerState.dashCoolDownTimer.isStopped()) { + //TODO - decide how to implement dash - could be a flash - maybe allow in air as well + //play dash anim maybe + //TODO - might give buffed speed stat to dash speed + //TODO - give player i frame + PlayerState.dashCoolDownTimer.start(); + PlayerState.dashTimer.start(); + } + } + /** + * Get the inputs from the keyboard, or Vec2.Zero if nothing is being pressed + */ + getInputDirection() { + let direction = Vec2_1.default.ZERO; + direction.x = (InputWrapper_1.default.isLeftPressed() ? -1 : 0) + (InputWrapper_1.default.isRightPressed() ? 1 : 0); + direction.y = (InputWrapper_1.default.isJumpJustPressed() ? -1 : 0); + return direction; + } + update(deltaT) { + // Do gravity + if (this.positionTimer.isStopped()) { + this.emitter.fireEvent(sword_enums_1.Player_Events.PLAYER_MOVE, { position: this.owner.position.clone() }); + this.positionTimer.start(); + } + if (InputWrapper_1.default.isDashJustPressed()) { + this.doDash(); + } + if (!PlayerState.dashTimer.isStopped()) { + this.parent.velocity.x = this.owner.invertX ? -800 : 800; + } + if (InputWrapper_1.default.getState() === sword_enums_1.GameState.GAMING) { + this.parent.owner.animation.resume(); + this.parent.velocity.y += this.gravity * deltaT; + this.owner.move(this.parent.velocity.scaled(deltaT)); + } + else { + this.parent.owner.animation.pause(); + } + } +} +exports.default = PlayerState; + +},{"../../../Wolfie2D/DataTypes/State/State":20,"../../../Wolfie2D/DataTypes/Vec2":24,"../../../Wolfie2D/Timing/Timer":97,"../../Tools/InputWrapper":140,"../../sword_enums":144}],128:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const PlayerController_1 = require("../PlayerController"); +const OnGround_1 = require("./OnGround"); +const PlayerState_1 = require("./PlayerState"); +class Walk extends OnGround_1.default { + onEnter(options) { + this.parent.speed = this.parent.MIN_SPEED; + } + update(deltaT) { + if (!PlayerState_1.default.dashTimer.isStopped()) { + this.owner.animation.playIfNotAlready("DASH"); + } + else { + if (this.parent.invincible) { + this.owner.animation.playIfNotAlready("HURT"); + } + else { + this.owner.animation.playIfNotAlready("WALK", true); + } + } + let dir = this.getInputDirection(); + if (dir.isZero()) { + this.finished(PlayerController_1.PlayerStates.IDLE); + } + this.parent.velocity.x = dir.x * (this.parent.speed); + super.update(deltaT); + } + onExit() { + this.owner.animation.stop(); + return {}; + } +} +exports.default = Walk; + +},{"../PlayerController":121,"./OnGround":126,"./PlayerState":127}],129:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Registry_1 = require("../../Wolfie2D/Registry/Registries/Registry"); +const ResourceManager_1 = require("../../Wolfie2D/ResourceManager/ResourceManager"); +const Slice_1 = require("../GameSystems/items/WeaponTypes/Slice"); +class WeaponTemplateRegistry extends Registry_1.default { + preload() { + const rm = ResourceManager_1.default.getInstance(); + //TODO - + // Load sprites for each weapon + //rm.image("something", "shattered_sword_assets/sprites/something.png"); + rm.image("knife", "shattered_sword_assets/sprites/knife.png"); + // Load spritesheets + //rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json"); + rm.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); + // Register default types + //this.registerItem("itemtype", itemTypefile); + this.registerItem("slice", Slice_1.default); + } + registerAndPreloadItem(key) { } + registerItem(key, constr) { + this.add(key, constr); + } +} +exports.default = WeaponTemplateRegistry; + +},{"../../Wolfie2D/Registry/Registries/Registry":63,"../../Wolfie2D/ResourceManager/ResourceManager":83,"../GameSystems/items/WeaponTypes/Slice":119}],130:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Registry_1 = require("../../Wolfie2D/Registry/Registries/Registry"); +class WeaponTypeRegistry extends Registry_1.default { + preload() { } + // We don't need this for this assignment + registerAndPreloadItem(key) { } + registerItem(key, type) { + this.add(key, type); + } +} +exports.default = WeaponTypeRegistry; + +},{"../../Wolfie2D/Registry/Registries/Registry":63}],131:[function(require,module,exports){ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const AABB_1 = require("../../Wolfie2D/DataTypes/Shapes/AABB"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const GameEventType_1 = require("../../Wolfie2D/Events/GameEventType"); +const GraphicTypes_1 = require("../../Wolfie2D/Nodes/Graphics/GraphicTypes"); +const Label_1 = require("../../Wolfie2D/Nodes/UIElements/Label"); +const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes"); +const Scene_1 = require("../../Wolfie2D/Scene/Scene"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +const PlayerController_1 = require("../Player/PlayerController"); +const sword_enums_1 = require("../sword_enums"); +const RegistryManager_1 = require("../../Wolfie2D/Registry/RegistryManager"); +const Weapon_1 = require("../GameSystems/items/Weapon"); +const BattleManager_1 = require("../GameSystems/BattleManager"); +const EnemyAI_1 = require("../AI/EnemyAI"); +const SnakeAI_1 = require("../AI/SnakeAI"); +const SlimeAI_1 = require("../AI/SlimeAI"); +const InventoryManager_1 = require("../GameSystems/InventoryManager"); +const Stack_1 = require("../../Wolfie2D/DataTypes/Stack"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +const GameOver_1 = require("./GameOver"); +const MainMenu_1 = require("./MainMenu"); +// TODO +/** + * Add in some level music. + * This can be done here in the base GameLevel class or individual level files + */ +class GameLevel extends Scene_1.default { + constructor() { + super(...arguments); + this.touchedStartCheckPoint = false; + this.touchedEndCheckPoint = false; + this.gameStarted = false; + this.levelEnded = false; + } + loadScene() { + //can load player sprite here + this.load.spritesheet("player", "shattered_sword_assets/spritesheets/Hiro.json"); + // TODO - change when done testing + this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); + // Load the scene info + this.load.object("weaponData", "shattered_sword_assets/data/weaponData.json"); + // Load in the enemy info + //this.load.object("enemyData", "shattered_sword_assets/data/enemy.json"); + // Load in item info + //this.load.object("itemData", "shattered_sword_assets/data/items.json"); + this.load.audio("jump", "shattered_sword_assets/sounds/jump2.wav"); + this.load.audio("hurt", "shattered_sword_assets/sounds/hurt.wav"); + this.load.audio("die", "shattered_sword_assets/sounds/die.wav"); + this.load.audio("level_up", "shattered_sword_assets/sounds/level_up.wav"); + //神社(じんじゃ)祭(まつり) by Second Dimension Imagination Group + this.load.audio("level_music", "shattered_sword_assets/sounds/bgm1.mp3"); + this.load.image("knife", "shattered_sword_assets/sprites/knife.png"); + this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png"); + this.load.image("black", "shattered_sword_assets/images/black.png"); + this.load.image("poisoning", "shattered_sword_assets/images/poisoning.png"); + this.load.image("burning", "shattered_sword_assets/images/burning.png"); + this.load.image("bleeding", "shattered_sword_assets/images/bleeding.png"); + //TODO - choose spritesheet for slice - modify the slice.json + this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json"); + this.load.spritesheet("test_dummy", "shattered_sword_assets/spritesheets/test_dummy.json"); + this.enemies = new Array(); + this.battleManager = new BattleManager_1.default(); + } + unloadScene() { + this.emitter.fireEvent(GameEventType_1.GameEventType.STOP_SOUND, { key: "level_music" }); + } + startScene() { + this.add.tilemap("map", new Vec2_1.default(2, 2)); + console.log("width,height:" + this.map.width, this.map.height); + this.viewport.setBounds(0, 0, this.map.width * 32, this.map.height * 32); + this.viewport.follow(this.player); + this.playerSpawn = this.rmg.getPlayer().scale(32); + console.log(this.playerSpawn); + this.startpos = this.rmg.getPlayer().scale(32); + // Do the game level standard initializations + this.initViewport(); + this.initLayers(); + // Create the battle manager + // TODO + this.initializeWeapons(); + // Initialize the items array - this represents items that are in the game world + this.items = new Array(); + this.initPlayer(); + //subscribe to relevant events + this.subscribeToEvents(); + this.addUI(); + let startCheckPoint = this.rmg.getStartCheckPoint(); + this.startCheckPoint = this.addCheckPoint(new Vec2_1.default(startCheckPoint[0], startCheckPoint[1]), new Vec2_1.default(startCheckPoint[2], startCheckPoint[3]), "startStory", "startTimer"); + let endCheckPoint = this.rmg.getEndCheckPoint(); + this.endCheckPoint = this.addCheckPoint(new Vec2_1.default(endCheckPoint[0], endCheckPoint[1]), new Vec2_1.default(endCheckPoint[2], endCheckPoint[3]), "endStory", "nextLevel"); + // Create an enemies array + // Send the player and enemies to the battle manager + this.battleManager.setPlayers([this.player._ai]); + // Initialize all enemies + //this.initializeEnemies(); + this.battleManager.setEnemies(this.enemies.map(enemy => enemy._ai)); + let enemies = this.rmg.getEnemies(); + //may have to move this to start scene in gameLevel + this.initializeEnemies(enemies); + this.gameStateStack = new Stack_1.default(); + this.setGameState(sword_enums_1.GameState.GAMING); + InputWrapper_1.default.enableInput(); + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: "level_music", loop: true, holdReference: true }); + } + updateScene(deltaT) { + if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) { + if (this.gameStarted) { + GameLevel.gameTimer += deltaT; + this.timerLable.textColor = Color_1.default.BLACK; + } + else { + this.timerLable.textColor = Color_1.default.RED; + } + let minutes = Math.floor(GameLevel.gameTimer / 60); + if (minutes >= 10) { + this.timerLable.text = minutes.toString(); + } + else { + this.timerLable.text = "0" + minutes.toString(); + } + let seconds = Math.floor(GameLevel.gameTimer % 60); + if (seconds >= 10) { + this.timerLable.text += ":" + seconds.toString(); + } + else { + this.timerLable.text += ":0" + seconds.toString(); + } + } + // Handle events and update the UI if needed + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) { + switch (event.type) { + case sword_enums_1.Player_Events.PLAYER_COLLIDE: + let n = this.sceneGraph.getNode(event.data.get("node")); + let other = this.sceneGraph.getNode(event.data.get("other")); + if (n === this.player) { + // Node is player, other is enemy + this.handlePlayerEnemyCollision(n, other); + } + else { + // Other is player, node is balloon + this.handlePlayerEnemyCollision(other, n); + } + break; + case sword_enums_1.Player_Events.ENEMY_KILLED: + let node = this.sceneGraph.getNode(event.data.get("owner")); //get enemy id + //remove enemy from enemies + this.enemies = this.enemies.filter(item => item !== event.data.get("ai")); + this.battleManager.removeEnemy(event.data.get("ai")); + //give the player the exp value of the enemy killed + if (event.data.get("ai").exp_val !== undefined) { + this.player._ai.giveExp(event.data.get("ai").exp_val); + } + node.destroy(); //destroy enemy node + this.player._ai.enemiesKilled++; + break; + case sword_enums_1.Player_Events.GIVE_REGULAR_BUFF: + this.buffs = this.player._ai.generateRegularBuffs(); + if (this.buffs[0].string === undefined) { + this.buffLabel1.text = "\n\nIncrease " + this.buffs[0].type + "\n by " + this.buffs[0].value; + } + else { + this.buffLabel1.text = this.buffs[0].string; + } + if (this.buffs[1].string === undefined) { + this.buffLabel2.text = "\n\nIncrease " + this.buffs[1].type + "\n by " + this.buffs[1].value; + } + else { + this.buffLabel2.text = this.buffs[1].string; + } + if (this.buffs[2].string === undefined) { + this.buffLabel3.text = "\n\nIncrease " + this.buffs[2].type + "\n by " + this.buffs[2].value; + } + else { + this.buffLabel3.text = this.buffs[2].string; + } + //pause game here + this.setGameState(sword_enums_1.GameState.BUFF); + this.buffLayer.enable(); + break; + case sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF: + this.buffs = this.player._ai.generateSpecialBuffs(); + if (this.buffs[0].string === undefined) { + this.buffLabel1.text = "\n\nIncrease " + this.buffs[0].type + "\n by " + this.buffs[0].value; + } + else { + this.buffLabel1.text = this.buffs[0].string; + } + if (this.buffs[1].string === undefined) { + this.buffLabel2.text = "\n\nIncrease " + this.buffs[1].type + "\n by " + this.buffs[1].value; + } + else { + this.buffLabel2.text = this.buffs[1].string; + } + if (this.buffs[2].string === undefined) { + this.buffLabel3.text = "\n\nIncrease " + this.buffs[2].type + "\n by " + this.buffs[2].value; + } + else { + this.buffLabel3.text = this.buffs[2].string; + } + //pause game here + this.setGameState(sword_enums_1.GameState.BUFF); + this.buffLayer.enable(); + break; + case sword_enums_1.Player_Events.PLAYER_KILLED: + //respawn player if he has lives, otherwise end game + console.log("player Died"); + this.player.animation.play("DEAD", false); + InputWrapper_1.default.disableInput(); + if (this.player._ai.lives > 0) { + this.respawnPlayer(); + } + else { //no more lives + this.viewport.setZoomLevel(1); + this.sceneManager.changeToScene(GameOver_1.default, {}); + InputWrapper_1.default.enableInput(); + } + break; + case "startStory": + this.playStartStory(); + break; + case "endStory": + this.playEndStory(); + break; + case "startTimer": + this.startTimer(); + break; + case "nextLevel": + this.goToNextLevel(); + break; + } + } + else if (this.gameStateStack.peek() === sword_enums_1.GameState.BUFF) { + switch (event.type) { + case "buff1": + this.player._ai.addBuff(this.buffs[0]); + this.buffLayer.disable(); + this.setGameState(); + if (this.levelEnded) { + this.goToNextLevel(); + } + break; + case "buff2": + this.player._ai.addBuff(this.buffs[1]); + this.buffLayer.disable(); + this.setGameState(); + if (this.levelEnded) { + this.goToNextLevel(); + } + break; + case "buff3": + this.player._ai.addBuff(this.buffs[2]); + this.buffLayer.disable(); + this.setGameState(); + if (this.levelEnded) { + this.goToNextLevel(); + } + break; + } + } + if (event.type === "cheat") { + this.enableCheat(); + } + if (event.type === "MainMenu") { + this.viewport.setZoomLevel(1); + this.sceneManager.changeToScene(MainMenu_1.default, {}); + InputWrapper_1.default.enableInput(); + } + } + if (this.gameStateStack.peek() === sword_enums_1.GameState.STORY) { + if (InputWrapper_1.default.isNextJustPressed() && this.gameStateStack.peek() === sword_enums_1.GameState.STORY) { + this.updateStory(); + } + } + if (InputWrapper_1.default.isPauseJustPressed()) { + this.pauseText.text = this.player._ai.toString(); + if (this.gameStateStack.peek() === sword_enums_1.GameState.GAMING) { + this.setGameState(sword_enums_1.GameState.PAUSE); + this.pauseLayer.enable(); + } + else if (this.gameStateStack.peek() === sword_enums_1.GameState.PAUSE) { + this.setGameState(); + this.pauseLayer.disable(); + } + } + if (InputWrapper_1.default.isBuff1JustPresed()) { + this.emitter.fireEvent("buff1"); + } + if (InputWrapper_1.default.isBuff2JustPresed()) { + this.emitter.fireEvent("buff2"); + } + if (InputWrapper_1.default.isBuff3JustPresed()) { + this.emitter.fireEvent("buff3"); + } + //update health UI + let playerAI = this.player.ai; + this.healthLabel.text = "Health: " + Math.round(playerAI.CURRENT_HP) + '/' + Math.round(playerAI.MAX_HP); + this.healthBar.size.set(playerAI.MAX_HP * 1.5, 10); + this.healthBar.position.set(playerAI.MAX_HP * 0.75 + 20, 20); + this.healthBar.fillWidth = playerAI.CURRENT_HP * 1.5; + if (playerAI.CURRENT_HP / playerAI.MAX_HP >= 2 / 3) { + this.healthBar.color = Color_1.default.GREEN; + this.healthLabel.textColor = Color_1.default.GREEN; + } + else if (playerAI.CURRENT_HP / playerAI.MAX_HP >= 1 / 3) { + this.healthBar.color = Color_1.default.YELLOW; + this.healthLabel.textColor = Color_1.default.YELLOW; + } + else { + this.healthBar.color = Color_1.default.RED; + this.healthLabel.textColor = Color_1.default.RED; + } + // this.healthLabel.sizeToText(); + //update shield ui + this.shieldLabel.text = "Shield: " + Math.round(playerAI.CURRENT_SHIELD) + '/' + Math.round(playerAI.MAX_SHIELD); + this.shieldBar.size.set(playerAI.CURRENT_SHIELD * 1.5, 10); + this.shieldBar.position.set(playerAI.CURRENT_SHIELD * 0.75 + 20, 50); + // this.shieldLabel.sizeToText(); + //update exp ui + this.expLabel.text = "EXP: " + Math.round(playerAI.CURRENT_EXP) + '/' + Math.round(playerAI.MAX_EXP); + this.expBar.fillWidth = (playerAI.CURRENT_EXP / playerAI.MAX_EXP) * 150; + // this.expLabel.sizeToText(); + //update level ui + this.playerLevelLabel.text = "Lv." + playerAI.level; + //update lives ui + this.livesCountLabel.text = "Lives: " + playerAI.lives; + //move background + // Get the viewport center and padded size + const viewportCenter = this.viewport.getCenter().clone(); + const baseViewportSize = this.viewport.getHalfSize().scaled(2); + //check position of player + this.playerFalloff(viewportCenter, baseViewportSize); + } + // TODO put UI changes in here + setGameState(gameState) { + if (gameState) { + this.gameStateStack.push(gameState); + InputWrapper_1.default.setState(gameState); + } + else { + this.gameStateStack.pop(); + InputWrapper_1.default.setState(this.gameStateStack.peek()); + } + } + /** + * Initialzes the layers + */ + initLayers() { + // Add a layer for UI + this.addUILayer("UI"); + // Add a layer for players and enemies + this.addLayer("primary", 1); + this.buffLayer = this.addUILayer("buffLayer"); + this.storyLayer = this.addUILayer("story"); + this.storyLayer.disable(); + this.pauseLayer = this.addUILayer("pause"); + this.pauseLayer.disable(); + this.receiver.subscribe("loadStory"); + } + /** + * Initializes the viewport + */ + initViewport() { + this.viewport.setZoomLevel(2); + } + /** + * Handles all subscriptions to events + */ + subscribeToEvents() { + this.receiver.subscribe([ + sword_enums_1.Player_Events.PLAYER_COLLIDE, + sword_enums_1.Player_Events.PLAYER_HIT_ENEMY, + sword_enums_1.Player_Events.ENEMY_KILLED, + sword_enums_1.Player_Events.LEVEL_START, + sword_enums_1.Player_Events.LEVEL_END, + sword_enums_1.Player_Events.PLAYER_KILLED, + sword_enums_1.Player_Events.GIVE_REGULAR_BUFF, + sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF + ]); + this.receiver.subscribe("buff1"); + this.receiver.subscribe("buff2"); + this.receiver.subscribe("buff3"); + this.receiver.subscribe("cheat"); + this.receiver.subscribe("startStory"); + this.receiver.subscribe("startTimer"); + this.receiver.subscribe("endStory"); + this.receiver.subscribe("nextLevel"); + this.receiver.subscribe("MainMenu"); + } + // TODO - + /** + * Adds in any necessary UI to the game + */ + addUI() { + // In-game labels + this.healthLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, 35), text: "Player Health: " + this.player.ai.CURRENT_HP }); + this.healthLabel.size.set(200, 50); + this.healthLabel.setHAlign(Label_1.HAlign.LEFT); + this.healthLabel.textColor = Color_1.default.GREEN; + this.healthLabel.font = "PixelSimple"; + this.healthLabel.fontSize = 25; + this.healthBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(0, 0), size: new Vec2_1.default(0, 0) }); + this.healthBar.borderColor = Color_1.default.BLACK; + this.healthBar.borderWidth = 3; + this.healthBar.color = Color_1.default.GREEN; + // this.poisonStat = this.add.sprite("poisoning", "UI"); + // this.poisonStat.position.set(55, 25); + // this.poisonStat.scale.set(0.3, 0.3); + // this.burnStat = this.add.sprite("burning", "UI"); + // this.burnStat.position.set(70, 25); + // this.burnStat.scale.set(0.3, 0.3); + // this.bleedStat = this.add.sprite("bleeding", "UI"); + // this.bleedStat.position.set(85, 25); + // this.bleedStat.scale.set(0.3, 0.3); + this.shieldLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, 65), text: "shield: " + this.player.ai.CURRENT_SHIELD }); + this.shieldLabel.size.set(200, 50); + this.shieldLabel.setHAlign(Label_1.HAlign.LEFT); + this.shieldLabel.textColor = Color_1.default.ORANGE; + this.shieldLabel.font = "PixelSimple"; + this.shieldLabel.fontSize = 25; + this.shieldBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(0, 0), size: new Vec2_1.default(0, 0) }); + this.shieldBar.borderColor = Color_1.default.BLACK; + this.shieldBar.borderWidth = 3; + this.shieldBar.color = Color_1.default.ORANGE; + this.playerLevelLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(20, 95), text: "Lv. " + this.player.ai.level }); + this.playerLevelLabel.size.set(0, 50); + this.playerLevelLabel.setHAlign(Label_1.HAlign.LEFT); + this.playerLevelLabel.textColor = Color_1.default.BLUE; + this.playerLevelLabel.font = "PixelSimple"; + this.playerLevelLabel.fontSize = 25; + this.expLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(100, 95), text: "EXP: " + this.player.ai.CURRENT_EXP }); + this.expLabel.size.set(200, 50); + this.expLabel.setHAlign(Label_1.HAlign.LEFT); + this.expLabel.textColor = Color_1.default.BLUE; + this.expLabel.font = "PixelSimple"; + this.expLabel.fontSize = 25; + this.expBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "UI", { position: new Vec2_1.default(95, 80), size: new Vec2_1.default(150, 10) }); + this.expBar.borderColor = Color_1.default.BLACK; + this.expBar.borderWidth = 3; + this.expBar.color = Color_1.default.BLUE; + //seed label + //worldsize.x doesnt work how i want it to + this.seedLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(70, Math.floor(this.viewport.getHalfSize().y * 2 - 30)), text: "Seed: " + InputWrapper_1.default.randomSeed }); + this.seedLabel.size.set(200, 50); + this.seedLabel.setHAlign(Label_1.HAlign.LEFT); + this.seedLabel.textColor = Color_1.default.BLACK; + this.seedLabel.font = "PixelSimple"; + this.add.sprite("black", "pause"); + this.add.sprite("black", "story"); + this.add.sprite("black", "buffLayer"); + //TODO - + //determine button location + this.buffButton1 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x * 2 / 3 - 180 / 2), Math.floor(this.viewport.getHalfSize().y)), text: "" }); + this.buffButton1.size.set(180, 200); + this.buffButton1.borderWidth = 5; + this.buffButton1.borderColor = Color_1.default.RED; + this.buffButton1.backgroundColor = Color_1.default.WHITE; + this.buffButton1.textColor = Color_1.default.BLACK; + this.buffButton1.onClickEventId = "buff1"; + this.buffButton1.fontSize = 20; + this.buffLabel1 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton1.position.x, this.buffButton1.position.y - 40), text: "buffLabel1" }); + this.buffLabel1.fontSize = 20; + this.buffButton2 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), Math.floor(this.viewport.getHalfSize().y)), text: "" }); + this.buffButton2.size.set(180, 200); + this.buffButton2.borderWidth = 5; + this.buffButton2.borderColor = Color_1.default.RED; + this.buffButton2.backgroundColor = Color_1.default.WHITE; + this.buffButton2.textColor = Color_1.default.BLACK; + this.buffButton2.onClickEventId = "buff2"; + this.buffButton2.fontSize = 20; + this.buffLabel2 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton2.position.x, this.buffButton2.position.y - 40), text: "buffLabel2" }); + this.buffLabel2.fontSize = 20; + this.buffButton3 = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "buffLayer", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x * 4 / 3 + 180 / 2), Math.floor(this.viewport.getHalfSize().y)), text: "" }); + this.buffButton3.size.set(180, 200); + this.buffButton3.borderWidth = 5; + this.buffButton3.borderColor = Color_1.default.RED; + this.buffButton3.backgroundColor = Color_1.default.WHITE; + this.buffButton3.textColor = Color_1.default.BLACK; + this.buffButton3.onClickEventId = "buff3"; + this.buffButton3.fontSize = 20; + this.buffLabel3 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "buffLayer", { position: new Vec2_1.default(this.buffButton3.position.x, this.buffButton3.position.y - 40), text: "buffLabel3" }); + this.buffLabel3.fontSize = 20; + this.buffs = this.player._ai.generateRegularBuffs(); + this.buffLayer.disable(); + this.pauseText = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 120), Math.floor(this.viewport.getHalfSize().y - 100)), text: "" }); + this.pauseInput = this.add.uiElement(UIElementTypes_1.UIElementType.TEXT_INPUT, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 20), Math.floor(this.viewport.getHalfSize().y + 100)), text: "" }); + this.pauseCheatText = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x - 120), Math.floor(this.viewport.getHalfSize().y + 80)), text: "⬇️⬇️⬇️Cheat Code⬇️⬇️⬇️" }); + this.pauseSubmit = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x + 120), Math.floor(this.viewport.getHalfSize().y + 100)), text: "Submit" }); + this.pauseLayer.setAlpha(0.5); + this.pauseText.textColor = Color_1.default.WHITE; + this.pauseText.setHAlign(Label_1.HAlign.LEFT); + this.pauseText.size = new Vec2_1.default(0, 40); + this.pauseText.text = "HP:\nATK:\nDamage Ratio:\nBuff1:\nBuff2:\nBuff3:\nBuff4:\nBuff5:\nBuff6:\nEnemy Killed:\n"; + this.pauseCheatText.textColor = Color_1.default.WHITE; + this.pauseCheatText.size = new Vec2_1.default(0, 40); + this.pauseCheatText.setHAlign(Label_1.HAlign.LEFT); + this.pauseInput.size.set(400, 30); + this.pauseSubmit.textColor = Color_1.default.BLACK; + this.pauseSubmit.borderColor = Color_1.default.BLACK; + this.pauseSubmit.backgroundColor = Color_1.default.WHITE; + this.pauseSubmit.onClickEventId = "cheat"; + this.pauseSubmit.borderWidth = 3; + this.mainMenuButton = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "pause", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), Math.floor(this.viewport.getHalfSize().y + 140)), text: "Main Menu" }); + this.mainMenuButton.size.set(180, 100); + this.mainMenuButton.borderWidth = 5; + this.mainMenuButton.borderColor = Color_1.default.BLACK; + this.mainMenuButton.backgroundColor = Color_1.default.WHITE; + this.mainMenuButton.textColor = Color_1.default.BLACK; + this.mainMenuButton.onClickEventId = "MainMenu"; + this.mainMenuButton.fontSize = 20; + this.livesCountLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(this.viewport.getHalfSize().x * 2 - 100, 30), text: "Lives: " }); + this.livesCountLabel.textColor = Color_1.default.YELLOW; + this.livesCountLabel.fontSize = 25; + this.timerLable = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "UI", { position: new Vec2_1.default(Math.floor(this.viewport.getHalfSize().x), 30), text: "00:00" }); + this.timerLable.fontSize = 60; + } + //TODO - determine whether we will have weapon datatype + /** + * + * Creates and returns a new weapon + * @param type The weaponType of the weapon, as a string + */ + createWeapon(type) { + let weaponType = RegistryManager_1.default.getRegistry("weaponTypes").get(type); + let sprite = this.add.sprite(weaponType.spriteKey, "primary"); + return new Weapon_1.default(sprite, weaponType, this.battleManager); + } + /** + * Initalizes all weapon types based of data from weaponData.json + */ + initializeWeapons() { + let weaponData = this.load.getObject("weaponData"); + for (let i = 0; i < weaponData.numWeapons; i++) { + let weapon = weaponData.weapons[i]; + // Get the constructor of the prototype + let constr = RegistryManager_1.default.getRegistry("weaponTemplates").get(weapon.weaponType); + // Create a weapon type + let weaponType = new constr(); + // Initialize the weapon type + weaponType.initialize(weapon); + // Register the weapon type + RegistryManager_1.default.getRegistry("weaponTypes").registerItem(weapon.name, weaponType); + } + } + /** + * Initializes the player + */ + initPlayer() { + //create the inventory + let inventory = new InventoryManager_1.default(this, 1, "inventorySlot", new Vec2_1.default(16, 16), 4, "slots1", "items1"); + //add starting weapon to inventory + let startingWeapon = this.createWeapon("knife"); + inventory.addItem(startingWeapon); //using slice to test right now + // Add the player + this.player = this.add.animatedSprite("player", "primary"); + this.player.scale.set(1, 1); + if (!this.playerSpawn) { + console.warn("Player spawn was never set - setting spawn to (0, 0)"); + this.playerSpawn = Vec2_1.default.ZERO; + } + this.startpos = this.playerSpawn; + this.player.position.copy(this.playerSpawn); + this.player.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, new Vec2_1.default(14, 16))); //sets the collision shape + this.player.colliderOffset.set(0, 16); + this.player.addAI(PlayerController_1.default, { + playerType: "platformer", + tilemap: "Main", + speed: 100, + health: 10, + inventory: inventory, + items: this.items, + inputEnabled: false, + range: 100 + }); + this.player.setGroup("player"); + this.viewport.follow(this.player); + } + //TODO - + /** + * Adds an Enemy into the game + * @param spriteKey The key of the Enemy sprite + * @param tilePos The tilemap position to add the Enemy to + * @param aiOptions The options for the Enemy AI + */ + addEnemy(spriteKey, tilePos, ai, aiOptions) { + let enemy = this.add.animatedSprite(spriteKey, "primary"); + //enemy.position.set(tilePos.x*32, tilePos.y*32); + enemy.position.copy(tilePos); + if ("scale" in aiOptions) { + enemy.scale.set(aiOptions.scale, aiOptions.scale); + } + else { + enemy.scale.set(2, 2); + } + //TODO - add custom collision shape for each enemy in an option variable + if ("size" in aiOptions) { + enemy.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, aiOptions.size.clone())); + } + else { + enemy.addPhysics(new AABB_1.default(Vec2_1.default.ZERO, new Vec2_1.default(16, 25))); + } + if ("offset" in aiOptions) { + enemy.colliderOffset.set(aiOptions.offset.x, aiOptions.offset.y); + } + else { + enemy.colliderOffset.set(0, 6); + } + enemy.addAI(ai, aiOptions); //TODO - add individual enemy AI + enemy._ai.healthBar = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "primary", { position: enemy.collisionShape.center.clone().add(new Vec2_1.default(0, -(enemy.collisionShape.hh + 5))), size: new Vec2_1.default(enemy.collisionShape.hw * 3, 5) }); + enemy._ai.healthBar.borderColor = Color_1.default.BLACK; + enemy._ai.healthBar.borderWidth = 1; + enemy._ai.healthBar.color = Color_1.default.GREEN; + enemy._ai.poisonStat = this.add.sprite("poisoning", "primary"); + enemy._ai.poisonStat.position = enemy.collisionShape.center.clone().add(new Vec2_1.default(((enemy.collisionShape.hw) * -1, -(enemy.collisionShape.hh + 5)))); + enemy._ai.poisonStat.scale.set(1, 1); + enemy._ai.burnStat = this.add.sprite("burning", "primary"); + enemy._ai.burnStat.position = enemy._ai.poisonStat.position.clone().add(new Vec2_1.default(15, 0)); + enemy._ai.burnStat.scale.set(1, 1); + enemy._ai.bleedStat = this.add.sprite("bleeding", "primary"); + enemy._ai.bleedStat.position = enemy._ai.poisonStat.position.clone().add(new Vec2_1.default(30, 0)); + enemy._ai.bleedStat.scale.set(1, 1); + enemy.setGroup("Enemy"); + enemy.setTrigger("player", sword_enums_1.Player_Events.PLAYER_COLLIDE, null); + //add enemy to the enemy array + this.enemies.push(enemy); + //this.battleManager.setEnemies(this.enemies.map(enemy => enemy._ai)); + this.battleManager.addEnemy(enemy._ai); + } + //TODO - give each enemy unique weapon + initializeEnemies(enemies) { + for (let enemy of enemies) { + switch (enemy.type) { + case "Snake": //Snake enemies drop from sky("trees")? or could just be very abundant + this.addEnemy("Snake", enemy.position.scale(32), SnakeAI_1.default, { + player: this.player, + health: 50, + tilemap: "Main", + size: new Vec2_1.default(14, 10), + offset: new Vec2_1.default(0, 22), + exp: 50, + }); + break; + case "Tiger": //Tiger can be miniboss for now? + this.addEnemy("Tiger", enemy.position.scale(32), EnemyAI_1.default, { + player: this.player, + health: 200, + tilemap: "Main", + exp: 100, + }); + break; + case "remus_werewolf": + this.addEnemy("remus_werewolf", enemy.position.scale(32), EnemyAI_1.default, { + player: this.player, + health: 200, + tilemap: "Main", + exp: 50, + }); + break; + case "black_pudding": + this.addEnemy("black_pudding", enemy.position.scale(32), SlimeAI_1.default, { + player: this.player, + health: 200, + tilemap: "Main", + //actions:actions, + scale: .25, + size: new Vec2_1.default(16, 10), + offset: new Vec2_1.default(0, 6), + exp: 50, + weapon: this.createWeapon("knife"), + }); + break; + default: + break; + } + } + } + addCheckPoint(startingTile, size, enter, exit) { + let checkPoint = this.add.graphic(GraphicTypes_1.GraphicType.RECT, "primary", { position: startingTile.scale(32), size: size.scale(32) }); + checkPoint.addPhysics(undefined, undefined, false, true); + checkPoint.setTrigger("player", enter, null); + checkPoint.color = new Color_1.default(0, 0, 0, 0); + return checkPoint; + } + /** + * damages the player if they collide with an enemy + * @param player player sprite + * @param enemy enemy sprite + */ + handlePlayerEnemyCollision(player, enemy) { + if (enemy === undefined) { + console.log("undefined enemy"); + return; + } + if (player === undefined) { + console.log("undefined player"); + return; + } + if (typeof enemy != undefined && typeof player != undefined) { + //damage the player + enemy._ai.collideWithPlayer(this.player._ai); + } + } + /** + * Increments the amount of life the player has + * @param amt The amount to add to the player life + */ + /* + protected incPlayerLife(amt: number): void { + GameLevel.livesCount += amt; + this.livesCountLabel.text = "Lives: " + GameLevel.livesCount; + if (GameLevel.livesCount === 0){ + InputWrapper.disableInput(); + this.player.disablePhysics(); + this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "player_death", loop: false, holdReference: false}); + this.player.tweens.play("death"); + } + } + */ + /** + * Returns the player to spawn + */ + respawnPlayer() { + InputWrapper_1.default.enableInput(); + this.player.position.copy(this.startpos); + this.player._ai.CURRENT_HP = this.player._ai.MAX_HP; + //(this.player._ai).lives --; + } + /** + * + * handles the player falling off the map + * + * @param viewportCenter The center of the viewport + * @param viewportSize The size of the viewport + */ + playerFalloff(viewportCenter, viewportSize) { + if (this.player.position.y >= viewportCenter.y + viewportSize.y / 2.0) { + this.player.position.set(this.playerSpawn.x, this.playerSpawn.y); + //TODO - decrease player health or can kill player here + //(this.player._ai).CURRENT_HP *= .75; + //this.emitter.fireEvent(Player_Events.PLAYER_KILLED); + } + } + playStartStory() { + if (!this.touchedStartCheckPoint) { + this.touchedStartCheckPoint = true; + this.storyLoader("shattered_sword_assets/jsons/story.json"); + this.startTimer(); + } + } + playEndStory() { + if (!this.touchedEndCheckPoint) { + this.touchedEndCheckPoint = true; + this.storyLoader("shattered_sword_assets/jsons/story.json"); + this.endTimer(); + this.levelEnded = true; + } + } + startTimer() { + this.gameStarted = true; + } + endTimer() { + this.gameStarted = false; + } + goToNextLevel() { + // this.sceneManager.changeToScene(Porcelain); + } + storyLoader(storyPath) { + return __awaiter(this, void 0, void 0, function* () { + if (this.gameStateStack.peek() === sword_enums_1.GameState.STORY) { + return; + } + this.setGameState(sword_enums_1.GameState.STORY); + const response = yield (yield fetch(storyPath)).json(); + this.story = response; + console.log("story:", this.story); + if (this.story.bgm) { + this.storyBGMs = new Array; + this.story.bgm.forEach((bgm) => { + if (this.load.getAudio(bgm.key)) { + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: bgm.key, loop: false, holdReference: true }); + } + else { + this.load.singleAudio(bgm.key, bgm.path, () => { + this.emitter.fireEvent(GameEventType_1.GameEventType.PLAY_SOUND, { key: bgm.key, loop: false, holdReference: true }); + }); + } + this.storyBGMs.push(bgm.key); + }); + } + this.currentSpeaker = this.story.texts[0].speaker; + this.currentContent = this.story.texts[0].content; + this.storyLayer.enable(); + this.storytextLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "story", { position: new Vec2_1.default(50, this.viewport.getHalfSize().y + 80), text: "" }); + this.storytextLabel.size = new Vec2_1.default(0, 25); + this.storytextLabel.textColor = Color_1.default.WHITE; + this.storytextLabel.font = "PixelSimple"; + this.storytextLabel.fontSize = 25; + this.storytextLabel.setHAlign(Label_1.HAlign.LEFT); + this.storyProgress = -1; + this.storySprites = new Array; + this.updateStory(); + }); + } + hasNextStory() { + return this.gameStateStack.peek() === sword_enums_1.GameState.STORY && this.storyProgress + 1 < this.story.texts.length; + } + updateStory() { + if (this.hasNextStory()) { + this.storyProgress++; + let tmp = undefined; + if (this.story.texts[this.storyProgress].actions) { + this.story.texts[this.storyProgress].actions.forEach(action => { + switch (action.type) { + case "loadSprite": + if (this.load.getImage(action.key)) { + tmp = this.add.sprite(action.key, "story"); + tmp.position.set(action.positon[0], action.positon[1]); + tmp.scale.set(action.scale[0], action.scale[1]); + this.storySprites.push(tmp); + } + else { + this.load.singleImage(action.key, action.path, () => { + tmp = this.add.sprite(action.key, "story"); + tmp.position.set(action.positon[0], action.positon[1]); + tmp.scale.set(action.scale[0], action.scale[1]); + this.storySprites.push(tmp); + }); + } + break; + case "moveSprite": + tmp = this.storySprites.find(function (sprite) { + return sprite.imageId === action.key; + }); + tmp.position.set(action.positon[0], action.positon[1]); + tmp.scale.set(action.scale[0], action.scale[1]); + break; + case "showSprite": + tmp = this.storySprites.find(function (sprite) { + return sprite.imageId === action.key; + }); + tmp.visible = true; + break; + case "hideSprite": + tmp = this.storySprites.find(function (sprite) { + return sprite.imageId === action.key; + }); + tmp.visible = false; + break; + default: + break; + } + }); + } + this.currentSpeaker = this.story.texts[this.storyProgress].speaker; + this.currentContent = this.story.texts[this.storyProgress].content; + this.storytextLabel.text = (this.currentSpeaker ? (this.currentSpeaker + ":") : ("")) + '\n' + this.currentContent; + } + else { + this.setGameState(); + this.storyProgress = Infinity; + this.storytextLabel.destroy(); + if (this.storySprites) { + this.storySprites.forEach((sprite) => { + sprite.visible = false; + sprite.destroy(); + }); + } + if (this.storyBGMs) { + this.storyBGMs.forEach((bgm) => { + this.emitter.fireEvent(GameEventType_1.GameEventType.STOP_SOUND, { key: bgm }); + console.log("sound stopped:", bgm); + }); + } + this.storyLayer.disable(); + this.storyBGMs = undefined; + this.storySprites = undefined; + this.story = undefined; + this.storytextLabel = undefined; + // this.storyLayer = undefined; + if (this.levelEnded) { + this.emitter.fireEvent(sword_enums_1.Player_Events.GIVE_SPECIAL_BUFF, {}); + } + } + } + // Cheat + enableCheat() { + if (this.pauseInput.text.toUpperCase() === "UUDDLRLRBABA") { + this.player._ai.godMode = true; + } + else { + let commands = this.pauseInput.text.split(' '); + console.log(commands); + if (commands.length === 3) { + if (commands[0].toUpperCase() === "SET") { + switch (commands[1].toUpperCase()) { + case "ATK": + this.player._ai.CURRENT_ATK = parseInt(commands[2]); + break; + case "HP": + this.player._ai.CURRENT_HP = parseInt(commands[2]); + break; + case "EXP": + this.player._ai.CURRENT_EXP = parseInt(commands[2]); + break; + case "SLD": + this.player._ai.CURRENT_SHIELD = parseInt(commands[2]); + break; + default: + break; + } + } + } + this.player._ai.godMode = false; + } + this.pauseInput.text = ""; + } +} +exports.default = GameLevel; +// Labels for the UI +//TODO - lives here or in playercontroller +GameLevel.livesCount = 3; +GameLevel.gameTimer = 0; + +},{"../../Wolfie2D/DataTypes/Shapes/AABB":16,"../../Wolfie2D/DataTypes/Stack":19,"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Events/GameEventType":30,"../../Wolfie2D/Nodes/Graphics/GraphicTypes":42,"../../Wolfie2D/Nodes/UIElements/Label":53,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Registry/RegistryManager":65,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../AI/EnemyAI":106,"../AI/SlimeAI":113,"../AI/SnakeAI":114,"../GameSystems/BattleManager":115,"../GameSystems/InventoryManager":116,"../GameSystems/items/Weapon":118,"../Player/PlayerController":121,"../Tools/InputWrapper":140,"../sword_enums":144,"./GameOver":132,"./MainMenu":135}],132:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes"); +const Scene_1 = require("../../Wolfie2D/Scene/Scene"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +const sword_enums_1 = require("../sword_enums"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +const MainMenu_1 = require("./MainMenu"); +class GameOver extends Scene_1.default { + startScene() { + InputWrapper_1.default.setState(sword_enums_1.GameState.PAUSE); + const center = this.viewport.getCenter(); + this.addUILayer("primary"); + const gameOver = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "primary", { position: new Vec2_1.default(center.x, center.y), text: "YOU DIED" }); + gameOver.textColor = Color_1.default.RED; + gameOver.fontSize = 100; + const hint = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "primary", { position: new Vec2_1.default(center.x, center.y + 100), text: "Click to go back to Main Menu" }); + hint.textColor = Color_1.default.WHITE; + } + updateScene() { + if (InputWrapper_1.default.isLeftMouseJustPressed()) { + this.sceneManager.changeToScene(MainMenu_1.default); + } + } +} +exports.default = GameOver; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"../sword_enums":144,"./MainMenu":135}],133:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator"); +const GameLevel_1 = require("./GameLevel"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +class Greatwall extends GameLevel_1.default { + loadScene() { + super.loadScene(); + this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/greatwall_template.json", InputWrapper_1.default.randomSeed); + this.map = this.rmg.getMap(); + console.log(this.map); + this.load.tilemapFromObject("map", this.map); + //load enemies + //can load enemy sprite here + //sprites obtained from cse380 sprite wesbite + // this.load.spritesheet("black_pudding","shattered_sword_assets/spritesheets/black_pudding.json"); + //load music here + } +} +exports.default = Greatwall; + +},{"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131}],134:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Scene_1 = require("../../Wolfie2D/Scene/Scene"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +const MainMenu_1 = require("./MainMenu"); +const Tutorial_1 = require("./Tutorial"); +const Porcelain_1 = require("./Porcelain"); +const Greatwall_1 = require("./Greatwall"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +class Levels extends Scene_1.default { + // TODO + loadScene() { } + startScene() { + const center = this.viewport.getCenter(); + // The main menu + this.primary = this.addUILayer("primary"); + const tutorial = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y - 100), text: "Start Game" }); + tutorial.size.set(200, 50); + tutorial.borderWidth = 2; + tutorial.borderColor = Color_1.default.WHITE; + tutorial.backgroundColor = Color_1.default.TRANSPARENT; + tutorial.onClickEventId = "start"; + const porcelain = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y), text: "porcelain(Test)" }); + porcelain.size.set(200, 50); + porcelain.borderWidth = 2; + porcelain.borderColor = Color_1.default.WHITE; + porcelain.backgroundColor = Color_1.default.TRANSPARENT; + porcelain.onClickEventId = "porcelain"; + const greatwall = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 100), text: "greatwall(Test)" }); + greatwall.size.set(200, 50); + greatwall.borderWidth = 2; + greatwall.borderColor = Color_1.default.WHITE; + greatwall.backgroundColor = Color_1.default.TRANSPARENT; + greatwall.onClickEventId = "greatwall"; + const back = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "primary", { position: new Vec2_1.default(center.x, center.y + 200), text: "Back" }); + back.size.set(200, 50); + back.borderWidth = 2; + back.borderColor = Color_1.default.WHITE; + back.backgroundColor = Color_1.default.TRANSPARENT; + back.onClickEventId = "back"; + this.receiver.subscribe("start"); + this.receiver.subscribe("porcelain"); + this.receiver.subscribe("greatwall"); + this.receiver.subscribe("back"); + } + updateScene() { + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + console.log(event); + if (event.type === "start") { + InputWrapper_1.default.randomSeed = Math.floor(Math.random() * 10000000000).toString(); + ; + let sceneOptions = { + physics: { + groupNames: ["ground", "player", "enemies"], + collisions: [ + [0, 1, 1], + [1, 0, 0], + [1, 0, 0] + ] + } + }; + this.sceneManager.changeToScene(Tutorial_1.default, {}, sceneOptions); + } + if (event.type === "porcelain") { + let sceneOptions = { + physics: { + groupNames: ["ground", "player", "enemies"], + collisions: [ + [0, 1, 1], + [1, 0, 0], + [1, 0, 0] + ] + } + }; + this.sceneManager.changeToScene(Porcelain_1.default, {}, sceneOptions); + } + if (event.type === "greatwall") { + let sceneOptions = { + physics: { + groupNames: ["ground", "player", "enemies"], + collisions: [ + [0, 1, 1], + [1, 0, 0], + [1, 0, 0] + ] + } + }; + this.sceneManager.changeToScene(Greatwall_1.default, {}, sceneOptions); + } + if (event.type === "back") { + this.sceneManager.changeToScene(MainMenu_1.default, {}); + } + } + } +} +exports.default = Levels; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/InputWrapper":140,"./Greatwall":133,"./MainMenu":135,"./Porcelain":136,"./Tutorial":138}],135:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Scene_1 = require("../../Wolfie2D/Scene/Scene"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +const Levels_1 = require("./Levels"); +const GameLevel_1 = require("./GameLevel"); +class MainMenu extends Scene_1.default { + // private rmg: RandomMapGenerator; + loadScene() { + // Load the menu song + //this.load.audio("menu", "shattered_sword_assets/music/menu.mp3"); + } + //TODO + startScene() { + GameLevel_1.default.gameTimer = 0; + const center = this.viewport.getCenter(); + // The main menu + this.mainMenu = this.addUILayer("mainMenu"); + // Add map button, and give it an event to emit on press + const map = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y - 100), text: "Map" }); + map.size.set(200, 50); + map.borderWidth = 2; + map.borderColor = Color_1.default.WHITE; + map.backgroundColor = Color_1.default.TRANSPARENT; + map.onClickEventId = "map"; + // Add about button + const about = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y + 100), text: "About" }); + about.size.set(200, 50); + about.borderWidth = 2; + about.borderColor = Color_1.default.WHITE; + about.backgroundColor = Color_1.default.TRANSPARENT; + about.onClickEventId = "about"; + // Add about button + const form = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y + 200), text: "Google Form" }); + form.size.set(200, 50); + form.borderWidth = 2; + form.borderColor = Color_1.default.WHITE; + form.backgroundColor = Color_1.default.TRANSPARENT; + form.onClick = function () { + window.open("https://forms.gle/Ku7RmUdNn7b9m5ch6"); + }; + // Add control button, and give it an event to emit on press + const control = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "mainMenu", { position: new Vec2_1.default(center.x, center.y), text: "Controls" }); + control.size.set(200, 50); + control.borderWidth = 2; + control.borderColor = Color_1.default.WHITE; + control.backgroundColor = Color_1.default.TRANSPARENT; + control.onClickEventId = "control"; + /* ########## ABOUT SCREEN ########## */ + this.about = this.addUILayer("about"); + this.about.setHidden(true); + const aboutHeader = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y - 250), text: "About" }); + aboutHeader.textColor = Color_1.default.WHITE; + const text1 = "This game was created by Henry Chen, Kelly Peng, and Renge"; + const text2 = "using the Wolfie2D game engine, a TypeScript game engine created by"; + const text3 = "Joe Weaver and Richard McKenna."; + const line1 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y - 50), text: text1 }); + const line2 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y), text: text2 }); + const line3 = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "about", { position: new Vec2_1.default(center.x, center.y + 50), text: text3 }); + line1.textColor = Color_1.default.WHITE; + line2.textColor = Color_1.default.WHITE; + line3.textColor = Color_1.default.WHITE; + const aboutBack = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "about", { position: new Vec2_1.default(center.x, center.y + 250), text: "Back" }); + aboutBack.size.set(200, 50); + aboutBack.borderWidth = 2; + aboutBack.borderColor = Color_1.default.WHITE; + aboutBack.backgroundColor = Color_1.default.TRANSPARENT; + aboutBack.onClickEventId = "menu"; + // Subscribe to the button events + this.receiver.subscribe("map"); + this.receiver.subscribe("about"); + this.receiver.subscribe("menu"); + this.receiver.subscribe("control"); + //Control screen + this.control = this.addUILayer("control"); + this.control.setHidden(true); + const header = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 250), text: "Controls" }); + header.textColor = Color_1.default.WHITE; + const lc = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 150), text: "A/D - Move Left/Right" }); + lc.textColor = Color_1.default.WHITE; + const rc = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 100), text: "W/S - Look Up/Down" }); + rc.textColor = Color_1.default.WHITE; + const wasd = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y - 50), text: "J/Z/Enter - Confirm Attack" }); + wasd.textColor = Color_1.default.WHITE; + const e = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y), text: "SPACE/X - Jump" }); + e.textColor = Color_1.default.WHITE; + const q = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 50), text: "K/C - Dash" }); + q.textColor = Color_1.default.WHITE; + const oneTwo = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 100), text: "L/V - Use Skill" }); + oneTwo.textColor = Color_1.default.WHITE; + const zx = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 150), text: "I/B - open Backpack" }); + zx.textColor = Color_1.default.WHITE; + const tb = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "control", { position: new Vec2_1.default(center.x, center.y + 200), text: "ESC - Pause" }); + tb.textColor = Color_1.default.WHITE; + const back = this.add.uiElement(UIElementTypes_1.UIElementType.BUTTON, "control", { position: new Vec2_1.default(center.x, center.y + 300), text: "Back" }); + back.size.set(200, 50); + back.borderWidth = 2; + back.borderColor = Color_1.default.WHITE; + back.backgroundColor = Color_1.default.TRANSPARENT; + back.onClickEventId = "menu"; + } + unloadScene() { + // The scene is being destroyed, so we can stop playing the song + //this.emitter.fireEvent(GameEventType.STOP_SOUND, {key: "menu"}); + } + updateScene() { + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + console.log(event); + if (event.type === "map") { + this.sceneManager.changeToScene(Levels_1.default, {}); + } + if (event.type === "about") { + this.about.setHidden(false); + this.mainMenu.setHidden(true); + } + if (event.type === "menu") { + this.mainMenu.setHidden(false); + this.about.setHidden(true); + this.control.setHidden(true); + } + if (event.type === "control") { + this.mainMenu.setHidden(true); + this.control.setHidden(false); + } + } + } +} +exports.default = MainMenu; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"./GameLevel":131,"./Levels":134}],136:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator"); +const GameLevel_1 = require("./GameLevel"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +class Porcelain extends GameLevel_1.default { + loadScene() { + super.loadScene(); + this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/porcelain_template.json", InputWrapper_1.default.randomSeed); + this.map = this.rmg.getMap(); + console.log(this.map); + this.load.tilemapFromObject("map", this.map); + // //load enemies + // this.load.spritesheet("Snake","shattered_sword_assets/spritesheets/Snake.json"); + // this.load.spritesheet("Tiger","shattered_sword_assets/spritesheets/Tiger.json"); + // //can load enemy sprite here + // //sprites obtained from cse380 sprite wesbite + // this.load.spritesheet("remus_werewolf","shattered_sword_assets/spritesheets/remus_werewolf.json"); + // this.load.spritesheet("black_pudding","shattered_sword_assets/spritesheets/black_pudding.json"); + //load music here + } +} +exports.default = Porcelain; + +},{"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131}],137:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Scene_1 = require("../../Wolfie2D/Scene/Scene"); +const ConfigManager_1 = require("../Tools/ConfigManager"); +const SaveManager_1 = require("../Tools/SaveManager"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const UIElementTypes_1 = require("../../Wolfie2D/Nodes/UIElements/UIElementTypes"); +const Color_1 = require("../../Wolfie2D/Utils/Color"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +const MainMenu_1 = require("./MainMenu"); +class SplashScreen extends Scene_1.default { + loadScene() { + //load images + this.load.image("backgroundImage", "shattered_sword_assets/images/logo.png"); + this.load.image("logo", "shattered_sword_assets/images/brown.png"); + // Load the menu song + //this.load.audio("menu", "assets/music/menu.mp3"); + } + //TODO + startScene() { + this.config = new ConfigManager_1.default(); + this.save = new SaveManager_1.default(); + // Scene has started, so start playing music + //this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "menu", loop: true, holdReference: true}); + const center = this.viewport.getCenter(); + let size = this.viewport.getHalfSize(); + this.viewport.setFocus(size); + this.viewport.setZoomLevel(1); + let backgroundLayer = this.addUILayer("background"); + backgroundLayer.setDepth(0); + let frontLayer = this.addUILayer("frontground"); + frontLayer.setDepth(1); + this.clickLabel = this.add.uiElement(UIElementTypes_1.UIElementType.LABEL, "frontground", { position: new Vec2_1.default(size.x, size.y + 300), text: "\"Click anywhere to start\"" }); + this.clickLabel.textColor = new Color_1.default(0, 0, 0, 1); + this.clickLabel.font = "Arial"; + this.clickLabel.fontSize = 70; + let background = this.add.sprite("backgroundImage", "background"); + background.position.set(size.x, size.y); + let logo = this.add.sprite("logo", "frontground"); + logo.position.set(size.x, size.y + 20); + logo.scale.set(4, 4); + } + unloadScene() { + // The scene is being destroyed, so we can stop playing the song + //this.emitter.fireEvent(GameEventType.STOP_SOUND, {key: "menu"}); + } + updateScene() { + if (InputWrapper_1.default.isLeftMouseJustPressed()) { //if left click + this.sceneManager.changeToScene(MainMenu_1.default, {}, {}); + } + while (this.receiver.hasNextEvent()) { + let event = this.receiver.getNextEvent(); + console.log(event); + if (InputWrapper_1.default.isLeftMouseJustPressed()) { //if left click + this.sceneManager.changeToScene(MainMenu_1.default, {}, {}); + } + } + } +} +exports.default = SplashScreen; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../../Wolfie2D/Nodes/UIElements/UIElementTypes":56,"../../Wolfie2D/Scene/Scene":90,"../../Wolfie2D/Utils/Color":99,"../Tools/ConfigManager":139,"../Tools/InputWrapper":140,"../Tools/SaveManager":143,"./MainMenu":135}],138:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +const RandomMapGenerator_1 = require("../Tools/RandomMapGenerator"); +const GameLevel_1 = require("./GameLevel"); +const SnakeAI_1 = require("../AI/SnakeAI"); +const Porcelain_1 = require("./Porcelain"); +const InputWrapper_1 = require("../Tools/InputWrapper"); +class Tutorial extends GameLevel_1.default { + loadScene() { + super.loadScene(); + this.rmg = new RandomMapGenerator_1.default("shattered_sword_assets/jsons/forest_template.json", InputWrapper_1.default.randomSeed); + this.map = this.rmg.getMap(); + this.load.tilemapFromObject("map", this.map); + //load enemies + this.load.spritesheet("Snake", "shattered_sword_assets/spritesheets/Snake.json"); + this.load.spritesheet("Tiger", "shattered_sword_assets/spritesheets/Tiger.json"); + //can load enemy sprite here + //sprites obtained from cse380 sprite wesbite + this.load.spritesheet("remus_werewolf", "shattered_sword_assets/spritesheets/remus_werewolf.json"); + this.load.spritesheet("black_pudding", "shattered_sword_assets/spritesheets/black_pudding.json"); + //load music here + } + updateScene(deltaT) { + super.updateScene(deltaT); + //spawn snake() + if (Math.random() < .0001 && this.gameStarted) { + console.log("RANDOM SNAKE!"); + this.addEnemy("Snake", this.player.position.clone().add(new Vec2_1.default(0, -320)), SnakeAI_1.default, { + player: this.player, + health: 50, + tilemap: "Main", + size: new Vec2_1.default(14, 10), + offset: new Vec2_1.default(0, 22), + exp: 50, + }); + } + } + goToNextLevel() { + this.viewport.setZoomLevel(1); + this.sceneManager.changeToScene(Porcelain_1.default); + } + playStartStory() { + if (!this.touchedStartCheckPoint) { + this.touchedStartCheckPoint = true; + this.storyLoader("shattered_sword_assets/jsons/level1story.json"); + this.startTimer(); + } + } +} +exports.default = Tutorial; + +},{"../../Wolfie2D/DataTypes/Vec2":24,"../AI/SnakeAI":114,"../Tools/InputWrapper":140,"../Tools/RandomMapGenerator":142,"./GameLevel":131,"./Porcelain":136}],139:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const LocalStorageDB_1 = require("./LocalStorageDB"); +class ConfigManager { + constructor() { + this.db = new LocalStorageDB_1.default("config"); + this.loadConfig(); + if (!ConfigManager.config) + this.initConfig(); + } + getVolume() { + return ConfigManager.config.volume; + } + setVolume(volume) { + ConfigManager.config.volume = volume; + this.saveConfig(); + } + // TODOs + // add more functions if needed + resetConfig(callback) { + this.initConfig(); + callback(ConfigManager.config); + } + loadConfig() { + ConfigManager.config = this.db.loadJSON(); + } + saveConfig() { + this.db.saveJSON(ConfigManager.config); + } + initConfig() { + this.db.readJSON("shattered_sword_assets/jsons/sampleconfig.json", (config) => { + if (!config) + throw new Error("Fail to load config file"); + ConfigManager.config = config; + console.log("Initializing Local Storage(config): ", ConfigManager.config); + this.saveConfig(); + }); + } +} +exports.default = ConfigManager; + +},{"./LocalStorageDB":141}],140:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Input_1 = require("../../Wolfie2D/Input/Input"); +const sword_enums_1 = require("../sword_enums"); +class InputWrapper { + static isUpPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isPressed("up")) { + return true; + } + return false; + } + static isDownPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isPressed("down")) { + return true; + } + return false; + } + static isLeftPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isPressed("left")) { + return true; + } + return false; + } + static isRightPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isPressed("right")) { + return true; + } + return false; + } + static isJumpJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isJustPressed("jump")) { + return true; + } + return false; + } + /** + * Returns whether or not the attack key is currently pressed + * @returns True if the attack key is pressed, false otherwise + */ + static isAttackJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isJustPressed("attack")) { + return true; + } + return false; + } + static isDashJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isJustPressed("dash")) { + return true; + } + return false; + } + static isSkillJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isJustPressed("skill")) { + return true; + } + return false; + } + static isInventoryJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING) { + return false; + } + if (Input_1.default.isJustPressed("inventory")) { + return true; + } + return false; + } + static isBuff1JustPresed() { + if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) { + return false; + } + return Input_1.default.isJustPressed("buff1"); + } + static isBuff2JustPresed() { + if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) { + return false; + } + return Input_1.default.isJustPressed("buff2"); + } + static isBuff3JustPresed() { + if (InputWrapper.gameState != sword_enums_1.GameState.BUFF) { + return false; + } + return Input_1.default.isJustPressed("buff3"); + } + static isPauseJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.GAMING && InputWrapper.gameState != sword_enums_1.GameState.PAUSE) { + return false; + } + if (Input_1.default.isJustPressed("pause")) { + return true; + } + return false; + } + static isNextJustPressed() { + if (InputWrapper.gameState != sword_enums_1.GameState.STORY) { + return false; + } + if (Input_1.default.isJustPressed("attack") || Input_1.default.isMouseJustPressed()) { + return true; + } + return false; + } + static isLeftMouseJustPressed() { + return Input_1.default.isMouseJustPressed(0); + } + static disableInput() { + Input_1.default.disableInput(); + } + static enableInput() { + Input_1.default.enableInput(); + } + // DO NOT call this function directly + static setState(gameState) { + InputWrapper.gameState = gameState; + } + static getState() { + return InputWrapper.gameState; + } +} +exports.default = InputWrapper; +InputWrapper.gameState = sword_enums_1.GameState.GAMING; + +},{"../../Wolfie2D/Input/Input":32,"../sword_enums":144}],141:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class LocalStorageDB { + constructor(key) { + this.key = key; + } + /** + * Read a json file from a path + * @param JSONFilePath The path to the JSON file + * @param callback Function to run after getting the JSON + */ + readJSON(JSONFilePath, callback) { + let xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/json"); + xobj.open('GET', JSONFilePath, false); + // xobj.onreadystatechange = function () { + // if ((xobj.readyState == 4) && (xobj.status == 200)) { + // callback(JSON.parse(xobj.responseText)); + // } + // }; + xobj.send(null); + callback(JSON.parse(xobj.responseText)); + } + loadJSON() { + return JSON.parse(localStorage.getItem(this.key)); + } + saveJSON(value) { + localStorage.setItem(this.key, JSON.stringify(value)); + } +} +exports.default = LocalStorageDB; + +},{}],142:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Enemy = void 0; +const TiledData_1 = require("../../Wolfie2D/DataTypes/Tilesets/TiledData"); +const Vec2_1 = require("../../Wolfie2D/DataTypes/Vec2"); +class RandomMapGenerator { + constructor(JSONFilePath, seed) { + let xhr = new XMLHttpRequest(); + xhr.overrideMimeType("application/json"); + xhr.open('GET', JSONFilePath, false); + xhr.send(null); + this.template = JSON.parse(xhr.responseText); + this.roomWithLeftEntrance = new Array(); + this.roomWithRightEntrance = new Array(); + this.roomWithUpEntrance = new Array(); + this.roomWithDownEntrance = new Array(); + this.minX = this.minY = this.maxX = this.maxY = + this.roomWithLeftEntranceWeight = this.roomWithRightEntranceWeight = + this.roomWithUpEntranceWeight = this.roomWithDownEntranceWeight = 0; + this.map = new TiledData_1.TiledTilemapData(); + this.rooms = new Array(); + this.enemies = new Array(); + this.player = new Vec2_1.default(); + this.startCheckPoint = [0, 0, 0, 0]; + this.endCheckPoint = [0, 0, 0, 0]; + let gen = require('random-seed'); + this.gen = new gen(seed); + this.hasExit = false; + this.minRoom = this.template.minroom; + this.roomPlaced = 0; + this.exitFacing = this.getEntranceFacing(this.template.exit.entrances[0], this.template.exit.width); + for (let room of this.template.rooms) { + let left = false, right = false, up = false, down = false; + for (let entrance of room.entrances) { + let facing = this.getEntranceFacing(entrance, room.width); + switch (facing) { + case Facing.LEFT: + left = true; + break; + case Facing.RIGHT: + right = true; + break; + case Facing.UP: + up = true; + break; + case Facing.DOWN: + down = true; + break; + default: + break; + } + } + if (left) { + this.roomWithLeftEntrance.push(room); + this.roomWithLeftEntranceWeight += room.weight; + } + if (right) { + this.roomWithRightEntrance.push(room); + this.roomWithRightEntranceWeight += room.weight; + } + if (up) { + this.roomWithUpEntrance.push(room); + this.roomWithUpEntranceWeight += room.weight; + } + if (down) { + this.roomWithDownEntrance.push(room); + this.roomWithDownEntranceWeight += room.weight; + } + } + } + getMap() { + let room = this.copyRoom(this.template.entrance, 0, 0); + let facing = this.getEntranceFacing(this.template.entrance.entrances[0], this.template.entrance.width); + let position = new Vec2_1.default(this.template.entrance.entrances[0].x, this.template.entrance.entrances[0].y); + // this.removeEntrance(room, this.template.entrance.entrances[0], facing); + this.rooms.push(room); + this.putNextRoom(position, this.getOppositeFacing(facing)); + if (!this.hasExit) + throw new Error("Fail to generate a map with exit!"); + this.fillData(); + console.log("Generated map:", this.map); + return this.map; + } + getPlayer() { + return new Vec2_1.default(this.player.x - this.minX, this.player.y - this.minY); + } + getStartCheckPoint() { + return [this.startCheckPoint[0] - this.minX, this.startCheckPoint[1] - this.minY, this.startCheckPoint[2], this.startCheckPoint[3]]; + } + getEndCheckPoint() { + return [this.endCheckPoint[0] - this.minX, this.endCheckPoint[1] - this.minY, this.endCheckPoint[2], this.endCheckPoint[3]]; + } + getEnemies() { + return this.enemies; + } + putNextRoom(position, facing) { + switch (facing) { + case Facing.LEFT: + position.x += 1; + break; + case Facing.RIGHT: + position.x -= 1; + break; + case Facing.UP: + position.y += 1; + break; + case Facing.DOWN: + position.y -= 1; + break; + default: + break; + } + if (this.roomPlaced >= this.minRoom && facing == this.exitFacing && !this.hasExit) { + this.putExitRoom(position); + return true; + } + let nextRoom = this.getRandomRoom(facing); + let nextPosition = undefined; + let thisEntrance = undefined; + for (let entrance of nextRoom.entrances) { + if (this.getEntranceFacing(entrance, nextRoom.width) == facing) { + let tmpPosition = new Vec2_1.default(position.x - entrance.x, position.y - entrance.y); + if (this.isValidRoom(tmpPosition, new Vec2_1.default(tmpPosition.x + nextRoom.width - 1, tmpPosition.y + nextRoom.height - 1))) { + thisEntrance = entrance; + nextPosition = tmpPosition; + } + } + } + if (!thisEntrance) { + if (!this.hasExit) { + throw new Error("Wrong order in map template" + facing); + } + return false; + } + let room = this.copyRoom(nextRoom, nextPosition.x, nextPosition.y); + this.removeEntrance(room, thisEntrance, facing); + this.rooms.push(room); + this.roomPlaced += 1; + if (this.hasExit && this.gen.random() <= 0.3) { + return true; + } + for (let entrance of nextRoom.entrances) { + if (entrance != thisEntrance) { + let facing = this.getEntranceFacing(entrance, nextRoom.width); + let position = new Vec2_1.default(nextPosition.x + entrance.x, nextPosition.y + entrance.y); + if (this.putNextRoom(position, this.getOppositeFacing(facing))) { + this.removeEntrance(room, entrance, facing); + } + } + } + return true; + } + putExitRoom(position) { + position = new Vec2_1.default(position.x - this.template.exit.entrances[0].x, position.y - this.template.exit.entrances[0].y); + if (!this.isValidRoom(position, new Vec2_1.default(position.x + this.template.exit.width - 1, position.y + this.template.exit.height - 1))) { + throw new Error("Cannot put exit room!!! Position is invalid!!! Please check order of entrances in map template."); + } + let room = this.copyRoom(this.template.exit, position.x, position.y); + this.rooms.push(room); + this.hasExit = true; + } + removeEntrance(room, entrance, facing) { + let width = room.bottomRight.x - room.topLeft.x + 1; + if (facing == Facing.LEFT || facing == Facing.RIGHT) { + for (let index = 0; index < entrance.width; index++) + room.topLayer[(entrance.y + index) * width + entrance.x] = 0; + if (entrance.y > 0) + room.topLayer[(entrance.y - 1) * width + entrance.x] = entrance.alt_tile[0]; + if (entrance.y + entrance.width <= (room.bottomRight.y - room.topLeft.y)) + room.topLayer[(entrance.y + entrance.width) * width + entrance.x] = entrance.alt_tile[1]; + } + else { + for (let index = 0; index < entrance.width; index++) + room.topLayer[(entrance.y) * width + entrance.x + index] = 0; + if (entrance.x > 0) + room.topLayer[(entrance.y) * width + entrance.x - 1] = entrance.alt_tile[0]; + if (entrance.x + entrance.width <= (room.bottomRight.x - room.topLeft.x)) + room.topLayer[(entrance.y) * width + entrance.x + entrance.width] = entrance.alt_tile[1]; + } + } + fillData() { + let width = this.maxX - this.minX + 1; + let height = this.maxY - this.minY + 1; + this.map.layers = new Array(2); + this.map.layers[0] = new TiledData_1.TiledLayerData; + this.map.layers[1] = new TiledData_1.TiledLayerData; + this.map.width = this.map.layers[0].width = this.map.layers[1].width = width; + this.map.height = this.map.layers[0].height = this.map.layers[1].height = height; + this.map.tileheight = this.template.tileheight; + this.map.tilewidth = this.template.tilewidth; + this.map.orientation = "orthogonal"; + this.map.layers[0].x = this.map.layers[0].y = this.map.layers[1].x = this.map.layers[1].y = 0; + this.map.layers[0].opacity = this.map.layers[1].opacity = 1; + this.map.layers[0].visible = this.map.layers[1].visible = true; + this.map.layers[0].type = this.map.layers[1].type = "tilelayer"; + this.map.layers[0].name = "Floor"; + this.map.layers[1].name = "Wall"; + this.map.layers[0].properties = [{ + name: "Collidable", + type: "bool", + value: false + }]; + this.map.layers[1].properties = [{ + name: "Collidable", + type: "bool", + value: true + }]; + this.map.tilesets = [{ + columns: this.template.columns, + tilewidth: this.template.tilewidth, + tileheight: this.template.tileheight, + tilecount: this.template.tilecount, + firstgid: this.template.firstgid, + imageheight: this.template.imageheight, + imagewidth: this.template.imagewidth, + margin: this.template.margin, + spacing: this.template.spacing, + name: this.template.name, + image: this.template.image + }]; + this.map.layers[0].data = new Array(width * height).fill(this.template.background); + this.map.layers[1].data = new Array(width * height); + for (let room of this.rooms) { + let roomWidth = room.bottomRight.x - room.topLeft.x + 1; + let roomHeight = room.bottomRight.y - room.topLeft.y + 1; + room.topLeft.x -= this.minX; + room.topLeft.y -= this.minY; + for (let i = 0; i < roomHeight; i++) + for (let j = 0; j < roomWidth; j++) { + this.map.layers[0].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.bottomLayer[i * roomWidth + j]; + this.map.layers[1].data[(room.topLeft.y + i) * width + room.topLeft.x + j] = room.topLayer[i * roomWidth + j]; + } + if (room.enemies) + for (let enemy of room.enemies) { + enemy.position.x += room.topLeft.x; + enemy.position.y += room.topLeft.y; + this.enemies.push(enemy); + } + } + } + isValidRoom(topLeft, bottomRight) { + for (let room of this.rooms) { + if (room.topLeft.x <= bottomRight.x && + room.bottomRight.x >= topLeft.x && + room.topLeft.y <= bottomRight.y && + room.bottomRight.y >= topLeft.y) { + console.warn("Found an invalid room! TopLeft:", topLeft.toString(), "BottomRight:", bottomRight.toString()); + return false; + } + } + return true; + } + getEntranceFacing(entrance, width) { + if (entrance.x === 0) + return Facing.LEFT; + else if (entrance.x === width - 1) + return Facing.RIGHT; + else if (entrance.y === 0) + return Facing.UP; + return Facing.DOWN; + } + getOppositeFacing(facing) { + switch (facing) { + case Facing.LEFT: + return Facing.RIGHT; + case Facing.RIGHT: + return Facing.LEFT; + case Facing.UP: + return Facing.DOWN; + case Facing.DOWN: + return Facing.UP; + } + } + getRandomRoom(facing) { + let array = this.getRoomArray(facing), weight = this.getRoomWeight(facing); + let value = this.gen(weight); + if (value >= weight) + throw new Error("Random number " + value + " is larger than total weight " + weight); + for (let room of array) { + if (value < room.weight) + return room; + value -= room.weight; + } + throw new Error("Cannot find Room! \nValue: " + value + "\nRooms: " + JSON.stringify(array)); + } + getRoomArray(facing) { + switch (facing) { + case Facing.LEFT: + return this.roomWithLeftEntrance; + case Facing.RIGHT: + return this.roomWithRightEntrance; + case Facing.UP: + return this.roomWithUpEntrance; + case Facing.DOWN: + return this.roomWithDownEntrance; + } + } + getRoomWeight(facing) { + switch (facing) { + case Facing.LEFT: + return this.roomWithLeftEntranceWeight; + case Facing.RIGHT: + return this.roomWithRightEntranceWeight; + case Facing.UP: + return this.roomWithUpEntranceWeight; + case Facing.DOWN: + return this.roomWithDownEntranceWeight; + } + } + copyRoom(old, posX, posY) { + let room = new Room(); + room.topLeft = new Vec2_1.default(posX, posY); + room.bottomRight = new Vec2_1.default(posX + old.width - 1, posY + old.height - 1); + room.topLayer = [...old.topLayer]; + room.bottomLayer = [...old.bottomLayer]; + room.enemies = new Array(); + if (old.sprites) { + for (let sprite of old.sprites) { + if (sprite.type === 'player') { + this.player.x = sprite.x + posX; + this.player.y = sprite.y + posY; + } + else { + if (this.gen.random() <= sprite.possibility) { + let tmp = new Enemy(); + tmp.type = sprite.type; + tmp.position = new Vec2_1.default(sprite.x, sprite.y); + room.enemies.push(tmp); + } + } + } + } + if (old.startCheckPoint) { + this.startCheckPoint = [...old.startCheckPoint]; + this.startCheckPoint[0] += posX; + this.startCheckPoint[1] += posY; + } + if (old.endCheckPoint) { + this.endCheckPoint = [...old.endCheckPoint]; + this.endCheckPoint[0] += posX; + this.endCheckPoint[1] += posY; + } + if (posX < this.minX) + this.minX = posX; + if (posY < this.minY) + this.minY = posY; + if (posX + old.width - 1 > this.maxX) + this.maxX = posX + old.width - 1; + if (posY + old.height - 1 > this.maxY) + this.maxY = posY + old.height - 1; + return room; + } +} +exports.default = RandomMapGenerator; +class Room { +} +class Enemy { +} +exports.Enemy = Enemy; +var Facing; +(function (Facing) { + Facing["LEFT"] = "left"; + Facing["RIGHT"] = "right"; + Facing["UP"] = "up"; + Facing["DOWN"] = "down"; +})(Facing || (Facing = {})); + +},{"../../Wolfie2D/DataTypes/Tilesets/TiledData":22,"../../Wolfie2D/DataTypes/Vec2":24,"random-seed":2}],143:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const LocalStorageDB_1 = require("./LocalStorageDB"); +class SaveManager { + constructor() { + this.db = new LocalStorageDB_1.default("save"); + this.loadSave(); + if (!SaveManager.save) + this.initSave(); + } + getLevel() { + return SaveManager.save.level; + } + setLevel(level) { + SaveManager.save.level = level; + this.saveSave(); + } + getName() { + return SaveManager.save.name; + } + setName(name) { + SaveManager.save.name = name; + this.saveSave(); + } + // TODOs + // add more functions if needed + resetSave(callback) { + this.initSave(); + callback(SaveManager.save); + } + loadSave() { + SaveManager.save = this.db.loadJSON(); + } + saveSave() { + this.db.saveJSON(SaveManager.save); + } + initSave() { + this.db.readJSON("shattered_sword_assets/jsons/samplesave.json", (save) => { + if (!save) + throw new Error("Fail to load save file"); + SaveManager.save = save; + console.log("Initializing Local Storage(save): ", SaveManager.save); + this.saveSave(); + }); + } +} +exports.default = SaveManager; + +},{"./LocalStorageDB":141}],144:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GameState = exports.Statuses = exports.Damage_Type = exports.Player_Events = void 0; +var Player_Events; +(function (Player_Events) { + Player_Events["PLAYER_MOVE"] = "PlayerMove"; + Player_Events["PLAYER_JUMP"] = "PlayerJump"; + Player_Events["PLAYER_ATTACK"] = "PlayerAttack"; + Player_Events["PLAYER_DASH"] = "PlayerDash"; + Player_Events["PLAYER_HEAL"] = "PlayerHeal"; + Player_Events["LEVEL_START"] = "LevelStart"; + Player_Events["LEVEL_END"] = "LevelEnd"; + Player_Events["PLAYER_KILLED"] = "PlayerKilled"; + Player_Events["ENEMY_KILLED"] = "EnemyKilled"; + Player_Events["PLAYER_HIT_ENEMY"] = "PlayerHitEnemy"; + Player_Events["BOSS_KILLED"] = "BossKilled"; + Player_Events["GIVE_REGULAR_BUFF"] = "GiveRegularBuff"; + Player_Events["GIVE_SPECIAL_BUFF"] = "GiveSpecialBuff"; + Player_Events["PLAYER_COLLIDE"] = "PlayerCollide"; +})(Player_Events = exports.Player_Events || (exports.Player_Events = {})); +var Damage_Type; +(function (Damage_Type) { + Damage_Type["NORMAL_DAMAGE"] = "NormalDamage"; + Damage_Type["ENVIRONMENT_DAMAGE"] = "EnvironmentDamage"; + Damage_Type["DOT_DAMAGE"] = "DOTDamage"; +})(Damage_Type = exports.Damage_Type || (exports.Damage_Type = {})); +var Statuses; +(function (Statuses) { + Statuses["IN_RANGE"] = "IN_RANGE"; + Statuses["LOW_HEALTH"] = "LOW_HEALTH"; + Statuses["CAN_RETREAT"] = "CAN_RETREAT"; + Statuses["REACHED_GOAL"] = "GOAL"; + Statuses["CAN_BERSERK"] = "CAN_BERSERK"; +})(Statuses = exports.Statuses || (exports.Statuses = {})); +var GameState; +(function (GameState) { + GameState["GAMING"] = "gaming"; + GameState["STORY"] = "story"; + GameState["BUFF"] = "buff"; + GameState["PAUSE"] = "pause"; +})(GameState = exports.GameState || (exports.GameState = {})); + +},{}]},{},[105]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvanNvbi1zdHJpbmdpZnktc2FmZS9zdHJpbmdpZnkuanMiLCJub2RlX21vZHVsZXMvcmFuZG9tLXNlZWQvaW5kZXguanMiLCJzcmMvV29sZmllMkQvQUkvQUlNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL0FJL1N0YXRlTWFjaGluZUFJLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9GdW5jdGlvbnMvTnVsbEZ1bmMudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL0dyYXBocy9FZGdlTm9kZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9HcmFwaHMvUG9zaXRpb25HcmFwaC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvSW50ZXJmYWNlcy9SZWdpb24udHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL01hcC50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvTWF0NHg0LnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9QaHlzaWNzL0FyZWFDb2xsaXNpb24udHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1BoeXNpY3MvSGl0LnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9RdWV1ZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvUmVuZGVyaW5nL1dlYkdMUHJvZ3JhbVR5cGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQ2lyY2xlLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvU2hhcGUudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1N0YWNrLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZS50cyIsInNyYy9Xb2xmaWUyRC9EYXRhVHlwZXMvU3RhdGUvU3RhdGVNYWNoaW5lLnRzIiwic3JjL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGEudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXQudHMiLCJzcmMvV29sZmllMkQvRGF0YVR5cGVzL1ZlYzIudHMiLCJzcmMvV29sZmllMkQvRGVidWcvRGVidWcudHMiLCJzcmMvV29sZmllMkQvRGVidWcvU3RhdHMudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0VtaXR0ZXIudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0V2ZW50UXVldWUudHMiLCJzcmMvV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudC50cyIsInNyYy9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZS50cyIsInNyYy9Xb2xmaWUyRC9FdmVudHMvUmVjZWl2ZXIudHMiLCJzcmMvV29sZmllMkQvSW5wdXQvSW5wdXQudHMiLCJzcmMvV29sZmllMkQvSW5wdXQvSW5wdXRIYW5kbGVyLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvRW52aXJvbm1lbnRJbml0aWFsaXplci50cyIsInNyYy9Xb2xmaWUyRC9Mb29wL0ZpeGVkVXBkYXRlR2FtZUxvb3AudHMiLCJzcmMvV29sZmllMkQvTG9vcC9HYW1lLnRzIiwic3JjL1dvbGZpZTJEL0xvb3AvR2FtZUxvb3AudHMiLCJzcmMvV29sZmllMkQvTG9vcC9HYW1lT3B0aW9ucy50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9DYW52YXNOb2RlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWMudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvR3JhcGhpY1R5cGVzLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL0dyYXBoaWNzL0xpbmUudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUGFydGljbGUudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUG9pbnQudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUmVjdC50cyIsInNyYy9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1RpbGVtYXAudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVGlsZW1hcHMvT3J0aG9nb25hbFRpbGVtYXAudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50LnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uLnRzIiwic3JjL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWwudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9TbGlkZXIudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9UZXh0SW5wdXQudHMiLCJzcmMvV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9VSUVsZW1lbnRUeXBlcy50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aC50cyIsInNyYy9Xb2xmaWUyRC9QYXRoZmluZGluZy9OYXZtZXNoLnRzIiwic3JjL1dvbGZpZTJEL1BoeXNpY3MvQmFzaWNQaHlzaWNzTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9QaHlzaWNzL1BoeXNpY3NNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1BsYXliYWNrL1JlY29yZGVyLnRzIiwic3JjL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvUmVnaXN0cnkudHMiLCJzcmMvV29sZmllMkQvUmVnaXN0cnkvUmVnaXN0cmllcy9TaGFkZXJSZWdpc3RyeS50cyIsInNyYy9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvQW5pbWF0aW9uTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQW5pbWF0aW9ucy9BbmltYXRpb25UeXBlcy50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQW5pbWF0aW9ucy9QYXJ0aWNsZVN5c3RlbU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0FuaW1hdGlvbnMvVHdlZW5Db250cm9sbGVyLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9BbmltYXRpb25zL1R3ZWVuTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvQ2FudmFzUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9HcmFwaGljUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9UaWxlbWFwUmVuZGVyZXIudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmluZy9VSUVsZW1lbnRSZW5kZXJlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvUmVuZGVyaW5nTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJlci50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvTGFiZWxTaGFkZXJUeXBlLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9Qb2ludFNoYWRlclR5cGUudHMiLCJzcmMvV29sZmllMkQvUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1F1YWRTaGFkZXJUeXBlLnRzIiwic3JjL1dvbGZpZTJEL1JlbmRlcmluZy9XZWJHTFJlbmRlcmluZy9TaGFkZXJUeXBlcy9SZWN0U2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvU3ByaXRlU2hhZGVyVHlwZS50cyIsInNyYy9Xb2xmaWUyRC9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0ZhY3Rvcmllcy9DYW52YXNOb2RlRmFjdG9yeS50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9GYWN0b3JpZXMvRmFjdG9yeU1hbmFnZXIudHMiLCJzcmMvV29sZmllMkQvU2NlbmUvRmFjdG9yaWVzL1RpbGVtYXBGYWN0b3J5LnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL0xheWVycy9VSUxheWVyLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL1NjZW5lLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lL1NjZW5lTWFuYWdlci50cyIsInNyYy9Xb2xmaWUyRC9TY2VuZS9TY2VuZU9wdGlvbnMudHMiLCJzcmMvV29sZmllMkQvU2NlbmVHcmFwaC9TY2VuZUdyYXBoLnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lR3JhcGgvU2NlbmVHcmFwaEFycmF5LnRzIiwic3JjL1dvbGZpZTJEL1NjZW5lR3JhcGgvVmlld3BvcnQudHMiLCJzcmMvV29sZmllMkQvU291bmQvQXVkaW9NYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1RpbWluZy9UaW1lci50cyIsInNyYy9Xb2xmaWUyRC9UaW1pbmcvVGltZXJNYW5hZ2VyLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL0NvbG9yLnRzIiwic3JjL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvR3JhcGhVdGlscy50cyIsInNyYy9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvUmVuZGVyaW5nVXRpbHMudHMiLCJzcmMvV29sZmllMkQvVXRpbHMvU3RyaW5nVXRpbHMudHMiLCJzcmMvbWFpbi50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlBSS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvQWxlcnQudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL0VuZW15U3RhdGVzL0F0dGFjay50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvRW5lbXlTdGF0ZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvUGF0cm9sLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9BSS9FbmVteVN0YXRlcy9TbGltZUF0dGFjay50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvQUkvRW5lbXlTdGF0ZXMvU25ha2VBdHRhY2sudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL1NsaW1lQUkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0FJL1NuYWtlQUkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL0JhdHRsZU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL0ludmVudG9yeU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL0l0ZW0udHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvbi50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvU2xpY2UudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGUudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJDb250cm9sbGVyLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL0ZhbGwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1BsYXllci9QbGF5ZXJTdGF0ZXMvSWRsZS50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllclN0YXRlcy9JbkFpci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvUGxheWVyL1BsYXllclN0YXRlcy9KdW1wLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL09uR3JvdW5kLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL1BsYXllclN0YXRlLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9QbGF5ZXIvUGxheWVyU3RhdGVzL1dhbGsudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1JlZ2lzdHJ5L1dlYXBvblJlZ2lzdHJ5LnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9SZWdpc3RyeS9XZWFwb25UeXBlUmVnaXN0cnkudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9HYW1lTGV2ZWwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9HYW1lT3Zlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0dyZWF0d2FsbC50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL0xldmVscy50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvU2NlbmVzL01haW5NZW51LnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvUG9yY2VsYWluLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvU3BsYXNoU2NyZWVuLnRzIiwic3JjL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvVHV0b3JpYWwudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL0NvbmZpZ01hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL0lucHV0V3JhcHBlci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvTG9jYWxTdG9yYWdlREIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL1Rvb2xzL1JhbmRvbU1hcEdlbmVyYXRvci50cyIsInNyYy9zaGF0dGVyZWRfc3dvcmQvVG9vbHMvU2F2ZU1hbmFnZXIudHMiLCJzcmMvc2hhdHRlcmVkX3N3b3JkL3N3b3JkX2VudW1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN4UUEsMENBQW1DO0FBRW5DOzs7R0FHRztBQUNILE1BQXFCLFNBQVM7SUFNN0I7UUFDQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLGFBQUcsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7O09BR0c7SUFDSCxhQUFhLENBQUMsS0FBWTtRQUN6QixJQUFJLENBQUMs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Q0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFdEMsUUFBUTtZQUNSLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFOUMsU0FBUztZQUNULElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFdEMsT0FBTztZQUNQLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFFN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3JCLENBQUMsQ0FBQTtRQUVELHdCQUF3QixDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsR0FBRyxVQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxF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QUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBQyxDQUFDLENBQUM7UUFDM00sSUFBSSxDQUFDLFVBQVUsR0FBYyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyw4QkFBYSxDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsRUFBQyxRQUFRLEVBQUUsSUFBSSxjQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBQyxDQUFDLENBQUM7UUFDcE4sSUFBSSxDQUFDLGNBQWMsR0FBVSxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyw4QkFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBQyxRQUFRLEVBQUUsSUFBSSxjQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFDLENBQUMsQ0FBQztRQUNyTyxJQUFJLENBQUMsV0FBVyxHQUFVLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLDhCQUFhLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFDLFFBQVEsRUFBRSxJQUFJ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QUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUMvQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNqRSxJQUFJLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEYsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDcEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRzthQUNJO1lBQ0QsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUMvQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNqRSxJQUFJLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEYsSUFBSSxRQUFRLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDcEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNoRztJQUNMLENBQUM7SUFFTyxRQUFRO1FBQ1osSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUN0QyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksMEJBQWMsQ0FBQztRQUN4QyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLDBCQUFjLENBQUM7UUFDeEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDN0UsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDakYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7UUFDL0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDN0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUFDO1FBQ3BDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDNUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDL0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxXQUFXLENBQUM7UUFDaEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztRQUNsQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsR0FBRyxDQUFDO2dCQUM3QixJQUFJLEVBQUUsWUFBWTtnQkFDbEIsSUFBSSxFQUFFLE1BQU07Z0JBQ1osS0FBSyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQUE7UUFDRixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEdBQUcsQ0FBQztnQkFDN0IsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLElBQUksRUFBRSxNQUFNO2dCQUNaLEtBQUssRUFBRSxJQUFJO2FBQ2QsQ0FBQyxDQUFBO1FBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsQ0FBQztnQkFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTztnQkFDOUIsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUztnQkFDbEMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVTtnQkFDcEMsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUztnQkFDbEMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUTtnQkFDaEMsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVztnQkFDdEMsVUFBVSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVTtnQkFDcEMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTTtnQkFDNUIsT0FBTyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTztnQkFDOUIsSUFBSSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSTtnQkFDeEIsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSzthQUM3QixDQUFDLENBQUE7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxLQUFLLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25GLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLEtBQUssQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUM7UUFFcEQsS0FBSyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ3pCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN4RCxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztZQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQzVCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFO2dCQUMvQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxFQUFFLENBQUMsRUFBRSxFQUFFO29CQUNoQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUNqSCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUNqSDtZQUNMLElBQUksSUFBSSxDQUFDLE9BQU87Z0JBQ1osS0FBSyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO29CQUM1QixLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztvQkFDbkMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7b0JBQ25DLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUM1QjtTQUNSO0lBQ0wsQ0FBQztJQUVPLFdBQVcsQ0FBQyxPQUFhLEVBQUUsV0FBaUI7UUFDaEQsS0FBSyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ3pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDO2dCQUMvQixJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQztnQkFDL0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLENBQUMsRUFBRTtnQkFDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsY0FBYyxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO2dCQUM1RyxPQUFPLEtBQUssQ0FBQzthQUNoQjtTQUNKO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVPLGlCQUFpQixDQUFDLFFBQWtCLEVBQUUsS0FBYTtRQUN2RCxJQUFJLFFBQVEsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUNoQixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7YUFDbEIsSUFBSSxRQUFRLENBQUMsQ0FBQyxLQUFLLEtBQUssR0FBRyxDQUFDO1lBQzdCLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQTthQUNsQixJQUFJLFFBQVEsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUNyQixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDckIsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxNQUFjO1FBQ3BDLFFBQVEsTUFBTSxFQUFFO1lBQ1osS0FBSyxNQUFNLENBQUMsSUFBSTtnQkFDWixPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDeEIsS0FBSyxNQUFNLENBQUMsS0FBSztnQkFDYixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDdkIsS0FBSyxNQUFNLENBQUMsRUFBRTtnQkFDVixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDdkIsS0FBSyxNQUFNLENBQUMsSUFBSTtnQkFDWixPQUFPLE1BQU0sQ0FBQyxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0lBRU8sYUFBYSxDQUFDLE1BQWM7UUFDaEMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMzRSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTdCLElBQUksS0FBSyxJQUFJLE1BQU07WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLGdCQUFnQixHQUFHLEtBQUssR0FBRywrQkFBK0IsR0FBRyxNQUFNLENBQUMsQ0FBQztRQUV6RixLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssRUFBRTtZQUNwQixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTTtnQkFDbkIsT0FBTyxJQUFJLENBQUM7WUFDaEIsS0FBSyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUM7U0FDeEI7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixHQUFHLEtBQUssR0FBRyxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7SUFFTyxZQUFZLENBQUMsTUFBYztRQUMvQixRQUFRLE1BQU0sRUFBRTtZQUNaLEtBQUssTUFBTSxDQUFDLElBQUk7Z0JBQ1osT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUM7WUFDckMsS0FBSyxNQUFNLENBQUMsS0FBSztnQkFDYixPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQztZQUN0QyxLQUFLLE1BQU0sQ0FBQyxFQUFFO2dCQUNWLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO1lBQ25DLEtBQUssTUFBTSxDQUFDLElBQUk7Z0JBQ1osT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUM7U0FDeEM7SUFDTCxDQUFDO0lBRU8sYUFBYSxDQUFDLE1BQWM7UUFDaEMsUUFBUSxNQUFNLEVBQUU7WUFDWixLQUFLLE1BQU0sQ0FBQyxJQUFJO2dCQUNaLE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDO1lBQzNDLEtBQUssTUFBTSxDQUFDLEtBQUs7Z0JBQ2IsT0FBTyxJQUFJLENBQUMsMkJBQTJCLENBQUM7WUFDNUMsS0FBSyxNQUFNLENBQUMsRUFBRTtnQkFDVixPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQztZQUN6QyxLQUFLLE1BQU0sQ0FBQyxJQUFJO2dCQUNaLE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDO1NBQzlDO0lBQ0wsQ0FBQztJQUVPLFFBQVEsQ0FBQyxHQUFpQixFQUFFLElBQVksRUFBRSxJQUFZO1FBQzFELElBQUksSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLGNBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLGNBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDekUsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDM0IsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFO1lBQ2IsS0FBSyxJQUFJLE1BQU0sSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFO2dCQUM1QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO29CQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztvQkFDaEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7aUJBQ25DO3FCQUNJO29CQUNELElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFO3dCQUN6QyxJQUFJLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO3dCQUN0QixHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7d0JBQ3ZCLEdBQUcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxjQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO3FCQUMxQjtpQkFDSjthQUNKO1NBQ0o7UUFDRCxJQUFJLEdBQUcsQ0FBQyxlQUFlLEVBQUU7WUFDckIsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ2hELElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO1NBQ25DO1FBQ0QsSUFBSSxHQUFHLENBQUMsYUFBYSxFQUFFO1lBQ25CLElBQUksQ0FBQyxhQUFhLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM1QyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztZQUM5QixJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQztTQUNqQztRQUNELElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJO1lBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJO1lBQ2hCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJO1lBQ2hDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJO1lBQ2pDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7Q0FDSjtBQWxaRCxxQ0FrWkM7QUFFRCxNQUFNLElBQUk7Q0FNVDtBQUVELE1BQWEsS0FBSztDQUdqQjtBQUhELHNCQUdDO0FBRUQsSUFBSyxNQUtKO0FBTEQsV0FBSyxNQUFNO0lBQ1AsdUJBQWEsQ0FBQTtJQUNiLHlCQUFlLENBQUE7SUFDZixtQkFBUyxDQUFBO0lBQ1QsdUJBQWEsQ0FBQTtBQUNqQixDQUFDLEVBTEksTUFBTSxLQUFOLE1BQU0sUUFLVjs7Ozs7QUN6YUQscURBQThDO0FBRTlDLE1BQXFCLFdBQVc7SUFJNUI7UUFDSSxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksd0JBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFaEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJO1lBQ2pCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBRUQsUUFBUTtRQUNKLE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDbEMsQ0FBQztJQUVELFFBQVEsQ0FBQyxLQUFhO1FBQ2xCLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUMvQixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELE9BQU87UUFDSCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ2pDLENBQUM7SUFFRCxPQUFPLENBQUMsSUFBWTtRQUNoQixXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDN0IsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxRQUFRO0lBQ1IsK0JBQStCO0lBRy9CLFNBQVMsQ0FBQyxRQUFtQjtRQUN6QixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDaEIsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU8sUUFBUTtRQUNaLFdBQVcsQ0FBQyxJQUFJLEdBQVMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNoRCxDQUFDO0lBRU8sUUFBUTtRQUNaLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRU8sUUFBUTtRQUNaLElBQUksQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLDhDQUE4QyxFQUFFLENBQUMsSUFBWSxFQUFFLEVBQUU7WUFDOUUsSUFBSSxDQUFDLElBQUk7Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQzlDLFdBQVcsQ0FBQyxJQUFJLEdBQVMsSUFBSSxDQUFDO1lBQzlCLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0NBQW9DLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3BFLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSjtBQXhERCw4QkF3REM7Ozs7OztBQzNERCxJQUFZLGFBZVg7QUFmRCxXQUFZLGFBQWE7SUFDckIsMkNBQTBCLENBQUE7SUFDMUIsMkNBQTBCLENBQUE7SUFDMUIsK0NBQThCLENBQUE7SUFDOUIsMkNBQTBCLENBQUE7SUFDMUIsMkNBQTBCLENBQUE7SUFDMUIsMkNBQTBCLENBQUE7SUFDMUIsdUNBQXNCLENBQUE7SUFDdEIsK0NBQThCLENBQUE7SUFDOUIsNkNBQTRCLENBQUE7SUFDNUIsb0RBQW1DLENBQUE7SUFDbkMsMkNBQTBCLENBQUE7SUFDMUIsc0RBQXFDLENBQUE7SUFDckMsc0RBQXFDLENBQUE7SUFDckMsaURBQWdDLENBQUE7QUFDcEMsQ0FBQyxFQWZXLGFBQWEsR0FBYixxQkFBYSxLQUFiLHFCQUFhLFFBZXhCO0FBQ0QsSUFBWSxXQUlYO0FBSkQsV0FBWSxXQUFXO0lBQ25CLDZDQUE4QixDQUFBO0lBQzlCLHVEQUF3QyxDQUFBO0lBQ3hDLHVDQUF3QixDQUFBO0FBQzVCLENBQUMsRUFKVyxXQUFXLEdBQVgsbUJBQVcsS0FBWCxtQkFBVyxRQUl0QjtBQUVELElBQVksUUFNWDtBQU5ELFdBQVksUUFBUTtJQUNoQixpQ0FBcUIsQ0FBQTtJQUNyQixxQ0FBeUIsQ0FBQTtJQUN6Qix1Q0FBMkIsQ0FBQTtJQUMzQixpQ0FBcUIsQ0FBQTtJQUNyQix1Q0FBMkIsQ0FBQTtBQUMvQixDQUFDLEVBTlcsUUFBUSxHQUFSLGdCQUFRLEtBQVIsZ0JBQVEsUUFNbkI7QUFFRCxJQUFZLFNBS1g7QUFMRCxXQUFZLFNBQVM7SUFDakIsOEJBQWlCLENBQUE7SUFDakIsNEJBQWUsQ0FBQTtJQUNmLDBCQUFhLENBQUE7SUFDYiw0QkFBZSxDQUFBO0FBQ25CLENBQUMsRUFMVyxTQUFTLEdBQVQsaUJBQVMsS0FBVCxpQkFBUyxRQUtwQiIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsImV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IHN0cmluZ2lmeVxuZXhwb3J0cy5nZXRTZXJpYWxpemUgPSBzZXJpYWxpemVyXG5cbmZ1bmN0aW9uIHN0cmluZ2lmeShvYmosIHJlcGxhY2VyLCBzcGFjZXMsIGN5Y2xlUmVwbGFjZXIpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgc2VyaWFsaXplcihyZXBsYWNlciwgY3ljbGVSZXBsYWNlciksIHNwYWNlcylcbn1cblxuZnVuY3Rpb24gc2VyaWFsaXplcihyZXBsYWNlciwgY3ljbGVSZXBsYWNlcikge1xuICB2YXIgc3RhY2sgPSBbXSwga2V5cyA9IFtdXG5cbiAgaWYgKGN5Y2xlUmVwbGFjZXIgPT0gbnVsbCkgY3ljbGVSZXBsYWNlciA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBpZiAoc3RhY2tbMF0gPT09IHZhbHVlKSByZXR1cm4gXCJbQ2lyY3VsYXIgfl1cIlxuICAgIHJldHVybiBcIltDaXJjdWxhciB+LlwiICsga2V5cy5zbGljZSgwLCBzdGFjay5pbmRleE9mKHZhbHVlKSkuam9pbihcIi5cIikgKyBcIl1cIlxuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBpZiAoc3RhY2subGVuZ3RoID4gMCkge1xuICAgICAgdmFyIHRoaXNQb3MgPSBzdGFjay5pbmRleE9mKHRoaXMpXG4gICAgICB+dGhpc1BvcyA/IHN0YWNrLnNwbGljZSh0aGlzUG9zICsgMSkgOiBzdGFjay5wdXNoKHRoaXMpXG4gICAgICB+dGhpc1BvcyA/IGtleXMuc3BsaWNlKHRoaXNQb3MsIEluZmluaXR5LCBrZXkpIDoga2V5cy5wdXNoKGtleSlcbiAgICAgIGlmICh+c3RhY2suaW5kZXhPZih2YWx1ZSkpIHZhbHVlID0gY3ljbGVSZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpXG4gICAgfVxuICAgIGVsc2Ugc3RhY2sucHVzaCh2YWx1ZSlcblxuICAgIHJldHVybiByZXBsYWNlciA9PSBudWxsID8gdmFsdWUgOiByZXBsYWNlci5jYWxsKHRoaXMsIGtleSwgdmFsdWUpXG4gIH1cbn1cbiIsIi8qXG4gKiByYW5kb20tc2VlZFxuICogaHR0cHM6Ly9naXRodWIuY29tL3NrcmF0Y2hkb3QvcmFuZG9tLXNlZWRcbiAqXG4gKiBUaGlzIGNvZGUgd2FzIG9yaWdpbmFsbHkgd3JpdHRlbiBieSBTdGV2ZSBHaWJzb24gYW5kIGNhbiBiZSBmb3VuZCBoZXJlOlxuICpcbiAqIGh0dHBzOi8vd3d3LmdyYy5jb20vb3RnL3VoZXBybmcuaHRtXG4gKlxuICogSXQgd2FzIHNsaWdodGx5IG1vZGlmaWVkIGZvciB1c2UgaW4gbm9kZSwgdG8gcGFzcyBqc2hpbnQsIGFuZCBhIGZldyBhZGRpdGlvbmFsXG4gKiBoZWxwZXIgZnVuY3Rpb25zIHdlcmUgYWRkZWQuXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEzIHNrcmF0Y2hkb3RcbiAqIER1YWwgTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGFuZCB0aGUgb3JpZ2luYWwgR1JDIGNvcHlyaWdodC9saWNlbnNlXG4gKiBpbmNsdWRlZCBiZWxvdy5cbiAqL1xuLypcdD09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblx0XHRcdFx0XHRcdFx0XHRcdEdpYnNvbiBSZXNlYXJjaCBDb3Jwb3JhdGlvblxuXHRcdFx0XHRVSEVQUk5HIC0gVWx0cmEgSGlnaCBFbnRyb3B5IFBzZXVkby1SYW5kb20gTnVtYmVyIEdlbmVyYXRvclxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdExJQ0VOU0UgQU5EIENPUFlSSUdIVDogIFRISVMgQ09ERSBJUyBIRVJFQlkgUkVMRUFTRUQgSU5UTyBUSEUgUFVCTElDIERPTUFJTlxuXHRHaWJzb24gUmVzZWFyY2ggQ29ycG9yYXRpb24gcmVsZWFzZXMgYW5kIGRpc2NsYWltcyBBTEwgUklHSFRTIEFORCBUSVRMRSBJTlxuXHRUSElTIENPREUgT1IgQU5ZIERFUklWQVRJVkVTLiBBbnlvbmUgbWF5IGJlIGZyZWVseSB1c2UgaXQgZm9yIGFueSBwdXJwb3NlLlxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdFRoaXMgaXMgR1JDJ3MgY3J5cHRvZ3JhcGhpY2FsbHkgc3Ryb25nIFBSTkcgKHBzZXVkby1yYW5kb20gbnVtYmVyIGdlbmVyYXRvcilcblx0Zm9yIEphdmFTY3JpcHQuIEl0IGlzIGRyaXZlbiBieSAxNTM2IGJpdHMgb2YgZW50cm9weSwgc3RvcmVkIGluIGFuIGFycmF5IG9mXG5cdDQ4LCAzMi1iaXQgSmF2YVNjcmlwdCB2YXJpYWJsZXMuICBTaW5jZSBtYW55IGFwcGxpY2F0aW9ucyBvZiB0aGlzIGdlbmVyYXRvcixcblx0aW5jbHVkaW5nIG91cnMgd2l0aCB0aGUgXCJPZmYgVGhlIEdyaWRcIiBMYXRpbiBTcXVhcmUgZ2VuZXJhdG9yLCBtYXkgcmVxdWlyZVxuXHR0aGUgZGV0ZXJpbWluaXN0aWMgcmUtZ2VuZXJhdGlvbiBvZiBhIHNlcXVlbmNlIG9mIFBSTnMsIHRoaXMgUFJORydzIGluaXRpYWxcblx0ZW50cm9waWMgc3RhdGUgY2FuIGJlIHJlYWQgYW5kIHdyaXR0ZW4gYXMgYSBzdGF0aWMgd2hvbGUsIGFuZCBpbmNyZW1lbnRhbGx5XG5cdGV2b2x2ZWQgYnkgcG91cmluZyBuZXcgc291cmNlIGVudHJvcHkgaW50byB0aGUgZ2VuZXJhdG9yJ3MgaW50ZXJuYWwgc3RhdGUuXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0RU5ETEVTUyBUSEFOS1MgYXJlIGR1ZSBKb2hhbm5lcyBCYWFnb2UgZm9yIGhpcyBjYXJlZnVsIGRldmVsb3BtZW50IG9mIGhpZ2hseVxuXHRyb2J1c3QgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbnMgb2YgSlMgUFJOR3MuICBUaGlzIHdvcmsgd2FzIGJhc2VkIHVwb24gaGlzXG5cdEphdmFTY3JpcHQgXCJBbGVhXCIgUFJORyB3aGljaCBpcyBiYXNlZCB1cG9uIHRoZSBleHRyZW1lbHkgcm9idXN0IE11bHRpcGx5LVxuXHRXaXRoLUNhcnJ5IChNV0MpIFBSTkcgaW52ZW50ZWQgYnkgR2VvcmdlIE1hcnNhZ2xpYS4gTVdDIEFsZ29yaXRobSBSZWZlcmVuY2VzOlxuXHRodHRwOi8vd3d3LkdSQy5jb20vb3RnL01hcnNhZ2xpYV9QUk5Hcy5wZGZcblx0aHR0cDovL3d3dy5HUkMuY29tL290Zy9NYXJzYWdsaWFfTVdDX0dlbmVyYXRvcnMucGRmXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0VGhlIHF1YWxpdHkgb2YgdGhpcyBhbGdvcml0aG0ncyBwc2V1ZG8tcmFuZG9tIG51bWJlcnMgaGF2ZSBiZWVuIHZlcmlmaWVkIGJ5XG5cdG11bHRpcGxlIGluZGVwZW5kZW50IHJlc2VhcmNoZXJzLiBJdCBoYW5kaWx5IHBhc3NlcyB0aGUgZmVybWlsYWIuY2ggdGVzdHMgYXNcblx0d2VsbCBhcyB0aGUgXCJkaWVoYXJkXCIgYW5kIFwiZGllaGFyZGVyXCIgdGVzdCBzdWl0ZXMuICBGb3IgaW5kaXZpZHVhbHMgd2lzaGluZ1xuXHR0byBmdXJ0aGVyIHZlcmlmeSB0aGUgcXVhbGl0eSBvZiB0aGlzIGFsZ29yaXRobSdzIHBzZXVkby1yYW5kb20gbnVtYmVycywgYVxuXHQyNTYtbWVnYWJ5dGUgZmlsZSBvZiB0aGlzIGFsZ29yaXRobSdzIG91dHB1dCBtYXkgYmUgZG93bmxvYWRlZCBmcm9tIEdSQy5jb20sXG5cdGFuZCBhIE1pY3Jvc29mdCBXaW5kb3dzIHNjcmlwdGluZyBob3N0IChXU0gpIHZlcnNpb24gb2YgdGhpcyBhbGdvcml0aG0gbWF5IGJlXG5cdGRvd25sb2FkZWQgYW5kIHJ1biBmcm9tIHRoZSBXaW5kb3dzIGNvbW1hbmQgcHJvbXB0IHRvIGdlbmVyYXRlIHVuaXF1ZSBmaWxlc1xuXHRvZiBhbnkgc2l6ZTpcblx0VGhlIEZlcm1pbGFiIFwiRU5UXCIgdGVzdHM6IGh0dHA6Ly9mb3VybWlsYWIuY2gvcmFuZG9tL1xuXHRUaGUgMjU2LW1lZ2FieXRlIHNhbXBsZSBQUk4gZmlsZSBhdCBHUkM6IGh0dHBzOi8vd3d3LkdSQy5jb20vb3RnL3VoZXBybmcuYmluXG5cdFRoZSBXaW5kb3dzIHNjcmlwdGluZyBob3N0IHZlcnNpb246IGh0dHBzOi8vd3d3LkdSQy5jb20vb3RnL3dzaC11aGVwcm5nLmpzXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0UXVhbGlmeWluZyBNV0MgbXVsdGlwbGllcnMgYXJlOiAxODc4ODQsIDY4NjExOCwgODk4MTM0LCAxMTA0Mzc1LCAxMjUwMjA1LFxuXHQxNDYwOTEwIGFuZCAxNzY4ODYzLiAoV2UgdXNlIHRoZSBsYXJnZXN0IG9uZSB0aGF0J3MgPCAyXjIxKVxuXHQ9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG4ndXNlIHN0cmljdCc7XG52YXIgc3RyaW5naWZ5ID0gcmVxdWlyZSgnanNvbi1zdHJpbmdpZnktc2FmZScpO1xuXG4vKlx0PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuVGhpcyBpcyBiYXNlZCB1cG9uIEpvaGFubmVzIEJhYWdvZSdzIGNhcmVmdWxseSBkZXNpZ25lZCBhbmQgZWZmaWNpZW50IGhhc2hcbmZ1bmN0aW9uIGZvciB1c2Ugd2l0aCBKYXZhU2NyaXB0LiAgSXQgaGFzIGEgcHJvdmVuIFwiYXZhbGFuY2hlXCIgZWZmZWN0IHN1Y2hcbnRoYXQgZXZlcnkgYml0IG9mIHRoZSBpbnB1dCBhZmZlY3RzIGV2ZXJ5IGJpdCBvZiB0aGUgb3V0cHV0IDUwJSBvZiB0aGUgdGltZSxcbndoaWNoIGlzIGdvb2QuXHRTZWU6IGh0dHA6Ly9iYWFnb2UuY29tL2VuL1JhbmRvbU11c2luZ3MvaGFzaC9hdmFsYW5jaGUueGh0bWxcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiovXG52YXIgTWFzaCA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIG4gPSAweGVmYzgyNDlkO1xuXHR2YXIgbWFzaCA9IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0aWYgKGRhdGEpIHtcblx0XHRcdGRhdGEgPSBkYXRhLnRvU3RyaW5nKCk7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0biArPSBkYXRhLmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRcdHZhciBoID0gMC4wMjUxOTYwMzI4MjQxNjkzOCAqIG47XG5cdFx0XHRcdG4gPSBoID4+PiAwO1xuXHRcdFx0XHRoIC09IG47XG5cdFx0XHRcdGggKj0gbjtcblx0XHRcdFx0biA9IGggPj4+IDA7XG5cdFx0XHRcdGggLT0gbjtcblx0XHRcdFx0biArPSBoICogMHgxMDAwMDAwMDA7IC8vIDJeMzJcblx0XHRcdH1cblx0XHRcdHJldHVybiAobiA+Pj4gMCkgKiAyLjMyODMwNjQzNjUzODY5NjNlLTEwOyAvLyAyXi0zMlxuXHRcdH0gZWxzZSB7XG5cdFx0XHRuID0gMHhlZmM4MjQ5ZDtcblx0XHR9XG5cdH07XG5cdHJldHVybiBtYXNoO1xufTtcblxudmFyIHVoZXBybmcgPSBmdW5jdGlvbiAoc2VlZCkge1xuXHRyZXR1cm4gKGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbyA9IDQ4OyAvLyBzZXQgdGhlICdvcmRlcicgbnVtYmVyIG9mIEVOVFJPUFktaG9sZGluZyAzMi1iaXQgdmFsdWVzXG5cdFx0dmFyIGMgPSAxOyAvLyBpbml0IHRoZSAnY2FycnknIHVzZWQgYnkgdGhlIG11bHRpcGx5LXdpdGgtY2FycnkgKE1XQykgYWxnb3JpdGhtXG5cdFx0dmFyIHAgPSBvOyAvLyBpbml0IHRoZSAncGhhc2UnIChtYXgtMSkgb2YgdGhlIGludGVybWVkaWF0ZSB2YXJpYWJsZSBwb2ludGVyXG5cdFx0dmFyIHMgPSBuZXcgQXJyYXkobyk7IC8vIGRlY2xhcmUgb3VyIGludGVybWVkaWF0ZSB2YXJpYWJsZXMgYXJyYXlcblx0XHR2YXIgaTsgLy8gZ2VuZXJhbCBwdXJwb3NlIGxvY2FsXG5cdFx0dmFyIGo7IC8vIGdlbmVyYWwgcHVycG9zZSBsb2NhbFxuXHRcdHZhciBrID0gMDsgLy8gZ2VuZXJhbCBwdXJwb3NlIGxvY2FsXG5cblx0XHQvLyB3aGVuIG91ciBcInVoZXBybmdcIiBpcyBpbml0aWFsbHkgaW52b2tlZCBvdXIgUFJORyBzdGF0ZSBpcyBpbml0aWFsaXplZCBmcm9tIHRoZVxuXHRcdC8vIGJyb3dzZXIncyBvd24gbG9jYWwgUFJORy4gVGhpcyBpcyBva2F5IHNpbmNlIGFsdGhvdWdoIGl0cyBnZW5lcmF0b3IgbWlnaHQgbm90XG5cdFx0Ly8gYmUgd29uZGVyZnVsLCBpdCdzIHVzZWZ1bCBmb3IgZXN0YWJsaXNoaW5nIGxhcmdlIHN0YXJ0dXAgZW50cm9weSBmb3Igb3VyIHVzYWdlLlxuXHRcdHZhciBtYXNoID0gbmV3IE1hc2goKTsgLy8gZ2V0IGEgcG9pbnRlciB0byBvdXIgaGlnaC1wZXJmb3JtYW5jZSBcIk1hc2hcIiBoYXNoXG5cblx0XHQvLyBmaWxsIHRoZSBhcnJheSB3aXRoIGluaXRpYWwgbWFzaCBoYXNoIHZhbHVlc1xuXHRcdGZvciAoaSA9IDA7IGkgPCBvOyBpKyspIHtcblx0XHRcdHNbaV0gPSBtYXNoKE1hdGgucmFuZG9tKCkpO1xuXHRcdH1cblxuXHRcdC8vIHRoaXMgUFJJVkFURSAoaW50ZXJuYWwgYWNjZXNzIG9ubHkpIGZ1bmN0aW9uIGlzIHRoZSBoZWFydCBvZiB0aGUgbXVsdGlwbHktd2l0aC1jYXJyeVxuXHRcdC8vIChNV0MpIFBSTkcgYWxnb3JpdGhtLiBXaGVuIGNhbGxlZCBpdCByZXR1cm5zIGEgcHNldWRvLXJhbmRvbSBudW1iZXIgaW4gdGhlIGZvcm0gb2YgYVxuXHRcdC8vIDMyLWJpdCBKYXZhU2NyaXB0IGZyYWN0aW9uICgwLjAgdG8gPDEuMCkgaXQgaXMgYSBQUklWQVRFIGZ1bmN0aW9uIHVzZWQgYnkgdGhlIGRlZmF1bHRcblx0XHQvLyBbMC0xXSByZXR1cm4gZnVuY3Rpb24sIGFuZCBieSB0aGUgcmFuZG9tICdzdHJpbmcobiknIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgJ24nXG5cdFx0Ly8gY2hhcmFjdGVycyBmcm9tIDMzIHRvIDEyNi5cblx0XHR2YXIgcmF3cHJuZyA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmICgrK3AgPj0gbykge1xuXHRcdFx0XHRwID0gMDtcblx0XHRcdH1cblx0XHRcdHZhciB0ID0gMTc2ODg2MyAqIHNbcF0gKyBjICogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsgLy8gMl4tMzJcblx0XHRcdHJldHVybiBzW3BdID0gdCAtIChjID0gdCB8IDApO1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIEVYUE9SVEVEIGZ1bmN0aW9uIGlzIHRoZSBkZWZhdWx0IGZ1bmN0aW9uIHJldHVybmVkIGJ5IHRoaXMgbGlicmFyeS5cblx0XHQvLyBUaGUgdmFsdWVzIHJldHVybmVkIGFyZSBpbnRlZ2VycyBpbiB0aGUgcmFuZ2UgZnJvbSAwIHRvIHJhbmdlLTEuIFdlIGZpcnN0XG5cdFx0Ly8gb2J0YWluIHR3byAzMi1iaXQgZnJhY3Rpb25zIChmcm9tIHJhd3BybmcpIHRvIHN5bnRoZXNpemUgYSBzaW5nbGUgaGlnaFxuXHRcdC8vIHJlc29sdXRpb24gNTMtYml0IHBybmcgKDAgdG8gPDEpLCB0aGVuIHdlIG11bHRpcGx5IHRoaXMgYnkgdGhlIGNhbGxlcidzXG5cdFx0Ly8gXCJyYW5nZVwiIHBhcmFtIGFuZCB0YWtlIHRoZSBcImZsb29yXCIgdG8gcmV0dXJuIGEgZXF1YWxseSBwcm9iYWJsZSBpbnRlZ2VyLlxuXHRcdHZhciByYW5kb20gPSBmdW5jdGlvbiAocmFuZ2UpIHtcblx0XHRcdHJldHVybiBNYXRoLmZsb29yKHJhbmdlICogKHJhd3BybmcoKSArIChyYXdwcm5nKCkgKiAweDIwMDAwMCB8IDApICogMS4xMTAyMjMwMjQ2MjUxNTY1ZS0xNikpOyAvLyAyXi01M1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIEVYUE9SVEVEIGZ1bmN0aW9uICdzdHJpbmcobiknIHJldHVybnMgYSBwc2V1ZG8tcmFuZG9tIHN0cmluZyBvZlxuXHRcdC8vICduJyBwcmludGFibGUgY2hhcmFjdGVycyByYW5naW5nIGZyb20gY2hyKDMzKSB0byBjaHIoMTI2KSBpbmNsdXNpdmUuXG5cdFx0cmFuZG9tLnN0cmluZyA9IGZ1bmN0aW9uIChjb3VudCkge1xuXHRcdFx0dmFyIGk7XG5cdFx0XHR2YXIgcyA9ICcnO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcblx0XHRcdFx0cyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDMzICsgcmFuZG9tKDk0KSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcztcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBQUklWQVRFIFwiaGFzaFwiIGZ1bmN0aW9uIGlzIHVzZWQgdG8gZXZvbHZlIHRoZSBnZW5lcmF0b3IncyBpbnRlcm5hbFxuXHRcdC8vIGVudHJvcHkgc3RhdGUuIEl0IGlzIGFsc28gY2FsbGVkIGJ5IHRoZSBFWFBPUlRFRCBhZGRFbnRyb3B5KCkgZnVuY3Rpb25cblx0XHQvLyB3aGljaCBpcyB1c2VkIHRvIHBvdXIgZW50cm9weSBpbnRvIHRoZSBQUk5HLlxuXHRcdHZhciBoYXNoID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG87IGorKykge1xuXHRcdFx0XHRcdHNbal0gLT0gbWFzaChhcmdzW2ldKTtcblx0XHRcdFx0XHRpZiAoc1tqXSA8IDApIHtcblx0XHRcdFx0XHRcdHNbal0gKz0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBcImNsZWFuIHN0cmluZ1wiIGZ1bmN0aW9uIHJlbW92ZXMgbGVhZGluZyBhbmQgdHJhaWxpbmcgc3BhY2VzIGFuZCBub24tcHJpbnRpbmdcblx0XHQvLyBjb250cm9sIGNoYXJhY3RlcnMsIGluY2x1ZGluZyBhbnkgZW1iZWRkZWQgY2FycmlhZ2UtcmV0dXJuIChDUikgYW5kIGxpbmUtZmVlZCAoTEYpIGNoYXJhY3RlcnMsXG5cdFx0Ly8gZnJvbSBhbnkgc3RyaW5nIGl0IGlzIGhhbmRlZC4gdGhpcyBpcyBhbHNvIHVzZWQgYnkgdGhlICdoYXNoc3RyaW5nJyBmdW5jdGlvbiAoYmVsb3cpIHRvIGhlbHBcblx0XHQvLyB1c2VycyBhbHdheXMgb2J0YWluIHRoZSBzYW1lIEVGRkVDVElWRSB1aGVwcm5nIHNlZWRpbmcga2V5LlxuXHRcdHJhbmRvbS5jbGVhblN0cmluZyA9IGZ1bmN0aW9uIChpblN0cikge1xuXHRcdFx0aW5TdHIgPSBpblN0ci5yZXBsYWNlKC8oXlxccyopfChcXHMqJCkvZ2ksICcnKTsgLy8gcmVtb3ZlIGFueS9hbGwgbGVhZGluZyBzcGFjZXNcblx0XHRcdGluU3RyID0gaW5TdHIucmVwbGFjZSgvW1xceDAwLVxceDFGXS9naSwgJycpOyAvLyByZW1vdmUgYW55L2FsbCBjb250cm9sIGNoYXJhY3RlcnNcblx0XHRcdGluU3RyID0gaW5TdHIucmVwbGFjZSgvXFxuIC8sICdcXG4nKTsgLy8gcmVtb3ZlIGFueS9hbGwgdHJhaWxpbmcgc3BhY2VzXG5cdFx0XHRyZXR1cm4gaW5TdHI7IC8vIHJldHVybiB0aGUgY2xlYW5lZCB1cCByZXN1bHRcblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBcImhhc2ggc3RyaW5nXCIgZnVuY3Rpb24gaGFzaGVzIHRoZSBwcm92aWRlZCBjaGFyYWN0ZXIgc3RyaW5nIGFmdGVyIGZpcnN0IHJlbW92aW5nXG5cdFx0Ly8gYW55IGxlYWRpbmcgb3IgdHJhaWxpbmcgc3BhY2VzIGFuZCBpZ25vcmluZyBhbnkgZW1iZWRkZWQgY2FycmlhZ2UgcmV0dXJucyAoQ1IpIG9yIExpbmUgRmVlZHMgKExGKVxuXHRcdHJhbmRvbS5oYXNoU3RyaW5nID0gZnVuY3Rpb24gKGluU3RyKSB7XG5cdFx0XHRpblN0ciA9IHJhbmRvbS5jbGVhblN0cmluZyhpblN0cik7XG5cdFx0XHRtYXNoKGluU3RyKTsgLy8gdXNlIHRoZSBzdHJpbmcgdG8gZXZvbHZlIHRoZSAnbWFzaCcgc3RhdGVcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBpblN0ci5sZW5ndGg7IGkrKykgeyAvLyBzY2FuIHRocm91Z2ggdGhlIGNoYXJhY3RlcnMgaW4gb3VyIHN0cmluZ1xuXHRcdFx0XHRrID0gaW5TdHIuY2hhckNvZGVBdChpKTsgLy8gZ2V0IHRoZSBjaGFyYWN0ZXIgY29kZSBhdCB0aGUgbG9jYXRpb25cblx0XHRcdFx0Zm9yIChqID0gMDsgaiA8IG87IGorKykgeyAvL1x0XCJtYXNoXCIgaXQgaW50byB0aGUgVUhFUFJORyBzdGF0ZVxuXHRcdFx0XHRcdHNbal0gLT0gbWFzaChrKTtcblx0XHRcdFx0XHRpZiAoc1tqXSA8IDApIHtcblx0XHRcdFx0XHRcdHNbal0gKz0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gdGhpcyBFWFBPUlRFRCBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIHNlZWQgdGhlIHJhbmRvbSBnZW5lcmF0b3IuXG5cdFx0cmFuZG9tLnNlZWQgPSBmdW5jdGlvbiAoc2VlZCkge1xuXHRcdFx0aWYgKHR5cGVvZiBzZWVkID09PSAndW5kZWZpbmVkJyB8fCBzZWVkID09PSBudWxsKSB7XG5cdFx0XHRcdHNlZWQgPSBNYXRoLnJhbmRvbSgpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHR5cGVvZiBzZWVkICE9PSAnc3RyaW5nJykge1xuXHRcdFx0XHRzZWVkID0gc3RyaW5naWZ5KHNlZWQsIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG5cdFx0XHRcdFx0aWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHRcdFx0cmV0dXJuICh2YWx1ZSkudG9TdHJpbmcoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdHJhbmRvbS5pbml0U3RhdGUoKTtcblx0XHRcdHJhbmRvbS5oYXNoU3RyaW5nKHNlZWQpO1xuXHRcdH07XG5cblx0XHQvLyB0aGlzIGhhbmR5IGV4cG9ydGVkIGZ1bmN0aW9uIGlzIHVzZWQgdG8gYWRkIGVudHJvcHkgdG8gb3VyIHVoZXBybmcgYXQgYW55IHRpbWVcblx0XHRyYW5kb20uYWRkRW50cm9weSA9IGZ1bmN0aW9uICggLyogYWNjZXB0IHplcm8gb3IgbW9yZSBhcmd1bWVudHMgKi8gKSB7XG5cdFx0XHR2YXIgYXJncyA9IFtdO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcblx0XHRcdH1cblx0XHRcdGhhc2goKGsrKykgKyAobmV3IERhdGUoKS5nZXRUaW1lKCkpICsgYXJncy5qb2luKCcnKSArIE1hdGgucmFuZG9tKCkpO1xuXHRcdH07XG5cblx0XHQvLyBpZiB3ZSB3YW50IHRvIHByb3ZpZGUgYSBkZXRlcm1pbmlzdGljIHN0YXJ0dXAgY29udGV4dCBmb3Igb3VyIFBSTkcsXG5cdFx0Ly8gYnV0IHdpdGhvdXQgZGlyZWN0bHkgc2V0dGluZyB0aGUgaW50ZXJuYWwgc3RhdGUgdmFyaWFibGVzLCB0aGlzIGFsbG93c1xuXHRcdC8vIHVzIHRvIGluaXRpYWxpemUgdGhlIG1hc2ggaGFzaCBhbmQgUFJORydzIGludGVybmFsIHN0YXRlIGJlZm9yZSBwcm92aWRpbmdcblx0XHQvLyBzb21lIGhhc2hpbmcgaW5wdXRcblx0XHRyYW5kb20uaW5pdFN0YXRlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0bWFzaCgpOyAvLyBwYXNzIGEgbnVsbCBhcmcgdG8gZm9yY2UgbWFzaCBoYXNoIHRvIGluaXRcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBvOyBpKyspIHtcblx0XHRcdFx0c1tpXSA9IG1hc2goJyAnKTsgLy8gZmlsbCB0aGUgYXJyYXkgd2l0aCBpbml0aWFsIG1hc2ggaGFzaCB2YWx1ZXNcblx0XHRcdH1cblx0XHRcdGMgPSAxOyAvLyBpbml0IG91ciBtdWx0aXBseS13aXRoLWNhcnJ5IGNhcnJ5XG5cdFx0XHRwID0gbzsgLy8gaW5pdCBvdXIgcGhhc2Vcblx0XHR9O1xuXG5cdFx0Ly8gd2UgdXNlIHRoaXMgKG9wdGlvbmFsKSBleHBvcnRlZCBmdW5jdGlvbiB0byBzaWduYWwgdGhlIEphdmFTY3JpcHQgaW50ZXJwcmV0ZXJcblx0XHQvLyB0aGF0IHdlJ3JlIGZpbmlzaGVkIHVzaW5nIHRoZSBcIk1hc2hcIiBoYXNoIGZ1bmN0aW9uIHNvIHRoYXQgaXQgY2FuIGZyZWUgdXAgdGhlXG5cdFx0Ly8gbG9jYWwgXCJpbnN0YW5jZSB2YXJpYWJsZXNcIiBpcyB3aWxsIGhhdmUgYmVlbiBtYWludGFpbmluZy4gIEl0J3Mgbm90IHN0cmljdGx5XG5cdFx0Ly8gbmVjZXNzYXJ5LCBvZiBjb3Vyc2UsIGJ1dCBpdCdzIGdvb2QgSmF2YVNjcmlwdCBjaXRpemVuc2hpcC5cblx0XHRyYW5kb20uZG9uZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdG1hc2ggPSBudWxsO1xuXHRcdH07XG5cblx0XHQvLyBpZiB3ZSBjYWxsZWQgXCJ1aGVwcm5nXCIgd2l0aCBhIHNlZWQgdmFsdWUsIHRoZW4gZXhlY3V0ZSByYW5kb20uc2VlZCgpIGJlZm9yZSByZXR1cm5pbmdcblx0XHRpZiAodHlwZW9mIHNlZWQgIT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyYW5kb20uc2VlZChzZWVkKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiAwIChpbmNsdXNpdmUpIGFuZCByYW5nZSAoZXhjbHVzaXZlKVxuXHRcdHJhbmRvbS5yYW5nZSA9IGZ1bmN0aW9uIChyYW5nZSkge1xuXHRcdFx0cmV0dXJuIHJhbmRvbShyYW5nZSk7XG5cdFx0fTtcblxuXHRcdC8vIFJldHVybnMgYSByYW5kb20gZmxvYXQgYmV0d2VlbiAwIChpbmNsdXNpdmUpIGFuZCAxIChleGNsdXNpdmUpXG5cdFx0cmFuZG9tLnJhbmRvbSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiByYW5kb20oTnVtYmVyLk1BWF9WQUxVRSAtIDEpIC8gTnVtYmVyLk1BWF9WQUxVRTtcblx0XHR9O1xuXG5cdFx0Ly8gUmV0dXJucyBhIHJhbmRvbSBmbG9hdCBiZXR3ZWVuIG1pbiAoaW5jbHVzaXZlKSBhbmQgbWF4IChleGNsdXNpdmUpXG5cdFx0cmFuZG9tLmZsb2F0QmV0d2VlbiA9IGZ1bmN0aW9uIChtaW4sIG1heCkge1xuXHRcdFx0cmV0dXJuIHJhbmRvbS5yYW5kb20oKSAqIChtYXggLSBtaW4pICsgbWluO1xuXHRcdH07XG5cblx0XHQvLyBSZXR1cm5zIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gKGluY2x1c2l2ZSkgYW5kIG1heCAoaW5jbHVzaXZlKVxuXHRcdHJhbmRvbS5pbnRCZXR3ZWVuID0gZnVuY3Rpb24gKG1pbiwgbWF4KSB7XG5cdFx0XHRyZXR1cm4gTWF0aC5mbG9vcihyYW5kb20ucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpICsgbWluO1xuXHRcdH07XG5cblx0XHQvLyB3aGVuIG91ciBtYWluIG91dGVyIFwidWhlcHJuZ1wiIGZ1bmN0aW9uIGlzIGNhbGxlZCwgYWZ0ZXIgc2V0dGluZyB1cCBvdXJcblx0XHQvLyBpbml0aWFsIHZhcmlhYmxlcyBhbmQgZW50cm9waWMgc3RhdGUsIHdlIHJldHVybiBhbiBcImluc3RhbmNlIHBvaW50ZXJcIlxuXHRcdC8vIHRvIHRoZSBpbnRlcm5hbCBhbm9ueW1vdXMgZnVuY3Rpb24gd2hpY2ggY2FuIHRoZW4gYmUgdXNlZCB0byBhY2Nlc3Ncblx0XHQvLyB0aGUgdWhlcHJuZydzIHZhcmlvdXMgZXhwb3J0ZWQgZnVuY3Rpb25zLiAgQXMgd2l0aCB0aGUgXCIuZG9uZVwiIGZ1bmN0aW9uXG5cdFx0Ly8gYWJvdmUsIHdlIHNob3VsZCBzZXQgdGhlIHJldHVybmVkIHZhbHVlIHRvICdudWxsJyBvbmNlIHdlJ3JlIGZpbmlzaGVkXG5cdFx0Ly8gdXNpbmcgYW55IG9mIHRoZXNlIGZ1bmN0aW9ucy5cblx0XHRyZXR1cm4gcmFuZG9tO1xuXHR9KCkpO1xufTtcblxuLy8gTW9kaWZpY2F0aW9uIGZvciB1c2UgaW4gbm9kZTpcbnVoZXBybmcuY3JlYXRlID0gZnVuY3Rpb24gKHNlZWQpIHtcblx0cmV0dXJuIG5ldyB1aGVwcm5nKHNlZWQpO1xufTtcbm1vZHVsZS5leHBvcnRzID0gdWhlcHJuZztcbiIsImltcG9ydCBBY3RvciBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvQWN0b3JcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FJXCI7XG5pbXBvcnQgR29hcEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9Hb2FwQUlcIlxuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuXG4vKipcbiAqIEEgbWFuYWdlciBjbGFzcyBmb3IgYWxsIG9mIHRoZSBBSSBpbiBhIHNjZW5lLlxuICogS2VlcHMgYSBsaXN0IG9mIHJlZ2lzdGVyZWQgYWN0b3JzIGFuZCBoYW5kbGVzIEFJIGdlbmVyYXRpb24gZm9yIGFjdG9ycy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQUlNYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cdC8qKiBUaGUgYXJyYXkgb2YgcmVnaXN0ZXJlZCBhY3RvcnMgKi9cblx0YWN0b3JzOiBBcnJheTxBY3Rvcj47XG5cdC8qKiBNYXBzIEFJIG5hbWVzIHRvIHRoZWlyIGNvbnN0cnVjdG9ycyAqL1xuXHRyZWdpc3RlcmVkQUk6IE1hcDxBSUNvbnN0cnVjdG9yPjtcblxuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMuYWN0b3JzID0gbmV3IEFycmF5KCk7XG5cdFx0dGhpcy5yZWdpc3RlcmVkQUkgPSBuZXcgTWFwKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGFuIGFjdG9yIHdpdGggdGhlIEFJTWFuYWdlclxuXHQgKiBAcGFyYW0gYWN0b3IgVGhlIGFjdG9yIHRvIHJlZ2lzdGVyXG5cdCAqL1xuXHRyZWdpc3RlckFjdG9yKGFjdG9yOiBBY3Rvcik6IHZvaWQge1xuXHRcdHRoaXMuYWN0b3JzLnB1c2goYWN0b3IpO1xuXHR9XG5cblx0cmVtb3ZlQWN0b3IoYWN0b3I6IEFjdG9yKTogdm9pZCB7XG5cdFx0bGV0IGluZGV4ID0gdGhpcy5hY3RvcnMuaW5kZXhPZihhY3Rvcik7XG5cblx0XHRpZihpbmRleCAhPT0gLTEpe1xuXHRcdFx0dGhpcy5hY3RvcnMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGFuIEFJIHdpdGggdGhlIEFJTWFuYWdlciBmb3IgdXNlIGxhdGVyIG9uXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBBSSB0byByZWdpc3RlclxuXHQgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBmb3IgdGhlIEFJXG5cdCAqL1xuXHRyZWdpc3RlckFJKG5hbWU6IHN0cmluZywgY29uc3RyOiBuZXcgPFQgZXh0ZW5kcyBBSSB8IEdvYXBBST4oKSA9PiBUICk6IHZvaWQge1xuXHRcdHRoaXMucmVnaXN0ZXJlZEFJLmFkZChuYW1lLCBjb25zdHIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhbiBBSSBpbnN0YW5jZSBmcm9tIGl0cyBuYW1lXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBBSSB0byBhZGRcblx0ICogQHJldHVybnMgQSBuZXcgQUkgaW5zdGFuY2Vcblx0ICovXG5cdGdlbmVyYXRlQUkobmFtZTogc3RyaW5nKTogQUkgfCBHb2FwQUkge1xuXHRcdGlmKHRoaXMucmVnaXN0ZXJlZEFJLmhhcyhuYW1lKSl7XG5cdFx0XHRyZXR1cm4gbmV3ICh0aGlzLnJlZ2lzdGVyZWRBSS5nZXQobmFtZSkpKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IGBDYW5ub3QgY3JlYXRlIEFJIHdpdGggbmFtZSAke25hbWV9LCBubyBBSSB3aXRoIHRoYXQgbmFtZSBpcyByZWdpc3RlcmVkYDtcblx0XHR9XG5cdH1cblxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHQvLyBSdW4gdGhlIGFpIGZvciBldmVyeSBhY3RpdmUgYWN0b3Jcblx0XHR0aGlzLmFjdG9ycy5mb3JFYWNoKGFjdG9yID0+IHsgaWYoYWN0b3IuYWlBY3RpdmUpIGFjdG9yLmFpLnVwZGF0ZShkZWx0YVQpIH0pO1xuXHR9XG59XG5cbnR5cGUgQUlDb25zdHJ1Y3RvciA9IG5ldyA8VCBleHRlbmRzIEFJPigpID0+IFQ7IiwiaW1wb3J0IEFJIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9BSVwiO1xuaW1wb3J0IFN0YXRlTWFjaGluZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1N0YXRlL1N0YXRlTWFjaGluZVwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi9Ob2Rlcy9HYW1lTm9kZVwiO1xuXG4vKipcbiAqIEEgdmVyc2lvbiBvZiBhIEByZWZlcmVuY2VbU3RhdGVNYWNoaW5lXSB0aGF0IGlzIGNvbmZpZ3VyZWQgdG8gd29yayBhcyBhbiBBSSBjb250cm9sbGVyIGZvciBhIEByZWZlcmVuY2VbR2FtZU5vZGVdXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0YXRlTWFjaGluZUFJIGV4dGVuZHMgU3RhdGVNYWNoaW5lIGltcGxlbWVudHMgQUkge1xuXHQvKipcdFRoZSBHYW1lTm9kZSB0aGF0IHVzZXMgdGhpcyBTdGF0ZU1hY2hpbmUgZm9yIGl0cyBBSSAqL1xuXHRwcm90ZWN0ZWQgb3duZXI6IEdhbWVOb2RlO1xuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRpbml0aWFsaXplQUkob3duZXI6IEdhbWVOb2RlLCBjb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHt9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGRlc3Ryb3koKXtcblx0XHQvLyBHZXQgcmlkIG9mIG91ciByZWZlcmVuY2UgdG8gdGhlIG93bmVyXG5cdFx0ZGVsZXRlIHRoaXMub3duZXI7XG5cdFx0dGhpcy5yZWNlaXZlci5kZXN0cm95KCk7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0YWN0aXZhdGUob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge31cbn0iLCIvLyBAaWdub3JlUGFnZVxuXG4vKipcbiAqIEEgcGxhY2Vob2xkZXIgZnVuY3Rpb24gZm9yIE5vIE9wZXJhdGlvbi4gRG9lcyBub3RoaW5nXG4gKi9cbmNvbnN0IE51bGxGdW5jID0gKCkgPT4ge307XG5cbmV4cG9ydCBkZWZhdWx0IE51bGxGdW5jOyIsIi8qKlxuICogQSBsaW5rZWQtbGlzdCBmb3IgdGhlIGVkZ2VzIGluIGEgQHJlZmVyZW5jZVtHcmFwaF0uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEVkZ2VOb2RlIHtcbiAgICAvKiogVGhlIG5vZGUgaW4gdGhlIEdyYXBoIHRoaXMgZWRnZSBjb25uZWN0cyB0byAqL1xuICAgIHk6IG51bWJlcjtcbiAgICAvKiogVGhlIHdlaWdodCBvZiB0aGlzIEVkZ2VOb2RlICovXG5cdHdlaWdodDogbnVtYmVyO1xuICAgIC8qKiBUaGUgbmV4dCBFZGdlTm9kZSBpbiB0aGUgbGlua2VkLWxpc3QgKi9cbiAgICBuZXh0OiBFZGdlTm9kZTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgRWRnZU5vZGVcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBub2RlIHRoaXMgZWRnZSBjb25uZWN0cyB0b1xuICAgICAqIEBwYXJhbSB3ZWlnaHQgVGhlIHdlaWdodCBvZiB0aGlzIGVkZ2VcbiAgICAgKi9cblx0Y29uc3RydWN0b3IoaW5kZXg6IG51bWJlciwgd2VpZ2h0PzogbnVtYmVyKXtcblx0XHR0aGlzLnkgPSBpbmRleDtcblx0XHR0aGlzLm5leHQgPSBudWxsO1xuXHRcdHRoaXMud2VpZ2h0ID0gd2VpZ2h0ID8gd2VpZ2h0IDogMTtcblx0fVxufSIsImltcG9ydCBFZGdlTm9kZSBmcm9tIFwiLi9FZGdlTm9kZVwiO1xuXG5leHBvcnQgY29uc3QgTUFYX1YgPSAxMDA7XG5cbi8qKlxuICogQW4gaW1wbGVtZW50YXRpb24gb2YgYSBncmFwaCBkYXRhIHN0cnVjdHVyZSB1c2luZyBlZGdlIGxpc3RzLiBJbnNwaXJlZCBieSBUaGUgQWxnb3JpdGhtIERlc2lnbiBNYW51YWwuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdyYXBoIHtcblx0LyoqIEFuIGFycmF5IG9mIGVkZ2VzIGF0IHRoZSBub2RlIHNwZWNpZmllZCBieSB0aGUgaW5kZXggKi9cblx0ZWRnZXM6IEFycmF5PEVkZ2VOb2RlPjtcblx0LyoqIEFuIGFycmF5IHJlcHJlc2VudGluZyB0aGUgZGVncmVlIG9mIHRoZSBub2RlIHNwZWNpZmllZCBieSB0aGUgaW5kZXggKi9cblx0ZGVncmVlOiBBcnJheTxudW1iZXI+O1xuXHQvKiogVGhlIG51bWJlciBvZiB2ZXJ0aWNlcyBpbiB0aGUgZ3JhcGggKi9cblx0bnVtVmVydGljZXM6IG51bWJlcjtcblx0LyoqIFRoZSBudW1iZXIgb2YgZWRnZXMgaW4gdGhlIGdyYXBoICovXG5cdG51bUVkZ2VzOiBudW1iZXI7XG5cdC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgZ3JhcGggaXMgZGlyZWN0ZWQgKi9cblx0ZGlyZWN0ZWQ6IGJvb2xlYW47XG5cdC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgZ3JhcGggaXMgd2VpZ2h0ZWQgKi9cblx0d2VpZ2h0ZWQ6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIENvbnN0cnVjdHMgYSBuZXcgZ3JhcGhcblx0ICogQHBhcmFtIGRpcmVjdGVkIFdoZXRoZXIgb3Igbm90IHRoaXMgZ3JhcGggaXMgZGlyZWN0ZWRcblx0ICovXG5cdGNvbnN0cnVjdG9yKGRpcmVjdGVkOiBib29sZWFuID0gZmFsc2Upe1xuXHRcdHRoaXMuZGlyZWN0ZWQgPSBkaXJlY3RlZDtcblx0XHR0aGlzLndlaWdodGVkID0gZmFsc2U7XG5cblx0XHR0aGlzLm51bVZlcnRpY2VzID0gMDtcblx0XHR0aGlzLm51bUVkZ2VzID0gMDtcblxuXHRcdHRoaXMuZWRnZXMgPSBuZXcgQXJyYXkoTUFYX1YpO1xuXHRcdHRoaXMuZGVncmVlID0gbmV3IEFycmF5KE1BWF9WKTtcblx0fVxuXG5cdC8qKiBBZGRzIGEgbm9kZSB0byB0aGlzIGdyYXBoIGFuZCByZXR1cm5zIHRoZSBpbmRleCBvZiBpdFxuXHQgKiBAcmV0dXJucyBUaGUgaW5kZXggb2YgdGhlIG5ldyBub2RlXG5cdCovXG5cdGFkZE5vZGUoKTogbnVtYmVyIHtcblx0XHR0aGlzLm51bVZlcnRpY2VzKys7XG5cdFx0cmV0dXJuIHRoaXMubnVtVmVydGljZXM7XG5cdH1cblxuXHQvKiogQWRkcyBhbiBlZGdlIGJldHdlZW4gbm9kZSB4IGFuZCB5LCB3aXRoIGFuIG9wdGlvbmFsIHdlaWdodFxuXHQgKiBAcGFyYW0geCBUaGUgaW5kZXggb2YgdGhlIHN0YXJ0IG9mIHRoZSBlZGdlXG5cdCAqIEBwYXJhbSB5IFRoZSBpbmRleCBvZiB0aGUgZW5kIG9mIHRoZSBlZGdlXG5cdCAqIEBwYXJhbSB3ZWlnaHQgVGhlIG9wdGlvbmFsIHdlaWdodCBvZiB0aGUgbmV3IGVkZ2Vcblx0Ki9cblx0YWRkRWRnZSh4OiBudW1iZXIsIHk6IG51bWJlciwgd2VpZ2h0PzogbnVtYmVyKTogdm9pZCB7XG5cdFx0bGV0IGVkZ2UgPSBuZXcgRWRnZU5vZGUoeSwgd2VpZ2h0KTtcblxuXG5cblx0XHRpZih0aGlzLmVkZ2VzW3hdKXtcblx0XHRcdGVkZ2UubmV4dCA9IHRoaXMuZWRnZXNbeF07XG5cdFx0fVxuXHRcdFxuXHRcdHRoaXMuZWRnZXNbeF0gPSBlZGdlO1xuXG5cdFx0aWYoIXRoaXMuZGlyZWN0ZWQpe1xuXHRcdFx0ZWRnZSA9IG5ldyBFZGdlTm9kZSh4LCB3ZWlnaHQpO1xuXG5cdFx0XHRpZih0aGlzLmVkZ2VzW3ldKXtcblx0XHRcdFx0ZWRnZS5uZXh0ID0gdGhpcy5lZGdlc1t5XTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0dGhpcy5lZGdlc1t5XSA9IGVkZ2U7XG5cdFx0fVxuXG5cdFx0dGhpcy5udW1FZGdlcyArPSAxO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyB3aGV0aGVyIG9yIG5vdCBhbiBlZGdlIGV4aXN0cyBiZXR3ZWVuIHR3byBub2Rlcy5cblx0ICogVGhpcyBjaGVjayBpcyBkaXJlY3Rpb25hbCBpZiB0aGlzIGlzIGEgZGlyZWN0ZWQgZ3JhcGguXG5cdCAqIEBwYXJhbSB4IFRoZSBmaXJzdCBub2RlXG5cdCAqIEBwYXJhbSB5IFRoZSBzZWNvbmQgbm9kZVxuXHQgKiBAcmV0dXJucyB0cnVlIGlmIGFuIGVkZ2UgZXhpc3RzLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdGVkZ2VFeGlzdHMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRsZXQgZWRnZSA9IHRoaXMuZWRnZXNbeF07XG5cblx0XHR3aGlsZShlZGdlICE9PSBudWxsKXtcblx0XHRcdGlmKGVkZ2UueSA9PT0geSl7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXHRcdFx0ZWRnZSA9IGVkZ2UubmV4dDtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZWRnZSBsaXN0IGFzc29jaWF0ZWQgd2l0aCBub2RlIHhcblx0ICogQHBhcmFtIHggVGhlIGluZGV4IG9mIHRoZSBub2RlXG5cdCAqIEByZXR1cm5zIFRoZSBoZWFkIG9mIGEgbGlua2VkLWxpc3Qgb2YgZWRnZXNcblx0ICovXG5cdGdldEVkZ2VzKHg6IG51bWJlcik6IEVkZ2VOb2RlIHtcblx0XHRyZXR1cm4gdGhpcy5lZGdlc1t4XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBkZWdyZWUgYXNzb2NpYXRlZCB3aXRoIG5vZGUgeFxuXHQgKiBAcGFyYW0geCBUaGUgaW5kZXggb2YgdGhlIG5vZGVcblx0ICovXG5cdGdldERlZ3JlZSh4OiBudW1iZXIpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLmRlZ3JlZVt4XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGUgc3BlY2lmZWQgbm9kZSBpbnRvIGEgc3RyaW5nXG5cdCAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGUgdG8gY29udmVydCB0byBhIHN0cmluZ1xuXHQgKiBAcmV0dXJucyBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBub2RlOiBcIk5vZGUgeFwiXG5cdCAqL1xuXHRwcm90ZWN0ZWQgbm9kZVRvU3RyaW5nKGluZGV4OiBudW1iZXIpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcIk5vZGUgXCIgKyBpbmRleDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGUgR3JhcGggaW50byBhIHN0cmluZyBmb3JtYXRcblx0ICogQHJldHVybnMgVGhlIGdyYXBoIGFzIGEgc3RyaW5nXG5cdCAqL1xuXHR0b1N0cmluZygpOiBzdHJpbmcge1xuXHRcdGxldCByZXR2YWwgPSBcIlwiO1xuXG5cdFx0Zm9yKGxldCBpID0gMDsgaSA8IHRoaXMubnVtVmVydGljZXM7IGkrKyl7XG5cdFx0XHRsZXQgZWRnZSA9IHRoaXMuZWRnZXNbaV07XG5cdFx0XHRsZXQgZWRnZVN0ciA9IFwiXCI7XG5cdFx0XHR3aGlsZShlZGdlICE9PSB1bmRlZmluZWQgJiYgZWRnZSAhPT0gbnVsbCl7XG5cdFx0XHRcdGVkZ2VTdHIgKz0gZWRnZS55LnRvU3RyaW5nKCk7XG5cdFx0XHRcdGlmKHRoaXMud2VpZ2h0ZWQpe1xuXHRcdFx0XHRcdGVkZ2VTdHIgKz0gXCIgKFwiICsgZWRnZS53ZWlnaHQgKyBcIilcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZihlZGdlLm5leHQgIT09IG51bGwpe1xuXHRcdFx0XHRcdGVkZ2VTdHIgKz0gXCIsIFwiO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0ZWRnZSA9IGVkZ2UubmV4dDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dmFsICs9IHRoaXMubm9kZVRvU3RyaW5nKGkpICsgXCI6IFwiICsgZWRnZVN0ciArIFwiXFxuXCI7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldHZhbDtcblx0fVxufSIsImltcG9ydCBHcmFwaCwgeyBNQVhfViB9IGZyb20gXCIuL0dyYXBoXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuaW1wb3J0IERlYnVnUmVuZGVyYWJsZSBmcm9tIFwiLi4vSW50ZXJmYWNlcy9EZWJ1Z1JlbmRlcmFibGVcIjtcblxuLyoqXG4gKiBBbiBleHRlbnNpb24gb2YgR3JhcGggdGhhdCBoYXMgbm9kZXMgd2l0aCBwb3NpdGlvbnMgaW4gMkQgc3BhY2UuXG4gKiBUaGlzIGlzIGEgd2VpZ2h0ZWQgZ3JhcGggKHRob3VnaCBub3QgaW5oZXJlbnRseSBkaXJlY3RkKVxuKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvc2l0aW9uR3JhcGggZXh0ZW5kcyBHcmFwaCBpbXBsZW1lbnRzIERlYnVnUmVuZGVyYWJsZSB7XG5cdC8qKiBBbiBhcnJheSBvZiB0aGUgcG9zaXRpb25zIG9mIHRoZSBub2RlcyBpbiB0aGlzIGdyYXBoICovXG5cdHBvc2l0aW9uczogQXJyYXk8VmVjMj47XG5cblx0LyoqXG5cdCAqIENyZWF0ZWVzIGEgbmV3IFBvc2l0aW9uR3JhcGhcblx0ICogQHBhcmFtIGRpcmVjdGVkIFdoZXRoZXIgb3Igbm90IHRoaXMgZ3JhcGggaXMgZGlyZWN0ZWRcblx0ICovXG5cdGNvbnN0cnVjdG9yKGRpcmVjdGVkOiBib29sZWFuID0gZmFsc2Upe1xuXHRcdHN1cGVyKGRpcmVjdGVkKTtcblx0XHR0aGlzLnBvc2l0aW9ucyA9IG5ldyBBcnJheShNQVhfVik7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhIHBvc2l0aW9uZWQgbm9kZSB0byB0aGlzIGdyYXBoXG5cdCAqIEBwYXJhbSBwb3NpdGlvbiBUaGUgcG9zaXRpb24gb2YgdGhlIG5vZGUgdG8gYWRkXG5cdCAqIEByZXR1cm5zIFRoZSBpbmRleCBvZiB0aGUgYWRkZWQgbm9kZVxuXHQgKi9cblx0YWRkUG9zaXRpb25lZE5vZGUocG9zaXRpb246IFZlYzIpOiBudW1iZXIge1xuXHRcdHRoaXMucG9zaXRpb25zW3RoaXMubnVtVmVydGljZXNdID0gcG9zaXRpb247XG5cdFx0cmV0dXJuIHRoaXMuYWRkTm9kZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIHBvc2l0aW9uIG9mIGEgbm9kZS5cblx0ICogQXV0b21hdGljYWxseSBhZGp1c3RzIHRoZSB3ZWlnaHRzIG9mIHRoZSBncmFwaCB0aWVkIHRvIHRoaXMgbm9kZS5cblx0ICogQXMgc3VjaCwgYmUgd2FybmVkIHRoYXQgdGhpcyBmdW5jdGlvbiBoYXMgYW4gTyhuICsgbSkgcnVubmluZyB0aW1lLCBhbmQgdXNlIGl0IHNwYXJpbmdseS5cblx0ICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbm9kZVxuXHQgKiBAcGFyYW0gcG9zaXRpb24gVGhlIG5ldyBwb3NpdGlvbiBvZiB0aGUgbm9kZVxuXHQgKi9cblx0c2V0Tm9kZVBvc2l0aW9uKGluZGV4OiBudW1iZXIsIHBvc2l0aW9uOiBWZWMyKTogdm9pZCB7XG5cdFx0dGhpcy5wb3NpdGlvbnNbaW5kZXhdID0gcG9zaXRpb247XG5cblx0XHQvLyBSZWNhbGN1bGF0ZSBhbGwgd2VpZ2h0cyBhc3NvY2lhdGVkIHdpdGggdGhpcyBpbmRleFxuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLm51bUVkZ2VzOyBpKyspe1xuXG5cdFx0XHRsZXQgZWRnZSA9IHRoaXMuZWRnZXNbaV07XG5cblx0XHRcdHdoaWxlKGVkZ2UgIT09IG51bGwpe1xuXHRcdFx0XHQvLyBJZiB0aGlzIG5vZGUgaXMgb24gZWl0aGVyIHNpZGUgb2YgdGhlIGVkZ2UsIHJlY2FsY3VsYXRlIHdlaWdodFxuXHRcdFx0XHRpZihpID09PSBpbmRleCB8fCBlZGdlLnkgPT09IGluZGV4KXtcblx0XHRcdFx0XHRlZGdlLndlaWdodCA9IHRoaXMucG9zaXRpb25zW2ldLmRpc3RhbmNlVG8odGhpcy5wb3NpdGlvbnNbZWRnZS55XSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRlZGdlID0gZWRnZS5uZXh0O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwb3NpdGlvbiBvZiBhIG5vZGVcblx0ICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbm9kZVxuXHQgKiBAcmV0dXJucyBUaGUgcG9zaXRpb24gb2YgdGhlIG5vZGVcblx0ICovXG5cdGdldE5vZGVQb3NpdGlvbihpbmRleDogbnVtYmVyKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMucG9zaXRpb25zW2luZGV4XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGFuIGVkZ2UgdG8gdGhpcyBncmFwaCBiZXR3ZWVuIG5vZGUgeCBhbmQgeS5cblx0ICogQXV0b21hdGljYWxseSBjYWxjdWxhdGVzIHRoZSB3ZWlnaHQgb2YgdGhlIGVkZ2UgYXMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIG5vZGVzLlxuXHQgKiBAcGFyYW0geCBUaGUgYmVnaW5uaW5nIG9mIHRoZSBlZGdlXG5cdCAqIEBwYXJhbSB5IFRoZSBlbmQgb2YgdGhlIGVkZ2Vcblx0ICovXG5cdGFkZEVkZ2UoeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcblx0XHRpZighdGhpcy5wb3NpdGlvbnNbeF0gfHwgIXRoaXMucG9zaXRpb25zW3ldKXtcblx0XHRcdHRocm93IFwiQ2FuJ3QgYWRkIGVkZ2UgdG8gdW4tcG9zaXRpb25lZCBub2RlIVwiO1xuXHRcdH1cblxuXHRcdC8vIFdlaWdodCBpcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgbm9kZXNcblx0XHRsZXQgd2VpZ2h0ID0gdGhpcy5wb3NpdGlvbnNbeF0uZGlzdGFuY2VUbyh0aGlzLnBvc2l0aW9uc1t5XSk7XG5cblx0XHRzdXBlci5hZGRFZGdlKHgsIHksIHdlaWdodCk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0cHJvdGVjdGVkIG5vZGVUb1N0cmluZyhpbmRleDogbnVtYmVyKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCJOb2RlIFwiICsgaW5kZXggKyBcIiAtIFwiICsgdGhpcy5wb3NpdGlvbnNbaW5kZXhdLnRvU3RyaW5nKCk7XG5cdH1cblxuXHRkZWJ1Z1JlbmRlciA9ICgpOiB2b2lkID0+IHtcblx0XHQvLyBmb3IobGV0IHBvaW50IG9mIHRoaXMucG9zaXRpb25zKXtcblx0XHQvLyBcdGN0eC5maWxsUmVjdCgocG9pbnQueCAtIG9yaWdpbi54IC0gNCkqem9vbSwgKHBvaW50LnkgLSBvcmlnaW4ueSAtIDQpKnpvb20sIDgsIDgpO1xuXHRcdC8vIH1cblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9WZWMyXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vU2hhcGVzL0FBQkJcIjtcblxuLyoqIEFuIG9iamVjdCB0aGF0IGlzIGEgcmVnaW9uLCB3aXRoIGEgc2l6ZSwgc2NhbGUsIGFuZCBib3VuZGFyeS4gKi9cbmV4cG9ydCBkZWZhdWx0IGludGVyZmFjZSBSZWdpb24ge1xuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGlzIG9iamVjdC4gKi9cbiAgICBzaXplOiBWZWMyO1xuXG4gICAgLyoqIFRoZSBzY2FsZSBvZiB0aGlzIG9iamVjdC4gKi9cbiAgICBzY2FsZTogVmVjMjtcblxuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgb2JqZWN0IHRha2luZyBpbnRvIGFjY291bnQgdGhlIHpvb20gYW5kIHNjYWxlICovXG4gICAgcmVhZG9ubHkgc2l6ZVdpdGhab29tOiBWZWMyO1xuXG4gICAgLyoqIFRoZSBib3VuZGluZyBib3ggb2YgdGhpcyBvYmplY3QuICovXG4gICAgYm91bmRhcnk6IEFBQkI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1JlZ2lvbihhcmc6IGFueSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBhcmcgJiYgYXJnLnNpemUgJiYgYXJnLnNjYWxlICYmIGFyZy5ib3VuZGFyeTtcbn0iLCJpbXBvcnQgQ29sbGVjdGlvbiBmcm9tIFwiLi9Db2xsZWN0aW9uXCI7XG5cbi8qKlxuICogQXNzb2NpYXRlcyBzdHJpbmdzIHdpdGggZWxlbWVudHMgb2YgdHlwZSBUXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1hcDxUPiBpbXBsZW1lbnRzIENvbGxlY3Rpb24ge1xuXHRwcml2YXRlIG1hcDogUmVjb3JkPHN0cmluZywgVD47XG5cblx0LyoqIENyZWF0ZXMgYSBuZXcgbWFwICovXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5tYXAgPSB7fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgdmFsdWUgVCBzdG9yZWQgYXQgYSBrZXkuXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaXRlbSB0byBiZSBzdG9yZWRcblx0ICogQHBhcmFtIHZhbHVlIFRoZSBpdGVtIHRvIGJlIHN0b3JlZFxuXHQgKi9cblx0YWRkKGtleTogc3RyaW5nLCB2YWx1ZTogVCk6IHZvaWQge1xuXHRcdHRoaXMubWFwW2tleV0gPSB2YWx1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCBhIGtleS5cblx0ICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpdGVtXG5cdCAqIEByZXR1cm5zIFRoZSBpdGVtIGF0IHRoZSBrZXkgb3IgdW5kZWZpbmVkXG5cdCAqL1xuXHRnZXQoa2V5OiBzdHJpbmcpOiBUIHtcblx0XHRyZXR1cm4gdGhpcy5tYXBba2V5XTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBbiBhbGlhcyBvZiBhZGQuIFNldHMgdGhlIHZhbHVlIHN0b3JlZCBhdCBrZXkgdG8gdGhlIG5ldyBzcGVjaWZpZWQgdmFsdWVcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpdGVtIHRvIGJlIHN0b3JlZFxuXHQgKiBAcGFyYW0gdmFsdWUgVGhlIGl0ZW0gdG8gYmUgc3RvcmVkXG5cdCAqL1xuXHRzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBUKTogdm9pZCB7XG5cdFx0dGhpcy5hZGQoa2V5LCB2YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0cnVlIGlmIHRoZXJlIGlzIGEgdmFsdWUgc3RvcmVkIGF0IHRoZSBzcGVjaWZpZWQga2V5LCBmYWxzZSBvdGhlcndpc2UuXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBjaGVja1xuXHQgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgb3Igbm90IHRoZXJlIGlzIGFuIGl0ZW0gYXQgdGhlIGdpdmVuIGtleS5cblx0ICovXG5cdGhhcyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLm1hcFtrZXldICE9PSB1bmRlZmluZWQ7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhbiBhcnJheSBvZiBhbGwgb2YgdGhlIGtleXMgaW4gdGhpcyBtYXAuXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIGtleXMgaW4gdGhlIG1hcC5cblx0ICovXG5cdGtleXMoKTogQXJyYXk8c3RyaW5nPiB7XG5cdFx0cmV0dXJuIE9iamVjdC5rZXlzKHRoaXMubWFwKTtcblx0fVxuXHRcblx0Ly8gQGltcGxlbWVudGVkXG5cdGZvckVhY2goZnVuYzogKGtleTogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XG5cdFx0T2JqZWN0LmtleXModGhpcy5tYXApLmZvckVhY2goa2V5ID0+IGZ1bmMoa2V5KSk7XG5cdH1cblxuXHQvKipcblx0ICogRGVsZXRlcyBhbiBpdGVtIGFzc29jaWF0ZWQgd2l0aCBhIGtleVxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgYXQgd2hpY2ggdG8gZGVsZXRlIGFuIGl0ZW1cblx0ICovXG5cdGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuXHRcdGRlbGV0ZSB0aGlzLm1hcFtrZXldO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGNsZWFyKCk6IHZvaWQge1xuXHRcdHRoaXMuZm9yRWFjaChrZXkgPT4gZGVsZXRlIHRoaXMubWFwW2tleV0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIHRoaXMgbWFwIHRvIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uLlxuXHQgKiBAcmV0dXJucyBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgbWFwLlxuXHQgKi9cblx0dG9TdHJpbmcoKTogc3RyaW5nIHtcblx0XHRsZXQgc3RyID0gXCJcIjtcblxuXHRcdHRoaXMuZm9yRWFjaCgoa2V5KSA9PiBzdHIgKz0ga2V5ICsgXCIgLT4gXCIgKyB0aGlzLmdldChrZXkpLnRvU3RyaW5nKCkgKyBcIlxcblwiKTtcblxuXHRcdHJldHVybiBzdHI7XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi9WZWMyXCI7XG5cbi8qKiBBIDR4NCBtYXRyaXgwICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNYXQ0eDQge1xuXHRwcml2YXRlIG1hdDogRmxvYXQzMkFycmF5O1xuXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5tYXQgPSBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdDAsIDAsIDAsIDAsXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDAsIDAsIDAsIDBcblx0XHRdKTtcblx0fVxuXG5cdC8vIFN0YXRpYyBtZW1iZXJzXG5cdHN0YXRpYyBnZXQgSURFTlRJVFkoKTogTWF0NHg0IHtcblx0XHRyZXR1cm4gbmV3IE1hdDR4NCgpLmlkZW50aXR5KCk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0IFpFUk8oKTogTWF0NHg0IHtcblx0XHRyZXR1cm4gbmV3IE1hdDR4NCgpLnplcm8oKTtcblx0fVxuXG5cdC8vIEFjY2Vzc29yc1xuXHRzZXQgXzAwKHg6IG51bWJlcikge1xuXHRcdHRoaXMubWF0WzBdID0geDtcblx0fVxuXG5cdHNldChjb2w6IG51bWJlciwgcm93OiBudW1iZXIsIHZhbHVlOiBudW1iZXIpOiBNYXQ0eDQge1xuXHRcdGlmKGNvbCA8IDAgfHwgY29sID4gMyB8fCByb3cgPCAwIHx8IHJvdyA+IDMpe1xuXHRcdFx0dGhyb3cgYEVycm9yIC0gaW5kZXggKCR7Y29sfSwgJHtyb3d9KSBpcyBvdXQgb2YgYm91bmRzIGZvciBNYXQ0eDRgXG5cdFx0fVxuXHRcdHRoaXMubWF0W3Jvdyo0ICsgY29sXSA9IHZhbHVlO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHRnZXQoY29sOiBudW1iZXIsIHJvdzogbnVtYmVyKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5tYXRbcm93KjQgKyBjb2xdO1xuXHR9XG5cblx0c2V0QWxsKC4uLml0ZW1zOiBBcnJheTxudW1iZXI+KTogTWF0NHg0IHtcblx0XHR0aGlzLm1hdC5zZXQoaXRlbXMpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0aWRlbnRpdHkoKTogTWF0NHg0IHtcblx0XHRyZXR1cm4gdGhpcy5zZXRBbGwoXG5cdFx0XHQxLCAwLCAwLCAwLFxuXHRcdFx0MCwgMSwgMCwgMCxcblx0XHRcdDAsIDAsIDEsIDAsXG5cdFx0XHQwLCAwLCAwLCAxXG5cdFx0KVxuXHR9XG5cblx0emVybygpOiBNYXQ0eDQge1xuXHRcdHJldHVybiB0aGlzLnNldEFsbChcblx0XHRcdDAsIDAsIDAsIDAsXG5cdFx0XHQwLCAwLCAwLCAwLFxuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDAsIDAsIDAsIDBcblx0XHQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1ha2VzIHRoaXMgTWF0NHg0IGEgcm90YXRpb24gbWF0cml4IG9mIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIHJhZGlhbnMgY2N3XG5cdCAqIEBwYXJhbSB6UmFkaWFucyBUaGUgbnVtYmVyIG9mIHJhZGlhbnMgdG8gcm90YXRlXG5cdCAqIEByZXR1cm5zIHRoaXMgTWF0NHg0XG5cdCAqL1xuXHRyb3RhdGUoelJhZGlhbnM6IG51bWJlcik6IE1hdDR4NCB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0QWxsKFxuXHRcdFx0TWF0aC5jb3MoelJhZGlhbnMpLCAtTWF0aC5zaW4oelJhZGlhbnMpLCBcdDAsIDAsXG5cdFx0XHRNYXRoLnNpbih6UmFkaWFucyksIE1hdGguY29zKHpSYWRpYW5zKSwgXHQwLCAwLFxuXHRcdFx0MCwgXHRcdFx0XHRcdDAsIFx0XHRcdFx0XHRcdDEsIDAsXG5cdFx0XHQwLCBcdFx0XHRcdFx0MCwgXHRcdFx0XHRcdFx0MCwgMVxuXHRcdCk7XG5cdH1cblxuXHQvKipcblx0ICogVHVybnMgdGhpcyBNYXQ0eDQgaW50byBhIHRyYW5zbGF0aW9uIG1hdHJpeCBvZiB0aGUgc3BlY2lmaWVkIHRyYW5zbGF0aW9uXG5cdCAqIEBwYXJhbSB0cmFuc2xhdGlvbiBUaGUgdHJhbnNsYXRpb24gaW4geCBhbmQgeVxuXHQgKiBAcmV0dXJucyB0aGlzIE1hdDR4NFxuXHQgKi9cblx0dHJhbnNsYXRlKHRyYW5zbGF0aW9uOiBWZWMyIHwgRmxvYXQzMkFycmF5KTogTWF0NHg0IHtcblx0XHQvLyBJZiB0cmFuc2xhdGlvbiBpcyBhIHZlYywgZ2V0IGl0cyBhcnJheVxuXHRcdGlmKHRyYW5zbGF0aW9uIGluc3RhbmNlb2YgVmVjMil7XG5cdFx0XHR0cmFuc2xhdGlvbiA9IHRyYW5zbGF0aW9uLnRvQXJyYXkoKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5zZXRBbGwoXG5cdFx0XHQxLCAwLCAwLCB0cmFuc2xhdGlvblswXSxcblx0XHRcdDAsIDEsIDAsIHRyYW5zbGF0aW9uWzFdLFxuXHRcdFx0MCwgMCwgMSwgMCxcblx0XHRcdDAsIDAsIDAsIDFcblx0XHQpO1xuXHR9XG5cblx0c2NhbGUoc2NhbGU6IFZlYzIgfCBGbG9hdDMyQXJyYXkgfCBudW1iZXIpOiBNYXQ0eDQge1xuXHRcdC8vIE1ha2Ugc3VyZSBzY2FsZSBpcyBhIGZsb2F0MzJBcnJheVxuXHRcdGlmKHNjYWxlIGluc3RhbmNlb2YgVmVjMil7XG5cdFx0XHRzY2FsZSA9IHNjYWxlLnRvQXJyYXkoKTtcblx0XHR9IGVsc2UgaWYoIShzY2FsZSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSkpe1xuXHRcdFx0c2NhbGUgPSBuZXcgRmxvYXQzMkFycmF5KFtzY2FsZSwgc2NhbGVdKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5zZXRBbGwoXG5cdFx0XHRzY2FsZVswXSwgMCwgXHRcdDAsIDAsXG5cdFx0XHQwLCBcdFx0ICBzY2FsZVsxXSwgMCwgMCxcblx0XHRcdDAsIFx0XHQgIDAsXHRcdDEsIDAsXG5cdFx0XHQwLCBcdFx0ICAwLFx0XHQwLCAxXG5cdFx0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IE1hdDR4NCB0aGF0IHJlcHJlc2VudHMgdGhlIHJpZ2h0IHNpZGUgbXVsdGlwbGljYXRpb24gVEhJUyB4IE9USEVSXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgb3RoZXIgTWF0NHg0IHRvIG11bHRpcGx5IGJ5XG5cdCAqIEByZXR1cm5zIGEgbmV3IE1hdDR4NCBjb250YWluaW5nIHRoZSBwcm9kdWN0IG9mIHRoZXNlIHR3byBNYXQ0eDRzXG5cdCAqL1xuXHRtdWx0KG90aGVyOiBNYXQ0eDQsIG91dD86IE1hdDR4NCk6IE1hdDR4NCB7XG5cdFx0bGV0IHRlbXAgPSBuZXcgRmxvYXQzMkFycmF5KDE2KTtcblxuXHRcdGZvcihsZXQgaSA9IDA7IGkgPCA0OyBpKyspe1xuXHRcdFx0Zm9yKGxldCBqID0gMDsgaiA8IDQ7IGorKyl7XG5cdFx0XHRcdGxldCB2YWx1ZSA9IDA7XG5cdFx0XHRcdGZvcihsZXQgayA9IDA7IGsgPCA0OyBrKyspe1xuXHRcdFx0XHRcdHZhbHVlICs9IHRoaXMuZ2V0KGssIGkpICogb3RoZXIuZ2V0KGosIGspO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRlbXBbaio0ICsgaV0gID0gdmFsdWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYob3V0ICE9PSB1bmRlZmluZWQpe1xuXHRcdFx0cmV0dXJuIG91dC5zZXRBbGwoLi4udGVtcCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBuZXcgTWF0NHg0KCkuc2V0QWxsKC4uLnRlbXApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNdWx0aXBsaWVzIGFsbCBnaXZlbiBtYXRyaWNpZXMgaW4gb3JkZXIuIGUuZy4gTVVMVChBLCBCLCBDKSAtPiBBKkIqQ1xuXHQgKiBAcGFyYW0gbWF0cyBBIGxpc3Qgb2YgTWF0NHg0cyB0byBtdWx0aXBseSBpbiBvcmRlclxuXHQgKiBAcmV0dXJucyBBIG5ldyBNYXQ0eDQgaG9sZGluZyB0aGUgcmVzdWx0IG9mIHRoZSBvcGVyYXRpb25cblx0ICovXG5cdHN0YXRpYyBNVUxUKC4uLm1hdHM6IEFycmF5PE1hdDR4ND4pOiBNYXQ0eDQge1xuXHRcdC8vIENyZWF0ZSBhIG5ldyBhcnJheVxuXHRcdGxldCB0ZW1wID0gTWF0NHg0LklERU5USVRZO1xuXG5cdFx0Ly8gTXVsdGlwbHkgYnkgZXZlcnkgYXJyYXkgaW4gb3JkZXIsIGluIHBsYWNlXG5cdFx0Zm9yKGxldCBpID0gMDsgaSA8IG1hdHMubGVuZ3RoOyBpKyspe1xuXHRcdFx0dGVtcC5tdWx0KG1hdHNbaV0sIHRlbXApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0ZW1wO1xuXHR9XG5cblx0dG9BcnJheSgpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiB0aGlzLm1hdDtcblx0fVxuXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuICBgfCR7dGhpcy5tYXRbMF0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMV0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMl0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbM10udG9GaXhlZCgyKX18XFxuYCArIFxuXHRcdFx0XHRgfCR7dGhpcy5tYXRbNF0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbNV0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbNl0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbN10udG9GaXhlZCgyKX18XFxuYCArXG5cdFx0XHRcdGB8JHt0aGlzLm1hdFs4XS50b0ZpeGVkKDIpfSwgJHt0aGlzLm1hdFs5XS50b0ZpeGVkKDIpfSwgJHt0aGlzLm1hdFsxMF0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMTFdLnRvRml4ZWQoMil9fFxcbmAgK1xuXHRcdFx0XHRgfCR7dGhpcy5tYXRbMTJdLnRvRml4ZWQoMil9LCAke3RoaXMubWF0WzEzXS50b0ZpeGVkKDIpfSwgJHt0aGlzLm1hdFsxNF0udG9GaXhlZCgyKX0sICR7dGhpcy5tYXRbMTVdLnRvRml4ZWQoMil9fGA7XG5cdH1cbn0iLCJpbXBvcnQgUGh5c2ljYWwgZnJvbSBcIi4uL0ludGVyZmFjZXMvUGh5c2ljYWxcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcbmltcG9ydCBIaXQgZnJvbSBcIi4vSGl0XCI7XG5cbi8qKlxuICogQSBjbGFzcyB0aGF0IGNvbnRhaW5zIHRoZSBhcmVhIG9mIG92ZXJsYXAgb2YgdHdvIGNvbGxpZGluZyBvYmplY3RzIHRvIGFsbG93IGZvciBzb3J0aW5nIGJ5IHRoZSBwaHlzaWNzIHN5c3RlbS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXJlYUNvbGxpc2lvbiB7XG4gICAgLyoqIFRoZSBhcmVhIG9mIHRoZSBvdmVybGFwIGZvciB0aGUgY29sbGlkaW5nIG9iamVjdHMgKi9cbiAgICBhcmVhOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIEFBQkIgb2YgdGhlIG90aGVyIGNvbGxpZGVyIGluIHRoaXMgY29sbGlzaW9uICovXG4gICAgY29sbGlkZXI6IEFBQkI7XG5cbiAgICAvKiogVHlwZSBvZiB0aGUgY29sbGlzaW9uICovXG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgLyoqIFRoZXIgb3RoZXIgb2JqZWN0IGluIHRoZSBjb2xsaXNpb24gKi9cbiAgICBvdGhlcjogUGh5c2ljYWw7XG5cbiAgICAvKiogVGhlIHRpbGUsIGlmIHRoaXMgd2FzIGEgdGlsZW1hcCBjb2xsaXNpb24gKi9cbiAgICB0aWxlOiBWZWMyO1xuXG4gICAgLyoqIFRoZSBwaHlzaWNzIGhpdCBmb3IgdGhpcyBvYmplY3QgKi9cbiAgICBoaXQ6IEhpdDtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQXJlYUNvbGxpc2lvbiBvYmplY3RcbiAgICAgKiBAcGFyYW0gYXJlYSBUaGUgYXJlYSBvZiB0aGUgY29sbGlzaW9uXG4gICAgICogQHBhcmFtIGNvbGxpZGVyIFRoZSBvdGhlciBjb2xsaWRlclxuICAgICAqL1xuXHRjb25zdHJ1Y3RvcihhcmVhOiBudW1iZXIsIGNvbGxpZGVyOiBBQUJCLCBvdGhlcjogUGh5c2ljYWwsIHR5cGU6IHN0cmluZywgdGlsZTogVmVjMil7XG5cdFx0dGhpcy5hcmVhID0gYXJlYTtcbiAgICAgICAgdGhpcy5jb2xsaWRlciA9IGNvbGxpZGVyO1xuICAgICAgICB0aGlzLm90aGVyID0gb3RoZXI7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMudGlsZSA9IHRpbGU7XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuXG4vKipcbiAqIEFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGRhdGEgY29sbGVjdGVkIGZyb20gYSBwaHlzaWNzIGhpdCBiZXR3ZWVuIHR3byBnZW9tZXRyaWMgb2JqZWN0cy5cbiAqIEluc3BpcmVkIGJ5IHRoZSBoZWxwZnVsIGNvbGxpc2lvbiBkb2N1bWVudGF0aW9uIEBsaW5rKGhlcmUpKGh0dHBzOi8vbm9vbmF0LmdpdGh1Yi5pby9pbnRlcnNlY3QvKS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSGl0IHtcbiAgICAvKiogVGhlIHRpbWUgb2YgdGhlIGNvbGxpc2lvbi4gT25seSBudW1iZXJzIDAgdGhyb3VnaCAxIGhhcHBlbiBpbiB0aGlzIGZyYW1lLiAqL1xuICAgIHRpbWU6IG51bWJlcjtcbiAgICAvKiogVGhlIG5lYXIgdGltZXMgb2YgdGhlIGNvbGxpc2lvbiAqL1xuICAgIG5lYXJUaW1lczogVmVjMiA9IFZlYzIuWkVSTztcbiAgICAvKiogVGhlIHBvc2l0aW9uIG9mIHRoZSBjb2xsaXNpb24gKi9cbiAgICBwb3M6IFZlYzIgPSBWZWMyLlpFUk87XG4gICAgLyoqIFRoZSBvdmVybGFwIGRpc3RhbmNlIG9mIHRoZSBoaXQgKi9cbiAgICBkZWx0YTogVmVjMiA9IFZlYzIuWkVSTztcbiAgICAvKiogVGhlIG5vcm1hbCB2ZWN0b3Igb2YgdGhlIGhpdCAqL1xuICAgIG5vcm1hbDogVmVjMiA9IFZlYzIuWkVSTztcbn0iLCJpbXBvcnQgQ29sbGVjdGlvbiBmcm9tIFwiLi9Db2xsZWN0aW9uXCI7XG5cbi8qKlxuICogQSBGSUZPIHF1ZXVlIHdpdGggZWxlbWVudHMgb2YgdHlwZSBUXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFF1ZXVlPFQ+IGltcGxlbWVudHMgQ29sbGVjdGlvbiB7XG4gICAgLyoqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgUXVldWUgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IE1BWF9FTEVNRU5UUzogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBpbnRlcm5hbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcXVldWUgKi9cbiAgICBwcml2YXRlIHE6IEFycmF5PFQ+O1xuICAgIFxuICAgIC8qKiBUaGUgaGVhZCBvZiB0aGUgcXVldWUgKi9cbiAgICBwcml2YXRlIGhlYWQ6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIHRhaWwgb2YgdGhlIHF1ZXVlICovXG4gICAgcHJpdmF0ZSB0YWlsOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIGN1cnJlbnQgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBxdWV1ZSAqL1xuICAgIHByaXZhdGUgc2l6ZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBxdWV1ZVxuICAgICAqIEBwYXJhbSBtYXhFbGVtZW50cyBUaGUgbWF4aW11bSBzaXplIG9mIHRoZSBzdGFja1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG1heEVsZW1lbnRzOiBudW1iZXIgPSAxMDApe1xuICAgICAgICB0aGlzLk1BWF9FTEVNRU5UUyA9IG1heEVsZW1lbnRzO1xuICAgICAgICB0aGlzLnEgPSBuZXcgQXJyYXkodGhpcy5NQVhfRUxFTUVOVFMpO1xuICAgICAgICB0aGlzLmhlYWQgPSAwO1xuICAgICAgICB0aGlzLnRhaWwgPSAwO1xuICAgICAgICB0aGlzLnNpemUgPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYW4gaXRlbSB0byB0aGUgYmFjayBvZiB0aGUgcXVldWVcbiAgICAgKiBAcGFyYW0gaXRlbSBUaGUgaXRlbSB0byBhZGQgdG8gdGhlIGJhY2sgb2YgdGhlIHF1ZXVlXG4gICAgICovXG4gICAgZW5xdWV1ZShpdGVtOiBUKTogdm9pZHtcbiAgICAgICAgaWYoKHRoaXMudGFpbCArIDEpICUgdGhpcy5NQVhfRUxFTUVOVFMgPT09IHRoaXMuaGVhZCl7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJRdWV1ZSBmdWxsIC0gY2Fubm90IGFkZCBlbGVtZW50XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zaXplICs9IDE7XG4gICAgICAgIHRoaXMucVt0aGlzLnRhaWxdID0gaXRlbTtcbiAgICAgICAgdGhpcy50YWlsID0gKHRoaXMudGFpbCArIDEpICUgdGhpcy5NQVhfRUxFTUVOVFM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIGl0ZW0gZnJvbSB0aGUgZnJvbnQgb2YgdGhlIHF1ZXVlXG4gICAgICogQHJldHVybnMgVGhlIGl0ZW0gYXQgdGhlIGZyb250IG9mIHRoZSBxdWV1ZVxuICAgICAqL1xuICAgIGRlcXVldWUoKTogVCB7XG4gICAgICAgIGlmKHRoaXMuaGVhZCA9PT0gdGhpcy50YWlsKXtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlF1ZXVlIGVtcHR5IC0gY2Fubm90IHJlbW92ZSBlbGVtZW50XCIpO1xuICAgICAgICB9XG5cblxuICAgICAgICB0aGlzLnNpemUgLT0gMTtcbiAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLnFbdGhpcy5oZWFkXTtcbiAgICAgICAgLy8gTm93IGRlbGV0ZSB0aGUgaXRlbVxuICAgICAgICBkZWxldGUgdGhpcy5xW3RoaXMuaGVhZF07XG4gICAgICAgIHRoaXMuaGVhZCA9ICh0aGlzLmhlYWQgKyAxKSAlIHRoaXMuTUFYX0VMRU1FTlRTO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaXRlbSBhdCB0aGUgZnJvbnQgb2YgdGhlIHF1ZXVlLCBidXQgZG9lcyBub3QgcmVtb3ZlIGl0XG4gICAgICogQHJldHVybnMgVGhlIGl0ZW0gYXQgdGhlIGZyb250IG9mIHRoZSBxdWV1ZVxuICAgICAqL1xuICAgIHBlZWtOZXh0KCk6IFQge1xuICAgICAgICBpZih0aGlzLmhlYWQgPT09IHRoaXMudGFpbCl7XG4gICAgICAgICAgICB0aHJvdyBcIlF1ZXVlIGVtcHR5IC0gY2Fubm90IGdldCBlbGVtZW50XCJcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBpdGVtID0gdGhpcy5xW3RoaXMuaGVhZF07XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gaXRlbTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHF1ZXVlIGhhcyBpdGVtcyBpbiBpdCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGlzIHF1ZXVlIGhhcyBpdGVtc1xuICAgICAqL1xuICAgIGhhc0l0ZW1zKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oZWFkICE9PSB0aGlzLnRhaWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBxdWV1ZS5cbiAgICAgKiBAcmV0dXJucyBUaGUgc2l6ZSBvZiB0aGUgcXVldWVcbiAgICAgKi9cbiAgICBnZXRTaXplKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNpemU7XG4gICAgfVxuXG4gICAgLy8gQGltcGxlbWVudGVkXG4gICAgY2xlYXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IGRlbGV0ZSB0aGlzLnFbaW5kZXhdKTtcbiAgICAgICAgdGhpcy5zaXplID0gMDtcbiAgICAgICAgdGhpcy5oZWFkID0gdGhpcy50YWlsO1xuICAgIH1cblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIGZvckVhY2goZnVuYzogKGl0ZW06IFQsIGluZGV4PzogbnVtYmVyKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIGxldCBpID0gdGhpcy5oZWFkO1xuICAgICAgICB3aGlsZShpICE9PSB0aGlzLnRhaWwpe1xuICAgICAgICAgICAgZnVuYyh0aGlzLnFbaV0sIGkpO1xuICAgICAgICAgICAgaSA9IChpICsgMSkgJSB0aGlzLk1BWF9FTEVNRU5UUztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoaXMgcXVldWUgaW50byBhIHN0cmluZyBmb3JtYXRcbiAgICAgKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhpcyBxdWV1ZVxuICAgICAqL1xuICAgIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgICAgIGxldCByZXR2YWwgPSBcIlwiO1xuXG4gICAgICAgIHRoaXMuZm9yRWFjaCggKGl0ZW0sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBsZXQgc3RyID0gaXRlbS50b1N0cmluZygpXG4gICAgICAgICAgICBpZihpbmRleCAhPT0gMCl7XG4gICAgICAgICAgICAgICAgc3RyICs9IFwiIC0+IFwiXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR2YWwgPSBzdHIgKyByZXR2YWw7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBcIlRvcCAtPiBcIiArIHJldHZhbDtcbiAgICB9XG59IiwiLyoqIEEgY29udGFpbmVyIGZvciBpbmZvIGFib3V0IGEgd2ViR0wgc2hhZGVyIHByb2dyYW0gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdlYkdMUHJvZ3JhbVR5cGUge1xuXHQvKiogQSB3ZWJHTCBwcm9ncmFtICovXG5cdHByb2dyYW06IFdlYkdMUHJvZ3JhbTtcblx0XG5cdC8qKiBBIHZlcnRleCBzaGFkZXIgKi9cblx0dmVydGV4U2hhZGVyOiBXZWJHTFNoYWRlcjtcblxuXHQvKiogQSBmcmFnbWVudCBzaGFkZXIgKi9cblx0ZnJhZ21lbnRTaGFkZXI6IFdlYkdMU2hhZGVyO1xuXG5cdC8qKlxuXHQgKiBEZWxldGVzIHRoaXMgc2hhZGVyIHByb2dyYW1cblx0ICovXG5cdGRlbGV0ZShnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0KTogdm9pZCB7XG5cdFx0Ly8gQ2xlYW4gdXAgYWxsIGFzcGVjdHMgb2YgdGhpcyBwcm9ncmFtXG5cdFx0aWYodGhpcy5wcm9ncmFtKXtcblx0XHRcdGdsLmRlbGV0ZVByb2dyYW0odGhpcy5wcm9ncmFtKTtcblx0XHR9XG5cdFx0XHRcblx0XHRpZih0aGlzLnZlcnRleFNoYWRlcil7XG5cdFx0XHRnbC5kZWxldGVTaGFkZXIodGhpcy52ZXJ0ZXhTaGFkZXIpO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMuZnJhZ21lbnRTaGFkZXIpe1xuXHRcdFx0Z2wuZGVsZXRlU2hhZGVyKHRoaXMuZnJhZ21lbnRTaGFkZXIpO1xuXHRcdH1cblx0fVxufSIsImltcG9ydCBTaGFwZSBmcm9tIFwiLi9TaGFwZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL1ZlYzJcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IENpcmNsZSBmcm9tIFwiLi9DaXJjbGVcIjtcbmltcG9ydCBIaXQgZnJvbSBcIi4uL1BoeXNpY3MvSGl0XCI7XG5cbi8qKlxuICogQW4gQXhpcy1BbGlnbmVkIEJvdW5kaW5nIEJveC4gSW4gb3RoZXIgd29yZHMsIGEgcmVjdGFuZ2xlIHRoYXQgaXMgYWx3YXlzIGFsaWduZWQgdG8gdGhlIHgteSBncmlkLlxuICogSW5zcGlyZWQgYnkgdGhlIGhlbHBmdWwgY29sbGlzaW9uIGRvY3VtZW50YXRpb24gQGxpbmsoaGVyZSkoaHR0cHM6Ly9ub29uYXQuZ2l0aHViLmlvL2ludGVyc2VjdC8pLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBQUJCIGV4dGVuZHMgU2hhcGUge1xuICAgIGNlbnRlcjogVmVjMjtcbiAgICBoYWxmU2l6ZTogVmVjMjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQUFCQlxuICAgICAqIEBwYXJhbSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgQUFCQlxuICAgICAqIEBwYXJhbSBoYWxmU2l6ZSBUaGUgaGFsZiBzaXplIG9mIHRoZSBBQUJCIC0gVGhlIGRpc3RhbmNlIGZyb20gdGhlIGNlbnRlciB0byBhbiBlZGdlIGluIHggYW5kIHlcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjZW50ZXI/OiBWZWMyLCBoYWxmU2l6ZT86IFZlYzIpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNlbnRlciA9IGNlbnRlciA/IGNlbnRlciA6IG5ldyBWZWMyKDAsIDApO1xuICAgICAgICB0aGlzLmhhbGZTaXplID0gaGFsZlNpemUgPyBoYWxmU2l6ZSA6IG5ldyBWZWMyKDAsIDApO1xuICAgIH1cblxuICAgIC8qKiBSZXR1cm5zIGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIEFBQkIgKi9cbiAgICBnZXQgdG9wTGVmdCgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMubGVmdCwgdGhpcy50b3ApXG4gICAgfVxuXG4gICAgLyoqIFJldHVybnMgYSBwb2ludCByZXByZXNlbnRpbmcgdGhlIHRvcCByaWdodCBjb3JuZXIgb2YgdGhlIEFBQkIgKi9cbiAgICBnZXQgdG9wUmlnaHQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLnJpZ2h0LCB0aGlzLnRvcClcbiAgICB9XG5cbiAgICAvKiogUmV0dXJucyBhIHBvaW50IHJlcHJlc2VudGluZyB0aGUgYm90dG9tIGxlZnQgY29ybmVyIG9mIHRoZSBBQUJCICovXG4gICAgZ2V0IGJvdHRvbUxlZnQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLmxlZnQsIHRoaXMuYm90dG9tKVxuICAgIH1cblxuICAgIC8qKiBSZXR1cm5zIGEgcG9pbnQgcmVwcmVzZW50aW5nIHRoZSBib3R0b20gcmlnaHQgY29ybmVyIG9mIHRoZSBBQUJCICovXG4gICAgZ2V0IGJvdHRvbVJpZ2h0KCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy5yaWdodCwgdGhpcy5ib3R0b20pXG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZ2V0Qm91bmRpbmdSZWN0KCk6IEFBQkIge1xuICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldEJvdW5kaW5nQ2lyY2xlKCk6IENpcmNsZSB7XG4gICAgICAgIGxldCByID0gTWF0aC5tYXgodGhpcy5odywgdGhpcy5oaClcbiAgICAgICAgcmV0dXJuIG5ldyBDaXJjbGUodGhpcy5jZW50ZXIuY2xvbmUoKSwgcik7XG4gICAgfVxuXG4gICAgLy8gQGRlcHJlY2F0ZWRcbiAgICBnZXRIYWxmU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFsZlNpemU7XG4gICAgfVxuXG4gICAgLy8gQGRlcHJlY2F0ZWRcbiAgICBzZXRIYWxmU2l6ZShoYWxmU2l6ZTogVmVjMik6IHZvaWQge1xuICAgICAgICB0aGlzLmhhbGZTaXplID0gaGFsZlNpemU7XG4gICAgfVxuXG4gICAgLy8gVE9ETyAtIG1vdmUgdGhlc2UgYWxsIHRvIHRoZSBTaGFwZSBjbGFzc1xuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIGJvb2xlYW4gY2hlY2sgb2Ygd2hldGhlciB0aGlzIEFBQkIgY29udGFpbnMgYSBwb2ludFxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgcG9pbnRcbiAgICAgKi9cbiAgICBjb250YWluc1BvaW50KHBvaW50OiBWZWMyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBwb2ludC54ID49IHRoaXMueCAtIHRoaXMuaHcgJiYgcG9pbnQueCA8PSB0aGlzLnggKyB0aGlzLmh3XG4gICAgICAgICAgICAmJiBwb2ludC55ID49IHRoaXMueSAtIHRoaXMuaGggJiYgcG9pbnQueSA8PSB0aGlzLnkgKyB0aGlzLmhoXG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIGJvb2xlYW4gY2hlY2sgb2Ygd2hldGhlciB0aGlzIEFBQkIgY29udGFpbnMgYSBwb2ludFxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgcG9pbnRcbiAgICAgKi9cbiAgICBpbnRlcnNlY3RQb2ludChwb2ludDogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICBsZXQgZHggPSBwb2ludC54IC0gdGhpcy54O1xuICAgICAgICBsZXQgcHggPSB0aGlzLmh3IC0gTWF0aC5hYnMoZHgpO1xuICAgICAgICBcbiAgICAgICAgaWYocHggPD0gMCl7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZHkgPSBwb2ludC55IC0gdGhpcy55O1xuICAgICAgICBsZXQgcHkgPSB0aGlzLmhoIC0gTWF0aC5hYnMoZHkpO1xuXG4gICAgICAgIGlmKHB5IDw9IDApe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBib29sZWFuIGNoZWNrIG9mIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIGEgcG9pbnQgd2l0aCBzb2Z0IGxlZnQgYW5kIHRvcCBib3VuZGFyaWVzLlxuICAgICAqIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgdG9wIGxlZnQgaXMgKDAsIDApLCB0aGUgcG9pbnQgKDAsIDApIGlzIG5vdCBpbiB0aGUgQUFCQlxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgdGhpcyBBQUJCIGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgcG9pbnRcbiAgICAgKi9cbiAgICBjb250YWluc1BvaW50U29mdChwb2ludDogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gcG9pbnQueCA+IHRoaXMueCAtIHRoaXMuaHcgJiYgcG9pbnQueCA8PSB0aGlzLnggKyB0aGlzLmh3XG4gICAgICAgICAgICAmJiBwb2ludC55ID4gdGhpcy55IC0gdGhpcy5oaCAmJiBwb2ludC55IDw9IHRoaXMueSArIHRoaXMuaGhcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGRhdGEgZnJvbSB0aGUgaW50ZXJzZWN0aW9uIG9mIHRoaXMgQUFCQiB3aXRoIGEgbGluZSBzZWdtZW50IGZyb20gYSBwb2ludCBpbiBhIGRpcmVjdGlvblxuICAgICAqIEBwYXJhbSBwb2ludCBUaGUgcG9pbnQgdGhhdCB0aGUgbGluZSBzZWdtZW50IHN0YXJ0cyBmcm9tXG4gICAgICogQHBhcmFtIGRlbHRhIFRoZSBkaXJlY3Rpb24gYW5kIGRpc3RhbmNlIG9mIHRoZSBzZWdtZW50XG4gICAgICogQHBhcmFtIHBhZGRpbmcgUGFkcyB0aGUgQUFCQiB0byBtYWtlIGl0IHdpZGVyIGZvciB0aGUgaW50ZXJzZWN0aW9uIHRlc3RcbiAgICAgKiBAcmV0dXJucyBUaGUgSGl0IG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGludGVyc2VjdGlvbiwgb3IgbnVsbCBpZiB0aGVyZSB3YXMgbm8gaW50ZXJzZWN0aW9uXG4gICAgICovXG4gICAgaW50ZXJzZWN0U2VnbWVudChwb2ludDogVmVjMiwgZGVsdGE6IFZlYzIsIHBhZGRpbmc/OiBWZWMyKTogSGl0IHtcbiAgICAgICAgbGV0IHBhZGRpbmdYID0gcGFkZGluZyA/IHBhZGRpbmcueCA6IDA7XG4gICAgICAgIGxldCBwYWRkaW5nWSA9IHBhZGRpbmcgPyBwYWRkaW5nLnkgOiAwO1xuXG4gICAgICAgIGxldCBzY2FsZVggPSAxL2RlbHRhLng7XG4gICAgICAgIGxldCBzY2FsZVkgPSAxL2RlbHRhLnk7XG5cbiAgICAgICAgbGV0IHNpZ25YID0gTWF0aFV0aWxzLnNpZ24oc2NhbGVYKTtcbiAgICAgICAgbGV0IHNpZ25ZID0gTWF0aFV0aWxzLnNpZ24oc2NhbGVZKTtcblxuICAgICAgICBsZXQgdG5lYXJ4ID0gc2NhbGVYKih0aGlzLnggLSBzaWduWCoodGhpcy5odyArIHBhZGRpbmdYKSAtIHBvaW50LngpO1xuICAgICAgICBsZXQgdG5lYXJ5ID0gc2NhbGVZKih0aGlzLnkgLSBzaWduWSoodGhpcy5oaCArIHBhZGRpbmdZKSAtIHBvaW50LnkpO1xuICAgICAgICBsZXQgdGZhcnggPSBzY2FsZVgqKHRoaXMueCArIHNpZ25YKih0aGlzLmh3ICsgcGFkZGluZ1gpIC0gcG9pbnQueCk7XG4gICAgICAgIGxldCB0ZmFyeSA9IHNjYWxlWSoodGhpcy55ICsgc2lnblkqKHRoaXMuaGggKyBwYWRkaW5nWSkgLSBwb2ludC55KTtcbiAgICAgICAgXG4gICAgICAgIGlmKHRuZWFyeCA+IHRmYXJ5IHx8IHRuZWFyeSA+IHRmYXJ4KXtcbiAgICAgICAgICAgIC8vIFdlIGFyZW4ndCBjb2xsaWRpbmcgLSB3ZSBjbGVhciBvbmUgYXhpcyBiZWZvcmUgaW50ZXJzZWN0aW5nIGFub3RoZXJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRuZWFyID0gTWF0aC5tYXgodG5lYXJ4LCB0bmVhcnkpO1xuXG4gICAgICAgIC8vIERvdWJsZSBjaGVjayBmb3IgTmFOc1xuICAgICAgICBpZih0bmVhcnggIT09IHRuZWFyeCl7XG4gICAgICAgICAgICB0bmVhciA9IHRuZWFyeTtcbiAgICAgICAgfSBlbHNlIGlmICh0bmVhcnkgIT09IHRuZWFyeSl7XG4gICAgICAgICAgICB0bmVhciA9IHRuZWFyeDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0ZmFyID0gTWF0aC5taW4odGZhcngsIHRmYXJ5KTtcblxuICAgICAgICBpZih0bmVhciA9PT0gLUluZmluaXR5KXtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodG5lYXIgPj0gMSB8fCB0ZmFyIDw9IDApe1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBhcmUgY29sbGlkaW5nXG4gICAgICAgIGxldCBoaXQgPSBuZXcgSGl0KCk7XG4gICAgICAgIGhpdC50aW1lID0gTWF0aFV0aWxzLmNsYW1wMDEodG5lYXIpO1xuICAgICAgICBoaXQubmVhclRpbWVzLnggPSB0bmVhcng7XG4gICAgICAgIGhpdC5uZWFyVGltZXMueSA9IHRuZWFyeTtcblxuICAgICAgICBpZih0bmVhcnggPiB0bmVhcnkpe1xuICAgICAgICAgICAgLy8gV2UgaGl0IG9uIHRoZSBsZWZ0IG9yIHJpZ2h0IHNpemVcbiAgICAgICAgICAgIGhpdC5ub3JtYWwueCA9IC1zaWduWDtcbiAgICAgICAgICAgIGhpdC5ub3JtYWwueSA9IDA7XG4gICAgICAgIH0gZWxzZSBpZihNYXRoLmFicyh0bmVhcnggLSB0bmVhcnkpIDwgMC4wMDAxKXtcbiAgICAgICAgICAgIC8vIFdlIGhpdCBvbiB0aGUgY29ybmVyXG4gICAgICAgICAgICBoaXQubm9ybWFsLnggPSAtc2lnblg7XG4gICAgICAgICAgICBoaXQubm9ybWFsLnkgPSAtc2lnblk7XG4gICAgICAgICAgICBoaXQubm9ybWFsLm5vcm1hbGl6ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gV2UgaGl0IG9uIHRoZSB0b3Agb3IgYm90dG9tXG4gICAgICAgICAgICBoaXQubm9ybWFsLnggPSAwO1xuICAgICAgICAgICAgaGl0Lm5vcm1hbC55ID0gLXNpZ25ZO1xuICAgICAgICB9XG5cbiAgICAgICAgaGl0LmRlbHRhLnggPSAoMS4wIC0gaGl0LnRpbWUpICogLWRlbHRhLng7XG4gICAgICAgIGhpdC5kZWx0YS55ID0gKDEuMCAtIGhpdC50aW1lKSAqIC1kZWx0YS55O1xuICAgICAgICBoaXQucG9zLnggPSBwb2ludC54ICsgZGVsdGEueCAqIGhpdC50aW1lO1xuICAgICAgICBoaXQucG9zLnkgPSBwb2ludC55ICsgZGVsdGEueSAqIGhpdC50aW1lO1xuXG4gICAgICAgIHJldHVybiBoaXQ7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgb3ZlcmxhcHMob3RoZXI6IFNoYXBlKTogYm9vbGVhbiB7XG4gICAgICAgIGlmKG90aGVyIGluc3RhbmNlb2YgQUFCQil7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vdmVybGFwc0FBQkIob3RoZXIpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IFwiT3ZlcmxhcCBub3QgZGVmaW5lZCBiZXR3ZWVuIHRoZXNlIHNoYXBlcy5cIlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIGJvb2xlYW4gY2hlY2sgb2Ygd2hldGhlciB0aGlzIEFBQkIgb3ZlcmxhcHMgYW5vdGhlclxuICAgICAqIEBwYXJhbSBvdGhlciBUaGUgb3RoZXIgQUFCQiB0byBjaGVjayBhZ2FpbnN0XG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIEFBQkIgb3ZlcmxhcHMgdGhlIG90aGVyLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb3ZlcmxhcHNBQUJCKG90aGVyOiBBQUJCKTogYm9vbGVhbiB7XG4gICAgICAgIGxldCBkeCA9IG90aGVyLnggLSB0aGlzLng7XG4gICAgICAgIGxldCBweCA9IHRoaXMuaHcgKyBvdGhlci5odyAtIE1hdGguYWJzKGR4KTtcbiAgICAgICAgXG4gICAgICAgIGlmKHB4IDw9IDApe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGR5ID0gb3RoZXIueSAtIHRoaXMueTtcbiAgICAgICAgbGV0IHB5ID0gdGhpcy5oaCArIG90aGVyLmhoIC0gTWF0aC5hYnMoZHkpO1xuXG4gICAgICAgIGlmKHB5IDw9IDApe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZXNlIEFBQkJzIGFyZSBKVVNUIHRvdWNoaW5nIC0gbm90IG92ZXJsYXBwaW5nLlxuICAgICAqIFZlYzIueCBpcyAtMSBpZiB0aGUgb3RoZXIgaXMgdG8gdGhlIGxlZnQsIDEgaWYgdG8gdGhlIHJpZ2h0LlxuICAgICAqIExpa2V3aXNlLCBWZWMyLnkgaXMgLTEgaWYgdGhlIG90aGVyIGlzIG9uIHRvcCwgMSBpZiBvbiBib3R0b20uXG4gICAgICogQHBhcmFtIG90aGVyIFRoZSBvdGhlciBBQUJCIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgVGhlIGNvbGxpc2lvbiBzaWRlcyBzdG9yZWQgaW4gYSBWZWMyIGlmIHRoZSBBQUJCcyBhcmUgdG91Y2hpbmcsIG51bGwgb3RoZXJ3aXNlXG4gICAgICovXG4gICAgdG91Y2hlc0FBQkIob3RoZXI6IEFBQkIpOiBWZWMyIHtcbiAgICAgICAgbGV0IGR4ID0gb3RoZXIueCAtIHRoaXMueDtcbiAgICAgICAgbGV0IHB4ID0gdGhpcy5odyArIG90aGVyLmh3IC0gTWF0aC5hYnMoZHgpO1xuXG4gICAgICAgIGxldCBkeSA9IG90aGVyLnkgLSB0aGlzLnk7XG4gICAgICAgIGxldCBweSA9IHRoaXMuaGggKyBvdGhlci5oaCAtIE1hdGguYWJzKGR5KTtcblxuICAgICAgICAvLyBJZiBvbmUgYXhpcyBpcyBqdXN0IHRvdWNoaW5nIGFuZCB0aGUgb3RoZXIgaXMgb3ZlcmxhcHBpbmcsIHRydWVcbiAgICAgICAgaWYoKHB4ID09PSAwICYmIHB5ID49IDApIHx8IChweSA9PT0gMCAmJiBweCA+PSAwKSl7XG4gICAgICAgICAgICBsZXQgcmV0ID0gbmV3IFZlYzIoKTtcblxuICAgICAgICAgICAgaWYocHggPT09IDApe1xuICAgICAgICAgICAgICAgIHJldC54ID0gb3RoZXIueCA8IHRoaXMueCA/IC0xIDogMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYocHkgPT09IDApe1xuICAgICAgICAgICAgICAgIHJldC55ID0gb3RoZXIueSA8IHRoaXMueSA/IC0xIDogMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZXNlIEFBQkJzIGFyZSBKVVNUIHRvdWNoaW5nIC0gbm90IG92ZXJsYXBwaW5nLlxuICAgICAqIEFsc28sIGlmIHRoZXkgYXJlIG9ubHkgdG91Y2hpbmcgY29ybmVycywgdGhleSBhcmUgY29uc2lkZXJlZCBub3QgdG91Y2hpbmcuXG4gICAgICogVmVjMi54IGlzIC0xIGlmIHRoZSBvdGhlciBpcyB0byB0aGUgbGVmdCwgMSBpZiB0byB0aGUgcmlnaHQuXG4gICAgICogTGlrZXdpc2UsIFZlYzIueSBpcyAtMSBpZiB0aGUgb3RoZXIgaXMgb24gdG9wLCAxIGlmIG9uIGJvdHRvbS5cbiAgICAgKiBAcGFyYW0gb3RoZXIgVGhlIG90aGVyIEFBQkIgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBUaGUgc2lkZSBvZiB0aGUgdG91Y2gsIHN0b3JlZCBhcyBhIFZlYzIsIG9yIG51bGwgaWYgdGhlcmUgaXMgbm8gdG91Y2hcbiAgICAgKi9cbiAgICB0b3VjaGVzQUFCQldpdGhvdXRDb3JuZXJzKG90aGVyOiBBQUJCKTogVmVjMiB7XG4gICAgICAgIGxldCBkeCA9IG90aGVyLnggLSB0aGlzLng7XG4gICAgICAgIGxldCBweCA9IHRoaXMuaHcgKyBvdGhlci5odyAtIE1hdGguYWJzKGR4KTtcblxuICAgICAgICBsZXQgZHkgPSBvdGhlci55IC0gdGhpcy55O1xuICAgICAgICBsZXQgcHkgPSB0aGlzLmhoICsgb3RoZXIuaGggLSBNYXRoLmFicyhkeSk7XG5cbiAgICAgICAgLy8gSWYgb25lIGF4aXMgaXMgdG91Y2hpbmcsIGFuZCB0aGUgb3RoZXIgaXMgc3RyaWN0bHkgb3ZlcmxhcHBpbmdcbiAgICAgICAgaWYoKHB4ID09PSAwICYmIHB5ID4gMCkgfHwgKHB5ID09PSAwICYmIHB4ID4gMCkpe1xuICAgICAgICAgICAgbGV0IHJldCA9IG5ldyBWZWMyKCk7XG5cbiAgICAgICAgICAgIGlmKHB4ID09PSAwKXtcbiAgICAgICAgICAgICAgICByZXQueCA9IG90aGVyLnggPCB0aGlzLnggPyAtMSA6IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldC55ID0gb3RoZXIueSA8IHRoaXMueSA/IC0xIDogMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldDtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBhcmVhIG9mIHRoZSBvdmVybGFwIGJldHdlZW4gdGhpcyBBQUJCIGFuZCBhbm90aGVyXG4gICAgICogQHBhcmFtIG90aGVyIFRoZSBvdGhlciBBQUJCXG4gICAgICogQHJldHVybnMgVGhlIGFyZWEgb2YgdGhlIG92ZXJsYXAgYmV0d2VlbiB0aGUgQUFCQnNcbiAgICAgKi9cbiAgICBvdmVybGFwQXJlYShvdGhlcjogQUFCQik6IG51bWJlciB7XG4gICAgICAgIGxldCBsZWZ0eCA9IE1hdGgubWF4KHRoaXMueCAtIHRoaXMuaHcsIG90aGVyLnggLSBvdGhlci5odyk7XG4gICAgICAgIGxldCByaWdodHggPSBNYXRoLm1pbih0aGlzLnggKyB0aGlzLmh3LCBvdGhlci54ICsgb3RoZXIuaHcpO1xuICAgICAgICBsZXQgZHggPSByaWdodHggLSBsZWZ0eDtcblxuICAgICAgICBsZXQgbGVmdHkgPSBNYXRoLm1heCh0aGlzLnkgLSB0aGlzLmhoLCBvdGhlci55IC0gb3RoZXIuaGgpO1xuICAgICAgICBsZXQgcmlnaHR5ID0gTWF0aC5taW4odGhpcy55ICsgdGhpcy5oaCwgb3RoZXIueSArIG90aGVyLmhoKTtcbiAgICAgICAgbGV0IGR5ID0gcmlnaHR5IC0gbGVmdHk7XG5cbiAgICAgICAgaWYoZHggPCAwIHx8IGR5IDwgMCkgcmV0dXJuIDA7XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gZHgqZHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW92ZXMgYW5kIHJlc2l6ZXMgdGhpcyByZWN0IGZyb20gaXRzIGN1cnJlbnQgcG9zaXRpb24gdG8gdGhlIHBvc2l0aW9uIHNwZWNpZmllZFxuICAgICAqIEBwYXJhbSB2ZWxvY2l0eSBUaGUgbW92ZW1lbnQgb2YgdGhlIHJlY3QgZnJvbSBpdHMgcG9zaXRpb25cbiAgICAgKiBAcGFyYW0gZnJvbVBvc2l0aW9uIEEgcG9zaXRpb24gc3BlY2lmaWVkIHRvIGJlIHRoZSBzdGFydGluZyBwb2ludCBvZiBzd2VlcGluZ1xuICAgICAqIEBwYXJhbSBoYWxmU2l6ZSBUaGUgaGFsZlNpemUgb2YgdGhlIHN3ZWVwaW5nIHJlY3QgXG4gICAgICovXG4gICAgc3dlZXAodmVsb2NpdHk6IFZlYzIsIGZyb21Qb3NpdGlvbj86IFZlYzIsIGhhbGZTaXplPzogVmVjMik6IHZvaWQge1xuICAgICAgICBpZighZnJvbVBvc2l0aW9uKXtcbiAgICAgICAgICAgIGZyb21Qb3NpdGlvbiA9IHRoaXMuY2VudGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWhhbGZTaXplKXtcbiAgICAgICAgICAgIGhhbGZTaXplID0gdGhpcy5oYWxmU2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjZW50ZXJYID0gZnJvbVBvc2l0aW9uLnggKyB2ZWxvY2l0eS54LzI7XG4gICAgICAgIGxldCBjZW50ZXJZID0gZnJvbVBvc2l0aW9uLnkgKyB2ZWxvY2l0eS55LzI7XG5cbiAgICAgICAgbGV0IG1pblggPSBNYXRoLm1pbihmcm9tUG9zaXRpb24ueCAtIGhhbGZTaXplLngsIGZyb21Qb3NpdGlvbi54ICsgdmVsb2NpdHkueCAtIGhhbGZTaXplLngpO1xuICAgICAgICBsZXQgbWluWSA9IE1hdGgubWluKGZyb21Qb3NpdGlvbi55IC0gaGFsZlNpemUueSwgZnJvbVBvc2l0aW9uLnkgKyB2ZWxvY2l0eS55IC0gaGFsZlNpemUueSk7XG5cbiAgICAgICAgdGhpcy5jZW50ZXIuc2V0KGNlbnRlclgsIGNlbnRlclkpO1xuICAgICAgICB0aGlzLmhhbGZTaXplLnNldChjZW50ZXJYIC0gbWluWCwgY2VudGVyWSAtIG1pblkpO1xuICAgIH1cbiAgICBcbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBjbG9uZSgpOiBBQUJCIHtcbiAgICAgICAgcmV0dXJuIG5ldyBBQUJCKHRoaXMuY2VudGVyLmNsb25lKCksIHRoaXMuaGFsZlNpemUuY2xvbmUoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhpcyBBQUJCIHRvIGEgc3RyaW5nIGZvcm1hdFxuICAgICAqIEByZXR1cm5zIChjZW50ZXI6ICh4LCB5KSwgaGFsZlNpemU6ICh4LCB5KSlcbiAgICAgKi9cbiAgICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gXCIoY2VudGVyOiBcIiArIHRoaXMuY2VudGVyLnRvU3RyaW5nKCkgKyBcIiwgaGFsZi1zaXplOiBcIiArIHRoaXMuaGFsZlNpemUudG9TdHJpbmcoKSArIFwiKVwiXG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9WZWMyXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi9BQUJCXCI7XG5pbXBvcnQgU2hhcGUgZnJvbSBcIi4vU2hhcGVcIjtcblxuLyoqXG4gKiBBIENpcmNsZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDaXJjbGUgZXh0ZW5kcyBTaGFwZSB7XG5cdHByaXZhdGUgX2NlbnRlcjogVmVjMjtcblx0cmFkaXVzOiBudW1iZXI7XG5cdFxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBDaXJjbGVcblx0ICogQHBhcmFtIGNlbnRlciBUaGUgY2VudGVyIG9mIHRoZSBjaXJjbGVcblx0ICogQHBhcmFtIHJhZGl1cyBUaGUgcmFkaXVzIG9mIHRoZSBjaXJjbGVcblx0ICovXG5cdGNvbnN0cnVjdG9yKGNlbnRlcjogVmVjMiwgcmFkaXVzOiBudW1iZXIpIHtcblx0XHRzdXBlcigpO1xuICAgICAgICB0aGlzLl9jZW50ZXIgPSBjZW50ZXIgPyBjZW50ZXIgOiBuZXcgVmVjMigwLCAwKTtcbiAgICAgICAgdGhpcy5yYWRpdXMgPSByYWRpdXMgPyByYWRpdXMgOiAwO1xuXHR9XG5cblx0Z2V0IGNlbnRlcigpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fY2VudGVyO1xuXHR9XG5cblx0c2V0IGNlbnRlcihjZW50ZXI6IFZlYzIpIHtcblx0XHR0aGlzLl9jZW50ZXIgPSBjZW50ZXI7XG5cdH1cblxuXHRnZXQgaGFsZlNpemUoKTogVmVjMiB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKHRoaXMucmFkaXVzLCB0aGlzLnJhZGl1cyk7XG5cdH1cblxuXHRnZXQgcigpOiBudW1iZXIge1xuXHRcdHJldHVybiB0aGlzLnJhZGl1cztcblx0fVxuXG5cdHNldCByKHJhZGl1czogbnVtYmVyKSB7XG5cdFx0dGhpcy5yYWRpdXMgPSByYWRpdXM7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0LyoqXG4gICAgICogQSBzaW1wbGUgYm9vbGVhbiBjaGVjayBvZiB3aGV0aGVyIHRoaXMgQUFCQiBjb250YWlucyBhIHBvaW50XG4gICAgICogQHBhcmFtIHBvaW50IFRoZSBwb2ludCB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgd2hldGhlciB0aGlzIEFBQkIgY29udGFpbnMgdGhlIHNwZWNpZmllZCBwb2ludFxuICAgICAqL1xuICAgIGNvbnRhaW5zUG9pbnQocG9pbnQ6IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VudGVyLmRpc3RhbmNlU3FUbyhwb2ludCkgPD0gdGhpcy5yYWRpdXMqdGhpcy5yYWRpdXM7XG4gICAgfVxuXG5cdC8vIEBvdmVycmlkZVxuXHRnZXRCb3VuZGluZ1JlY3QoKTogQUFCQiB7XG5cdFx0cmV0dXJuIG5ldyBBQUJCKHRoaXMuX2NlbnRlci5jbG9uZSgpLCBuZXcgVmVjMih0aGlzLnJhZGl1cywgdGhpcy5yYWRpdXMpKTtcblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRnZXRCb3VuZGluZ0NpcmNsZSgpOiBDaXJjbGUge1xuXHRcdHJldHVybiB0aGlzLmNsb25lKCk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0b3ZlcmxhcHMob3RoZXI6IFNoYXBlKTogYm9vbGVhbiB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC5cIik7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0Y2xvbmUoKTogQ2lyY2xlIHtcblx0XHRyZXR1cm4gbmV3IENpcmNsZSh0aGlzLl9jZW50ZXIuY2xvbmUoKSwgdGhpcy5yYWRpdXMpO1xuXHR9XG5cblx0dG9TdHJpbmcoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCIoY2VudGVyOiBcIiArIHRoaXMuY2VudGVyLnRvU3RyaW5nKCkgKyBcIiwgcmFkaXVzOiBcIiArIHRoaXMucmFkaXVzICsgXCIpXCI7XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4vQUFCQlwiO1xuaW1wb3J0IENpcmNsZSBmcm9tIFwiLi9DaXJjbGVcIjtcblxuLyoqXG4gKiBBbiBhYnN0cmFjdCBTaGFwZSBjbGFzcyB0aGF0IGFjdHMgYXMgYW4gaW50ZXJmYWNlIGZvciBiZXR0ZXIgaW50ZXJhY3Rpb25zIHdpdGggc3ViY2xhc3Nlcy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgU2hhcGUge1xuICAgIGFic3RyYWN0IGdldCBjZW50ZXIoKTogVmVjMjtcblxuICAgIGFic3RyYWN0IHNldCBjZW50ZXIoY2VudGVyOiBWZWMyKTtcblxuICAgIGFic3RyYWN0IGdldCBoYWxmU2l6ZSgpOiBWZWMyO1xuXG4gICAgZ2V0IHgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VudGVyLng7XG4gICAgfVxuXG4gICAgZ2V0IHkoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2VudGVyLnk7XG4gICAgfVxuXG4gICAgZ2V0IGh3KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbGZTaXplLng7XG4gICAgfVxuXG4gICAgZ2V0IGhoKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbGZTaXplLnk7XG4gICAgfVxuXG4gICAgZ2V0IHRvcCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy55IC0gdGhpcy5oaDtcbiAgICB9XG5cbiAgICBnZXQgYm90dG9tKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnkgKyB0aGlzLmhoO1xuICAgIH1cblxuICAgIGdldCBsZWZ0KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnggLSB0aGlzLmh3O1xuICAgIH1cblxuICAgIGdldCByaWdodCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy54ICsgdGhpcy5odztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgYm91bmRpbmcgcmVjdGFuZ2xlIGZvciB0aGlzIHNoYXBlLiBXYXJuaW5nIC0gbWF5IGJlIHRoZSBzYW1lIGFzIHRoaXMgU2hhcGUuXG4gICAgICogRm9yIGluc3RhbmNlLCB0aGUgYm91bmRpbmcgY2lyY2xlIG9mIGFuIEFBQkIgaXMgaXRzZWxmLiBVc2UgY2xvbmUoKSBpZiB5b3UgbmVlZCBhIG5ldyBzaGFwZS5cbiAgICAgKiBAcmV0dXJucyBBbiBBQUJCIHRoYXQgYm91bmRzIHRoaXMgc2hhcGVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBnZXRCb3VuZGluZ1JlY3QoKTogQUFCQjtcblxuICAgIC8qKlxuICAgICAqIEdldHMgYSBib3VuZGluZyBjaXJjbGUgZm9yIHRoaXMgc2hhcGUuIFdhcm5pbmcgLSBtYXkgYmUgdGhlIHNhbWUgYXMgdGhpcyBTaGFwZS5cbiAgICAgKiBGb3IgaW5zdGFuY2UsIHRoZSBib3VuZGluZyBjaXJjbGUgb2YgYSBDaXJjbGUgaXMgaXRzZWxmLiBVc2UgY2xvbmUoKSBpZiB5b3UgbmVlZCBhIG5ldyBzaGFwZS5cbiAgICAgKiBAcmV0dXJucyBBIENpcmNsZSB0aGF0IGJvdW5kcyB0aGlzIHNoYXBlXG4gICAgICovXG4gICAgYWJzdHJhY3QgZ2V0Qm91bmRpbmdDaXJjbGUoKTogQ2lyY2xlO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGNvcHkgb2YgdGhpcyBTaGFwZVxuICAgICAqIEByZXR1cm5zIEEgbmV3IGNvcHkgb2YgdGhpcyBzaGFwZVxuICAgICAqL1xuICAgIGFic3RyYWN0IGNsb25lKCk6IFNoYXBlO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoaXMgc2hhcGUgb3ZlcmxhcHMgYW5vdGhlclxuICAgICAqIEBwYXJhbSBvdGhlciBUaGUgb3RoZXIgc2hhcGUgdG8gY2hlY2sgYWdhaW5zdFxuICAgICAqIEByZXR1cm5zIGEgYm9vbGVhbiB0aGF0IHJlcHJlc2VudHMgd2hldGhlciB0aGlzIFNoYXBlIG92ZXJsYXBzIHRoZSBvdGhlciBvbmVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBvdmVybGFwcyhvdGhlcjogU2hhcGUpOiBib29sZWFuO1xuXG4gICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIGJvb2xlYW4gY2hlY2sgb2Ygd2hldGhlciB0aGlzIFNoYXBlIGNvbnRhaW5zIGEgcG9pbnRcbiAgICAgKiBAcGFyYW0gcG9pbnQgVGhlIHBvaW50IHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIHRoaXMgU2hhcGUgY29udGFpbnMgdGhlIHNwZWNpZmllZCBwb2ludFxuICAgICAqL1xuICAgIGFic3RyYWN0IGNvbnRhaW5zUG9pbnQocG9pbnQ6IFZlYzIpOiBib29sZWFuO1xuXG4gICAgc3RhdGljIGdldFRpbWVPZkNvbGxpc2lvbihBOiBTaGFwZSwgdmVsQTogVmVjMiwgQjogU2hhcGUsIHZlbEI6IFZlYzIpOiBbVmVjMiwgVmVjMiwgYm9vbGVhbiwgYm9vbGVhbl0ge1xuXHRcdGlmKEEgaW5zdGFuY2VvZiBBQUJCICYmIEIgaW5zdGFuY2VvZiBBQUJCKXtcblx0XHRcdHJldHVybiBTaGFwZS5nZXRUaW1lT2ZDb2xsaXNpb25fQUFCQl9BQUJCKEEsIHZlbEEsIEIsIHZlbEIpO1xuXHRcdH1cbiAgICB9XG4gICAgXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0VGltZU9mQ29sbGlzaW9uX0FBQkJfQUFCQihBOiBBQUJCLCB2ZWxBOiBWZWMyLCBCOiBTaGFwZSwgdmVsQjogVmVjMik6IFtWZWMyLCBWZWMyLCBib29sZWFuLCBib29sZWFuXSB7XG4gICAgICAgIGxldCBwb3NTbWFsbGVyID0gQS5jZW50ZXI7XG4gICAgICAgIGxldCBwb3NMYXJnZXIgPSBCLmNlbnRlcjtcbiAgICAgICAgXG4gICAgICAgIGxldCBzaXplU21hbGxlciA9IEEuaGFsZlNpemU7XG4gICAgICAgIGxldCBzaXplTGFyZ2VyID0gQi5oYWxmU2l6ZTtcbiAgICBcbiAgICAgICAgbGV0IGZpcnN0Q29udGFjdCA9IG5ldyBWZWMyKDAsIDApO1xuICAgICAgICBsZXQgbGFzdENvbnRhY3QgPSBuZXcgVmVjMigwLCAwKTtcbiAgICBcbiAgICAgICAgbGV0IGNvbGxpZGluZ1ggPSBmYWxzZTtcbiAgICAgICAgbGV0IGNvbGxpZGluZ1kgPSBmYWxzZTtcbiAgICBcbiAgICAgICAgLy8gU29ydCBieSBwb3NpdGlvblxuICAgICAgICBpZihwb3NMYXJnZXIueCA8IHBvc1NtYWxsZXIueCl7XG4gICAgICAgICAgICAvLyBTd2FwLCBiZWNhdXNlIHNtYWxsZXIgaXMgZnVydGhlciByaWdodCB0aGFuIGxhcmdlclxuICAgICAgICAgICAgbGV0IHRlbXA6IFZlYzI7XG4gICAgICAgICAgICB0ZW1wID0gc2l6ZVNtYWxsZXI7XG4gICAgICAgICAgICBzaXplU21hbGxlciA9IHNpemVMYXJnZXI7XG4gICAgICAgICAgICBzaXplTGFyZ2VyID0gdGVtcDtcbiAgICBcbiAgICAgICAgICAgIHRlbXAgPSBwb3NTbWFsbGVyO1xuICAgICAgICAgICAgcG9zU21hbGxlciA9IHBvc0xhcmdlcjtcbiAgICAgICAgICAgIHBvc0xhcmdlciA9IHRlbXA7XG4gICAgXG4gICAgICAgICAgICB0ZW1wID0gdmVsQTtcbiAgICAgICAgICAgIHZlbEEgPSB2ZWxCO1xuICAgICAgICAgICAgdmVsQiA9IHRlbXA7XG4gICAgICAgIH1cbiAgICBcbiAgICAgICAgLy8gQSBpcyBsZWZ0LCBCIGlzIHJpZ2h0XG4gICAgICAgIGZpcnN0Q29udGFjdC54ID0gSW5maW5pdHk7XG4gICAgICAgIGxhc3RDb250YWN0LnggPSBJbmZpbml0eTtcbiAgICBcbiAgICAgICAgaWYgKHBvc0xhcmdlci54IC0gc2l6ZUxhcmdlci54ID49IHBvc1NtYWxsZXIueCArIHNpemVTbWFsbGVyLngpe1xuICAgICAgICAgICAgLy8gSWYgd2UgYXJlbid0IGN1cnJlbnRseSBjb2xsaWRpbmdcbiAgICAgICAgICAgIGxldCByZWxWZWwgPSB2ZWxBLnggLSB2ZWxCLng7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKHJlbFZlbCA+IDApe1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZXkgYXJlIG1vdmluZyB0b3dhcmRzIGVhY2ggb3RoZXJcbiAgICAgICAgICAgICAgICBmaXJzdENvbnRhY3QueCA9ICgocG9zTGFyZ2VyLnggLSBzaXplTGFyZ2VyLngpIC0gKHBvc1NtYWxsZXIueCArIHNpemVTbWFsbGVyLngpKS8ocmVsVmVsKTtcbiAgICAgICAgICAgICAgICBsYXN0Q29udGFjdC54ID0gKChwb3NMYXJnZXIueCArIHNpemVMYXJnZXIueCkgLSAocG9zU21hbGxlci54IC0gc2l6ZVNtYWxsZXIueCkpLyhyZWxWZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29sbGlkaW5nWCA9IHRydWU7XG4gICAgICAgIH1cbiAgICBcbiAgICAgICAgaWYocG9zTGFyZ2VyLnkgPCBwb3NTbWFsbGVyLnkpe1xuICAgICAgICAgICAgLy8gU3dhcCwgYmVjYXVzZSBzbWFsbGVyIGlzIGZ1cnRoZXIgdXAgdGhhbiBsYXJnZXJcbiAgICAgICAgICAgIGxldCB0ZW1wOiBWZWMyO1xuICAgICAgICAgICAgdGVtcCA9IHNpemVTbWFsbGVyO1xuICAgICAgICAgICAgc2l6ZVNtYWxsZXIgPSBzaXplTGFyZ2VyO1xuICAgICAgICAgICAgc2l6ZUxhcmdlciA9IHRlbXA7XG4gICAgXG4gICAgICAgICAgICB0ZW1wID0gcG9zU21hbGxlcjtcbiAgICAgICAgICAgIHBvc1NtYWxsZXIgPSBwb3NMYXJnZXI7XG4gICAgICAgICAgICBwb3NMYXJnZXIgPSB0ZW1wO1xuICAgIFxuICAgICAgICAgICAgdGVtcCA9IHZlbEE7XG4gICAgICAgICAgICB2ZWxBID0gdmVsQjtcbiAgICAgICAgICAgIHZlbEIgPSB0ZW1wO1xuICAgICAgICB9XG4gICAgXG4gICAgICAgIC8vIEEgaXMgdG9wLCBCIGlzIGJvdHRvbVxuICAgICAgICBmaXJzdENvbnRhY3QueSA9IEluZmluaXR5O1xuICAgICAgICBsYXN0Q29udGFjdC55ID0gSW5maW5pdHk7XG4gICAgXG4gICAgICAgIGlmIChwb3NMYXJnZXIueSAtIHNpemVMYXJnZXIueSA+PSBwb3NTbWFsbGVyLnkgKyBzaXplU21hbGxlci55KXtcbiAgICAgICAgICAgIC8vIElmIHdlIGFyZW4ndCBjdXJyZW50bHkgY29sbGlkaW5nXG4gICAgICAgICAgICBsZXQgcmVsVmVsID0gdmVsQS55IC0gdmVsQi55O1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZihyZWxWZWwgPiAwKXtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGV5IGFyZSBtb3ZpbmcgdG93YXJkcyBlYWNoIG90aGVyXG4gICAgICAgICAgICAgICAgZmlyc3RDb250YWN0LnkgPSAoKHBvc0xhcmdlci55IC0gc2l6ZUxhcmdlci55KSAtIChwb3NTbWFsbGVyLnkgKyBzaXplU21hbGxlci55KSkvKHJlbFZlbCk7XG4gICAgICAgICAgICAgICAgbGFzdENvbnRhY3QueSA9ICgocG9zTGFyZ2VyLnkgKyBzaXplTGFyZ2VyLnkpIC0gKHBvc1NtYWxsZXIueSAtIHNpemVTbWFsbGVyLnkpKS8ocmVsVmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbGxpZGluZ1kgPSB0cnVlO1xuICAgICAgICB9XG4gICAgXG4gICAgICAgIHJldHVybiBbZmlyc3RDb250YWN0LCBsYXN0Q29udGFjdCwgY29sbGlkaW5nWCwgY29sbGlkaW5nWV07XG4gICAgfVxufSIsImltcG9ydCBDb2xsZWN0aW9uIGZyb20gXCIuL0NvbGxlY3Rpb25cIjtcblxuLyoqXG4gKiBBIExJRk8gc3RhY2sgd2l0aCBpdGVtcyBvZiB0eXBlIFRcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3RhY2s8VD4gaW1wbGVtZW50cyBDb2xsZWN0aW9uIHtcbiAgICAvKiogVGhlIG1heGltdW0gbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBTdGFjayAqL1xuICAgIHByaXZhdGUgTUFYX0VMRU1FTlRTOiBudW1iZXI7XG4gICAgXG4gICAgLyoqIFRoZSBpbnRlcm5hbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgc3RhY2sgKi9cbiAgICBwcml2YXRlIHN0YWNrOiBBcnJheTxUPjtcbiAgICBcbiAgICAvKiogVGhlIGhlYWQgb2YgdGhlIHN0YWNrICovXG5cdHByaXZhdGUgaGVhZDogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBzdGFja1xuICAgICAqIEBwYXJhbSBtYXhFbGVtZW50cyBUaGUgbWF4aW11bSBzaXplIG9mIHRoZSBzdGFja1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG1heEVsZW1lbnRzOiBudW1iZXIgPSAxMDApe1xuICAgICAgICB0aGlzLk1BWF9FTEVNRU5UUyA9IG1heEVsZW1lbnRzO1xuICAgICAgICB0aGlzLnN0YWNrID0gbmV3IEFycmF5PFQ+KHRoaXMuTUFYX0VMRU1FTlRTKTtcbiAgICAgICAgdGhpcy5oZWFkID0gLTE7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIEFkZHMgYW4gaXRlbSB0byB0aGUgdG9wIG9mIHRoZSBzdGFja1xuICAgICAqIEBwYXJhbSBpdGVtIFRoZSBuZXcgaXRlbSB0byBhZGQgdG8gdGhlIHN0YWNrXG4gICAgICovXG4gICAgcHVzaChpdGVtOiBUKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMuaGVhZCArIDEgPT09IHRoaXMuTUFYX0VMRU1FTlRTKXtcbiAgICAgICAgICAgIHRocm93IFwiU3RhY2sgZnVsbCAtIGNhbm5vdCBhZGQgZWxlbWVudFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGVhZCArPSAxO1xuICAgICAgICB0aGlzLnN0YWNrW3RoaXMuaGVhZF0gPSBpdGVtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW4gaXRlbSBmcm9tIHRoZSB0b3Agb2YgdGhlIHN0YWNrXG4gICAgICogQHJldHVybnMgVGhlIGl0ZW0gYXQgdGhlIHRvcCBvZiB0aGUgc3RhY2tcbiAgICAgKi9cbiAgICBwb3AoKTogVCB7XG4gICAgICAgIGlmKHRoaXMuaGVhZCA9PT0gLTEpe1xuICAgICAgICAgICAgdGhyb3cgXCJTdGFjayBlbXB0eSAtIGNhbm5vdCByZW1vdmUgZWxlbWVudFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaGVhZCAtPSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5zdGFja1t0aGlzLmhlYWQgKyAxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBlbGVtZW50IGN1cnJlbnRseSBhdCB0aGUgdG9wIG9mIHRoZSBzdGFja1xuICAgICAqIEByZXR1cm5zIFRoZSBpdGVtIGF0IHRoZSB0b3Agb2YgdGhlIHN0YWNrXG4gICAgICovXG4gICAgcGVlaygpOiBUIHtcbiAgICAgICAgaWYodGhpcy5oZWFkID09PSAtMSl7XG4gICAgICAgICAgICB0aHJvdyBcIlN0YWNrIGVtcHR5IC0gY2Fubm90IGdldCBlbGVtZW50XCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhY2tbdGhpcy5oZWFkXTtcbiAgICB9XG5cbiAgICAvKiogUmV0dXJucyB0cnVlIGlmIHRoaXMgc3RhY2sgaXMgZW1wdHlcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gdGhhdCByZXByZXNlbnRzIHdoZXRoZXIgb3Igbm90IHRoZSBzdGFjayBpcyBlbXB0eVxuICAgICovXG4gICAgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGVhZCA9PT0gLTE7XG4gICAgfVxuXG4gICAgLy8gQGltcGxlbWVudGVkXG4gICAgY2xlYXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IGRlbGV0ZSB0aGlzLnN0YWNrW2luZGV4XSk7XG4gICAgICAgIHRoaXMuaGVhZCA9IC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG51bWJlciBvZiBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIHN0YWNrXG4gICAgICogQHJldHVybnMgVGhlIG51bWJlciBvZiBpdGVtcyBpbiB0aGUgc3RhY2tcbiAgICAgKi9cbiAgICBzaXplKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmhlYWQgKyAxO1xuICAgIH1cblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIGZvckVhY2goZnVuYzogKGl0ZW06IFQsIGluZGV4PzogbnVtYmVyKSA9PiB2b2lkKTogdm9pZHtcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICB3aGlsZShpIDw9IHRoaXMuaGVhZCl7XG4gICAgICAgICAgICBmdW5jKHRoaXMuc3RhY2tbaV0sIGkpO1xuICAgICAgICAgICAgaSArPSAxO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhpcyBzdGFjayBpbnRvIGEgc3RyaW5nIGZvcm1hdFxuICAgICAqIEByZXR1cm5zIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGlzIHN0YWNrXG4gICAgICovXG4gICAgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICAgICAgbGV0IHJldHZhbCA9IFwiXCI7XG5cbiAgICAgICAgdGhpcy5mb3JFYWNoKCAoaXRlbSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGxldCBzdHIgPSBpdGVtLnRvU3RyaW5nKClcbiAgICAgICAgICAgIGlmKGluZGV4ICE9PSAwKXtcbiAgICAgICAgICAgICAgICBzdHIgKz0gXCIgLT4gXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHZhbCA9IHN0ciArIHJldHZhbDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIFwiVG9wIC0+IFwiICsgcmV0dmFsO1xuICAgIH1cbn0iLCJpbXBvcnQgRW1pdHRlciBmcm9tIFwiLi4vLi4vRXZlbnRzL0VtaXR0ZXJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9JbnRlcmZhY2VzL1VwZGF0ZWFibGVcIjtcbmltcG9ydCBTdGF0ZU1hY2hpbmUgZnJvbSBcIi4vU3RhdGVNYWNoaW5lXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgaW1wbGVtZW50YXRpb24gb2YgYSBzdGF0ZSBmb3IgYSBAcmVmZXJlbmNlW1N0YXRlTWFjaGluZV0uXG4gKiBUaGlzIGNsYXNzIHNob3VsZCBiZSBleHRlbmRlZCB0byBhbGxvdyBmb3IgY3VzdG9tIHN0YXRlIGJlaGF2aW9ycy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgU3RhdGUgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcbiAgICAvKiogVGhlIFN0YXRlTWFjaGluZSB0aGF0IHVzZXMgdGhpcyBTdGF0ZSAqL1xuICAgIHByb3RlY3RlZCBwYXJlbnQ6IFN0YXRlTWFjaGluZTtcblxuICAgIC8qKiBBbiBldmVudCBlbWl0dGVyICovXG4gICAgcHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFN0YXRlXG4gICAgICogQHBhcmFtIHBhcmVudCBUaGUgcGFyZW50IFN0YXRlTWFjaGluZSBvZiB0aGlzIHN0YXRlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocGFyZW50OiBTdGF0ZU1hY2hpbmUpIHtcbiAgICAgICAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBtZXRob2QgdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGlzIHN0YXRlIGlzIGVudGVyZWQuIFVzZSB0aGlzIHRvIGluaXRpYWxpemUgYW55IHZhcmlhYmxlcyBiZWZvcmUgdXBkYXRlcyBvY2N1ci5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBJbmZvcm1hdGlvbiB0byBwYXNzIHRvIHRoaXMgc3RhdGVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQSBsaWZlY3ljbGUgbWV0aG9kIHRoYXQgaGFuZGxlcyBhbiBpbnB1dCBldmVudCwgc3VjaCBhcyB0YWtpbmcgZGFtYWdlLlxuICAgICAqIEBwYXJhbSBldmVudCBUaGUgR2FtZUV2ZW50IHRvIHByb2Nlc3NcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBoYW5kbGVJbnB1dChldmVudDogR2FtZUV2ZW50KTogdm9pZDtcblxuICAgIC8vIEBpbXBsZW1lbnRlZFxuICAgIGFic3RyYWN0IHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBUZWxscyB0aGUgc3RhdGUgbWFjaGluZSB0aGF0IHRoaXMgc3RhdGUgaGFzIGVuZGVkLCBhbmQgbWFrZXMgaXQgdHJhbnNpdGlvbiB0byB0aGUgbmV3IHN0YXRlIHNwZWNpZmllZFxuICAgICAqIEBwYXJhbSBzdGF0ZU5hbWUgVGhlIG5hbWUgb2YgdGhlIHN0YXRlIHRvIHRyYW5zaXRpb24gdG9cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZmluaXNoZWQoc3RhdGVOYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXJlbnQuY2hhbmdlU3RhdGUoc3RhdGVOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIGxpZmVjeWNsZSBtZXRob2QgaXMgY2FsbGVkIHdoZW4gdGhlIHN0YXRlIGlzIGVuZGluZy5cbiAgICAgKiBAcmV0dXJucyBpbmZvIHRvIHBhc3MgdG8gdGhlIG5leHQgc3RhdGVcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55Pjtcbn0iLCJpbXBvcnQgU3RhY2sgZnJvbSBcIi4uL1N0YWNrXCI7XG5pbXBvcnQgU3RhdGUgZnJvbSBcIi4vU3RhdGVcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL01hcFwiO1xuaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi8uLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi8uLi9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IFVwZGF0ZWFibGUgZnJvbSBcIi4uL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIGEgUHVzaCBEb3duIEF1dG9tYXRhIFN0YXRlIG1hY2hpbmUuIFN0YXRlcyBjYW4gYWxzbyBiZSBoaWVyYXJjaGljYWxcbiAqIGZvciBtb3JlIGZsZXhpYmlsaXR5LCBhcyBkZXNjcmliZWQgaW4gQGxpbmsoR2FtZSBQcm9ncmFtbWluZyBQYXR0ZXJucykoaHR0cHM6Ly9nYW1lcHJvZ3JhbW1pbmdwYXR0ZXJucy5jb20vc3RhdGUuaHRtbCkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN0YXRlTWFjaGluZSBpbXBsZW1lbnRzIFVwZGF0ZWFibGUge1xuICAgIC8qKiBBIHN0YWNrIG9mIHRoZSBjdXJyZW50IHN0YXRlcyAqL1xuICAgIHByb3RlY3RlZCBzdGFjazogU3RhY2s8U3RhdGU+O1xuICAgIC8qKiBBIG1hcGUgb2Ygc3RhdGUga2V5cyB0byBhY3R1YWwgc3RhdGUgaW5zdGFuY2VzICovXG4gICAgcHJvdGVjdGVkIHN0YXRlTWFwOiBNYXA8U3RhdGU+O1xuICAgIC8qKiBUaGUgY3VycmVudCBzdGF0ZSAqL1xuICAgIHByb3RlY3RlZCBjdXJyZW50U3RhdGU6IFN0YXRlO1xuICAgIC8qKiBBbiBldmVudCByZWNlaXZlciAqL1xuICAgIHByb3RlY3RlZCByZWNlaXZlcjogUmVjZWl2ZXI7XG4gICAgLyoqIEFuIGV2ZW50IGVtaXR0ZXIgKi9cbiAgICBwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcbiAgICAvKiogQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGlzIFN0YXRlTWFjaGluZSBpcyBjdXJyZW50bHkgYWN0aXZlICovXG4gICAgcHJvdGVjdGVkIGFjdGl2ZTogYm9vbGVhbjtcbiAgICAvKiogQSBib29sZWFuIHJlcHJlc2VudGluZyB3aGV0aGVyIG9yIG5vdCB0aGlzIFN0YXRlTWFjaGluZSBzaG91bGQgZW1pdCBhbiBldmVudCBvbiBzdGF0ZSBjaGFuZ2UgKi9cbiAgICBwcm90ZWN0ZWQgZW1pdEV2ZW50T25TdGF0ZUNoYW5nZTogYm9vbGVhbjtcbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGJlIGVtaXR0ZWQgb24gc3RhdGUgY2hhbmdlICovXG4gICAgcHJvdGVjdGVkIHN0YXRlQ2hhbmdlRXZlbnROYW1lOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IFN0YXRlTWFjaGluZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgICAgdGhpcy5zdGF0ZU1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuICAgICAgICB0aGlzLmVtaXRFdmVudE9uU3RhdGVDaGFuZ2UgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBhY3Rpdml0eSBzdGF0ZSBvZiB0aGlzIHN0YXRlIG1hY2hpbmVcbiAgICAgKiBAcGFyYW0gZmxhZyBUcnVlIGlmIHlvdSB3YW50IHRvIHNldCB0aGlzIG1hY2hpbmUgcnVubmluZywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc2V0QWN0aXZlKGZsYWc6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hY3RpdmUgPSBmbGFnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIHRoaXMgc3RhdGUgbWFjaGluZSBlbWl0IGFuIGV2ZW50IGFueSB0aW1lIGl0cyBzdGF0ZSBjaGFuZ2VzXG4gICAgICogQHBhcmFtIHN0YXRlQ2hhbmdlRXZlbnROYW1lIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0XG4gICAgICovXG4gICAgc2V0RW1pdEV2ZW50T25TdGF0ZUNoYW5nZShzdGF0ZUNoYW5nZUV2ZW50TmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW1pdEV2ZW50T25TdGF0ZUNoYW5nZSA9IHRydWU7XG4gICAgICAgIHRoaXMuc3RhdGVDaGFuZ2VFdmVudE5hbWUgPSBzdGF0ZUNoYW5nZUV2ZW50TmFtZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdG9wcyB0aGlzIHN0YXRlIG1hY2hpbmUgZnJvbSBlbWl0dGluZyBldmVudHMgb24gc3RhdGUgY2hhbmdlLlxuICAgICAqL1xuICAgIGNhbmNlbEVtaXRFdmVudE9uU3RhdGVDaGFuZ2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW1pdEV2ZW50T25TdGF0ZUNoYW5nZSA9IGZhbHNlO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGlzIHN0YXRlIG1hY2hpbmUgd2l0aCBhbiBpbml0aWFsIHN0YXRlIGFuZCBzZXRzIGl0IHJ1bm5pbmdcbiAgICAgKiBAcGFyYW0gaW5pdGlhbFN0YXRlIFRoZSBuYW1lIG9mIGluaXRpYWwgc3RhdGUgb2YgdGhlIHN0YXRlIG1hY2hpbmVcbiAgICAgKi9cbiAgICBpbml0aWFsaXplKGluaXRpYWxTdGF0ZTogc3RyaW5nLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGF0ZU1hcC5nZXQoaW5pdGlhbFN0YXRlKSk7XG4gICAgICAgIHRoaXMuY3VycmVudFN0YXRlID0gdGhpcy5zdGFjay5wZWVrKCk7XG4gICAgICAgIHRoaXMuY3VycmVudFN0YXRlLm9uRW50ZXIob3B0aW9ucyk7XG4gICAgICAgIHRoaXMuc2V0QWN0aXZlKHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBzdGF0ZSB0byB0aGlzIHN0YXRlIG1hY2hpbmVcbiAgICAgKiBAcGFyYW0gc3RhdGVOYW1lIFRoZSBuYW1lIG9mIHRoZSBzdGF0ZSB0byBhZGRcbiAgICAgKiBAcGFyYW0gc3RhdGUgVGhlIHN0YXRlIHRvIGFkZFxuICAgICAqL1xuICAgIGFkZFN0YXRlKHN0YXRlTmFtZTogc3RyaW5nLCBzdGF0ZTogU3RhdGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdGF0ZU1hcC5hZGQoc3RhdGVOYW1lLCBzdGF0ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgc3RhdGUgb2YgdGhpcyBzdGF0ZSBtYWNoaW5lIHRvIHRoZSBwcm92aWRlZCBzdHJpbmdcbiAgICAgKiBAcGFyYW0gc3RhdGUgVGhlIHN0cmluZyBuYW1lIG9mIHRoZSBzdGF0ZSB0byBjaGFuZ2UgdG9cbiAgICAgKi9cbiAgICBjaGFuZ2VTdGF0ZShzdGF0ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8vIEV4aXQgdGhlIGN1cnJlbnQgc3RhdGVcbiAgICAgICAgbGV0IG9wdGlvbnMgPSB0aGlzLmN1cnJlbnRTdGF0ZS5vbkV4aXQoKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGNvcnJlY3Qgc3RhdGUgaXMgYXQgdGhlIHRvcCBvZiB0aGUgc3RhY2tcbiAgICAgICAgaWYoc3RhdGUgPT09IFwicHJldmlvdXNcIil7XG4gICAgICAgICAgICAvLyBQb3AgdGhlIGN1cnJlbnQgc3RhdGUgb2ZmIHRoZSBzdGFja1xuICAgICAgICAgICAgdGhpcy5zdGFjay5wb3AoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJldHJpZXZlIHRoZSBuZXcgc3RhdGUgZnJvbSB0aGUgc3RhdGVtYXAgYW5kIHB1dCBpdCBhdCB0aGUgdG9wIG9mIHRoZSBzdGFja1xuICAgICAgICAgICAgdGhpcy5zdGFjay5wb3AoKTtcbiAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCh0aGlzLnN0YXRlTWFwLmdldChzdGF0ZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0cmVpdmUgdGhlIG5ldyBzdGF0ZSBmcm9tIHRoZSBzdGFja1xuICAgICAgICB0aGlzLmN1cnJlbnRTdGF0ZSA9IHRoaXMuc3RhY2sucGVlaygpO1xuXG4gICAgICAgIC8vIEVtaXQgYW4gZXZlbnQgaWYgdHVybmVkIG9uXG4gICAgICAgIGlmKHRoaXMuZW1pdEV2ZW50T25TdGF0ZUNoYW5nZSl7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMuc3RhdGVDaGFuZ2VFdmVudE5hbWUsIHtzdGF0ZTogdGhpcy5jdXJyZW50U3RhdGV9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVudGVyIHRoZSBuZXcgc3RhdGVcbiAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUub25FbnRlcihvcHRpb25zKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGlucHV0LiBUaGlzIGhhcHBlbnMgYXQgdGhlIHZlcnkgYmVnaW5uaW5nIG9mIHRoaXMgc3RhdGUgbWFjaGluZSdzIHVwZGF0ZSBjeWNsZS5cbiAgICAgKiBAcGFyYW0gZXZlbnQgVGhlIGdhbWUgZXZlbnQgdG8gcHJvY2Vzc1xuICAgICAqL1xuICAgIGhhbmRsZUV2ZW50KGV2ZW50OiBHYW1lRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy5hY3RpdmUpe1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50U3RhdGUuaGFuZGxlSW5wdXQoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQGltcGxlbWVudGVkXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIC8vIERpc3RyaWJ1dGUgZXZlbnRzXG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlRXZlbnQoZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVsZWdhdGUgdGhlIHVwZGF0ZSB0byB0aGUgY3VycmVudCBzdGF0ZVxuICAgICAgICB0aGlzLmN1cnJlbnRTdGF0ZS51cGRhdGUoZGVsdGFUKTtcbiAgICB9XG59IiwiLy8gQGlnbm9yZVBhZ2Vcbi8qKlxuICogYSByZXByZXNlbnRhdGlvbiBvZiBUaWxlZCdzIHRpbGVtYXAgZGF0YVxuICovXG5leHBvcnQgY2xhc3MgVGlsZWRUaWxlbWFwRGF0YSB7XG4gICAgaGVpZ2h0OiBudW1iZXI7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICB0aWxlaGVpZ2h0OiBudW1iZXI7XG4gICAgdGlsZXdpZHRoOiBudW1iZXI7XG4gICAgb3JpZW50YXRpb246IHN0cmluZztcbiAgICBsYXllcnM6IEFycmF5PFRpbGVkTGF5ZXJEYXRhPjtcbiAgICB0aWxlc2V0czogQXJyYXk8VGlsZWRUaWxlc2V0RGF0YT47XG59XG5cbi8qKlxuICogQSByZXByZXNlbnRhdGlvbiBvZiBhIGN1c3RvbSBsYXllciBwcm9wZXJ0eSBpbiBhIFRpbGVkIHRpbGVtYXBcbiAqL1xuZXhwb3J0IGNsYXNzIFRpbGVkTGF5ZXJQcm9wZXJ0eSB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHR5cGU6IHN0cmluZztcbiAgICB2YWx1ZTogYW55O1xufVxuXG4vKipcbiAqIEEgcmVwcmVzZW50YXRpb24gb2YgYSB0aWxlc2V0IGluIGEgVGlsZWQgdGlsZW1hcFxuICovXG5leHBvcnQgY2xhc3MgVGlsZWRUaWxlc2V0RGF0YSB7XG4gICAgY29sdW1uczogbnVtYmVyO1xuICAgIHRpbGV3aWR0aDogbnVtYmVyO1xuICAgIHRpbGVoZWlnaHQ6IG51bWJlcjtcbiAgICB0aWxlY291bnQ6IG51bWJlcjtcbiAgICBmaXJzdGdpZDogbnVtYmVyO1xuICAgIGltYWdlaGVpZ2h0OiBudW1iZXI7XG4gICAgaW1hZ2V3aWR0aDogbnVtYmVyO1xuICAgIG1hcmdpbjogbnVtYmVyO1xuICAgIHNwYWNpbmc6IG51bWJlcjtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgaW1hZ2U6IHN0cmluZztcbiAgICB0aWxlcz86IEFycmF5PFRpbGVkQ29sbGVjdGlvblRpbGU+XG59XG5cbi8qKlxuICogQSByZXByZXNlbnRhdGlvbiBvZiBhIGxheWVyIGluIGEgVGlsZWQgdGlsZW1hcFxuICovXG5leHBvcnQgY2xhc3MgVGlsZWRMYXllckRhdGEge1xuICAgIGRhdGE6IG51bWJlcltdO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICBoZWlnaHQ6IG51bWJlcjtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgb3BhY2l0eTogbnVtYmVyO1xuICAgIHZpc2libGU6IGJvb2xlYW47XG4gICAgcHJvcGVydGllczogVGlsZWRMYXllclByb3BlcnR5W107XG4gICAgdHlwZTogc3RyaW5nO1xuICAgIG9iamVjdHM/OiBBcnJheTxUaWxlZE9iamVjdD47XG59XG5cbmV4cG9ydCBjbGFzcyBUaWxlZE9iamVjdCB7XG4gICAgZ2lkOiBudW1iZXI7XG4gICAgaGVpZ2h0OiBudW1iZXI7XG4gICAgd2lkdGg6IG51bWJlcjtcbiAgICBpZDogbnVtYmVyO1xuICAgIG5hbWU6IHN0cmluZzs7XG4gICAgcHJvcGVydGllczogQXJyYXk8VGlsZWRMYXllclByb3BlcnR5PjtcbiAgICByb3RhdGlvbjogbnVtYmVyO1xuICAgIHR5cGU6IHN0cmluZztcbiAgICB2aXNpYmxlOiBib29sZWFuO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBUaWxlZENvbGxlY3Rpb25UaWxlIHtcbiAgICBpZDogbnVtYmVyO1xuICAgIGltYWdlOiBzdHJpbmc7XG4gICAgaW1hZ2VoZWlnaHQ6IG51bWJlcjtcbiAgICBpbWFnZXdpZHRoOiBudW1iZXI7XG59XG4iLCJpbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vVmVjMlwiO1xuaW1wb3J0IHsgVGlsZWRUaWxlc2V0RGF0YSB9IGZyb20gXCIuL1RpbGVkRGF0YVwiO1xuXG4vKipcbiAqIFRoZSBkYXRhIHJlcHJlc2VudGF0aW9uIG9mIGEgVGlsZXNldCBmb3IgdGhlIGdhbWUgZW5naW5lLiBUaGlzIHJlcHJlc2VudHMgb25lIGltYWdlLFxuICogd2l0aCBhIHN0YXJ0SW5kZXggaWYgcmVxdWlyZWQgKGFzIGl0IGlzIHdpdGggVGlsZWQgdXNpbmcgdHdvIGltYWdlcyBpbiBvbmUgdGlsc2V0KS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGlsZXNldCB7XG4gICAgLyoqIFRoZSBrZXkgb2YgdGhlIGltYWdlIHVzZWQgYnkgdGhpcyB0aWxlc2V0ICovXG4gICAgcHJvdGVjdGVkIGltYWdlS2V5OiBzdHJpbmc7XG4gICAgLyoqIFRoZSBzaXplIG9mIHRoZSB0aWxlc2V0IGltYWdlICovXG4gICAgcHJvdGVjdGVkIGltYWdlU2l6ZTogVmVjMjtcbiAgICAvKiogVGhlIGluZGV4IG9mIDB0aCBpbWFnZSBvZiB0aGlzIHRpbGVzZXQgKi9cbiAgICBwcm90ZWN0ZWQgc3RhcnRJbmRleDogbnVtYmVyO1xuICAgIC8qKiBUaGUgaW5kZXggb2YgdGhlIGxhc3QgaW1hZ2Ugb2YgdGhpcyB0aWxzZXQgKi9cbiAgICBwcm90ZWN0ZWQgZW5kSW5kZXg6IG51bWJlcjtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIHRpbGVzIGluIHRoaXMgdGlsZXNldCAqL1xuICAgIHByb3RlY3RlZCB0aWxlU2l6ZTogVmVjMjtcbiAgICAvKiogVGhlIG51bWJlciBvZiByb3dzIGluIHRoaXMgdGlsZXNldCAqL1xuICAgIHByb3RlY3RlZCBudW1Sb3dzOiBudW1iZXI7XG4gICAgLyoqIFRoZSBudW1iZXIgb2YgY29sdW1ucyBpbiB0aGlzIHRpbGVzZXQgKi9cbiAgICBwcm90ZWN0ZWQgbnVtQ29sczogbnVtYmVyO1xuXG4gICAgLy8gVE9ETzogQ2hhbmdlIHRoaXMgdG8gYmUgbW9yZSBnZW5lcmFsIGFuZCB3b3JrIHdpdGggb3RoZXIgdGlsZXNldCBmb3JtYXRzXG4gICAgY29uc3RydWN0b3IodGlsZXNldERhdGE6IFRpbGVkVGlsZXNldERhdGEpe1xuICAgICAgICAvLyBEZWZlciBoYW5kbGluZyBvZiB0aGUgZGF0YSB0byBhIGhlbHBlciBjbGFzc1xuICAgICAgICB0aGlzLmluaXRGcm9tVGlsZWREYXRhKHRpbGVzZXREYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSB0aWxlc2V0IGZyb20gdGhlIGRhdGEgZnJvbSBhIFRpbGVkIGpzb24gZmlsZVxuICAgICAqIEBwYXJhbSB0aWxlZERhdGEgVGhlIHBhcnNlZCBvYmplY3QgZnJvbSBhIFRpbGVkIGpzb24gZmlsZVxuICAgICAqL1xuICAgIGluaXRGcm9tVGlsZWREYXRhKHRpbGVkRGF0YTogVGlsZWRUaWxlc2V0RGF0YSk6IHZvaWQge1xuICAgICAgICB0aGlzLm51bVJvd3MgPSB0aWxlZERhdGEudGlsZWNvdW50L3RpbGVkRGF0YS5jb2x1bW5zO1xuICAgICAgICB0aGlzLm51bUNvbHMgPSB0aWxlZERhdGEuY29sdW1ucztcbiAgICAgICAgdGhpcy5zdGFydEluZGV4ID0gdGlsZWREYXRhLmZpcnN0Z2lkO1xuICAgICAgICB0aGlzLmVuZEluZGV4ID0gdGhpcy5zdGFydEluZGV4ICsgdGlsZWREYXRhLnRpbGVjb3VudCAtIDE7XG4gICAgICAgIHRoaXMudGlsZVNpemUgPSBuZXcgVmVjMih0aWxlZERhdGEudGlsZXdpZHRoLCB0aWxlZERhdGEudGlsZXdpZHRoKTtcbiAgICAgICAgdGhpcy5pbWFnZUtleSA9IHRpbGVkRGF0YS5pbWFnZTtcbiAgICAgICAgdGhpcy5pbWFnZVNpemUgPSBuZXcgVmVjMih0aWxlZERhdGEuaW1hZ2V3aWR0aCwgdGlsZWREYXRhLmltYWdlaGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvKiogXG4gICAgICogR2V0cyB0aGUgaW1hZ2Uga2V5IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRpbGVtYXBcbiAgICAgKiBAcmV0dXJucyBUaGUgaW1hZ2Uga2V5IG9mIHRoaXMgdGlsZW1hcFxuICAgICAqL1xuICAgIGdldEltYWdlS2V5KCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLmltYWdlS2V5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBWZWMyIGNvbnRhaW5pbmcgdGhlIGxlZnQgYW5kIHRvcCBvZmZzZXQgZnJvbSB0aGUgaW1hZ2Ugb3JpZ2luIGZvciB0aGlzIHRpbGUuXG4gICAgICogQHBhcmFtIHRpbGVJbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgZnJvbSBzdGFydEluZGV4IHRvIGVuZEluZGV4IG9mIHRoaXMgdGlsZXNldFxuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSBvZmZzZXQgZm9yIHRoZSBzcGVjaWZpZWQgdGlsZS5cbiAgICAgKi9cbiAgICBnZXRJbWFnZU9mZnNldEZvclRpbGUodGlsZUluZGV4OiBudW1iZXIpOiBWZWMyIHtcbiAgICAgICAgLy8gR2V0IHRoZSB0cnVlIGluZGV4XG4gICAgICAgIGxldCBpbmRleCA9IHRpbGVJbmRleCAtIHRoaXMuc3RhcnRJbmRleDtcbiAgICAgICAgbGV0IHJvdyA9IE1hdGguZmxvb3IoaW5kZXggLyB0aGlzLm51bUNvbHMpO1xuICAgICAgICBsZXQgY29sID0gaW5kZXggJSB0aGlzLm51bUNvbHM7XG4gICAgICAgIGxldCB3aWR0aCA9IHRoaXMudGlsZVNpemUueDtcbiAgICAgICAgbGV0IGhlaWdodCA9IHRoaXMudGlsZVNpemUueTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHBvc2l0aW9uIHRvIHN0YXJ0IGEgY3JvcCBpbiB0aGUgdGlsZXNldCBpbWFnZVxuICAgICAgICBsZXQgbGVmdCA9IGNvbCAqIHdpZHRoO1xuICAgICAgICBsZXQgdG9wID0gcm93ICogaGVpZ2h0O1xuXG4gICAgICAgIHJldHVybiBuZXcgVmVjMihsZWZ0LCB0b3ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHN0YXJ0IGluZGV4XG4gICAgICogQHJldHVybnMgVGhlIHN0YXJ0IGluZGV4XG4gICAgICovXG4gICAgZ2V0U3RhcnRJbmRleCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGFydEluZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHRpbGUgc2V0XG4gICAgICogQHJldHVybnMgQSBWZWMyIGNvbnRhaW5pbmcgdGhlIHRpbGUgc2l6ZVxuICAgICAqL1xuICAgIGdldFRpbGVTaXplKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlU2l6ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGUgdGlsZXNldFxuICAgICAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2Ygcm93c1xuICAgICAqL1xuICAgIGdldE51bVJvd3MoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVtUm93cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgdGlsc2V0XG4gICAgICogQHJldHVybnMgVGhlIG51bWJlciBvZiBjb2x1bW5zXG4gICAgICovXG4gICAgZ2V0TnVtQ29scygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5udW1Db2xzO1xuICAgIH1cblxuICAgIGdldFRpbGVDb3VudCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5lbmRJbmRleCAtIHRoaXMuc3RhcnRJbmRleCArIDE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgb3Igbm90IHRoaXMgdGlsc2V0IGNvbnRhaW5zIHRoZSBzcGVjaWZpZWQgdGlsZSBpbmRleC4gVGhpcyBpcyB1c2VkIGZvciByZW5kZXJpbmcuXG4gICAgICogQHBhcmFtIHRpbGVJbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGUgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHdoZXRoZXIgb3Igbm90IHRoaXMgdGlsc2V0IHVzZXMgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqL1xuICAgIGhhc1RpbGUodGlsZUluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRpbGVJbmRleCA+PSB0aGlzLnN0YXJ0SW5kZXggJiYgdGlsZUluZGV4IDw9IHRoaXMuZW5kSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVyIGEgc2luZ3VsYXIgdGlsZSB3aXRoIGluZGV4IHRpbGVJbmRleCBmcm9tIHRoZSB0aWxlc2V0IGxvY2F0ZWQgYXQgcG9zaXRpb24gZGF0YUluZGV4XG4gICAgICogQHBhcmFtIGN0eCBUaGUgcmVuZGVyaW5nIGNvbnRleHRcbiAgICAgKiBAcGFyYW0gdGlsZUluZGV4IFRoZSB2YWx1ZSBvZiB0aGUgdGlsZSB0byByZW5kZXJcbiAgICAgKiBAcGFyYW0gZGF0YUluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZSBpbiB0aGUgZGF0YSBhcnJheVxuICAgICAqIEBwYXJhbSB3b3JsZFNpemUgVGhlIHNpemUgb2YgdGhlIHdvcmxkXG4gICAgICogQHBhcmFtIG9yaWdpbiBUaGUgdmlld3BvcnQgb3JpZ2luIGluIHRoZSBjdXJyZW50IGxheWVyXG4gICAgICogQHBhcmFtIHNjYWxlIFRoZSBzY2FsZSBvZiB0aGUgdGlsZW1hcFxuICAgICAqL1xuICAgIHJlbmRlclRpbGUoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQsIHRpbGVJbmRleDogbnVtYmVyLCBkYXRhSW5kZXg6IG51bWJlciwgbWF4Q29sczogbnVtYmVyLCBvcmlnaW46IFZlYzIsIHNjYWxlOiBWZWMyLCB6b29tOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGltYWdlID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkuZ2V0SW1hZ2UodGhpcy5pbWFnZUtleSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0cnVlIGluZGV4XG4gICAgICAgIGxldCBpbmRleCA9IHRpbGVJbmRleCAtIHRoaXMuc3RhcnRJbmRleDtcbiAgICAgICAgbGV0IHJvdyA9IE1hdGguZmxvb3IoaW5kZXggLyB0aGlzLm51bUNvbHMpO1xuICAgICAgICBsZXQgY29sID0gaW5kZXggJSB0aGlzLm51bUNvbHM7XG4gICAgICAgIGxldCB3aWR0aCA9IHRoaXMudGlsZVNpemUueDtcbiAgICAgICAgbGV0IGhlaWdodCA9IHRoaXMudGlsZVNpemUueTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHBvc2l0aW9uIHRvIHN0YXJ0IGEgY3JvcCBpbiB0aGUgdGlsZXNldCBpbWFnZVxuICAgICAgICBsZXQgbGVmdCA9IGNvbCAqIHdpZHRoO1xuICAgICAgICBsZXQgdG9wID0gcm93ICogaGVpZ2h0O1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgcG9zaXRpb24gaW4gdGhlIHdvcmxkIHRvIHJlbmRlciB0aGUgdGlsZVxuICAgICAgICBsZXQgeCA9IE1hdGguZmxvb3IoKGRhdGFJbmRleCAlIG1heENvbHMpICogd2lkdGggKiBzY2FsZS54KTtcbiAgICAgICAgbGV0IHkgPSBNYXRoLmZsb29yKE1hdGguZmxvb3IoZGF0YUluZGV4IC8gbWF4Q29scykgKiBoZWlnaHQgKiBzY2FsZS55KTtcbiAgICAgICAgY3R4LmRyYXdJbWFnZShpbWFnZSwgbGVmdCwgdG9wLCB3aWR0aCwgaGVpZ2h0LCBNYXRoLmZsb29yKCh4IC0gb3JpZ2luLngpKnpvb20pLCBNYXRoLmZsb29yKCh5IC0gb3JpZ2luLnkpKnpvb20pLCBNYXRoLmNlaWwod2lkdGggKiBzY2FsZS54ICogem9vbSksIE1hdGguY2VpbChoZWlnaHQgKiBzY2FsZS55ICogem9vbSkpO1xuICAgIH1cbn0iLCJpbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi9VdGlscy9NYXRoVXRpbHNcIjtcblxuLyoqXG4gKiBBIHR3by1kaW1lbnNpb25hbCB2ZWN0b3IgKHgsIHkpXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlYzIge1xuXG5cdC8vIFN0b3JlIHggYW5kIHkgaW4gYW4gYXJyYXlcblx0LyoqIFRoZSBhcnJheSB0aGF0IHN0b3JlcyB0aGUgYWN0dWFsIHZlY3RvciB2YWx1ZXMgeCBhbmQgeSAqL1xuXHRwcml2YXRlIHZlYzogRmxvYXQzMkFycmF5O1xuXG5cdC8qKlx0XG5cdCAqIFdoZW4gdGhpcyB2ZWN0b3IgY2hhbmdlcyBpdHMgdmFsdWUsIGRvIHNvbWV0aGluZ1xuXHQgKi9cblx0cHJpdmF0ZSBvbkNoYW5nZTogRnVuY3Rpb24gPSAoKSA9PiB7fTtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBWZWMyXG5cdCAqIEBwYXJhbSB4IFRoZSB4IHZhbHVlIG9mIHRoZSB2ZWN0b3Jcblx0ICogQHBhcmFtIHkgVGhlIHkgdmFsdWUgb2YgdGhlIHZlY3RvclxuXHQgKi9cblx0Y29uc3RydWN0b3IoeDogbnVtYmVyID0gMCwgeTogbnVtYmVyID0gMCkge1xuXHRcdHRoaXMudmVjID0gbmV3IEZsb2F0MzJBcnJheSgyKTtcblx0XHR0aGlzLnZlY1swXSA9IHg7XG5cdFx0dGhpcy52ZWNbMV0gPSB5O1xuXHR9XG5cblx0Ly8gRXhwb3NlIHggYW5kIHkgd2l0aCBnZXR0ZXJzIGFuZCBzZXR0ZXJzXG5cdGdldCB4KCkge1xuXHRcdHJldHVybiB0aGlzLnZlY1swXTtcblx0fVxuXG5cdHNldCB4KHg6IG51bWJlcikge1xuXHRcdHRoaXMudmVjWzBdID0geDtcblxuXHRcdGlmKHRoaXMub25DaGFuZ2Upe1xuXHRcdFx0dGhpcy5vbkNoYW5nZSgpO1xuXHRcdH1cblx0fVxuXG5cdGdldCB5KCkge1xuXHRcdHJldHVybiB0aGlzLnZlY1sxXTtcblx0fVxuXG5cdHNldCB5KHk6IG51bWJlcikge1xuXHRcdHRoaXMudmVjWzFdID0geTtcblxuXHRcdGlmKHRoaXMub25DaGFuZ2Upe1xuXHRcdFx0dGhpcy5vbkNoYW5nZSgpO1xuXHRcdH1cblx0fVxuXG5cdHN0YXRpYyBnZXQgWkVSTygpIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIoMCwgMCk7XG5cdH1cblxuXHRzdGF0aWMgcmVhZG9ubHkgWkVST19TVEFUSUMgPSBuZXcgVmVjMigwLCAwKTtcblxuXHRzdGF0aWMgZ2V0IElORigpIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIoSW5maW5pdHksIEluZmluaXR5KTtcblx0fVxuXG5cdHN0YXRpYyBnZXQgVVAoKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKDAsIC0xKTtcblx0fVxuXG5cdHN0YXRpYyBnZXQgRE9XTigpIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIoMCwgMSk7XG5cdH1cblxuXHRzdGF0aWMgZ2V0IExFRlQoKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKC0xLCAwKTtcblx0fVxuXG5cdHN0YXRpYyBnZXQgUklHSFQoKSB7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKDEsIDApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBzcXVhcmVkIG1hZ25pdHVkZSBvZiB0aGUgdmVjdG9yLiBUaGlzIHRlbmRzIHRvIGJlIGZhc3Rlciwgc28gdXNlIGl0IGluIHNpdHVhdGlvbnMgd2hlcmUgdGFraW5nIHRoZVxuXHQgKiBzcXVhcmUgcm9vdCBkb2Vzbid0IG1hdHRlciwgbGlrZSBmb3IgY29tcGFyaW5nIGRpc3RhbmNlcy5cblx0ICogQHJldHVybnMgVGhlIHNxdWFyZWQgbWFnbml0dWRlIG9mIHRoZSB2ZWN0b3Jcblx0ICovXG5cdG1hZ1NxKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMueCp0aGlzLnggKyB0aGlzLnkqdGhpcy55O1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBtYWduaXR1ZGUgb2YgdGhlIHZlY3Rvci5cblx0ICogQHJldHVybnMgVGhlIG1hZ25pdHVkZSBvZiB0aGUgdmVjdG9yLlxuXHQgKi9cblx0bWFnKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIE1hdGguc3FydCh0aGlzLm1hZ1NxKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERpdmRlcyB4IGFuZCB5IGJ5IHRoZSBtYWduaXR1ZGUgdG8gb2J0YWluIHRoZSB1bml0IHZlY3RvciBpbiB0aGUgZGlyZWN0aW9uIG9mIHRoaXMgdmVjdG9yLlxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhcyBhIHVuaXQgdmVjdG9yLlxuXHQgKi9cblx0bm9ybWFsaXplKCk6IFZlYzIge1xuXHRcdGlmKHRoaXMueCA9PT0gMCAmJiB0aGlzLnkgPT09IDApIHJldHVybiB0aGlzO1xuXHRcdGxldCBtYWcgPSB0aGlzLm1hZygpO1xuXHRcdHRoaXMueCAvPSBtYWc7XG5cdFx0dGhpcy55IC89IG1hZztcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBXb3JrcyBsaWtlIG5vcm1hbGl6ZSgpLCBidXQgcmV0dXJucyBhIG5ldyBWZWMyXG5cdCAqIEByZXR1cm5zIEEgbmV3IHZlY3RvciB0aGF0IGlzIHRoZSB1bml0IHZlY3RvciBmb3IgdGhpcyBvbmVcblx0ICovXG5cdG5vcm1hbGl6ZWQoKTogVmVjMiB7XG5cdFx0aWYodGhpcy5pc1plcm8oKSl7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9XG5cdFx0XG5cdFx0bGV0IG1hZyA9IHRoaXMubWFnKCk7XG5cdFx0cmV0dXJuIG5ldyBWZWMyKHRoaXMueC9tYWcsIHRoaXMueS9tYWcpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHggYW5kIHkgZWxlbWVudHMgb2YgdGhpcyB2ZWN0b3IgdG8gemVyby5cblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IsIHdpdGggeCBhbmQgeSBzZXQgdG8gemVyby5cblx0ICovXG5cdHplcm8oKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0KDAsIDApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZlY3RvcidzIHggYW5kIHkgYmFzZWQgb24gdGhlIGFuZ2xlIHByb3ZpZGVkLiBHb2VzIGNvdW50ZXIgY2xvY2t3aXNlLlxuXHQgKiBAcGFyYW0gYW5nbGUgVGhlIGFuZ2xlIGluIHJhZGlhbnNcblx0ICogQHBhcmFtIHJhZGl1cyBUaGUgbWFnbml0dWRlIG9mIHRoZSB2ZWN0b3IgYXQgdGhlIHNwZWNpZmllZCBhbmdsZVxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3Rvci5cblx0ICovXG5cdHNldFRvQW5nbGUoYW5nbGU6IG51bWJlciwgcmFkaXVzOiBudW1iZXIgPSAxKTogVmVjMiB7XG5cdFx0dGhpcy54ID0gTWF0aFV0aWxzLmZsb29yVG9QbGFjZShNYXRoLmNvcyhhbmdsZSkqcmFkaXVzLCA1KTtcblx0XHR0aGlzLnkgPSBNYXRoVXRpbHMuZmxvb3JUb1BsYWNlKC1NYXRoLnNpbihhbmdsZSkqcmFkaXVzLCA1KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgdmVjdG9yIHRoYXQgcG9pbnQgZnJvbSB0aGlzIHZlY3RvciB0byBhbm90aGVyIG9uZVxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBwb2ludCB0b1xuXHQgKiBAcmV0dXJucyBBIG5ldyBWZWMyIHRoYXQgcG9pbnRzIGZyb20gdGhpcyB2ZWN0b3IgdG8gdGhlIG9uZSBwcm92aWRlZFxuXHQgKi9cblx0dmVjVG8ob3RoZXI6IFZlYzIpOiBWZWMyIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIob3RoZXIueCAtIHRoaXMueCwgb3RoZXIueSAtIHRoaXMueSk7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgdmVjdG9yIGNvbnRhaW5pbmcgdGhlIGRpcmVjdGlvbiBmcm9tIHRoaXMgdmVjdG9yIHRvIGFub3RoZXJcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gcG9pbnQgdG9cblx0ICogQHJldHVybnMgQSBuZXcgVmVjMiB0aGF0IHBvaW50cyBmcm9tIHRoaXMgdmVjdG9yIHRvIHRoZSBvbmUgcHJvdmlkZWQuIFRoaXMgbmV3IFZlYzIgd2lsbCBiZSBhIHVuaXQgdmVjdG9yLlxuXHQgKi9cblx0ZGlyVG8ob3RoZXI6IFZlYzIpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy52ZWNUbyhvdGhlcikubm9ybWFsaXplKCk7XG5cdH1cblxuXHQvKipcblx0ICogS2VlcHMgdGhlIHZlY3RvcidzIGRpcmVjdGlvbiwgYnV0IHNldHMgaXRzIG1hZ25pdHVkZSB0byBiZSB0aGUgcHJvdmlkZWQgbWFnbml0dWRlXG5cdCAqIEBwYXJhbSBtYWduaXR1ZGUgVGhlIG1hZ25pdHVkZSB0aGUgdmVjdG9yIHNob3VsZCBiZVxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciB3aXRoIGl0cyBtYWduaXR1ZGUgc2V0IHRvIHRoZSBuZXcgbWFnbml0dWRlXG5cdCAqL1xuXHRzY2FsZVRvKG1hZ25pdHVkZTogbnVtYmVyKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMubm9ybWFsaXplKCkuc2NhbGUobWFnbml0dWRlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTY2FsZXMgeCBhbmQgeSBieSB0aGUgbnVtYmVyIHByb3ZpZGVkLCBvciBpZiB0d28gbnVtYmVyIGFyZSBwcm92aWRlZCwgc2NhbGVzIHRoZW0gaW5kaXZpZHVhbGx5LlxuXHQgKiBAcGFyYW0gZmFjdG9yIFRoZSBzY2FsaW5nIGZhY3RvciBmb3IgdGhlIHZlY3Rvciwgb3IgZm9yIG9ubHkgdGhlIHgtY29tcG9uZW50IGlmIHlGYWN0b3IgaXMgcHJvdmlkZWRcblx0ICogQHBhcmFtIHlGYWN0b3IgVGhlIHNjYWxpbmcgZmFjdG9yIGZvciB0aGUgeS1jb21wb25lbnQgb2YgdGhlIHZlY3RvclxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhZnRlciBzY2FsaW5nXG5cdCAqL1xuXHRzY2FsZShmYWN0b3I6IG51bWJlciwgeUZhY3RvcjogbnVtYmVyID0gbnVsbCk6IFZlYzIge1xuXHRcdGlmKHlGYWN0b3IgIT09IG51bGwpe1xuXHRcdFx0dGhpcy54ICo9IGZhY3Rvcjtcblx0XHRcdHRoaXMueSAqPSB5RmFjdG9yO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdHRoaXMueCAqPSBmYWN0b3I7XG5cdFx0dGhpcy55ICo9IGZhY3Rvcjtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgc2NhbGVkIHZlcnNpb24gb2YgdGhpcyB2ZWN0b3Igd2l0aG91dCBtb2RpZnlpbmcgaXQuXG5cdCAqIEBwYXJhbSBmYWN0b3IgVGhlIHNjYWxpbmcgZmFjdG9yIGZvciB0aGUgdmVjdG9yLCBvciBmb3Igb25seSB0aGUgeC1jb21wb25lbnQgaWYgeUZhY3RvciBpcyBwcm92aWRlZFxuXHQgKiBAcGFyYW0geUZhY3RvciBUaGUgc2NhbGluZyBmYWN0b3IgZm9yIHRoZSB5LWNvbXBvbmVudCBvZiB0aGUgdmVjdG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IHZlY3RvciB0aGF0IGhhcyB0aGUgdmFsdWVzIG9mIHRoaXMgdmVjdG9yIGFmdGVyIHNjYWxpbmdcblx0ICovXG5cdHNjYWxlZChmYWN0b3I6IG51bWJlciwgeUZhY3RvcjogbnVtYmVyID0gbnVsbCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLmNsb25lKCkuc2NhbGUoZmFjdG9yLCB5RmFjdG9yKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSb3RhdGVzIHRoZSB2ZWN0b3IgY291bnRlci1jbG9ja3dpc2UgYnkgdGhlIGFuZ2xlIGFtb3VudCBzcGVjaWZpZWRcblx0ICogQHBhcmFtIGFuZ2xlIFRoZSBhbmdsZSB0byByb3RhdGUgYnkgaW4gcmFkaWFuc1xuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhZnRlciByb3RhdGlvbi5cblx0ICovXG5cdHJvdGF0ZUNDVyhhbmdsZTogbnVtYmVyKTogVmVjMiB7XG5cdFx0bGV0IGNzID0gTWF0aC5jb3MoYW5nbGUpO1xuXHRcdGxldCBzbiA9IE1hdGguc2luKGFuZ2xlKTtcblx0XHRsZXQgdGVtcFggPSB0aGlzLngqY3MgLSB0aGlzLnkqc247XG5cdFx0bGV0IHRlbXBZID0gdGhpcy54KnNuICsgdGhpcy55KmNzO1xuXHRcdHRoaXMueCA9IHRlbXBYO1xuXHRcdHRoaXMueSA9IHRlbXBZO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHZlY3RvcnMgY29vcmRpbmF0ZXMgdG8gYmUgdGhlIG9uZXMgcHJvdmlkZWRcblx0ICogQHBhcmFtIHggVGhlIG5ldyB4IHZhbHVlIGZvciB0aGlzIHZlY3RvclxuXHQgKiBAcGFyYW0geSBUaGUgbmV3IHkgdmFsdWUgZm9yIHRoaXMgdmVjdG9yXG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yXG5cdCAqL1xuXHRzZXQoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBWZWMyIHtcblx0XHR0aGlzLnggPSB4O1xuXHRcdHRoaXMueSA9IHk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQ29waWVzIHRoZSB2YWx1ZXMgb2YgdGhlIG90aGVyIFZlYzIgaW50byB0aGlzIG9uZS5cblx0ICogQHBhcmFtIG90aGVyIFRoZSBWZWMyIHRvIGNvcHlcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3Igd2l0aCBpdHMgdmFsdWVzIHNldCB0byB0aGUgdmVjdG9yIHByb3ZpZGVkXG5cdCAqL1xuXHRjb3B5KG90aGVyOiBWZWMyKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0KG90aGVyLngsIG90aGVyLnkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhpcyB2ZWN0b3IgdGhlIGFub3RoZXIgdmVjdG9yXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgVmVjMiB0byBhZGQgdG8gdGhpcyBvbmVcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYWZ0ZXIgYWRkaW5nIHRoZSBvbmUgcHJvdmlkZWRcblx0ICovXG5cdGFkZChvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdHRoaXMueCArPSBvdGhlci54O1xuXHRcdHRoaXMueSArPSBvdGhlci55O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluY3JlbWVudHMgdGhlIGZpZWxkcyBvZiB0aGlzIHZlY3Rvci4gQm90aCBhcmUgaW5jcmVtZW50ZWQgd2l0aCBhLCBpZiBvbmx5IGEgaXMgcHJvdmlkZWQuXG5cdCAqIEBwYXJhbSBhIFRoZSBmaXJzdCBudW1iZXIgdG8gaW5jcmVtZW50IGJ5XG5cdCAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgbnVtYmVyIHRvIGluY3JlbWVudCBieVxuXHQgKiBAcmV0dXJuc3MgVGhpcyB2ZWN0b3IgYWZ0ZXIgaW5jcmVtZW50aW5nXG5cdCAqL1xuXHRpbmMoYTogbnVtYmVyLCBiPzogbnVtYmVyKTogVmVjMiB7XG5cdFx0aWYoYiA9PT0gdW5kZWZpbmVkKXtcblx0XHRcdHRoaXMueCArPSBhO1xuXHRcdFx0dGhpcy55ICs9IGE7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMueCArPSBhO1xuXHRcdFx0dGhpcy55ICs9IGI7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN1YnRyYWN0cyBhbm90aGVyIHZlY3RvciBmcm9tIHRoaXMgdmVjdG9yXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgVmVjMiB0byBzdWJ0cmFjdCBmcm9tIHRoaXMgb25lXG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIGFmdGVyIHN1YnRyYWN0aW5nIHRoZSBvbmUgcHJvdmlkZWRcblx0ICovXG5cdHN1YihvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdHRoaXMueCAtPSBvdGhlci54O1xuXHRcdHRoaXMueSAtPSBvdGhlci55O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIE11bHRpcGxpZXMgdGhpcyB2ZWN0b3Igd2l0aCBhbm90aGVyIHZlY3RvciBlbGVtZW50LXdpc2UuIEluIG90aGVyIHdvcmRzLCB0aGlzLnggKj0gb3RoZXIueCBhbmQgdGhpcy55ICo9IG90aGVyLnlcblx0ICogQHBhcmFtIG90aGVyIFRoZSBWZWMyIHRvIG11bHRpcGx5IHRoaXMgb25lIGJ5XG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIGFmdGVyIG11bHRpcGx5aW5nIGl0cyBjb21wb25lbnRzIGJ5IHRoaXMgb25lXG5cdCAqL1xuXHRtdWx0KG90aGVyOiBWZWMyKTogVmVjMiB7XG5cdFx0dGhpcy54ICo9IG90aGVyLng7XG5cdFx0dGhpcy55ICo9IG90aGVyLnk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRGl2aWRlcyB0aGlzIHZlY3RvciB3aXRoIGFub3RoZXIgdmVjdG9yIGVsZW1lbnQtd2lzZS4gSW4gb3RoZXIgd29yZHMsIHRoaXMueCAvPSBvdGhlci54IGFuZCB0aGlzLnkgLz0gb3RoZXIueVxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBkaXZpZGUgdGhpcyBvbmUgYnlcblx0ICogQHJldHVybnMgVGhpcyB2ZWN0b3IgYWZ0ZXIgZGl2aXNpb25cblx0ICovXG5cdGRpdihvdGhlcjogVmVjMik6IFZlYzIge1xuXHRcdGlmKG90aGVyLnggPT09IDAgfHwgb3RoZXIueSA9PT0gMCkgdGhyb3cgXCJEaXZpZGUgYnkgemVybyBlcnJvclwiO1xuXHRcdHRoaXMueCAvPSBvdGhlci54O1xuXHRcdHRoaXMueSAvPSBvdGhlci55O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIERvZXMgYW4gZWxlbWVudCB3aXNlIHJlbWFpbmRlciBvcGVyYXRpb24gb24gdGhpcyB2ZWN0b3IuIHRoaXMueCAlPSBvdGhlci54IGFuZCB0aGlzLnkgJT0gb3RoZXIueVxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIG90aGVyIHZlY3RvclxuXHQgKiBAcmV0dXJucyB0aGlzIHZlY3RvclxuXHQgKi9cblx0cmVtYWluZGVyKG90aGVyOiBWZWMyKTogVmVjMiB7XG5cdFx0dGhpcy54ID0gdGhpcy54ICUgb3RoZXIueDtcblx0XHR0aGlzLnkgPSB0aGlzLnkgJSBvdGhlci55O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHNxdWFyZWQgZGlzdGFuY2UgYmV0d2VlbiB0aGlzIHZlY3RvciBhbmQgYW5vdGhlciB2ZWN0b3Jcblx0ICogQHBhcmFtIG90aGVyIFRoZSB2ZWN0b3IgdG8gY29tcHV0ZSBkaXN0YW5jZSBzcXVhcmVkIHRvXG5cdCAqIEByZXR1cm5zIFRoZSBzcXVhcmVkIGRpc3RhbmNlIGJldHdlZW4gdGhpcyB2ZWN0b3IgYW5kIHRoZSBvbmUgcHJvdmlkZWRcblx0ICovXG5cdGRpc3RhbmNlU3FUbyhvdGhlcjogVmVjMik6IG51bWJlciB7XG5cdFx0cmV0dXJuICh0aGlzLnggLSBvdGhlci54KSoodGhpcy54IC0gb3RoZXIueCkgKyAodGhpcy55IC0gb3RoZXIueSkqKHRoaXMueSAtIG90aGVyLnkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhpcyB2ZWN0b3IgYW5kIGFub3RoZXIgdmVjdG9yXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgdmVjdG9yIHRvIGNvbXB1dGUgZGlzdGFuY2UgdG9cblx0ICogQHJldHVybnMgVGhlIGRpc3RhbmNlIGJldHdlZW4gdGhpcyB2ZWN0b3IgYW5kIHRoZSBvbmUgcHJvdmlkZWRcblx0ICovXG5cdGRpc3RhbmNlVG8ob3RoZXI6IFZlYzIpOiBudW1iZXIge1xuXHRcdHJldHVybiBNYXRoLnNxcnQodGhpcy5kaXN0YW5jZVNxVG8ob3RoZXIpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBkb3QgcHJvZHVjdCBvZiB0aGlzIHZlY3RvciBhbmQgYW5vdGhlclxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBjb21wdXRlIHRoZSBkb3QgcHJvZHVjdCB3aXRoXG5cdCAqIEByZXR1cm5zIFRoZSBkb3QgcHJvZHVjdCBvZiB0aGlzIHZlY3RvciBhbmQgdGhlIG9uZSBwcm92aWRlZC5cblx0ICovXG5cdGRvdChvdGhlcjogVmVjMik6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMueCpvdGhlci54ICsgdGhpcy55Km90aGVyLnk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgYW5nbGUgY291bnRlci1jbG9ja3dpc2UgaW4gcmFkaWFucyBmcm9tIHRoaXMgdmVjdG9yIHRvIGFub3RoZXIgdmVjdG9yXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgdmVjdG9yIHRvIGNvbXB1dGUgdGhlIGFuZ2xlIHRvXG5cdCAqIEByZXR1cm5zIFRoZSBhbmdsZSwgcm90YXRpbmcgQ0NXLCBmcm9tIHRoaXMgdmVjdG9yIHRvIHRoZSBvdGhlciB2ZWN0b3Jcblx0ICovXG5cdGFuZ2xlVG9DQ1cob3RoZXI6IFZlYzIpOiBudW1iZXIge1xuXHRcdGxldCBkb3QgPSB0aGlzLmRvdChvdGhlcik7XG5cdFx0bGV0IGRldCA9IHRoaXMueCpvdGhlci55IC0gdGhpcy55Km90aGVyLng7XG5cdFx0bGV0IGFuZ2xlID0gLU1hdGguYXRhbjIoZGV0LCBkb3QpO1xuXG5cdFx0aWYoYW5nbGUgPCAwKXtcblx0XHRcdGFuZ2xlICs9IDIqTWF0aC5QSTtcblx0XHR9XG5cblx0XHRyZXR1cm4gYW5nbGU7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHZlY3RvciByb3VuZGVkIHRvIDEgZGVjaW1hbCBwb2ludFxuXHQgKiBAcmV0dXJucyBUaGlzIHZlY3RvciBhcyBhIHN0cmluZ1xuXHQgKi9cblx0dG9TdHJpbmcoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy50b0ZpeGVkKCk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHZlY3RvciByb3VuZGVkIHRvIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIGRlY2ltYWwgcG9pbnRzXG5cdCAqIEBwYXJhbSBudW1EZWNpbWFsUG9pbnRzIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwb2ludHMgdG8gY3JlYXRlIGEgc3RyaW5nIHRvXG5cdCAqIEByZXR1cm5zIFRoaXMgdmVjdG9yIGFzIGEgc3RyaW5nXG5cdCAqL1xuXHR0b0ZpeGVkKG51bURlY2ltYWxQb2ludHM6IG51bWJlciA9IDEpOiBzdHJpbmcge1xuXHRcdHJldHVybiBcIihcIiArIHRoaXMueC50b0ZpeGVkKG51bURlY2ltYWxQb2ludHMpICsgXCIsIFwiICsgdGhpcy55LnRvRml4ZWQobnVtRGVjaW1hbFBvaW50cykgKyBcIilcIjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IHZlY3RvciB3aXRoIHRoZSBzYW1lIGNvb3JkaW5hdGVzIGFzIHRoaXMgb25lLlxuXHQgKiBAcmV0dXJucyBBIG5ldyBWZWMyIHdpdGggdGhlIHNhbWUgdmFsdWVzIGFzIHRoaXMgb25lXG5cdCAqL1xuXHRjbG9uZSgpOiBWZWMyIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIodGhpcy54LCB0aGlzLnkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHZlY3RvciBhbmQgb3RoZXIgaGF2ZSB0aGUgRVhBQ1Qgc2FtZSB4IGFuZCB5IChub3QgYXNzdXJlZCB0byBiZSBzYWZlIGZvciBmbG9hdHMpXG5cdCAqIEBwYXJhbSBvdGhlciBUaGUgdmVjdG9yIHRvIGNoZWNrIGFnYWluc3Rcblx0ICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgZXF1YWxpdHkgb2YgdGhlIHR3byB2ZWN0b3JzXG5cdCAqL1xuXHRzdHJpY3RFcXVhbHMob3RoZXI6IFZlYzIpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy54ID09PSBvdGhlci54ICYmIHRoaXMueSA9PT0gb3RoZXIueTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyB2ZWN0b3IgYW5kIG90aGVyIGhhdmUgdGhlIHNhbWUgeCBhbmQgeVxuXHQgKiBAcGFyYW0gb3RoZXIgVGhlIHZlY3RvciB0byBjaGVjayBhZ2FpbnN0XG5cdCAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIGVxdWFsaXR5IG9mIHRoZSB0d28gdmVjdG9yc1xuXHQgKi9cblx0ZXF1YWxzKG90aGVyOiBWZWMyKTogYm9vbGVhbiB7XG5cdFx0bGV0IHhFcSA9IE1hdGguYWJzKHRoaXMueCAtIG90aGVyLngpIDwgMC4wMDAwMDAxO1xuXHRcdGxldCB5RXEgPSBNYXRoLmFicyh0aGlzLnkgLSBvdGhlci55KSA8IDAuMDAwMDAwMTtcblxuXHRcdHJldHVybiB4RXEgJiYgeUVxO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHZlY3RvciBpcyB0aGUgemVybyB2ZWN0b3IgZXhhY3RseSAobm90IGFzc3VyZWQgdG8gYmUgc2FmZSBmb3IgZmxvYXRzKS5cblx0ICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgZXF1YWxpdHkgb2YgdGhpcyB2ZWN0b3IgYW5kIHRoZSB6ZXJvIHZlY3RvclxuXHQgKi9cblx0c3RyaWN0SXNaZXJvKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLnggPT09IDAgJiYgdGhpcy55ID09PSAwO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIHggYW5kIHkgZm9yIHRoaXMgdmVjdG9yIGFyZSBib3RoIHplcm8uXG5cdCAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIGVxdWFsaXR5IG9mIHRoaXMgdmVjdG9yIGFuZCB0aGUgemVybyB2ZWN0b3Jcblx0ICovXG5cdGlzWmVybygpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gTWF0aC5hYnModGhpcy54KSA8IDAuMDAwMDAwMSAmJiBNYXRoLmFicyh0aGlzLnkpIDwgMC4wMDAwMDAxO1xuXHR9XG5cdFxuXHQvKipcblx0ICogU2V0cyB0aGUgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbmV2ZXIgdGhpcyB2ZWN0b3IgaXMgY2hhbmdlZC5cblx0ICogQHBhcmFtIGYgVGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHQgKi9cblx0c2V0T25DaGFuZ2UoZjogRnVuY3Rpb24pOiB2b2lkIHtcblx0XHR0aGlzLm9uQ2hhbmdlID0gZjtcblx0fVxuXG5cdHRvQXJyYXkoKTogRmxvYXQzMkFycmF5IHtcblx0XHRyZXR1cm4gdGhpcy52ZWM7XG5cdH1cblxuXHQvKipcblx0ICogUGVyZm9ybXMgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjdG9yc1xuXHQgKiBAcGFyYW0gYSBUaGUgZmlyc3QgdmVjdG9yXG5cdCAqIEBwYXJhbSBiIFRoZSBzZWNvbmQgdmVjdG9yXG5cdCAqIEBwYXJhbSB0IFRoZSB0aW1lIG9mIHRoZSBsZXJwLCB3aXRoIDAgYmVpbmcgdmVjdG9yIEEsIGFuZCAxIGJlaW5nIHZlY3RvciBCXG5cdCAqIEByZXR1cm5zIEEgbmV3IFZlYzIgcmVwcmVzZW50aW5nIHRoZSBsZXJwIGJldHdlZW4gdmVjdG9yIGEgYW5kIGIuXG5cdCAqL1xuXHRzdGF0aWMgbGVycChhOiBWZWMyLCBiOiBWZWMyLCB0OiBudW1iZXIpOiBWZWMyIHtcblx0XHRyZXR1cm4gbmV3IFZlYzIoTWF0aFV0aWxzLmxlcnAoYS54LCBiLngsIHQpLCBNYXRoVXRpbHMubGVycChhLnksIGIueSwgdCkpO1xuXHR9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5cbi8qKlxuICogQSB1dGlsIGNsYXNzIGZvciByZW5kZXJpbmcgRGVidWcgbWVzc2FnZXMgdG8gdGhlIGNhbnZhcy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGVidWcge1xuXG5cdC8qKiBBIG1hcCBvZiBsb2cgbWVzc2FnZXMgdG8gZGlzcGxheSBvbiB0aGUgc2NyZWVuICovIFxuXHRwcml2YXRlIHN0YXRpYyBsb2dNZXNzYWdlczogTWFwPHN0cmluZz4gPSBuZXcgTWFwKCk7XG5cblx0LyoqIEFuIGFycmF5IG9mIGdhbWUgbm9kZXMgdG8gcmVuZGVyIGRlYnVnIGluZm8gZm9yICovXG5cdHByaXZhdGUgc3RhdGljIG5vZGVzOiBBcnJheTxHYW1lTm9kZT47XG5cblx0LyoqIFRoZSByZW5kZXJpbmcgY29udGV4dCBmb3IgYW55IGRlYnVnIG1lc3NhZ2VzICovXG5cdHByaXZhdGUgc3RhdGljIGRlYnVnUmVuZGVyaW5nQ29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuXG5cdC8qKlx0VGhlIHNpemUgb2YgdGhlIGRlYnVnIGNhbnZhcyAqL1xuXHRwcml2YXRlIHN0YXRpYyBkZWJ1Z0NhbnZhc1NpemU6IFZlYzI7XG5cblx0LyoqIFRoZSByZW5kZXJpbmcgY29sb3IgZm9yIHRleHQgKi9cblx0cHJpdmF0ZSBzdGF0aWMgZGVmYXVsdFRleHRDb2xvcjogQ29sb3IgPSBDb2xvci5XSElURTtcblxuXHQvKipcblx0ICogQWRkIGEgbWVzc2FnZSB0byBkaXNwbGF5IG9uIHRoZSBkZWJ1ZyBzY3JlZW5cblx0ICogQHBhcmFtIGlkIEEgdW5pcXVlIElEIGZvciB0aGlzIG1lc3NhZ2Vcblx0ICogQHBhcmFtIG1lc3NhZ2VzIFRoZSBtZXNzYWdlcyB0byBwcmludCB0byB0aGUgZGVidWcgc2NyZWVuXG5cdCAqL1xuXHRzdGF0aWMgbG9nKGlkOiBzdHJpbmcsIC4uLm1lc3NhZ2VzOiBhbnkpOiB2b2lkIHtcblx0XHQvLyBsZXQgbWVzc2FnZSA9IFwiXCI7XG5cdFx0Ly8gZm9yKGxldCBpID0gMDsgaSA8IG1lc3NhZ2VzLmxlbmd0aDsgaSsrKXtcblx0XHQvLyBcdG1lc3NhZ2UgKz0gbWVzc2FnZXNbaV0udG9TdHJpbmcoKTtcblx0XHQvLyB9XG5cdFx0Ly8gSm9pbiBhbGwgbWVzc2FnZXMgd2l0aCBzcGFjZXNcblx0XHRsZXQgbWVzc2FnZSA9IG1lc3NhZ2VzLm1hcCgobTogYW55KSA9PiBtLnRvU3RyaW5nKCkpLmpvaW4oXCIgXCIpO1xuXHRcdHRoaXMubG9nTWVzc2FnZXMuYWRkKGlkLCBtZXNzYWdlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEZWxldGVzIGEgYSBrZXkgZnJvbSB0aGUgbG9nIGFuZCBzdG9wcyBpdCBmcm9tIGtlZXBpbmcgdXAgc3BhY2Ugb24gdGhlIHNjcmVlblxuXHQgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBsb2cgaXRlbSB0byBjbGVhclxuXHQgKi9cblx0c3RhdGljIGNsZWFyTG9nSXRlbShpZDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dNZXNzYWdlcy5kZWxldGUoaWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGxpc3Qgb2Ygbm9kZXMgdG8gcmVuZGVyIHdpdGggdGhlIGRlYnVnZ2VyXG5cdCAqIEBwYXJhbSBub2RlcyBUaGUgbmV3IGxpc3Qgb2Ygbm9kZXNcblx0ICovXG5cdHN0YXRpYyBzZXROb2Rlcyhub2RlczogQXJyYXk8R2FtZU5vZGU+KTogdm9pZCB7XG5cdFx0dGhpcy5ub2RlcyA9IG5vZGVzO1xuXHR9XG5cblx0LyoqXG5cdCAqIERyYXdzIGEgYm94IGF0IHRoZSBzcGVjaWZpZWQgcG9zaXRpb25cblx0ICogQHBhcmFtIGNlbnRlciBUaGUgY2VudGVyIG9mIHRoZSBib3hcblx0ICogQHBhcmFtIGhhbGZTaXplIFRoZSBkaW1lbnNpb25zIG9mIHRoZSBib3hcblx0ICogQHBhcmFtIGZpbGxlZCBBIGJvb2xlYW4gZm9yIHdoZXRoZXIgb3Igbm90IHRoZSBib3ggaXMgZmlsbGVkXG5cdCAqIEBwYXJhbSBjb2xvciBUaGUgY29sb3Igb2YgdGhlIGJveCB0byBkcmF3XG5cdCAqL1xuXHRzdGF0aWMgZHJhd0JveChjZW50ZXI6IFZlYzIsIGhhbGZTaXplOiBWZWMyLCBmaWxsZWQ6IGJvb2xlYW4sIGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdGxldCBhbHBoYSA9IHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhID0gY29sb3IuYTtcblxuXHRcdGlmKGZpbGxlZCl7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5maWxsU3R5bGUgPSBjb2xvci50b1N0cmluZygpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbFJlY3QoY2VudGVyLnggLSBoYWxmU2l6ZS54LCBjZW50ZXIueSAtIGhhbGZTaXplLnksIGhhbGZTaXplLngqMiwgaGFsZlNpemUueSoyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGxpbmVXaWR0aCA9IDI7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5saW5lV2lkdGggPSBsaW5lV2lkdGg7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5zdHJva2VTdHlsZSA9IGNvbG9yLnRvU3RyaW5nKCk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5zdHJva2VSZWN0KGNlbnRlci54IC0gaGFsZlNpemUueCwgY2VudGVyLnkgLSBoYWxmU2l6ZS55LCBoYWxmU2l6ZS54KjIsIGhhbGZTaXplLnkqMik7XG5cdFx0fVxuXG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZ2xvYmFsQWxwaGEgPSBhbHBoYTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEcmF3cyBhIGNpcmNsZSBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uXG5cdCAqIEBwYXJhbSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgY2lyY2xlXG5cdCAqIEBwYXJhbSByYWRpdXMgVGhlIGRpbWVuc2lvbnMgb2YgdGhlIGJveFxuXHQgKiBAcGFyYW0gZmlsbGVkIEEgYm9vbGVhbiBmb3Igd2hldGhlciBvciBub3QgdGhlIGNpcmNsZSBpcyBmaWxsZWRcblx0ICogQHBhcmFtIGNvbG9yIFRoZSBjb2xvciBvZiB0aGUgY2lyY2xlXG5cdCAqL1xuXHRzdGF0aWMgZHJhd0NpcmNsZShjZW50ZXI6IFZlYzIsIHJhZGl1czogbnVtYmVyLCBmaWxsZWQ6IGJvb2xlYW4sIGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdGxldCBhbHBoYSA9IHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhO1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhID0gY29sb3IuYTtcblxuXHRcdGlmKGZpbGxlZCl7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5maWxsU3R5bGUgPSBjb2xvci50b1N0cmluZygpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuYmVnaW5QYXRoKCk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5hcmMoY2VudGVyLngsIGNlbnRlci55LCByYWRpdXMsIDAsIDIgKiBNYXRoLlBJKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmNsb3NlUGF0aCgpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRsZXQgbGluZVdpZHRoID0gMjtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmxpbmVXaWR0aCA9IGxpbmVXaWR0aDtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LnN0cm9rZVN0eWxlID0gY29sb3IudG9TdHJpbmcoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmJlZ2luUGF0aCgpO1xuXHRcdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuYXJjKGNlbnRlci54LCBjZW50ZXIueSwgcmFkaXVzLCAwLCAyICogTWF0aC5QSSk7XG5cdFx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5jbG9zZVBhdGgoKTtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LnN0cm9rZSgpO1xuXHRcdH1cblxuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0Lmdsb2JhbEFscGhhID0gYWxwaGE7XG5cdH1cblxuXHQvKipcblx0ICogRHJhd3MgYSByYXkgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvblxuXHQgKiBAcGFyYW0gZnJvbSBUaGUgc3RhcnRpbmcgcG9zaXRpb24gb2YgdGhlIHJheVxuXHQgKiBAcGFyYW0gdG8gVGhlIGVuZGluZyBwb3NpdGlvbiBvZiB0aGUgcmF5XG5cdCAqIEBwYXJhbSBjb2xvciBUaGUgY29sb3Igb2YgdGhlIHJheVxuXHQgKi9cblx0c3RhdGljIGRyYXdSYXkoZnJvbTogVmVjMiwgdG86IFZlYzIsIGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmxpbmVXaWR0aCA9IDI7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuc3Ryb2tlU3R5bGUgPSBjb2xvci50b1N0cmluZygpO1xuXG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuYmVnaW5QYXRoKCk7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQubW92ZVRvKGZyb20ueCwgZnJvbS55KTtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5saW5lVG8odG8ueCwgdG8ueSk7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuY2xvc2VQYXRoKCk7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuc3Ryb2tlKCk7XG5cdH1cblxuXHQvKipcblx0ICogRHJhd3MgYSBwb2ludCBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uXG5cdCAqIEBwYXJhbSBwb3MgVGhlIHBvc2l0aW9uIG9mIHRoZSBwb2ludFxuXHQgKiBAcGFyYW0gY29sb3IgVGhlIGNvbG9yIG9mIHRoZSBwb2ludFxuXHQgKi9cblx0c3RhdGljIGRyYXdQb2ludChwb3M6IFZlYzIsIGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdGxldCBwb2ludFNpemUgPSA2O1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGxTdHlsZSA9IGNvbG9yLnRvU3RyaW5nKCk7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbFJlY3QocG9zLnggLSBwb2ludFNpemUvMiwgcG9zLnkgLSBwb2ludFNpemUvMiwgcG9pbnRTaXplLCBwb2ludFNpemUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGRlZmF1bHQgcmVuZGVyaW5nIGNvbG9yIGZvciB0ZXh0IGZvciB0aGUgZGVidWdnZXJcblx0ICogQHBhcmFtIGNvbG9yIFRoZSBjb2xvciB0byByZW5kZXIgdGhlIHRleHRcblx0ICovXG5cdHN0YXRpYyBzZXREZWZhdWx0VGV4dENvbG9yKGNvbG9yOiBDb2xvcik6IHZvaWQge1xuXHRcdHRoaXMuZGVmYXVsdFRleHRDb2xvciA9IGNvbG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBlcmZvcm1zIGFueSBuZWNlc3Nhcnkgc2V0dXAgb3BlcmF0aW9ucyBvbiB0aGUgRGVidWcgY2FudmFzXG5cdCAqIEBwYXJhbSBjYW52YXMgVGhlIGRlYnVnIGNhbnZhc1xuXHQgKiBAcGFyYW0gd2lkdGggVGhlIGRlc2lyZWQgd2lkdGggb2YgdGhlIGNhbnZhc1xuXHQgKiBAcGFyYW0gaGVpZ2h0IFRoZSBkZXNpcmVkIGhlaWdodCBvZiB0aGUgY2FudmFzXG5cdCAqIEByZXR1cm5zIFRoZSByZW5kZXJpbmcgY29udGV4dCBleHRyYWN0ZWQgZnJvbSB0aGUgY2FudmFzXG5cdCAqL1xuXHRzdGF0aWMgaW5pdGlhbGl6ZURlYnVnQ2FudmFzKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHtcbiAgICAgICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG5cdFx0Y2FudmFzLmhlaWdodCA9IGhlaWdodDtcblx0XHRcblx0XHR0aGlzLmRlYnVnQ2FudmFzU2l6ZSA9IG5ldyBWZWMyKHdpZHRoLCBoZWlnaHQpO1xuXG4gICAgICAgIHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQ7XG5cdH1cblxuXHQvKiogQ2xlYXJzIHRoZSBkZWJ1ZyBjYW52YXMgKi9cblx0c3RhdGljIGNsZWFyQ2FudmFzKCk6IHZvaWQge1xuXHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmNsZWFyUmVjdCgwLCAwLCB0aGlzLmRlYnVnQ2FudmFzU2l6ZS54LCB0aGlzLmRlYnVnQ2FudmFzU2l6ZS55KTtcblx0fVxuXG5cdC8qKiBSZW5kZXJzIHRoZSB0ZXh0IGFuZCBub2RlcyBzZW50IHRvIHRoZSBEZWJ1ZyBzeXN0ZW0gKi9cblx0c3RhdGljIHJlbmRlcigpOiB2b2lkIHtcblx0XHR0aGlzLnJlbmRlclRleHQoKTtcblx0XHR0aGlzLnJlbmRlck5vZGVzKCk7XG5cdH1cblxuXHQvKiogUmVuZGVycyB0aGUgdGV4dCBzZW50IHRvIHRoZSBEZWJ1ZyBjYW52YXMgKi9cblx0c3RhdGljIHJlbmRlclRleHQoKTogdm9pZCB7XG5cdFx0bGV0IHkgPSAyMDtcblx0XHR0aGlzLmRlYnVnUmVuZGVyaW5nQ29udGV4dC5mb250ID0gXCIyMHB4IEFyaWFsXCI7XG5cdFx0dGhpcy5kZWJ1Z1JlbmRlcmluZ0NvbnRleHQuZmlsbFN0eWxlID0gdGhpcy5kZWZhdWx0VGV4dENvbG9yLnRvU3RyaW5nKCk7XG5cblx0XHQvLyBEcmF3IGFsbCBvZiB0aGUgdGV4dFxuXHRcdHRoaXMubG9nTWVzc2FnZXMuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IHtcblx0XHRcdHRoaXMuZGVidWdSZW5kZXJpbmdDb250ZXh0LmZpbGxUZXh0KHRoaXMubG9nTWVzc2FnZXMuZ2V0KGtleSksIDEwLCB5KVxuXHRcdFx0eSArPSAzMDtcdFxuXHRcdH0pO1xuXHR9XG5cblx0LyoqIFJlbmRlcnMgdGhlIG5vZGVzIHJlZ2lzdGVyZWQgd2l0aCB0aGUgZGVidWcgY2FudmFzICovXG5cdHN0YXRpYyByZW5kZXJOb2RlcygpOiB2b2lkIHtcblx0XHRpZih0aGlzLm5vZGVzKXtcblx0XHRcdHRoaXMubm9kZXMuZm9yRWFjaChub2RlID0+IHtcblx0XHRcdFx0bm9kZS5kZWJ1Z1JlbmRlcigpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuXG4vLyBAaWdub3JlUGFnZVxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3RhdHMgZXh0ZW5kcyBPYmplY3Qge1xuICAgIC8vIFRoZSBmcHMgb2YgdGhlIGdhbWUuXG4gICAgcHJpdmF0ZSBzdGF0aWMgcHJldmZwczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBOVU1fUE9JTlRTOiBudW1iZXIgPSA2MDtcbiAgICBwcml2YXRlIHN0YXRpYyBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICBwcml2YXRlIHN0YXRpYyBDQU5WQVNfV0lEVEg6IG51bWJlciA9IDMwMDtcbiAgICBwcml2YXRlIHN0YXRpYyBDQU5WQVNfSEVJR0hUOiBudW1iZXIgPSAzMDA7XG4gICAgcHJpdmF0ZSBzdGF0aWMgc3RhdHNEaXY6IEhUTUxEaXZFbGVtZW50O1xuICAgIHByaXZhdGUgc3RhdGljIGdyYXBoQ2hvaWNlczogSFRNTFNlbGVjdEVsZW1lbnQ7XG5cbiAgICAvLyBRdWFkdHJlZSBzdGF0c1xuICAgIHByaXZhdGUgc3RhdGljIHByZXZDbGVhclRpbWVzOiBBcnJheTxudW1iZXI+O1xuICAgIHByaXZhdGUgc3RhdGljIFNHQ2xlYXJUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBhdmdTR0NsZWFyVGltZTogbnVtYmVyO1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgcHJldkZpbGxUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBTR0ZpbGxUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBhdmdTR0ZpbGxUaW1lOiBudW1iZXI7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBwcmV2VXBkYXRlVGltZXM6IEFycmF5PG51bWJlcj47XG4gICAgcHJpdmF0ZSBzdGF0aWMgU0dVcGRhdGVUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBhdmdTR1VwZGF0ZVRpbWU6IG51bWJlcjtcblxuICAgIHByaXZhdGUgc3RhdGljIHByZXZRdWVyeVRpbWVzOiBBcnJheTxudW1iZXI+O1xuICAgIHByaXZhdGUgc3RhdGljIFNHUXVlcnlUaW1lczogQXJyYXk8bnVtYmVyPjtcbiAgICBwcml2YXRlIHN0YXRpYyBhdmdTR1F1ZXJ5VGltZTogbnVtYmVyO1xuXG4gICAgc3RhdGljIGluaXRTdGF0cygpOiB2b2lkIHtcbiAgICAgICAgbGV0IGNhbnZhcyA9IDxIVE1MQ2FudmFzRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXRzLWNhbnZhc1wiKTtcbiAgICAgICAgY2FudmFzLndpZHRoID0gdGhpcy5DQU5WQVNfV0lEVEg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSB0aGlzLkNBTlZBU19IRUlHSFQ7XG4gICAgICAgIHRoaXMuY3R4ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcblxuICAgICAgICB0aGlzLnN0YXRzRGl2ID0gPEhUTUxEaXZFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RhdHMtZGlzcGxheVwiKTtcblxuICAgICAgICB0aGlzLnByZXZmcHMgPSBuZXcgQXJyYXkoKTtcblxuICAgICAgICB0aGlzLnByZXZDbGVhclRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuU0dDbGVhclRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuYXZnU0dDbGVhclRpbWUgPSAwO1xuXG4gICAgICAgIHRoaXMucHJldkZpbGxUaW1lcyA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLlNHRmlsbFRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuYXZnU0dGaWxsVGltZSA9IDA7XG5cbiAgICAgICAgdGhpcy5wcmV2VXBkYXRlVGltZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5TR1VwZGF0ZVRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuYXZnU0dVcGRhdGVUaW1lID0gMDtcblxuICAgICAgICB0aGlzLnByZXZRdWVyeVRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuU0dRdWVyeVRpbWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuYXZnU0dRdWVyeVRpbWUgPSAwO1xuXG4gICAgICAgIGxldCBjbGVhclRpbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgY2xlYXJUaW1lLnNldEF0dHJpYnV0ZShcImlkXCIsIFwic2djbGVhclwiKTtcbiAgICAgICAgbGV0IGZpbGxUaW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIGZpbGxUaW1lLnNldEF0dHJpYnV0ZShcImlkXCIsIFwic2dmaWxsXCIpO1xuICAgICAgICBsZXQgdXBkYXRlVGltZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICB1cGRhdGVUaW1lLnNldEF0dHJpYnV0ZShcImlkXCIsIFwic2d1cGRhdGVcIik7XG4gICAgICAgIGxldCBxdWVyeVRpbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgcXVlcnlUaW1lLnNldEF0dHJpYnV0ZShcImlkXCIsIFwic2dxdWVyeVwiKTtcbiAgICAgICAgbGV0IGJyMSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgbGV0IGJyMiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcbiAgICAgICAgbGV0IGJyMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJiclwiKTtcblxuICAgICAgICB0aGlzLnN0YXRzRGl2LmFwcGVuZChjbGVhclRpbWUsIGJyMSwgZmlsbFRpbWUsIGJyMiwgdXBkYXRlVGltZSwgYnIzLCBxdWVyeVRpbWUpO1xuXG4gICAgICAgIHRoaXMuZ3JhcGhDaG9pY2VzID0gPEhUTUxTZWxlY3RFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiY2hhcnQtb3B0aW9uXCIpO1xuICAgICAgICBsZXQgb3B0aW9uMSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbjEudmFsdWUgPSBcInByZXZmcHNcIjtcbiAgICAgICAgb3B0aW9uMS5sYWJlbCA9IFwiRlBTXCI7XG4gICAgICAgIGxldCBvcHRpb24yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgb3B0aW9uMi52YWx1ZSA9IFwicHJldkNsZWFyVGltZXNcIjtcbiAgICAgICAgb3B0aW9uMi5sYWJlbCA9IFwiQ2xlYXIgVGltZVwiO1xuICAgICAgICBsZXQgb3B0aW9uMyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbjMudmFsdWUgPSBcInByZXZGaWxsVGltZXNcIjtcbiAgICAgICAgb3B0aW9uMy5sYWJlbCA9IFwiRmlsbCB0aW1lXCI7XG4gICAgICAgIGxldCBvcHRpb240ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgb3B0aW9uNC52YWx1ZSA9IFwicHJldlVwZGF0ZVRpbWVzXCI7XG4gICAgICAgIG9wdGlvbjQubGFiZWwgPSBcIlVwZGF0ZSB0aW1lXCI7XG4gICAgICAgIGxldCBvcHRpb241ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgb3B0aW9uNS52YWx1ZSA9IFwicHJldlF1ZXJ5VGltZXNcIjtcbiAgICAgICAgb3B0aW9uNS5sYWJlbCA9IFwiUXVlcnkgVGltZVwiO1xuICAgICAgICBsZXQgb3B0aW9uQWxsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgb3B0aW9uQWxsLnZhbHVlID0gXCJhbGxcIjtcbiAgICAgICAgb3B0aW9uQWxsLmxhYmVsID0gXCJBbGxcIjtcbiAgICAgICAgdGhpcy5ncmFwaENob2ljZXMuYXBwZW5kKG9wdGlvbjEsIG9wdGlvbjIsIG9wdGlvbjMsIG9wdGlvbjQsIG9wdGlvbjUsIG9wdGlvbkFsbCk7XG4gICAgfVxuXG4gICAgc3RhdGljIHVwZGF0ZUZQUyhmcHM6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnByZXZmcHMucHVzaChmcHMpO1xuICAgICAgICBpZih0aGlzLnByZXZmcHMubGVuZ3RoID4gU3RhdHMuTlVNX1BPSU5UUyl7XG4gICAgICAgICAgICB0aGlzLnByZXZmcHMuc2hpZnQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuU0dDbGVhclRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgdGhpcy5wcmV2Q2xlYXJUaW1lcy5wdXNoKHRoaXMuYXZnU0dDbGVhclRpbWUpO1xuICAgICAgICAgICAgaWYodGhpcy5wcmV2Q2xlYXJUaW1lcy5sZW5ndGggPiB0aGlzLk5VTV9QT0lOVFMpe1xuICAgICAgICAgICAgICAgIHRoaXMucHJldkNsZWFyVGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLlNHRmlsbFRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgdGhpcy5wcmV2RmlsbFRpbWVzLnB1c2godGhpcy5hdmdTR0ZpbGxUaW1lKTtcbiAgICAgICAgICAgIGlmKHRoaXMucHJldkZpbGxUaW1lcy5sZW5ndGggPiB0aGlzLk5VTV9QT0lOVFMpe1xuICAgICAgICAgICAgICAgIHRoaXMucHJldkZpbGxUaW1lcy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKHRoaXMuU0dVcGRhdGVUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMucHJldlVwZGF0ZVRpbWVzLnB1c2godGhpcy5hdmdTR1VwZGF0ZVRpbWUpO1xuICAgICAgICAgICAgaWYodGhpcy5wcmV2VXBkYXRlVGltZXMubGVuZ3RoID4gdGhpcy5OVU1fUE9JTlRTKXtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZVcGRhdGVUaW1lcy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKHRoaXMuU0dRdWVyeVRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgdGhpcy5wcmV2UXVlcnlUaW1lcy5wdXNoKHRoaXMuYXZnU0dRdWVyeVRpbWUpO1xuICAgICAgICAgICAgaWYodGhpcy5wcmV2UXVlcnlUaW1lcy5sZW5ndGggPiB0aGlzLk5VTV9QT0lOVFMpe1xuICAgICAgICAgICAgICAgIHRoaXMucHJldlF1ZXJ5VGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudXBkYXRlU0dTdGF0cygpO1xuICAgIH1cblxuICAgIHN0YXRpYyBsb2coa2V5OiBzdHJpbmcsIGRhdGE6IGFueSk6IHZvaWQge1xuICAgICAgICBpZihrZXkgPT09IFwic2djbGVhclwiKXtcbiAgICAgICAgICAgIHRoaXMuU0dDbGVhclRpbWVzLnB1c2goZGF0YSk7XG4gICAgICAgICAgICBpZih0aGlzLlNHQ2xlYXJUaW1lcy5sZW5ndGggPiAxMDApe1xuICAgICAgICAgICAgICAgIHRoaXMuU0dDbGVhclRpbWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihrZXkgPT09IFwic2dmaWxsXCIpe1xuICAgICAgICAgICAgdGhpcy5TR0ZpbGxUaW1lcy5wdXNoKGRhdGEpO1xuICAgICAgICAgICAgaWYodGhpcy5TR0ZpbGxUaW1lcy5sZW5ndGggPiAxMDApe1xuICAgICAgICAgICAgICAgIHRoaXMuU0dGaWxsVGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKGtleSA9PT0gXCJzZ3VwZGF0ZVwiKXtcbiAgICAgICAgICAgIHRoaXMuU0dVcGRhdGVUaW1lcy5wdXNoKGRhdGEpO1xuICAgICAgICAgICAgaWYodGhpcy5TR1VwZGF0ZVRpbWVzLmxlbmd0aCA+IDEwMCl7XG4gICAgICAgICAgICAgICAgdGhpcy5TR1VwZGF0ZVRpbWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihrZXkgPT09IFwic2dxdWVyeVwiKXtcbiAgICAgICAgICAgIHRoaXMuU0dRdWVyeVRpbWVzLnB1c2goZGF0YSk7XG4gICAgICAgICAgICBpZih0aGlzLlNHUXVlcnlUaW1lcy5sZW5ndGggPiAxMDAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLlNHUXVlcnlUaW1lcy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICBzdGF0aWMgcmVuZGVyKCk6IHZvaWQge1xuICAgICAgICAvLyBEaXNwbGF5IHN0YXRzXG4gICAgICAgIHRoaXMuZHJhd0NoYXJ0cygpO1xuICAgIH1cblxuICAgIHN0YXRpYyBkcmF3Q2hhcnRzKCl7XG4gICAgICAgIHRoaXMuY3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLkNBTlZBU19XSURUSCwgdGhpcy5DQU5WQVNfSEVJR0hUKTtcblxuICAgICAgICBsZXQgcGFyYW1TdHJpbmcgPSB0aGlzLmdyYXBoQ2hvaWNlcy52YWx1ZTtcblxuICAgICAgICBpZihwYXJhbVN0cmluZyA9PT0gXCJwcmV2ZnBzXCIgfHwgcGFyYW1TdHJpbmcgPT09IFwiYWxsXCIpe1xuICAgICAgICAgICAgbGV0IHBhcmFtID0gdGhpcy5wcmV2ZnBzO1xuICAgICAgICAgICAgbGV0IGNvbG9yID0gQ29sb3IuQkxVRS50b1N0cmluZygpO1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2hhcnQocGFyYW0sIGNvbG9yKTtcbiAgICAgICAgfVxuICAgICAgICBpZihwYXJhbVN0cmluZyA9PT0gXCJwcmV2Q2xlYXJUaW1lc1wiIHx8IHBhcmFtU3RyaW5nID09PSBcImFsbFwiKXtcbiAgICAgICAgICAgIGxldCBwYXJhbSA9IHRoaXMucHJldkNsZWFyVGltZXM7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSBDb2xvci5SRUQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NoYXJ0KHBhcmFtLCBjb2xvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYocGFyYW1TdHJpbmcgPT09IFwicHJldkZpbGxUaW1lc1wiIHx8IHBhcmFtU3RyaW5nID09PSBcImFsbFwiKXtcbiAgICAgICAgICAgIGxldCBwYXJhbSA9IHRoaXMucHJldkZpbGxUaW1lcztcbiAgICAgICAgICAgIGxldCBjb2xvciA9IENvbG9yLkdSRUVOLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB0aGlzLmRyYXdDaGFydChwYXJhbSwgY29sb3IpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHBhcmFtU3RyaW5nID09PSBcInByZXZVcGRhdGVUaW1lc1wiIHx8IHBhcmFtU3RyaW5nID09PSBcImFsbFwiKXtcbiAgICAgICAgICAgIGxldCBwYXJhbSA9IHRoaXMucHJldlVwZGF0ZVRpbWVzO1xuICAgICAgICAgICAgbGV0IGNvbG9yID0gQ29sb3IuQ1lBTi50b1N0cmluZygpO1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2hhcnQocGFyYW0sIGNvbG9yKTtcbiAgICAgICAgfVxuICAgICAgICBpZihwYXJhbVN0cmluZyA9PT0gXCJwcmV2UXVlcnlUaW1lc1wiIHx8IHBhcmFtU3RyaW5nID09PSBcImFsbFwiKXtcbiAgICAgICAgICAgIGxldCBwYXJhbSA9IHRoaXMucHJldlF1ZXJ5VGltZXM7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSBDb2xvci5PUkFOR0UudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHRoaXMuZHJhd0NoYXJ0KHBhcmFtLCBjb2xvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgZHJhd0NoYXJ0KHBhcmFtOiBBcnJheTxudW1iZXI+LCBjb2xvcjogc3RyaW5nKXtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBDb2xvci5CTEFDSy50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHgubW92ZVRvKDEwLCAxMCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVUbygxMCwgdGhpcy5DQU5WQVNfSEVJR0hUIC0gMTApO1xuICAgICAgICB0aGlzLmN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlKCk7XG4gICAgICAgIHRoaXMuY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICB0aGlzLmN0eC5tb3ZlVG8oMTAsIHRoaXMuQ0FOVkFTX0hFSUdIVCAtIDEwKTtcbiAgICAgICAgdGhpcy5jdHgubGluZVRvKHRoaXMuQ0FOVkFTX1dJRFRIIC0gMTAsIHRoaXMuQ0FOVkFTX0hFSUdIVCAtIDEwKTtcbiAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpO1xuXG4gICAgICAgIGxldCBtYXggPSBNYXRoLm1heCguLi5wYXJhbSk7XG4gICAgICAgIGxldCBwcmV2WCA9IDEwO1xuICAgICAgICBsZXQgcHJldlkgPSB0aGlzLkNBTlZBU19IRUlHSFQgLSAxMCAtIHBhcmFtWzBdL21heCoodGhpcy5DQU5WQVNfSEVJR0hULTIwKTtcbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjtcblxuICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgcGFyYW0ubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgbGV0IGZwcyA9IHBhcmFtW2ldO1xuICAgICAgICAgICAgbGV0IHggPSAxMCArIGkqKHRoaXMuQ0FOVkFTX1dJRFRIIC0gMjApL3RoaXMuTlVNX1BPSU5UUztcbiAgICAgICAgICAgIGxldCB5ID0gdGhpcy5DQU5WQVNfSEVJR0hUIC0gMTAgLSBmcHMvbWF4Kih0aGlzLkNBTlZBU19IRUlHSFQtMjApXG4gICAgICAgICAgICB0aGlzLmN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIHRoaXMuY3R4Lm1vdmVUbyhwcmV2WCwgcHJldlkpO1xuICAgICAgICAgICAgdGhpcy5jdHgubGluZVRvKHgsIHkpO1xuICAgICAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2UoKTtcblxuICAgICAgICAgICAgcHJldlggPSB4O1xuICAgICAgICAgICAgcHJldlkgPSB5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIHVwZGF0ZVNHU3RhdHMoKXtcbiAgICAgICAgaWYodGhpcy5TR0NsZWFyVGltZXMubGVuZ3RoID4gMCl7XG4gICAgICAgICAgICB0aGlzLmF2Z1NHQ2xlYXJUaW1lID0gdGhpcy5TR0NsZWFyVGltZXMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsKS90aGlzLlNHQ2xlYXJUaW1lcy5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLlNHRmlsbFRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICAgICAgdGhpcy5hdmdTR0ZpbGxUaW1lID0gdGhpcy5TR0ZpbGxUaW1lcy5yZWR1Y2UoKGFjYywgdmFsKSA9PiBhY2MgKyB2YWwpL3RoaXMuU0dGaWxsVGltZXMubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5TR1VwZGF0ZVRpbWVzLmxlbmd0aCA+IDApe1xuICAgICAgICB0aGlzLmF2Z1NHVXBkYXRlVGltZSA9IHRoaXMuU0dVcGRhdGVUaW1lcy5yZWR1Y2UoKGFjYywgdmFsKSA9PiBhY2MgKyB2YWwpL3RoaXMuU0dVcGRhdGVUaW1lcy5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLlNHUXVlcnlUaW1lcy5sZW5ndGggPiAwKXtcbiAgICAgICAgICAgIHRoaXMuYXZnU0dRdWVyeVRpbWUgPSB0aGlzLlNHUXVlcnlUaW1lcy5yZWR1Y2UoKGFjYywgdmFsKSA9PiBhY2MgKyB2YWwpL3RoaXMuU0dRdWVyeVRpbWVzLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2djbGVhclwiKS5pbm5lckhUTUwgPSBcIkF2ZyBTRyBjbGVhciB0aW1lOiBcIiArIHRoaXMuYXZnU0dDbGVhclRpbWU7XG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2dmaWxsXCIpLmlubmVySFRNTCA9IFwiQXZnIFNHIGZpbGwgdGltZTogXCIgKyB0aGlzLmF2Z1NHRmlsbFRpbWU7XG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2d1cGRhdGVcIikuaW5uZXJIVE1MID0gXCJBdmcgU0cgdXBkYXRlIHRpbWU6IFwiICsgdGhpcy5hdmdTR1VwZGF0ZVRpbWU7XG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic2dxdWVyeVwiKS5pbm5lckhUTUwgPSBcIkF2ZyBTRyBxdWVyeSB0aW1lOiBcIiArIHRoaXMuYXZnU0dRdWVyeVRpbWU7XG4gICAgfVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuL0V2ZW50UXVldWVcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4vR2FtZUV2ZW50XCI7XG5cbi8qKlxuICogQW4gZXZlbnQgZW1pdHRlciBvYmplY3Qgb3RoZXIgc3lzdGVtcyBjYW4gdXNlIHRvIGhvb2sgaW50byB0aGUgRXZlbnRRdWV1ZS5cbiAqIFByb3ZpZGVzIGFuIGVhc3kgaW50ZXJmYWNlIGZvciBmaXJpbmcgb2ZmIGV2ZW50cy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRW1pdHRlciB7XG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgRXZlbnRRdWV1ZSAqL1xuXHRwcml2YXRlIGV2ZW50UXVldWU6IEV2ZW50UXVldWU7XG5cblx0LyoqIENyZWF0ZXMgYSBuZXcgRW1pdHRlciAqL1xuXHRjb25zdHJ1Y3Rvcigpe1xuXHRcdHRoaXMuZXZlbnRRdWV1ZSA9IEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbWl0IGFuZCBldmVudCBvZiB0eXBlIGV2ZW50VHlwZSB3aXRoIHRoZSBkYXRhIHBhY2tldCBkYXRhXG5cdCAqIEBwYXJhbSBldmVudFR5cGUgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGZpcmUgb2ZmXG5cdCAqIEBwYXJhbSBkYXRhIEEgQHJlZmVyZW5jZVtNYXBdIG9yIHJlY29yZCBjb250YWluaW5nIGFueSBkYXRhIGFib3V0IHRoZSBldmVudFxuXHQgKi9cblx0ZmlyZUV2ZW50KGV2ZW50VHlwZTogc3RyaW5nLCBkYXRhOiBNYXA8YW55PiB8IFJlY29yZDxzdHJpbmcsIGFueT4gPSBudWxsKTogdm9pZCB7XG5cdFx0dGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KG5ldyBHYW1lRXZlbnQoZXZlbnRUeXBlLCBkYXRhKSk7XG5cdH1cbn0iLCJpbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi9HYW1lRXZlbnRcIjtcbmltcG9ydCBSZWNlaXZlciBmcm9tIFwiLi9SZWNlaXZlclwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBUaGUgbWFpbiBldmVudCBzeXN0ZW0gb2YgdGhlIGdhbWUgZW5naW5lLlxuICogRXZlbnRzIGFyZSBzZW50IHRvIHRoZSBFdmVudFF1ZXVlLCB3aGljaCBoYW5kbGVzIGRpc3RyaWJ1dGlvbiB0byBhbnkgc3lzdGVtcyB0aGF0IGFyZSBsaXN0ZW5pbmcgZm9yIHRob3NlIGV2ZW50cy5cbiAqIFRoaXMgYWxsb3dzIGZvciBoYW5kbGluZyBvZiBpbnB1dCB3aXRob3V0IGhhdmluZyBjbGFzc2VzIGRpcmVjdGx5IGhvb2sgaW50byBqYXZhc2NyaXB0IGV2ZW50IGhhbmRsZXMsIFxuICogYW5kIGFsbG93cyBvdGhlcndpc2Ugc2VwYXJhdGUgY2xhc3NlcyB0byBjb21tdW5pY2F0ZSB3aXRoIGVhY2ggb3RoZXIgY2xlYW5seSwgc3VjaCBhcyBhIFBsYXllciBvYmplY3QgXG4gKiByZXF1ZXN0aW5nIGEgc291bmQgYmUgcGxheWVkIGJ5IHRoZSBhdWRpbyBzeXN0ZW0uXG4gKiBcbiAqIFRoZSBkaXN0cmlidXRpb24gb2YgQHJlZmVyZW5jZVtHYW1lRXZlbnRdcyBoYXBwZW5zIGFzIGZvbGxvd3M6XG4gKiBcbiAqIEV2ZW50cyBhcmUgcmVjaWV2ZWQgdGhyb3VnaG91dCBhIGZyYW1lIGFuZCBhcmUgcXVldWVkIHVwIGJ5IHRoZSBFdmVudFF1ZXVlLlxuICogQXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgbmV4dCBmcmFtZSwgZXZlbnRzIGFyZSBzZW50IG91dCB0byBhbnkgcmVjZWl2ZXJzIHRoYXQgYXJlIGhvb2tlZCBpbnRvIHRoZSBldmVudCB0eXBlLlxuICogQHJlZmVyZW5jZVtSZWNlaXZlcl1zIGFyZSB0aGVuIGZyZWUgdG8gcHJvY2VzcyBldmVudHMgYXMgdGhleSBzZWUgZml0LlxuICogXG4gKiBPdmVyYWxsLCB0aGUgRXZlbnRRdWV1ZSBjYW4gYmUgY29uc2lkZXJlZCBhcyBzb21ldGhpbmcgc2ltaWxhciB0byBhbiBlbWFpbCBzZXJ2ZXIsXG4gKiBhbmQgdGhlIEByZWZlcmVuY2VbUmVjZWl2ZXJdcyBjYW4gYmUgY29uc2lkZXJlZCBhcyB0aGUgY2xpZW50IGluYm94ZXMuXG4gKiBcbiAqIFNlZSBAbGluayhHYW1lIFByb2dyYW1taW5nIFBhdHRlcm5zKShodHRwczovL2dhbWVwcm9ncmFtbWluZ3BhdHRlcm5zLmNvbS9ldmVudC1xdWV1ZS5odG1sKSBmb3IgbW9yZSBkaXNjdXNzaW9uIG9uIEV2ZW50UXVldWVzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEV2ZW50UXVldWUge1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBFdmVudFF1ZXVlID0gbnVsbDtcbiAgICBcbiAgICAvKiogVGhlIG1heGltdW0gbnVtYmVyIG9mIGV2ZW50cyB2aXNpYmxlICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBNQVhfU0laRTogbnVtYmVyO1xuICAgIFxuICAgIC8qKiBUaGUgYWN0dWFsIHF1ZXVlIG9mIGV2ZW50cyAqL1xuICAgIHByaXZhdGUgcTogUXVldWU8R2FtZUV2ZW50PjtcbiAgICBcbiAgICAvKiogVGhlIG1hcCBvZiByZWNlaXZlcnMgcmVnaXN0ZXJlZCBmb3IgYW4gZXZlbnQgbmFtZSAqL1xuXHRwcml2YXRlIHJlY2VpdmVyczogTWFwPEFycmF5PFJlY2VpdmVyPj47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMuTUFYX1NJWkUgPSAxMDA7XG4gICAgICAgIHRoaXMucSA9IG5ldyBRdWV1ZTxHYW1lRXZlbnQ+KHRoaXMuTUFYX1NJWkUpO1xuICAgICAgICB0aGlzLnJlY2VpdmVycyA9IG5ldyBNYXA8QXJyYXk8UmVjZWl2ZXI+PigpO1xuXHR9XG4gICAgXG4gICAgLyoqIFJldHJpZXZlcyB0aGUgaW5zdGFuY2Ugb2YgdGhlIFNpbmdsZXRvbiBFdmVudFF1ZXVlICovXG5cdHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBFdmVudFF1ZXVlIHtcblx0XHRpZih0aGlzLmluc3RhbmNlID09PSBudWxsKXtcblx0XHRcdHRoaXMuaW5zdGFuY2UgPSBuZXcgRXZlbnRRdWV1ZSgpO1xuXHRcdH1cblx0XHRcblx0XHRyZXR1cm4gdGhpcy5pbnN0YW5jZTtcblx0fVxuXG4gICAgLyoqIEFkZHMgYW4gZXZlbnQgdG8gdGhlIEV2ZW50UXVldWUuXG4gICAgICogVGhpcyBpcyBleHBvc2VkIHRvIHRoZSByZXN0IG9mIHRoZSBnYW1lIGVuZ2luZSB0aHJvdWdoIHRoZSBAcmVmZXJlbmNlW0VtaXR0ZXJdIGNsYXNzICovXG4gICAgYWRkRXZlbnQoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQge1xuICAgICAgICB0aGlzLnEuZW5xdWV1ZShldmVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXNzb2NpYXRlcyBhIHJlY2VpdmVyIHdpdGggYSB0eXBlIG9mIGV2ZW50LiBFdmVyeSB0aW1lIHRoaXMgZXZlbnQgYXBwZWFycyBpbiB0aGUgZnV0dXJlLFxuICAgICAqIGl0IHdpbGwgYmUgZ2l2ZW4gdG8gdGhlIHJlY2VpdmVyIChhbmQgYW55IG90aGVycyB3YXRjaGluZyB0aGF0IHR5cGUpLlxuICAgICAqIFRoaXMgaXMgZXhwb3NlZCB0byB0aGUgcmVzdCBvZiB0aGUgZ2FtZSBlbmdpbmUgdGhyb3VnaCB0aGUgQHJlZmVyZW5jZVtSZWNlaXZlcl0gY2xhc3NcbiAgICAgKiBAcGFyYW0gcmVjZWl2ZXIgVGhlIGV2ZW50IHJlY2VpdmVyXG4gICAgICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb3IgdHlwZXMgb2YgZXZlbnRzIHRvIHN1YnNjcmliZSB0b1xuICAgICAqL1xuICAgIHN1YnNjcmliZShyZWNlaXZlcjogUmVjZWl2ZXIsIHR5cGU6IHN0cmluZyB8IEFycmF5PHN0cmluZz4pOiB2b2lkIHtcbiAgICAgICAgaWYodHlwZSBpbnN0YW5jZW9mIEFycmF5KXtcbiAgICAgICAgICAgIC8vIElmIGl0IGlzIGFuIGFycmF5LCBzdWJzY3JpYmUgdG8gYWxsIGV2ZW50IHR5cGVzXG4gICAgICAgICAgICBmb3IobGV0IHQgb2YgdHlwZSl7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRMaXN0ZW5lcihyZWNlaXZlciwgdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmFkZExpc3RlbmVyKHJlY2VpdmVyLCB0eXBlKTtcbiAgICAgICAgfVxuXHR9XG5cbiAgICAvKipcbiAgICAgKiBVbnN1YnNjcmliZXMgdGhlIHNwZWNpZmllZCByZWNlaXZlciBmcm9tIGFsbCBldmVudHMsIG9yIGZyb20gd2hhdGV2ZXIgZXZlbnRzIGFyZSBwcm92aWRlZFxuICAgICAqIEBwYXJhbSByZWNlaXZlciBUaGUgcmVjZWl2ZXIgdG8gdW5zdWJzY3JpYmVcbiAgICAgKiBAcGFyYW0ga2V5cyBUaGUgZXZlbnRzIHRvIHVuc3Vic2NyaWJlIGZyb20uIElmIG5vbmUgYXJlIHByb3ZpZGVkLCB1bnN1YnNjcmliZSBmcm9tIGFsbFxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHJlY2VpdmVyOiBSZWNlaXZlciwgLi4uZXZlbnRzOiBBcnJheTxzdHJpbmc+KTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVjZWl2ZXJzLmZvckVhY2goZXZlbnROYW1lID0+IHtcbiAgICAgICAgICAgIC8vIElmIGtleXMgd2VyZSBwcm92aWRlZCwgb25seSBjb250aW51ZSBpZiB0aGlzIGtleSBpcyBvbmUgb2YgdGhlbVxuICAgICAgICAgICAgaWYoZXZlbnRzLmxlbmd0aCA+IDAgJiYgZXZlbnRzLmluZGV4T2YoZXZlbnROYW1lKSA9PT0gLTEpIHJldHVybjtcblxuICAgICAgICAgICAgLy8gRmluZCB0aGUgaW5kZXggb2Ygb3VyIHJlY2VpdmVyIGZvciB0aGlzIGtleVxuICAgICAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5yZWNlaXZlcnMuZ2V0KGV2ZW50TmFtZSkuaW5kZXhPZihyZWNlaXZlcik7XG5cbiAgICAgICAgICAgIC8vIElmIGFuIGluZGV4IHdhcyBmb3VuZCwgcmVtb3ZlIHRoZSByZWNlaXZlclxuICAgICAgICAgICAgaWYoaW5kZXggIT09IC0xKXtcbiAgICAgICAgICAgICAgICB0aGlzLnJlY2VpdmVycy5nZXQoZXZlbnROYW1lKS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBc3NvY2lhdGUgdGhlIHJlY2VpdmVyIGFuZCB0aGUgdHlwZVxuXHRwcml2YXRlIGFkZExpc3RlbmVyKHJlY2VpdmVyOiBSZWNlaXZlciwgdHlwZTogc3RyaW5nKTogdm9pZCB7XG5cdFx0aWYodGhpcy5yZWNlaXZlcnMuaGFzKHR5cGUpKXtcblx0XHRcdHRoaXMucmVjZWl2ZXJzLmdldCh0eXBlKS5wdXNoKHJlY2VpdmVyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5yZWNlaXZlcnMuYWRkKHR5cGUsIFtyZWNlaXZlcl0pO1xuXHRcdH1cblx0fVxuICAgIFxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB3aGlsZSh0aGlzLnEuaGFzSXRlbXMoKSl7XG4gICAgICAgICAgICAvLyBSZXRyaWV2ZSBlYWNoIGV2ZW50XG5cdFx0XHRsZXQgZXZlbnQgPSB0aGlzLnEuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBJZiBhIHJlY2VpdmVyIGhhcyB0aGlzIGV2ZW50IHR5cGUsIHNlbmQgaXQgdGhlIGV2ZW50XG4gICAgICAgICAgICBpZih0aGlzLnJlY2VpdmVycy5oYXMoZXZlbnQudHlwZSkpe1xuICAgICAgICAgICAgICAgIGZvcihsZXQgcmVjZWl2ZXIgb2YgdGhpcy5yZWNlaXZlcnMuZ2V0KGV2ZW50LnR5cGUpKXtcbiAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZXIucmVjZWl2ZShldmVudCk7XG4gICAgICAgICAgICAgICAgfVxuXHRcdFx0fVxuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBJZiBhIHJlY2VpdmVyIGlzIHN1YnNjcmliZWQgdG8gYWxsIGV2ZW50cywgc2VuZCBpdCB0aGUgZXZlbnRcbiAgICAgICAgICAgIGlmKHRoaXMucmVjZWl2ZXJzLmhhcyhHYW1lRXZlbnRUeXBlLkFMTCkpe1xuICAgICAgICAgICAgICAgIGZvcihsZXQgcmVjZWl2ZXIgb2YgdGhpcy5yZWNlaXZlcnMuZ2V0KEdhbWVFdmVudFR5cGUuQUxMKSl7XG4gICAgICAgICAgICAgICAgICAgIHJlY2VpdmVyLnJlY2VpdmUoZXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCJcblxuLyoqXG4gKiBBIHJlcHJlc2VudGF0aW9uIG9mIGFuIGluLWdhbWUgZXZlbnQgdGhhdCBpcyBwYXNzZWQgdGhyb3VnaCB0aGUgQHJlZmVyZW5jZVtFdmVudFF1ZXVlXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHYW1lRXZlbnQge1xuICAgIC8qKiBUaGUgdHlwZSBvZiB0aGUgZXZlbnQgKi9cbiAgICBwdWJsaWMgdHlwZTogc3RyaW5nO1xuICAgIC8qKiBUaGUgZGF0YSBjb250YWluZWQgYnkgdGhlIGV2ZW50ICovXG4gICAgcHVibGljIGRhdGE6IE1hcDxhbnk+O1xuICAgIC8qKiBUaGUgdGltZSBvZiB0aGUgZXZlbnQgaW4gbXMgKi9cblx0cHVibGljIHRpbWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgR2FtZUV2ZW50LlxuICAgICAqIFRoaXMgaXMgaGFuZGxlZCBpbXBsaWNpdGx5IHRocm91Z2ggdGhlIEByZWZlcmVuY2VbRW1pdHRlcl0gY2xhc3NcbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiB0aGUgR2FtZUV2ZW50XG4gICAgICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgY29udGFpbmVkIGJ5IHRoZSBHYW1lRXZlbnRcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih0eXBlOiBzdHJpbmcsIGRhdGE6IE1hcDxhbnk+IHwgUmVjb3JkPHN0cmluZywgYW55PiA9IG51bGwpIHtcbiAgICAgICAgLy8gUGFyc2UgdGhlIGdhbWUgZXZlbnQgZGF0YVxuICAgICAgICBpZiAoZGF0YSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gbmV3IE1hcDxhbnk+KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoIShkYXRhIGluc3RhbmNlb2YgTWFwKSl7XG4gICAgICAgICAgICAvLyBkYXRhIGlzIGEgcmF3IG9iamVjdCwgdW5wYWNrXG4gICAgICAgICAgICB0aGlzLmRhdGEgPSBuZXcgTWFwPGFueT4oKTtcbiAgICAgICAgICAgIGZvcihsZXQga2V5IGluIGRhdGEpe1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YS5hZGQoa2V5LCBkYXRhW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgIHRoaXMudGltZSA9IERhdGUubm93KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHRoZSB0eXBlIG9mIHRoZSBHYW1lRXZlbnRcbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIEdhbWVFdmVudCBpcyB0aGUgc3BlY2lmaWVkIHR5cGUsIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBpc1R5cGUodHlwZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGUgPT09IHR5cGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGlzIEdhbWVFdmVudCBhcyBhIHN0cmluZ1xuICAgICAqIEByZXR1cm5zIFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIEdhbWVFdmVudFxuICAgICAqL1xuICAgIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGUgKyBcIjogQFwiICsgdGhpcy50aW1lO1xuICAgIH1cbn0iLCIvLyBAaWdub3JlUGFnZVxuXG5leHBvcnQgZW51bSBHYW1lRXZlbnRUeXBlIHtcblx0LyoqXG5cdCAqIE1vdXNlIERvd24gZXZlbnQuIEhhcyBkYXRhOiB7cG9zaXRpb246IFZlYzIgLSBNb3VzZSBQb3NpdGlvbn1cblx0ICovXG5cdE1PVVNFX0RPV04gPSBcIm1vdXNlX2Rvd25cIixcblx0LyoqXG5cdCAqIE1vdXNlIFVwIGV2ZW50LiBIYXMgZGF0YToge3Bvc2l0aW9uOiBWZWMyIC0gTW91c2UgUG9zaXRpb259XG5cdCAqL1xuXHRNT1VTRV9VUCA9IFwibW91c2VfdXBcIixcblx0LyoqXG5cdCAqIE1vdXNlIE1vdmUgZXZlbnQuIEhhcyBkYXRhOiB7cG9zaXRpb246IFZlYzIgLSBNb3VzZSBQb3NpdGlvbn1cblx0ICovXG5cdE1PVVNFX01PVkUgPSBcIm1vdXNlX21vdmVcIixcblxuXHQvKipcblx0ICogS2V5IERvd24gZXZlbnQuIEhhcyBkYXRhOiB7a2V5OiBzdHJpbmcgLSBUaGUga2V5IHRoYXQgaXMgZG93bn1cblx0ICovXG5cdEtFWV9ET1dOID0gXCJrZXlfZG93blwiLFxuXG5cdC8qKlxuXHQgKiBLZXkgVXAgZXZlbnQuIEhhcyBkYXRhOiB7a2V5OiBzdHJpbmcgLSBUaGUga2V5IHRoYXQgaXMgdXB9XG5cdCAqL1xuXHRLRVlfVVAgPSBcImtleV91cFwiLFxuXG5cdC8qKlxuXHQgKiBDYW52YXMgQmx1ciBldmVudC4gSGFzIGRhdGE6IHt9XG5cdCAqL1xuXHRDQU5WQVNfQkxVUiA9IFwiY2FudmFzX2JsdXJcIixcblxuXHQvKipcblx0ICogTW91c2Ugd2hlZWwgdXAgZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0V0hFRUxfVVAgPSBcIndoZWVsX3VwXCIsXG5cblx0LyoqXG5cdCAqIE1vdXNlIHdoZWVsIGRvd24gZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0V0hFRUxfRE9XTiA9IFwid2hlZWxfZG93blwiLFxuXG5cdC8qKlxuXHQgKiBTdGFydCBSZWNvcmRpbmcgZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0U1RBUlRfUkVDT1JESU5HID0gXCJzdGFydF9yZWNvcmRpbmdcIixcblxuXHQvKipcblx0ICogU3RvcCBSZWNvcmRpbmcgZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0U1RPUF9SRUNPUkRJTkcgPSBcInN0b3BfcmVjb3JkaW5nXCIsXG5cdFxuXHQvKipcblx0ICogUGxheSBSZWNvcmRpbmcgZXZlbnQuIEhhcyBkYXRhOiB7fVxuXHQgKi9cblx0UExBWV9SRUNPUkRJTkcgPSBcInBsYXlfcmVjb3JkaW5nXCIsXG5cblx0LyoqXG5cdCAqIFBsYXkgU291bmQgZXZlbnQuIEhhcyBkYXRhOiB7a2V5OiBzdHJpbmcsIGxvb3A6IGJvb2xlYW4sIGhvbGRSZWZlcmVuY2U6IGJvb2xlYW4gfVxuXHQgKi9cblx0UExBWV9TT1VORCA9IFwicGxheV9zb3VuZFwiLFxuXG5cdC8qKlxuXHQgKiBQbGF5IFNvdW5kIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nfVxuXHQgKi9cblx0U1RPUF9TT1VORCA9IFwic3RvcF9zb3VuZFwiLFxuXG5cdC8qKlxuXHQgKiBQbGF5IFNvdW5kIGV2ZW50LiBIYXMgZGF0YToge2tleTogc3RyaW5nLCBsb29wOiBib29sZWFuLCBob2xkUmVmZXJlbmNlOiBib29sZWFuLCBjaGFubmVsOiBBdWRpb0NoYW5uZWxUeXBlIH1cblx0ICovXG4gXHRQTEFZX1NGWCA9IFwicGxheV9zZnhcIixcblxuIFx0LyoqXG5cdCAqIFBsYXkgU291bmQgZXZlbnQuIEhhcyBkYXRhOiB7a2V5OiBzdHJpbmcsIGxvb3A6IGJvb2xlYW4sIGhvbGRSZWZlcmVuY2U6IGJvb2xlYW4gfVxuXHQgKi9cbiAgXHRQTEFZX01VU0lDID0gXCJwbGF5X211c2ljXCIsXG5cblx0LyoqXG5cdCAqIE11dGUgYXVkaW8gY2hhbm5lbCBldmVudC4gSGFzIGRhdGE6IHtjaGFubmVsOiBBdWRpb0NoYW5uZWxUeXBlfVxuXHQgKi9cblx0TVVURV9DSEFOTkVMID0gXCJtdXRlX2NoYW5uZWxcIixcblxuXHQvKipcblx0ICogVW5tdXRlIGF1ZGlvIGNoYW5uZWwgZXZlbnQuIEhhcyBkYXRhOiB7Y2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZX1cblx0ICovXG5cdFVOTVVURV9DSEFOTkVMID0gXCJ1bm11dGVfY2hhbm5lbFwiLFxuXG5cdC8qKlxuXHQgKiBFbmNvbXBhc3NlcyBhbGwgZXZlbnQgdHlwZXMuIFVzZWQgZm9yIHJlY2VpdmVycyBvbmx5LlxuXHQgKi9cblx0QUxMID0gXCJhbGxcIixcbn0iLCJpbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IEV2ZW50UXVldWUgZnJvbSBcIi4vRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi9HYW1lRXZlbnRcIjtcblxuLyoqXG4gKiBSZWNlaXZlcyBzdWJzY3JpYmVkIGV2ZW50cyBmcm9tIHRoZSBFdmVudFF1ZXVlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWNlaXZlciB7XG5cdC8qKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgZXZlbnRzIHRoaXMgUmVjZWl2ZXIgY2FuIGhvbGQgYXQgb25lIHRpbWUgKi9cblx0cmVhZG9ubHkgTUFYX1NJWkU6IG51bWJlcjtcblxuXHQvKiogVGhlIGluYm94IG9mIHRoZSBSZWNlaXZlciAqL1xuXHRwcml2YXRlIHE6IFF1ZXVlPEdhbWVFdmVudD47XG5cblx0LyoqIENyZWF0ZXMgYSBuZXcgUmVjZWl2ZXIgKi9cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLk1BWF9TSVpFID0gMTAwO1xuICAgICAgICB0aGlzLnEgPSBuZXcgUXVldWUodGhpcy5NQVhfU0laRSk7XG5cdH1cblxuXHRkZXN0cm95KCl7XG5cdFx0RXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpLnVuc3Vic2NyaWJlKHRoaXMpO1xuXHR9XG5cdFxuXHQvKipcblx0ICogQWRkcyB0aGVzZSB0eXBlcyBvZiBldmVudHMgdG8gdGhpcyByZWNlaXZlcidzIHF1ZXVlIGV2ZXJ5IHVwZGF0ZS5cblx0ICogQHBhcmFtIGV2ZW50VHlwZXMgVGhlIHR5cGVzIG9mIGV2ZW50cyB0aGlzIHJlY2VpdmVyIHdpbGwgYmUgc3Vic2NyaWJlZCB0b1xuXHQgKi9cblx0c3Vic2NyaWJlKGV2ZW50VHlwZXM6IHN0cmluZyB8IEFycmF5PHN0cmluZz4pOiB2b2lkIHtcblx0XHRFdmVudFF1ZXVlLmdldEluc3RhbmNlKCkuc3Vic2NyaWJlKHRoaXMsIGV2ZW50VHlwZXMpO1xuXHRcdHRoaXMucS5jbGVhcigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYW4gZXZlbnQgdG8gdGhlIHF1ZXVlIG9mIHRoaXMgcmVjaWV2ZXIuIFRoaXMgaXMgdXNlZCBieSB0aGUgQHJlZmVyZW5jZVtFdmVudFF1ZXVlXSB0byBkaXN0cmlidXRlIGV2ZW50c1xuXHQgKiBAcGFyYW0gZXZlbnQgVGhlIGV2ZW50IHRvIHJlY2VpdmVcblx0ICovXG5cdHJlY2VpdmUoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQge1xuXHRcdHRyeXtcblx0XHR0aGlzLnEuZW5xdWV1ZShldmVudCk7XG5cdFx0fSBjYXRjaChlKXtcblx0XHRcdGNvbnNvbGUud2FybihcIlJlY2VpdmVyIG92ZXJmbG93IGZvciBldmVudCBcIiArIGV2ZW50LnRvU3RyaW5nKCkpO1xuXHRcdFx0dGhyb3cgZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmV0cmlldmVzIHRoZSBuZXh0IGV2ZW50IGZyb20gdGhlIHJlY2VpdmVyJ3MgcXVldWVcblx0ICogQHJldHVybnMgVGhlIG5leHQgR2FtZUV2ZW50XG5cdCAqL1xuXHRnZXROZXh0RXZlbnQoKTogR2FtZUV2ZW50IHtcblx0XHRyZXR1cm4gdGhpcy5xLmRlcXVldWUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMb29rcyBhdCB0aGUgbmV4dCBldmVudCBpbiB0aGUgcmVjZWl2ZXIncyBxdWV1ZSwgYnV0IGRvZXNuJ3QgcmVtb3ZlIGl0IGZyb20gdGhlIHF1ZXVlXG5cdCAqIEByZXR1cm5zIFRoZSBuZXh0IEdhbWVFdmVudFxuXHQgKi9cblx0cGVla05leHRFdmVudCgpOiBHYW1lRXZlbnQge1xuXHRcdHJldHVybiB0aGlzLnEucGVla05leHQoKVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcmVjZWl2ZXIgaGFzIGFueSBldmVudHMgaW4gaXRzIHF1ZXVlXG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHJlY2VpdmVyIGhhcyBhbm90aGVyIGV2ZW50LCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdGhhc05leHRFdmVudCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5xLmhhc0l0ZW1zKCk7XG5cdH1cblxuXHQvKipcblx0ICogSWdub3JlIGFsbCBldmVudHMgdGhpcyBmcmFtZVxuXHQgKi9cblx0aWdub3JlRXZlbnRzKCk6IHZvaWQge1xuXHRcdHRoaXMucS5jbGVhcigpO1xuXHR9XG59IiwiaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEV2ZW50UXVldWUgZnJvbSBcIi4uL0V2ZW50cy9FdmVudFF1ZXVlXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBSZWNlaXZlcyBpbnB1dCBldmVudHMgZnJvbSB0aGUgQHJlZmVyZW5jZVtFdmVudFF1ZXVlXSBhbmQgYWxsb3dzIGZvciBlYXN5IGFjY2VzcyBvZiBpbmZvcm1hdGlvbiBhYm91dCBpbnB1dCBieSBvdGhlciBzeXN0ZW1zXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElucHV0IHtcblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VQcmVzc2VkOiBib29sZWFuO1xuXHRwcml2YXRlIHN0YXRpYyBtb3VzZUp1c3RQcmVzc2VkOiBib29sZWFuO1xuXHRwcml2YXRlIHN0YXRpYyBtb3VzZUJ1dHRvblByZXNzZWQ6IG51bWJlcjtcblxuXHRwcml2YXRlIHN0YXRpYyBrZXlKdXN0UHJlc3NlZDogTWFwPGJvb2xlYW4+O1xuXHRwcml2YXRlIHN0YXRpYyBrZXlQcmVzc2VkOiBNYXA8Ym9vbGVhbj47XG5cblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VQb3NpdGlvbjogVmVjMjtcblx0cHJpdmF0ZSBzdGF0aWMgbW91c2VQcmVzc1Bvc2l0aW9uOiBWZWMyO1xuXG5cdHByaXZhdGUgc3RhdGljIHNjcm9sbERpcmVjdGlvbjogbnVtYmVyO1xuXHRwcml2YXRlIHN0YXRpYyBqdXN0U2Nyb2xsZWQ6IGJvb2xlYW47XG5cblx0cHJpdmF0ZSBzdGF0aWMgZXZlbnRRdWV1ZTogRXZlbnRRdWV1ZTtcblx0cHJpdmF0ZSBzdGF0aWMgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXHRwcml2YXRlIHN0YXRpYyB2aWV3cG9ydDogVmlld3BvcnQ7XG5cblx0cHJpdmF0ZSBzdGF0aWMga2V5TWFwOiBNYXA8QXJyYXk8c3RyaW5nPj47XG5cblx0cHJpdmF0ZSBzdGF0aWMga2V5c0Rpc2FibGVkOiBib29sZWFuO1xuXHRwcml2YXRlIHN0YXRpYyBtb3VzZURpc2FibGVkOiBib29sZWFuO1xuXG5cdC8qKlxuXHQgKiBJbml0aWFsaXplcyB0aGUgSW5wdXQgb2JqZWN0XG5cdCAqIEBwYXJhbSB2aWV3cG9ydCBBIHJlZmVyZW5jZSB0byB0aGUgdmlld3BvcnQgb2YgdGhlIGdhbWVcblx0ICovXG5cdHN0YXRpYyBpbml0aWFsaXplKHZpZXdwb3J0OiBWaWV3cG9ydCwga2V5TWFwOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCBhbnk+Pikge1xuXHRcdElucHV0LnZpZXdwb3J0ID0gdmlld3BvcnQ7XG5cdFx0SW5wdXQubW91c2VQcmVzc2VkID0gZmFsc2U7XG5cdFx0SW5wdXQubW91c2VKdXN0UHJlc3NlZCA9IGZhbHNlO1xuXHRcdElucHV0LnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG5cdFx0SW5wdXQua2V5SnVzdFByZXNzZWQgPSBuZXcgTWFwPGJvb2xlYW4+KCk7XG5cdFx0SW5wdXQua2V5UHJlc3NlZCA9IG5ldyBNYXA8Ym9vbGVhbj4oKTtcblx0XHRJbnB1dC5tb3VzZVBvc2l0aW9uID0gbmV3IFZlYzIoMCwgMCk7XG5cdFx0SW5wdXQubW91c2VQcmVzc1Bvc2l0aW9uID0gbmV3IFZlYzIoMCwgMCk7XG5cdFx0SW5wdXQuc2Nyb2xsRGlyZWN0aW9uID0gMDtcblx0XHRJbnB1dC5qdXN0U2Nyb2xsZWQgPSBmYWxzZTtcblx0XHRJbnB1dC5rZXlzRGlzYWJsZWQgPSBmYWxzZTtcblx0XHRJbnB1dC5tb3VzZURpc2FibGVkID0gZmFsc2U7XG5cblx0XHQvLyBJbml0aWFsaXplIHRoZSBrZXltYXBcblx0XHRJbnB1dC5rZXlNYXAgPSBuZXcgTWFwKCk7XG5cblx0XHQvLyBBZGQgYWxsIGtleXMgdG8gdGhlIGtleW1hcFxuXHRcdGZvciAobGV0IGVudHJ5IGluIGtleU1hcCkge1xuXHRcdFx0bGV0IG5hbWUgPSBrZXlNYXBbZW50cnldLm5hbWU7XG5cdFx0XHRsZXQga2V5cyA9IGtleU1hcFtlbnRyeV0ua2V5cztcblx0XHRcdElucHV0LmtleU1hcC5hZGQobmFtZSwga2V5cyk7XG5cdFx0fVxuXG5cdFx0SW5wdXQuZXZlbnRRdWV1ZSA9IEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKTtcblx0XHQvLyBTdWJzY3JpYmUgdG8gYWxsIGlucHV0IGV2ZW50c1xuXHRcdElucHV0LmV2ZW50UXVldWUuc3Vic2NyaWJlKElucHV0LnJlY2VpdmVyLCBbR2FtZUV2ZW50VHlwZS5NT1VTRV9ET1dOLCBHYW1lRXZlbnRUeXBlLk1PVVNFX1VQLCBHYW1lRXZlbnRUeXBlLk1PVVNFX01PVkUsXG5cdFx0R2FtZUV2ZW50VHlwZS5LRVlfRE9XTiwgR2FtZUV2ZW50VHlwZS5LRVlfVVAsIEdhbWVFdmVudFR5cGUuQ0FOVkFTX0JMVVIsIEdhbWVFdmVudFR5cGUuV0hFRUxfVVAsIEdhbWVFdmVudFR5cGUuV0hFRUxfRE9XTl0pO1xuXHR9XG5cblx0c3RhdGljIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIFJlc2V0IHRoZSBqdXN0UHJlc3NlZCB2YWx1ZXMgdG8gZmFsc2Vcblx0XHRJbnB1dC5tb3VzZUp1c3RQcmVzc2VkID0gZmFsc2U7XG5cdFx0SW5wdXQua2V5SnVzdFByZXNzZWQuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IElucHV0LmtleUp1c3RQcmVzc2VkLnNldChrZXksIGZhbHNlKSk7XG5cdFx0SW5wdXQuanVzdFNjcm9sbGVkID0gZmFsc2U7XG5cdFx0SW5wdXQuc2Nyb2xsRGlyZWN0aW9uID0gMDtcblxuXHRcdHdoaWxlIChJbnB1dC5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSkge1xuXHRcdFx0bGV0IGV2ZW50ID0gSW5wdXQucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG5cblx0XHRcdC8vIEhhbmRsZSBlYWNoIGV2ZW50IHR5cGVcblx0XHRcdGlmIChldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLk1PVVNFX0RPV04pIHtcblx0XHRcdFx0SW5wdXQubW91c2VKdXN0UHJlc3NlZCA9IHRydWU7XG5cdFx0XHRcdElucHV0Lm1vdXNlUHJlc3NlZCA9IHRydWU7XG5cdFx0XHRcdElucHV0Lm1vdXNlUHJlc3NQb3NpdGlvbiA9IGV2ZW50LmRhdGEuZ2V0KFwicG9zaXRpb25cIik7XG5cdFx0XHRcdElucHV0Lm1vdXNlQnV0dG9uUHJlc3NlZCA9IGV2ZW50LmRhdGEuZ2V0KFwiYnV0dG9uXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5NT1VTRV9VUCkge1xuXHRcdFx0XHRJbnB1dC5tb3VzZVByZXNzZWQgPSBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuTU9VU0VfTU9WRSkge1xuXHRcdFx0XHRJbnB1dC5tb3VzZVBvc2l0aW9uID0gZXZlbnQuZGF0YS5nZXQoXCJwb3NpdGlvblwiKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuS0VZX0RPV04pIHtcblx0XHRcdFx0bGV0IGtleSA9IGV2ZW50LmRhdGEuZ2V0KFwia2V5XCIpO1xuXHRcdFx0XHQvLyBIYW5kbGUgc3BhY2UgYmFyXG5cdFx0XHRcdGlmIChrZXkgPT09IFwiIFwiKSB7XG5cdFx0XHRcdFx0a2V5ID0gXCJzcGFjZVwiO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICghSW5wdXQua2V5UHJlc3NlZC5nZXQoa2V5KSkge1xuXHRcdFx0XHRcdElucHV0LmtleUp1c3RQcmVzc2VkLnNldChrZXksIHRydWUpO1xuXHRcdFx0XHRcdElucHV0LmtleVByZXNzZWQuc2V0KGtleSwgdHJ1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuS0VZX1VQKSB7XG5cdFx0XHRcdGxldCBrZXkgPSBldmVudC5kYXRhLmdldChcImtleVwiKTtcblx0XHRcdFx0Ly8gSGFuZGxlIHNwYWNlIGJhclxuXHRcdFx0XHRpZiAoa2V5ID09PSBcIiBcIikge1xuXHRcdFx0XHRcdGtleSA9IFwic3BhY2VcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRJbnB1dC5rZXlQcmVzc2VkLnNldChrZXksIGZhbHNlKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuQ0FOVkFTX0JMVVIpIHtcblx0XHRcdFx0SW5wdXQuY2xlYXJLZXlQcmVzc2VzKClcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuV0hFRUxfVVApIHtcblx0XHRcdFx0SW5wdXQuc2Nyb2xsRGlyZWN0aW9uID0gLTE7XG5cdFx0XHRcdElucHV0Lmp1c3RTY3JvbGxlZCA9IHRydWU7XG5cdFx0XHR9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuV0hFRUxfRE9XTikge1xuXHRcdFx0XHRJbnB1dC5zY3JvbGxEaXJlY3Rpb24gPSAxO1xuXHRcdFx0XHRJbnB1dC5qdXN0U2Nyb2xsZWQgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgc3RhdGljIGNsZWFyS2V5UHJlc3NlcygpOiB2b2lkIHtcblx0XHRJbnB1dC5rZXlKdXN0UHJlc3NlZC5mb3JFYWNoKChrZXk6IHN0cmluZykgPT4gSW5wdXQua2V5SnVzdFByZXNzZWQuc2V0KGtleSwgZmFsc2UpKTtcblx0XHRJbnB1dC5rZXlQcmVzc2VkLmZvckVhY2goKGtleTogc3RyaW5nKSA9PiBJbnB1dC5rZXlQcmVzc2VkLnNldChrZXksIGZhbHNlKSk7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCBhIGtleSB3YXMgbmV3bHkgcHJlc3NlZCBJbnB1dCBmcmFtZS5cblx0ICogSWYgdGhlIGtleSBpcyBzdGlsbCBwcmVzc2VkIGZyb20gbGFzdCBmcmFtZSBhbmQgd2Fzbid0IHJlLXByZXNzZWQsIElucHV0IHdpbGwgcmV0dXJuIGZhbHNlLlxuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXlcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUga2V5IHdhcyBqdXN0IHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0c3RhdGljIGlzS2V5SnVzdFByZXNzZWQoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRpZiAoSW5wdXQua2V5c0Rpc2FibGVkKSByZXR1cm4gZmFsc2U7XG5cblx0XHRpZiAoSW5wdXQua2V5SnVzdFByZXNzZWQuaGFzKGtleSkpIHtcblx0XHRcdHJldHVybiBJbnB1dC5rZXlKdXN0UHJlc3NlZC5nZXQoa2V5KVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYW4gYXJyYXkgb2YgYWxsIG9mIHRoZSBrZXlzIHRoYXQgYXJlIG5ld2x5IHByZXNzZWQgSW5wdXQgZnJhbWUuXG5cdCAqIElmIGEga2V5IGlzIHN0aWxsIHByZXNzZWQgZnJvbSBsYXN0IGZyYW1lIGFuZCB3YXNuJ3QgcmUtcHJlc3NlZCwgaXQgd2lsbCBub3QgYmUgaW4gSW5wdXQgbGlzdC5cblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgYWxsIG9mIHRoZSBuZXdseSBwcmVzc2VkIGtleXMuXG5cdCAqL1xuXHRzdGF0aWMgZ2V0S2V5c0p1c3RQcmVzc2VkKCk6IEFycmF5PHN0cmluZz4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBbXTtcblxuXHRcdGxldCBrZXlzID0gQXJyYXk8c3RyaW5nPigpO1xuXHRcdElucHV0LmtleUp1c3RQcmVzc2VkLmZvckVhY2goa2V5ID0+IHtcblx0XHRcdGlmIChJbnB1dC5rZXlKdXN0UHJlc3NlZC5nZXQoa2V5KSkge1xuXHRcdFx0XHRrZXlzLnB1c2goa2V5KTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRyZXR1cm4ga2V5cztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IGEga2V5IGlzIGJlaW5nIHByZXNzZWQuXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleVxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBrZXkgaXMgY3VycmVudGx5IHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cblx0c3RhdGljIGlzS2V5UHJlc3NlZChrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdGlmIChJbnB1dC5rZXlzRGlzYWJsZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdGlmIChJbnB1dC5rZXlQcmVzc2VkLmhhcyhrZXkpKSB7XG5cdFx0XHRyZXR1cm4gSW5wdXQua2V5UHJlc3NlZC5nZXQoa2V5KVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIGJpbmRpbmcgb2YgYW4gaW5wdXQgbmFtZSB0byBrZXlzXG5cdCAqIEBwYXJhbSBpbnB1dE5hbWUgVGhlIG5hbWUgb2YgdGhlIGlucHV0XG5cdCAqIEBwYXJhbSBrZXlzIFRoZSBjb3JyZXNwb25kaW5nIGtleXNcblx0ICovXG5cdHN0YXRpYyBjaGFuZ2VLZXlCaW5kaW5nKGlucHV0TmFtZTogc3RyaW5nLCBrZXlzOiBBcnJheTxzdHJpbmc+KTogdm9pZCB7XG5cdFx0SW5wdXQua2V5TWFwLnNldChpbnB1dE5hbWUsIGtleXMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFycyBhbGwga2V5IGJpbmRpbmdzXG5cdCAqL1xuXHRzdGF0aWMgY2xlYXJBbGxLZXlCaW5kaW5ncygpOiB2b2lkIHtcblx0XHRJbnB1dC5rZXlNYXAuY2xlYXIoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IGFuIGlucHV0IHdhcyBqdXN0IHByZXNzZWQgdGhpcyBmcmFtZVxuXHQgKiBAcGFyYW0gaW5wdXROYW1lIFRoZSBuYW1lIG9mIHRoZSBpbnB1dFxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBpbnB1dCB3YXMganVzdCBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc0p1c3RQcmVzc2VkKGlucHV0TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG5cdFx0aWYgKElucHV0LmtleXNEaXNhYmxlZCkgcmV0dXJuIGZhbHNlO1xuXG5cdFx0aWYgKElucHV0LmtleU1hcC5oYXMoaW5wdXROYW1lKSkge1xuXHRcdFx0Y29uc3Qga2V5cyA9IElucHV0LmtleU1hcC5nZXQoaW5wdXROYW1lKTtcblx0XHRcdGxldCBqdXN0UHJlc3NlZCA9IGZhbHNlO1xuXG5cdFx0XHRmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuXHRcdFx0XHRqdXN0UHJlc3NlZCA9IGp1c3RQcmVzc2VkIHx8IElucHV0LmlzS2V5SnVzdFByZXNzZWQoa2V5KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGp1c3RQcmVzc2VkO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciBvciBub3QgYW4gaW5wdXQgaXMgY3VycmVudGx5IHByZXNzZWRcblx0ICogQHBhcmFtIGlucHV0TmFtZSBUaGUgbmFtZSBvZiB0aGUgaW5wdXRcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgaW5wdXQgaXMgcHJlc3NlZCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRzdGF0aWMgaXNQcmVzc2VkKGlucHV0TmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG5cdFx0aWYgKElucHV0LmtleXNEaXNhYmxlZCkgcmV0dXJuIGZhbHNlO1xuXG5cdFx0aWYgKElucHV0LmtleU1hcC5oYXMoaW5wdXROYW1lKSkge1xuXHRcdFx0Y29uc3Qga2V5cyA9IElucHV0LmtleU1hcC5nZXQoaW5wdXROYW1lKTtcblx0XHRcdGxldCBwcmVzc2VkID0gZmFsc2U7XG5cblx0XHRcdGZvciAobGV0IGtleSBvZiBrZXlzKSB7XG5cdFx0XHRcdHByZXNzZWQgPSBwcmVzc2VkIHx8IElucHV0LmlzS2V5UHJlc3NlZChrZXkpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gcHJlc3NlZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXHQvKipcblx0ICogXG5cdCAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIG1vdXNlIHdhcyBuZXdseSBwcmVzc2VkIElucHV0IGZyYW1lLlxuXHQgKiBAcGFyYW0gbW91c2VCdXR0b24gT3B0aW9uYWxseSBzcGVjaWZ5IHdoaWNoIG1vdXNlIGNsaWNrIHlvdSB3YW50IHRvIGtub3cgd2FzIHByZXNzZWQuIFxuXHQgKiAwIGZvciBsZWZ0IGNsaWNrLCAxIGZvciBtaWRkbGUgY2xpY2ssIDIgZm9yIHJpZ2h0IGNsaWNrLlxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBtb3VzZSB3YXMganVzdCBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc01vdXNlSnVzdFByZXNzZWQobW91c2VCdXR0b24/OiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRpZiAobW91c2VCdXR0b24gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIElucHV0Lm1vdXNlSnVzdFByZXNzZWQgJiYgIUlucHV0Lm1vdXNlRGlzYWJsZWQgJiYgbW91c2VCdXR0b24gPT0gdGhpcy5tb3VzZUJ1dHRvblByZXNzZWQ7XG5cdFx0fVxuXHRcdHJldHVybiBJbnB1dC5tb3VzZUp1c3RQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIG1vdXNlIGlzIGN1cnJlbnRseSBwcmVzc2VkXG5cdCAqIEBwYXJhbSBtb3VzZUJ1dHRvbiBPcHRpb25hbGx5IHNwZWNpZnkgd2hpY2ggbW91c2UgY2xpY2sgeW91IHdhbnQgdG8ga25vdyB3YXMgcHJlc3NlZC4gXG5cdCAqIDAgZm9yIGxlZnQgY2xpY2ssIDEgZm9yIG1pZGRsZSBjbGljaywgMiBmb3IgcmlnaHQgY2xpY2suXG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIG1vdXNlIGlzIGN1cnJlbnRseSBwcmVzc2VkLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBpc01vdXNlUHJlc3NlZChtb3VzZUJ1dHRvbj86IG51bWJlcik6IGJvb2xlYW4ge1xuXHRcdGlmIChtb3VzZUJ1dHRvbiAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gSW5wdXQubW91c2VQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkICYmIG1vdXNlQnV0dG9uID09IHRoaXMubW91c2VCdXR0b25QcmVzc2VkO1xuXHRcdH1cblx0XHRyZXR1cm4gSW5wdXQubW91c2VQcmVzc2VkICYmICFJbnB1dC5tb3VzZURpc2FibGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciB0aGUgdXNlciBzY3JvbGxlZCBvciBub3Rcblx0ICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgdXNlciBqdXN0IHNjcm9sbGVkIElucHV0IGZyYW1lLCBmYWxzZSBvdGhlcndpc2Vcblx0ICovXG5cdHN0YXRpYyBkaWRKdXN0U2Nyb2xsKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiBJbnB1dC5qdXN0U2Nyb2xsZWQgJiYgIUlucHV0Lm1vdXNlRGlzYWJsZWQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzY3JvbGxcblx0ICogQHJldHVybnMgLTEgaWYgdGhlIHVzZXIgc2Nyb2xsZWQgdXAsIDEgaWYgdGhleSBzY3JvbGxlZCBkb3duXG5cdCAqL1xuXHRzdGF0aWMgZ2V0U2Nyb2xsRGlyZWN0aW9uKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIElucHV0LnNjcm9sbERpcmVjdGlvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgcGxheWVyJ3MgbW91c2Vcblx0ICogQHJldHVybnMgVGhlIG1vdXNlIHBvc2l0aW9uIHN0b3JlZCBhcyBhIFZlYzJcblx0ICovXG5cdHN0YXRpYyBnZXRNb3VzZVBvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiBJbnB1dC5tb3VzZVBvc2l0aW9uLnNjYWxlZCgxIC8gdGhpcy52aWV3cG9ydC5nZXRab29tTGV2ZWwoKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIHBsYXllcidzIG1vdXNlIGluIHRoZSBnYW1lIHdvcmxkLFxuXHQgKiB0YWtpbmcgaW50byBjb25zaWRlcmF0aW9uIHRoZSBzY3JvbGxpbmcgb2YgdGhlIHZpZXdwb3J0XG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0R2xvYmFsTW91c2VQb3NpdGlvbigpOiBWZWMyIHtcblx0XHRyZXR1cm4gSW5wdXQubW91c2VQb3NpdGlvbi5jbG9uZSgpLnNjYWxlKDEgLyB0aGlzLnZpZXdwb3J0LmdldFpvb21MZXZlbCgpKS5hZGQoSW5wdXQudmlld3BvcnQuZ2V0T3JpZ2luKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIHBvc2l0aW9uIG9mIHRoZSBsYXN0IG1vdXNlIHByZXNzXG5cdCAqIEByZXR1cm5zIFRoZSBtb3VzZSBwb3NpdGlvbiBzdG9yZWQgYXMgYSBWZWMyXG5cdCAqL1xuXHRzdGF0aWMgZ2V0TW91c2VQcmVzc1Bvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiBJbnB1dC5nZXRNb3VzZVBvc2l0aW9uKCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIGxhc3QgbW91c2UgcHJlc3MgaW4gdGhlIGdhbWUgd29ybGQsXG5cdCAqIHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gdGhlIHNjcm9sbGluZyBvZiB0aGUgdmlld3BvcnRcblx0ICogQHJldHVybnMgVGhlIG1vdXNlIHBvc2l0aW9uIHN0b3JlZCBhcyBhIFZlYzJcblx0ICovXG5cdHN0YXRpYyBnZXRHbG9iYWxNb3VzZVByZXNzUG9zaXRpb24oKTogVmVjMiB7XG5cdFx0cmV0dXJuIElucHV0Lm1vdXNlUHJlc3NQb3NpdGlvbi5jbG9uZSgpLmFkZChJbnB1dC52aWV3cG9ydC5nZXRPcmlnaW4oKSk7XG5cdH1cblxuXHQvKipcblx0ICogRGlzYWJsZXMgYWxsIGtleXByZXNzIGFuZCBtb3VzZSBjbGljayBpbnB1dHNcblx0ICovXG5cdHN0YXRpYyBkaXNhYmxlSW5wdXQoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5c0Rpc2FibGVkID0gdHJ1ZTtcblx0XHRJbnB1dC5tb3VzZURpc2FibGVkID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBFbmFibGVzIGFsbCBrZXlwcmVzcyBhbmQgbW91c2UgY2xpY2sgaW5wdXRzXG5cdCAqL1xuXHRzdGF0aWMgZW5hYmxlSW5wdXQoKTogdm9pZCB7XG5cdFx0SW5wdXQua2V5c0Rpc2FibGVkID0gZmFsc2U7XG5cdFx0SW5wdXQubW91c2VEaXNhYmxlZCA9IGZhbHNlO1xuXHR9XG59IiwiaW1wb3J0IEV2ZW50UXVldWUgZnJvbSBcIi4uL0V2ZW50cy9FdmVudFF1ZXVlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBIYW5kbGVzIGNvbW11bmljYXRpb24gd2l0aCB0aGUgd2ViIGJyb3dzZXIgdG8gcmVjZWl2ZSBhc3luY2hyb25vdXMgZXZlbnRzIGFuZCBzZW5kIHRoZW0gdG8gdGhlIEByZWZlcmVuY2VbRXZlbnRRdWV1ZV1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW5wdXRIYW5kbGVyIHtcblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuICAgICBcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IElucHV0SGFuZGxlclxuICAgICAqIEBwYXJhbSBjYW52YXMgVGhlIGdhbWUgY2FudmFzXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCl7XG5cdFx0dGhpcy5ldmVudFF1ZXVlID0gRXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpO1xuXHRcdFxuICAgICAgICBjYW52YXMub25tb3VzZWRvd24gPSAoZXZlbnQpID0+IHRoaXMuaGFuZGxlTW91c2VEb3duKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBjYW52YXMub25tb3VzZXVwID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU1vdXNlVXAoZXZlbnQsIGNhbnZhcyk7XG4gICAgICAgIGNhbnZhcy5vbmNvbnRleHRtZW51ID0gdGhpcy5oYW5kbGVDb250ZXh0TWVudTtcbiAgICAgICAgY2FudmFzLm9ubW91c2Vtb3ZlID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU1vdXNlTW92ZShldmVudCwgY2FudmFzKTtcbiAgICAgICAgZG9jdW1lbnQub25rZXlkb3duID0gdGhpcy5oYW5kbGVLZXlEb3duO1xuICAgICAgICBkb2N1bWVudC5vbmtleXVwID0gdGhpcy5oYW5kbGVLZXlVcDtcbiAgICAgICAgZG9jdW1lbnQub25ibHVyID0gdGhpcy5oYW5kbGVCbHVyO1xuICAgICAgICBkb2N1bWVudC5vbmNvbnRleHRtZW51ID0gdGhpcy5oYW5kbGVCbHVyO1xuICAgICAgICBkb2N1bWVudC5vbndoZWVsID0gdGhpcy5oYW5kbGVXaGVlbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZU1vdXNlRG93biA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuXHRcdGxldCBwb3MgPSB0aGlzLmdldE1vdXNlUG9zaXRpb24oZXZlbnQsIGNhbnZhcyk7XG4gICAgICAgIGxldCBidXR0b24gPSBldmVudC5idXR0b247XG4gICAgICAgIGxldCBnYW1lRXZlbnQgPSBuZXcgR2FtZUV2ZW50KEdhbWVFdmVudFR5cGUuTU9VU0VfRE9XTiwge3Bvc2l0aW9uOiBwb3MsIGJ1dHRvbjogYnV0dG9ufSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlTW91c2VVcCA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQgcG9zID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLk1PVVNFX1VQLCB7cG9zaXRpb246IHBvc30pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZU1vdXNlTW92ZSA9IChldmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQgcG9zID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50LCBjYW52YXMpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLk1PVVNFX01PVkUsIHtwb3NpdGlvbjogcG9zfSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlS2V5RG93biA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQga2V5ID0gdGhpcy5nZXRLZXkoZXZlbnQpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLktFWV9ET1dOLCB7a2V5OiBrZXl9KTtcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlLmFkZEV2ZW50KGdhbWVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoYW5kbGVLZXlVcCA9IChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBsZXQga2V5ID0gdGhpcy5nZXRLZXkoZXZlbnQpO1xuICAgICAgICBsZXQgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLktFWV9VUCwge2tleToga2V5fSk7XG4gICAgICAgIHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChnYW1lRXZlbnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlQmx1ciA9IChldmVudDogRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgbGV0IGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5DQU5WQVNfQkxVUiwge30pO1xuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUNvbnRleHRNZW51ID0gKGV2ZW50OiBFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZVdoZWVsID0gKGV2ZW50OiBXaGVlbEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBcbiAgICAgICAgbGV0IGdhbWVFdmVudDogR2FtZUV2ZW50O1xuICAgICAgICBpZihldmVudC5kZWx0YVkgPCAwKXtcbiAgICAgICAgICAgIGdhbWVFdmVudCA9IG5ldyBHYW1lRXZlbnQoR2FtZUV2ZW50VHlwZS5XSEVFTF9VUCwge30pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2FtZUV2ZW50ID0gbmV3IEdhbWVFdmVudChHYW1lRXZlbnRUeXBlLldIRUVMX0RPV04sIHt9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmV2ZW50UXVldWUuYWRkRXZlbnQoZ2FtZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEtleShrZXlFdmVudDogS2V5Ym9hcmRFdmVudCl7XG4gICAgICAgIHJldHVybiBrZXlFdmVudC5rZXkudG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldE1vdXNlUG9zaXRpb24obW91c2VFdmVudDogTW91c2VFdmVudCwgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IFZlYzIge1xuICAgICAgICBsZXQgcmVjdCA9IGNhbnZhcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgbGV0IHggPSBtb3VzZUV2ZW50LmNsaWVudFggLSByZWN0LmxlZnQ7XG4gICAgICAgIGxldCB5ID0gbW91c2VFdmVudC5jbGllbnRZIC0gcmVjdC50b3A7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih4LCB5KTtcbiAgICB9XG59IiwiaW1wb3J0IHt9IGZyb20gXCIuLi8uLi9pbmRleFwiOyAgLy8gVGhpcyBpbXBvcnQgYWxsb3dzIHVzIHRvIG1vZGlmeSB0aGUgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHRvIGFkZCBleHRyYSBmdW5jdGlvbmFsaXR5XG4vLyBAaWdub3JlUGFnZVxuXG4vKipcbiAqIFNldHMgdXAgdGhlIGVudmlyb25tZW50IG9mIHRoZSBnYW1lIGVuZ2luZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFbnZpcm9ubWVudEluaXRpYWxpemVyIHtcbiAgICBzdGF0aWMgc2V0dXAoKXtcbiAgICAgICAgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJELnByb3RvdHlwZS5yb3VuZGVkUmVjdCA9IGZ1bmN0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyLCB3OiBudW1iZXIsIGg6IG51bWJlciwgcjogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgICAgICAvLyBDbGFtcCB0aGUgcmFkaXVzIGJldHdlZW4gMCBhbmQgdGhlIG1pbiBvZiB0aGUgd2lkdGggb3IgaGVpZ2h0XG4gICAgICAgICAgICBpZihyIDwgMCkgciA9IDA7XG4gICAgICAgICAgICBpZihyID4gTWF0aC5taW4odywgaCkpIHIgPSBNYXRoLm1pbih3LCBoKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBEcmF3IHRoZSByb3VuZGVkIHJlY3RcbiAgICAgICAgICAgIHRoaXMuYmVnaW5QYXRoKCk7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gVG9wXG4gICAgICAgICAgICB0aGlzLm1vdmVUbyh4ICsgciwgeSk7XG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4ICsgdyAtIHIsIHkpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4ICsgdywgeSwgeCArIHcsIHkgKyByLCByKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBSaWdodFxuICAgICAgICAgICAgdGhpcy5saW5lVG8oeCArIHcsIHkgKyBoIC0gcik7XG4gICAgICAgICAgICB0aGlzLmFyY1RvKHggKyB3LCB5ICsgaCwgeCArIHcgLSByLCB5ICsgaCwgcik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gQm90dG9tXG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4ICsgciwgeSArIGgpO1xuICAgICAgICAgICAgdGhpcy5hcmNUbyh4LCB5ICsgaCwgeCwgeSArIGggLSByLCByKTtcbiAgICAgICAgXG4gICAgICAgICAgICAvLyBMZWZ0XG4gICAgICAgICAgICB0aGlzLmxpbmVUbyh4LCB5ICsgcik7XG4gICAgICAgICAgICB0aGlzLmFyY1RvKHgsIHksIHggKyByLCB5LCByKVxuICAgICAgICBcbiAgICAgICAgICAgIHRoaXMuY2xvc2VQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5wcm90b3R5cGUuc3Ryb2tlUm91bmRlZFJlY3QgPSBmdW5jdGlvbih4LCB5LCB3LCBoLCByKXtcbiAgICAgICAgICAgIHRoaXMucm91bmRlZFJlY3QoeCwgeSwgdywgaCwgcik7XG4gICAgICAgICAgICB0aGlzLnN0cm9rZSgpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQucHJvdG90eXBlLmZpbGxSb3VuZGVkUmVjdCA9IGZ1bmN0aW9uKHgsIHksIHcsIGgsIHIpe1xuICAgICAgICAgICAgdGhpcy5yb3VuZGVkUmVjdCh4LCB5LCB3LCBoLCByKTtcbiAgICAgICAgICAgIHRoaXMuZmlsbCgpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBHYW1lTG9vcCBmcm9tIFwiLi9HYW1lTG9vcFwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IFN0YXRzIGZyb20gXCIuLi9EZWJ1Zy9TdGF0c1wiO1xuXG4vKipcbiAqIEEgZ2FtZSBsb29wIHdpdGggYSBmaXhlZCB1cGRhdGUgdGltZSBhbmQgYSB2YXJpYWJsZSByZW5kZXIgdGltZS5cbiAqIEV2ZXJ5IGZyYW1lLCB0aGUgZ2FtZSB1cGRhdGVzIHVudGlsIGFsbCB0aW1lIHNpbmNlIHRoZSBsYXN0IGZyYW1lIGhhcyBiZWVuIHByb2Nlc3NlZC5cbiAqIElmIHRvbyBtdWNoIHRpbWUgaGFzIHBhc3NlZCwgc3VjaCBhcyBpZiB0aGUgbGFzdCB1cGRhdGUgd2FzIHRvbyBzbG93LCBcbiAqIG9yIGlmIHRoZSBicm93c2VyIHdhcyBwdXQgaW50byB0aGUgYmFja2dyb3VuZCwgdGhlIGxvb3Agd2lsbCBwYW5pYyBhbmQgZGlzY2FyZCB0aW1lLlxuICogQSByZW5kZXIgaGFwcGVucyBhdCB0aGUgZW5kIG9mIGV2ZXJ5IGZyYW1lLiBUaGlzIGhhcHBlbnMgYXMgZmFzdCBhcyBwb3NzaWJsZSB1bmxlc3Mgc3BlY2lmaWVkLlxuICogQSBsb29wIG9mIHRoaXMgdHlwZSBhbGxvd3MgZm9yIGRldGVybWluaXN0aWMgYmVoYXZpb3IgLSBObyBtYXR0ZXIgd2hhdCB0aGUgZnJhbWUgcmF0ZSBpcywgdGhlIHVwZGF0ZSBzaG91bGQgYmVoYXZlIHRoZSBzYW1lLCBcbiAqIGFzIGl0IGlzIG9jY3VyaW5nIGluIGEgZml4ZWQgaW50ZXJ2YWwuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpeGVkVXBkYXRlR2FtZUxvb3AgZXh0ZW5kcyBHYW1lTG9vcCB7XG5cblx0LyoqIFRoZSBtYXggYWxsb3dlZCB1cGRhdGUgZnBzLiovXG4gICAgcHJpdmF0ZSBtYXhVcGRhdGVGUFM6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIHRpbWVzdGVwIGZvciBlYWNoIHVwZGF0ZS4gVGhpcyBpcyB0aGUgZGVsdGFUIHBhc3NlZCB0byB1cGRhdGUgY2FsbHMuICovXG5cdHByaXZhdGUgdXBkYXRlVGltZXN0ZXA6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgYW1vdW50IG9mIHRpbWUgd2UgYXJlIHlldCB0byBzaW11bGF0ZS4gKi9cbiAgICBwcml2YXRlIGZyYW1lRGVsdGE6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgdGltZSB3aGVuIHRoZSBsYXN0IGZyYW1lIHdhcyBkcmF3bi4gKi9cbiAgICBwcml2YXRlIGxhc3RGcmFtZVRpbWU6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIG1pbmltdW0gdGltZSB3ZSB3YW50IHRvIHdhaXQgYmV0d2VlbiBnYW1lIGZyYW1lcy4gKi9cbiAgICBwcml2YXRlIG1pbkZyYW1lRGVsYXk6IG51bWJlcjtcblxuXHQvKiogVGhlIGN1cnJlbnQgZnJhbWUgb2YgdGhlIGdhbWUuICovXG5cdHByaXZhdGUgZnJhbWU6IG51bWJlcjtcblxuXHQvKiogVGhlIGFjdHVhbCBmcHMgb2YgdGhlIGdhbWUuICovXG4gICAgcHJpdmF0ZSBmcHM6IG51bWJlcjtcbiAgICBcbiAgICAvKiogVGhlIHRpbWUgYmV0d2VlbiBmcHMgbWVhc3VyZW1lbnQgdXBkYXRlcy4gKi9cbiAgICBwcml2YXRlIGZwc1VwZGF0ZUludGVydmFsOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHRpbWUgb2YgdGhlIGxhc3QgZnBzIHVwZGF0ZS4gKi9cbiAgICBwcml2YXRlIGxhc3RGcHNVcGRhdGU6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIGZyYW1lcyBzaW5jZSB0aGUgbGFzdCBmcHMgdXBkYXRlIHdhcyBkb25lLiAqL1xuICAgIHByaXZhdGUgZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHN0YXR1cyBvZiB3aGV0aGVyIG9yIG5vdCB0aGUgZ2FtZSBsb29wIGhhcyBzdGFydGVkLiAqL1xuICAgIHByaXZhdGUgc3RhcnRlZDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgc3RhdHVzIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBnYW1lIGxvb3AgaXMgcGF1c2VkICovXG4gICAgcHJpdmF0ZSBwYXVzZWQ6IGJvb2xlYW47XG4gICAgXG4gICAgLyoqIFRoZSBzdGF0dXMgb2Ygd2hldGhlciBvciBub3QgdGhlIGdhbWUgbG9vcCBpcyBjdXJyZW50bHkgcnVubmluZy4gKi9cbiAgICBwcml2YXRlIHJ1bm5pbmc6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIG51bWJlciBvZiB1cGRhdGUgc3RlcHMgdGhpcyBpdGVyYXRpb24gb2YgdGhlIGdhbWUgbG9vcC4gKi9cbiAgICBwcml2YXRlIG51bVVwZGF0ZVN0ZXBzOiBudW1iZXI7XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0c3VwZXIoKTtcbiAgICAgICAgdGhpcy5tYXhVcGRhdGVGUFMgPSA2MDtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RlcCA9IE1hdGguZmxvb3IoMTAwMC90aGlzLm1heFVwZGF0ZUZQUyk7XG4gICAgICAgIHRoaXMuZnJhbWVEZWx0YSA9IDA7XG4gICAgICAgIHRoaXMubGFzdEZyYW1lVGltZSA9IDA7XG4gICAgICAgIHRoaXMubWluRnJhbWVEZWxheSA9IDA7XG4gICAgICAgIHRoaXMuZnJhbWUgPSAwO1xuICAgICAgICB0aGlzLmZwcyA9IHRoaXMubWF4VXBkYXRlRlBTOyAgIC8vIEluaXRpYWxpemUgdGhlIGZwcyB0byB0aGUgbWF4IGFsbG93ZWQgZnBzXG4gICAgICAgIHRoaXMuZnBzVXBkYXRlSW50ZXJ2YWwgPSAxMDAwO1xuICAgICAgICB0aGlzLmxhc3RGcHNVcGRhdGUgPSAwO1xuICAgICAgICB0aGlzLmZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZSA9IDA7XG4gICAgICAgIHRoaXMuc3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhdXNlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5udW1VcGRhdGVTdGVwcyA9IDA7XG5cdH1cblxuXHRnZXRGUFMoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gMDtcblx0fVxuXG5cdC8qKlxuICAgICAqIFVwZGF0ZXMgdGhlIGZyYW1lIGNvdW50IGFuZCBzdW0gb2YgdGltZSBmb3IgdGhlIGZyYW1lcmF0ZSBvZiB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSB0aW1lc3RlcCBUaGUgY3VycmVudCB0aW1lIGluIG1zXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUZQUyh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmZwcyA9IDAuOSAqIHRoaXMuZnJhbWVzU2luY2VMYXN0RnBzVXBkYXRlICogMTAwMCAvICh0aW1lc3RhbXAgLSB0aGlzLmxhc3RGcHNVcGRhdGUpICsoMSAtIDAuOSkgKiB0aGlzLmZwcztcbiAgICAgICAgdGhpcy5sYXN0RnBzVXBkYXRlID0gdGltZXN0YW1wO1xuICAgICAgICB0aGlzLmZyYW1lc1NpbmNlTGFzdEZwc1VwZGF0ZSA9IDA7XG5cbiAgICAgICAgRGVidWcubG9nKFwiZnBzXCIsIFwiRlBTOiBcIiArIHRoaXMuZnBzLnRvRml4ZWQoMSkpO1xuICAgICAgICBTdGF0cy51cGRhdGVGUFModGhpcy5mcHMpO1xuICAgIH1cblxuXHQgICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgbWF4aW11bSBhbGxvd2VkIHBoeXNpY3MgZnJhbWVyYXRlIG9mIHRoZSBnYW1lXG4gICAgICogQHBhcmFtIGluaXRNYXggVGhlIG1heCBmcmFtZXJhdGVcbiAgICAgKi9cbiAgICBzZXRNYXhVcGRhdGVGUFMoaW5pdE1heDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWF4VXBkYXRlRlBTID0gaW5pdE1heDtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RlcCA9IE1hdGguZmxvb3IoMTAwMC90aGlzLm1heFVwZGF0ZUZQUyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWF4aW11bSByZW5kZXJpbmcgZnJhbWVyYXRlXG4gICAgICogQHBhcmFtIG1heEZQUyBUaGUgbWF4IGZyYW1lcmF0ZVxuICAgICAqL1xuICAgIHNldE1heEZQUyhtYXhGUFM6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLm1pbkZyYW1lRGVsYXkgPSAxMDAwL21heEZQUztcblx0fVxuXHRcblx0LyoqXG5cdCAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gdGhlIGdhbWUgbG9vcCBwYW5pY3MsIGkuZS4gaXQgdHJpZXMgdG8gcHJvY2VzcyB0b28gbXVjaCB0aW1lIGluIGFuIGVudGlyZSBmcmFtZS5cblx0ICogVGhpcyB3aWxsIHJlc2V0IHRoZSBhbW91bnQgb2YgdGltZSBiYWNrIHRvIHplcm8uXG5cdCAqIEByZXR1cm5zIFRoZSBhbW91bnQgb2YgdGltZSB3ZSBhcmUgZGlzY2FyZGluZyBmcm9tIHByb2Nlc3NpbmcuXG5cdCAqL1xuXHRyZXNldEZyYW1lRGVsdGEoKSA6IG51bWJlciB7XG4gICAgICAgIGxldCBvbGRGcmFtZURlbHRhID0gdGhpcy5mcmFtZURlbHRhO1xuICAgICAgICB0aGlzLmZyYW1lRGVsdGEgPSAwO1xuICAgICAgICByZXR1cm4gb2xkRnJhbWVEZWx0YTtcbiAgICB9XG5cblx0LyoqXG4gICAgICogU3RhcnRzIHVwIHRoZSBnYW1lIGxvb3AgYW5kIGNhbGxzIHRoZSBmaXJzdCByZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgICAgKi9cblx0c3RhcnQoKTogdm9pZCB7XG4gICAgICAgIGlmKCF0aGlzLnN0YXJ0ZWQpe1xuICAgICAgICAgICAgdGhpcy5zdGFydGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgodGltZXN0YW1wKSA9PiB0aGlzLmRvRmlyc3RGcmFtZSh0aW1lc3RhbXApKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHBhdXNlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcmVzdW1lKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IGZhbHNlO1xuICAgIH1cblxuXHQvKipcbiAgICAgKiBUaGUgZmlyc3QgZ2FtZSBmcmFtZSAtIGluaXRpYWxpemVzIHRoZSBmaXJzdCBmcmFtZSB0aW1lIGFuZCBiZWdpbnMgdGhlIHJlbmRlclxuICAgICAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIGN1cnJlbnQgdGltZSBpbiBtc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBkb0ZpcnN0RnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkICB7XG4gICAgICAgIHRoaXMucnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5fZG9SZW5kZXIoKTtcblxuICAgICAgICB0aGlzLmxhc3RGcmFtZVRpbWUgPSB0aW1lc3RhbXA7XG4gICAgICAgIHRoaXMubGFzdEZwc1VwZGF0ZSA9IHRpbWVzdGFtcDtcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUgPSAwO1xuXG4gICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKHQpID0+IHRoaXMuZG9GcmFtZSh0KSk7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIGFueSBwcm9jZXNzaW5nIHRoYXQgbmVlZHMgdG8gYmUgZG9uZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGZyYW1lXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWUgb2YgdGhlIGZyYW1lIGluIG1zXG5cdCAqL1xuXHRwcm90ZWN0ZWQgc3RhcnRGcmFtZSh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIFVwZGF0ZSB0aGUgYW1vdW50IG9mIHRpbWUgd2UgbmVlZCBvdXIgdXBkYXRlIHRvIHByb2Nlc3Ncblx0XHR0aGlzLmZyYW1lRGVsdGEgKz0gdGltZXN0YW1wIC0gdGhpcy5sYXN0RnJhbWVUaW1lO1xuXG5cdFx0Ly8gU2V0IHRoZSBuZXcgdGltZSBvZiB0aGUgbGFzdCBmcmFtZVxuICAgICAgICB0aGlzLmxhc3RGcmFtZVRpbWUgPSB0aW1lc3RhbXA7XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBlc3RpbWF0ZSBvZiB0aGUgZnJhbWVyYXRlXG4gICAgICAgIGlmKHRpbWVzdGFtcCA+IHRoaXMubGFzdEZwc1VwZGF0ZSArIHRoaXMuZnBzVXBkYXRlSW50ZXJ2YWwpe1xuICAgICAgICAgICAgdGhpcy51cGRhdGVGUFModGltZXN0YW1wKTtcbiAgICAgICAgfVxuXG5cdFx0Ly8gSW5jcmVtZW50IHRoZSBudW1iZXIgb2YgZnJhbWVzXG4gICAgICAgIHRoaXMuZnJhbWUrKztcbiAgICAgICAgdGhpcy5mcmFtZXNTaW5jZUxhc3RGcHNVcGRhdGUrKztcblx0fVxuXG5cdC8qKlxuICAgICAqIFRoZSBtYWluIGxvb3Agb2YgdGhlIGdhbWUuIFVwZGF0ZXMgdW50aWwgdGhlIGN1cnJlbnQgdGltZSBpcyByZWFjaGVkLiBSZW5kZXJzIG9uY2VcbiAgICAgKiBAcGFyYW0gdGltZXN0YW1wIFRoZSBjdXJyZW50IHRpbWUgaW4gbXNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZG9GcmFtZSA9ICh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQgPT4ge1xuICAgICAgICAvLyBJZiBhIHBhdXNlIHdhcyBleGVjdXRlZCwgc3RvcCBkb2luZyB0aGUgbG9vcC5cbiAgICAgICAgaWYodGhpcy5wYXVzZWQpeyBcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlcXVlc3QgYW5pbWF0aW9uIGZyYW1lIHRvIHByZXBhcmUgZm9yIGFub3RoZXIgdXBkYXRlIG9yIHJlbmRlclxuICAgICAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCh0KSA9PiB0aGlzLmRvRnJhbWUodCkpO1xuXG4gICAgICAgIC8vIElmIHdlIGFyZSB0cnlpbmcgdG8gcmVuZGVyIHRvbyBzb29uLCBkbyBub3RoaW5nLlxuICAgICAgICBpZih0aW1lc3RhbXAgPCB0aGlzLmxhc3RGcmFtZVRpbWUgKyB0aGlzLm1pbkZyYW1lRGVsYXkpe1xuICAgICAgICAgICAgcmV0dXJuO1xuXHRcdH1cblx0XHRcblx0XHQvLyBBIGZyYW1lIGlzIGFjdHVhbGx5IGhhcHBlbmluZ1xuXHRcdHRoaXMuc3RhcnRGcmFtZSh0aW1lc3RhbXApO1xuXG5cdFx0Ly8gVXBkYXRlIHdoaWxlIHRoZXJlIGlzIHN0aWxsIHRpbWUgdG8gbWFrZSB1cC4gSWYgd2UgZG8gdG9vIG1hbnkgdXBkYXRlIHN0ZXBzLCBwYW5pYyBhbmQgZXhpdCB0aGUgbG9vcC5cblx0XHR0aGlzLm51bVVwZGF0ZVN0ZXBzID0gMDtcblx0XHRsZXQgcGFuaWMgPSBmYWxzZTtcblxuICAgICAgICB3aGlsZSh0aGlzLmZyYW1lRGVsdGEgPj0gdGhpcy51cGRhdGVUaW1lc3RlcCl7XG5cdFx0XHQvLyBEbyBhbiB1cGRhdGVcblx0XHRcdHRoaXMuX2RvVXBkYXRlKHRoaXMudXBkYXRlVGltZXN0ZXAvMTAwMCk7XG5cdFx0XHRcblx0XHRcdC8vIFJlbW92ZSB0aGUgdXBkYXRlIHN0ZXAgdGltZSBmcm9tIHRoZSB0aW1lIHdlIGhhdmUgdG8gcHJvY2Vzc1xuICAgICAgICAgICAgdGhpcy5mcmFtZURlbHRhIC09IHRoaXMudXBkYXRlVGltZXN0ZXA7XG5cblx0XHRcdC8vIEluY3JlbWVudCBzdGVwcyBhbmQgY2hlY2sgaWYgd2UndmUgZG9uZSB0b28gbWFueVxuICAgICAgICAgICAgdGhpcy5udW1VcGRhdGVTdGVwcysrO1xuICAgICAgICAgICAgaWYodGhpcy5udW1VcGRhdGVTdGVwcyA+IDEwMCl7XG4gICAgICAgICAgICAgICAgcGFuaWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlcyBhcmUgZG9uZSwgcmVuZGVyXG4gICAgICAgIHRoaXMuX2RvUmVuZGVyKCk7XG5cbiAgICAgICAgLy8gV3JhcCB1cCB0aGUgZnJhbWVcbiAgICAgICAgdGhpcy5maW5pc2hGcmFtZShwYW5pYyk7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBXcmFwcyB1cCB0aGUgZnJhbWUgYW5kIGhhbmRsZXMgdGhlIHBhbmljIHN0YXRlIGlmIHRoZXJlIGlzIG9uZVxuXHQgKiBAcGFyYW0gcGFuaWMgV2hldGhlciBvciBub3QgdGhlIGxvb3AgcGFuaWNrZWRcblx0ICovXG5cdHByb3RlY3RlZCBmaW5pc2hGcmFtZShwYW5pYzogYm9vbGVhbik6IHZvaWQge1xuXHRcdGlmKHBhbmljKSB7XG4gICAgICAgICAgICB2YXIgZGlzY2FyZGVkVGltZSA9IE1hdGgucm91bmQodGhpcy5yZXNldEZyYW1lRGVsdGEoKSk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ01haW4gbG9vcCBwYW5pY2tlZCwgcHJvYmFibHkgYmVjYXVzZSB0aGUgYnJvd3NlciB0YWIgd2FzIHB1dCBpbiB0aGUgYmFja2dyb3VuZC4gRGlzY2FyZGluZyAnICsgZGlzY2FyZGVkVGltZSArICdtcycpO1xuICAgICAgICB9XG5cdH1cblxufSIsImltcG9ydCBFdmVudFF1ZXVlIGZyb20gXCIuLi9FdmVudHMvRXZlbnRRdWV1ZVwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IElucHV0SGFuZGxlciBmcm9tIFwiLi4vSW5wdXQvSW5wdXRIYW5kbGVyXCI7XG5pbXBvcnQgUmVjb3JkZXIgZnJvbSBcIi4uL1BsYXliYWNrL1JlY29yZGVyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBTY2VuZU1hbmFnZXIgZnJvbSBcIi4uL1NjZW5lL1NjZW5lTWFuYWdlclwiO1xuaW1wb3J0IEF1ZGlvTWFuYWdlciBmcm9tIFwiLi4vU291bmQvQXVkaW9NYW5hZ2VyXCI7XG5pbXBvcnQgU3RhdHMgZnJvbSBcIi4uL0RlYnVnL1N0YXRzXCI7XG5pbXBvcnQgUmVuZGVyaW5nTWFuYWdlciBmcm9tIFwiLi4vUmVuZGVyaW5nL1JlbmRlcmluZ01hbmFnZXJcIjtcbmltcG9ydCBDYW52YXNSZW5kZXJlciBmcm9tIFwiLi4vUmVuZGVyaW5nL0NhbnZhc1JlbmRlcmVyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgR2FtZU9wdGlvbnMgZnJvbSBcIi4vR2FtZU9wdGlvbnNcIjtcbmltcG9ydCBHYW1lTG9vcCBmcm9tIFwiLi9HYW1lTG9vcFwiO1xuaW1wb3J0IEZpeGVkVXBkYXRlR2FtZUxvb3AgZnJvbSBcIi4vRml4ZWRVcGRhdGVHYW1lTG9vcFwiO1xuaW1wb3J0IEVudmlyb25tZW50SW5pdGlhbGl6ZXIgZnJvbSBcIi4vRW52aXJvbm1lbnRJbml0aWFsaXplclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmVnaXN0cnlNYW5hZ2VyIGZyb20gXCIuLi9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXJcIjtcbmltcG9ydCBXZWJHTFJlbmRlcmVyIGZyb20gXCIuLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJlclwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZS9TY2VuZVwiO1xuXG4vKipcbiAqIFRoZSBtYWluIGxvb3Agb2YgdGhlIGdhbWUgZW5naW5lLlxuICogSGFuZGxlcyB0aGUgdXBkYXRlIG9yZGVyLCBhbmQgaW5pdGlhbGl6ZXMgYWxsIHN1YnN5c3RlbXMuXG4gKiBUaGUgR2FtZSBtYW5hZ2VzIHRoZSB1cGRhdGUgY3ljbGUsIGFuZCByZXF1ZXN0cyBhbmltYXRpb24gZnJhbWVzIHRvIHJlbmRlciB0byB0aGUgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2FtZSB7XG4gICAgZ2FtZU9wdGlvbnM6IEdhbWVPcHRpb25zO1xuICAgIHByaXZhdGUgc2hvd0RlYnVnOiBib29sZWFuO1xuICAgIHByaXZhdGUgc2hvd1N0YXRzOiBib29sZWFuO1xuXG4gICAgLy8gVGhlIGdhbWUgbG9vcFxuICAgIHByaXZhdGUgbG9vcDogR2FtZUxvb3A7XG5cbiAgICAvLyBHYW1lIGNhbnZhcyBhbmQgaXRzIHdpZHRoIGFuZCBoZWlnaHRcbiAgICByZWFkb25seSBHQU1FX0NBTlZBUzogSFRNTENhbnZhc0VsZW1lbnQ7XG4gICAgcmVhZG9ubHkgREVCVUdfQ0FOVkFTOiBIVE1MQ2FudmFzRWxlbWVudDtcblx0cmVhZG9ubHkgV0lEVEg6IG51bWJlcjtcbiAgICByZWFkb25seSBIRUlHSFQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHZpZXdwb3J0OiBWaWV3cG9ydDtcbiAgICBwcml2YXRlIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIHwgV2ViR0xSZW5kZXJpbmdDb250ZXh0O1xuICAgIHByaXZhdGUgY2xlYXJDb2xvcjogQ29sb3I7XG4gICAgXG4gICAgLy8gQWxsIG9mIHRoZSBuZWNlc3Nhcnkgc3Vic3lzdGVtcyB0aGF0IG5lZWQgdG8gcnVuIGhlcmVcblx0cHJpdmF0ZSBldmVudFF1ZXVlOiBFdmVudFF1ZXVlO1xuXHRwcml2YXRlIGlucHV0SGFuZGxlcjogSW5wdXRIYW5kbGVyO1xuXHRwcml2YXRlIHJlY29yZGVyOiBSZWNvcmRlcjtcbiAgICBwcml2YXRlIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuICAgIHByaXZhdGUgc2NlbmVNYW5hZ2VyOiBTY2VuZU1hbmFnZXI7XG4gICAgcHJpdmF0ZSBhdWRpb01hbmFnZXI6IEF1ZGlvTWFuYWdlcjtcbiAgICBwcml2YXRlIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXI7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEdhbWVcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgb3B0aW9ucyBmb3IgR2FtZSBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KXtcbiAgICAgICAgLy8gQmVmb3JlIGFueXRoaW5nIGVsc2UsIGJ1aWxkIHRoZSBlbnZpcm9ubWVudFxuICAgICAgICBFbnZpcm9ubWVudEluaXRpYWxpemVyLnNldHVwKCk7XG5cbiAgICAgICAgLy8gVHlwZWNhc3QgdGhlIGNvbmZpZyBvYmplY3QgdG8gYSBHYW1lQ29uZmlnIG9iamVjdFxuICAgICAgICB0aGlzLmdhbWVPcHRpb25zID0gR2FtZU9wdGlvbnMucGFyc2Uob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5zaG93RGVidWcgPSB0aGlzLmdhbWVPcHRpb25zLnNob3dEZWJ1ZztcbiAgICAgICAgdGhpcy5zaG93U3RhdHMgPSB0aGlzLmdhbWVPcHRpb25zLnNob3dTdGF0cztcblxuICAgICAgICAvLyBDcmVhdGUgYW4gaW5zdGFuY2Ugb2YgYSBnYW1lIGxvb3BcbiAgICAgICAgdGhpcy5sb29wID0gbmV3IEZpeGVkVXBkYXRlR2FtZUxvb3AoKTtcblxuICAgICAgICAvLyBHZXQgdGhlIGdhbWUgY2FudmFzIGFuZCBnaXZlIGl0IGEgYmFja2dyb3VuZCBjb2xvclxuICAgICAgICB0aGlzLkdBTUVfQ0FOVkFTID0gPEhUTUxDYW52YXNFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZ2FtZS1jYW52YXNcIik7XG4gICAgICAgIHRoaXMuREVCVUdfQ0FOVkFTID0gPEhUTUxDYW52YXNFbGVtZW50PmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiZGVidWctY2FudmFzXCIpO1xuICAgIFxuICAgICAgICAvLyBHaXZlIHRoZSBjYW52YXMgYSBzaXplIGFuZCBnZXQgdGhlIHJlbmRlcmluZyBjb250ZXh0XG4gICAgICAgIHRoaXMuV0lEVEggPSB0aGlzLmdhbWVPcHRpb25zLmNhbnZhc1NpemUueDtcbiAgICAgICAgdGhpcy5IRUlHSFQgPSB0aGlzLmdhbWVPcHRpb25zLmNhbnZhc1NpemUueTtcblxuICAgICAgICAvLyBUaGlzIHN0ZXAgTVVTVCBoYXBwZW4gYmVmb3JlIHRoZSByZXNvdXJjZSBtYW5hZ2VyIGRvZXMgYW55dGhpbmdcbiAgICAgICAgaWYodGhpcy5nYW1lT3B0aW9ucy51c2VXZWJHTCl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmluZ01hbmFnZXIgPSBuZXcgV2ViR0xSZW5kZXJlcigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyID0gbmV3IENhbnZhc1JlbmRlcmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbml0aWFsaXplR2FtZVdpbmRvdygpO1xuICAgICAgICB0aGlzLmN0eCA9IHRoaXMucmVuZGVyaW5nTWFuYWdlci5pbml0aWFsaXplQ2FudmFzKHRoaXMuR0FNRV9DQU5WQVMsIHRoaXMuV0lEVEgsIHRoaXMuSEVJR0hUKTtcbiAgICAgICAgdGhpcy5jbGVhckNvbG9yID0gbmV3IENvbG9yKHRoaXMuZ2FtZU9wdGlvbnMuY2xlYXJDb2xvci5yLCB0aGlzLmdhbWVPcHRpb25zLmNsZWFyQ29sb3IuZywgdGhpcy5nYW1lT3B0aW9ucy5jbGVhckNvbG9yLmIpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgZGVidWdnaW5nIGFuZCBzdGF0c1xuICAgICAgICBEZWJ1Zy5pbml0aWFsaXplRGVidWdDYW52YXModGhpcy5ERUJVR19DQU5WQVMsIHRoaXMuV0lEVEgsIHRoaXMuSEVJR0hUKTtcbiAgICAgICAgU3RhdHMuaW5pdFN0YXRzKCk7XG5cbiAgICAgICAgaWYodGhpcy5nYW1lT3B0aW9ucy5zaG93U3RhdHMpIHtcbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHN0YXRzIG91dHB1dCBhbmQgbWFrZSBpdCBubyBsb25nZXIgaGlkZGVuXG4gICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXRzXCIpLmhpZGRlbiA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2l6ZSB0aGUgdmlld3BvcnQgdG8gdGhlIGdhbWUgY2FudmFzXG4gICAgICAgIGNvbnN0IGNhbnZhc1NpemUgPSBuZXcgVmVjMih0aGlzLldJRFRILCB0aGlzLkhFSUdIVCk7XG4gICAgICAgIHRoaXMudmlld3BvcnQgPSBuZXcgVmlld3BvcnQoY2FudmFzU2l6ZSwgdGhpcy5nYW1lT3B0aW9ucy56b29tTGV2ZWwpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgYWxsIG5lY2Vzc2FyeSBnYW1lIHN1YnN5c3RlbXNcbiAgICAgICAgdGhpcy5ldmVudFF1ZXVlID0gRXZlbnRRdWV1ZS5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmlucHV0SGFuZGxlciA9IG5ldyBJbnB1dEhhbmRsZXIodGhpcy5HQU1FX0NBTlZBUyk7XG4gICAgICAgIElucHV0LmluaXRpYWxpemUodGhpcy52aWV3cG9ydCwgdGhpcy5nYW1lT3B0aW9ucy5pbnB1dHMpO1xuICAgICAgICB0aGlzLnJlY29yZGVyID0gbmV3IFJlY29yZGVyKCk7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyID0gbmV3IFNjZW5lTWFuYWdlcih0aGlzLnZpZXdwb3J0LCB0aGlzLnJlbmRlcmluZ01hbmFnZXIpO1xuICAgICAgICB0aGlzLmF1ZGlvTWFuYWdlciA9IEF1ZGlvTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB1cCB0aGUgZ2FtZSB3aW5kb3cgdGhhdCBob2xkcyB0aGUgY2FudmFzZXNcbiAgICAgKi9cbiAgICBwcml2YXRlIGluaXRpYWxpemVHYW1lV2luZG93KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBnYW1lV2luZG93ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJnYW1lLXdpbmRvd1wiKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFNldCB0aGUgaGVpZ2h0IG9mIHRoZSBnYW1lIHdpbmRvd1xuICAgICAgICBnYW1lV2luZG93LnN0eWxlLndpZHRoID0gdGhpcy5XSURUSCArIFwicHhcIjtcbiAgICAgICAgZ2FtZVdpbmRvdy5zdHlsZS5oZWlnaHQgPSB0aGlzLkhFSUdIVCArIFwicHhcIjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgdGhlIFNjZW5lTWFuYWdlciBmcm9tIHRoZSBHYW1lXG4gICAgICogQHJldHVybnMgVGhlIFNjZW5lTWFuYWdlclxuICAgICAqL1xuICAgIGdldFNjZW5lTWFuYWdlcigpOiBTY2VuZU1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2VuZU1hbmFnZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RhcnRzIHRoZSBnYW1lXG4gICAgICovXG4gICAgc3RhcnQoSW5pdGlhbFNjZW5lOiBuZXcgKC4uLmFyZ3M6IGFueSkgPT4gU2NlbmUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgLy8gU2V0IHRoZSB1cGRhdGUgZnVuY3Rpb24gb2YgdGhlIGxvb3BcbiAgICAgICAgdGhpcy5sb29wLmRvVXBkYXRlID0gKGRlbHRhVDogbnVtYmVyKSA9PiB0aGlzLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgcmVuZGVyIGZ1bmN0aW9uIG9mIHRoZSBsb29wXG4gICAgICAgIHRoaXMubG9vcC5kb1JlbmRlciA9ICgpID0+IHRoaXMucmVuZGVyKCk7XG5cbiAgICAgICAgLy8gUHJlbG9hZCByZWdpc3RyeSBpdGVtc1xuICAgICAgICBSZWdpc3RyeU1hbmFnZXIucHJlbG9hZCgpO1xuXG4gICAgICAgIC8vIExvYWQgdGhlIGl0ZW1zIHdpdGggdGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIubG9hZFJlc291cmNlc0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlJ3JlIGRvbmUgbG9hZGluZywgc3RhcnQgdGhlIGxvb3BcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRmluaXNoZWQgUHJlbG9hZCAtIGxvYWRpbmcgZmlyc3Qgc2NlbmVcIik7XG4gICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKEluaXRpYWxTY2VuZSwge30sIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5sb29wLnN0YXJ0KCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgYWxsIG5lY2Vzc2FyeSBzdWJzeXN0ZW1zIG9mIHRoZSBnYW1lLiBEZWZlcnMgc2NlbmUgdXBkYXRlcyB0byB0aGUgc2NlbmVNYW5hZ2VyXG4gICAgICogQHBhcmFtIGRlbHRhVCBUaGUgdGltZSBzaW5lIHRoZSBsYXN0IHVwZGF0ZVxuICAgICAqL1xuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0cnl7XG4gICAgICAgICAgICAvLyBIYW5kbGUgYWxsIGV2ZW50cyB0aGF0IGhhcHBlbmVkIHNpbmNlIHRoZSBzdGFydCBvZiB0aGUgbGFzdCBsb29wXG4gICAgICAgICAgICB0aGlzLmV2ZW50UXVldWUudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgaW5wdXQgZGF0YSBzdHJ1Y3R1cmVzIHNvIGdhbWUgb2JqZWN0cyBjYW4gc2VlIHRoZSBpbnB1dFxuICAgICAgICAgICAgSW5wdXQudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVjb3JkaW5nIG9mIHRoZSBnYW1lXG4gICAgICAgICAgICB0aGlzLnJlY29yZGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgYWxsIHNjZW5lc1xuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSBhbGwgc291bmRzXG4gICAgICAgICAgICB0aGlzLmF1ZGlvTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gTG9hZCBvciB1bmxvYWQgYW55IHJlc291cmNlcyBpZiBuZWVkZWRcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICB9IGNhdGNoKGUpe1xuICAgICAgICAgICAgdGhpcy5sb29wLnBhdXNlKCk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJVbmNhdWdodCBFcnJvciBpbiBVcGRhdGUgLSBDcmFzaGluZyBncmFjZWZ1bGx5XCIpO1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyB0aGUgY2FudmFzIGFuZCBkZWZlcnMgc2NlbmUgcmVuZGVyaW5nIHRvIHRoZSBzY2VuZU1hbmFnZXIuIFJlbmRlcnMgdGhlIGRlYnVnIGNhbnZhc1xuICAgICAqL1xuICAgIHJlbmRlcigpOiB2b2lkIHtcbiAgICAgICAgdHJ5e1xuICAgICAgICAgICAgLy8gQ2xlYXIgdGhlIGNhbnZhc2VzXG4gICAgICAgICAgICBEZWJ1Zy5jbGVhckNhbnZhcygpO1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlcmluZ01hbmFnZXIuY2xlYXIodGhpcy5jbGVhckNvbG9yKTtcblxuICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIucmVuZGVyKCk7XG5cbiAgICAgICAgICAgIC8vIEhhY2t5IGRlYnVnIG1vZGVcbiAgICAgICAgICAgIGlmKElucHV0LmlzS2V5SnVzdFByZXNzZWQoXCJnXCIpKXtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dEZWJ1ZyA9ICF0aGlzLnNob3dEZWJ1ZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRGVidWcgcmVuZGVyXG4gICAgICAgICAgICBpZih0aGlzLnNob3dEZWJ1Zyl7XG4gICAgICAgICAgICAgICAgRGVidWcucmVuZGVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHRoaXMuc2hvd1N0YXRzKXtcbiAgICAgICAgICAgICAgICBTdGF0cy5yZW5kZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIHRoaXMubG9vcC5wYXVzZSgpO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiVW5jYXVnaHQgRXJyb3IgaW4gUmVuZGVyIC0gQ3Jhc2hpbmcgZ3JhY2VmdWxseVwiKTtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IE51bGxGdW5jIGZyb20gXCIuLi9EYXRhVHlwZXMvRnVuY3Rpb25zL051bGxGdW5jXCI7XG5cbi8qKlxuICogVGhlIG1haW4gZ2FtZSBsb29wIG9mIHRoZSBnYW1lLiBLZWVwcyB0cmFjayBvZiBmcHMgYW5kIGhhbmRsZXMgc2NoZWR1bGluZyBvZiB1cGRhdGVzIGFuZCByZW5kZXJpbmcuXG4gKiBUaGlzIGNsYXNzIGlzIGxlZnQgYWJzdHJhY3QsIHNvIHRoYXQgYSBzdWJjbGFzcyBjYW4gaGFuZGxlIGV4YWN0bHkgaG93IHRoZSBsb29wIGlzIHNjaGVkdWxlZC5cbiAqIEZvciBhbiBleGFtcGxlIG9mIGRpZmZlcmVudCB0eXBlcyBvZiBnYW1lIGxvb3Agc2NoZWR1bGluZywgY2hlY2sgb3V0IEBsaW5rKEdhbWUgUHJvZ3JhbW1pbmcgUGF0dGVybnMpKGh0dHBzOi8vZ2FtZXByb2dyYW1taW5ncGF0dGVybnMuY29tL2dhbWUtbG9vcC5odG1sKVxuICovXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBHYW1lTG9vcCB7XG5cblx0LyoqIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gYW4gdXBkYXRlIG9jY3VycyAqL1xuXHRwcm90ZWN0ZWQgX2RvVXBkYXRlOiBGdW5jdGlvbiA9IE51bGxGdW5jO1xuXG5cdHNldCBkb1VwZGF0ZSh1cGRhdGU6IEZ1bmN0aW9uKXtcblx0XHR0aGlzLl9kb1VwZGF0ZSA9IHVwZGF0ZTtcblx0fVxuXG5cdC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIGEgcmVuZGVyIG9jY3VycyAqL1xuXHRwcm90ZWN0ZWQgX2RvUmVuZGVyOiBGdW5jdGlvbiA9IE51bGxGdW5jO1xuXG5cblx0c2V0IGRvUmVuZGVyKHJlbmRlcjogRnVuY3Rpb24pe1xuXHRcdHRoaXMuX2RvUmVuZGVyID0gcmVuZGVyO1xuXHR9XG5cdFxuXHQvKipcblx0ICogUmV0cmlldmVzIHRoZSBjdXJyZW50IEZQUyBvZiB0aGUgZ2FtZVxuXHQgKi9cblx0YWJzdHJhY3QgZ2V0RlBTKCk6IG51bWJlcjtcblxuXHQvKipcbiAgICAgKiBTdGFydHMgdXAgdGhlIGdhbWUgbG9vcFxuICAgICAqL1xuXHRhYnN0cmFjdCBzdGFydCgpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBQYXVzZXMgdGhlIGdhbWUgbG9vcCwgdXN1YWxseSBmb3IgYW4gZXJyb3IgY29uZGl0aW9uLlxuXHQgKi9cblx0YWJzdHJhY3QgcGF1c2UoKTogdm9pZDtcblxuXHQvKipcblx0ICogUmVzdW1lcyB0aGUgZ2FtZSBsb29wLlxuXHQgKi9cblx0YWJzdHJhY3QgcmVzdW1lKCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJ1bnMgdGhlIGZpcnN0IGZyYW1lIG9mIHRoZSBnYW1lLiBObyB1cGRhdGUgb2NjdXJzIGhlcmUsIG9ubHkgYSByZW5kZXIuXG5cdCAqIFRoaXMgaXMgbmVlZGVkIHRvIGluaXRpYWxpemUgZGVsdGEgdGltZSB2YWx1ZXNcblx0ICogQHBhcmFtIHRpbWVzdGFtcCBUaGUgdGltZXN0YW1wIG9mIHRoZSBmcmFtZS4gVGhpcyBpcyByZWNlaXZlZCBmcm9tIHRoZSBicm93c2VyXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZG9GaXJzdEZyYW1lKHRpbWVzdGFtcDogbnVtYmVyKTogdm9pZDtcblxuXHQvKipcblx0ICogUnVuIGJlZm9yZSBhbnkgdXBkYXRlcyBvciB0aGUgcmVuZGVyIG9mIGEgZnJhbWUuXG5cdCAqIEBwYXJhbSB0aW1lc3RhbXAgVGhlIHRpbWVzdGFtcCBvZiB0aGUgZnJhbWUuIFRoaXMgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgYnJvd3NlclxuXHQgKi9cblx0cHJvdGVjdGVkIGFic3RyYWN0IHN0YXJ0RnJhbWUodGltZXN0YW1wOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBUaGUgY29yZSBvZiB0aGUgZnJhbWUsIHdoZXJlIGFueSBuZWNlc3NhcnkgdXBkYXRlcyBvY2N1ciwgYW5kIHdoZXJlIGEgcmVuZGVyIGhhcHBlbnNcblx0ICogQHBhcmFtIHRpbWVzdGFtcCBUaGUgdGltZXN0YW1wIG9mIHRoZSBmcmFtZS4gVGhpcyBpcyByZWNlaXZlZCBmcm9tIHRoZSBicm93c2VyXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZG9GcmFtZSh0aW1lc3RhbXA6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFdyYXBzIHVwIHRoZSBmcmFtZVxuXHQgKiBAcGFyYW0gcGFuaWMgV2hldGhlciBvciBub3QgdGhlIHVwZGF0ZSBjeWNsZSBwYW5pY2tlZC4gVGhpcyBoYXBwZW5zIHdoZW4gdG9vIG1hbnkgdXBkYXRlcyB0cnkgdG8gaGFwcGVuIGluIGEgc2luZ2xlIGZyYW1lXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgZmluaXNoRnJhbWUocGFuaWM6IGJvb2xlYW4pOiB2b2lkO1xufSIsIi8vIEBpZ25vcmVQYWdlXG5cbi8qKiBUaGUgb3B0aW9ucyBmb3IgaW5pdGlhbGl6aW5nIHRoZSBAcmVmZXJlbmNlW0dhbWVMb29wXSAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2FtZU9wdGlvbnMge1xuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgdmlld3BvcnQgKi9cbiAgICBjYW52YXNTaXplOiB7eDogbnVtYmVyLCB5OiBudW1iZXJ9O1xuXG4gICAgLyogVGhlIGRlZmF1bHQgbGV2ZWwgb2Ygem9vbSAqL1xuICAgIHpvb21MZXZlbDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBjb2xvciB0byBjbGVhciB0aGUgY2FudmFzIHRvIGVhY2ggZnJhbWUgKi9cbiAgICBjbGVhckNvbG9yOiB7cjogbnVtYmVyLCBnOiBudW1iZXIsIGI6IG51bWJlcn1cblxuICAgIC8qIEEgbGlzdCBvZiBpbnB1dCBiaW5kaW5ncyAqL1xuICAgIGlucHV0czogQXJyYXk8e25hbWU6IHN0cmluZywga2V5czogQXJyYXk8c3RyaW5nPn0+O1xuXG4gICAgLyogV2hldGhlciBvciBub3QgdGhlIGRlYnVnIHJlbmRlcmluZyBzaG91bGQgb2NjdXIgKi9cbiAgICBzaG93RGVidWc6IGJvb2xlYW47XG5cbiAgICAvKiBXaGV0aGVyIG9yIG5vdCB0aGUgc3RhdHMgcmVuZGVyaW5nIHNob3VsZCBvY2N1ciAqL1xuICAgIHNob3dTdGF0czogYm9vbGVhbjtcblxuICAgIC8qIFdoZXRoZXIgb3Igbm90IHRvIHVzZSB3ZWJHTCAqL1xuICAgIHVzZVdlYkdMOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogUGFyc2VzIHRoZSBkYXRhIGluIHRoZSByYXcgb3B0aW9ucyBvYmplY3RcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZ2FtZSBvcHRpb25zIGFzIGEgUmVjb3JkXG4gICAgICogQHJldHVybnMgQSB2ZXJzaW9uIG9mIHRoZSBvcHRpb25zIGNvbnZlcnRlZCB0byBhIEdhbWVPcHRpb25zIG9iamVjdFxuICAgICAqL1xuICAgIHN0YXRpYyBwYXJzZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR2FtZU9wdGlvbnMge1xuICAgICAgICBsZXQgZ09wdCA9IG5ldyBHYW1lT3B0aW9ucygpO1xuXG4gICAgICAgIGdPcHQuY2FudmFzU2l6ZSA9IG9wdGlvbnMuY2FudmFzU2l6ZSA/IG9wdGlvbnMuY2FudmFzU2l6ZSA6IHt4OiA4MDAsIHk6IDYwMH07XG4gICAgICAgIGdPcHQuem9vbUxldmVsID0gb3B0aW9ucy56b29tTGV2ZWwgPyBvcHRpb25zLnpvb21MZXZlbCA6IDE7XG4gICAgICAgIGdPcHQuY2xlYXJDb2xvciA9IG9wdGlvbnMuY2xlYXJDb2xvciA/IG9wdGlvbnMuY2xlYXJDb2xvciA6IHtyOiAyNTUsIGc6IDI1NSwgYjogMjU1fTtcbiAgICAgICAgZ09wdC5pbnB1dHMgPSBvcHRpb25zLmlucHV0cyA/IG9wdGlvbnMuaW5wdXRzIDogW107XG4gICAgICAgIGdPcHQuc2hvd0RlYnVnID0gISFvcHRpb25zLnNob3dEZWJ1ZztcbiAgICAgICAgZ09wdC5zaG93U3RhdHMgPSAhIW9wdGlvbnMuc2hvd1N0YXRzO1xuICAgICAgICBnT3B0LnVzZVdlYkdMID0gISFvcHRpb25zLnVzZVdlYkdMO1xuXG4gICAgICAgIHJldHVybiBnT3B0O1xuICAgIH1cbn0iLCJpbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4vR2FtZU5vZGVcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFJlZ2lvbiBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUmVnaW9uXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbiB0aGUgZ2FtZSB3b3JsZCB0aGF0IGNhbiBiZSBkcmF3biB0byB0aGUgc2NyZWVuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIENhbnZhc05vZGUgZXh0ZW5kcyBHYW1lTm9kZSBpbXBsZW1lbnRzIFJlZ2lvbiB7XG5cdHByaXZhdGUgX3NpemU6IFZlYzI7XG5cdHByaXZhdGUgX3NjYWxlOiBWZWMyO1xuXHRwcml2YXRlIF9ib3VuZGFyeTogQUFCQjtcblx0cHJpdmF0ZSBfaGFzQ3VzdG9tU2hhZGVyOiBib29sZWFuO1xuXHRwcml2YXRlIF9jdXN0b21TaGFkZXJLZXk6IHN0cmluZztcblx0cHJpdmF0ZSBfYWxwaGE6IG51bWJlcjtcblxuXHQvKiogQSBmbGFnIGZvciB3aGV0aGVyIG9yIG5vdCB0aGUgQ2FudmFzTm9kZSBpcyB2aXNpYmxlICovXG5cdHZpc2libGU6IGJvb2xlYW4gPSB0cnVlO1xuXHRcblx0Y29uc3RydWN0b3IoKXtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMuX3NpemUgPSBuZXcgVmVjMigwLCAwKTtcblx0XHR0aGlzLl9zaXplLnNldE9uQ2hhbmdlKCgpID0+IHRoaXMuc2l6ZUNoYW5nZWQoKSk7XG5cdFx0dGhpcy5fc2NhbGUgPSBuZXcgVmVjMigxLCAxKTtcblx0XHR0aGlzLl9zY2FsZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNjYWxlQ2hhbmdlZCgpKTtcblx0XHR0aGlzLl9ib3VuZGFyeSA9IG5ldyBBQUJCKCk7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXG5cdFx0dGhpcy5faGFzQ3VzdG9tU2hhZGVyID0gZmFsc2U7XG5cdH1cblxuXHRnZXQgYWxwaGEoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5fYWxwaGE7XG5cdH1cblxuXHRzZXQgYWxwaGEoYTogbnVtYmVyKSB7XG5cdFx0dGhpcy5fYWxwaGEgPSBhO1xuXHR9XG5cblx0Z2V0IHNpemUoKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuX3NpemU7XG5cdH1cblxuXHRzZXQgc2l6ZShzaXplOiBWZWMyKXtcblx0XHR0aGlzLl9zaXplID0gc2l6ZTtcblx0XHQvLyBFbnRlciBhcyBhIGxhbWJkYSB0byBiaW5kIFwidGhpc1wiXG5cdFx0dGhpcy5fc2l6ZS5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnNpemVDaGFuZ2VkKCkpO1xuXHRcdHRoaXMuc2l6ZUNoYW5nZWQoKTtcblx0fVxuXG5cdGdldCBzY2FsZSgpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fc2NhbGU7XG5cdH1cblxuXHRzZXQgc2NhbGUoc2NhbGU6IFZlYzIpe1xuXHRcdHRoaXMuX3NjYWxlID0gc2NhbGU7XG5cdFx0Ly8gRW50ZXIgYXMgYSBsYW1iZGEgdG8gYmluZCBcInRoaXNcIlxuXHRcdHRoaXMuX3NjYWxlLnNldE9uQ2hhbmdlKCgpID0+IHRoaXMuc2NhbGVDaGFuZ2VkKCkpO1xuXHRcdHRoaXMuc2NhbGVDaGFuZ2VkKCk7XG5cdH1cblxuXHRzZXQgc2NhbGVYKHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLnNjYWxlLnggPSB2YWx1ZTtcblx0fVxuXG5cdHNldCBzY2FsZVkodmFsdWU6IG51bWJlcikge1xuXHRcdHRoaXMuc2NhbGUueSA9IHZhbHVlO1xuXHR9XG5cblx0Z2V0IGhhc0N1c3RvbVNoYWRlcigpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5faGFzQ3VzdG9tU2hhZGVyO1xuXHR9XG5cblx0Z2V0IGN1c3RvbVNoYWRlcktleSgpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLl9jdXN0b21TaGFkZXJLZXk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0cHJvdGVjdGVkIHBvc2l0aW9uQ2hhbmdlZCgpOiB2b2lkIHtcblx0XHRzdXBlci5wb3NpdGlvbkNoYW5nZWQoKTtcblx0XHR0aGlzLnVwZGF0ZUJvdW5kYXJ5KCk7XG5cdH1cblxuXHQvKiogQ2FsbGVkIGlmIHRoZSBzaXplIHZlY3RvciBpcyBjaGFuZ2VkIG9yIHJlcGxhY2VkLiAqL1xuXHRwcm90ZWN0ZWQgc2l6ZUNoYW5nZWQoKTogdm9pZCB7XG5cdFx0dGhpcy51cGRhdGVCb3VuZGFyeSgpO1xuXHR9XG5cblx0LyoqIENhbGxlZCBpZiB0aGUgc2NhbGUgdmVjdG9yIGlzIGNoYW5nZWQgb3IgcmVwbGFjZWQgKi9cblx0cHJvdGVjdGVkIHNjYWxlQ2hhbmdlZCgpOiB2b2lkIHtcblx0XHR0aGlzLnVwZGF0ZUJvdW5kYXJ5KCk7XG5cdH1cblxuXHQvLyBAZG9jSWdub3JlXG5cdC8qKiBDYWxsZWQgaWYgdGhlIHBvc2l0aW9uLCBzaXplLCBvciBzY2FsZSBvZiB0aGUgQ2FudmFzTm9kZSBpcyBjaGFuZ2VkLiBVcGRhdGVzIHRoZSBib3VuZGFyeS4gKi9cblx0cHJpdmF0ZSB1cGRhdGVCb3VuZGFyeSgpOiB2b2lkIHtcblx0XHR0aGlzLl9ib3VuZGFyeS5jZW50ZXIuc2V0KHRoaXMucG9zaXRpb24ueCwgdGhpcy5wb3NpdGlvbi55KTtcblx0XHR0aGlzLl9ib3VuZGFyeS5oYWxmU2l6ZS5zZXQodGhpcy5zaXplLngqdGhpcy5zY2FsZS54LzIsIHRoaXMuc2l6ZS55KnRoaXMuc2NhbGUueS8yKTtcblx0fVxuXG5cdGdldCBib3VuZGFyeSgpOiBBQUJCIHtcblx0XHRyZXR1cm4gdGhpcy5fYm91bmRhcnk7XG5cdH1cblxuXHRnZXQgc2l6ZVdpdGhab29tKCk6IFZlYzIge1xuXHRcdGxldCB6b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcblxuXHRcdHJldHVybiB0aGlzLmJvdW5kYXJ5LmhhbGZTaXplLmNsb25lKCkuc2NhbGVkKHpvb20sIHpvb20pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBjdXN0b20gc2hhZGVyIHRvIHRoaXMgQ2FudmFzTm9kZVxuXHQgKiBAcGFyYW0ga2V5IFRoZSByZWdpc3RyeSBrZXkgb2YgdGhlIFNoYWRlclR5cGVcblx0ICovXG5cdHVzZUN1c3RvbVNoYWRlcihrZXk6IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMuX2hhc0N1c3RvbVNoYWRlciA9IHRydWU7XG5cdFx0dGhpcy5fY3VzdG9tU2hhZGVyS2V5ID0ga2V5O1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcG9pbnQgKHgsIHkpIGlzIGluc2lkZSBvZiB0aGlzIGNhbnZhcyBvYmplY3Rcblx0ICogQHBhcmFtIHggVGhlIHggcG9zaXRpb24gb2YgdGhlIHBvaW50XG5cdCAqIEBwYXJhbSB5IFRoZSB5IHBvc2l0aW9uIG9mIHRoZSBwb2ludFxuXHQgKiBAcmV0dXJucyBBIGZsYWcgcmVwcmVzZW50aW5nIHdoZXRoZXIgb3Igbm90IHRoaXMgbm9kZSBjb250YWlucyB0aGUgcG9pbnQuXG5cdCAqL1xuXHRjb250YWlucyh4OiBudW1iZXIsIHk6IG51bWJlcik6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLl9ib3VuZGFyeS5jb250YWluc1BvaW50KG5ldyBWZWMyKHgsIHkpKTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHRkZWJ1Z1JlbmRlcigpOiB2b2lkIHtcblx0XHREZWJ1Zy5kcmF3Qm94KHRoaXMucmVsYXRpdmVQb3NpdGlvbiwgdGhpcy5zaXplV2l0aFpvb20sIGZhbHNlLCBDb2xvci5CTFVFKTtcblx0XHRzdXBlci5kZWJ1Z1JlbmRlcigpO1xuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgQUkgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL0FJXCI7XG5pbXBvcnQgUGh5c2ljYWwgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1BoeXNpY2FsXCI7XG5pbXBvcnQgUG9zaXRpb25lZCBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUG9zaXRpb25lZFwiO1xuaW1wb3J0IHsgaXNSZWdpb24gfSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUmVnaW9uXCI7XG5pbXBvcnQgVW5pcXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VbmlxdWVcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgRGVidWdSZW5kZXJhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9EZWJ1Z1JlbmRlcmFibGVcIjtcbmltcG9ydCBBY3RvciBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvQWN0b3JcIjtcbmltcG9ydCBTaGFwZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9TaGFwZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuLi9QYXRoZmluZGluZy9OYXZpZ2F0aW9uUGF0aFwiO1xuaW1wb3J0IFR3ZWVuQ29udHJvbGxlciBmcm9tIFwiLi4vUmVuZGVyaW5nL0FuaW1hdGlvbnMvVHdlZW5Db250cm9sbGVyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgQ2lyY2xlIGZyb20gXCIuLi9EYXRhVHlwZXMvU2hhcGVzL0NpcmNsZVwiO1xuaW1wb3J0IEdvYXBBSSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvR29hcEFJXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdCBpbiB0aGUgZ2FtZSB3b3JsZC5cbiAqIFRvIGNvbnN0cnVjdCBHYW1lTm9kZXMsIHNlZSB0aGUgQHJlZmVyZW5jZVtTY2VuZV0gZG9jdW1lbnRhdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgR2FtZU5vZGUgaW1wbGVtZW50cyBQb3NpdGlvbmVkLCBVbmlxdWUsIFVwZGF0ZWFibGUsIFBoeXNpY2FsLCBBY3RvciwgRGVidWdSZW5kZXJhYmxlIHtcblx0LyotLS0tLS0tLS0tIFBPU0lUSU9ORUQgLS0tLS0tLS0tLSovXG5cdHByaXZhdGUgX3Bvc2l0aW9uOiBWZWMyO1xuXG5cdC8qLS0tLS0tLS0tLSBVTklRVUUgLS0tLS0tLS0tLSovXG5cdHByaXZhdGUgX2lkOiBudW1iZXI7XG5cblx0LyotLS0tLS0tLS0tIFBIWVNJQ0FMIC0tLS0tLS0tLS0qL1xuXHRoYXNQaHlzaWNzOiBib29sZWFuID0gZmFsc2U7XG5cdG1vdmluZzogYm9vbGVhbiA9IGZhbHNlO1xuXHRmcm96ZW46IGJvb2xlYW4gPSBmYWxzZTtcblx0b25Hcm91bmQ6IGJvb2xlYW4gPSBmYWxzZTtcblx0b25XYWxsOiBib29sZWFuID0gZmFsc2U7XG5cdG9uQ2VpbGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXHRhY3RpdmU6IGJvb2xlYW4gPSBmYWxzZTtcblx0Y29sbGlzaW9uU2hhcGU6IFNoYXBlO1xuXHRjb2xsaWRlck9mZnNldDogVmVjMjtcblx0aXNTdGF0aWM6IGJvb2xlYW47XG5cdGlzQ29sbGlkYWJsZTogYm9vbGVhbjtcblx0aXNUcmlnZ2VyOiBib29sZWFuO1xuXHR0cmlnZ2VyTWFzazogbnVtYmVyO1xuXHR0cmlnZ2VyRW50ZXJzOiBBcnJheTxzdHJpbmc+O1xuXHR0cmlnZ2VyRXhpdHM6IEFycmF5PHN0cmluZz47XG5cdF92ZWxvY2l0eTogVmVjMjtcblx0c3dlcHRSZWN0OiBBQUJCO1xuXHRjb2xsaWRlZFdpdGhUaWxlbWFwOiBib29sZWFuO1xuXHRncm91cDogbnVtYmVyO1xuXHRpc1BsYXllcjogYm9vbGVhbjtcblx0aXNDb2xsaWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHQvKi0tLS0tLS0tLS0gQUNUT1IgLS0tLS0tLS0tLSovXG5cdF9haTogQUkgfCBHb2FwQUk7XG5cdGFpQWN0aXZlOiBib29sZWFuO1xuXHRwYXRoOiBOYXZpZ2F0aW9uUGF0aDtcblx0cGF0aGZpbmRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuXHQvKi0tLS0tLS0tLS0gR0VORVJBTCAtLS0tLS0tLS0tKi9cblx0LyoqIEFuIGV2ZW50IHJlY2VpdmVyLiAqL1xuXHRwcm90ZWN0ZWQgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuXHQvKiogQW4gZXZlbnQgZW1pdHRlci4gKi9cblx0cHJvdGVjdGVkIGVtaXR0ZXI6IEVtaXR0ZXI7XG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgc2NlbmUgdGhpcyBHYW1lTm9kZSBpcyBhIHBhcnQgb2YuICovXG5cdHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cdC8qKiBUaGUgdmlzdWFsIGxheWVyIHRoaXMgR2FtZU5vZGUgcmVzaWRlcyBpbi4gKi9cblx0cHJvdGVjdGVkIGxheWVyOiBMYXllcjtcblx0LyoqIEEgdXRpbGl0eSB0aGF0IGFsbG93cyB0aGUgdXNlIG9mIHR3ZWVucyBvbiB0aGlzIEdhbWVOb2RlICovXG5cdHR3ZWVuczogVHdlZW5Db250cm9sbGVyO1xuXHQvKiogQSB0d2VlbmFibGUgcHJvcGVydHkgZm9yIHJvdGF0aW9uLiBEb2VzIG5vdCBhZmZlY3QgdGhlIGJvdW5kaW5nIGJveCBvZiB0aGlzIEdhbWVOb2RlIC0gT25seSByZW5kZXJpbmcuICovXG5cdHJvdGF0aW9uOiBudW1iZXI7XG5cdC8qKiBUaGUgb3BhY2l0eSB2YWx1ZSBvZiB0aGlzIEdhbWVOb2RlICovXG5cdGFic3RyYWN0IHNldCBhbHBoYShhOiBudW1iZXIpO1xuXG5cdGFic3RyYWN0IGdldCBhbHBoYSgpOiBudW1iZXI7XG5cblx0Ly8gQ29uc3RydWN0b3IgZG9jcyBhcmUgaWdub3JlZCwgYXMgdGhlIHVzZXIgc2hvdWxkIE5PVCBjcmVhdGUgbmV3IEdhbWVOb2RlcyB3aXRoIGEgcmF3IGNvbnN0cnVjdG9yXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5fcG9zaXRpb24gPSBuZXcgVmVjMigwLCAwKTtcblx0XHR0aGlzLl9wb3NpdGlvbi5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblx0XHR0aGlzLnR3ZWVucyA9IG5ldyBUd2VlbkNvbnRyb2xsZXIodGhpcyk7XG5cdFx0dGhpcy5yb3RhdGlvbiA9IDA7XG5cdH1cblxuXHRkZXN0cm95KCl7XG5cdFx0dGhpcy50d2VlbnMuZGVzdHJveSgpO1xuXHRcdHRoaXMucmVjZWl2ZXIuZGVzdHJveSgpO1xuXG5cdFx0aWYodGhpcy5oYXNQaHlzaWNzKXtcblx0XHRcdHRoaXMucmVtb3ZlUGh5c2ljcygpO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMuX2FpKXtcblx0XHRcdHRoaXMuX2FpLmRlc3Ryb3koKTtcblx0XHRcdGRlbGV0ZSB0aGlzLl9haTtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVtb3ZlQWN0b3IodGhpcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zY2VuZS5yZW1vdmUodGhpcyk7XG5cblx0XHR0aGlzLmxheWVyLnJlbW92ZU5vZGUodGhpcyk7XG5cdH1cblxuXHQvKi0tLS0tLS0tLS0gUE9TSVRJT05FRCAtLS0tLS0tLS0tKi9cblx0Z2V0IHBvc2l0aW9uKCk6IFZlYzIge1xuXHRcdHJldHVybiB0aGlzLl9wb3NpdGlvbjtcblx0fVxuXG5cdHNldCBwb3NpdGlvbihwb3M6IFZlYzIpIHtcblx0XHR0aGlzLl9wb3NpdGlvbiA9IHBvcztcblx0XHR0aGlzLl9wb3NpdGlvbi5zZXRPbkNoYW5nZSgoKSA9PiB0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpKTtcblx0XHR0aGlzLnBvc2l0aW9uQ2hhbmdlZCgpO1xuXHR9XG5cblx0Z2V0IHJlbGF0aXZlUG9zaXRpb24oKTogVmVjMiB7XG5cdFx0cmV0dXJuIHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHRoaXMucG9zaXRpb24pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgcG9pbnQgdG8gY29vcmRpbmF0ZXMgcmVsYXRpdmUgdG8gdGhlIHpvb20gYW5kIG9yaWdpbiBvZiB0aGlzIG5vZGVcblx0ICogQHBhcmFtIHBvaW50IFRoZSBwb2ludCB0byBjb252ZXJcblx0ICogQHJldHVybnMgQSBuZXcgVmVjMiByZXByZXNlbnRpbmcgdGhlIHBvaW50IGluIHJlbGF0aXZlIGNvb3JkaW5hdGVzXG5cdCAqL1xuXHRpblJlbGF0aXZlQ29vcmRpbmF0ZXMocG9pbnQ6IFZlYzIpOiBWZWMyIHtcblx0XHRsZXQgb3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24odGhpcyk7XG5cdFx0bGV0IHpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuXHRcdHJldHVybiBwb2ludC5jbG9uZSgpLnN1YihvcmlnaW4pLnNjYWxlKHpvb20pO1xuXHR9XG5cblx0LyotLS0tLS0tLS0tIFVOSVFVRSAtLS0tLS0tLS0tKi9cblx0Z2V0IGlkKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuX2lkO1xuXHR9XG5cblx0c2V0IGlkKGlkOiBudW1iZXIpIHtcblx0XHQvLyBpZCBjYW4gb25seSBiZSBzZXQgb25jZVxuXHRcdGlmKHRoaXMuX2lkID09PSB1bmRlZmluZWQpe1xuXHRcdFx0dGhpcy5faWQgPSBpZDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhyb3cgXCJBdHRlbXB0ZWQgdG8gYXNzaWduIGlkIHRvIG9iamVjdCB0aGF0IGFscmVhZHkgaGFzIGlkLlwiXG5cdFx0fVxuXHR9XG5cblx0LyotLS0tLS0tLS0tIFBIWVNJQ0FMIC0tLS0tLS0tLS0qL1xuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG4gICAgICogQHBhcmFtIHZlbG9jaXR5IFRoZSB2ZWxvY2l0eSB3aXRoIHdoaWNoIHRvIG1vdmUgdGhlIG9iamVjdC5cbiAgICAgKi9cblx0bW92ZSh2ZWxvY2l0eTogVmVjMik6IHZvaWQge1xuXHRcdGlmKHRoaXMuZnJvemVuKSByZXR1cm47XG5cdFx0dGhpcy5tb3ZpbmcgPSB0cnVlO1xuXHRcdHRoaXMuX3ZlbG9jaXR5ID0gdmVsb2NpdHk7XG5cdH07XG5cblx0bW92ZU9uUGF0aChzcGVlZDogbnVtYmVyLCBwYXRoOiBOYXZpZ2F0aW9uUGF0aCk6IHZvaWQge1xuXHRcdGlmKHRoaXMuZnJvemVuKSByZXR1cm47XG5cdFx0dGhpcy5wYXRoID0gcGF0aDtcblx0XHRsZXQgZGlyID0gcGF0aC5nZXRNb3ZlRGlyZWN0aW9uKHRoaXMpO1xuXHRcdHRoaXMubW92aW5nID0gdHJ1ZTtcblx0XHR0aGlzLnBhdGhmaW5kaW5nID0gdHJ1ZTtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IGRpci5zY2FsZShzcGVlZCk7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gdmVsb2NpdHkgVGhlIHZlbG9jaXR5IHdpdGggd2hpY2ggdGhlIG9iamVjdCB3aWxsIG1vdmUuXG4gICAgICovXG5cdGZpbmlzaE1vdmUoKTogdm9pZCB7XG5cdFx0dGhpcy5tb3ZpbmcgPSBmYWxzZTtcblx0XHR0aGlzLnBvc2l0aW9uLmFkZCh0aGlzLl92ZWxvY2l0eSk7XG5cdFx0aWYodGhpcy5wYXRoZmluZGluZyl7XG5cdFx0XHR0aGlzLnBhdGguaGFuZGxlUGF0aFByb2dyZXNzKHRoaXMpO1xuXHRcdFx0dGhpcy5wYXRoID0gbnVsbDtcblx0XHRcdHRoaXMucGF0aGZpbmRpbmcgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG5cdCAqIEBwYXJhbSBjb2xsaXNpb25TaGFwZSBUaGUgY29sbGlkZXIgZm9yIHRoaXMgb2JqZWN0LiBJZiB0aGlzIGhhcyBhIHJlZ2lvbiAoaW1wbGVtZW50cyBSZWdpb24pLFxuXHQgKiBpdCB3aWxsIGJlIHVzZWQgd2hlbiBubyBjb2xsaXNpb24gc2hhcGUgaXMgc3BlY2lmaWVkIChvciBpZiBjb2xsaXNpb24gc2hhcGUgaXMgbnVsbCkuXG5cdCAqIEBwYXJhbSBpc0NvbGxpZGFibGUgV2hldGhlciB0aGlzIGlzIGNvbGxpZGFibGUgb3Igbm90LiBUcnVlIGJ5IGRlZmF1bHQuXG5cdCAqIEBwYXJhbSBpc1N0YXRpYyBXaGV0aGVyIHRoaXMgaXMgc3RhdGljIG9yIG5vdC4gRmFsc2UgYnkgZGVmYXVsdFxuXHQgKi9cblx0YWRkUGh5c2ljcyhjb2xsaXNpb25TaGFwZT86IFNoYXBlLCBjb2xsaWRlck9mZnNldD86IFZlYzIsIGlzQ29sbGlkYWJsZTogYm9vbGVhbiA9IHRydWUsIGlzU3RhdGljOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcblx0XHQvLyBJbml0aWFsaXplIHRoZSBwaHlzaWNzIHZhcmlhYmxlc1xuXHRcdHRoaXMuaGFzUGh5c2ljcyA9IHRydWU7XG5cdFx0dGhpcy5tb3ZpbmcgPSBmYWxzZTtcblx0XHR0aGlzLm9uR3JvdW5kID0gZmFsc2U7XG5cdFx0dGhpcy5vbldhbGwgPSBmYWxzZTtcblx0XHR0aGlzLm9uQ2VpbGluZyA9IGZhbHNlO1xuXHRcdHRoaXMuYWN0aXZlID0gdHJ1ZTtcblx0XHR0aGlzLmlzQ29sbGlkYWJsZSA9IGlzQ29sbGlkYWJsZTtcblx0XHR0aGlzLmlzU3RhdGljID0gaXNTdGF0aWM7XG5cdFx0dGhpcy5pc1RyaWdnZXIgPSBmYWxzZTtcblx0XHR0aGlzLnRyaWdnZXJNYXNrID0gMDtcblx0XHR0aGlzLnRyaWdnZXJFbnRlcnMgPSBuZXcgQXJyYXkoMzIpO1xuXHRcdHRoaXMudHJpZ2dlckV4aXRzID0gbmV3IEFycmF5KDMyKTtcblx0XHR0aGlzLl92ZWxvY2l0eSA9IFZlYzIuWkVSTztcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IG5ldyBBQUJCKCk7XG5cdFx0dGhpcy5jb2xsaWRlZFdpdGhUaWxlbWFwID0gZmFsc2U7XG5cdFx0dGhpcy5ncm91cCA9IC0xO1x0XHRcdFx0XHQvLyBUaGUgZGVmYXVsdCBncm91cCwgY29sbGlkZXMgd2l0aCBldmVyeXRoaW5nXG5cblx0XHQvLyBTZXQgdGhlIGNvbGxpc2lvbiBzaGFwZSBpZiBwcm92aWRlZCwgb3Igc2ltcGx5IHVzZSB0aGUgdGhlIHJlZ2lvbiBpZiB0aGVyZSBpcyBvbmUuXG5cdFx0aWYoY29sbGlzaW9uU2hhcGUpe1xuXHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IGNvbGxpc2lvblNoYXBlO1xuXHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uO1xuXHRcdH0gZWxzZSBpZiAoaXNSZWdpb24odGhpcykpIHtcblx0XHRcdC8vIElmIHRoZSBnYW1lbm9kZSBoYXMgYSByZWdpb24gYW5kIG5vIG90aGVyIGlzIHNwZWNpZmllZCwgdXNlIHRoYXRcblx0XHRcdHRoaXMuY29sbGlzaW9uU2hhcGUgPSAoPGFueT50aGlzKS5ib3VuZGFyeS5jbG9uZSgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBcIk5vIGNvbGxpc2lvbiBzaGFwZSBzcGVjaWZpZWQgZm9yIHBoeXNpY3Mgb2JqZWN0LlwiXG5cdFx0fVxuXG5cdFx0Ly8gSWYgd2Ugd2VyZSBwcm92aWRlZCB3aXRoIGEgY29sbGlkZXIgb2Zmc2V0LCBzZXQgaXQuIE90aGVyd2lzZSB0aGVyZSBpcyBubyBvZmZzZXQsIHNvIHVzZSB0aGUgemVybyB2ZWN0b3Jcblx0XHRpZihjb2xsaWRlck9mZnNldCl7XG5cdFx0XHR0aGlzLmNvbGxpZGVyT2Zmc2V0ID0gY29sbGlkZXJPZmZzZXQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuY29sbGlkZXJPZmZzZXQgPSBWZWMyLlpFUk87XG5cdFx0fVxuXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aGUgc3dlcHQgcmVjdFxuXHRcdHRoaXMuc3dlcHRSZWN0ID0gdGhpcy5jb2xsaXNpb25TaGFwZS5nZXRCb3VuZGluZ1JlY3QoKTtcblxuXHRcdC8vIFJlZ2lzdGVyIHRoZSBvYmplY3Qgd2l0aCBwaHlzaWNzXG5cdFx0dGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLnJlZ2lzdGVyT2JqZWN0KHRoaXMpO1xuXHR9XG5cblx0LyoqIFJlbW92ZXMgdGhpcyBvYmplY3QgZnJvbSB0aGUgcGh5c2ljcyBzeXN0ZW0gKi9cbiAgICByZW1vdmVQaHlzaWNzKCk6IHZvaWQge1xuXHRcdC8vIFJlbW92ZSB0aGlzIGZyb20gdGhlIHBoeXNpY3MgbWFuYWdlclxuXHRcdHRoaXMuc2NlbmUuZ2V0UGh5c2ljc01hbmFnZXIoKS5kZXJlZ2lzdGVyT2JqZWN0KHRoaXMpO1xuXG5cdFx0Ly8gTnVsbGlmeSBhbGwgcGh5c2ljcyBmaWVsZHNcblx0XHR0aGlzLmhhc1BoeXNpY3MgPSBmYWxzZTtcblx0XHR0aGlzLm1vdmluZyA9IGZhbHNlO1xuXHRcdHRoaXMub25Hcm91bmQgPSBmYWxzZTtcblx0XHR0aGlzLm9uV2FsbCA9IGZhbHNlO1xuXHRcdHRoaXMub25DZWlsaW5nID0gZmFsc2U7XG5cdFx0dGhpcy5hY3RpdmUgPSBmYWxzZTtcblx0XHR0aGlzLmlzQ29sbGlkYWJsZSA9IGZhbHNlO1xuXHRcdHRoaXMuaXNTdGF0aWMgPSBmYWxzZTtcblx0XHR0aGlzLmlzVHJpZ2dlciA9IGZhbHNlO1xuXHRcdHRoaXMudHJpZ2dlck1hc2sgPSAwO1xuXHRcdHRoaXMudHJpZ2dlckVudGVycyA9IG51bGw7XG5cdFx0dGhpcy50cmlnZ2VyRXhpdHMgPSBudWxsO1xuXHRcdHRoaXMuX3ZlbG9jaXR5ID0gVmVjMi5aRVJPO1xuXHRcdHRoaXMuc3dlcHRSZWN0ID0gbnVsbDtcblx0XHR0aGlzLmNvbGxpZGVkV2l0aFRpbGVtYXAgPSBmYWxzZTtcblx0XHR0aGlzLmdyb3VwID0gLTE7XG5cdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IG51bGw7XG5cdFx0dGhpcy5jb2xsaWRlck9mZnNldCA9IFZlYzIuWkVSTztcblx0XHR0aGlzLnN3ZXB0UmVjdCA9IG51bGw7XG5cdH1cblxuXHQvKiogRGlzYWJsZXMgcGh5c2ljcyBtb3ZlbWVudCBmb3IgdGhpcyBub2RlICovXG5cdGZyZWV6ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZyb3plbiA9IHRydWU7XG5cdH1cblxuXHQvKiogUmVlbmFibGVzIHBoeXNpY3MgbW92ZW1lbnQgZm9yIHRoaXMgbm9kZSAqL1xuXHR1bmZyZWV6ZSgpOiB2b2lkIHtcblx0XHR0aGlzLmZyb3plbiA9IGZhbHNlO1xuXHR9XG5cbiAgICAvKiogUHJldmVudHMgdGhpcyBvYmplY3QgZnJvbSBwYXJ0aWNpcGF0aW5nIGluIGFsbCBjb2xsaXNpb25zIGFuZCB0cmlnZ2Vycy4gSXQgY2FuIHN0aWxsIG1vdmUuICovXG4gICAgZGlzYWJsZVBoeXNpY3MoKTogdm9pZCB7XG5cdFx0dGhpcy5hY3RpdmUgPSBmYWxzZTtcblx0fVxuXG4gICAgLyoqIEVuYWJsZXMgdGhpcyBvYmplY3QgdG8gcGFydGljaXBhdGUgaW4gY29sbGlzaW9ucyBhbmQgdHJpZ2dlcnMuIFRoaXMgaXMgb25seSBuZWNlc3NhcnkgaWYgZGlzYWJsZVBoeXNpY3Mgd2FzIGNhbGxlZCAqL1xuICAgIGVuYWJsZVBoeXNpY3MoKTogdm9pZCB7XG5cdFx0dGhpcy5hY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIGNvbGxpZGVyIGZvciB0aGlzIEdhbWVOb2RlXG5cdCAqIEBwYXJhbSBjb2xsaWRlciBUaGUgbmV3IGNvbGxpZGVyIHRvIHVzZVxuXHQgKi9cblx0c2V0Q29sbGlzaW9uU2hhcGUoY29sbGlkZXI6IFNoYXBlKTogdm9pZCB7XG5cdFx0dGhpcy5jb2xsaXNpb25TaGFwZSA9IGNvbGxpZGVyO1xuXHRcdHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyLmNvcHkodGhpcy5wb3NpdGlvbik7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0LyoqXG4gICAgICogU2V0cyB0aGlzIG9iamVjdCB0byBiZSBhIHRyaWdnZXIgZm9yIGEgc3BlY2lmaWMgZ3JvdXBcbiAgICAgKiBAcGFyYW0gZ3JvdXAgVGhlIG5hbWUgb2YgdGhlIGdyb3VwIHRoYXQgYWN0aXZhdGVzIHRoZSB0cmlnZ2VyXG4gICAgICogQHBhcmFtIG9uRW50ZXIgVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQgd2hlbiB0aGlzIHRyaWdnZXIgaXMgYWN0aXZhdGVkXG4gICAgICogQHBhcmFtIG9uRXhpdCBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZCB3aGVuIHRoaXMgdHJpZ2dlciBzdG9wcyBiZWluZyBhY3RpdmF0ZWRcbiAgICAgKi9cbiAgICBzZXRUcmlnZ2VyKGdyb3VwOiBzdHJpbmcsIG9uRW50ZXI6IHN0cmluZywgb25FeGl0OiBzdHJpbmcpOiB2b2lkIHtcblx0XHQvLyBNYWtlIHRoaXMgb2JqZWN0IGEgdHJpZ2dlclxuXHRcdHRoaXMuaXNUcmlnZ2VyID0gdHJ1ZTtcblxuXHRcdC8vIEdldCB0aGUgbnVtYmVyIG9mIHRoZSBwaHlzaWNzIGxheWVyXG5cdFx0bGV0IGxheWVyTnVtYmVyID0gdGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLmdldEdyb3VwTnVtYmVyKGdyb3VwKTtcblxuXHRcdGlmKGxheWVyTnVtYmVyID09PSAwKXtcblx0XHRcdGNvbnNvbGUud2FybihgVHJpZ2dlciBmb3IgR2FtZU5vZGUgJHt0aGlzLmlkfSBub3Qgc2V0IC0gZ3JvdXAgXCIke2dyb3VwfVwiIHdhcyBub3QgcmVjb2duaXplZCBieSB0aGUgcGh5c2ljcyBtYW5hZ2VyLmApO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB0aGlzIHRvIHRoZSB0cmlnZ2VyIG1hc2tcblx0XHR0aGlzLnRyaWdnZXJNYXNrIHw9IGxheWVyTnVtYmVyO1xuXG5cdFx0Ly8gTGF5ZXIgbnVtYmVycyBhcmUgYml0cywgc28gZ2V0IHdoaWNoIGJpdCBpdCBpc1xuXHRcdGxldCBpbmRleCA9IE1hdGgubG9nMihsYXllck51bWJlcik7XG5cblx0XHQvLyBTZXQgdGhlIGV2ZW50IG5hbWVzXG5cdFx0dGhpcy50cmlnZ2VyRW50ZXJzW2luZGV4XSA9IG9uRW50ZXI7XG5cdFx0dGhpcy50cmlnZ2VyRXhpdHNbaW5kZXhdID0gb25FeGl0O1xuXHR9O1xuXG5cdC8vIEBpbXBsZW1lbnRlZFxuXHQvKipcblx0ICogQHBhcmFtIGdyb3VwIFRoZSBwaHlzaWNzIGdyb3VwIHRoaXMgbm9kZSBzaG91bGQgYmVsb25nIHRvXG5cdCAqL1xuXHRzZXRHcm91cChncm91cDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLnNldEdyb3VwKHRoaXMsIGdyb3VwKTtcblx0fVxuXG5cdC8vIEBpbXBsZW1lbmVkXG5cdGdldExhc3RWZWxvY2l0eSgpOiBWZWMyIHtcblx0XHRyZXR1cm4gdGhpcy5fdmVsb2NpdHk7XG5cdH1cblxuXHQvKi0tLS0tLS0tLS0gQUNUT1IgLS0tLS0tLS0tLSovXG5cdGdldCBhaSgpOiBBSSB8IEdvYXBBSSB7XG5cdFx0cmV0dXJuIHRoaXMuX2FpO1xuXHR9XG5cblx0c2V0IGFpKGFpOiBBSSB8IEdvYXBBSSkge1xuXHRcdGlmKCF0aGlzLl9haSl7XG5cdFx0XHQvLyBJZiB3ZSBoYXZlbid0IGJlZW4gcHJldmlvdXNseSBoYWQgYW4gYWksIHJlZ2lzdGVyIHVzIHdpdGggdGhlIGFpIG1hbmFnZXJcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVnaXN0ZXJBY3Rvcih0aGlzKTtcblx0XHR9XG5cblx0XHR0aGlzLl9haSA9IGFpO1xuXHRcdHRoaXMuYWlBY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdGFkZEFJPFQgZXh0ZW5kcyBBSSB8IEdvYXBBST4oYWk6IHN0cmluZyB8IChuZXcgKCkgPT4gVCksIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCB0eXBlPzogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYoIXRoaXMuX2FpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0QUlNYW5hZ2VyKCkucmVnaXN0ZXJBY3Rvcih0aGlzKTtcblx0XHR9XG5cblx0XHRpZih0eXBlb2YgYWkgPT09IFwic3RyaW5nXCIpe1xuXHRcdFx0dGhpcy5fYWkgPSB0aGlzLnNjZW5lLmdldEFJTWFuYWdlcigpLmdlbmVyYXRlQUkoYWkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9haSA9IG5ldyBhaSgpO1xuXHRcdH1cblxuXHRcdC8vIFF1ZXN0aW9uLCBob3cgbXVjaCBkbyB3ZSB3YW50IGRpZmZlcmVudCB0eXBlIG9mIEFJIHRvIGJlIGhhbmRsZWQgdGhlIHNhbWUsIGkuZS4gc2hvdWxkIEdvYXBBSSBhbmQgQUkgc2ltaWxhciBtZXRob2RzIGFuZCBzaWduYXR1cmVzIGZvciB0aGUgc2FrZSBvZiB1bml0eVxuXHRcdHRoaXMuX2FpLmluaXRpYWxpemVBSSh0aGlzLCBvcHRpb25zKTtcblxuXHRcdHRoaXMuYWlBY3RpdmUgPSB0cnVlO1xuXHR9XG5cblx0Ly8gQGltcGxlbWVudGVkXG5cdHNldEFJQWN0aXZlKGFjdGl2ZTogYm9vbGVhbiwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdHRoaXMuYWlBY3RpdmUgPSBhY3RpdmU7XG5cdFx0aWYodGhpcy5haUFjdGl2ZSl7XG5cdFx0XHR0aGlzLmFpLmFjdGl2YXRlKG9wdGlvbnMpO1xuXHRcdH1cblx0fVxuXG5cdC8qLS0tLS0tLS0tLSBUV0VFTkFCTEUgUFJPUEVSVElFUyAtLS0tLS0tLS0tKi9cblx0c2V0IHBvc2l0aW9uWCh2YWx1ZTogbnVtYmVyKSB7XG5cdFx0dGhpcy5wb3NpdGlvbi54ID0gdmFsdWU7XG5cdH1cblxuXHRzZXQgcG9zaXRpb25ZKHZhbHVlOiBudW1iZXIpIHtcblx0XHR0aGlzLnBvc2l0aW9uLnkgPSB2YWx1ZTtcblx0fVxuXG5cdGFic3RyYWN0IHNldCBzY2FsZVgodmFsdWU6IG51bWJlcik7XG5cblx0YWJzdHJhY3Qgc2V0IHNjYWxlWSh2YWx1ZTogbnVtYmVyKTtcblxuXHQvKi0tLS0tLS0tLS0gR0FNRSBOT0RFIC0tLS0tLS0tLS0qL1xuXHQvKipcblx0ICogU2V0cyB0aGUgc2NlbmUgZm9yIHRoaXMgb2JqZWN0LlxuXHQgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRoaXMgb2JqZWN0IGJlbG9uZ3MgdG8uXG5cdCAqL1xuXHRzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcblx0XHR0aGlzLnNjZW5lID0gc2NlbmU7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgc2NlbmUgdGhpcyBvYmplY3QgaXMgaW4uIFxuXHQgKiBAcmV0dXJucyBUaGUgc2NlbmUgdGhpcyBvYmplY3QgYmVsb25ncyB0b1xuXHQqL1xuXHRnZXRTY2VuZSgpOiBTY2VuZSB7XG5cdFx0cmV0dXJuIHRoaXMuc2NlbmU7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgbGF5ZXIgb2YgdGhpcyBvYmplY3QuXG5cdCAqIEBwYXJhbSBsYXllciBUaGUgbGF5ZXIgdGhpcyBvYmplY3Qgd2lsbCBiZSBvbi5cblx0ICovXG5cdHNldExheWVyKGxheWVyOiBMYXllcik6IHZvaWQge1xuXHRcdHRoaXMubGF5ZXIgPSBsYXllcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBsYXllciB0aGlzIG9iamVjdCBpcyBvbi5cblx0ICogQHJldHVybnMgVGhpcyBsYXllciB0aGlzIG9iamVjdCBpcyBvbi5cblx0Ki9cblx0Z2V0TGF5ZXIoKTogTGF5ZXIge1xuXHRcdHJldHVybiB0aGlzLmxheWVyO1xuXHR9XG5cblx0LyoqIENhbGxlZCBpZiB0aGUgcG9zaXRpb24gdmVjdG9yIGlzIG1vZGlmaWVkIG9yIHJlcGxhY2VkICovXG5cdHByb3RlY3RlZCBwb3NpdGlvbkNoYW5nZWQoKTogdm9pZCB7XG5cdFx0aWYodGhpcy5jb2xsaXNpb25TaGFwZSl7XG5cdFx0XHRpZih0aGlzLmNvbGxpZGVyT2Zmc2V0KXtcblx0XHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uLmNsb25lKCkuYWRkKHRoaXMuY29sbGlkZXJPZmZzZXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIgPSB0aGlzLnBvc2l0aW9uLmNsb25lKCk7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHR9XG5cdH07XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgdGhpcyBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gZGVsdGFUIFRoZSB0aW1lc3RlcCBvZiB0aGUgdXBkYXRlLlxuXHQgKi9cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0Ly8gRGVmZXIgZXZlbnQgaGFuZGxpbmcgdG8gQUkuXG5cdFx0d2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG5cdFx0XHR0aGlzLl9haS5oYW5kbGVFdmVudCh0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpKTtcblx0XHR9XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0ZGVidWdSZW5kZXIoKTogdm9pZCB7XG5cdFx0Ly8gRHJhdyB0aGUgcG9zaXRpb24gb2YgdGhpcyBHYW1lTm9kZVxuXHRcdERlYnVnLmRyYXdQb2ludCh0aGlzLnJlbGF0aXZlUG9zaXRpb24sIENvbG9yLkJMVUUpO1xuXG5cdFx0Ly8gSWYgdmVsb2NpdHkgaXMgbm90IHplcm8sIGRyYXcgYSB2ZWN0b3IgZm9yIGl0XG5cdFx0aWYodGhpcy5fdmVsb2NpdHkgJiYgIXRoaXMuX3ZlbG9jaXR5LmlzWmVybygpKXtcblx0XHRcdERlYnVnLmRyYXdSYXkodGhpcy5yZWxhdGl2ZVBvc2l0aW9uLCB0aGlzLl92ZWxvY2l0eS5jbG9uZSgpLnNjYWxlVG8oMjApLmFkZCh0aGlzLnJlbGF0aXZlUG9zaXRpb24pLCBDb2xvci5CTFVFKTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGlzIGhhcyBhIGNvbGxpZGVyLCBkcmF3IGl0XG5cdFx0aWYodGhpcy5jb2xsaXNpb25TaGFwZSl7XG5cdFx0XHRsZXQgY29sb3IgPSB0aGlzLmlzQ29sbGlkaW5nID8gQ29sb3IuUkVEIDogQ29sb3IuR1JFRU47XG5cblx0XHRcdGlmKHRoaXMuaXNUcmlnZ2VyKXtcblx0XHRcdFx0Y29sb3IgPSBDb2xvci5NQUdFTlRBO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRjb2xvci5hID0gMC4yO1xuXG5cdFx0XHRpZih0aGlzLmNvbGxpc2lvblNoYXBlIGluc3RhbmNlb2YgQUFCQil7XG5cdFx0XHRcdERlYnVnLmRyYXdCb3godGhpcy5pblJlbGF0aXZlQ29vcmRpbmF0ZXModGhpcy5jb2xsaXNpb25TaGFwZS5jZW50ZXIpLCB0aGlzLmNvbGxpc2lvblNoYXBlLmhhbGZTaXplLnNjYWxlZCh0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpKSwgdHJ1ZSwgY29sb3IpO1xuXHRcdFx0fSBlbHNlIGlmKHRoaXMuY29sbGlzaW9uU2hhcGUgaW5zdGFuY2VvZiBDaXJjbGUpe1xuXHRcdFx0XHREZWJ1Zy5kcmF3Q2lyY2xlKHRoaXMuaW5SZWxhdGl2ZUNvb3JkaW5hdGVzKHRoaXMuY29sbGlzaW9uU2hhcGUuY2VudGVyKSwgdGhpcy5jb2xsaXNpb25TaGFwZS5odyp0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpLCB0cnVlLCBjb2xvcik7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBlbnVtIFR3ZWVuYWJsZVByb3BlcnRpZXN7XG5cdHBvc1ggPSBcInBvc2l0aW9uWFwiLFxuXHRwb3NZID0gXCJwb3NpdGlvbllcIixcblx0c2NhbGVYID0gXCJzY2FsZVhcIixcblx0c2NhbGVZID0gXCJzY2FsZVlcIixcblx0cm90YXRpb24gPSBcInJvdGF0aW9uXCIsXG5cdGFscGhhID0gXCJhbHBoYVwiXG59IiwiaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4vQ2FudmFzTm9kZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhIGdhbWUgb2JqZWN0IHRoYXQgZG9lc24ndCByZWx5IG9uIGFueSByZXNvdXJjZXMgdG8gcmVuZGVyIC0gaXQgaXMgZHJhd24gdG8gdGhlIHNjcmVlbiBieSB0aGUgY2FudmFzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIEdyYXBoaWMgZXh0ZW5kcyBDYW52YXNOb2RlIHtcbiAgICAvKiogVGhlIGNvbG9yIG9mIHRoZSBHcmFwaGljICovXG4gICAgY29sb3I6IENvbG9yO1xuXG4gICAgY29uc3RydWN0b3IoKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5jb2xvciA9IENvbG9yLlJFRDtcbiAgICB9XG5cbiAgICBnZXQgYWxwaGEoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5jb2xvci5hO1xuXHR9XG5cblx0c2V0IGFscGhhKGE6IG51bWJlcikge1xuXHRcdHRoaXMuY29sb3IuYSA9IGE7XG5cdH1cblxuICAgIC8vIEBkZXByZWNhdGVkXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY29sb3Igb2YgdGhlIEdyYXBoaWMuIERFUFJFQ0FURURcbiAgICAgKiBAcGFyYW0gY29sb3IgVGhlIG5ldyBjb2xvciBvZiB0aGUgR3JhcGhpYy5cbiAgICAgKi9cbiAgICBzZXRDb2xvcihjb2xvcjogQ29sb3Ipe1xuICAgICAgICB0aGlzLmNvbG9yID0gY29sb3I7XG4gICAgfVxuXG4gICAgc2V0IGNvbG9yUihyOiBudW1iZXIpe1xuICAgICAgICB0aGlzLmNvbG9yLnIgPSByO1xuICAgIH1cblxuICAgIGdldCBjb2xvclIoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sb3IucjtcbiAgICB9XG5cbiAgICBzZXQgY29sb3JHKGc6IG51bWJlcil7XG4gICAgICAgIHRoaXMuY29sb3IuZyA9IGc7XG4gICAgfVxuXG4gICAgZ2V0IGNvbG9yRygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xvci5nO1xuICAgIH1cblxuICAgIHNldCBjb2xvckIoYjogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5jb2xvci5iID0gYjtcbiAgICB9XG5cbiAgICBnZXQgY29sb3JCKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbG9yLmI7XG4gICAgfVxufSIsImV4cG9ydCBlbnVtIEdyYXBoaWNUeXBlIHtcblx0UE9JTlQgPSBcIlBPSU5UXCIsXG5cdFJFQ1QgPSBcIlJFQ1RcIixcblx0TElORSA9IFwiTElORVwiLFxuXHRQQVJUSUNMRSA9IFwiUEFSVElDTEVcIlxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL0dyYXBoaWNcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGluZSBleHRlbmRzIEdyYXBoaWMge1xuICAgIHByb3RlY3RlZCBfZW5kOiBWZWMyO1xuICAgIHRoaWNrbmVzczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3Ioc3RhcnQ6IFZlYzIsIGVuZDogVmVjMil7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuc3RhcnQgPSBzdGFydDtcbiAgICAgICAgdGhpcy5lbmQgPSBlbmQ7XG4gICAgICAgIHRoaXMudGhpY2tuZXNzID0gMjtcblxuICAgICAgICAvLyBEb2VzIHRoaXMgcmVhbGx5IGhhdmUgYSBtZWFuaW5nIGZvciBsaW5lcz9cbiAgICAgICAgdGhpcy5zaXplLnNldCg1LCA1KTtcbiAgICB9XG5cbiAgICBzZXQgc3RhcnQocG9zOiBWZWMyKXtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvcztcbiAgICB9XG5cbiAgICBnZXQgc3RhcnQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnBvc2l0aW9uO1xuICAgIH1cblxuICAgIHNldCBlbmQocG9zOiBWZWMyKXtcbiAgICAgICAgdGhpcy5fZW5kID0gcG9zO1xuICAgIH1cblxuICAgIGdldCBlbmQoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbmQ7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFBvaW50IGZyb20gXCIuL1BvaW50XCI7XG5cbi8qKlxuICogLSBQb3NpdGlvbiBYXG4tIFZlbG9jaXR5IChzcGVlZCBhbmQgZGlyZWN0aW9uKSBYXG4tIENvbG9yIFhcbi0gTGlmZXRpbWUgXG4tIEFnZSBjYW4gYmUgaGFuZGxlZCBhcyBsaWZldGltZVxuLSBTaGFwZSBYXG4tIFNpemUgWFxuLSBUcmFuc3BhcmVuY3kgWFxuICovXG5cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFydGljbGUgZXh0ZW5kcyBQb2ludCB7XG4gICAgYWdlOiBudW1iZXI7XG5cbiAgICBpblVzZTogYm9vbGVhbjtcblxuICAgIHZlbDogVmVjMjtcblxuICAgIG1hc3M6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCBzaXplOiBWZWMyLCBtYXNzOiBudW1iZXIpIHtcbiAgICAgICAgLy8gQXJlIHdlIG1ha2luZyB0aGlzIGEgY2lyY2xlP1xuICAgICAgICBzdXBlcihwb3NpdGlvbik7XG4gICAgICAgIHRoaXMuaW5Vc2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5tYXNzID0gbWFzcztcbiAgICB9XG5cbiAgICBzZXRQYXJ0aWNsZUFjdGl2ZShsaWZldGltZTogbnVtYmVyLCBwb3NpdGlvbjogVmVjMikge1xuICAgICAgICB0aGlzLmFnZSA9IGxpZmV0aW1lO1xuICAgICAgICB0aGlzLmluVXNlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xuICAgIH1cblxuICAgIGRlY3JlbWVudEFnZShkZWNheTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuYWdlIC09IGRlY2F5O1xuICAgIH1cblxuICAgIHNldFBhcnRpY2xlSW5hY3RpdmUoKXtcbiAgICAgICAgdGhpcy5pblVzZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBzZXQgdmVsWSh5OiBudW1iZXIpe1xuICAgICAgICB0aGlzLnZlbC55ID0geTtcbiAgICB9XG5cbiAgICBnZXQgdmVsWSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy52ZWwueTtcbiAgICB9XG5cblxufSIsImltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9HcmFwaGljXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcblxuLyoqIEEgYmFzaWMgcG9pbnQgdG8gYmUgZHJhd24gb24gdGhlIHNjcmVlbi4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50IGV4dGVuZHMgR3JhcGhpYyB7XG5cbiAgICBjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMikge1xuICAgICAgICAvLyBBcmUgd2UgbWFraW5nIHRoaXMgYSBjaXJjbGU/XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgICAgICAgdGhpcy5zaXplLnNldCg1LCA1KTtcbiAgICB9XG59IiwiaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL0dyYXBoaWNcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuXG4vKiogQSBiYXNpYyByZWN0YW5nbGUgdG8gYmUgZHJhd24gb24gdGhlIHNjcmVlbi4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlY3QgZXh0ZW5kcyBHcmFwaGljIHtcblxuICAgIC8qKiBUaGUgYm9yZGVyIGNvbG9yIG9mIHRoZSBSZWN0ICovXG4gICAgYm9yZGVyQ29sb3I6IENvbG9yO1xuXG4gICAgLyoqIFRoZSB3aWR0aCBvZiB0aGUgYm9yZGVyICovXG4gICAgYm9yZGVyV2lkdGg6IG51bWJlcjtcblxuICAgIGZpbGxXaWR0aDogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IocG9zaXRpb246IFZlYzIsIHNpemU6IFZlYzIpe1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG4gICAgICAgIHRoaXMuc2l6ZSA9IHNpemU7XG4gICAgICAgIHRoaXMuYm9yZGVyQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgdGhpcy5ib3JkZXJXaWR0aCA9IDA7XG4gICAgICAgIHRoaXMuZmlsbFdpZHRoID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBib3JkZXIgY29sb3Igb2YgdGhpcyByZWN0YW5nbGVcbiAgICAgKiBAcGFyYW0gY29sb3IgVGhlIGJvcmRlciBjb2xvclxuICAgICAqL1xuICAgIHNldEJvcmRlckNvbG9yKGNvbG9yOiBDb2xvcik6IHZvaWQge1xuICAgICAgICB0aGlzLmJvcmRlckNvbG9yID0gY29sb3I7XG4gICAgfVxuXG4gICAgLy8gQGRlcHJlY2F0ZWRcbiAgICBnZXRCb3JkZXJDb2xvcigpOiBDb2xvciB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvcmRlckNvbG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGJvcmRlciB3aWR0aCBvZiB0aGlzIHJlY3RhbmdsZVxuICAgICAqIEBwYXJhbSB3aWR0aCBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZSBpbiBwaXhlbHNcbiAgICAgKi9cbiAgICBzZXRCb3JkZXJXaWR0aCh3aWR0aDogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5ib3JkZXJXaWR0aCA9IHdpZHRoO1xuICAgIH1cblxuICAgIGdldEJvcmRlcldpZHRoKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvcmRlcldpZHRoO1xuICAgIH1cbn0iLCJpbXBvcnQgU3ByaXRlIGZyb20gXCIuL1Nwcml0ZVwiO1xuaW1wb3J0IEFuaW1hdGlvbk1hbmFnZXIgZnJvbSBcIi4uLy4uL1JlbmRlcmluZy9BbmltYXRpb25zL0FuaW1hdGlvbk1hbmFnZXJcIjtcbmltcG9ydCBTcHJpdGVzaGVldCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1Nwcml0ZXNoZWV0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcblxuLyoqIEFuIHNwcml0ZSB3aXRoIHNwZWNpZmllZCBhbmltYXRpb24gZnJhbWVzLiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQW5pbWF0ZWRTcHJpdGUgZXh0ZW5kcyBTcHJpdGUge1xuICAgIC8qKiBUaGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhpcyBzcHJpdGUgc2hlZXQgKi9cbiAgICBwcm90ZWN0ZWQgbnVtQ29sczogbnVtYmVyO1xuXG4gICAgZ2V0IGNvbHMoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubnVtQ29scztcbiAgICB9XG5cbiAgICAvKiogVGhlIG51bWJlciBvZiByb3dzIGluIHRoaXMgc3ByaXRlIHNoZWV0ICovXG4gICAgcHJvdGVjdGVkIG51bVJvd3M6IG51bWJlcjtcblxuICAgIGdldCByb3dzKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLm51bVJvd3M7XG4gICAgfVxuXG4gICAgLyoqIFRoZSBhbmltYXRpb25NYW5hZ2VyIGZvciB0aGlzIHNwcml0ZSAqL1xuICAgIGFuaW1hdGlvbjogQW5pbWF0aW9uTWFuYWdlcjtcblxuICAgIGNvbnN0cnVjdG9yKHNwcml0ZXNoZWV0OiBTcHJpdGVzaGVldCl7XG4gICAgICAgIHN1cGVyKHNwcml0ZXNoZWV0Lm5hbWUpO1xuICAgICAgICB0aGlzLm51bUNvbHMgPSBzcHJpdGVzaGVldC5jb2x1bW5zO1xuICAgICAgICB0aGlzLm51bVJvd3MgPSBzcHJpdGVzaGVldC5yb3dzO1xuXG4gICAgICAgIC8vIFNldCB0aGUgc2l6ZSBvZiB0aGUgc3ByaXRlIHRvIHRoZSBzcHJpdGUgc2l6ZSBzcGVjaWZpZWQgYnkgdGhlIHNwcml0ZXNoZWV0XG4gICAgICAgIHRoaXMuc2l6ZS5zZXQoc3ByaXRlc2hlZXQuc3ByaXRlV2lkdGgsIHNwcml0ZXNoZWV0LnNwcml0ZUhlaWdodCk7XG5cbiAgICAgICAgdGhpcy5hbmltYXRpb24gPSBuZXcgQW5pbWF0aW9uTWFuYWdlcih0aGlzKTtcblxuICAgICAgICAvLyBBZGQgdGhlIGFuaW1hdGlvbnMgdG8gdGhlIGFuaW1hdGVkIHNwcml0ZVxuICAgICAgICBmb3IobGV0IGFuaW1hdGlvbiBvZiBzcHJpdGVzaGVldC5hbmltYXRpb25zKXtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uLmFkZChhbmltYXRpb24ubmFtZSwgYW5pbWF0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGltYWdlIG9mZnNldCBmb3IgdGhlIGN1cnJlbnQgaW5kZXggb2YgYW5pbWF0aW9uXG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB3ZSdyZSBhdCBpbiB0aGUgYW5pbWF0aW9uXG4gICAgICogQHJldHVybnMgQSBWZWMyIGNvbnRhaW5pbmcgdGhlIGltYWdlIG9mZnNldFxuICAgICAqL1xuICAgIGdldEFuaW1hdGlvbk9mZnNldChpbmRleDogbnVtYmVyKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMigoaW5kZXggJSB0aGlzLm51bUNvbHMpICogdGhpcy5zaXplLngsIE1hdGguZmxvb3IoaW5kZXggLyB0aGlzLm51bUNvbHMpICogdGhpcy5zaXplLnkpO1xuICAgIH1cbn0iLCJpbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGEgc3ByaXRlIC0gYW4gaW4tZ2FtZSBpbWFnZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcHJpdGUgZXh0ZW5kcyBDYW52YXNOb2RlIHtcbiAgICAvKiogVGhlIGlkIG9mIHRoZSBpbWFnZSBmcm9tIHRoZSByZXNvdXJjZU1hbmFnZXIgKi9cbiAgICBpbWFnZUlkOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBvZmZzZXQgb2YgdGhlIHNwcml0ZSBpbiBhbiBhdGxhcyBpbWFnZSAqL1xuICAgIGltYWdlT2Zmc2V0OiBWZWMyO1xuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgeC1heGlzIHNob3VsZCBiZSBpbnZlcnRlZCBvbiByZW5kZXIgKi9cbiAgICBpbnZlcnRYOiBib29sZWFuO1xuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgeS1heGlzIHNob3VsZCBiZSBpbnZlcnRlZCBvbiByZW5kZXIgKi9cbiAgICBpbnZlcnRZOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoaW1hZ2VJZDogc3RyaW5nKXtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5pbWFnZUlkID0gaW1hZ2VJZDtcbiAgICAgICAgbGV0IGltYWdlID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCkuZ2V0SW1hZ2UodGhpcy5pbWFnZUlkKTtcbiAgICAgICAgdGhpcy5zaXplID0gbmV3IFZlYzIoaW1hZ2Uud2lkdGgsIGltYWdlLmhlaWdodCk7XG4gICAgICAgIHRoaXMuaW1hZ2VPZmZzZXQgPSBWZWMyLlpFUk87XG4gICAgICAgIHRoaXMuaW52ZXJ0WCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmludmVydFkgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBvZmZzZXQgb2YgdGhlIHNwcml0ZSBmcm9tICgwLCAwKSBpbiB0aGUgaW1hZ2UncyBjb29yZGluYXRlc1xuICAgICAqIEBwYXJhbSBvZmZzZXQgVGhlIG9mZnNldCBvZiB0aGUgc3ByaXRlIGZyb20gKDAsIDApIGluIGltYWdlIGNvb3JkaW5hdGVzXG4gICAgICovXG4gICAgc2V0SW1hZ2VPZmZzZXQob2Zmc2V0OiBWZWMyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW1hZ2VPZmZzZXQgPSBvZmZzZXQ7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFRpbGVzZXQgZnJvbSBcIi4uL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlc2V0XCI7XG5pbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhLCBUaWxlZExheWVyRGF0YSB9IGZyb20gXCIuLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCJcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuL0NhbnZhc05vZGVcIjtcbmltcG9ydCBQaHlzaWNzTWFuYWdlciBmcm9tIFwiLi4vUGh5c2ljcy9QaHlzaWNzTWFuYWdlclwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhIHRpbGVtYXAgLSB0aGlzIGNhbiBjb25zaXN0IG9mIGEgY29tYmluYXRpb24gb2YgdGlsZXNldHMgaW4gb25lIGxheWVyXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFRpbGVtYXAgZXh0ZW5kcyBDYW52YXNOb2RlIHtcbiAgICAvKiogQW4gYXJyYXkgb2YgdGhlIHRpbGVzZXRzIHRoYXQgdGhpcyB0aWxlbWFwIHVzZXMgKi9cbiAgICBwcm90ZWN0ZWQgdGlsZXNldHM6IEFycmF5PFRpbGVzZXQ+O1xuXG4gICAgLyoqIFRoZSBzaXplIG9mIGEgdGlsZSBpbiB0aGlzIHRpbGVtYXAgKi9cbiAgICBwcm90ZWN0ZWQgdGlsZVNpemU6IFZlYzI7XG5cbiAgICAvKiogQW4gYXJyYXkgb2YgdGlsZSBkYXRhICovXG4gICAgcHJvdGVjdGVkIGRhdGE6IEFycmF5PG51bWJlcj47XG5cbiAgICAvKiogQW4gYXJyYXkgb2YgdGlsZSBjb2xsaXNpb24gZGF0YSAqL1xuICAgIHByb3RlY3RlZCBjb2xsaXNpb25NYXA6IEFycmF5PGJvb2xlYW4+O1xuXG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoZSB0aWxlbWFwICovXG4gICAgbmFtZTogc3RyaW5nO1xuXG4gICAgLy8gVE9ETzogTWFrZSB0aGlzIG5vIGxvbmdlciBiZSBzcGVjaWZpYyB0byBUaWxlZFxuICAgIGNvbnN0cnVjdG9yKHRpbGVtYXBEYXRhOiBUaWxlZFRpbGVtYXBEYXRhLCBsYXllcjogVGlsZWRMYXllckRhdGEsIHRpbGVzZXRzOiBBcnJheTxUaWxlc2V0Piwgc2NhbGU6IFZlYzIpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy50aWxlc2V0cyA9IHRpbGVzZXRzO1xuICAgICAgICB0aGlzLnRpbGVTaXplID0gbmV3IFZlYzIoMCwgMCk7XG4gICAgICAgIHRoaXMubmFtZSA9IGxheWVyLm5hbWU7XG5cbiAgICAgICAgbGV0IHRpbGVjb3VudCA9IDA7XG4gICAgICAgIGZvcihsZXQgdGlsZXNldCBvZiB0aWxlc2V0cyl7XG4gICAgICAgICAgICB0aWxlY291bnQgKz0gdGlsZXNldC5nZXRUaWxlQ291bnQoKSArIDE7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNvbGxpc2lvbk1hcCA9IG5ldyBBcnJheSh0aWxlY291bnQpO1xuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2xsaXNpb25NYXAubGVuZ3RoOyBpKyspe1xuICAgICAgICAgICAgdGhpcy5jb2xsaXNpb25NYXBbaV0gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZmVyIHBhcnNpbmcgb2YgdGhlIGRhdGEgdG8gY2hpbGQgY2xhc3NlcyAtIHRoaXMgYWxsb3dzIGZvciBpc29tZXRyaWMgdnMuIG9ydGhvZ3JhcGhpYyB0aWxlbWFwcyBhbmQgaGFuZGxpbmcgb2YgVGlsZWQgZGF0YSBvciBvdGhlciBkYXRhXG4gICAgICAgIHRoaXMucGFyc2VUaWxlbWFwRGF0YSh0aWxlbWFwRGF0YSwgbGF5ZXIpO1xuICAgICAgICB0aGlzLnNjYWxlLnNldChzY2FsZS54LCBzY2FsZS55KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIHRoZSB0aWxlc2V0cyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0aWxlbWFwXG4gICAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgYWxsIG9mIHRoZSB0aWxlc2V0cyBhc3NvY2FpdGVkIHdpdGggdGhpcyB0aWxlbWFwLlxuICAgICAqL1xuICAgIGdldFRpbGVzZXRzKCk6IFRpbGVzZXRbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbGVzZXRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpemUgb2YgdGlsZXMgaW4gdGhpcyB0aWxlbWFwIGFzIHRoZXkgYXBwZWFyIGluIHRoZSBnYW1lIHdvcmxkIGFmdGVyIHNjYWxpbmdcbiAgICAgKiBAcmV0dXJucyBBIHZlY3RvciBjb250YWluaW5nIHRoZSBzaXplIG9mIHRpbGVzIGluIHRoaXMgdGlsZW1hcCBhcyB0aGV5IGFwcGVhciBpbiB0aGUgZ2FtZSB3b3JsZCBhZnRlciBzY2FsaW5nLlxuICAgICAqL1xuICAgIGdldFRpbGVTaXplKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlU2l6ZS5zY2FsZWQodGhpcy5zY2FsZS54LCB0aGlzLnNjYWxlLnkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHRpbGUgc2l6ZSB0YWtpbmcgem9vbSBpbnRvIGFjY291bnRcbiAgICAgKiBAcmV0dXJucyBUaGUgdGlsZSBzaXplIHdpdGggem9vbVxuICAgICovXG4gICAgZ2V0VGlsZVNpemVXaXRoWm9vbSgpOiBWZWMyIHtcbiAgICAgICAgbGV0IHpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmdldFRpbGVTaXplKCkuc2NhbGUoem9vbSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyB0aGlzIHRpbGVtYXAgdG8gdGhlIHBoeXNpY3Mgc3lzdGVtXG4gICAgKi9cbiAgICBhZGRQaHlzaWNzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmhhc1BoeXNpY3MgPSB0cnVlO1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IHRydWU7XG4gICAgICAgIHRoaXMuZ3JvdXAgPSAtMTtcbiAgICAgICAgdGhpcy5zY2VuZS5nZXRQaHlzaWNzTWFuYWdlcigpLnJlZ2lzdGVyVGlsZW1hcCh0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB2YWx1ZSBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uXG4gICAgICogQHBhcmFtIHdvcmxkQ29vcmRzIFRoZSBwb3NpdGlvbiBpbiB3b3JsZCBjb29yZGluYXRlc1xuICAgICAqIEByZXR1cm5zIEEgbnVtYmVyIHRoYXQgcmVwcmVzZW50cyB0aGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIHdvcmxkIHBvc2l0aW9uLlxuICAgICAqL1xuICAgIGFic3RyYWN0IGdldFRpbGVBdFdvcmxkUG9zaXRpb24od29ybGRDb29yZHM6IFZlYzIpOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB3b3JsZCBwb3NpdGlvbiBvZiB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlIGluIHRoZSB0aWxlRGF0YSBhcnJheVxuICAgICAqIEByZXR1cm5zIFRoZSB3b3JsZCBwb3NpdGlvbiBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICovXG4gICAgYWJzdHJhY3QgZ2V0VGlsZVdvcmxkUG9zaXRpb24oaW5kZXg6IG51bWJlcik6IFZlYzI7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB2YWx1ZSBvZiB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZSBpbiB0aGUgdGlsZURhdGEgYXJyYXlcbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVEYXRhIGFycmF5XG4gICAgICovXG4gICAgYWJzdHJhY3QgZ2V0VGlsZShpbmRleDogbnVtYmVyKTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdGlsZSBhdCB0aGUgc3BlY2lmaWVkIGluZGV4XG4gICAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgdGlsZVxuICAgICAqIEBwYXJhbSB0eXBlIFRoZSBuZXcgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIGFic3RyYWN0IHNldFRpbGUoaW5kZXg6IG51bWJlciwgdHlwZTogbnVtYmVyKTogdm9pZDtcblxuICAgIC8vIFRPRE86IFRoaXMgc2hvdWxkbid0IHVzZSB0aWxlZCBkYXRhIHNwZWNpZmljYWxseSAtIGl0IHNob3VsZCBiZSBtb3JlIGdlbmVyYWxcbiAgICAvKipcbiAgICAgKiBTZXRzIHVwIHRoZSB0aWxlc2V0IHVzaW5nIHRoZSBkYXRhIGxvYWRlZCBmcm9tIGZpbGVcbiAgICAgKiBAcGFyYW0gdGlsZW1hcERhdGEgVGhlIHRpbGVtYXAgZGF0YSBmcm9tIGZpbGVcbiAgICAgKiBAcGFyYW0gbGF5ZXIgVGhlIGxheWVyIGRhdGEgZnJvbSBmaWxlXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHBhcnNlVGlsZW1hcERhdGEodGlsZW1hcERhdGE6IFRpbGVkVGlsZW1hcERhdGEsIGxheWVyOiBUaWxlZExheWVyRGF0YSk6IHZvaWQ7XG59IiwiaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL1RpbGVtYXBcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgVGlsZWRUaWxlbWFwRGF0YSwgVGlsZWRMYXllckRhdGEgfSBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9VdGlscy9Db2xvclwiO1xuXG4vKipcbiAqIFRoZSByZXByZXNlbnRhdGlvbiBvZiBhbiBvcnRob2dvbmFsIHRpbGVtYXAgLSBpLmUuIGEgdG9wIGRvd24gb3IgcGxhdGZvcm1lciB0aWxlbWFwXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE9ydGhvZ29uYWxUaWxlbWFwIGV4dGVuZHMgVGlsZW1hcCB7XG4gICAgLyoqIFRoZSBudW1iZXIgb2YgY29sdW1ucyBpbiB0aGUgdGlsZW1hcCAqL1xuICAgIHByb3RlY3RlZCBudW1Db2xzOiBudW1iZXI7XG4gICAgLyoqIFRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGUgdGlsZW1hcCAqL1xuICAgIHByb3RlY3RlZCBudW1Sb3dzOiBudW1iZXI7XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcGFyc2VUaWxlbWFwRGF0YSh0aWxlbWFwRGF0YTogVGlsZWRUaWxlbWFwRGF0YSwgbGF5ZXI6IFRpbGVkTGF5ZXJEYXRhKTogdm9pZCB7XG4gICAgICAgIC8vIFRoZSBzaXplIG9mIHRoZSB0aWxlbWFwIGluIGxvY2FsIHNwYWNlXG4gICAgICAgIHRoaXMubnVtQ29scyA9IHRpbGVtYXBEYXRhLndpZHRoO1xuICAgICAgICB0aGlzLm51bVJvd3MgPSB0aWxlbWFwRGF0YS5oZWlnaHQ7XG5cbiAgICAgICAgLy8gVGhlIHNpemUgb2YgdGlsZXNcbiAgICAgICAgdGhpcy50aWxlU2l6ZS5zZXQodGlsZW1hcERhdGEudGlsZXdpZHRoLCB0aWxlbWFwRGF0YS50aWxlaGVpZ2h0KTtcblxuICAgICAgICAvLyBUaGUgc2l6ZSBvZiB0aGUgdGlsZW1hcCBvbiB0aGUgY2FudmFzXG4gICAgICAgIHRoaXMuc2l6ZS5zZXQodGhpcy5udW1Db2xzICogdGhpcy50aWxlU2l6ZS54LCB0aGlzLm51bVJvd3MgKiB0aGlzLnRpbGVTaXplLnkpO1xuICAgICAgICB0aGlzLnBvc2l0aW9uLmNvcHkodGhpcy5zaXplLnNjYWxlZCgwLjUpKTtcbiAgICAgICAgdGhpcy5kYXRhID0gbGF5ZXIuZGF0YTtcbiAgICAgICAgdGhpcy52aXNpYmxlID0gbGF5ZXIudmlzaWJsZTtcblxuICAgICAgICAvLyBXaGV0aGVyIHRoZSB0aWxlbWFwIGlzIGNvbGxpZGFibGUgb3Igbm90XG4gICAgICAgIHRoaXMuaXNDb2xsaWRhYmxlID0gZmFsc2U7XG4gICAgICAgIGlmKGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgZm9yKGxldCBpdGVtIG9mIGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgIGlmKGl0ZW0ubmFtZSA9PT0gXCJDb2xsaWRhYmxlXCIpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzQ29sbGlkYWJsZSA9IGl0ZW0udmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGFsbCB0aWxlcyBiZXNpZGVzIFwiZW1wdHk6IDBcIiB0byBiZSBjb2xsaWRhYmxlXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCB0aGlzLmNvbGxpc2lvbk1hcC5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbGxpc2lvbk1hcFtpXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0aWxlbWFwXG4gICAgICogQHJldHVybnMgQSBWZWMyIGNvbnRhaW5pbmcgdGhlIG51bWJlciBvZiBjb2x1bW5zIGFuZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIHRpbGVtYXAuXG4gICAgICovXG4gICAgZ2V0RGltZW5zaW9ucygpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHRoaXMubnVtQ29scywgdGhpcy5udW1Sb3dzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRhIHZhbHVlIG9mIHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgd29ybGQgcG9zaXRpb25cbiAgICAgKiBAcGFyYW0gd29ybGRDb29yZHMgVGhlIGNvb3JkaW5hdGVzIGluIHdvcmxkIHNwYWNlXG4gICAgICogQHJldHVybnMgVGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBnZXRUaWxlQXRXb3JsZFBvc2l0aW9uKHdvcmxkQ29vcmRzOiBWZWMyKTogbnVtYmVyIHtcbiAgICAgICAgbGV0IGxvY2FsQ29vcmRzID0gdGhpcy5nZXRDb2xSb3dBdCh3b3JsZENvb3Jkcyk7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFRpbGVBdFJvd0NvbChsb2NhbENvb3Jkcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB0aWxlIGF0IHRoZSBzcGVjaWZpZWQgcm93IGFuZCBjb2x1bW5cbiAgICAgKiBAcGFyYW0gcm93Q29sIFRoZSBjb29yZGluYXRlcyBpbiB0aWxlbWFwIHNwYWNlXG4gICAgICogQHJldHVybnMgVGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBnZXRUaWxlQXRSb3dDb2wocm93Q29sOiBWZWMyKTogbnVtYmVyIHtcbiAgICAgICAgaWYocm93Q29sLnggPCAwIHx8IHJvd0NvbC54ID49IHRoaXMubnVtQ29scyB8fCByb3dDb2wueSA8IDAgfHwgcm93Q29sLnkgPj0gdGhpcy5udW1Sb3dzKXtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmRhdGFbcm93Q29sLnkgKiB0aGlzLm51bUNvbHMgKyByb3dDb2wueF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgd29ybGQgcG9zaXRpb24gb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGVcbiAgICAgKiBAcmV0dXJucyBBIFZlYzIgY29udGFpbmluZyB0aGUgd29ybGQgcG9zaXRpb24gb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBnZXRUaWxlV29ybGRQb3NpdGlvbihpbmRleDogbnVtYmVyKTogVmVjMiB7XG4gICAgICAgIC8vIEdldCB0aGUgbG9jYWwgcG9zaXRpb25cbiAgICAgICAgbGV0IGNvbCA9IGluZGV4ICUgdGhpcy5udW1Db2xzO1xuICAgICAgICBsZXQgcm93ID0gTWF0aC5mbG9vcihpbmRleCAvIHRoaXMubnVtQ29scyk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB3b3JsZCBwb3NpdGlvblxuICAgICAgICBsZXQgeCA9IGNvbCAqIHRoaXMudGlsZVNpemUueCAqIHRoaXMuc2NhbGUueDtcbiAgICAgICAgbGV0IHkgPSByb3cgKiB0aGlzLnRpbGVTaXplLnkgKiB0aGlzLnNjYWxlLnk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBWZWMyKHgsIHkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGRhdGEgdmFsdWUgb2YgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCBpbmRleFxuICAgICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHRpbGVcbiAgICAgKiBAcmV0dXJucyBUaGUgZGF0YSB2YWx1ZSBvZiB0aGUgdGlsZVxuICAgICAqL1xuICAgIGdldFRpbGUoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGFbaW5kZXhdO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHNldFRpbGUoaW5kZXg6IG51bWJlciwgdHlwZTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGF0YVtpbmRleF0gPSB0eXBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCByb3cgYW5kIGNvbHVtblxuICAgICAqIEBwYXJhbSByb3dDb2wgVGhlIHBvc2l0aW9uIG9mIHRoZSB0aWxlIGluIHRpbGVtYXAgc3BhY2VcbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgbmV3IGRhdGEgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgKi9cbiAgICBzZXRUaWxlQXRSb3dDb2wocm93Q29sOiBWZWMyLCB0eXBlOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGluZGV4ID0gcm93Q29sLnkgKiB0aGlzLm51bUNvbHMgKyByb3dDb2wueDtcbiAgICAgICAgdGhpcy5zZXRUaWxlKGluZGV4LCB0eXBlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHRpbGUgYXQgdGhlIHNwZWNpZmllZCByb3cgYW5kIGNvbHVtbiBvZiB0aGUgdGlsZW1hcCBpcyBjb2xsaWRhYmxlXG4gICAgICogQHBhcmFtIGluZGV4T3JDb2wgVGhlIGluZGV4IG9mIHRoZSB0aWxlIG9yIHRoZSBjb2x1bW4gaXQgaXMgaW5cbiAgICAgKiBAcGFyYW0gcm93IFRoZSByb3cgdGhlIHRpbGUgaXMgaW5cbiAgICAgKiBAcmV0dXJucyBBIGZsYWcgcmVwcmVzZW50aW5nIHdoZXRoZXIgb3Igbm90IHRoZSB0aWxlIGlzIGNvbGxpZGFibGUuXG4gICAgICovXG4gICAgaXNUaWxlQ29sbGlkYWJsZShpbmRleE9yQ29sOiBudW1iZXIsIHJvdz86IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICAvLyBUaGUgdmFsdWUgb2YgdGhlIHRpbGVcbiAgICAgICAgbGV0IHRpbGUgPSAwO1xuXG4gICAgICAgIGlmKHJvdyl7XG4gICAgICAgICAgICAvLyBXZSBoYXZlIGEgY29sdW1uIGFuZCBhIHJvd1xuICAgICAgICAgICAgdGlsZSA9IHRoaXMuZ2V0VGlsZUF0Um93Q29sKG5ldyBWZWMyKGluZGV4T3JDb2wsIHJvdykpO1xuXG4gICAgICAgICAgICBpZih0aWxlIDwgMCl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYoaW5kZXhPckNvbCA8IDAgfHwgaW5kZXhPckNvbCA+PSB0aGlzLmRhdGEubGVuZ3RoKXtcbiAgICAgICAgICAgICAgICAvLyBUaWxlcyB0aGF0IGRvbid0IGV4aXN0IGFyZW4ndCBjb2xsaWRhYmxlXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gV2UgaGF2ZSBhbiBpbmRleFxuICAgICAgICAgICAgdGlsZSA9IHRoaXMuZ2V0VGlsZShpbmRleE9yQ29sKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbGxpc2lvbk1hcFt0aWxlXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUYWtlcyBpbiB3b3JsZCBjb29yZGluYXRlcyBhbmQgcmV0dXJucyB0aGUgcm93IGFuZCBjb2x1bW4gb2YgdGhlIHRpbGUgYXQgdGhhdCBwb3NpdGlvblxuICAgICAqIEBwYXJhbSB3b3JsZENvb3JkcyBUaGUgY29vcmRpbmF0ZXMgb2YgdGhlIHBvdGVudGlhbCB0aWxlIGluIHdvcmxkIHNwYWNlXG4gICAgICogQHJldHVybnMgQSBWZWMyIGNvbnRhaW5pbmcgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb3RlbnRpYWwgdGlsZSBpbiB0aWxlbWFwIHNwYWNlXG4gICAgICovXG4gICAgZ2V0Q29sUm93QXQod29ybGRDb29yZHM6IFZlYzIpOiBWZWMyIHtcbiAgICAgICAgbGV0IGNvbCA9IE1hdGguZmxvb3Iod29ybGRDb29yZHMueCAvIHRoaXMudGlsZVNpemUueCAvIHRoaXMuc2NhbGUueCk7XG4gICAgICAgIGxldCByb3cgPSBNYXRoLmZsb29yKHdvcmxkQ29vcmRzLnkgLyB0aGlzLnRpbGVTaXplLnkgLyB0aGlzLnNjYWxlLnkpO1xuXG4gICAgICAgIHJldHVybiBuZXcgVmVjMihjb2wsIHJvdyk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7fVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZGVidWdSZW5kZXIoKXtcbiAgICAgICAgLy8gSGFsZiBvZiB0aGUgdGlsZSBzaXplXG4gICAgICAgIGxldCB6b29tZWRIYWxmVGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplV2l0aFpvb20oKS5zY2FsZWQoMC41KTtcbiAgICAgICAgbGV0IGhhbGZUaWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKS5zY2FsZWQoMC41KTtcblxuICAgICAgICAvLyBUaGUgY2VudGVyIG9mIHRoZSB0b3AgbGVmdCB0aWxlXG4gICAgICAgIGxldCB0b3BMZWZ0ID0gdGhpcy5wb3NpdGlvbi5jbG9uZSgpLnN1Yih0aGlzLnNpemUuc2NhbGVkKDAuNSkpO1xuICAgICAgICBcbiAgICAgICAgLy8gQSB2ZWMgdG8gc3RvcmUgdGhlIGNlbnRlclxuICAgICAgICBsZXQgY2VudGVyID0gVmVjMi5aRVJPO1xuXG4gICAgICAgIGZvcihsZXQgY29sID0gMDsgY29sIDwgdGhpcy5udW1Db2xzOyBjb2wrKyl7XG4gICAgICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHgtcG9zaXRpb25cbiAgICAgICAgICAgIGNlbnRlci54ID0gdG9wTGVmdC54ICsgY29sKjIqaGFsZlRpbGVTaXplLnggKyBoYWxmVGlsZVNpemUueDtcblxuICAgICAgICAgICAgZm9yKGxldCByb3cgPSAwOyByb3cgPCB0aGlzLm51bVJvd3M7IHJvdysrKXtcbiAgICAgICAgICAgICAgICBpZih0aGlzLmlzQ29sbGlkYWJsZSAmJiB0aGlzLmlzVGlsZUNvbGxpZGFibGUoY29sLCByb3cpKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSB5LXBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNlbnRlci55ID0gdG9wTGVmdC55ICsgcm93KjIqaGFsZlRpbGVTaXplLnkgKyBoYWxmVGlsZVNpemUueTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBEcmF3IGEgYm94IGZvciB0aGlzIHRpbGVcbiAgICAgICAgICAgICAgICAgICAgRGVidWcuZHJhd0JveCh0aGlzLmluUmVsYXRpdmVDb29yZGluYXRlcyhjZW50ZXIpLCB6b29tZWRIYWxmVGlsZVNpemUsIGZhbHNlLCBDb2xvci5CTFVFKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4vQ2FudmFzTm9kZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi9VdGlscy9Db2xvclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgSW5wdXQgZnJvbSBcIi4uL0lucHV0L0lucHV0XCI7XG5cbi8qKlxuICogVGhlIHJlcHJlc2VudGF0aW9uIG9mIGEgVUlFbGVtZW50IC0gdGhlIHBhcmVudCBjbGFzcyBvZiB0aGluZ3MgbGlrZSBidXR0b25zXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFVJRWxlbWVudCBleHRlbmRzIENhbnZhc05vZGUge1xuXHQvLyBTdHlsZSBhdHRyaWJ1dGVzIC0gVE9ETyAtIGFic3RyYWN0IHRoaXMgaW50byBhIHN0eWxlIG9iamVjdC9pbnRlcmZhY2Vcblx0LyoqIFRoZSBiYWNrZ291bmQgY29sb3IgKi9cblx0YmFja2dyb3VuZENvbG9yOiBDb2xvcjtcblx0LyoqIFRoZSBib3JkZXIgY29sb3IgKi9cblx0Ym9yZGVyQ29sb3I6IENvbG9yO1xuXHQvKiogVGhlIGJvcmRlciByYWRpdXMgKi9cblx0Ym9yZGVyUmFkaXVzOiBudW1iZXI7XG5cdC8qKiBUaGUgYm9yZGVyIHdpZHRoICovXG5cdGJvcmRlcldpZHRoOiBudW1iZXI7XG5cdC8qKiBUaGUgcGFkZGluZyAqL1xuXHRwYWRkaW5nOiBWZWMyO1xuXG5cdC8vIEV2ZW50QXR0cmlidXRlc1xuXHQvKiogVGhlIHJlYWN0aW9uIG9mIHRoaXMgVUlFbGVtZW50IG9uIGEgY2xpY2sgKi9cblx0b25DbGljazogRnVuY3Rpb247XG5cdC8qKiBUaGUgZXZlbnQgcHJvcGFnYXRlZCBvbiBjbGljayAqL1xuXHRvbkNsaWNrRXZlbnRJZDogc3RyaW5nO1xuXHQvKiogVGhlIHJlYWN0aW9uIHRvIHRoZSByZWxlYXNlIG9mIGEgY2xpY2sgKi9cblx0b25SZWxlYXNlOiBGdW5jdGlvbjtcblx0LyoqIFRoZSBldmVudCBwcm9wYWdhdGVkIG9uIHRoZSByZWxlYXNlIG9mIGEgY2xpY2sgKi9cblx0b25SZWxlYXNlRXZlbnRJZDogc3RyaW5nO1xuXHQvKiogVGhlIHJlYWN0aW9uIHdoZW4gYSBtb3VzZSBlbnRlcnMgdGhpcyBVSUVsZW1lbnQgKi9cblx0b25FbnRlcjogRnVuY3Rpb247XG5cdC8qKiBUaGUgZXZlbnQgcHJvcGFnYXRlZCB3aGVuIGEgbW91c2UgZW50ZXJzIHRoaXMgVUlFbGVtZW50ICovXG5cdG9uRW50ZXJFdmVudElkOiBzdHJpbmc7XG5cdC8qKiBUaGUgcmVhY3Rpb24gd2hlbiBhIG1vdXNlIGxlYXZlcyB0aGlzIFVJRWxlbWVudCAqL1xuXHRvbkxlYXZlOiBGdW5jdGlvbjtcblx0LyoqIFRoZSBldmVudCBwcm9wb2dhdGVkIHdoZW4gYSBtb3VzZSBsZWF2ZXMgdGhpcyBVSUVsZW1lbnQgKi9cblx0b25MZWF2ZUV2ZW50SWQ6IHN0cmluZztcblxuXHQvKiogV2hldGhlciBvciBub3QgdGhpcyBVSUVsZW1lbnQgaXMgY3VycmVudGx5IGNsaWNrZWQgb24gKi9cblx0cHJvdGVjdGVkIGlzQ2xpY2tlZDogYm9vbGVhbjtcblx0LyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgVUlFbGVtZW50IGlzIGN1cnJlbnRseSBob3ZlcmVkIG92ZXIgKi9cblx0cHJvdGVjdGVkIGlzRW50ZXJlZDogYm9vbGVhbjtcblxuXHRjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMil7XG5cdFx0c3VwZXIoKTtcblx0XHR0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG5cdFx0XG5cdFx0dGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBuZXcgQ29sb3IoMCwgMCwgMCwgMCk7XG5cdFx0dGhpcy5ib3JkZXJDb2xvciA9IG5ldyBDb2xvcigwLCAwLCAwLCAwKTtcblx0XHR0aGlzLmJvcmRlclJhZGl1cyA9IDU7XG5cdFx0dGhpcy5ib3JkZXJXaWR0aCA9IDE7XG5cdFx0dGhpcy5wYWRkaW5nID0gVmVjMi5aRVJPO1xuXG5cdFx0dGhpcy5vbkNsaWNrID0gbnVsbDtcblx0XHR0aGlzLm9uQ2xpY2tFdmVudElkID0gbnVsbDtcblx0XHR0aGlzLm9uUmVsZWFzZSA9IG51bGw7XG5cdFx0dGhpcy5vblJlbGVhc2VFdmVudElkID0gbnVsbDtcblxuXHRcdHRoaXMub25FbnRlciA9IG51bGw7XG5cdFx0dGhpcy5vbkVudGVyRXZlbnRJZCA9IG51bGw7XG5cdFx0dGhpcy5vbkxlYXZlID0gbnVsbDtcblx0XHR0aGlzLm9uTGVhdmVFdmVudElkID0gbnVsbDtcblxuXHRcdHRoaXMuaXNDbGlja2VkID0gZmFsc2U7XG5cdFx0dGhpcy5pc0VudGVyZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8vIEBkZXByZWNhdGVkXG5cdHNldEJhY2tncm91bmRDb2xvcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLmJhY2tncm91bmRDb2xvciA9IGNvbG9yO1xuXHR9XG5cblx0Ly8gQGRlcHJlY2F0ZWRcblx0c2V0UGFkZGluZyhwYWRkaW5nOiBWZWMyKTogdm9pZCB7XG5cdFx0dGhpcy5wYWRkaW5nLmNvcHkocGFkZGluZyk7XG5cdH1cblxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblxuXHRcdC8vIFNlZSBvZiB0aGlzIG9iamVjdCB3YXMganVzdCBjbGlja2VkXG5cdFx0aWYoSW5wdXQuaXNNb3VzZUp1c3RQcmVzc2VkKCkpe1xuXHRcdFx0bGV0IGNsaWNrUG9zID0gSW5wdXQuZ2V0TW91c2VQcmVzc1Bvc2l0aW9uKCk7XG5cdFx0XHRpZih0aGlzLmNvbnRhaW5zKGNsaWNrUG9zLngsIGNsaWNrUG9zLnkpICYmIHRoaXMudmlzaWJsZSAmJiAhdGhpcy5sYXllci5pc0hpZGRlbigpKXtcblx0XHRcdFx0dGhpcy5pc0NsaWNrZWQgPSB0cnVlO1xuXG5cdFx0XHRcdGlmKHRoaXMub25DbGljayAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0dGhpcy5vbkNsaWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYodGhpcy5vbkNsaWNrRXZlbnRJZCAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0bGV0IGRhdGEgPSB7fTtcblx0XHRcdFx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMub25DbGlja0V2ZW50SWQsIGRhdGEpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlIG1vdXNlIHdhc24ndCBqdXN0IHByZXNzZWQsIHRoZW4gd2UgZGVmaW5pdGVseSB3ZXJlbid0IGNsaWNrZWRcblx0XHRpZighSW5wdXQuaXNNb3VzZVByZXNzZWQoKSl7XG5cdFx0XHRpZih0aGlzLmlzQ2xpY2tlZCl7XG5cdFx0XHRcdHRoaXMuaXNDbGlja2VkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2hlY2sgaWYgdGhlIG1vdXNlIGlzIGhvdmVyaW5nIG92ZXIgdGhpcyBlbGVtZW50XG5cdFx0bGV0IG1vdXNlUG9zID0gSW5wdXQuZ2V0TW91c2VQb3NpdGlvbigpO1xuXHRcdGlmKG1vdXNlUG9zICYmIHRoaXMuY29udGFpbnMobW91c2VQb3MueCwgbW91c2VQb3MueSkpe1xuXHRcdFx0dGhpcy5pc0VudGVyZWQgPSB0cnVlO1xuXG5cdFx0XHRpZih0aGlzLm9uRW50ZXIgIT09IG51bGwpe1xuXHRcdFx0XHR0aGlzLm9uRW50ZXIoKTtcblx0XHRcdH1cblx0XHRcdGlmKHRoaXMub25FbnRlckV2ZW50SWQgIT09IG51bGwpe1xuXHRcdFx0XHRsZXQgZGF0YSA9IHt9O1xuXHRcdFx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMub25FbnRlckV2ZW50SWQsIGRhdGEpO1xuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIGlmKHRoaXMuaXNFbnRlcmVkKSB7XG5cdFx0XHR0aGlzLmlzRW50ZXJlZCA9IGZhbHNlO1xuXG5cdFx0XHRpZih0aGlzLm9uTGVhdmUgIT09IG51bGwpe1xuXHRcdFx0XHR0aGlzLm9uTGVhdmUoKTtcblx0XHRcdH1cblx0XHRcdGlmKHRoaXMub25MZWF2ZUV2ZW50SWQgIT09IG51bGwpe1xuXHRcdFx0XHRsZXQgZGF0YSA9IHt9O1xuXHRcdFx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KHRoaXMub25MZWF2ZUV2ZW50SWQsIGRhdGEpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZih0aGlzLmlzQ2xpY2tlZCkge1xuXHRcdFx0Ly8gSWYgbW91c2UgaXMgZHJhZ2dlZCBvZmYgb2YgZWxlbWVudCB3aGlsZSBkb3duLCBpdCBpcyBub3QgY2xpY2tlZCBhbnltb3JlXG5cdFx0XHR0aGlzLmlzQ2xpY2tlZCA9IGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBPdmVycmlkYWJsZSBtZXRob2QgZm9yIGNhbGN1bGF0aW5nIGJhY2tncm91bmQgY29sb3IgLSB1c2VmdWwgZm9yIGVsZW1lbnRzIHRoYXQgd2FudCB0byBiZSBjb2xvcmVkIG9uIGRpZmZlcmVudCBhZnRlciBjZXJ0YWluIGV2ZW50c1xuXHQgKiBAcmV0dXJucyBUaGUgYmFja2dyb3VuZCBjb2xvciBvZiB0aGUgVUlFbGVtZW50XG5cdCAqL1xuXHRjYWxjdWxhdGVCYWNrZ3JvdW5kQ29sb3IoKTogQ29sb3Ige1xuXHRcdHJldHVybiB0aGlzLmJhY2tncm91bmRDb2xvcjtcblx0fVxuXG5cdC8qKlxuXHQgKiBPdmVycmlkYWJsZSBtZXRob2QgZm9yIGNhbGN1bGF0aW5nIGJvcmRlciBjb2xvciAtIHVzZWZ1bCBmb3IgZWxlbWVudHMgdGhhdCB3YW50IHRvIGJlIGNvbG9yZWQgb24gZGlmZmVyZW50IGFmdGVyIGNlcnRhaW4gZXZlbnRzXG5cdCAqIEByZXR1cm5zIFRoZSBib3JkZXIgY29sb3Igb2YgdGhlIFVJRWxlbWVudFxuXHQgKi9cblx0Y2FsY3VsYXRlQm9yZGVyQ29sb3IoKTogQ29sb3Ige1xuXHRcdHJldHVybiB0aGlzLmJvcmRlckNvbG9yO1xuXHR9XG59IiwiaW1wb3J0IExhYmVsIGZyb20gXCIuL0xhYmVsXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcblxuLyoqIEEgY2xpY2thYmxlIGJ1dHRvbiBVSUVsZW1lbnQgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJ1dHRvbiBleHRlbmRzIExhYmVsIHtcblxuXHRjb25zdHJ1Y3Rvcihwb3NpdGlvbjogVmVjMiwgdGV4dDogc3RyaW5nKXtcblx0XHRzdXBlcihwb3NpdGlvbiwgdGV4dCk7XG5cdFx0XG5cdFx0dGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBuZXcgQ29sb3IoMTUwLCA3NSwgMjAzKTtcblx0XHR0aGlzLmJvcmRlckNvbG9yID0gbmV3IENvbG9yKDQxLCA0NiwgMzApO1xuXHRcdHRoaXMudGV4dENvbG9yID0gbmV3IENvbG9yKDI1NSwgMjU1LCAyNTUpO1xuXHR9XG5cblx0Ly8gQG92ZXJyaWRlXG5cdGNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpOiBDb2xvciB7XG5cdFx0Ly8gQ2hhbmdlIHRoZSBiYWNrZ3JvdW5kIGNvbG9yIGlmIGNsaWNrZWQgb3IgaG92ZXJlZFxuXHRcdGlmKHRoaXMuaXNFbnRlcmVkICYmICF0aGlzLmlzQ2xpY2tlZCl7XG5cdFx0XHRyZXR1cm4gdGhpcy5iYWNrZ3JvdW5kQ29sb3IubGlnaHRlbigpO1xuXHRcdH0gZWxzZSBpZih0aGlzLmlzQ2xpY2tlZCl7XG5cdFx0XHRyZXR1cm4gdGhpcy5iYWNrZ3JvdW5kQ29sb3IuZGFya2VuKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB0aGlzLmJhY2tncm91bmRDb2xvcjtcblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL1VJRWxlbWVudFwiO1xuXG4vKiogQSBiYXNpYyB0ZXh0LWNvbnRhaW5pbmcgbGFiZWwgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExhYmVsIGV4dGVuZHMgVUlFbGVtZW50e1xuXHQvKiogVGhlIGNvbG9yIG9mIHRoZSB0ZXh0IG9mIHRoaXMgVUlFbGVtZW50ICovXG5cdHRleHRDb2xvcjogQ29sb3I7XG5cdC8qKiBUaGUgdmFsdWUgb2YgdGhlIHRleHQgb2YgdGhpcyBVSUVsZW1lbnQgKi9cblx0dGV4dDogc3RyaW5nO1xuXHQvKiogVGhlIG5hbWUgb2YgdGhlIGZvbnQgKi9cblx0Zm9udDogc3RyaW5nO1xuXHQvKiogVGhlIHNpemUgb2YgdGhlIGZvbnQgKi9cblx0Zm9udFNpemU6IG51bWJlcjtcblx0LyoqIFRoZSBob3Jpem9udGFsIGFsaWdubWVudCBvZiB0aGUgdGV4dCB3aXRoaW4gdGhlIGxhYmVsICovXG5cdHByb3RlY3RlZCBoQWxpZ246IHN0cmluZztcblx0LyoqIFRoZSB2ZXJ0aWNhbCBhbGlnbm1lbnQgb2YgdGV4dCB3aXRoaW4gdGhlIGxhYmVsICovXG5cdHByb3RlY3RlZCB2QWxpZ246IHN0cmluZztcblxuXHQvKiogQSBmbGFnIGZvciBpZiB0aGUgd2lkdGggb2YgdGhlIHRleHQgaGFzIGJlZW4gbWVhc3VyZWQgb24gdGhlIGNhbnZhcyBmb3IgYXV0byB3aWR0aCBhc3NpZ25tZW50ICovXG5cdHByb3RlY3RlZCBzaXplQXNzaWduZWQ6IGJvb2xlYW47XG5cblx0Y29uc3RydWN0b3IocG9zaXRpb246IFZlYzIsIHRleHQ6IHN0cmluZyl7XG5cdFx0c3VwZXIocG9zaXRpb24pO1xuXHRcdHRoaXMudGV4dCA9IHRleHQ7XG5cdFx0dGhpcy50ZXh0Q29sb3IgPSBuZXcgQ29sb3IoMCwgMCwgMCwgMSk7XG5cdFx0dGhpcy5mb250ID0gXCJBcmlhbFwiO1xuXHRcdHRoaXMuZm9udFNpemUgPSAzMDtcblx0XHR0aGlzLmhBbGlnbiA9IFwiY2VudGVyXCI7XG5cdFx0dGhpcy52QWxpZ24gPSBcImNlbnRlclwiO1xuXG5cdFx0dGhpcy5zaXplQXNzaWduZWQgPSBmYWxzZTtcblx0fVxuXG5cdC8vIEBkZXByZWNhdGVkXG5cdHNldFRleHQodGV4dDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy50ZXh0ID0gdGV4dDtcblx0fVxuXG5cdC8vIEBkZXByZWNhdGVkXG5cdHNldFRleHRDb2xvcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLnRleHRDb2xvciA9IGNvbG9yO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYSBzdHJpbmcgY29udGFpbmcgdGhlIGZvbnQgZGV0YWlscyBmb3IgcmVuZGVyaW5nXG5cdCAqIEByZXR1cm5zIEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGZvbnQgZGV0YWlsc1xuXHQgKi9cblx0Z2V0Rm9udFN0cmluZygpOiBzdHJpbmcge1xuXHRcdHJldHVybiB0aGlzLmZvbnRTaXplICsgXCJweCBcIiArIHRoaXMuZm9udDtcblx0fVxuXG5cdC8qKlxuXHQgKiBPdmVycmlkYWJsZSBtZXRob2QgZm9yIGNhbGN1bGF0aW5nIHRleHQgY29sb3IgLSB1c2VmdWwgZm9yIGVsZW1lbnRzIHRoYXQgd2FudCB0byBiZSBjb2xvcmVkIG9uIGRpZmZlcmVudCBhZnRlciBjZXJ0YWluIGV2ZW50c1xuXHQgKiBAcmV0dXJucyBhIHN0cmluZyBjb250YWluZyB0aGUgdGV4dCBjb2xvclxuXHQgKi9cblx0Y2FsY3VsYXRlVGV4dENvbG9yKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMudGV4dENvbG9yLnRvU3RyaW5nUkdCQSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVzZXMgdGhlIGNhbnZhcyB0byBjYWxjdWxhdGUgdGhlIHdpZHRoIG9mIHRoZSB0ZXh0XG5cdCAqIEBwYXJhbSBjdHggVGhlIHJlbmRlcmluZyBjb250ZXh0XG5cdCAqIEByZXR1cm5zIEEgbnVtYmVyIHJlcHJlc2VudGluZyB0aGUgcmVuZGVyZWQgdGV4dCB3aWR0aFxuXHQgKi9cblx0cHJvdGVjdGVkIGNhbGN1bGF0ZVRleHRXaWR0aChjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCk6IG51bWJlciB7XG5cdFx0Y3R4LmZvbnQgPSB0aGlzLmZvbnRTaXplICsgXCJweCBcIiArIHRoaXMuZm9udDtcblx0XHRyZXR1cm4gY3R4Lm1lYXN1cmVUZXh0KHRoaXMudGV4dCkud2lkdGg7XG5cdH1cblxuXHRzZXRIQWxpZ24oYWxpZ246IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMuaEFsaWduID0gYWxpZ247XG5cdH1cblxuXHRzZXRWQWxpZ24oYWxpZ246IHN0cmluZyk6IHZvaWQge1xuXHRcdHRoaXMudkFsaWduID0gYWxpZ247XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlIHRoZSBvZmZzZXQgb2YgdGhlIHRleHQgLSB0aGlzIGlzIHVzZWQgZm9yIHJlbmRlcmluZyB0ZXh0IHdpdGggZGlmZmVyZW50IGFsaWdubWVudHNcblx0ICogQHBhcmFtIGN0eCBUaGUgcmVuZGVyaW5nIGNvbnRleHRcblx0ICogQHJldHVybnMgVGhlIG9mZnNldCBvZiB0aGUgdGV4dCBpbiBhIFZlYzJcblx0ICovXG5cdGNhbGN1bGF0ZVRleHRPZmZzZXQoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpOiBWZWMyIHtcblx0XHRsZXQgdGV4dFdpZHRoID0gdGhpcy5jYWxjdWxhdGVUZXh0V2lkdGgoY3R4KTtcblxuXHRcdGxldCBvZmZzZXQgPSBuZXcgVmVjMigwLCAwKTtcblxuXHRcdGxldCBoRGlmZiA9IHRoaXMuc2l6ZS54IC0gdGV4dFdpZHRoO1xuXHRcdGlmKHRoaXMuaEFsaWduID09PSBIQWxpZ24uQ0VOVEVSKXtcblx0XHRcdG9mZnNldC54ID0gaERpZmYvMjtcblx0XHR9IGVsc2UgaWYgKHRoaXMuaEFsaWduID09PSBIQWxpZ24uUklHSFQpe1xuXHRcdFx0b2Zmc2V0LnggPSBoRGlmZjtcblx0XHR9XG5cblx0XHRpZih0aGlzLnZBbGlnbiA9PT0gVkFsaWduLlRPUCl7XG5cdFx0XHRjdHgudGV4dEJhc2VsaW5lID0gXCJ0b3BcIjtcblx0XHRcdG9mZnNldC55ID0gMDtcblx0XHR9IGVsc2UgaWYgKHRoaXMudkFsaWduID09PSBWQWxpZ24uQk9UVE9NKXtcblx0XHRcdGN0eC50ZXh0QmFzZWxpbmUgPSBcImJvdHRvbVwiO1xuXHRcdFx0b2Zmc2V0LnkgPSB0aGlzLnNpemUueTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y3R4LnRleHRCYXNlbGluZSA9IFwibWlkZGxlXCI7XG5cdFx0XHRvZmZzZXQueSA9IHRoaXMuc2l6ZS55LzI7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9mZnNldDtcblx0fVxuXG5cdHByb3RlY3RlZCBzaXplQ2hhbmdlZCgpOiB2b2lkIHtcblx0XHRzdXBlci5zaXplQ2hhbmdlZCgpO1xuXHRcdHRoaXMuc2l6ZUFzc2lnbmVkID0gdHJ1ZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBdXRvbWF0aWNhbGx5IHNpemVzIHRoZSBlbGVtZW50IHRvIHRoZSB0ZXh0IHdpdGhpbiBpdFxuXHQgKiBAcGFyYW0gY3R4IFRoZSByZW5kZXJpbmcgY29udGV4dFxuXHQgKi9cblx0cHJvdGVjdGVkIGF1dG9TaXplKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZCB7XG5cdFx0bGV0IHdpZHRoID0gdGhpcy5jYWxjdWxhdGVUZXh0V2lkdGgoY3R4KTtcblx0XHRsZXQgaGVpZ2h0ID0gdGhpcy5mb250U2l6ZTtcblx0XHR0aGlzLnNpemUuc2V0KHdpZHRoICsgdGhpcy5wYWRkaW5nLngqMiwgaGVpZ2h0ICsgdGhpcy5wYWRkaW5nLnkqMik7XG5cdFx0dGhpcy5zaXplQXNzaWduZWQgPSB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRpYWxseSBhc3NpZ25zIGEgc2l6ZSB0byB0aGUgVUlFbGVtZW50IGlmIG5vbmUgaXMgcHJvdmlkZWRcblx0ICogQHBhcmFtIGN0eCBUaGUgcmVuZGVyaW5nIGNvbnRleHRcblx0ICovXG5cdGhhbmRsZUluaXRpYWxTaXppbmcoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpOiB2b2lkIHtcblx0XHRpZighdGhpcy5zaXplQXNzaWduZWQpe1xuXHRcdFx0dGhpcy5hdXRvU2l6ZShjdHgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKiBPbiB0aGUgbmV4dCByZW5kZXIsIHNpemUgdGhpcyBlbGVtZW50IHRvIGl0J3MgY3VycmVudCB0ZXh0IHVzaW5nIGl0cyBjdXJyZW50IGZvbnQgc2l6ZSAqL1xuXHRzaXplVG9UZXh0KCk6IHZvaWQge1xuXHRcdHRoaXMuc2l6ZUFzc2lnbmVkID0gZmFsc2U7XG5cdH1cbn1cblxuZXhwb3J0IGVudW0gVkFsaWduIHtcblx0VE9QID0gXCJ0b3BcIixcblx0Q0VOVEVSID0gXCJjZW50ZXJcIixcblx0Qk9UVE9NID0gXCJib3R0b21cIlxufVxuXG5leHBvcnQgZW51bSBIQWxpZ24ge1xuXHRMRUZUID0gXCJsZWZ0XCIsXG5cdENFTlRFUiA9IFwiY2VudGVyXCIsXG5cdFJJR0hUID0gXCJyaWdodFwiXG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgSW5wdXQgZnJvbSBcIi4uLy4uL0lucHV0L0lucHV0XCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL1VJRWxlbWVudFwiO1xuXG4vKiogQSBzbGlkZXIgVUlFbGVtZW50ICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTbGlkZXIgZXh0ZW5kcyBVSUVsZW1lbnQge1xuICAgIC8qKiBUaGUgdmFsdWUgb2YgdGhlIHNsaWRlciBmcm9tIFswLCAxXSAqL1xuICAgIHByb3RlY3RlZCB2YWx1ZTogbnVtYmVyO1xuICAgIC8qKiBUaGUgY29sb3Igb2YgdGhlIHNsaWRlciBuaWIgKi9cbiAgICBwdWJsaWMgbmliQ29sb3I6IENvbG9yO1xuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgbmliICovXG4gICAgcHVibGljIG5pYlNpemU6IFZlYzI7XG4gICAgLyoqIFRoZSBjb2xvciBvZiB0aGUgc2xpZGVyIHRyYWNrICovXG4gICAgcHVibGljIHNsaWRlckNvbG9yOiBDb2xvcjtcbiAgICAvKiogVGhlIHJlYWN0aW9uIG9mIHRoaXMgVUlFbGVtZW50IHRvIGEgdmFsdWUgY2hhbmdlICovXG4gICAgcHVibGljIG9uVmFsdWVDaGFuZ2U6IEZ1bmN0aW9uO1xuICAgIC8qKiBUaGUgZXZlbnQgcHJvcGFnYXRlZCBieSB0aGlzIFVJRWxlbWVudCB3aGVuIHZhbHVlIGNoYW5nZXMgKi9cbiAgICBwdWJsaWMgb25WYWx1ZUNoYW5nZUV2ZW50SWQ6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyLCBpbml0VmFsdWU6IG51bWJlcil7XG4gICAgICAgIHN1cGVyKHBvc2l0aW9uKTtcblxuICAgICAgICB0aGlzLnZhbHVlID0gaW5pdFZhbHVlO1xuICAgICAgICB0aGlzLm5pYkNvbG9yID0gQ29sb3IuUkVEO1xuICAgICAgICB0aGlzLnNsaWRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIHRoaXMuYm9yZGVyQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgdGhpcy5uaWJTaXplID0gbmV3IFZlYzIoMTAsIDIwKTtcblxuICAgICAgICAvLyBTZXQgYSBkZWZhdWx0IHNpemVcbiAgICAgICAgdGhpcy5zaXplLnNldCgyMDAsIDIwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHZhbHVlIG9mIHRoZSBzbGlkZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgb2YgdGhlIHNsaWRlclxuICAgICAqL1xuICAgIGdldFZhbHVlKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH1cblxuICAgIC8qKiBBIG1ldGhvZCBjYWxsZWQgaW4gcmVzcG9uc2UgdG8gdGhlIHZhbHVlIGNoYW5naW5nICovXG4gICAgcHJvdGVjdGVkIHZhbHVlQ2hhbmdlZCgpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy5vblZhbHVlQ2hhbmdlKXtcbiAgICAgICAgICAgIHRoaXMub25WYWx1ZUNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMub25WYWx1ZUNoYW5nZUV2ZW50SWQpe1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLm9uVmFsdWVDaGFuZ2VFdmVudElkLCB7dGFyZ2V0OiB0aGlzLCB2YWx1ZTogdGhpcy52YWx1ZX0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGlmKHRoaXMuaXNDbGlja2VkKXtcbiAgICAgICAgICAgIGxldCB2YWwgPSBNYXRoVXRpbHMuaW52TGVycCh0aGlzLnBvc2l0aW9uLnggLSB0aGlzLnNpemUueC8yLCB0aGlzLnBvc2l0aW9uLnggKyB0aGlzLnNpemUueC8yLCBJbnB1dC5nZXRNb3VzZVBvc2l0aW9uKCkueCk7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gTWF0aFV0aWxzLmNsYW1wMDEodmFsKTtcbiAgICAgICAgICAgIHRoaXMudmFsdWVDaGFuZ2VkKCk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4vTGFiZWxcIjtcbmltcG9ydCBJbnB1dCBmcm9tIFwiLi4vLi4vSW5wdXQvSW5wdXRcIjtcblxuLyoqIEEgdGV4dCBpbnB1dCBVSUVsZW1lbnQgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRleHRJbnB1dCBleHRlbmRzIExhYmVsIHtcbiAgICAvKiogQSBmbGFnIHRoZSByZXByZXNlbnRzIHdoZXRoZXIgdGhlIHVzZXIgY2FuIHR5cGUgaW4gdGhpcyBUZXh0SW5wdXQgKi9cbiAgICBmb2N1c2VkOiBib29sZWFuO1xuICAgIC8qKiBUaGUgcG9zaXRpb24gb2YgdGhlIGN1cnNvciBpbiB0aGlzIFRleHRJbnB1dCAqL1xuICAgIGN1cnNvckNvdW50ZXI6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBvc2l0aW9uOiBWZWMyKXtcbiAgICAgICAgc3VwZXIocG9zaXRpb24sIFwiXCIpO1xuXG4gICAgICAgIHRoaXMuZm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmN1cnNvckNvdW50ZXIgPSAwO1xuXG4gICAgICAgIC8vIEdpdmUgYSBkZWZhdWx0IHNpemUgdG8gdGhlIHggb25seVxuICAgICAgICB0aGlzLnNpemUuc2V0KDIwMCwgdGhpcy5mb250U2l6ZSk7XG4gICAgICAgIHRoaXMuaEFsaWduID0gXCJsZWZ0XCI7XG5cbiAgICAgICAgdGhpcy5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9IENvbG9yLldISVRFO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBzdXBlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICBpZihJbnB1dC5pc01vdXNlSnVzdFByZXNzZWQoKSl7XG5cdFx0XHRsZXQgY2xpY2tQb3MgPSBJbnB1dC5nZXRNb3VzZVByZXNzUG9zaXRpb24oKTtcblx0XHRcdGlmKHRoaXMuY29udGFpbnMoY2xpY2tQb3MueCwgY2xpY2tQb3MueSkpe1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJzb3JDb3VudGVyID0gMzA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5mb2N1c2VkKXtcbiAgICAgICAgICAgIGxldCBrZXlzID0gSW5wdXQuZ2V0S2V5c0p1c3RQcmVzc2VkKCk7XG4gICAgICAgICAgICBsZXQgbnVtcyA9IFwiMTIzNDU2Nzg5MFwiO1xuICAgICAgICAgICAgbGV0IHNwZWNpYWxDaGFycyA9IFwiYH4hQCMkJV4mKigpLV89K1t7XX1cXFxcfDs6J1xcXCIsPC4+Lz9cIjtcbiAgICAgICAgICAgIGxldCBsZXR0ZXJzID0gXCJxd2VydHl1aW9wYXNkZmdoamtsenhjdmJubVwiO1xuICAgICAgICAgICAgbGV0IG1hc2sgPSBudW1zICsgc3BlY2lhbENoYXJzICsgbGV0dGVycztcbiAgICAgICAgICAgIGtleXMgPSBrZXlzLmZpbHRlcihrZXkgPT4gbWFzay5pbmNsdWRlcyhrZXkpKTtcbiAgICAgICAgICAgIGxldCBzaGlmdFByZXNzZWQgPSBJbnB1dC5pc0tleVByZXNzZWQoXCJzaGlmdFwiKTtcbiAgICAgICAgICAgIGxldCBiYWNrc3BhY2VQcmVzc2VkID0gSW5wdXQuaXNLZXlKdXN0UHJlc3NlZChcImJhY2tzcGFjZVwiKTtcbiAgICAgICAgICAgIGxldCBzcGFjZVByZXNzZWQgPSBJbnB1dC5pc0tleUp1c3RQcmVzc2VkKFwic3BhY2VcIik7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKGJhY2tzcGFjZVByZXNzZWQpe1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IHRoaXMudGV4dC5zdWJzdHJpbmcoMCwgdGhpcy50ZXh0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHNwYWNlUHJlc3NlZCl7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ICs9IFwiIFwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGtleXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGlmKHNoaWZ0UHJlc3NlZCl7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dCArPSBrZXlzWzBdLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0ICs9IGtleXNbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufSIsImV4cG9ydCBlbnVtIFVJRWxlbWVudFR5cGUge1xuXHRCVVRUT04gPSBcIkJVVFRPTlwiLFxuXHRMQUJFTCA9IFwiTEFCRUxcIixcblx0U0xJREVSID0gXCJTTElERVJcIixcblx0VEVYVF9JTlBVVCA9IFwiVEVYVElOUFVUXCJcbn0iLCJpbXBvcnQgTmF2aWdhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9OYXZpZ2FibGVcIjtcbmltcG9ydCBNYXAgZnJvbSBcIi4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IE5hdmlnYXRpb25QYXRoIGZyb20gXCIuL05hdmlnYXRpb25QYXRoXCI7XG5cbi8qKlxuICogVGhlIG1hbmFnZXIgY2xhc3MgZm9yIG5hdmlnYXRpb24uXG4gKiBIYW5kbGVzIGFsbCBuYXZpZ2FibGUgZW50aXRpZXMsIHN1Y2ggYW5kIGFsbG93cyB0aGVtIHRvIGJlIGFjY2Vzc2VkIGJ5IG91dHNpZGUgc3lzdGVtcyBieSByZXF1ZXN0aW5nIGEgcGF0aFxuICogZnJvbSBvbmUgcG9zaXRpb24gdG8gYW5vdGhlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTmF2aWdhdGlvbk1hbmFnZXIge1xuXHQvKiogVGhlIGxpc3Qgb2YgYWxsIG5hdmlnYWJsZSBlbnRpdGllcyAqL1xuXHRwcm90ZWN0ZWQgbmF2aWdhYmxlRW50aXRpZXM6IE1hcDxOYXZpZ2FibGU+O1xuXG5cdGNvbnN0cnVjdG9yKCl7XG5cdFx0dGhpcy5uYXZpZ2FibGVFbnRpdGllcyA9IG5ldyBNYXAoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgbmF2aWdhYmxlIGVudGl0eSB0byB0aGUgTmF2aWdhdGlvbk1hbmFnZXJcblx0ICogQHBhcmFtIG5hdk5hbWUgVGhlIG5hbWUgb2YgdGhlIG5hdmlnYWJsZSBlbnRpdHJ5XG5cdCAqIEBwYXJhbSBuYXYgVGhlIGFjdHVhbCBOYXZpZ2FibGUgaW5zdGFuY2Vcblx0ICovXG5cdGFkZE5hdmlnYWJsZUVudGl0eShuYXZOYW1lOiBzdHJpbmcsIG5hdjogTmF2aWdhYmxlKTogdm9pZCB7XG5cdFx0dGhpcy5uYXZpZ2FibGVFbnRpdGllcy5hZGQobmF2TmFtZSwgbmF2KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGEgcGF0aCBmcm9tZSBvbmUgcG9pbnQgdG8gYW5vdGhlciB1c2luZyBhIHNwZWNpZmllZCBOYXZpZ2FibGUgb2JqZWN0XG5cdCAqIEBwYXJhbSBuYXZOYW1lIFRoZSBuYW1lIG9mIHRoZSByZWdpc3RlcmVkIE5hdmlnYWJsZSBvYmplY3Rcblx0ICogQHBhcmFtIGZyb21Qb3NpdGlvbiBUaGUgc3RhcnRpbmcgcG9zaXRpb24gb2YgbmF2aWdhdGlvblxuXHQgKiBAcGFyYW0gdG9Qb3NpdGlvbiBUaGUgZW5kaW5nIHBvc2l0aW9uIG9mIE5hdmlnYXRpb25cblx0ICogQHBhcmFtIGRpcmVjdCBJZiB0cnVlLCBnbyBkaXJlY3QgZnJvbSBmcm9tUG9zaXRpb24gdG8gdG9Qb3NpdGlvbiwgZG9uJ3QgdXNlIE5hdk1lc2hcblx0ICogQHJldHVybnMgQSBOYXZpZ2F0aW9uUGF0aCBjb250YWluaW5nIHRoZSByb3V0ZSB0byB0YWtlIG92ZXIgdGhlIE5hdmlnYWJsZSBlbnRpdHkgdG8gZ2V0IGJldHdlZW4gdGhlIHByb3ZpZGVkIHBvc2l0aW9ucy5cblx0ICovXG5cdGdldFBhdGgobmF2TmFtZTogc3RyaW5nLCBmcm9tUG9zaXRpb246IFZlYzIsIHRvUG9zaXRpb246IFZlYzIsIGRpcmVjdD86IGJvb2xlYW4pOiBOYXZpZ2F0aW9uUGF0aCB7XG5cdFx0bGV0IG5hdiA9IHRoaXMubmF2aWdhYmxlRW50aXRpZXMuZ2V0KG5hdk5hbWUpO1xuXHRcdHJldHVybiBuYXYuZ2V0TmF2aWdhdGlvblBhdGgoZnJvbVBvc2l0aW9uLmNsb25lKCksIHRvUG9zaXRpb24uY2xvbmUoKSwgZGlyZWN0KTtcblx0fVxufSIsImltcG9ydCBTdGFjayBmcm9tIFwiLi4vRGF0YVR5cGVzL1N0YWNrXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vTm9kZXMvR2FtZU5vZGVcIjtcblxuLyoqXG4gKiBBIHBhdGggdGhhdCBBSXMgY2FuIGZvbGxvdy4gVXNlcyBmaW5pc2hNb3ZlKCkgaW4gUGh5c2ljYWwgdG8gZGV0ZXJtaW5lIHByb2dyZXNzIG9uIHRoZSByb3V0ZVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0aW9uUGF0aCB7XG5cdC8qKiBUaGUgbmF2aWdhdGlvbiBwYXRoLCBzdG9yZWQgYXMgYSBzdGFjayBvZiBuZXh0IHBvc2l0aW9ucyAqL1xuXHRwcm90ZWN0ZWQgcGF0aDogU3RhY2s8VmVjMj47XG5cdC8qKiBUaGUgY3VycmVudCBkaXJlY3Rpb24gb2YgbW92ZW1lbnQgKi9cblx0cHJvdGVjdGVkIGN1cnJlbnRNb3ZlRGlyZWN0aW9uOiBWZWMyO1xuXHQvKiogVGhlIGRpc3RhbmNlIGEgbm9kZSBtdXN0IGJlIHRvIGEgcG9pbnQgdG8gY29uc2lkZXIgaXQgYXMgaGF2aW5nIGFycml2ZWQgKi9cblx0cHJvdGVjdGVkIGRpc3RhbmNlVGhyZXNob2xkOiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIENvbnN0cnVjdHMgYSBuZXcgTmF2aWdhdGlvblBhdGhcblx0ICogQHBhcmFtIHBhdGggVGhlIHBhdGggb2Ygbm9kZXMgdG8gdGFrZVxuXHQgKi9cblx0Y29uc3RydWN0b3IocGF0aDogU3RhY2s8VmVjMj4pe1xuXHRcdHRoaXMucGF0aCA9IHBhdGg7XG5cdFx0dGhpcy5jdXJyZW50TW92ZURpcmVjdGlvbiA9IFZlYzIuWkVSTztcblx0XHR0aGlzLmRpc3RhbmNlVGhyZXNob2xkID0gNDtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBzdGF0dXMgb2YgbmF2aWdhdGlvbiBhbG9uZyB0aGlzIE5hdmlnYXRpb25QYXRoXG5cdCAqIEByZXR1cm5zIFRydWUgaWYgdGhlIG5vZGUgaGFzIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgcGF0aCwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqL1xuXHRpc0RvbmUoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMucGF0aC5pc0VtcHR5KCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgbW92ZW1lbnQgZGlyZWN0aW9uIGluIHRoZSBjdXJyZW50IHBvc2l0aW9uIGFsb25nIHRoZSBwYXRoXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIG1vdmUgYWxvbmcgdGhlIHBhdGhcblx0ICogQHJldHVybnMgVGhlIG1vdmVtZW50IGRpcmVjdGlvbiBhcyBhIFZlYzJcblx0ICovXG5cdGdldE1vdmVEaXJlY3Rpb24obm9kZTogR2FtZU5vZGUpOiBWZWMyIHtcblx0XHQvLyBSZXR1cm4gZGlyZWN0aW9uIHRvIG5leHQgcG9pbnQgaW4gdGhlIG5hdlxuXHRcdHJldHVybiBub2RlLnBvc2l0aW9uLmRpclRvKHRoaXMucGF0aC5wZWVrKCkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZXMgdGhpcyBOYXZpZ2F0aW9uUGF0aCB0byB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgR2FtZU5vZGVcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgbW92aW5nIGFsb25nIHRoZSBwYXRoXG5cdCAqL1xuXHRoYW5kbGVQYXRoUHJvZ3Jlc3Mobm9kZTogR2FtZU5vZGUpOiB2b2lkIHtcblx0XHRpZihub2RlLnBvc2l0aW9uLmRpc3RhbmNlU3FUbyh0aGlzLnBhdGgucGVlaygpKSA8IHRoaXMuZGlzdGFuY2VUaHJlc2hvbGQqdGhpcy5kaXN0YW5jZVRocmVzaG9sZCl7XG5cdFx0XHQvLyBXZSd2ZSByZWFjaGVkIG91ciBub2RlLCBtb3ZlIG9uIHRvIHRoZSBuZXh0IGRlc3RpbmF0aW9uXG5cdFx0XHR0aGlzLnBhdGgucG9wKCk7XG5cdFx0fVxuXHR9XG5cblx0dG9TdHJpbmcoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5wYXRoLnRvU3RyaW5nKClcblx0fVxufSIsImltcG9ydCBQb3NpdGlvbkdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL1Bvc2l0aW9uR3JhcGhcIjtcbmltcG9ydCBOYXZpZ2FibGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL05hdmlnYWJsZVwiO1xuaW1wb3J0IFN0YWNrIGZyb20gXCIuLi9EYXRhVHlwZXMvU3RhY2tcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdyYXBoVXRpbHMgZnJvbSBcIi4uL1V0aWxzL0dyYXBoVXRpbHNcIjtcbmltcG9ydCBOYXZpZ2F0aW9uUGF0aCBmcm9tIFwiLi9OYXZpZ2F0aW9uUGF0aFwiO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIGEgTmF2bWVzaC4gTmF2bWVzaGVzIGFyZSBncmFwaHMgaW4gdGhlIGdhbWUgd29ybGQgYWxvbmcgd2hpY2ggbm9kZXMgY2FuIG1vdmUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5hdm1lc2ggaW1wbGVtZW50cyBOYXZpZ2FibGUge1xuXHQvKiogVGhlIGdyYXBoIG9mIHBvaW50cyBpbiB0aGUgTmF2TWVzaCAqL1xuXHRwcm90ZWN0ZWQgZ3JhcGg6IFBvc2l0aW9uR3JhcGg7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgTmF2bWVzaCBmcm9tIHRoZSBwb2ludHMgaW4gdGhlIHNwZWVjaWZpZWQgZ3JhcGhcblx0ICogQHBhcmFtIGdyYXBoIFRoZSBncmFwaCB0byBjb25zdHJ1Y3QgYSBuYXZtZXNoIGZyb21cblx0ICovXG5cdGNvbnN0cnVjdG9yKGdyYXBoOiBQb3NpdGlvbkdyYXBoKXtcblx0XHR0aGlzLmdyYXBoID0gZ3JhcGg7XG5cdH1cblxuXHQvLyBAaW1wbGVtZW50ZWRcblx0Z2V0TmF2aWdhdGlvblBhdGgoZnJvbVBvc2l0aW9uOiBWZWMyLCB0b1Bvc2l0aW9uOiBWZWMyLCBkaXJlY3Q6IGJvb2xlYW4pOiBOYXZpZ2F0aW9uUGF0aCB7XG5cdFx0bGV0IHN0YXJ0ID0gdGhpcy5nZXRDbG9zZXN0Tm9kZShmcm9tUG9zaXRpb24pO1xuXHRcdGxldCBlbmQgPSB0aGlzLmdldENsb3Nlc3ROb2RlKHRvUG9zaXRpb24pO1xuXG5cdFx0bGV0IHBhdGhTdGFjayA9IG5ldyBTdGFjazxWZWMyPih0aGlzLmdyYXBoLm51bVZlcnRpY2VzKTtcblx0XHRcblx0XHQvLyBQdXNoIHRoZSBmaW5hbCBwb3NpdGlvbiBhbmQgdGhlIGZpbmFsIHBvc2l0aW9uIGluIHRoZSBncmFwaFxuXHRcdHBhdGhTdGFjay5wdXNoKHRvUG9zaXRpb24uY2xvbmUoKSk7XG5cblx0XHRpZiAoZGlyZWN0KSB7XG5cdFx0XHRyZXR1cm4gbmV3IE5hdmlnYXRpb25QYXRoKHBhdGhTdGFjayk7XG5cdFx0fVxuXG5cdFx0cGF0aFN0YWNrLnB1c2godGhpcy5ncmFwaC5wb3NpdGlvbnNbZW5kXSk7XG5cblx0XHRsZXQgcGFyZW50ID0gR3JhcGhVdGlscy5kamlrc3RyYSh0aGlzLmdyYXBoLCBzdGFydCk7XG5cblx0XHQvLyBBZGQgYWxsIHBhcmVudHMgYWxvbmcgdGhlIHBhdGhcblx0XHRsZXQgaSA9IGVuZDtcblx0XHR3aGlsZShwYXJlbnRbaV0gIT09IC0xKXtcblx0XHRcdHBhdGhTdGFjay5wdXNoKHRoaXMuZ3JhcGgucG9zaXRpb25zW3BhcmVudFtpXV0pO1xuXHRcdFx0aSA9IHBhcmVudFtpXTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IE5hdmlnYXRpb25QYXRoKHBhdGhTdGFjayk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0aGUgY2xvc2VzdCBub2RlIGluIHRoaXMgTmF2bWVzaCB0byB0aGUgc3BlY2lmaWVkIHBvc2l0aW9uXG5cdCAqIEBwYXJhbSBwb3NpdGlvbiBUaGUgcG9zaXRpb24gdG8gcXVlcnlcblx0ICogQHJldHVybnMgVGhlIGluZGV4IG9mIHRoZSBjbG9zZXN0IG5vZGUgaW4gdGhlIE5hdm1lc2ggdG8gdGhlIHBvc2l0aW9uXG5cdCAqL1xuXHRwcm90ZWN0ZWQgZ2V0Q2xvc2VzdE5vZGUocG9zaXRpb246IFZlYzIpOiBudW1iZXIge1xuXHRcdGxldCBuID0gdGhpcy5ncmFwaC5udW1WZXJ0aWNlcztcblx0XHRsZXQgaSA9IDE7XG5cdFx0bGV0IGluZGV4ID0gMDtcblx0XHRsZXQgZGlzdCA9IHBvc2l0aW9uLmRpc3RhbmNlU3FUbyh0aGlzLmdyYXBoLnBvc2l0aW9uc1swXSk7XG5cdFx0d2hpbGUoaSA8IG4pe1xuXHRcdFx0bGV0IGQgPSBwb3NpdGlvbi5kaXN0YW5jZVNxVG8odGhpcy5ncmFwaC5wb3NpdGlvbnNbaV0pO1xuXHRcdFx0aWYoZCA8IGRpc3Qpe1xuXHRcdFx0XHRkaXN0ID0gZDtcblx0XHRcdFx0aW5kZXggPSBpO1xuXHRcdFx0fVxuXHRcdFx0aSsrO1xuXHRcdH1cblxuXHRcdHJldHVybiBpbmRleDtcblx0fVxufSIsImltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBQaHlzaWNhbCBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvUGh5c2ljYWxcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgUGh5c2ljc01hbmFnZXIgZnJvbSBcIi4vUGh5c2ljc01hbmFnZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IE9ydGhvZ29uYWxUaWxlbWFwIGZyb20gXCIuLi9Ob2Rlcy9UaWxlbWFwcy9PcnRob2dvbmFsVGlsZW1hcFwiO1xuaW1wb3J0IEFyZWFDb2xsaXNpb24gZnJvbSBcIi4uL0RhdGFUeXBlcy9QaHlzaWNzL0FyZWFDb2xsaXNpb25cIjtcbmltcG9ydCBVbmlxdWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9JbnRlcmZhY2VzL1VuaXF1ZVwiO1xuXG4vKipcbiAqIEFMR09SSVRITTpcbiAqIFx0SW4gYW4gZWZmb3J0IHRvIGtlZXAgdGhpbmdzIHNpbXBsZSBhbmQgd29ya2luZyBlZmZlY3RpdmVseSwgZWFjaCBkeW5hbWljIG5vZGUgd2lsbCByZXNvbHZlIGl0c1xuICogXHRjb2xsaXNpb25zIGNvbnNpZGVyaW5nIHRoZSByZXN0IG9mIHRoZSB3b3JsZCBhcyBzdGF0aWMuXG4gKiBcbiAqIFx0Q29sbGlzaW9uIGRldGVjdGluZyB3aWxsIGhhcHBlbiBmaXJzdC4gVGhpcyBjYW4gYmUgY29uc2lkZXJlZCBhIGJyb2FkIHBoYXNlLCBidXQgaXQgaXMgbm90IGVzcGVjaWFsbHlcbiAqIFx0ZWZmaWNpZW50LCBhcyBpdCBkb2VzIG5vdCBuZWVkIHRvIGJlIGZvciB0aGlzIGdhbWUgZW5naW5lLiBFdmVyeSBkeW5hbWljIG5vZGUgaXMgY2hlY2tlZCBhZ2FpbnN0IGV2ZXJ5XG4gKiBcdG90aGVyIG5vZGUgZm9yIGNvbGxpc2lvbiBhcmVhLiBJZiBjb2xsaXNpb24gYXJlYSBpcyBub24temVybyAobWVhbmluZyB0aGUgY3VycmVudCBub2RlIHN3ZWVwcyBpbnRvIGFub3RoZXIpLFxuICogXHRpdCBpcyBhZGRlZCB0byBhIGxpc3Qgb2YgaGl0cy5cbiAqIFxuICogXHRJTklUSUFMSVpBVElPTjpcbiAqIFx0XHQtIFBoeXNpY3MgY29uc3RhbnRzIGFyZSByZXNldFxuICogXHRcdC0gU3dlcHQgc2hhcGVzIGFyZSByZWNhbGN1bGF0ZWQuIElmIGEgbm9kZSBpc24ndCBtb3ZpbmcsIGl0IGlzIHNraXBwZWQuXG4gKiBcbiAqIFx0Q09MTElTSU9OIERFVEVDVElPTjpcbiAqIFx0XHQtIEZvciBhIG5vZGUsIGNvbGxpc2lvbiBhcmVhIHdpbGwgYmUgY2FsY3VsYXRlZCB1c2luZyB0aGUgc3dlcHQgQUFCQiBvZiB0aGUgbm9kZSBhZ2FpbnN0IGV2ZXJ5IG90aGVyIEFBQkIgaW4gYSBzdGF0aWMgc3RhdGVcbiAqIFx0XHQtIFRoZXNlIGNvbGxpc2lvbnMgd2lsbCBiZSBzb3J0ZWQgYnkgYXJlYSBpbiBkZXNjZW5kaW5nIG9yZGVyXG4gKiBcdFxuICogXHRDT0xMSVNJT04gUkVTT0xVVElPTjpcbiAqIFx0XHQtIEZvciBlYWNoIGhpdCwgdGltZSBvZiBjb2xsaXNpb24gaXMgY2FsY3VsYXRlZCB1c2luZyBhIHN3ZXB0IGxpbmUgdGhyb3VnaCB0aGUgQUFCQiBvZiB0aGUgc3RhdGljIG5vZGUgZXhwYW5kZWRcbiAqIFx0XHRcdHdpdGggbWlua293c2tpIHN1bXMgKGRpc2NyZXRlbHksIGJ1dCB0aGUgY29uY2VwdCBpcyB0aGVyZSlcbiAqIFx0XHQtIFRoZSBjb2xsaXNpb24gaXMgcmVzb2x2ZWQgYmFzZWQgb24gdGhlIG5lYXIgdGltZSBvZiB0aGUgY29sbGlzaW9uIChmcm9tIG1ldGhvZCBvZiBzZXBhcmF0ZWQgYXhlcylcbiAqIFx0XHRcdC0gWCBpcyByZXNvbHZlZCBieSBuZWFyIHgsIFkgYnkgbmVhciB5LlxuICogXHRcdFx0LSBUaGVyZSBpcyBzb21lIGZ1ZGdpbmcgdG8gYWxsb3cgZm9yIHNsaWRpbmcgYWxvbmcgd2FsbHMgb2Ygc2VwYXJhdGUgY29sbGlkZXJzLiBTb3J0aW5nIGJ5IGFyZWEgYWxzbyBoZWxwcyB3aXRoIHRoaXMuXG4gKiBcdFx0XHQtIENvcm5lciB0byBjb3JuZXIgY29sbGlzaW9ucyBhcmUgcmVzb2x2ZSB0byBmYXZvciB4LW1vdmVtZW50LiBUaGlzIGlzIGluIGNvbnNpZGVyYXRpb24gb2YgcGxhdGZvcm1lcnMsIHRvIGdpdmVcbiAqIFx0XHRcdFx0dGhlIHBsYXllciBzb21lIGhlbHAgd2l0aCBqdW1wc1xuICogXG4gKiBcdFByb3M6XG4gKiBcdFx0LSBFdmVyeXRoaW5nIGhhcHBlbnMgd2l0aCBhIGNvbnNpc3RlbnQgdGltZS4gVGhlcmUgaXMgYSBkaXN0aW5jdCBiZWZvcmUgYW5kIGFmdGVyIGZvciBlYWNoIHJlc29sdXRpb24uXG4gKiBcdFx0LSBObyBiYWNrLXRyYWNraW5nIG5lZWRzIHRvIGJlIGRvbmUuIE9uY2Ugd2UgcmVzb2x2ZSBhIG5vZGUsIGl0IGlzIGRlZmluaXRpdmVseSByZXNvbHZlZC5cbiAqIFx0XG4gKiBcdENvbnM6XG4gKiBcdFx0LSBOb2RlcyB0aGF0IGFyZSBwcm9jZXNzZWQgZWFybHkgaGF2ZSBtb3ZlbWVudCBwcmlvcml0eSBvdmVyIG90aGVyIG5vZGVzLiBUaGlzIGNhbiBsZWFkIHRvIHNvbWUgdW5kZXNpcmFibGUgaW50ZXJhY3Rpb25zLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNpY1BoeXNpY3NNYW5hZ2VyIGV4dGVuZHMgUGh5c2ljc01hbmFnZXIge1xuXG5cdC8qKiBUaGUgYXJyYXkgb2Ygc3RhdGljIG5vZGVzICovXG5cdHByb3RlY3RlZCBzdGF0aWNOb2RlczogQXJyYXk8UGh5c2ljYWw+O1xuXG5cdC8qKiBUaGUgYXJyYXkgb2YgZHluYW1pYyBub2RlcyAqL1xuXHRwcm90ZWN0ZWQgZHluYW1pY05vZGVzOiBBcnJheTxQaHlzaWNhbD47XG5cblx0LyoqIFRoZSBhcnJheSBvZiB0aWxlbWFwcyAqL1xuXHRwcm90ZWN0ZWQgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+O1xuXG5cdC8qKiBBbiBhcnJheSBvZiB0aGUgY29sbGlzaW9uIG1hc2tzIGZvciBlYWNoIGdyb3VwICovXG5cdHByb3RlY3RlZCBjb2xsaXNpb25NYXNrczogQXJyYXk8bnVtYmVyPjtcblxuXHRjb25zdHJ1Y3RvcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KXtcblx0XHRzdXBlcigpO1xuXHRcdHRoaXMuc3RhdGljTm9kZXMgPSBuZXcgQXJyYXkoKTtcblx0XHR0aGlzLmR5bmFtaWNOb2RlcyA9IG5ldyBBcnJheSgpO1xuXHRcdHRoaXMudGlsZW1hcHMgPSBuZXcgQXJyYXkoKTtcblx0XHR0aGlzLmNvbGxpc2lvbk1hc2tzID0gbmV3IEFycmF5KDMyKTtcblxuXHRcdC8vIFBhcnNlIG9wdGlvbnNcblx0XHR0aGlzLnBhcnNlT3B0aW9ucyhvcHRpb25zKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJzZXMgdGhlIG9wdGlvbnMgZm9yIGNvbnN0cnVjdGluZyB0aGUgcGh5c2ljcyBtYW5hZ2VyXG5cdCAqIEBwYXJhbSBvcHRpb25zIEEgcmVjb3JkIG9mIG9wdGlvbnNcblx0ICovXG5cdHByb3RlY3RlZCBwYXJzZU9wdGlvbnMob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdGlmKG9wdGlvbnMuZ3JvdXBOYW1lcyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuY29sbGlzaW9ucyAhPT0gdW5kZWZpbmVkKXtcblx0XHRcdGZvcihsZXQgaSA9IDA7IGkgPCBvcHRpb25zLmdyb3VwTmFtZXMubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHRsZXQgZ3JvdXAgPSBvcHRpb25zLmdyb3VwTmFtZXNbaV07XG5cblx0XHRcdFx0Ly8gUmVnaXN0ZXIgdGhlIGdyb3VwIG5hbWUgYW5kIG51bWJlclxuXHRcdFx0XHR0aGlzLmdyb3VwTmFtZXNbaV0gPSBncm91cDtcblxuXHRcdFx0XHR0aGlzLmdyb3VwTWFwLnNldChncm91cCwgMSA8PCBpKTtcblxuXHRcdFx0XHRsZXQgY29sbGlzaW9uTWFzayA9IDA7XG5cblx0XHRcdFx0Zm9yKGxldCBqID0gMDsgaiA8IG9wdGlvbnMuY29sbGlzaW9uc1tpXS5sZW5ndGg7IGorKyl7XG5cdFx0XHRcdFx0aWYob3B0aW9ucy5jb2xsaXNpb25zW2ldW2pdKXtcblx0XHRcdFx0XHRcdGNvbGxpc2lvbk1hc2sgfD0gMSA8PCBqO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMuY29sbGlzaW9uTWFza3NbaV0gPSBjb2xsaXNpb25NYXNrO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHRyZWdpc3Rlck9iamVjdChub2RlOiBQaHlzaWNhbCk6IHZvaWQge1xuXHRcdGlmKG5vZGUuaXNTdGF0aWMpe1xuXHRcdFx0Ly8gU3RhdGljIGFuZCBub3QgY29sbGlkYWJsZVxuXHRcdFx0dGhpcy5zdGF0aWNOb2Rlcy5wdXNoKG5vZGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBEeW5hbWljIGFuZCBub3QgY29sbGlkYWJsZVxuXHRcdFx0dGhpcy5keW5hbWljTm9kZXMucHVzaChub2RlKTtcblx0XHR9XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0ZGVyZWdpc3Rlck9iamVjdChub2RlOiBQaHlzaWNhbCk6IHZvaWQge1xuXHRcdGlmKG5vZGUuaXNTdGF0aWMpe1xuXHRcdFx0Ly8gUmVtb3ZlIHRoZSBub2RlIGZyb20gdGhlIHN0YXRpYyBsaXN0XG5cdFx0XHRjb25zdCBpbmRleCA9IHRoaXMuc3RhdGljTm9kZXMuaW5kZXhPZihub2RlKTtcblx0XHRcdHRoaXMuc3RhdGljTm9kZXMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gUmVtb3ZlIHRoZSBub2RlIGZyb20gdGhlIGR5bmFtaWMgbGlzdFxuXHRcdFx0Y29uc3QgaW5kZXggPSB0aGlzLmR5bmFtaWNOb2Rlcy5pbmRleE9mKG5vZGUpO1xuXHRcdFx0dGhpcy5keW5hbWljTm9kZXMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0cmVnaXN0ZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkIHtcblx0XHR0aGlzLnRpbGVtYXBzLnB1c2godGlsZW1hcCk7XG5cdH1cblxuXHQvLyBAb3ZlcnJpZGVcblx0ZGVyZWdpc3RlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQge1xuXHRcdGNvbnN0IGluZGV4ID0gdGhpcy50aWxlbWFwcy5pbmRleE9mKHRpbGVtYXApO1xuXHRcdHRoaXMudGlsZW1hcHMuc3BsaWNlKGluZGV4LCAxKTtcblx0fVxuXG5cdC8vIEBvdmVycmlkZVxuXHR1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcblx0XHRmb3IobGV0IG5vZGUgb2YgdGhpcy5keW5hbWljTm9kZXMpe1xuXHRcdFx0LyotLS0tLS0tLS0tIElOSVRJQUxJWkFUSU9OIFBIQVNFIC0tLS0tLS0tLS0qL1xuXHRcdFx0Ly8gQ2xlYXIgZnJhbWUgZGVwZW5kZW50IGJvb2xlYW4gdmFsdWVzIGZvciBlYWNoIG5vZGVcblx0XHRcdG5vZGUub25Hcm91bmQgPSBmYWxzZTtcblx0XHRcdG5vZGUub25DZWlsaW5nID0gZmFsc2U7XG5cdFx0XHRub2RlLm9uV2FsbCA9IGZhbHNlO1xuXHRcdFx0bm9kZS5jb2xsaWRlZFdpdGhUaWxlbWFwID0gZmFsc2U7XG5cdFx0XHRub2RlLmlzQ29sbGlkaW5nID0gZmFsc2U7XG5cblx0XHRcdC8vIElmIHRoaXMgbm9kZSBpcyBub3QgYWN0aXZlLCBkb24ndCBwcm9jZXNzIGl0XG5cdFx0XHRpZighbm9kZS5hY3RpdmUpe1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVXBkYXRlIHRoZSBzd2VwdCBzaGFwZXMgb2YgZWFjaCBub2RlXG5cdFx0XHRpZihub2RlLm1vdmluZyl7XG5cdFx0XHRcdC8vIElmIG1vdmluZywgcmVmbGVjdCB0aGF0IGluIHRoZSBzd2VwdCBzaGFwZVxuXHRcdFx0XHRub2RlLnN3ZXB0UmVjdC5zd2VlcChub2RlLl92ZWxvY2l0eSwgbm9kZS5jb2xsaXNpb25TaGFwZS5jZW50ZXIsIG5vZGUuY29sbGlzaW9uU2hhcGUuaGFsZlNpemUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gSWYgb3VyIG5vZGUgaXNuJ3QgbW92aW5nLCBkb24ndCBib3RoZXIgdG8gY2hlY2sgaXQgKG90aGVyIG5vZGVzIHdpbGwgZGV0ZWN0IGlmIHRoZXkgcnVuIGludG8gaXQpXG5cdFx0XHRcdG5vZGUuX3ZlbG9jaXR5Lnplcm8oKTtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cblx0XHRcdC8qLS0tLS0tLS0tLSBERVRFQ1RJT04gUEhBU0UgLS0tLS0tLS0tLSovXG5cdFx0XHQvLyBHYXRoZXIgYSBzZXQgb2Ygb3ZlcmxhcHNcblx0XHRcdGxldCBvdmVybGFwcyA9IG5ldyBBcnJheTxBcmVhQ29sbGlzaW9uPigpO1xuXG5cdFx0XHRsZXQgZ3JvdXBJbmRleCA9IG5vZGUuZ3JvdXAgPT09IC0xID8gLTEgOiBNYXRoLmxvZzIobm9kZS5ncm91cCk7XG5cblx0XHRcdC8vIEZpcnN0LCBjaGVjayB0aGlzIG5vZGUgYWdhaW5zdCBldmVyeSBzdGF0aWMgbm9kZSAob3JkZXIgZG9lc24ndCBhY3R1YWxseSBtYXR0ZXIgaGVyZSwgc2luY2Ugd2Ugc29ydCBhbnl3YXlzKVxuXHRcdFx0Zm9yKGxldCBvdGhlciBvZiB0aGlzLnN0YXRpY05vZGVzKXtcblx0XHRcdFx0Ly8gSWdub3JlIGluYWN0aXZlIG5vZGVzXG5cdFx0XHRcdGlmKCFvdGhlci5hY3RpdmUpIGNvbnRpbnVlO1xuXG5cdFx0XHRcdGxldCBjb2xsaWRlciA9IG90aGVyLmNvbGxpc2lvblNoYXBlLmdldEJvdW5kaW5nUmVjdCgpO1xuXHRcdFx0XHRsZXQgYXJlYSA9IG5vZGUuc3dlcHRSZWN0Lm92ZXJsYXBBcmVhKGNvbGxpZGVyKTtcblx0XHRcdFx0aWYoYXJlYSA+IDApe1xuXHRcdFx0XHRcdC8vIFdlIGhhZCBhIGNvbGxpc2lvblxuXHRcdFx0XHRcdG92ZXJsYXBzLnB1c2gobmV3IEFyZWFDb2xsaXNpb24oYXJlYSwgY29sbGlkZXIsIG90aGVyLCBcIkdhbWVOb2RlXCIsIG51bGwpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaGVuLCBjaGVjayBpdCBhZ2FpbnN0IGV2ZXJ5IGR5bmFtaWMgbm9kZVxuXHRcdFx0Zm9yKGxldCBvdGhlciBvZiB0aGlzLmR5bmFtaWNOb2Rlcyl7XG5cdFx0XHRcdC8vIElnbm9yZSBvdXJzZWx2ZXNcblx0XHRcdFx0aWYobm9kZSA9PT0gb3RoZXIpIGNvbnRpbnVlO1xuXG5cdFx0XHRcdC8vIElnbm9yZSBpbmFjdGl2ZSBub2Rlc1xuXHRcdFx0XHRpZighb3RoZXIuYWN0aXZlKSBjb250aW51ZTtcblxuXHRcdFx0XHRsZXQgY29sbGlkZXIgPSBvdGhlci5jb2xsaXNpb25TaGFwZS5nZXRCb3VuZGluZ1JlY3QoKTtcblx0XHRcdFx0bGV0IGFyZWEgPSBub2RlLnN3ZXB0UmVjdC5vdmVybGFwQXJlYShjb2xsaWRlcik7XG5cdFx0XHRcdGlmKGFyZWEgPiAwKXtcblx0XHRcdFx0XHQvLyBXZSBoYWQgYSBjb2xsaXNpb25cblx0XHRcdFx0XHRvdmVybGFwcy5wdXNoKG5ldyBBcmVhQ29sbGlzaW9uKGFyZWEsIGNvbGxpZGVyLCBvdGhlciwgXCJHYW1lTm9kZVwiLCBudWxsKSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTGFzdGx5LCBnYXRoZXIgYSBzZXQgb2YgQUFCQnMgZnJvbSB0aGUgdGlsZW1hcC5cblx0XHRcdC8vIFRoaXMgc3RlcCBpbnZvbHZlcyB0aGUgbW9zdCBleHRyYSB3b3JrLCBzbyBpdCBpcyBhYnN0cmFjdGVkIGludG8gYSBtZXRob2Rcblx0XHRcdGZvcihsZXQgdGlsZW1hcCBvZiB0aGlzLnRpbGVtYXBzKXtcblx0XHRcdFx0Ly8gSWdub3JlIGluYWN0aXZlIHRpbGVtYXBzXG5cdFx0XHRcdGlmKCF0aWxlbWFwLmFjdGl2ZSkgY29udGludWU7XG5cblx0XHRcdFx0aWYodGlsZW1hcCBpbnN0YW5jZW9mIE9ydGhvZ29uYWxUaWxlbWFwKXtcblx0XHRcdFx0XHR0aGlzLmNvbGxpZGVXaXRoT3J0aG9nb25hbFRpbGVtYXAobm9kZSwgdGlsZW1hcCwgb3ZlcmxhcHMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNvcnQgdGhlIG92ZXJsYXBzIGJ5IGFyZWFcblx0XHRcdG92ZXJsYXBzID0gb3ZlcmxhcHMuc29ydCgoYSwgYikgPT4gYi5hcmVhIC0gYS5hcmVhKTtcblxuXHRcdFx0Ly8gS2VlcCB0cmFjayBvZiBoaXRzIHRvIHVzZSBsYXRlclxuXHRcdFx0bGV0IGhpdHMgPSBbXTtcblxuXHRcdFx0LyotLS0tLS0tLS0tIFJFU09MVVRJT04gUEhBU0UgLS0tLS0tLS0tLSovXG5cdFx0XHQvLyBGb3IgZXZlcnkgb3ZlcmxhcCwgZGV0ZXJtaW5lIGlmIHdlIG5lZWQgdG8gY29sbGlkZSB3aXRoIGl0IGFuZCB3aGVuXG5cdFx0XHRmb3IobGV0IG92ZXJsYXAgb2Ygb3ZlcmxhcHMpe1xuXHRcdFx0XHQvLyBJZ25vcmUgbm9kZXMgd2UgZG9uJ3QgaW50ZXJhY3Qgd2l0aFxuXHRcdFx0XHRpZiggZ3JvdXBJbmRleCAhPT0gLTEgJiYgb3ZlcmxhcC5vdGhlci5ncm91cCAhPT0gLTEgJiYgKCh0aGlzLmNvbGxpc2lvbk1hc2tzW2dyb3VwSW5kZXhdICYgb3ZlcmxhcC5vdGhlci5ncm91cCkgPT09IDApICkgY29udGludWU7XG5cblx0XHRcdFx0Ly8gRG8gYSBzd2VwdCBsaW5lIHRlc3Qgb24gdGhlIHN0YXRpYyBBQUJCIHdpdGggdGhpcyBBQUJCIHNpemUgYXMgcGFkZGluZyAodGhpcyBpcyBiYXNpY2FsbHkgdXNpbmcgYSBtaW5rb3dza2kgc3VtISlcblx0XHRcdFx0Ly8gU3RhcnQgdGhlIHN3ZWVwIGF0IHRoZSBwb3NpdGlvbiBvZiB0aGlzIG5vZGUgd2l0aCBhIGRlbHRhIG9mIF92ZWxvY2l0eVxuXHRcdFx0XHRjb25zdCBwb2ludCA9IG5vZGUuY29sbGlzaW9uU2hhcGUuY2VudGVyO1xuXHRcdFx0XHRjb25zdCBkZWx0YSA9IG5vZGUuX3ZlbG9jaXR5O1xuXHRcdFx0XHRjb25zdCBwYWRkaW5nID0gbm9kZS5jb2xsaXNpb25TaGFwZS5oYWxmU2l6ZTtcblx0XHRcdFx0Y29uc3Qgb3RoZXJBQUJCID0gb3ZlcmxhcC5jb2xsaWRlcjtcblxuXG5cdFx0XHRcdGNvbnN0IGhpdCA9IG90aGVyQUFCQi5pbnRlcnNlY3RTZWdtZW50KG5vZGUuY29sbGlzaW9uU2hhcGUuY2VudGVyLCBub2RlLl92ZWxvY2l0eSwgbm9kZS5jb2xsaXNpb25TaGFwZS5oYWxmU2l6ZSk7XG5cblx0XHRcdFx0b3ZlcmxhcC5oaXQgPSBoaXQ7XG5cblx0XHRcdFx0aWYoaGl0ICE9PSBudWxsKXtcblx0XHRcdFx0XHRoaXRzLnB1c2goaGl0KTtcblxuXHRcdFx0XHRcdC8vIFdlIGdvdCBhIGhpdCwgcmVzb2x2ZSB3aXRoIHRoZSB0aW1lIGluc2lkZSBvZiB0aGUgaGl0XG5cdFx0XHRcdFx0bGV0IHRuZWFyeCA9IGhpdC5uZWFyVGltZXMueDtcblx0XHRcdFx0XHRsZXQgdG5lYXJ5ID0gaGl0Lm5lYXJUaW1lcy55O1xuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgZWRnZSBjbGlwcGluZyAoZWRnZSBvdmVybGFwcyBkb24ndCBjb3VudCwgb25seSBhcmVhIG92ZXJsYXBzKVxuXHRcdFx0XHRcdC8vIEltcG9ydGFudGx5IGRvbid0IGFsbG93IGJvdGggY2FzZXMgdG8gYmUgdHJ1ZS4gVGhlbiB3ZSBjbGlwIHRocm91Z2ggY29ybmVycy4gRmF2b3IgeCB0byBoZWxwIHBsYXllcnMgbGFuZCBqdW1wc1xuXHRcdFx0XHRcdGlmKHRuZWFyeCA8IDEuMCAmJiAocG9pbnQueSA9PT0gb3RoZXJBQUJCLnRvcCAtIHBhZGRpbmcueSB8fCBwb2ludC55ID09PSBvdGhlckFBQkIuYm90dG9tICsgcGFkZGluZy55KSAmJiBkZWx0YS54ICE9PSAwKSB7XG5cdFx0XHRcdFx0XHR0bmVhcnggPSAxLjA7XG5cdFx0XHRcdFx0fSBlbHNlIGlmKHRuZWFyeSA8IDEuMCAmJiAocG9pbnQueCA9PT0gb3RoZXJBQUJCLmxlZnQgLSBwYWRkaW5nLnggfHwgcG9pbnQueCA9PT0gb3RoZXJBQUJCLnJpZ2h0ICsgcGFkZGluZy54KSAmJiBkZWx0YS55ICE9PSAwKSB7XG5cdFx0XHRcdFx0XHR0bmVhcnkgPSAxLjA7XG5cdFx0XHRcdFx0fVxuXG5cblx0XHRcdFx0XHRpZihoaXQubmVhclRpbWVzLnggPj0gMCAmJiBoaXQubmVhclRpbWVzLnggPCAxKXtcblx0XHRcdFx0XHRcdC8vIEFueSB0aWxlbWFwIG9iamVjdHMgdGhhdCBtYWRlIGl0IGhlcmUgYXJlIGNvbGxpZGFibGVcblx0XHRcdFx0XHRcdGlmKG92ZXJsYXAudHlwZSA9PT0gXCJUaWxlbWFwXCIgfHwgb3ZlcmxhcC5vdGhlci5pc0NvbGxpZGFibGUpe1xuXHRcdFx0XHRcdFx0XHRub2RlLl92ZWxvY2l0eS54ID0gbm9kZS5fdmVsb2NpdHkueCAqIHRuZWFyeDtcblx0XHRcdFx0XHRcdFx0bm9kZS5pc0NvbGxpZGluZyA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYoaGl0Lm5lYXJUaW1lcy55ID49IDAgJiYgaGl0Lm5lYXJUaW1lcy55IDwgMSl7XG5cdFx0XHRcdFx0XHQvLyBBbnkgdGlsZW1hcCBvYmplY3RzIHRoYXQgbWFkZSBpdCBoZXJlIGFyZSBjb2xsaWRhYmxlXG5cdFx0XHRcdFx0XHRpZihvdmVybGFwLnR5cGUgPT09IFwiVGlsZW1hcFwiIHx8IG92ZXJsYXAub3RoZXIuaXNDb2xsaWRhYmxlKXtcblx0XHRcdFx0XHRcdFx0bm9kZS5fdmVsb2NpdHkueSA9IG5vZGUuX3ZlbG9jaXR5LnkgKiB0bmVhcnk7XG5cdFx0XHRcdFx0XHRcdG5vZGUuaXNDb2xsaWRpbmcgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvKi0tLS0tLS0tLS0gSU5GT1JNQVRJT04vVFJJR0dFUiBQSEFTRSAtLS0tLS0tLS0tKi9cblx0XHRcdC8vIENoZWNrIGlmIHdlIGVuZGVkIHVwIG9uIHRoZSBncm91bmQsIGNlaWxpbmcgb3Igd2FsbFxuXHRcdFx0Ly8gQWxzbyBjaGVjayBmb3IgdHJpZ2dlcnNcblx0XHRcdGZvcihsZXQgb3ZlcmxhcCBvZiBvdmVybGFwcyl7XG5cdFx0XHRcdC8vIENoZWNrIGZvciBhIHRyaWdnZXIuIElmIHdlIGNhcmUgYWJvdXQgdGhlIHRyaWdnZXIsIHJlYWN0XG5cdFx0XHRcdGlmKG92ZXJsYXAub3RoZXIuaXNUcmlnZ2VyICYmIChvdmVybGFwLm90aGVyLnRyaWdnZXJNYXNrICYgbm9kZS5ncm91cCkgJiYgbm9kZS5ncm91cCAhPSAtMSl7XG5cdFx0XHRcdFx0Ly8gR2V0IHRoZSBiaXQgdGhhdCB0aGlzIGdyb3VwIGlzIHJlcHJlc2VudGVkIGJ5XG5cdFx0XHRcdFx0bGV0IGluZGV4ID0gTWF0aC5mbG9vcihNYXRoLmxvZzIobm9kZS5ncm91cCkpO1xuXG5cdFx0XHRcdFx0Ly8gRXh0cmFjdCB0aGUgdHJpZ2dlckVudGVyIGV2ZW50IG5hbWVcblx0XHRcdFx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KG92ZXJsYXAub3RoZXIudHJpZ2dlckVudGVyc1tpbmRleF0sIHtcblx0XHRcdFx0XHRcdG5vZGU6ICg8R2FtZU5vZGU+bm9kZSkuaWQsXG5cdFx0XHRcdFx0XHRvdGhlcjogKDxHYW1lTm9kZT5vdmVybGFwLm90aGVyKS5pZFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gSWdub3JlIGNvbGxpc2lvbiBzaWRlcyBmb3Igbm9kZXMgd2UgZG9uJ3QgaW50ZXJhY3Qgd2l0aFxuXHRcdFx0XHRpZiggZ3JvdXBJbmRleCAhPT0gLTEgJiYgb3ZlcmxhcC5vdGhlci5ncm91cCAhPT0gLTEgJiYgKCh0aGlzLmNvbGxpc2lvbk1hc2tzW2dyb3VwSW5kZXhdICYgb3ZlcmxhcC5vdGhlci5ncm91cCkgPT09IDApKSBjb250aW51ZTtcblxuXHRcdFx0XHQvLyBPbmx5IGNoZWNrIGZvciBkaXJlY3Rpb24gaWYgdGhlIG92ZXJsYXAgd2FzIGNvbGxpZGFibGVcblx0XHRcdFx0aWYob3ZlcmxhcC50eXBlID09PSBcIlRpbGVtYXBcIiB8fCBvdmVybGFwLm90aGVyLmlzQ29sbGlkYWJsZSl7XG5cdFx0XHRcdFx0bGV0IGNvbGxpc2lvblNpZGUgPSBvdmVybGFwLmNvbGxpZGVyLnRvdWNoZXNBQUJCV2l0aG91dENvcm5lcnMobm9kZS5jb2xsaXNpb25TaGFwZS5nZXRCb3VuZGluZ1JlY3QoKSk7XG5cdFx0XHRcdFx0aWYoY29sbGlzaW9uU2lkZSAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0XHQvLyBJZiB3ZSB0b3VjaCwgbm90IGluY2x1ZGluZyBjb3JuZXIgY2FzZXMsIGNoZWNrIHRoZSBjb2xsaXNpb24gbm9ybWFsXG5cdFx0XHRcdFx0XHRpZihvdmVybGFwLmhpdCAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0XHRcdC8vIElmIHdlIGhpdCBhIHRpbGVtYXAsIGtlZXAgdHJhY2sgb2YgaXRcblx0XHRcdFx0XHRcdFx0aWYob3ZlcmxhcC50eXBlID09IFwiVGlsZW1hcFwiKXtcblx0XHRcdFx0XHRcdFx0XHRub2RlLmNvbGxpZGVkV2l0aFRpbGVtYXAgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYoY29sbGlzaW9uU2lkZS55ID09PSAtMSl7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gTm9kZSBpcyBvbiB0b3Agb2Ygb3ZlcmxhcCwgc28gb25Hcm91bmRcblx0XHRcdFx0XHRcdFx0XHRub2RlLm9uR3JvdW5kID0gdHJ1ZTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmKGNvbGxpc2lvblNpZGUueSA9PT0gMSl7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gTm9kZSBpcyBvbiBib3R0b20gb2Ygb3ZlcmxhcCwgc28gb25DZWlsaW5nXG5cdFx0XHRcdFx0XHRcdFx0bm9kZS5vbkNlaWxpbmcgPSB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdC8vIE5vZGUgd2Fzbid0IHRvdWNoaW5nIG9uIHksIHNvIGl0IGlzIHRvdWNoaW5nIG9uIHhcblx0XHRcdFx0XHRcdFx0XHRub2RlLm9uV2FsbCA9IHRydWU7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVzb2x2ZSB0aGUgY29sbGlzaW9uIHdpdGggdGhlIG5vZGUsIGFuZCBtb3ZlIGl0XG5cdFx0XHRub2RlLmZpbmlzaE1vdmUoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBhIGNvbGxpc2lvbiBiZXR3ZWVuIHRoaXMgbm9kZSBhbmQgYW4gb3J0aG9nb25hbCB0aWxlbWFwXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlXG5cdCAqIEBwYXJhbSB0aWxlbWFwIFRoZSB0aWxlbWFwIHRoZSBub2RlIG1heSBiZSBjb2xsaWRpbmcgd2l0aFxuXHQgKiBAcGFyYW0gb3ZlcmxhcHMgVGhlIGxpc3Qgb2Ygb3ZlcmxhcHNcblx0ICovXG5cdHByb3RlY3RlZCBjb2xsaWRlV2l0aE9ydGhvZ29uYWxUaWxlbWFwKG5vZGU6IFBoeXNpY2FsLCB0aWxlbWFwOiBPcnRob2dvbmFsVGlsZW1hcCwgb3ZlcmxhcHM6IEFycmF5PEFyZWFDb2xsaXNpb24+KTogdm9pZCB7XG5cdFx0Ly8gR2V0IHRoZSBtaW4gYW5kIG1heCB4IGFuZCB5IGNvb3JkaW5hdGVzIG9mIHRoZSBtb3Zpbmcgbm9kZVxuXHRcdGxldCBtaW4gPSBuZXcgVmVjMihub2RlLnN3ZXB0UmVjdC5sZWZ0LCBub2RlLnN3ZXB0UmVjdC50b3ApO1xuXHRcdGxldCBtYXggPSBuZXcgVmVjMihub2RlLnN3ZXB0UmVjdC5yaWdodCwgbm9kZS5zd2VwdFJlY3QuYm90dG9tKTtcblxuXHRcdC8vIENvbnZlcnQgdGhlIG1pbi9tYXggeC95IHRvIHRoZSBtaW4gYW5kIG1heCByb3cvY29sIGluIHRoZSB0aWxlbWFwIGFycmF5XG5cdFx0bGV0IG1pbkluZGV4ID0gdGlsZW1hcC5nZXRDb2xSb3dBdChtaW4pO1xuXHRcdGxldCBtYXhJbmRleCA9IHRpbGVtYXAuZ2V0Q29sUm93QXQobWF4KTtcblxuXHRcdGxldCB0aWxlU2l6ZSA9IHRpbGVtYXAuZ2V0VGlsZVNpemUoKTtcblxuXHRcdC8vIExvb3Agb3ZlciBhbGwgcG9zc2libGUgdGlsZXMgKHdoaWNoIGlzbid0IG1hbnkgaW4gdGhlIHNjb3BlIG9mIHRoZSB2ZWxvY2l0eSBwZXIgZnJhbWUpXG5cdFx0Zm9yKGxldCBjb2wgPSBtaW5JbmRleC54OyBjb2wgPD0gbWF4SW5kZXgueDsgY29sKyspe1xuXHRcdFx0Zm9yKGxldCByb3cgPSBtaW5JbmRleC55OyByb3cgPD0gbWF4SW5kZXgueTsgcm93Kyspe1xuXHRcdFx0XHRpZih0aWxlbWFwLmlzVGlsZUNvbGxpZGFibGUoY29sLCByb3cpKXtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIHBvc2l0aW9uIG9mIHRoaXMgdGlsZVxuXHRcdFx0XHRcdGxldCB0aWxlUG9zID0gbmV3IFZlYzIoY29sICogdGlsZVNpemUueCArIHRpbGVTaXplLngvMiwgcm93ICogdGlsZVNpemUueSArIHRpbGVTaXplLnkvMik7XG5cblx0XHRcdFx0XHQvLyBDcmVhdGUgYSBuZXcgY29sbGlkZXIgZm9yIHRoaXMgdGlsZVxuXHRcdFx0XHRcdGxldCBjb2xsaWRlciA9IG5ldyBBQUJCKHRpbGVQb3MsIHRpbGVTaXplLnNjYWxlZCgxLzIpKTtcblxuXHRcdFx0XHRcdC8vIENhbGN1bGF0ZSBjb2xsaXNpb24gYXJlYSBiZXR3ZWVuIHRoZSBub2RlIGFuZCB0aGUgdGlsZVxuXHRcdFx0XHRcdGxldCBhcmVhID0gbm9kZS5zd2VwdFJlY3Qub3ZlcmxhcEFyZWEoY29sbGlkZXIpO1xuXHRcdFx0XHRcdGlmKGFyZWEgPiAwKXtcblx0XHRcdFx0XHRcdC8vIFdlIGhhZCBhIGNvbGxpc2lvblxuXHRcdFx0XHRcdFx0b3ZlcmxhcHMucHVzaChuZXcgQXJlYUNvbGxpc2lvbihhcmVhLCBjb2xsaWRlciwgdGlsZW1hcCwgXCJUaWxlbWFwXCIsIG5ldyBWZWMyKGNvbCwgcm93KSkpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFBoeXNpY2FsIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9QaHlzaWNhbFwiO1xuXG4vKipcbiAqIEFuIGFic3RyYWN0IHBoeXNpY3MgbWFuYWdlci5cbiAqIFRoaXMgY2xhc3MgZXhwb3NlcyBmdW5jdGlvbnMgZm9yIHN1YmNsYXNzZXMgdG8gaW1wbGVtZW50IHRoYXQgc2hvdWxkIGFsbG93IGZvciBhIHdvcmtpbmcgcGh5c2ljcyBzeXN0ZW0gdG8gYmUgY3JlYXRlZC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUGh5c2ljc01hbmFnZXIgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcblx0LyoqIFRoZSBldmVudCByZWNlaXZlciBmb3IgdGhlIHBoeXNpY3Mgc3lzdGVtICovXG5cdHByb3RlY3RlZCByZWNlaXZlcjogUmVjZWl2ZXI7XG5cdC8qKiBUaGUgZXZlbnQgZW1pdHRlciBmb3IgdGhlIHBoeXNpY3Mgc3lzdGVtICovXG5cdHByb3RlY3RlZCBlbWl0dGVyOiBFbWl0dGVyO1xuXG5cdC8qKiBNYXBzIGxheWVyIG5hbWVzIHRvIG51bWJlcnMgKi9cblx0cHJvdGVjdGVkIGdyb3VwTWFwOiBNYXA8bnVtYmVyPjtcblxuXHQvKiogTWFwcyBsYXllciBudW1iZXJzIHRvIG5hbWVzICovXG5cdHByb3RlY3RlZCBncm91cE5hbWVzOiBBcnJheTxzdHJpbmc+O1xuXG5cdC8qKiBUaGUgZGVmYXVsdCBncm91cCBuYW1lICovXG5cdHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9HUk9VUDogc3RyaW5nID0gXCJEZWZhdWx0XCI7XG5cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG5cdFx0dGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblxuXHRcdC8vIFRoZSBjcmVhdGlvbiBhbmQgaW1wbGVtZW50YXRpb24gb2YgbGF5ZXJzIGlzIGRlZmVycmVkIHRvIHRoZSBzdWJjbGFzc1xuXHRcdHRoaXMuZ3JvdXBNYXAgPSBuZXcgTWFwKCk7XG5cdFx0dGhpcy5ncm91cE5hbWVzID0gbmV3IEFycmF5KCk7XG5cdH1cblxuXHRkZXN0cm95KCk6IHZvaWQge1xuXHRcdHRoaXMucmVjZWl2ZXIuZGVzdHJveSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVycyBhIGdhbWVub2RlIHdpdGggdGhpcyBwaHlzaWNzIG1hbmFnZXJcblx0ICogQHBhcmFtIG9iamVjdCBUaGUgb2JqZWN0IHRvIHJlZ2lzdGVyXG5cdCAqL1xuXHRhYnN0cmFjdCByZWdpc3Rlck9iamVjdChvYmplY3Q6IFBoeXNpY2FsKTogdm9pZDtcblxuXG5cdC8qKlxuXHQgKiBSZW1vdmVzIHJlZmVyZW5jZXMgdG8gdGhpcyBvYmplY3QgZnJvbSB0aGUgcGh5c2ljcyBtYW5hZ2VyclxuXHQgKiBAcGFyYW0gb2JqZWN0IFRoZSBvYmplY3QgdG8gZGVyZWdpc3RlclxuXHQgKi9cblx0YWJzdHJhY3QgZGVyZWdpc3Rlck9iamVjdChvYmplY3Q6IFBoeXNpY2FsKTogdm9pZDtcblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgdGlsZW1hcCB3aXRoIHRoaXMgcGh5c2ljcyBtYW5hZ2VyXG5cdCAqIEBwYXJhbSB0aWxlbWFwIFRoZSB0aWxlbWFwIHRvIHJlZ2lzdGVyXG5cdCAqL1xuXHRhYnN0cmFjdCByZWdpc3RlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgcmVmZXJlbmNlcyB0byB0aGlzIHRpbGVtYXAgZnJvbSB0aGUgcGh5c2ljcyBtYW5hZ2VyclxuXHQgKiBAcGFyYW0gdGlsZW1hcCBUaGUgb2JqZWN0IHRvIGRlcmVnaXN0ZXJcblx0ICovXG5cdGFic3RyYWN0IGRlcmVnaXN0ZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkO1xuXG5cdGFic3RyYWN0IHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHBoeXNpY3MgbGF5ZXIgb2YgdGhlIEdhbWVOb2RlXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBHYW1lTm9kZVxuXHQgKiBAcGFyYW0gZ3JvdXAgVGhlIGdyb3VwIHRoYXQgdGhlIEdhbWVOb2RlIHNob3VsZCBiZSBvblxuXHQgKi9cblx0c2V0R3JvdXAobm9kZTogUGh5c2ljYWwsIGdyb3VwOiBzdHJpbmcpOiB2b2lkIHtcblx0XHRub2RlLmdyb3VwID0gdGhpcy5ncm91cE1hcC5nZXQoZ3JvdXApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHJpZXZlcyB0aGUgbGF5ZXIgbnVtYmVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgbmFtZVxuXHQgKiBAcGFyYW0gbGF5ZXIgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG5cdCAqIEByZXR1cm5zIFRoZSBsYXllciBudW1iZXIsIG9yIDAgaWYgdGhlcmUgaXMgbm90IGEgbGF5ZXIgd2l0aCB0aGF0IG5hbWUgcmVnaXN0ZXJlZFxuXHQgKi9cblx0Z2V0R3JvdXBOdW1iZXIoZ3JvdXA6IHN0cmluZyk6IG51bWJlciB7XG5cdFx0aWYodGhpcy5ncm91cE1hcC5oYXMoZ3JvdXApKXtcblx0XHRcdHJldHVybiB0aGlzLmdyb3VwTWFwLmdldChncm91cCk7XG5cdFx0fSBlbHNle1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYWxsIGdyb3VwIG5hbWVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgbnVtYmVyIHByb3ZpZGVkXG5cdCAqIEBwYXJhbSBncm91cHMgQSBtYXNrIG9mIGdyb3Vwc1xuXHQgKiBAcmV0dXJucyBBbGwgZ3JvdXBzIGNvbnRhaW5lZCBpbiB0aGUgbWFza1xuXHQgKi9cblx0Z2V0R3JvdXBOYW1lcyhncm91cHM6IG51bWJlcik6IEFycmF5PHN0cmluZz4ge1xuXHRcdGlmKGdyb3VwcyA9PT0gLTEpe1xuXHRcdFx0cmV0dXJuIFtQaHlzaWNzTWFuYWdlci5ERUZBVUxUX0dST1VQXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGV0IGcgPSAxO1xuXHRcdFx0bGV0IG5hbWVzID0gW107XG5cblx0XHRcdGZvcihsZXQgaSA9IDA7IGkgPCAzMjsgaSsrKXtcblx0XHRcdFx0aWYoZyAmIGdyb3Vwcyl7XG5cdFx0XHRcdFx0Ly8gVGhpcyBncm91cCBpcyBpbiB0aGUgZ3JvdXBzIG51bWJlclxuXHRcdFx0XHRcdG5hbWVzLnB1c2godGhpcy5ncm91cE5hbWVzW2ldKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFNoaWZ0IHRoZSBiaXQgb3ZlclxuXHRcdFx0XHRnID0gZyA8PCAxO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSIsImltcG9ydCBRdWV1ZSBmcm9tIFwiLi4vRGF0YVR5cGVzL1F1ZXVlXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IEV2ZW50UXVldWUgZnJvbSBcIi4uL0V2ZW50cy9FdmVudFF1ZXVlXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlY29yZGVyIHtcblx0cHJpdmF0ZSByZWNlaXZlcjogUmVjZWl2ZXI7XG5cdHByaXZhdGUgbG9nOiBRdWV1ZTxMb2dJdGVtPjtcblx0cHJpdmF0ZSByZWNvcmRpbmc6IGJvb2xlYW47XG5cdHByaXZhdGUgZXZlbnRRdWV1ZTogRXZlbnRRdWV1ZTtcblx0cHJpdmF0ZSBmcmFtZTogbnVtYmVyO1xuXHRwcml2YXRlIHBsYXlpbmc6IGJvb2xlYW47XG5cblx0Y29uc3RydWN0b3IoKXtcblx0XHR0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG5cdFx0dGhpcy5sb2cgPSBuZXcgUXVldWUoMTAwMCk7XG5cdFx0dGhpcy5yZWNvcmRpbmcgPSBmYWxzZTtcblx0XHR0aGlzLnBsYXlpbmcgPSBmYWxzZTtcblx0XHR0aGlzLmZyYW1lID0gMDtcblxuXHRcdHRoaXMuZXZlbnRRdWV1ZSA9IEV2ZW50UXVldWUuZ2V0SW5zdGFuY2UoKTtcblx0XHR0aGlzLmV2ZW50UXVldWUuc3Vic2NyaWJlKHRoaXMucmVjZWl2ZXIsIFwiYWxsXCIpO1xuXHR9XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYodGhpcy5yZWNvcmRpbmcpe1xuXHRcdFx0dGhpcy5mcmFtZSArPSAxO1xuXHRcdH1cblxuXHRcdGlmKHRoaXMucGxheWluZyl7XG5cdFx0XHQvLyBJZiBwbGF5aW5nLCBpZ25vcmUgZXZlbnRzLCBqdXN0IGZlZWQgdGhlIHJlY29yZCB0byB0aGUgZXZlbnQgcXVldWVcblx0XHRcdHRoaXMucmVjZWl2ZXIuaWdub3JlRXZlbnRzKCk7XG5cblx0XHRcdC8qXG5cdFx0XHRcdFdoaWxlIHRoZXJlIGlzIGEgbmV4dCBpdGVtLCBhbmQgd2hpbGUgaXQgc2hvdWxkIG9jY3VyIGluIHRoaXMgZnJhbWUsXG5cdFx0XHRcdHNlbmQgdGhlIGV2ZW50LiBpLmUuLCB3aGlsZSBjdXJyZW50X2ZyYW1lICogY3VycmVudF9kZWx0YV90IGlzIGdyZWF0ZXJcblx0XHRcdFx0dGhhbiByZWNvcmRlZF9mcmFtZSAqIHJlY29yZGVkX2RlbHRhX3Rcblx0XHRcdCovXG5cdFx0XHR3aGlsZSh0aGlzLmxvZy5oYXNJdGVtcygpXG5cdFx0XHRcdFx0JiYgdGhpcy5sb2cucGVla05leHQoKS5mcmFtZSAqIHRoaXMubG9nLnBlZWtOZXh0KCkuZGVsdGEgPCB0aGlzLmZyYW1lICogZGVsdGFUKXtcblx0XHRcdFx0bGV0IGV2ZW50ID0gdGhpcy5sb2cuZGVxdWV1ZSgpLmV2ZW50O1xuXHRcdFx0XHRjb25zb2xlLmxvZyhldmVudCk7XG5cdFx0XHRcdHRoaXMuZXZlbnRRdWV1ZS5hZGRFdmVudChldmVudCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmKCF0aGlzLmxvZy5oYXNJdGVtcygpKXtcblx0XHRcdFx0dGhpcy5wbGF5aW5nID0gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZnJhbWUgKz0gMTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gSWYgbm90IHBsYXlpbmcsIGhhbmRsZSBldmVudHNcblx0XHRcdHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuXHRcdFx0XHRsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuXG5cdFx0XHRcdGlmKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuU1RPUF9SRUNPUkRJTkcpe1xuXHRcdFx0XHRcdHRoaXMucmVjb3JkaW5nID0gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZih0aGlzLnJlY29yZGluZyl7XG5cdFx0XHRcdFx0dGhpcy5sb2cuZW5xdWV1ZShuZXcgTG9nSXRlbSh0aGlzLmZyYW1lLCBkZWx0YVQsIGV2ZW50KSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlNUQVJUX1JFQ09SRElORyl7XG5cdFx0XHRcdFx0dGhpcy5sb2cuY2xlYXIoKTtcblx0XHRcdFx0XHR0aGlzLnJlY29yZGluZyA9IHRydWU7XG5cdFx0XHRcdFx0dGhpcy5mcmFtZSA9IDBcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuUExBWV9SRUNPUkRJTkcpe1xuXHRcdFx0XHRcdHRoaXMuZnJhbWUgPSAwO1xuXHRcdFx0XHRcdHRoaXMucmVjb3JkaW5nID0gZmFsc2U7XG5cdFx0XHRcdFx0dGhpcy5wbGF5aW5nID0gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG5jbGFzcyBMb2dJdGVtIHtcblx0ZnJhbWU6IG51bWJlcjtcblx0ZGVsdGE6IG51bWJlcjtcblx0ZXZlbnQ6IEdhbWVFdmVudDtcblxuXHRjb25zdHJ1Y3RvcihmcmFtZTogbnVtYmVyLCBkZWx0YVQ6IG51bWJlciwgZXZlbnQ6IEdhbWVFdmVudCl7XG5cdFx0dGhpcy5mcmFtZSA9IGZyYW1lO1xuXHRcdHRoaXMuZGVsdGEgPSBkZWx0YVQ7XG5cdFx0dGhpcy5ldmVudCA9IGV2ZW50O1xuXHR9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL01hcFwiO1xuXG4vKiogKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFJlZ2lzdHJ5PFQ+IGV4dGVuZHMgTWFwPFQ+e1xuXG4gICAgLyoqIFByZWxvYWRzIHJlZ2lzdHJ5IGRhdGEgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgcHJlbG9hZCgpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGFuIGl0ZW0gYW5kIHByZWxvYWRzIGFueSBuZWNlc3NhcnkgZmlsZXNcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gcmVnaXN0ZXIgdGhpcyBpdGVtIHdpdGhcbiAgICAgKiBAcGFyYW0gYXJncyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgbmVlZGVkIGZvciByZWdpc3RyYXRpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgcmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShrZXk6IHN0cmluZywgLi4uYXJnczogYW55KTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhbiBpdGVtIGFuZCBwcmVsb2FkcyBhbnkgbmVjZXNzYXJ5IGZpbGVzXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHJlZ2lzdGVyIHRoaXMgaXRlbSB3aXRoXG4gICAgICogQHBhcmFtIGFyZ3MgQW55IGFkaXRpb25hbCBhcmd1bWVudHMgbmVlZGVkIGZvciByZWdpc3RyYXRpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgYWJzdHJhY3QgcmVnaXN0ZXJJdGVtKGtleTogc3RyaW5nLCAuLi5hcmdzOiBhbnkpOiB2b2lkO1xufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZVwiO1xuaW1wb3J0IExhYmVsU2hhZGVyVHlwZSBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL0xhYmVsU2hhZGVyVHlwZVwiO1xuaW1wb3J0IFBvaW50U2hhZGVyVHlwZSBmcm9tIFwiLi4vLi4vUmVuZGVyaW5nL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVzL1BvaW50U2hhZGVyVHlwZVwiO1xuaW1wb3J0IFJlY3RTaGFkZXJUeXBlIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvUmVjdFNoYWRlclR5cGVcIjtcbmltcG9ydCBTcHJpdGVTaGFkZXJUeXBlIGZyb20gXCIuLi8uLi9SZW5kZXJpbmcvV2ViR0xSZW5kZXJpbmcvU2hhZGVyVHlwZXMvU3ByaXRlU2hhZGVyVHlwZVwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFJlZ2lzdHJ5IGZyb20gXCIuL1JlZ2lzdHJ5XCI7XG5cbi8qKlxuICogQSByZWdpc3RyeSB0aGF0IGhhbmRsZXMgc2hhZGVyc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTaGFkZXJSZWdpc3RyeSBleHRlbmRzIFJlZ2lzdHJ5PFNoYWRlclR5cGU+IHtcblxuXHQvLyBTaGFkZXIgbmFtZXNcblx0cHVibGljIHN0YXRpYyBQT0lOVF9TSEFERVIgPSBcInBvaW50XCI7XG5cdHB1YmxpYyBzdGF0aWMgUkVDVF9TSEFERVIgPSBcInJlY3RcIjtcblx0cHVibGljIHN0YXRpYyBTUFJJVEVfU0hBREVSID0gXCJzcHJpdGVcIjtcblx0cHVibGljIHN0YXRpYyBMQUJFTF9TSEFERVIgPSBcImxhYmVsXCI7XG5cblx0cHJpdmF0ZSByZWdpc3RyeUl0ZW1zOiBBcnJheTxTaGFkZXJSZWdpc3RyeUl0ZW0+ID0gbmV3IEFycmF5KCk7XG5cblx0LyoqXG5cdCAqIFByZWxvYWRzIGFsbCBidWlsdC1pbiBzaGFkZXJzXG5cdCAqL1xuXHRwdWJsaWMgcHJlbG9hZCgpe1xuXHRcdC8vIEdldCB0aGUgcmVzb3VyY2VNYW5hZ2VyIGFuZCBxdWV1ZSBhbGwgYnVpbHQtaW4gc2hhZGVycyBmb3IgcHJlbG9hZGluZ1xuXHRcdGNvbnN0IHJtID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cblx0XHQvLyBRdWV1ZSBhIGxvYWQgZm9yIHRoZSBwb2ludCBzaGFkZXJcblx0XHR0aGlzLnJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oU2hhZGVyUmVnaXN0cnkuUE9JTlRfU0hBREVSLCBQb2ludFNoYWRlclR5cGUsIFwiYnVpbHRpbi9zaGFkZXJzL3BvaW50LnZzaGFkZXJcIiwgXCJidWlsdGluL3NoYWRlcnMvcG9pbnQuZnNoYWRlclwiKTtcblxuXHRcdC8vIFF1ZXVlIGEgbG9hZCBmb3IgdGhlIHJlY3Qgc2hhZGVyXG5cdFx0dGhpcy5yZWdpc3RlckFuZFByZWxvYWRJdGVtKFNoYWRlclJlZ2lzdHJ5LlJFQ1RfU0hBREVSLCBSZWN0U2hhZGVyVHlwZSwgXCJidWlsdGluL3NoYWRlcnMvcmVjdC52c2hhZGVyXCIsIFwiYnVpbHRpbi9zaGFkZXJzL3JlY3QuZnNoYWRlclwiKTtcblxuXHRcdC8vIFF1ZXVlIGEgbG9hZCBmb3IgdGhlIHNwcml0ZSBzaGFkZXJcblx0XHR0aGlzLnJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oU2hhZGVyUmVnaXN0cnkuU1BSSVRFX1NIQURFUiwgU3ByaXRlU2hhZGVyVHlwZSwgXCJidWlsdGluL3NoYWRlcnMvc3ByaXRlLnZzaGFkZXJcIiwgXCJidWlsdGluL3NoYWRlcnMvc3ByaXRlLmZzaGFkZXJcIik7XG5cdFxuXHRcdC8vIFF1ZXVlIGEgbG9hZCBmb3IgdGhlIGxhYmVsIHNoYWRlclxuXHRcdHRoaXMucmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShTaGFkZXJSZWdpc3RyeS5MQUJFTF9TSEFERVIsIExhYmVsU2hhZGVyVHlwZSwgXCJidWlsdGluL3NoYWRlcnMvbGFiZWwudnNoYWRlclwiLCBcImJ1aWx0aW4vc2hhZGVycy9sYWJlbC5mc2hhZGVyXCIpO1xuXG5cdFx0Ly8gUXVldWUgYSBsb2FkIGZvciBhbnkgcHJlbG9hZGVkIGl0ZW1zXG5cdFx0Zm9yKGxldCBpdGVtIG9mIHRoaXMucmVnaXN0cnlJdGVtcyl7XG5cdFx0XHRjb25zdCBzaGFkZXIgPSBuZXcgaXRlbS5jb25zdHIoaXRlbS5rZXkpO1xuXHRcdFx0c2hhZGVyLmluaXRCdWZmZXJPYmplY3QoKTtcblx0XHRcdHRoaXMuYWRkKGl0ZW0ua2V5LCBzaGFkZXIpO1xuXG5cdFx0XHQvLyBMb2FkIGlmIGRlc2lyZWRcblx0XHRcdGlmKGl0ZW0ucHJlbG9hZCAhPT0gdW5kZWZpbmVkKXtcblx0XHRcdFx0cm0uc2hhZGVyKGl0ZW0ua2V5LCBpdGVtLnByZWxvYWQudnNoYWRlckxvY2F0aW9uLCBpdGVtLnByZWxvYWQuZnNoYWRlckxvY2F0aW9uKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgc2hhZGVyIGluIHRoZSByZWdpc3RyeSBhbmQgbG9hZHMgaXQgYmVmb3JlIHRoZSBnYW1lIGJlZ2luc1xuXHQgKiBAcGFyYW0ga2V5IFRoZSBrZXkgeW91IHdpc2ggdG8gYXNzaWduIHRvIHRoZSBzaGFkZXJcblx0ICogQHBhcmFtIGNvbnN0ciBUaGUgY29uc3RydWN0b3Igb2YgdGhlIFNoYWRlclR5cGVcblx0ICogQHBhcmFtIHZzaGFkZXJMb2NhdGlvbiBUaGUgbG9jYXRpb24gb2YgdGhlIHZlcnRleCBzaGFkZXJcblx0ICogQHBhcmFtIGZzaGFkZXJMb2NhdGlvbiB0aGUgbG9jYXRpb24gb2YgdGhlIGZyYWdtZW50IHNoYWRlclxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVyQW5kUHJlbG9hZEl0ZW0oa2V5OiBzdHJpbmcsIGNvbnN0cjogbmV3IChwcm9ncmFtS2V5OiBzdHJpbmcpID0+IFNoYWRlclR5cGUsIHZzaGFkZXJMb2NhdGlvbjogc3RyaW5nLCBmc2hhZGVyTG9jYXRpb246IHN0cmluZyk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXJQcmVsb2FkID0gbmV3IFNoYWRlclByZWxvYWQoKTtcblx0XHRzaGFkZXJQcmVsb2FkLnZzaGFkZXJMb2NhdGlvbiA9IHZzaGFkZXJMb2NhdGlvbjtcblx0XHRzaGFkZXJQcmVsb2FkLmZzaGFkZXJMb2NhdGlvbiA9IGZzaGFkZXJMb2NhdGlvbjtcblxuXHRcdGxldCByZWdpc3RyeUl0ZW0gPSBuZXcgU2hhZGVyUmVnaXN0cnlJdGVtKCk7XG5cdFx0cmVnaXN0cnlJdGVtLmtleSA9IGtleTtcblx0XHRyZWdpc3RyeUl0ZW0uY29uc3RyID0gY29uc3RyO1xuXHRcdHJlZ2lzdHJ5SXRlbS5wcmVsb2FkID0gc2hhZGVyUHJlbG9hZDtcblxuXHRcdHRoaXMucmVnaXN0cnlJdGVtcy5wdXNoKHJlZ2lzdHJ5SXRlbSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIGEgc2hhZGVyIGluIHRoZSByZWdpc3RyeS4gTk9URTogSWYgeW91IHVzZSB0aGlzLCB5b3UgTVVTVCBsb2FkIHRoZSBzaGFkZXIgYmVmb3JlIHVzZS5cblx0ICogSWYgeW91IHdpc2ggdG8gcHJlbG9hZCB0aGUgc2hhZGVyLCB1c2UgcmVnaXN0ZXJBbmRQcmVsb2FkSXRlbSgpXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSB5b3Ugd2lzaCB0byBhc3NpZ24gdG8gdGhlIHNoYWRlclxuXHQgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgU2hhZGVyVHlwZVxuXHQgKi9cblx0cHVibGljIHJlZ2lzdGVySXRlbShrZXk6IHN0cmluZywgY29uc3RyOiBuZXcgKHByb2dyYW1LZXk6IHN0cmluZykgPT4gU2hhZGVyVHlwZSk6IHZvaWQge1xuXHRcdGxldCByZWdpc3RyeUl0ZW0gPSBuZXcgU2hhZGVyUmVnaXN0cnlJdGVtKCk7XG5cdFx0cmVnaXN0cnlJdGVtLmtleSA9IGtleTtcblx0XHRyZWdpc3RyeUl0ZW0uY29uc3RyID0gY29uc3RyO1xuXG5cdFx0dGhpcy5yZWdpc3RyeUl0ZW1zLnB1c2gocmVnaXN0cnlJdGVtKTtcblx0fVxufVxuXG5jbGFzcyBTaGFkZXJSZWdpc3RyeUl0ZW0ge1xuXHRrZXk6IHN0cmluZztcblx0Y29uc3RyOiBuZXcgKHByb2dyYW1LZXk6IHN0cmluZykgPT4gU2hhZGVyVHlwZTtcblx0cHJlbG9hZDogU2hhZGVyUHJlbG9hZDtcbn1cblxuY2xhc3MgU2hhZGVyUHJlbG9hZCB7XG5cdHZzaGFkZXJMb2NhdGlvbjogc3RyaW5nO1xuXHRmc2hhZGVyTG9jYXRpb246IHN0cmluZztcbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgUmVnaXN0cnkgZnJvbSBcIi4vUmVnaXN0cmllcy9SZWdpc3RyeVwiO1xuaW1wb3J0IFNoYWRlclJlZ2lzdHJ5IGZyb20gXCIuL1JlZ2lzdHJpZXMvU2hhZGVyUmVnaXN0cnlcIjtcblxuLyoqXG4gKiBUaGUgUmVnaXN0cnkgaXMgdGhlIHN5c3RlbSdzIHdheSBvZiBjb252ZXJ0aW5nIGNsYXNzZXMgYW5kIHR5cGVzIGludG8gc3RyaW5nXG4gKiByZXByZXNlbnRhdGlvbnMgZm9yIHVzZSBlbHNld2hlcmUgaW4gdGhlIGFwcGxpY2F0aW9uLlxuICogSXQgYWxsb3dzIGNsYXNzZXMgdG8gYmUgYWNjZXNzZWQgd2l0aG91dCBleHBsaWNpdGx5IHVzaW5nIGNvbnN0cnVjdG9ycyBpbiBjb2RlLFxuICogYW5kIGZvciByZXNvdXJjZXMgdG8gYmUgbG9hZGVkIGF0IEdhbWUgY3JlYXRpb24gdGltZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVnaXN0cnlNYW5hZ2VyIHtcblxuXHRwdWJsaWMgc3RhdGljIHNoYWRlcnMgPSBuZXcgU2hhZGVyUmVnaXN0cnkoKTtcblxuXHQvKiogQWRkaXRpb25hbCBjdXN0b20gcmVnaXN0cmllcyB0byBhZGQgdG8gdGhlIHJlZ2lzdHJ5IG1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHN0YXRpYyByZWdpc3RyaWVzOiBNYXA8UmVnaXN0cnk8YW55Pj4gPSBuZXcgTWFwKCk7XG5cblx0c3RhdGljIHByZWxvYWQoKXtcblx0XHR0aGlzLnNoYWRlcnMucHJlbG9hZCgpO1xuXG5cdFx0dGhpcy5yZWdpc3RyaWVzLmZvckVhY2goKGtleTogc3RyaW5nKSA9PiB0aGlzLnJlZ2lzdHJpZXMuZ2V0KGtleSkucHJlbG9hZCgpKTtcblx0fVxuXG5cdHN0YXRpYyBhZGRDdXN0b21SZWdpc3RyeShuYW1lOiBzdHJpbmcsIHJlZ2lzdHJ5OiBSZWdpc3RyeTxhbnk+KXtcblx0XHR0aGlzLnJlZ2lzdHJpZXMuYWRkKG5hbWUsIHJlZ2lzdHJ5KTtcblx0fVxuXG5cdHN0YXRpYyBnZXRSZWdpc3RyeShrZXk6IHN0cmluZyl7XG5cdFx0cmV0dXJuIHRoaXMucmVnaXN0cmllcy5nZXQoa2V5KTtcblx0fVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi8uLi9FdmVudHMvRW1pdHRlclwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uLy4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCB7IEFuaW1hdGlvbkRhdGEsIEFuaW1hdGlvblN0YXRlIH0gZnJvbSBcIi4vQW5pbWF0aW9uVHlwZXNcIjtcblxuLyoqXG4gKiBBbiBhbmltYXRpb24gbWFuYWdlciBjbGFzcyBmb3IgYW4gYW5pbWF0ZWQgQ2FudmFzTm9kZS5cbiAqIFRoaXMgY2xhc3Mga2VlcHMgdHJhY2sgb2YgdGhlIHBvc3NpYmxlIGFuaW1hdGlvbnMsIGFzIHdlbGwgYXMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHN0YXRlLFxuICogYW5kIGFic3RyYWN0cyBhbGwgaW50ZXJhY3Rpb25zIHdpdGggcGxheWluZywgcGF1c2luZywgYW5kIHN0b3BwaW5nIGFuaW1hdGlvbnMgYXMgd2VsbCBhcyBcbiAqIGNyZWF0aW5nIG5ldyBhbmltYXRpb25zIGZyb20gdGhlIENhbnZhc05vZGUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFuaW1hdGlvbk1hbmFnZXIge1xuICAgIC8qKiBUaGUgb3duZXIgb2YgdGhpcyBhbmltYXRpb24gbWFuYWdlciAqL1xuICAgIHByb3RlY3RlZCBvd25lcjogQ2FudmFzTm9kZTtcbiAgICBcbiAgICAvKiogVGhlIGN1cnJlbnQgYW5pbWF0aW9uIHN0YXRlIG9mIHRoaXMgc3ByaXRlICovXG4gICAgcHJvdGVjdGVkIGFuaW1hdGlvblN0YXRlOiBBbmltYXRpb25TdGF0ZTtcblxuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGUgY3VycmVudCBhbmltYXRpb24gb2YgdGhpcyBzcHJpdGUgKi9cbiAgICBwcm90ZWN0ZWQgY3VycmVudEFuaW1hdGlvbjogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50IGZyYW1lIG9mIHRoaXMgYW5pbWF0aW9uICovXG4gICAgcHJvdGVjdGVkIGN1cnJlbnRGcmFtZTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBwcm9ncmVzcyBvZiB0aGUgY3VycmVudCBhbmltYXRpb24gdGhyb3VnaCB0aGUgY3VycmVudCBmcmFtZSAqL1xuICAgIHByb3RlY3RlZCBmcmFtZVByb2dyZXNzOiBudW1iZXI7XG5cbiAgICAvKiogV2hldGhlciB0aGUgY3VycmVudCBhbmltYXRpb24gaXMgbG9vcGluZyBvciBub3QgKi9cbiAgICBwcm90ZWN0ZWQgbG9vcDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgbWFwIG9mIGFuaW1hdGlvbnMgKi9cbiAgICBwcm90ZWN0ZWQgYW5pbWF0aW9uczogTWFwPEFuaW1hdGlvbkRhdGE+O1xuXG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoZSBldmVudCAoaWYgYW55KSB0byBzZW5kIHdoZW4gdGhlIGN1cnJlbnQgYW5pbWF0aW9uIHN0b3BzIHBsYXlpbmcuICovXG4gICAgcHJvdGVjdGVkIG9uRW5kRXZlbnQ6IHN0cmluZztcblxuICAgIC8qKiBUaGUgZXZlbnQgZW1pdHRlciBmb3IgdGhpcyBhbmltYXRpb24gbWFuYWdlciAqL1xuICAgIHByb3RlY3RlZCBlbWl0dGVyOiBFbWl0dGVyO1xuXG4gICAgLyoqIEEgcXVldWVkIGFuaW1hdGlvbiAqL1xuICAgIHByb3RlY3RlZCBwZW5kaW5nQW5pbWF0aW9uOiBzdHJpbmc7XG5cbiAgICAvKiogVGhlIGxvb3Agc3RhdHVzIG9mIGEgcGVuZGluZyBhbmltYXRpb24gKi9cbiAgICBwcm90ZWN0ZWQgcGVuZGluZ0xvb3A6IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIG9uRW5kIGV2ZW50IG9mIGEgcGVuZGluZyBhbmltYXRpb24gKi9cbiAgICBwcm90ZWN0ZWQgcGVuZGluZ09uRW5kOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IEFuaW1hdGlvbk1hbmFnZXJcbiAgICAgKiBAcGFyYW0gb3duZXIgVGhlIG93bmVyIG9mIHRoZSBBbmltYXRpb25NYW5hZ2VyXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob3duZXI6IENhbnZhc05vZGUpe1xuICAgICAgICB0aGlzLm93bmVyID0gb3duZXI7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5TVE9QUEVEO1xuICAgICAgICB0aGlzLmN1cnJlbnRBbmltYXRpb24gPSBcIlwiO1xuICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZSA9IDA7XG4gICAgICAgIHRoaXMuZnJhbWVQcm9ncmVzcyA9IDA7XG4gICAgICAgIHRoaXMubG9vcCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFuaW1hdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMub25FbmRFdmVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGFuIGFuaW1hdGlvbiB0byB0aGlzIHNwcml0ZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIHVuaXF1ZSBrZXkgb2YgdGhlIGFuaW1hdGlvblxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIGFuaW1hdGlvbiBkYXRhXG4gICAgICovXG4gICAgYWRkKGtleTogc3RyaW5nLCBhbmltYXRpb246IEFuaW1hdGlvbkRhdGEpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hbmltYXRpb25zLmFkZChrZXksIGFuaW1hdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW5kZXggc3BlY2lmaWVkIGJ5IHRoZSBjdXJyZW50IGFuaW1hdGlvbiBhbmQgY3VycmVudCBmcmFtZVxuICAgICAqIEByZXR1cm5zIFRoZSBpbmRleCBpbiB0aGUgY3VycmVudCBhbmltYXRpb25cbiAgICAgKi9cbiAgICBnZXRJbmRleCgpOiBudW1iZXIge1xuICAgICAgICBpZih0aGlzLmFuaW1hdGlvbnMuaGFzKHRoaXMuY3VycmVudEFuaW1hdGlvbikpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYW5pbWF0aW9ucy5nZXQodGhpcy5jdXJyZW50QW5pbWF0aW9uKS5mcmFtZXNbdGhpcy5jdXJyZW50RnJhbWVdLmluZGV4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gY3VycmVudCBhbmltYXRpb24sIHdhcm4gdGhlIHVzZXJcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgQW5pbWF0aW9uIGluZGV4IHdhcyByZXF1ZXN0ZWQsIGJ1dCB0aGUgY3VycmVudCBhbmltYXRpb246ICR7dGhpcy5jdXJyZW50QW5pbWF0aW9ufSB3YXMgaW52YWxpZGApO1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIHNwZWNpZmllZCBhbmltYXRpb24gaXMgY3VycmVudGx5IHBsYXlpbmdcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGFuaW1hdGlvbiB0byBjaGVja1xuICAgICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIHNwZWNpZmllZCBhbmltYXRpb24gaXMgcGxheWluZywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaXNQbGF5aW5nKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRBbmltYXRpb24gPT09IGtleSAmJiB0aGlzLmFuaW1hdGlvblN0YXRlID09PSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgY3VycmVudCBhbmltYXRpb24gaW5kZXggYW5kIGFkdmFuY2VzIHRoZSBhbmltYXRpb24gZnJhbWVcbiAgICAgKiBAcmV0dXJucyBUaGUgaW5kZXggb2YgdGhlIGFuaW1hdGlvbiBmcmFtZVxuICAgICAqL1xuICAgIGdldEluZGV4QW5kQWR2YW5jZUFuaW1hdGlvbigpOiBudW1iZXIge1xuICAgICAgICAvLyBJZiB3ZSBhcmVuJ3QgcGxheWluZywgd2Ugd29uJ3QgYmUgYWR2YW5jaW5nIHRoZSBhbmltYXRpb25cbiAgICAgICAgaWYoISh0aGlzLmFuaW1hdGlvblN0YXRlID09PSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HKSl7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRJbmRleCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5hbmltYXRpb25zLmhhcyh0aGlzLmN1cnJlbnRBbmltYXRpb24pKXtcbiAgICAgICAgICAgIGxldCBjdXJyZW50QW5pbWF0aW9uID0gdGhpcy5hbmltYXRpb25zLmdldCh0aGlzLmN1cnJlbnRBbmltYXRpb24pO1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gY3VycmVudEFuaW1hdGlvbi5mcmFtZXNbdGhpcy5jdXJyZW50RnJhbWVdLmluZGV4O1xuXG4gICAgICAgICAgICAvLyBBZHZhbmNlIHRoZSBhbmltYXRpb25cbiAgICAgICAgICAgIHRoaXMuZnJhbWVQcm9ncmVzcyArPSAxO1xuICAgICAgICAgICAgaWYodGhpcy5mcmFtZVByb2dyZXNzID49IGN1cnJlbnRBbmltYXRpb24uZnJhbWVzW3RoaXMuY3VycmVudEZyYW1lXS5kdXJhdGlvbil7XG4gICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSBiZWVuIG9uIHRoaXMgZnJhbWUgZm9yIGl0cyB3aG9sZSBkdXJhdGlvbiwgZ28gdG8gdGhlIG5leHQgb25lXG4gICAgICAgICAgICAgICAgdGhpcy5mcmFtZVByb2dyZXNzID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRGcmFtZSArPSAxO1xuXG4gICAgICAgICAgICAgICAgaWYodGhpcy5jdXJyZW50RnJhbWUgPj0gY3VycmVudEFuaW1hdGlvbi5mcmFtZXMubGVuZ3RoKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSByZWFjaGVkIHRoZSBlbmQgb2YgdGhpcyBhbmltYXRpb25cbiAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5sb29wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudEZyYW1lID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZnJhbWVQcm9ncmVzcyA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZEN1cnJlbnRBbmltYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmV0dXJuIHRoZSBjdXJyZW50IGluZGV4XG4gICAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBObyBjdXJyZW50IGFuaW1hdGlvbiwgY2FuJ3QgYWR2YW5jZS4gV2FybiB0aGUgdXNlclxuICAgICAgICAgICAgY29uc29sZS53YXJuKGBBbmltYXRpb24gaW5kZXggYW5kIGFkdmFuY2Ugd2FzIHJlcXVlc3RlZCwgYnV0IHRoZSBjdXJyZW50IGFuaW1hdGlvbiAoJHt0aGlzLmN1cnJlbnRBbmltYXRpb259KSBpbiBub2RlIHdpdGggaWQ6ICR7dGhpcy5vd25lci5pZH0gd2FzIGludmFsaWRgKTtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEVuZHMgdGhlIGN1cnJlbnQgYW5pbWF0aW9uIGFuZCBmaXJlcyBhbnkgbmVjZXNzYXJ5IGV2ZW50cywgYXMgd2VsbCBhcyBzdGFydGluZyBhbnkgbmV3IGFuaW1hdGlvbnMgKi9cbiAgICBwcm90ZWN0ZWQgZW5kQ3VycmVudEFuaW1hdGlvbigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXJyZW50RnJhbWUgPSAwO1xuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuU1RPUFBFRDtcblxuICAgICAgICBpZih0aGlzLm9uRW5kRXZlbnQgIT09IG51bGwpe1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0aGlzLm9uRW5kRXZlbnQsIHtvd25lcjogdGhpcy5vd25lci5pZCwgYW5pbWF0aW9uOiB0aGlzLmN1cnJlbnRBbmltYXRpb259KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZXJlIGlzIGEgcGVuZGluZyBhbmltYXRpb24sIHBsYXkgaXRcbiAgICAgICAgaWYodGhpcy5wZW5kaW5nQW5pbWF0aW9uICE9PSBudWxsKXtcbiAgICAgICAgICAgIHRoaXMucGxheSh0aGlzLnBlbmRpbmdBbmltYXRpb24sIHRoaXMucGVuZGluZ0xvb3AsIHRoaXMucGVuZGluZ09uRW5kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBsYXlzIHRoZSBzcGVjaWZpZWQgYW5pbWF0aW9uLiBEb2VzIG5vdCByZXN0YXJ0IGl0IGlmIGl0IGlzIGFscmVhZHkgcGxheWluZ1xuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIG5hbWUgb2YgdGhlIGFuaW1hdGlvbiB0byBwbGF5XG4gICAgICogQHBhcmFtIGxvb3AgV2hldGhlciBvciBub3QgdG8gbG9vcCB0aGUgYW5pbWF0aW9uLiBGYWxzZSBieSBkZWZhdWx0XG4gICAgICogQHBhcmFtIG9uRW5kIFRoZSBuYW1lIG9mIGFuIGV2ZW50IHRvIHNlbmQgd2hlbiB0aGlzIGFuaW1hdGlvbiBuYXR1cmFsbHkgc3RvcHMgcGxheWluZy4gVGhpcyBvbmx5IG1hdHRlcnMgaWYgbG9vcCBpcyBmYWxzZS5cbiAgICAgKi9cbiAgICBwbGF5SWZOb3RBbHJlYWR5KGFuaW1hdGlvbjogc3RyaW5nLCBsb29wPzogYm9vbGVhbiwgb25FbmQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy5jdXJyZW50QW5pbWF0aW9uICE9PSBhbmltYXRpb24pe1xuICAgICAgICAgICAgdGhpcy5wbGF5KGFuaW1hdGlvbiwgbG9vcCwgb25FbmQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheXMgdGhlIHNwZWNpZmllZCBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBuYW1lIG9mIHRoZSBhbmltYXRpb24gdG8gcGxheVxuICAgICAqIEBwYXJhbSBsb29wIFdoZXRoZXIgb3Igbm90IHRvIGxvb3AgdGhlIGFuaW1hdGlvbi4gRmFsc2UgYnkgZGVmYXVsdFxuICAgICAqIEBwYXJhbSBvbkVuZCBUaGUgbmFtZSBvZiBhbiBldmVudCB0byBzZW5kIHdoZW4gdGhpcyBhbmltYXRpb24gbmF0dXJhbGx5IHN0b3BzIHBsYXlpbmcuIFRoaXMgb25seSBtYXR0ZXJzIGlmIGxvb3AgaXMgZmFsc2UuXG4gICAgICovXG4gICAgcGxheShhbmltYXRpb246IHN0cmluZywgbG9vcD86IGJvb2xlYW4sIG9uRW5kPzogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY3VycmVudEFuaW1hdGlvbiA9IGFuaW1hdGlvbjtcbiAgICAgICAgdGhpcy5jdXJyZW50RnJhbWUgPSAwO1xuICAgICAgICB0aGlzLmZyYW1lUHJvZ3Jlc3MgPSAwO1xuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUExBWUlORztcblxuICAgICAgICAvLyBJZiBsb29wIGFyZyB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0XG4gICAgICAgIGlmKGxvb3AgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICB0aGlzLmxvb3AgPSBsb29wO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCB1c2Ugd2hhdCB0aGUganNvbiBmaWxlIHNwZWNpZmllZFxuICAgICAgICAgICAgdGhpcy5sb29wID0gdGhpcy5hbmltYXRpb25zLmdldChhbmltYXRpb24pLnJlcGVhdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9uRW5kICE9PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgdGhpcy5vbkVuZEV2ZW50ID0gb25FbmQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9uRW5kRXZlbnQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVzZXQgcGVuZGluZyBhbmltYXRpb25cbiAgICAgICAgdGhpcy5wZW5kaW5nQW5pbWF0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBRdWV1ZXMgYSBzaW5nbGUgYW5pbWF0aW9uIHRvIGJlIHBsYXllZCBhZnRlciB0aGUgY3VycmVudCBvbmUuIERvZXMgTk9UIHN0YWNrLlxuICAgICAqIFF1ZXVlaW5nIGFkZGl0aW9uYWwgYW5pbWF0aW9ucyBwYXN0IDEgd2lsbCBqdXN0IHJlcGxhY2UgdGhlIHF1ZXVlZCBhbmltYXRpb25cbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBhbmltYXRpb24gdG8gcXVldWVcbiAgICAgKiBAcGFyYW0gbG9vcCBXaGV0aGVyIG9yIG5vdCB0aGUgbG9vcCB0aGUgcXVldWVkIGFuaW1hdGlvblxuICAgICAqIEBwYXJhbSBvbkVuZCBUaGUgZXZlbnQgdG8gZmlyZSB3aGVuIHRoZSBxdWV1ZWQgYW5pbWF0aW9uIGVuZHNcbiAgICAgKi9cbiAgICBxdWV1ZShhbmltYXRpb246IHN0cmluZywgbG9vcDogYm9vbGVhbiA9IGZhbHNlLCBvbkVuZD86IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLnBlbmRpbmdBbmltYXRpb24gPSBhbmltYXRpb247XG4gICAgICAgIHRoaXMucGVuZGluZ0xvb3AgPSBsb29wO1xuICAgICAgICBpZihvbkVuZCAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ09uRW5kID0gb25FbmQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdPbkVuZCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogUGF1c2VzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiAqL1xuICAgIHBhdXNlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuUEFVU0VEO1xuICAgIH1cblxuICAgIC8qKiBSZXN1bWVzIHRoZSBjdXJyZW50IGFuaW1hdGlvbiBpZiBwb3NzaWJsZSAqL1xuICAgIHJlc3VtZSgpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy5hbmltYXRpb25TdGF0ZSA9PT0gQW5pbWF0aW9uU3RhdGUuUEFVU0VEKXtcbiAgICAgICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5QTEFZSU5HO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFN0b3BzIHRoZSBjdXJyZW50IGFuaW1hdGlvbi4gVGhlIGFuaW1hdGlvbiBjYW5ub3QgYmUgcmVzdW1lZCBhZnRlciB0aGlzLiAqL1xuICAgIHN0b3AoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uU3RhdGUgPSBBbmltYXRpb25TdGF0ZS5TVE9QUEVEO1xuICAgIH1cbn0iLCJpbXBvcnQgeyBUd2VlbmFibGVQcm9wZXJ0aWVzIH0gZnJvbSBcIi4uLy4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgeyBFYXNlRnVuY3Rpb25UeXBlIH0gZnJvbSBcIi4uLy4uL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuZXhwb3J0IGVudW0gQW5pbWF0aW9uU3RhdGUge1xuICAgIFNUT1BQRUQgPSAwLFxuICAgIFBBVVNFRCA9IDEsXG4gICAgUExBWUlORyA9IDIsXG59XG5cbmV4cG9ydCBjbGFzcyBBbmltYXRpb25EYXRhIHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgZnJhbWVzOiBBcnJheTx7aW5kZXg6IG51bWJlciwgZHVyYXRpb246IG51bWJlcn0+O1xuICAgIHJlcGVhdDogYm9vbGVhbiA9IGZhbHNlO1xufVxuXG5leHBvcnQgY2xhc3MgVHdlZW5FZmZlY3Qge1xuICAgIC8qKiBUaGUgcHJvcGVydHkgdG8gdHdlZW4gKi9cbiAgICBwcm9wZXJ0eTogVHdlZW5hYmxlUHJvcGVydGllcztcblxuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgVHdlZW4gc2hvdWxkIHJlc2V0IHRoZSBwcm9wZXJ0eSB0byBpdHMgb3JpZ2luYWwgdmFsdWUgYWZ0ZXIgcGxheWluZyAqL1xuICAgIHJlc2V0T25Db21wbGV0ZTogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgc3RhcnRpbmcgdmFsdWUgZm9yIHRoZSB0d2VlbiAqL1xuICAgIHN0YXJ0OiBhbnk7XG5cbiAgICAvKiogVGhlIGVuZGluZyB2YWx1ZSBmb3IgdGhlIHR3ZWVuICovXG4gICAgZW5kOiBhbnk7XG5cbiAgICAvKiogVGhlIGVhc2UgZnVuY3Rpb24gdG8gdXNlICovXG4gICAgZWFzZTogRWFzZUZ1bmN0aW9uVHlwZTtcblxuICAgIC8qKiBETyBOT1QgTU9ESUZZIC0gVGhlIG9yaWdpbmFsIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSAtIHNldCBhdXRvbWF0aWNhbGx5ICovXG4gICAgaW5pdGlhbFZhbHVlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBUd2VlbkRhdGEge1xuICAgIC8vIE1lbWJlcnMgZm9yIGluaXRpYWxpemF0aW9uIGJ5IHRoZSB1c2VyXG4gICAgLyoqIFRoZSBhbW91bnQgb2YgdGltZSBpbiBtcyB0byB3YWl0IGJlZm9yZSBleGVjdXRpbmcgdGhlIHR3ZWVuICovXG4gICAgc3RhcnREZWxheTogbnVtYmVyO1xuICAgIC8qKiBUaGUgZHVyYXRpb24gb2YgdGltZSBvdmVyIHdoaWNoIHRoZSB2YWx1ZSB3aXRoIGNoYW5nZSBmcm9tIHN0YXJ0IHRvIGVuZCAqL1xuICAgIGR1cmF0aW9uOiBudW1iZXI7XG4gICAgLyoqIEFuIGFycmF5IG9mIHRoZSBlZmZlY3RzIG9uIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBvYmplY3QgKi9cbiAgICBlZmZlY3RzOiBBcnJheTxUd2VlbkVmZmVjdD47XG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IHRoaXMgdHdlZW4gc2hvdWxkIHJldmVyc2UgZnJvbSBlbmQgdG8gc3RhcnQgZm9yIGVhY2ggcHJvcGVydHkgd2hlbiBpdCBmaW5pc2hlcyAqL1xuICAgIHJldmVyc2VPbkNvbXBsZXRlOiBib29sZWFuO1xuICAgIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGlzIHR3ZWVuIHNob3VsZCBsb29wIHdoZW4gaXQgY29tcGxldGVzICovXG4gICAgbG9vcDogYm9vbGVhbjtcbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQgKGlmIGFueSkgd2hlbiB0aGUgdHdlZW4gZmluaXNoZXMgcGxheWluZyAqL1xuICAgIG9uRW5kOiBzdHJpbmdcblxuICAgIC8qKiBFeHRyYSBkYXRhIHRvIGJlIHNlbnQgd2hlbiB0aGUgb25FbmQgZXZlbnQgaXMgZmlyZWQuIEtleXMgd2l0aCB0aGUgbmFtZSAna2V5JyBvciAnbm9kZScgYXJlIHJlc2VydmVkIGFuZCBjYW4ndCBiZSB1c2VkIGFzIG5hbWVzIGZvciB5b3VyIGV4dHJhIGRhdGEgKi9cbiAgICBvbkVuZERhdGE6IFJlY29yZDxzdHJpbmcsIGFueT47XG4gICAgXG4gICAgLy8gTWVtYmVycyBmb3IgbWFuYWdlbWVudCBieSB0aGUgdHdlZW4gbWFuYWdlclxuICAgIC8qKiBUaGUgcHJvZ3Jlc3Mgb2YgdGhpcyB0d2VlbiB0aHJvdWdoIGl0cyBlZmZlY3RzICovXG4gICAgcHJvZ3Jlc3M6IG51bWJlcjtcblxuICAgIC8qKiBUaGUgYW1vdW50IG9mIHRpbWUgaW4gbXMgdGhhdCBoYXMgcGFzc2VkIGZyb20gd2hlbiB0aGlzIHR3ZWVuIHN0YXJ0ZWQgcnVubmluZyAqL1xuICAgIGVsYXBzZWRUaW1lOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIHN0YXRlIG9mIHRoaXMgdHdlZW4gKi9cbiAgICBhbmltYXRpb25TdGF0ZTogQW5pbWF0aW9uU3RhdGU7XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyB0d2VlbiBpcyBjdXJyZW50bHkgcmV2ZXJzaW5nICovXG4gICAgcmV2ZXJzaW5nOiBib29sZWFuO1xufSIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgUGFydGljbGVTeXN0ZW0gZnJvbSBcIi4vUGFydGljbGVTeXN0ZW1cIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFydGljbGVTeXN0ZW1NYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogUGFydGljbGVTeXN0ZW1NYW5hZ2VyID0gbnVsbDtcbiAgICBcbiAgICBwcm90ZWN0ZWQgcGFydGljbGVTeXN0ZW1zOiBBcnJheTxQYXJ0aWNsZVN5c3RlbT47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHRoaXMucGFydGljbGVTeXN0ZW1zID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldEluc3RhbmNlKCk6IFBhcnRpY2xlU3lzdGVtTWFuYWdlciB7XG4gICAgICAgIGlmKFBhcnRpY2xlU3lzdGVtTWFuYWdlci5pbnN0YW5jZSA9PT0gbnVsbCl7XG4gICAgICAgICAgICBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIuaW5zdGFuY2UgPSBuZXcgUGFydGljbGVTeXN0ZW1NYW5hZ2VyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUGFydGljbGVTeXN0ZW1NYW5hZ2VyLmluc3RhbmNlO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyUGFydGljbGVTeXN0ZW0oc3lzdGVtOiBQYXJ0aWNsZVN5c3RlbSl7XG4gICAgICAgIHRoaXMucGFydGljbGVTeXN0ZW1zLnB1c2goc3lzdGVtKTtcbiAgICB9XG5cbiAgICBkZXJlZ2lzdGVyUGFydGljbGVTeXN0ZW0oc3lzdGVtOiBQYXJ0aWNsZVN5c3RlbSl7XG4gICAgICAgIGxldCBpbmRleCA9IHRoaXMucGFydGljbGVTeXN0ZW1zLmluZGV4T2Yoc3lzdGVtKTtcbiAgICAgICAgdGhpcy5wYXJ0aWNsZVN5c3RlbXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG5cbiAgICBjbGVhclBhcnRpY2xlU3lzdGVtcygpe1xuICAgICAgICB0aGlzLnBhcnRpY2xlU3lzdGVtcyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBmb3IobGV0IHBhcnRpY2xlU3lzdGVtIG9mIHRoaXMucGFydGljbGVTeXN0ZW1zKXtcbiAgICAgICAgICAgIHBhcnRpY2xlU3lzdGVtLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCB7IEFuaW1hdGlvblN0YXRlLCBUd2VlbkRhdGEgfSBmcm9tIFwiLi9BbmltYXRpb25UeXBlc1wiO1xuaW1wb3J0IEVhc2VGdW5jdGlvbnMgZnJvbSBcIi4uLy4uL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFR3ZWVuTWFuYWdlciBmcm9tIFwiLi9Ud2Vlbk1hbmFnZXJcIjtcbmltcG9ydCBFbWl0dGVyIGZyb20gXCIuLi8uLi9FdmVudHMvRW1pdHRlclwiO1xuXG4vKipcbiAqIEEgbWFuYWdlciBmb3IgdGhlIHR3ZWVucyBvZiBhIEdhbWVOb2RlLlxuICogVHdlZW5zIGFyZSBzaG9ydCBhbmltYXRpb25zIHBsYXllZCBieSBpbnRlcnBvbGF0aW5nIGJldHdlZW4gdHdvIHByb3BlcnRpZXMgdXNpbmcgYW4gZWFzaW5nIGZ1bmN0aW9uLlxuICogRm9yIGEgZ29vZCB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgZWFzaW5nIGZ1bmN0aW9ucywgY2hlY2sgb3V0IEBsaW5rKGh0dHBzOi8vZWFzaW5ncy5uZXQvKShodHRwczovL2Vhc2luZ3MubmV0LykuXG4gKiBNdWx0aXBsZSB0d2VlbiBjYW4gYmUgcGxheWVkIGF0IHRoZSBzYW1lIHRpbWUsIGFzIGxvbmcgYXMgdGhleSBkb24ndCBjaGFuZ2UgdGhlIHNhbWUgcHJvcGVydHkuXG4gKiBUaGlzIGFsbG93cyBmb3Igc29tZSBpbnRlcmVzdGluZyBwb2xpc2hlcyBvciBhbmltYXRpb25zIHRoYXQgbWF5IGJlIHZlcnkgZGlmZmljdWx0IHRvIGRvIHdpdGggc3ByaXRlIHdvcmsgYWxvbmVcbiAqIC0gZXNwZWNpYWxseSBwaXhlbCBhcnQgKHN1Y2ggYXMgcm90YXRpb25zIG9yIHNjYWxpbmcpLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUd2VlbkNvbnRyb2xsZXIge1xuICAgIC8qKiBUaGUgR2FtZU5vZGUgdGhpcyBUd2VlbkNvbnRyb2xsZXIgYWN0cyB1cG9uICovXG4gICAgcHJvdGVjdGVkIG93bmVyOiBHYW1lTm9kZTtcbiAgICAvKiogVGhlIGxpc3Qgb2YgY3JlYXRlZCB0d2VlbnMgKi9cbiAgICBwcm90ZWN0ZWQgdHdlZW5zOiBNYXA8VHdlZW5EYXRhPjtcbiAgICAvKiogQW4gZXZlbnQgZW1pdHRlciAqL1xuICAgIHByb3RlY3RlZCBlbWl0dGVyOiBFbWl0dGVyO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBUd2VlbkNvbnRyb2xsZXJcbiAgICAgKiBAcGFyYW0gb3duZXIgVGhlIG93bmVyIG9mIHRoZSBUd2VlbkNvbnRyb2xsZXJcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihvd25lcjogR2FtZU5vZGUpe1xuICAgICAgICB0aGlzLm93bmVyID0gb3duZXI7XG4gICAgICAgIHRoaXMudHdlZW5zID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmVtaXR0ZXIgPSBuZXcgRW1pdHRlcigpO1xuXG4gICAgICAgIC8vIEdpdmUgb3Vyc2VsdmVzIHRvIHRoZSBUd2Vlbk1hbmFnZXJcbiAgICAgICAgVHdlZW5NYW5hZ2VyLmdldEluc3RhbmNlKCkucmVnaXN0ZXJUd2VlbkNvbnRyb2xsZXIodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVzdHJveXMgdGhpcyBUd2VlbkNvbnRyb2xsZXJcbiAgICAgKi9cbiAgICBkZXN0cm95KCl7XG4gICAgICAgIC8vIE9ubHkgdGhlIGdhbWVub2RlIGFuZCB0aGUgdHdlZW4gbWFuYWdlciBzaG91bGQgaGF2ZSBhIHJlZmVyZW5jZSB0byB0aGlzXG4gICAgICAgIGRlbGV0ZSB0aGlzLm93bmVyLnR3ZWVucztcbiAgICAgICAgVHdlZW5NYW5hZ2VyLmdldEluc3RhbmNlKCkuZGVyZWdpc3RlclR3ZWVuQ29udHJvbGxlcih0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSB0d2VlbiB0byB0aGlzIGdhbWUgbm9kZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIG5hbWUgb2YgdGhlIHR3ZWVuXG4gICAgICogQHBhcmFtIHR3ZWVuIFRoZSBkYXRhIG9mIHRoZSB0d2VlblxuICAgICAqL1xuICAgIGFkZChrZXk6IHN0cmluZywgdHdlZW46IFJlY29yZDxzdHJpbmcsIGFueT4gfCBUd2VlbkRhdGEpOiB2b2lkIHtcbiAgICAgICAgbGV0IHR5cGVkVHdlZW4gPSA8VHdlZW5EYXRhPnR3ZWVuO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgbWVtYmVycyB0aGF0IHdlIG5lZWQgKGFuZCB0aGUgdXNlciBkaWRuJ3QgcHJvdmlkZSlcbiAgICAgICAgdHlwZWRUd2Vlbi5wcm9ncmVzcyA9IDA7XG4gICAgICAgIHR5cGVkVHdlZW4uZWxhcHNlZFRpbWUgPSAwO1xuICAgICAgICB0eXBlZFR3ZWVuLmFuaW1hdGlvblN0YXRlID0gQW5pbWF0aW9uU3RhdGUuU1RPUFBFRDtcblxuICAgICAgICB0aGlzLnR3ZWVucy5hZGQoa2V5LCB0eXBlZFR3ZWVuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQbGF5IGEgdHdlZW4gd2l0aCBhIGNlcnRhaW4gbmFtZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIG5hbWUgb2YgdGhlIHR3ZWVuIHRvIHBsYXlcbiAgICAgKiBAcGFyYW0gbG9vcCBXaGV0aGVyIG9yIG5vdCB0aGUgdHdlZW4gc2hvdWxkIGxvb3BcbiAgICAgKi9cbiAgICBwbGF5KGtleTogc3RyaW5nLCBsb29wPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZih0aGlzLnR3ZWVucy5oYXMoa2V5KSl7XG4gICAgICAgICAgICBsZXQgdHdlZW4gPSB0aGlzLnR3ZWVucy5nZXQoa2V5KTtcblxuICAgICAgICAgICAgLy8gU2V0IGxvb3AgaWYgbmVlZGVkXG4gICAgICAgICAgICBpZihsb29wICE9PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgIHR3ZWVuLmxvb3AgPSBsb29wO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGluaXRpYWwgdmFsdWVzXG4gICAgICAgICAgICBmb3IobGV0IGVmZmVjdCBvZiB0d2Vlbi5lZmZlY3RzKXtcbiAgICAgICAgICAgICAgICBpZihlZmZlY3QucmVzZXRPbkNvbXBsZXRlKXtcbiAgICAgICAgICAgICAgICAgICAgZWZmZWN0LmluaXRpYWxWYWx1ZSA9IHRoaXMub3duZXJbZWZmZWN0LnByb3BlcnR5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXJ0IHRoZSB0d2VlbiBydW5uaW5nXG4gICAgICAgICAgICB0d2Vlbi5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBMQVlJTkc7XG4gICAgICAgICAgICB0d2Vlbi5lbGFwc2VkVGltZSA9IDA7XG4gICAgICAgICAgICB0d2Vlbi5wcm9ncmVzcyA9IDA7XG4gICAgICAgICAgICB0d2Vlbi5yZXZlcnNpbmcgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgVHJpZWQgdG8gcGxheSB0d2VlbiBcIiR7a2V5fVwiIG9uIG5vZGUgd2l0aCBpZCAke3RoaXMub3duZXIuaWR9LCBidXQgbm8gc3VjaCB0d2VlbiBleGlzdHNgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcyBhIHBsYXlpbmcgdHdlZW4uIERvZXMgbm90IGFmZmVjdCB0d2VlbnMgdGhhdCBhcmUgc3RvcHBlZC5cbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBuYW1lIG9mIHRoZSB0d2VlbiB0byBwYXVzZS5cbiAgICAgKi9cbiAgICBwYXVzZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLnR3ZWVucy5oYXMoa2V5KSl7XG4gICAgICAgICAgICB0aGlzLnR3ZWVucy5nZXQoa2V5KS5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBBVVNFRDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3VtZXMgYSBwYXVzZWQgdHdlZW4uXG4gICAgICogQHBhcmFtIGtleSBUaGUgbmFtZSBvZiB0aGUgdHdlZW4gdG8gcmVzdW1lXG4gICAgICovXG4gICAgcmVzdW1lKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmKHRoaXMudHdlZW5zLmhhcyhrZXkpKXtcbiAgICAgICAgICAgIGxldCB0d2VlbiA9IHRoaXMudHdlZW5zLmdldChrZXkpO1xuICAgICAgICAgICAgaWYodHdlZW4uYW5pbWF0aW9uU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLlBBVVNFRClcbiAgICAgICAgICAgICAgICB0d2Vlbi5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlBMQVlJTkc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdG9wcyBhIGN1cnJlbnRseSBwbGF5aW5nIHR3ZWVuXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSB0d2VlblxuICAgICAqL1xuICAgIHN0b3Aoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYodGhpcy50d2VlbnMuaGFzKGtleSkpe1xuICAgICAgICAgICAgbGV0IHR3ZWVuID0gdGhpcy50d2VlbnMuZ2V0KGtleSk7XG4gICAgICAgICAgICB0d2Vlbi5hbmltYXRpb25TdGF0ZSA9IEFuaW1hdGlvblN0YXRlLlNUT1BQRUQ7XG5cbiAgICAgICAgICAgIC8vIFJldHVybiB0byB0aGUgaW5pdGlhbCB2YWx1ZXNcbiAgICAgICAgICAgIGZvcihsZXQgZWZmZWN0IG9mIHR3ZWVuLmVmZmVjdHMpe1xuICAgICAgICAgICAgICAgIGlmKGVmZmVjdC5yZXNldE9uQ29tcGxldGUpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm93bmVyW2VmZmVjdC5wcm9wZXJ0eV0gPSBlZmZlY3QuaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBuYXR1cmFsIHN0b3Agb2YgYSBjdXJyZW50bHkgcGxheWluZyB0d2VlblxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgdHdlZW5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZW5kKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RvcChrZXkpO1xuICAgICAgICBpZih0aGlzLnR3ZWVucy5oYXMoa2V5KSl7XG4gICAgICAgICAgICAvLyBHZXQgdGhlIHR3ZWVuXG4gICAgICAgICAgICBsZXQgdHdlZW4gPSB0aGlzLnR3ZWVucy5nZXQoa2V5KTtcblxuICAgICAgICAgICAgLy8gSWYgaXQgaGFzIGFuIG9uRW5kLCBzZW5kIGFuIGV2ZW50XG4gICAgICAgICAgICBpZih0d2Vlbi5vbkVuZCl7XG4gICAgICAgICAgICAgICAgbGV0IGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7a2V5OiBrZXksIG5vZGU6IHRoaXMub3duZXIuaWR9XG4gICAgICAgICAgICAgICAgLy8gSWYgaXQgaGFzIG9uRW5kIGV2ZW50IGRhdGEsIGFkZCBlYWNoIGVudHJ5LCBhcyBsb25nIGFzIHRoZSBrZXkgaXMgbm90IG5hbWVkICdrZXknIG9yICdub2RlJ1xuICAgICAgICAgICAgICAgIGlmICh0d2Vlbi5vbkVuZERhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXModHdlZW4ub25FbmREYXRhKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImtleVwiICYmIGtleSAhPT0gXCJub2RlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW2tleV0gPSB0d2Vlbi5vbkVuZERhdGFba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudCh0d2Vlbi5vbkVuZCwgZGF0YSk7IFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcHMgYWxsIGN1cnJlbnRseSBwbGF5aW5nIHR3ZWVuc1xuICAgICAqL1xuICAgIHN0b3BBbGwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMudHdlZW5zLmZvckVhY2goa2V5ID0+IHRoaXMuc3RvcChrZXkpKTtcbiAgICB9XG4gICAgXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMudHdlZW5zLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgICAgIGxldCB0d2VlbiA9IHRoaXMudHdlZW5zLmdldChrZXkpO1xuICAgICAgICAgICAgaWYodHdlZW4uYW5pbWF0aW9uU3RhdGUgPT09IEFuaW1hdGlvblN0YXRlLlBMQVlJTkcpe1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcHJvZ3Jlc3Mgb2YgdGhlIHR3ZWVuXG4gICAgICAgICAgICAgICAgdHdlZW4uZWxhcHNlZFRpbWUgKz0gZGVsdGFUKjEwMDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSdyZSBwYXN0IHRoZSBzdGFydERlbGF5LCBkbyB0aGUgdHdlZW5cbiAgICAgICAgICAgICAgICBpZih0d2Vlbi5lbGFwc2VkVGltZSA+PSB0d2Vlbi5zdGFydERlbGF5KXtcbiAgICAgICAgICAgICAgICAgICAgaWYoIXR3ZWVuLnJldmVyc2luZyAmJiB0d2Vlbi5lbGFwc2VkVGltZSA+PSB0d2Vlbi5zdGFydERlbGF5ICsgdHdlZW4uZHVyYXRpb24pe1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UncmUgb3ZlciB0aW1lLCBzdG9wIHRoZSB0d2VlbiwgbG9vcCwgb3IgcmV2ZXJzZVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHdlZW4ucmV2ZXJzZU9uQ29tcGxldGUpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlJ3JlIG92ZXIgdGltZSBhbmQgY2FuIHJldmVyc2UsIGRvIHNvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHdlZW4ucmV2ZXJzaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih0d2Vlbi5sb29wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBjYW4ndCByZXZlcnNlIGFuZCBjYW4gbG9vcCwgZG8gc29cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5lbGFwc2VkVGltZSAtPSB0d2Vlbi5kdXJhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlbid0IGxvb3BpbmcgYW5kIGNhbid0IHJldmVyc2UsIHNvIHN0b3BcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZChrZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgZm9yIHRoZSBlbmQgb2YgcmV2ZXJzaW5nXG4gICAgICAgICAgICAgICAgICAgIGlmKHR3ZWVuLnJldmVyc2luZyAmJiB0d2Vlbi5lbGFwc2VkVGltZSA+PSB0d2Vlbi5zdGFydERlbGF5ICsgMip0d2Vlbi5kdXJhdGlvbil7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0d2Vlbi5sb29wKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5yZXZlcnNpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5lbGFwc2VkVGltZSAtPSAyKnR3ZWVuLmR1cmF0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZChrZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBwcm9ncmVzcywgbWFrZSBzdXJlIGl0IGlzIGJldHdlZW4gMCBhbmQgMS4gRXJyb3JzIGZyb20gdGhpcyBzaG91bGQgbmV2ZXIgYmUgbGFyZ2VcbiAgICAgICAgICAgICAgICAgICAgaWYodHdlZW4ucmV2ZXJzaW5nKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR3ZWVuLnByb2dyZXNzID0gTWF0aFV0aWxzLmNsYW1wMDEoKDIqdHdlZW4uZHVyYXRpb24gLSAodHdlZW4uZWxhcHNlZFRpbWUtIHR3ZWVuLnN0YXJ0RGVsYXkpKS90d2Vlbi5kdXJhdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0d2Vlbi5wcm9ncmVzcyA9IE1hdGhVdGlscy5jbGFtcDAxKCh0d2Vlbi5lbGFwc2VkVGltZSAtIHR3ZWVuLnN0YXJ0RGVsYXkpL3R3ZWVuLmR1cmF0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgZWZmZWN0IG9mIHR3ZWVuLmVmZmVjdHMpe1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHZhbHVlIGZyb20gdGhlIGVhc2UgZnVuY3Rpb24gdGhhdCBjb3JyZXNwb25kcyB0byBvdXIgcHJvZ3Jlc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlYXNlID0gRWFzZUZ1bmN0aW9uc1tlZmZlY3QuZWFzZV0odHdlZW4ucHJvZ3Jlc3MpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIHZhbHVlIHRvIGxlcnAgdGhlIHByb3BlcnR5XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWUgPSBNYXRoVXRpbHMubGVycChlZmZlY3Quc3RhcnQsIGVmZmVjdC5lbmQsIGVhc2UpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBc3NpZ24gdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vd25lcltlZmZlY3QucHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn0iLCJpbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IFR3ZWVuQ29udHJvbGxlciBmcm9tIFwiLi9Ud2VlbkNvbnRyb2xsZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVHdlZW5NYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogVHdlZW5NYW5hZ2VyID0gbnVsbDtcbiAgICBcbiAgICBwcm90ZWN0ZWQgdHdlZW5Db250cm9sbGVyczogQXJyYXk8VHdlZW5Db250cm9sbGVyPjtcblxuICAgIHByaXZhdGUgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy50d2VlbkNvbnRyb2xsZXJzID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGdldEluc3RhbmNlKCk6IFR3ZWVuTWFuYWdlciB7XG4gICAgICAgIGlmKFR3ZWVuTWFuYWdlci5pbnN0YW5jZSA9PT0gbnVsbCl7XG4gICAgICAgICAgICBUd2Vlbk1hbmFnZXIuaW5zdGFuY2UgPSBuZXcgVHdlZW5NYW5hZ2VyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gVHdlZW5NYW5hZ2VyLmluc3RhbmNlO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyVHdlZW5Db250cm9sbGVyKGNvbnRyb2xsZXI6IFR3ZWVuQ29udHJvbGxlcil7XG4gICAgICAgIHRoaXMudHdlZW5Db250cm9sbGVycy5wdXNoKGNvbnRyb2xsZXIpO1xuICAgIH1cblxuICAgIGRlcmVnaXN0ZXJUd2VlbkNvbnRyb2xsZXIoY29udHJvbGxlcjogVHdlZW5Db250cm9sbGVyKXtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy50d2VlbkNvbnRyb2xsZXJzLmluZGV4T2YoY29udHJvbGxlcik7XG4gICAgICAgIHRoaXMudHdlZW5Db250cm9sbGVycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cblxuICAgIGNsZWFyVHdlZW5Db250cm9sbGVycygpe1xuICAgICAgICB0aGlzLnR3ZWVuQ29udHJvbGxlcnMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgZm9yKGxldCB0d2VlbkNvbnRyb2xsZXIgb2YgdGhpcy50d2VlbkNvbnRyb2xsZXJzKXtcbiAgICAgICAgICAgIHR3ZWVuQ29udHJvbGxlci51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBPcnRob2dvbmFsVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcHMvT3J0aG9nb25hbFRpbGVtYXBcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9VSUxheWVyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgR3JhcGhpY1JlbmRlcmVyIGZyb20gXCIuL0NhbnZhc1JlbmRlcmluZy9HcmFwaGljUmVuZGVyZXJcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuL1JlbmRlcmluZ01hbmFnZXJcIlxuaW1wb3J0IFRpbGVtYXBSZW5kZXJlciBmcm9tIFwiLi9DYW52YXNSZW5kZXJpbmcvVGlsZW1hcFJlbmRlcmVyXCI7XG5pbXBvcnQgVUlFbGVtZW50UmVuZGVyZXIgZnJvbSBcIi4vQ2FudmFzUmVuZGVyaW5nL1VJRWxlbWVudFJlbmRlcmVyXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgU2xpZGVyIGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL1NsaWRlclwiO1xuaW1wb3J0IFRleHRJbnB1dCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50cy9UZXh0SW5wdXRcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTGluZSBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvTGluZVwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi9EZWJ1Zy9EZWJ1Z1wiO1xuXG4vKipcbiAqIEFuIGltcGxlbWVudGF0aW9uIG9mIHRoZSBSZW5kZXJpbmdNYW5hZ2VyIGNsYXNzIHVzaW5nIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2FudmFzUmVuZGVyZXIgZXh0ZW5kcyBSZW5kZXJpbmdNYW5hZ2VyIHtcbiAgICBwcm90ZWN0ZWQgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG4gICAgcHJvdGVjdGVkIGdyYXBoaWNSZW5kZXJlcjogR3JhcGhpY1JlbmRlcmVyO1xuICAgIHByb3RlY3RlZCB0aWxlbWFwUmVuZGVyZXI6IFRpbGVtYXBSZW5kZXJlcjtcbiAgICBwcm90ZWN0ZWQgdWlFbGVtZW50UmVuZGVyZXI6IFVJRWxlbWVudFJlbmRlcmVyO1xuXG4gICAgcHJvdGVjdGVkIG9yaWdpbjogVmVjMjtcbiAgICBwcm90ZWN0ZWQgem9vbTogbnVtYmVyO1xuXG4gICAgcHJvdGVjdGVkIHdvcmxkU2l6ZTogVmVjMjtcblxuICAgIGNvbnN0cnVjdG9yKCl7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgc2V0U2NlbmUoc2NlbmU6IFNjZW5lKXtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgICAgICB0aGlzLmdyYXBoaWNSZW5kZXJlci5zZXRTY2VuZShzY2VuZSk7XG4gICAgICAgIHRoaXMudGlsZW1hcFJlbmRlcmVyLnNldFNjZW5lKHNjZW5lKTtcbiAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlci5zZXRTY2VuZShzY2VuZSk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgaW5pdGlhbGl6ZUNhbnZhcyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCB7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgICAgIHRoaXMud29ybGRTaXplID0gbmV3IFZlYzIod2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgdGhpcy5jdHggPSBjYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuXG4gICAgICAgIHRoaXMuZ3JhcGhpY1JlbmRlcmVyID0gbmV3IEdyYXBoaWNSZW5kZXJlcih0aGlzLmN0eCk7XG4gICAgICAgIHRoaXMudGlsZW1hcFJlbmRlcmVyID0gbmV3IFRpbGVtYXBSZW5kZXJlcih0aGlzLmN0eCk7XG4gICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIgPSBuZXcgVUlFbGVtZW50UmVuZGVyZXIodGhpcy5jdHgpXG5cbiAgICAgICAgLy8gRm9yIGNyaXNwIHBpeGVsIGFydFxuICAgICAgICB0aGlzLmN0eC5pbWFnZVNtb290aGluZ0VuYWJsZWQgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4gdGhpcy5jdHg7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcmVuZGVyKHZpc2libGVTZXQ6IENhbnZhc05vZGVbXSwgdGlsZW1hcHM6IFRpbGVtYXBbXSwgdWlMYXllcnM6IE1hcDxVSUxheWVyPik6IHZvaWQge1xuICAgICAgICAvLyBTb3J0IGJ5IGRlcHRoLCB0aGVuIGJ5IHZpc2libGUgc2V0IGJ5IHktdmFsdWVcbiAgICAgICAgdmlzaWJsZVNldC5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICBpZihhLmdldExheWVyKCkuZ2V0RGVwdGgoKSA9PT0gYi5nZXRMYXllcigpLmdldERlcHRoKCkpe1xuICAgICAgICAgICAgICAgIHJldHVybiAoYS5ib3VuZGFyeS5ib3R0b20pIC0gKGIuYm91bmRhcnkuYm90dG9tKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEuZ2V0TGF5ZXIoKS5nZXREZXB0aCgpIC0gYi5nZXRMYXllcigpLmdldERlcHRoKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCB0aWxlbWFwSW5kZXggPSAwO1xuICAgICAgICBsZXQgdGlsZW1hcExlbmd0aCA9IHRpbGVtYXBzLmxlbmd0aDtcblxuICAgICAgICBsZXQgdmlzaWJsZVNldEluZGV4ID0gMDtcbiAgICAgICAgbGV0IHZpc2libGVTZXRMZW5ndGggPSB2aXNpYmxlU2V0Lmxlbmd0aDtcblxuICAgICAgICB3aGlsZSh0aWxlbWFwSW5kZXggPCB0aWxlbWFwTGVuZ3RoIHx8IHZpc2libGVTZXRJbmRleCA8IHZpc2libGVTZXRMZW5ndGgpe1xuICAgICAgICAgICAgLy8gQ2hlY2sgY29uZGl0aW9ucyB3aGVyZSB3ZSd2ZSBhbHJlYWR5IHJlYWNoZWQgdGhlIGVkZ2Ugb2Ygb25lIGxpc3RcbiAgICAgICAgICAgIGlmKHRpbGVtYXBJbmRleCA+PSB0aWxlbWFwTGVuZ3RoKXtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IHJlbmRlciB0aGUgcmVtYWluaW5nIHZpc2libGUgc2V0XG4gICAgICAgICAgICAgICAgbGV0IG5vZGUgPSB2aXNpYmxlU2V0W3Zpc2libGVTZXRJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBpZihub2RlLnZpc2libGUpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlck5vZGUobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZih2aXNpYmxlU2V0SW5kZXggPj0gdmlzaWJsZVNldExlbmd0aCl7XG4gICAgICAgICAgICAgICAgLy8gT25seSByZW5kZXIgdGlsZW1hcHNcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclRpbGVtYXAodGlsZW1hcHNbdGlsZW1hcEluZGV4KytdKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmVuZGVyIHdoaWNoZXZlciBpcyBmdXJ0aGVyIGRvd25cbiAgICAgICAgICAgIGlmKHRpbGVtYXBzW3RpbGVtYXBJbmRleF0uZ2V0TGF5ZXIoKS5nZXREZXB0aCgpIDw9IHZpc2libGVTZXRbdmlzaWJsZVNldEluZGV4XS5nZXRMYXllcigpLmdldERlcHRoKCkpe1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyVGlsZW1hcCh0aWxlbWFwc1t0aWxlbWFwSW5kZXgrK10pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsZXQgbm9kZSA9IHZpc2libGVTZXRbdmlzaWJsZVNldEluZGV4KytdO1xuICAgICAgICAgICAgICAgIGlmKG5vZGUudmlzaWJsZSl7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyTm9kZShub2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW5kZXIgdGhlIHVpTGF5ZXJzIG9uIHRvcCBvZiBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgbGV0IHNvcnRlZFVJTGF5ZXJzID0gbmV3IEFycmF5PFVJTGF5ZXI+KCk7XG5cbiAgICAgICAgdWlMYXllcnMuZm9yRWFjaChrZXkgPT4gc29ydGVkVUlMYXllcnMucHVzaCh1aUxheWVycy5nZXQoa2V5KSkpO1xuXG4gICAgICAgIHNvcnRlZFVJTGF5ZXJzID0gc29ydGVkVUlMYXllcnMuc29ydCgodWkxLCB1aTIpID0+IHVpMS5nZXREZXB0aCgpIC0gdWkyLmdldERlcHRoKCkpO1xuXG4gICAgICAgIHNvcnRlZFVJTGF5ZXJzLmZvckVhY2godWlMYXllciA9PiB7XG5cdFx0XHRpZighdWlMYXllci5pc0hpZGRlbigpKVxuXHRcdFx0XHR1aUxheWVyLmdldEl0ZW1zKCkuZm9yRWFjaChub2RlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYoKDxDYW52YXNOb2RlPm5vZGUpLnZpc2libGUpe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJOb2RlKDxDYW52YXNOb2RlPm5vZGUpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuXHRcdH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBzcGVjaWZpZWQgQ2FudmFzTm9kZVxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBDYW52YXNOb2RlIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJOb2RlKG5vZGU6IENhbnZhc05vZGUpOiB2b2lkIHtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0IGFjY29yZGluZyB0byB0aGlzIHNwcml0ZVxuICAgICAgICB0aGlzLm9yaWdpbiA9IHRoaXMuc2NlbmUuZ2V0Vmlld1RyYW5zbGF0aW9uKG5vZGUpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgem9vbSBsZXZlbCBvZiB0aGUgc2NlbmVcbiAgICAgICAgdGhpcy56b29tID0gdGhpcy5zY2VuZS5nZXRWaWV3U2NhbGUoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIE1vdmUgdGhlIGNhbnZhcyB0byB0aGUgcG9zaXRpb24gb2YgdGhlIG5vZGUgYW5kIHJvdGF0ZVxuICAgICAgICBsZXQgeFNjYWxlID0gMTtcbiAgICAgICAgbGV0IHlTY2FsZSA9IDE7XG4gICAgICAgIFxuICAgICAgICBpZihub2RlIGluc3RhbmNlb2YgU3ByaXRlKXtcbiAgICAgICAgICAgIHhTY2FsZSA9IG5vZGUuaW52ZXJ0WCA/IC0xIDogMTtcbiAgICAgICAgICAgIHlTY2FsZSA9IG5vZGUuaW52ZXJ0WSA/IC0xIDogMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybSh4U2NhbGUsIDAsIDAsIHlTY2FsZSwgKG5vZGUucG9zaXRpb24ueCAtIHRoaXMub3JpZ2luLngpKnRoaXMuem9vbSwgKG5vZGUucG9zaXRpb24ueSAtIHRoaXMub3JpZ2luLnkpKnRoaXMuem9vbSk7XG4gICAgICAgIHRoaXMuY3R4LnJvdGF0ZSgtbm9kZS5yb3RhdGlvbik7XG4gICAgICAgIGxldCBnbG9iYWxBbHBoYSA9IHRoaXMuY3R4Lmdsb2JhbEFscGhhO1xuICAgICAgICAvLyBpZihub2RlIGluc3RhbmNlb2YgUmVjdCl7XG4gICAgICAgICAgICAvLyBEZWJ1Zy5sb2coXCJub2RlXCIgKyBub2RlLmlkLCBcIk5vZGVcIiArIG5vZGUuaWQgKyBcIiBBbHBoYTogXCIgKyBub2RlLmFscGhhKTtcbiAgICAgICAgLy8gfVxuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IG5vZGUuYWxwaGE7XG4gICAgICAgIFxuICAgICAgICBpZihub2RlIGluc3RhbmNlb2YgQW5pbWF0ZWRTcHJpdGUpe1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJBbmltYXRlZFNwcml0ZSg8QW5pbWF0ZWRTcHJpdGU+bm9kZSk7XG4gICAgICAgIH0gZWxzZSBpZihub2RlIGluc3RhbmNlb2YgU3ByaXRlKXtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyU3ByaXRlKDxTcHJpdGU+bm9kZSk7XG4gICAgICAgIH0gZWxzZSBpZihub2RlIGluc3RhbmNlb2YgR3JhcGhpYyl7XG4gICAgICAgICAgICB0aGlzLnJlbmRlckdyYXBoaWMoPEdyYXBoaWM+bm9kZSk7XG4gICAgICAgIH0gZWxzZSBpZihub2RlIGluc3RhbmNlb2YgVUlFbGVtZW50KXtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyVUlFbGVtZW50KDxVSUVsZW1lbnQ+bm9kZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGdsb2JhbEFscGhhO1xuICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbmRlclNwcml0ZShzcHJpdGU6IFNwcml0ZSk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIGltYWdlIGZyb20gdGhlIHJlc291cmNlIG1hbmFnZXJcbiAgICAgICAgbGV0IGltYWdlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0SW1hZ2Uoc3ByaXRlLmltYWdlSWQpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAgICBDb29yZGluYXRlcyBpbiB0aGUgc3BhY2Ugb2YgdGhlIGltYWdlOlxuICAgICAgICAgICAgICAgIGltYWdlIGNyb3Agc3RhcnQgLT4geCwgeVxuICAgICAgICAgICAgICAgIGltYWdlIGNyb3Agc2l6ZSAgLT4gdywgaFxuICAgICAgICAgICAgQ29vcmRpbmF0ZXMgaW4gdGhlIHNwYWNlIG9mIHRoZSB3b3JsZFxuICAgICAgICAgICAgICAgIGltYWdlIGRyYXcgc3RhcnQgLT4geCwgeVxuICAgICAgICAgICAgICAgIGltYWdlIGRyYXcgc2l6ZSAgLT4gdywgaFxuICAgICAgICAqL1xuICAgICAgICB0aGlzLmN0eC5kcmF3SW1hZ2UoaW1hZ2UsXG4gICAgICAgICAgICBzcHJpdGUuaW1hZ2VPZmZzZXQueCwgc3ByaXRlLmltYWdlT2Zmc2V0LnksXG4gICAgICAgICAgICBzcHJpdGUuc2l6ZS54LCBzcHJpdGUuc2l6ZS55LFxuICAgICAgICAgICAgKC1zcHJpdGUuc2l6ZS54KnNwcml0ZS5zY2FsZS54LzIpKnRoaXMuem9vbSwgKC1zcHJpdGUuc2l6ZS55KnNwcml0ZS5zY2FsZS55LzIpKnRoaXMuem9vbSxcbiAgICAgICAgICAgIHNwcml0ZS5zaXplLnggKiBzcHJpdGUuc2NhbGUueCp0aGlzLnpvb20sIHNwcml0ZS5zaXplLnkgKiBzcHJpdGUuc2NhbGUueSp0aGlzLnpvb20pO1xuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIHByb3RlY3RlZCByZW5kZXJBbmltYXRlZFNwcml0ZShzcHJpdGU6IEFuaW1hdGVkU3ByaXRlKTogdm9pZCB7XG4gICAgICAgIC8vIEdldCB0aGUgaW1hZ2UgZnJvbSB0aGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAgICBsZXQgaW1hZ2UgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRJbWFnZShzcHJpdGUuaW1hZ2VJZCk7XG5cbiAgICAgICAgbGV0IGFuaW1hdGlvbkluZGV4ID0gc3ByaXRlLmFuaW1hdGlvbi5nZXRJbmRleEFuZEFkdmFuY2VBbmltYXRpb24oKTtcblxuICAgICAgICBsZXQgYW5pbWF0aW9uT2Zmc2V0ID0gc3ByaXRlLmdldEFuaW1hdGlvbk9mZnNldChhbmltYXRpb25JbmRleCk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICAgIENvb3JkaW5hdGVzIGluIHRoZSBzcGFjZSBvZiB0aGUgaW1hZ2U6XG4gICAgICAgICAgICAgICAgaW1hZ2UgY3JvcCBzdGFydCAtPiB4LCB5XG4gICAgICAgICAgICAgICAgaW1hZ2UgY3JvcCBzaXplICAtPiB3LCBoXG4gICAgICAgICAgICBDb29yZGluYXRlcyBpbiB0aGUgc3BhY2Ugb2YgdGhlIHdvcmxkIChnaXZlbiB3ZSBtb3ZlZClcbiAgICAgICAgICAgICAgICBpbWFnZSBkcmF3IHN0YXJ0IC0+IC13LzIsIC1oLzJcbiAgICAgICAgICAgICAgICBpbWFnZSBkcmF3IHNpemUgIC0+IHcsIGhcbiAgICAgICAgKi9cbiAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKGltYWdlLFxuICAgICAgICAgICAgc3ByaXRlLmltYWdlT2Zmc2V0LnggKyBhbmltYXRpb25PZmZzZXQueCwgc3ByaXRlLmltYWdlT2Zmc2V0LnkgKyBhbmltYXRpb25PZmZzZXQueSxcbiAgICAgICAgICAgIHNwcml0ZS5zaXplLngsIHNwcml0ZS5zaXplLnksXG4gICAgICAgICAgICAoLXNwcml0ZS5zaXplLngqc3ByaXRlLnNjYWxlLngvMikqdGhpcy56b29tLCAoLXNwcml0ZS5zaXplLnkqc3ByaXRlLnNjYWxlLnkvMikqdGhpcy56b29tLFxuICAgICAgICAgICAgc3ByaXRlLnNpemUueCAqIHNwcml0ZS5zY2FsZS54KnRoaXMuem9vbSwgc3ByaXRlLnNpemUueSAqIHNwcml0ZS5zY2FsZS55KnRoaXMuem9vbSk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbmRlckdyYXBoaWMoZ3JhcGhpYzogR3JhcGhpYyk6IHZvaWQge1xuICAgICAgICBpZihncmFwaGljIGluc3RhbmNlb2YgUG9pbnQpe1xuICAgICAgICAgICAgdGhpcy5ncmFwaGljUmVuZGVyZXIucmVuZGVyUG9pbnQoPFBvaW50PmdyYXBoaWMsIHRoaXMuem9vbSk7XG4gICAgICAgIH0gZWxzZSBpZihncmFwaGljIGluc3RhbmNlb2YgTGluZSl7XG4gICAgICAgICAgICB0aGlzLmdyYXBoaWNSZW5kZXJlci5yZW5kZXJMaW5lKDxMaW5lPmdyYXBoaWMsIHRoaXMub3JpZ2luLCB0aGlzLnpvb20pO1xuICAgICAgICB9IGVsc2UgaWYoZ3JhcGhpYyBpbnN0YW5jZW9mIFJlY3Qpe1xuICAgICAgICAgICAgdGhpcy5ncmFwaGljUmVuZGVyZXIucmVuZGVyUmVjdCg8UmVjdD5ncmFwaGljLCB0aGlzLnpvb20pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbmRlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQge1xuICAgICAgICBpZih0aWxlbWFwIGluc3RhbmNlb2YgT3J0aG9nb25hbFRpbGVtYXApe1xuICAgICAgICAgICAgdGhpcy50aWxlbWFwUmVuZGVyZXIucmVuZGVyT3J0aG9nb25hbFRpbGVtYXAoPE9ydGhvZ29uYWxUaWxlbWFwPnRpbGVtYXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIHJlbmRlclVJRWxlbWVudCh1aUVsZW1lbnQ6IFVJRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBMYWJlbCl7XG4gICAgICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyLnJlbmRlckxhYmVsKHVpRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBCdXR0b24pe1xuICAgICAgICAgICAgdGhpcy51aUVsZW1lbnRSZW5kZXJlci5yZW5kZXJCdXR0b24odWlFbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmKHVpRWxlbWVudCBpbnN0YW5jZW9mIFNsaWRlcil7XG4gICAgICAgICAgICB0aGlzLnVpRWxlbWVudFJlbmRlcmVyLnJlbmRlclNsaWRlcih1aUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2UgaWYodWlFbGVtZW50IGluc3RhbmNlb2YgVGV4dElucHV0KXtcbiAgICAgICAgICAgIHRoaXMudWlFbGVtZW50UmVuZGVyZXIucmVuZGVyVGV4dElucHV0KHVpRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjbGVhcihjbGVhckNvbG9yOiBDb2xvcik6IHZvaWQge1xuICAgICAgICB0aGlzLmN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy53b3JsZFNpemUueCwgdGhpcy53b3JsZFNpemUueSk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGNsZWFyQ29sb3IudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5jdHguZmlsbFJlY3QoMCwgMCwgdGhpcy53b3JsZFNpemUueCwgdGhpcy53b3JsZFNpemUueSk7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IExpbmUgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL0xpbmVcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vLi4vTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1NjZW5lL1NjZW5lXCI7XG5cbi8qKlxuICogQSB1dGlsaXR5IGNsYXNzIHRvIGhlbHAgdGhlIEByZWZlcmVuY2VbQ2FudmFzUmVuZGVyZXJdIHJlbmRlciBAcmVmZXJlbmNlW0dyYXBoaWNdc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHcmFwaGljUmVuZGVyZXIge1xuICAgIC8qKiBUaGUgcmVzb3VyY2UgbWFuYWdlciBvZiB0aGUgZ2FtZSBlbmdpbmUgKi9cbiAgICBwcm90ZWN0ZWQgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG4gICAgLyoqIFRoZSBjdXJyZW50IHNjZW5lICovXG4gICAgcHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcbiAgICAvKiogVGhlIHJlbmRlcmluZyBjb250ZXh0ICovXG4gICAgcHJvdGVjdGVkIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuXG4gICAgY29uc3RydWN0b3IoY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQpe1xuICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgICAgICB0aGlzLmN0eCA9IGN0eDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBzY2VuZSBvZiB0aGlzIEdyYXBoaWNSZW5kZXJlclxuICAgICAqIEBwYXJhbSBzY2VuZSBUaGUgY3VycmVudCBzY2VuZVxuICAgICAqL1xuICAgIHNldFNjZW5lKHNjZW5lOiBTY2VuZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIHBvaW50XG4gICAgICogQHBhcmFtIHBvaW50IFRoZSBwb2ludCB0byByZW5kZXJcbiAgICAgKiBAcGFyYW0gem9vbSBUaGUgem9vbSBsZXZlbFxuICAgICAqL1xuICAgIHJlbmRlclBvaW50KHBvaW50OiBQb2ludCwgem9vbTogbnVtYmVyKTogdm9pZCB7XG5cdFx0dGhpcy5jdHguZmlsbFN0eWxlID0gcG9pbnQuY29sb3IudG9TdHJpbmdSR0JBKCk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxSZWN0KCgtcG9pbnQuc2l6ZS54LzIpKnpvb20sICgtcG9pbnQuc2l6ZS55LzIpKnpvb20sXG4gICAgICAgIHBvaW50LnNpemUueCp6b29tLCBwb2ludC5zaXplLnkqem9vbSk7XG4gICAgfVxuXG4gICAgcmVuZGVyTGluZShsaW5lOiBMaW5lLCBvcmlnaW46IFZlYzIsIHpvb206IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmN0eC5zdHJva2VTdHlsZSA9IGxpbmUuY29sb3IudG9TdHJpbmdSR0JBKCk7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IGxpbmUudGhpY2tuZXNzO1xuICAgICAgICB0aGlzLmN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgdGhpcy5jdHgubW92ZVRvKDAsIDApO1xuICAgICAgICB0aGlzLmN0eC5saW5lVG8oKGxpbmUuZW5kLnggLSBsaW5lLnN0YXJ0LngpKnpvb20sIChsaW5lLmVuZC55IC0gbGluZS5zdGFydC55KSp6b29tKTtcbiAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7XG4gICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSByZWN0XG4gICAgICogQHBhcmFtIHJlY3QgVGhlIHJlY3QgdG8gcmVuZGVyXG4gICAgICogQHBhcmFtIHpvb20gVGhlIHpvb20gbGV2ZWxcbiAgICAgKi9cbiAgICByZW5kZXJSZWN0KHJlY3Q6IFJlY3QsIHpvb206IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBEcmF3IHRoZSBpbnRlcmlvciBvZiB0aGUgcmVjdFxuICAgICAgICBpZihyZWN0LmNvbG9yLmEgIT09IDApe1xuICAgICAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gcmVjdC5jb2xvci50b1N0cmluZ1JHQigpO1xuICAgICAgICAgICAgaWYgKHJlY3QuZmlsbFdpZHRoICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsbFJlY3QoKC1yZWN0LnNpemUueC8yKSp6b29tLCAoLXJlY3Quc2l6ZS55LzIpKnpvb20sIHJlY3QuZmlsbFdpZHRoKnpvb20sIHJlY3Quc2l6ZS55Knpvb20pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCgoLXJlY3Quc2l6ZS54LzIpKnpvb20sICgtcmVjdC5zaXplLnkvMikqem9vbSwgcmVjdC5zaXplLngqem9vbSwgcmVjdC5zaXplLnkqem9vbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEcmF3IHRoZSBib3JkZXIgb2YgdGhlIHJlY3QgaWYgaXQgaXNuJ3QgdHJhbnNwYXJlbnRcbiAgICAgICAgaWYocmVjdC5ib3JkZXJDb2xvci5hICE9PSAwKXtcbiAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZVN0eWxlID0gcmVjdC5nZXRCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5saW5lV2lkdGggPSByZWN0LmdldEJvcmRlcldpZHRoKCk7XG4gICAgICAgICAgICB0aGlzLmN0eC5zdHJva2VSZWN0KCgtcmVjdC5zaXplLngvMikqem9vbSwgKC1yZWN0LnNpemUueS8yKSp6b29tLCByZWN0LnNpemUueCp6b29tLCByZWN0LnNpemUueSp6b29tKTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBUaWxlc2V0IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZXNldFwiO1xuXG4vKipcbiAqIEEgdXRpbGl0eSBjbGFzcyBmb3IgdGhlIEByZWZlcmVuY2VbQ2FudmFzUmVuZGVyZXJdIHRvIHJlbmRlciBAcmVmZXJlbmNlW1RpbGVtYXBdc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUaWxlbWFwUmVuZGVyZXIge1xuICAgIHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuICAgIGNvbnN0cnVjdG9yKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKXtcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICAgICAgdGhpcy5jdHggPSBjdHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2NlbmUgb2YgdGhpcyBUaWxlbWFwUmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgc2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYW4gb3J0aG9nb25hbCB0aWxlbWFwXG4gICAgICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyT3J0aG9nb25hbFRpbGVtYXAodGlsZW1hcDogT3J0aG9nb25hbFRpbGVtYXApOiB2b2lkIHtcbiAgICAgICAgbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSB0aWxlbWFwLmdldExheWVyKCkuZ2V0QWxwaGEoKTtcbiAgICAgICAgXG4gICAgICAgIGxldCBvcmlnaW4gPSB0aGlzLnNjZW5lLmdldFZpZXdUcmFuc2xhdGlvbih0aWxlbWFwKTtcbiAgICAgICAgbGV0IHNpemUgPSB0aGlzLnNjZW5lLmdldFZpZXdwb3J0KCkuZ2V0SGFsZlNpemUoKTtcbiAgICAgICAgbGV0IHpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuICAgICAgICBsZXQgYm90dG9tUmlnaHQgPSBvcmlnaW4uY2xvbmUoKS5hZGQoc2l6ZS5zY2FsZWQoMip6b29tKSk7XG5cbiAgICAgICAgaWYodGlsZW1hcC52aXNpYmxlKXtcbiAgICAgICAgICAgIGxldCBtaW5Db2xSb3cgPSB0aWxlbWFwLmdldENvbFJvd0F0KG9yaWdpbik7XG4gICAgICAgICAgICBsZXQgbWF4Q29sUm93ID0gdGlsZW1hcC5nZXRDb2xSb3dBdChib3R0b21SaWdodCk7XG5cbiAgICAgICAgICAgIGZvcihsZXQgeCA9IG1pbkNvbFJvdy54OyB4IDw9IG1heENvbFJvdy54OyB4Kyspe1xuICAgICAgICAgICAgICAgIGZvcihsZXQgeSA9IG1pbkNvbFJvdy55OyB5IDw9IG1heENvbFJvdy55OyB5Kyspe1xuICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHRpbGUgYXQgdGhpcyBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBsZXQgdGlsZSA9IHRpbGVtYXAuZ2V0VGlsZUF0Um93Q29sKG5ldyBWZWMyKHgsIHkpKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IHRoZSByb3QvZmxpcCBwYXJhbWV0ZXJzIGlmIHRoZXJlIGFyZSBhbnlcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFzayA9ICgweEUgPDwgMjgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByb3RGbGlwID0gKChtYXNrICYgdGlsZSkgPj4gMjgpICYgMHhGO1xuICAgICAgICAgICAgICAgICAgICB0aWxlID0gdGlsZSAmIH5tYXNrO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpbmQgdGhlIHRpbGVzZXQgdGhhdCBvd25zIHRoaXMgdGlsZSBpbmRleCBhbmQgcmVuZGVyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgdGlsZXNldCBvZiB0aWxlbWFwLmdldFRpbGVzZXRzKCkpe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGlsZXNldC5oYXNUaWxlKHRpbGUpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlclRpbGUodGlsZXNldCwgdGlsZSwgeCwgeSwgb3JpZ2luLCB0aWxlbWFwLnNjYWxlLCB6b29tLCByb3RGbGlwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gcHJldmlvdXNBbHBoYTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgdGlsZVxuICAgICAqIEBwYXJhbSB0aWxlc2V0IFRoZSB0aWxlc2V0IHRoaXMgdGlsZSBiZWxvbmdzIHRvIFxuICAgICAqIEBwYXJhbSB0aWxlSW5kZXggVGhlIGluZGV4IG9mIHRoZSB0aWxlXG4gICAgICogQHBhcmFtIHRpbGVtYXBSb3cgVGhlIHJvdyBvZiB0aGUgdGlsZSBpbiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB0aWxlbWFwQ29sIFRoZSBjb2x1bW4gb2YgdGhlIHRpbGUgaW4gdGhlIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gb3JpZ2luIFRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHNjYWxlIFRoZSBzY2FsZSBvZiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSB6b29tIFRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJUaWxlKHRpbGVzZXQ6IFRpbGVzZXQsIHRpbGVJbmRleDogbnVtYmVyLCB0aWxlbWFwUm93OiBudW1iZXIsIHRpbGVtYXBDb2w6IG51bWJlciwgb3JpZ2luOiBWZWMyLCBzY2FsZTogVmVjMiwgem9vbTogbnVtYmVyLCByb3RGbGlwOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGltYWdlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0SW1hZ2UodGlsZXNldC5nZXRJbWFnZUtleSgpKTtcblxuICAgICAgICAvLyBHZXQgdGhlIHRydWUgaW5kZXhcbiAgICAgICAgbGV0IGluZGV4ID0gdGlsZUluZGV4IC0gdGlsZXNldC5nZXRTdGFydEluZGV4KCk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSByb3cgYW5kIGNvbCBvZiB0aGUgdGlsZSBpbiBpbWFnZSBzcGFjZVxuICAgICAgICBsZXQgcm93ID0gTWF0aC5mbG9vcihpbmRleCAvIHRpbGVzZXQuZ2V0TnVtQ29scygpKTtcbiAgICAgICAgbGV0IGNvbCA9IGluZGV4ICUgdGlsZXNldC5nZXROdW1Db2xzKCk7XG4gICAgICAgIGxldCB3aWR0aCA9IHRpbGVzZXQuZ2V0VGlsZVNpemUoKS54O1xuICAgICAgICBsZXQgaGVpZ2h0ID0gdGlsZXNldC5nZXRUaWxlU2l6ZSgpLnk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBwb3NpdGlvbiB0byBzdGFydCBhIGNyb3AgaW4gdGhlIHRpbGVzZXQgaW1hZ2VcbiAgICAgICAgbGV0IGxlZnQgPSBjb2wgKiB3aWR0aDtcbiAgICAgICAgbGV0IHRvcCA9IHJvdyAqIGhlaWdodDtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHBvc2l0aW9uIGluIHRoZSB3b3JsZCB0byByZW5kZXIgdGhlIHRpbGVcbiAgICAgICAgbGV0IHggPSBNYXRoLmZsb29yKHRpbGVtYXBSb3cgKiB3aWR0aCAqIHNjYWxlLngpO1xuICAgICAgICBsZXQgeSA9IE1hdGguZmxvb3IodGlsZW1hcENvbCAqIGhlaWdodCAqIHNjYWxlLnkpO1xuXG4gICAgICAgIGxldCB3b3JsZFggPSBNYXRoLmZsb29yKCh4IC0gb3JpZ2luLngpKnpvb20pO1xuICAgICAgICBsZXQgd29ybGRZID0gTWF0aC5mbG9vcigoeSAtIG9yaWdpbi55KSp6b29tKTtcbiAgICAgICAgbGV0IHdvcmxkV2lkdGggPSBNYXRoLmNlaWwod2lkdGggKiBzY2FsZS54ICogem9vbSk7XG4gICAgICAgIGxldCB3b3JsZEhlaWdodCA9IE1hdGguY2VpbChoZWlnaHQgKiBzY2FsZS55ICogem9vbSk7XG5cbiAgICAgICAgaWYocm90RmxpcCAhPT0gMCl7XG4gICAgICAgICAgICBsZXQgc2NhbGVYID0gMTtcbiAgICAgICAgICAgIGxldCBzY2FsZVkgPSAxO1xuICAgICAgICAgICAgbGV0IHNoZWFyWCA9IDA7XG4gICAgICAgICAgICBsZXQgc2hlYXJZID0gMDtcblxuICAgICAgICAgICAgLy8gRmxpcCBvbiB0aGUgeC1heGlzXG4gICAgICAgICAgICBpZihyb3RGbGlwICYgOCl7XG4gICAgICAgICAgICAgICAgc2NhbGVYID0gLTE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZsaXAgb24gdGhlIHktYXhpc1xuICAgICAgICAgICAgaWYocm90RmxpcCAmIDQpe1xuICAgICAgICAgICAgICAgIHNjYWxlWSA9IC0xO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGbGlwIG92ZXIgdGhlIGxpbmUgeT14XG4gICAgICAgICAgICBpZihyb3RGbGlwICYgMil7XG4gICAgICAgICAgICAgICAgc2hlYXJYID0gc2NhbGVZO1xuICAgICAgICAgICAgICAgIHNoZWFyWSA9IHNjYWxlWDtcbiAgICAgICAgICAgICAgICBzY2FsZVggPSAwO1xuICAgICAgICAgICAgICAgIHNjYWxlWSA9IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybShzY2FsZVgsIHNoZWFyWCwgc2hlYXJZLCBzY2FsZVksIHdvcmxkWCArIHdvcmxkV2lkdGgvMiwgd29ybGRZICsgd29ybGRIZWlnaHQvMik7XG4gICAgICAgIFxuICAgICAgICAgICAgLy8gUmVuZGVyIHRoZSB0aWxlXG4gICAgICAgICAgICB0aGlzLmN0eC5kcmF3SW1hZ2UoaW1hZ2UsXG4gICAgICAgICAgICAgICAgbGVmdCwgdG9wLFxuICAgICAgICAgICAgICAgIHdpZHRoLCBoZWlnaHQsXG4gICAgICAgICAgICAgICAgLXdvcmxkV2lkdGgvMiwgLXdvcmxkSGVpZ2h0LzIsXG4gICAgICAgICAgICAgICAgd29ybGRXaWR0aCwgd29ybGRIZWlnaHQpO1xuXG4gICAgICAgICAgICBpZihyb3RGbGlwICE9PSAwKXtcbiAgICAgICAgICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBObyByb3RhdGlvbnMsIGRvbid0IGRvIHRoZSBjYWxjdWxhdGlvbnMsIGp1c3QgcmVuZGVyIHRoZSB0aWxlXG4gICAgICAgICAgICAvLyBSZW5kZXIgdGhlIHRpbGVcbiAgICAgICAgICAgIHRoaXMuY3R4LmRyYXdJbWFnZShpbWFnZSxcbiAgICAgICAgICAgICAgICBsZWZ0LCB0b3AsXG4gICAgICAgICAgICAgICAgd2lkdGgsIGhlaWdodCxcbiAgICAgICAgICAgICAgICB3b3JsZFgsIHdvcmxkWSxcbiAgICAgICAgICAgICAgICB3b3JsZFdpZHRoLCB3b3JsZEhlaWdodCk7XG4gICAgICAgIH1cblxuXG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEJ1dHRvbiBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9CdXR0b25cIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IFNsaWRlciBmcm9tIFwiLi4vLi4vTm9kZXMvVUlFbGVtZW50cy9TbGlkZXJcIjtcbmltcG9ydCBUZXh0SW5wdXQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvVGV4dElucHV0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi9VdGlscy9NYXRoVXRpbHNcIjtcblxuLyoqXG4gKiBBIHV0aWxpdHkgY2xhc3MgdG8gaGVscCB0aGUgQHJlZmVyZW5jZVtDYW52YXNSZW5kZXJlcl0gcmVuZGVyIEByZWZlcmVuY2VbVUlFbGVtZW50XXNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVUlFbGVtZW50UmVuZGVyZXIge1xuICAgIHByb3RlY3RlZCByZXNvdXJjZU1hbmFnZXI6IFJlc291cmNlTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgc2NlbmU6IFNjZW5lO1xuICAgIHByb3RlY3RlZCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblxuICAgIGNvbnN0cnVjdG9yKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKSB7XG4gICAgICAgIHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIHRoaXMuY3R4ID0gY3R4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIG9mIHRoaXMgVUlFbGVtZW50UmVuZGVyZXJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGN1cnJlbnQgc2NlbmVcbiAgICAgKi9cbiAgICBzZXRTY2VuZShzY2VuZTogU2NlbmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBsYWJlbFxuICAgICAqIEBwYXJhbSBsYWJlbCBUaGUgbGFiZWwgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyTGFiZWwobGFiZWw6IExhYmVsKTogdm9pZCB7XG4gICAgICAgIC8vIC8vIElmIHRoZSBzaXplIGlzIHVuYXNzaWduZWQgKGJ5IHRoZSB1c2VyIG9yIGF1dG9tYXRpY2FsbHkpIGFzc2lnbiBpdFxuICAgICAgICAvLyBsYWJlbC5oYW5kbGVJbml0aWFsU2l6aW5nKHRoaXMuY3R4KTtcblxuICAgICAgICAvLyAvLyBHcmFiIHRoZSBnbG9iYWwgYWxwaGEgc28gd2UgY2FuIGFkanVzdCBpdCBmb3IgdGhpcyByZW5kZXJcbiAgICAgICAgLy8gbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcblxuICAgICAgICAvLyAvLyBHZXQgdGhlIGZvbnQgYW5kIHRleHQgcG9zaXRpb24gaW4gbGFiZWxcbiAgICAgICAgLy8gdGhpcy5jdHguZm9udCA9IGxhYmVsLmdldEZvbnRTdHJpbmcoKTtcbiAgICAgICAgLy8gbGV0IG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuXG4gICAgICAgIC8vIC8vIFN0cm9rZSBhbmQgZmlsbCBhIHJvdW5kZWQgcmVjdCBhbmQgZ2l2ZSBpdCB0ZXh0XG4gICAgICAgIC8vIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwuYmFja2dyb3VuZENvbG9yLmE7XG4gICAgICAgIC8vIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGxhYmVsLmNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueC8yLCAtbGFiZWwuc2l6ZS55LzIsXG4gICAgICAgIC8vIFx0bGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICAvLyB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJvcmRlckNvbG9yLmE7XG4gICAgICAgIC8vIHRoaXMuY3R4LmxpbmVXaWR0aCA9IGxhYmVsLmJvcmRlcldpZHRoO1xuICAgICAgICAvLyB0aGlzLmN0eC5zdHJva2VSb3VuZGVkUmVjdCgtbGFiZWwuc2l6ZS54LzIsIC1sYWJlbC5zaXplLnkvMixcbiAgICAgICAgLy8gXHRsYWJlbC5zaXplLngsIGxhYmVsLnNpemUueSwgbGFiZWwuYm9yZGVyUmFkaXVzKTtcblxuICAgICAgICAvLyB0aGlzLmN0eC5maWxsU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVUZXh0Q29sb3IoKTtcbiAgICAgICAgLy8gdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBsYWJlbC50ZXh0Q29sb3IuYTtcbiAgICAgICAgLy8gdGhpcy5jdHguZmlsbFRleHQobGFiZWwudGV4dCwgb2Zmc2V0LnggLSBsYWJlbC5zaXplLngvMiwgb2Zmc2V0LnkgLSBsYWJlbC5zaXplLnkvMik7XG5cbiAgICAgICAgLy8gdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgICAgICAvLyBJZiB0aGUgc2l6ZSBpcyB1bmFzc2lnbmVkIChieSB0aGUgdXNlciBvciBhdXRvbWF0aWNhbGx5KSBhc3NpZ24gaXRcbiAgICAgICAgbGV0IGxpbmVzID0gbGFiZWwudGV4dC5zcGxpdCgnXFxuJyk7XG4gICAgICAgIGxldCB0ZW1wVGV4dCA9IGxhYmVsLnRleHQ7XG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBsZXQgbWF4ID0gMDtcbiAgICAgICAgICAgIGxldCBtYXhMZW5ndGhJbmRleCA9IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxpbmVzW2ldLmxlbmd0aCA+IG1heCkge1xuICAgICAgICAgICAgICAgICAgICBtYXggPSBsaW5lc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIG1heExlbmd0aEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYWJlbC50ZXh0ID0gbGluZXNbbWF4TGVuZ3RoSW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIGxhYmVsLmhhbmRsZUluaXRpYWxTaXppbmcodGhpcy5jdHgpO1xuICAgICAgICAvLyBHcmFiIHRoZSBnbG9iYWwgYWxwaGEgc28gd2UgY2FuIGFkanVzdCBpdCBmb3IgdGhpcyByZW5kZXJcbiAgICAgICAgbGV0IHByZXZpb3VzQWxwaGEgPSB0aGlzLmN0eC5nbG9iYWxBbHBoYTtcblxuICAgICAgICAvLyBHZXQgdGhlIGZvbnQgYW5kIHRleHQgcG9zaXRpb24gaW4gbGFiZWxcbiAgICAgICAgdGhpcy5jdHguZm9udCA9IGxhYmVsLmdldEZvbnRTdHJpbmcoKTtcbiAgICAgICAgbGV0IG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuXG4gICAgICAgIC8vIFN0cm9rZSBhbmQgZmlsbCBhIHJvdW5kZWQgcmVjdCBhbmQgZ2l2ZSBpdCB0ZXh0XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwuYmFja2dyb3VuZENvbG9yLmE7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGxhYmVsLmNhbGN1bGF0ZUJhY2tncm91bmRDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoLWxhYmVsLnNpemUueCAvIDIsIC1sYWJlbC5zaXplLnkgLyAyLFxuICAgICAgICAgICAgbGFiZWwuc2l6ZS54LCBsYWJlbC5zaXplLnksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBsYWJlbC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLnRvU3RyaW5nUkdCQSgpO1xuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IGxhYmVsLmJvcmRlckNvbG9yLmE7XG4gICAgICAgIHRoaXMuY3R4LmxpbmVXaWR0aCA9IGxhYmVsLmJvcmRlcldpZHRoO1xuICAgICAgICB0aGlzLmN0eC5zdHJva2VSb3VuZGVkUmVjdCgtbGFiZWwuc2l6ZS54IC8gMiwgLWxhYmVsLnNpemUueSAvIDIsXG4gICAgICAgICAgICBsYWJlbC5zaXplLngsIGxhYmVsLnNpemUueSArICgobGluZXMubGVuZ3RoIC0gMSkgKiBsYWJlbC5mb250U2l6ZSksIGxhYmVsLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gbGFiZWwuY2FsY3VsYXRlVGV4dENvbG9yKCk7XG4gICAgICAgIHRoaXMuY3R4Lmdsb2JhbEFscGhhID0gbGFiZWwudGV4dENvbG9yLmE7XG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxUZXh0KGxhYmVsLnRleHQsIG9mZnNldC54IC0gbGFiZWwuc2l6ZS54IC8gMiwgKG9mZnNldC55IC0gbGFiZWwuc2l6ZS55IC8gMikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGxldCBhZGRpdGlvbmFsWSA9IGkgKiAobGFiZWwuc2l6ZS55IC8gMiArIChsYWJlbC5mb250U2l6ZSA9PT0gNDAgPyAyMCA6IDEwKSk7XG4gICAgICAgICAgICAgICAgbGFiZWwudGV4dCA9IGxpbmVzW2ldO1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IGxhYmVsLmNhbGN1bGF0ZVRleHRPZmZzZXQodGhpcy5jdHgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxUZXh0KGxpbmVzW2ldLCAob2Zmc2V0LnggLSBsYWJlbC5zaXplLnggLyAyKSwgKG9mZnNldC55IC0gbGFiZWwuc2l6ZS55IC8gMiArIGFkZGl0aW9uYWxZKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgICAgICBsYWJlbC50ZXh0ID0gdGVtcFRleHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIGJ1dHRvblxuICAgICAqIEBwYXJhbSBidXR0b24gVGhlIGJ1dHRvbiB0byByZW5kZXJcbiAgICAgKi9cbiAgICByZW5kZXJCdXR0b24oYnV0dG9uOiBCdXR0b24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZW5kZXJMYWJlbChidXR0b24pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBzbGlkZXJcbiAgICAgKiBAcGFyYW0gc2xpZGVyIFRoZSBzbGlkZXIgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyU2xpZGVyKHNsaWRlcjogU2xpZGVyKTogdm9pZCB7XG4gICAgICAgIC8vIEdyYWIgdGhlIGdsb2JhbCBhbHBoYSBzbyB3ZSBjYW4gYWRqdXN0IGl0IGZvciB0aGlzIHJlbmRlclxuICAgICAgICBsZXQgcHJldmlvdXNBbHBoYSA9IHRoaXMuY3R4Lmdsb2JhbEFscGhhO1xuICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IHNsaWRlci5nZXRMYXllcigpLmdldEFscGhhKCk7XG5cbiAgICAgICAgLy8gQ2FsY3VhbGF0ZSB0aGUgc2xpZGVyIHNpemVcbiAgICAgICAgbGV0IHNsaWRlclNpemUgPSBuZXcgVmVjMihzbGlkZXIuc2l6ZS54LCAyKTtcblxuICAgICAgICAvLyBEcmF3IHRoZSBzbGlkZXJcbiAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gc2xpZGVyLnNsaWRlckNvbG9yLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMuY3R4LmZpbGxSb3VuZGVkUmVjdCgtc2xpZGVyU2l6ZS54IC8gMiwgLXNsaWRlclNpemUueSAvIDIsXG4gICAgICAgICAgICBzbGlkZXJTaXplLngsIHNsaWRlclNpemUueSwgc2xpZGVyLmJvcmRlclJhZGl1cyk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuaWIgc2l6ZSBhbmQgcG9zaXRpb25cbiAgICAgICAgbGV0IHggPSBNYXRoVXRpbHMubGVycCgtc2xpZGVyLnNpemUueCAvIDIsIHNsaWRlci5zaXplLnggLyAyLCBzbGlkZXIuZ2V0VmFsdWUoKSk7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgbmliXG4gICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IHNsaWRlci5uaWJDb2xvci50b1N0cmluZygpO1xuICAgICAgICB0aGlzLmN0eC5maWxsUm91bmRlZFJlY3QoeCAtIHNsaWRlci5uaWJTaXplLnggLyAyLCAtc2xpZGVyLm5pYlNpemUueSAvIDIsXG4gICAgICAgICAgICBzbGlkZXIubmliU2l6ZS54LCBzbGlkZXIubmliU2l6ZS55LCBzbGlkZXIuYm9yZGVyUmFkaXVzKTtcblxuICAgICAgICAvLyBSZXNldCB0aGUgYWxwaGFcbiAgICAgICAgdGhpcy5jdHguZ2xvYmFsQWxwaGEgPSBwcmV2aW91c0FscGhhO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSB0ZXh0SW5wdXRcbiAgICAgKiBAcGFyYW0gdGV4dElucHV0IFRoZSB0ZXh0SW5wdXQgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcmVuZGVyVGV4dElucHV0KHRleHRJbnB1dDogVGV4dElucHV0KTogdm9pZCB7XG4gICAgICAgIC8vIFNob3cgYSBjdXJzb3Igc29tZXRpbWVzXG4gICAgICAgIGlmICh0ZXh0SW5wdXQuZm9jdXNlZCAmJiB0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciAlIDYwID4gMzApIHtcbiAgICAgICAgICAgIHRleHRJbnB1dC50ZXh0ICs9IFwifFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXJMYWJlbCh0ZXh0SW5wdXQpO1xuXG4gICAgICAgIGlmICh0ZXh0SW5wdXQuZm9jdXNlZCkge1xuICAgICAgICAgICAgaWYgKHRleHRJbnB1dC5jdXJzb3JDb3VudGVyICUgNjAgPiAzMCkge1xuICAgICAgICAgICAgICAgIHRleHRJbnB1dC50ZXh0ID0gdGV4dElucHV0LnRleHQuc3Vic3RyaW5nKDAsIHRleHRJbnB1dC50ZXh0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0ZXh0SW5wdXQuY3Vyc29yQ291bnRlciArPSAxO1xuICAgICAgICAgICAgaWYgKHRleHRJbnB1dC5jdXJzb3JDb3VudGVyID49IDYwKSB7XG4gICAgICAgICAgICAgICAgdGV4dElucHV0LmN1cnNvckNvdW50ZXIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBHcmFwaGljIGZyb20gXCIuLi9Ob2Rlcy9HcmFwaGljXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgVGlsZW1hcCBmcm9tIFwiLi4vTm9kZXMvVGlsZW1hcFwiO1xuaW1wb3J0IFVJRWxlbWVudCBmcm9tIFwiLi4vTm9kZXMvVUlFbGVtZW50XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmUvU2NlbmVcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcblxuLyoqXG4gKiBBbiBhYnN0cmFjdCBmcmFtZXdvcmsgdG8gcHV0IGFsbCByZW5kZXJpbmcgaW4gb25jZSBwbGFjZSBpbiB0aGUgYXBwbGljYXRpb25cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUmVuZGVyaW5nTWFuYWdlciB7XG4gICAgLyoqIFRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cbiAgICBwcm90ZWN0ZWQgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIHNjZW5lIGN1cnJlbnRseSBiZWluZyByZW5kZXJlZCAqL1xuICAgIHByb3RlY3RlZCBzY2VuZTogU2NlbmU7XG5cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNjZW5lIGN1cnJlbnRseSBiZWluZyByZW5kZXJlZFxuICAgICAqIEBwYXJhbSBzY2VuZSBUaGUgY3VycmVudCBTY2VuZVxuICAgICAqL1xuICAgIHNldFNjZW5lKHNjZW5lOiBTY2VuZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgY2FudmFzIGZvciB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSBjYW52YXMgVGhlIGNhbnZhcyBlbGVtZW50XG4gICAgICogQHBhcmFtIHdpZHRoIFRoZSBkZXNpcmVkIHdpZHRoIG9mIHRoZSBjYW52YXNcbiAgICAgKiBAcGFyYW0gaGVpZ2h0IFRoZSBkZXNpcmVkIGhlaWdodCBvZiB0aGUgY2FudmFzXG4gICAgICogQHJldHVybnMgVGhlIHJlbmRlcmluZyBjb250ZXh0IG9mIHRoZSBjYW52YXNcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBpbml0aWFsaXplQ2FudmFzKGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogYW55O1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgdmlzaWJsZSBzZXQgb2YgQ2FudmFzTm9kZXMgYW5kIHZpc2libGUgcG9ydGlvbnMgb2YgdGlsZW1hcHMsIGFzIHdlbGwgYXMgYW55IFVJRWxlbWVudCBpbiBVSUxheWVyc1xuICAgICAqIEBwYXJhbSB2aXNpYmxlU2V0IFRoZSB2aXNpYmxlIHNldCBvZiBDYW52YXNOb2Rlc1xuICAgICAqIEBwYXJhbSB0aWxlbWFwcyBUaGUgdGlsZW1hcHMgdXNlZCBpbiB0aGUgYXBwbGljYXRpb25cbiAgICAgKiBAcGFyYW0gdWlMYXllcnMgVGhlIHVzZXIgaW50ZXJmYWNlIGxheWVyc1xuICAgICAqL1xuICAgIGFic3RyYWN0IHJlbmRlcih2aXNpYmxlU2V0OiBBcnJheTxDYW52YXNOb2RlPiwgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+LCB1aUxheWVyczogTWFwPFVJTGF5ZXI+KTogdm9pZDtcblxuICAgIC8qKiBDbGVhcnMgdGhlIGNhbnZhcyAqL1xuICAgIGFic3RyYWN0IGNsZWFyKGNvbG9yOiBDb2xvcik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIGEgc3ByaXRlXG4gICAgICogQHBhcmFtIHNwcml0ZSBUaGUgc3ByaXRlIHRvIHJlbmRlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhYnN0cmFjdCByZW5kZXJTcHJpdGUoc3ByaXRlOiBTcHJpdGUpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhbiBhbmltYXRlZCBzcHJpdGVcbiAgICAgKiBAcGFyYW0gc3ByaXRlIFRoZSBhbmltYXRlZCBzcHJpdGUgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlckFuaW1hdGVkU3ByaXRlKHNwcml0ZTogQW5pbWF0ZWRTcHJpdGUpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogUmVuZGVycyBhIGdyYXBoaWNcbiAgICAgKiBAcGFyYW0gZ3JhcGhpYyBUaGUgZ3JhcGhpYyB0byByZW5kZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWJzdHJhY3QgcmVuZGVyR3JhcGhpYyhncmFwaGljOiBHcmFwaGljKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSB0aWxlbWFwXG4gICAgICogQHBhcmFtIHRpbGVtYXAgVGhlIHRpbGVtYXAgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlclRpbGVtYXAodGlsZW1hcDogVGlsZW1hcCk6IHZvaWQ7XG5cblxuICAgIC8qKlxuICAgICAqIFJlbmRlcnMgYSBVSUVsZW1lbnRcbiAgICAgKiBAcGFyYW0gdWlFbGVtZW50IFRoZSBVSUVsZW1lbnQgdG8gcmVuZGVyXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IHJlbmRlclVJRWxlbWVudCh1aUVsZW1lbnQ6IFVJRWxlbWVudCk6IHZvaWQ7XG59IiwiaW1wb3J0IEdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR3JhcGhpYyBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY1wiO1xuaW1wb3J0IHsgR3JhcGhpY1R5cGUgfSBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvR3JhcGhpY1R5cGVzXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgU2hhZGVyUmVnaXN0cnkgZnJvbSBcIi4uL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvU2hhZGVyUmVnaXN0cnlcIjtcbmltcG9ydCBSZWdpc3RyeU1hbmFnZXIgZnJvbSBcIi4uL1JlZ2lzdHJ5L1JlZ2lzdHJ5TWFuYWdlclwiO1xuaW1wb3J0IFJlc291cmNlTWFuYWdlciBmcm9tIFwiLi4vUmVzb3VyY2VNYW5hZ2VyL1Jlc291cmNlTWFuYWdlclwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBSZW5kZXJpbmdVdGlscyBmcm9tIFwiLi4vVXRpbHMvUmVuZGVyaW5nVXRpbHNcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuL1JlbmRlcmluZ01hbmFnZXJcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuL1dlYkdMUmVuZGVyaW5nL1NoYWRlclR5cGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViR0xSZW5kZXJlciBleHRlbmRzIFJlbmRlcmluZ01hbmFnZXIge1xuXG5cdHByb3RlY3RlZCBvcmlnaW46IFZlYzI7XG5cdHByb3RlY3RlZCB6b29tOiBudW1iZXI7XG5cdHByb3RlY3RlZCB3b3JsZFNpemU6IFZlYzI7XG5cblx0cHJvdGVjdGVkIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cdHByb3RlY3RlZCB0ZXh0Q3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7XG5cblx0aW5pdGlhbGl6ZUNhbnZhcyhjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCB7XG5cdFx0Y2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG5cblx0XHR0aGlzLndvcmxkU2l6ZSA9IFZlYzIuWkVSTztcblx0XHR0aGlzLndvcmxkU2l6ZS54ID0gd2lkdGg7XG5cdFx0dGhpcy53b3JsZFNpemUueSA9IGhlaWdodDtcblxuXHRcdC8vIEdldCB0aGUgV2ViR0wgY29udGV4dFxuICAgICAgICB0aGlzLmdsID0gY2FudmFzLmdldENvbnRleHQoXCJ3ZWJnbFwiKTtcblxuXHRcdHRoaXMuZ2wudmlld3BvcnQoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcblxuXHRcdHRoaXMuZ2wuZGlzYWJsZSh0aGlzLmdsLkRFUFRIX1RFU1QpO1xuICAgICAgICB0aGlzLmdsLmVuYWJsZSh0aGlzLmdsLkJMRU5EKTtcbiAgICAgICAgdGhpcy5nbC5ibGVuZEZ1bmModGhpcy5nbC5TUkNfQUxQSEEsIHRoaXMuZ2wuT05FX01JTlVTX1NSQ19BTFBIQSk7XG4gICAgICAgIHRoaXMuZ2wuZW5hYmxlKHRoaXMuZ2wuQ1VMTF9GQUNFKTtcblxuXHRcdC8vIFRlbGwgdGhlIHJlc291cmNlIG1hbmFnZXIgd2UncmUgdXNpbmcgV2ViR0xcblx0XHRSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51c2VXZWJHTCh0cnVlLCB0aGlzLmdsKTtcblxuXHRcdC8vIFNob3cgdGhlIHRleHQgY2FudmFzIGFuZCBnZXQgaXRzIGNvbnRleHRcblx0XHRsZXQgdGV4dENhbnZhcyA9IDxIVE1MQ2FudmFzRWxlbWVudD5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInRleHQtY2FudmFzXCIpO1xuXHRcdHRleHRDYW52YXMuaGlkZGVuID0gZmFsc2U7XG5cdFx0dGhpcy50ZXh0Q3R4ID0gdGV4dENhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cblx0XHQvLyBTaXplIHRoZSB0ZXh0IGNhbnZhcyB0byBiZSB0aGUgc2FtZSBhcyB0aGUgZ2FtZSBjYW52YXNcblx0XHR0ZXh0Q2FudmFzLmhlaWdodCA9IGhlaWdodDtcblx0XHR0ZXh0Q2FudmFzLndpZHRoID0gd2lkdGg7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2w7XG5cdH1cblxuXHRyZW5kZXIodmlzaWJsZVNldDogQ2FudmFzTm9kZVtdLCB0aWxlbWFwczogVGlsZW1hcFtdLCB1aUxheWVyczogTWFwPFVJTGF5ZXI+KTogdm9pZCB7XG5cdFx0Zm9yKGxldCBub2RlIG9mIHZpc2libGVTZXQpe1xuXHRcdFx0dGhpcy5yZW5kZXJOb2RlKG5vZGUpO1xuXHRcdH1cblxuXHRcdHVpTGF5ZXJzLmZvckVhY2goa2V5ID0+IHtcblx0XHRcdGlmKCF1aUxheWVycy5nZXQoa2V5KS5pc0hpZGRlbigpKVxuXHRcdFx0XHR1aUxheWVycy5nZXQoa2V5KS5nZXRJdGVtcygpLmZvckVhY2gobm9kZSA9PiB0aGlzLnJlbmRlck5vZGUoPENhbnZhc05vZGU+bm9kZSkpXG5cdFx0fSk7XG5cdH1cblxuXHRjbGVhcihjb2xvcjogQ29sb3IpOiB2b2lkIHtcblx0XHR0aGlzLmdsLmNsZWFyQ29sb3IoY29sb3IuciwgY29sb3IuZywgY29sb3IuYiwgY29sb3IuYSk7XG5cdFx0dGhpcy5nbC5jbGVhcih0aGlzLmdsLkNPTE9SX0JVRkZFUl9CSVQgfCB0aGlzLmdsLkRFUFRIX0JVRkZFUl9CSVQpO1xuXG5cdFx0dGhpcy50ZXh0Q3R4LmNsZWFyUmVjdCgwLCAwLCB0aGlzLndvcmxkU2l6ZS54LCB0aGlzLndvcmxkU2l6ZS55KTtcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJOb2RlKG5vZGU6IENhbnZhc05vZGUpOiB2b2lkIHtcblx0XHQvLyBDYWxjdWxhdGUgdGhlIG9yaWdpbiBvZiB0aGUgdmlld3BvcnQgYWNjb3JkaW5nIHRvIHRoaXMgc3ByaXRlXG4gICAgICAgIHRoaXMub3JpZ2luID0gdGhpcy5zY2VuZS5nZXRWaWV3VHJhbnNsYXRpb24obm9kZSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB6b29tIGxldmVsIG9mIHRoZSBzY2VuZVxuICAgICAgICB0aGlzLnpvb20gPSB0aGlzLnNjZW5lLmdldFZpZXdTY2FsZSgpO1xuXHRcdFxuXHRcdGlmKG5vZGUuaGFzQ3VzdG9tU2hhZGVyKXtcblx0XHRcdC8vIElmIHRoZSBub2RlIGhhcyBhIGN1c3RvbSBzaGFkZXIsIHJlbmRlciB1c2luZyB0aGF0XG5cdFx0XHR0aGlzLnJlbmRlckN1c3RvbShub2RlKTtcblx0XHR9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIEdyYXBoaWMpe1xuXHRcdFx0dGhpcy5yZW5kZXJHcmFwaGljKG5vZGUpO1xuXHRcdH0gZWxzZSBpZihub2RlIGluc3RhbmNlb2YgU3ByaXRlKXtcblx0XHRcdGlmKG5vZGUgaW5zdGFuY2VvZiBBbmltYXRlZFNwcml0ZSl7XG5cdFx0XHRcdHRoaXMucmVuZGVyQW5pbWF0ZWRTcHJpdGUobm9kZSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnJlbmRlclNwcml0ZShub2RlKTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYobm9kZSBpbnN0YW5jZW9mIFVJRWxlbWVudCl7XG5cdFx0XHR0aGlzLnJlbmRlclVJRWxlbWVudChub2RlKTtcblx0XHR9XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyU3ByaXRlKHNwcml0ZTogU3ByaXRlKTogdm9pZCB7XG5cdFx0bGV0IHNoYWRlciA9IFJlZ2lzdHJ5TWFuYWdlci5zaGFkZXJzLmdldChTaGFkZXJSZWdpc3RyeS5TUFJJVEVfU0hBREVSKTtcblx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyhzcHJpdGUpLCBzcHJpdGUpO1xuXHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdH1cblxuXHRwcm90ZWN0ZWQgcmVuZGVyQW5pbWF0ZWRTcHJpdGUoc3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQoU2hhZGVyUmVnaXN0cnkuU1BSSVRFX1NIQURFUik7XG5cdFx0bGV0IG9wdGlvbnMgPSB0aGlzLmFkZE9wdGlvbnMoc2hhZGVyLmdldE9wdGlvbnMoc3ByaXRlKSwgc3ByaXRlKTtcblx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHR9XG5cblx0cHJvdGVjdGVkIHJlbmRlckdyYXBoaWMoZ3JhcGhpYzogR3JhcGhpYyk6IHZvaWQge1xuXG5cdFx0aWYoZ3JhcGhpYyBpbnN0YW5jZW9mIFBvaW50KXtcblx0XHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQoU2hhZGVyUmVnaXN0cnkuUE9JTlRfU0hBREVSKTtcblx0XHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKGdyYXBoaWMpLCBncmFwaGljKTtcblx0XHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdFx0fSBlbHNlIGlmKGdyYXBoaWMgaW5zdGFuY2VvZiBSZWN0KSB7XG5cdFx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LlJFQ1RfU0hBREVSKTtcblx0XHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKGdyYXBoaWMpLCBncmFwaGljKTtcblx0XHRcdHNoYWRlci5yZW5kZXIodGhpcy5nbCwgb3B0aW9ucyk7XG5cdFx0fSBcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJUaWxlbWFwKHRpbGVtYXA6IFRpbGVtYXApOiB2b2lkIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJNZXRob2Qgbm90IGltcGxlbWVudGVkLlwiKTtcblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJVSUVsZW1lbnQodWlFbGVtZW50OiBVSUVsZW1lbnQpOiB2b2lkIHtcblx0XHRpZih1aUVsZW1lbnQgaW5zdGFuY2VvZiBMYWJlbCl7XG5cdFx0XHRsZXQgc2hhZGVyID0gUmVnaXN0cnlNYW5hZ2VyLnNoYWRlcnMuZ2V0KFNoYWRlclJlZ2lzdHJ5LkxBQkVMX1NIQURFUik7XG5cdFx0XHRsZXQgb3B0aW9ucyA9IHRoaXMuYWRkT3B0aW9ucyhzaGFkZXIuZ2V0T3B0aW9ucyh1aUVsZW1lbnQpLCB1aUVsZW1lbnQpO1xuXHRcdFx0c2hhZGVyLnJlbmRlcih0aGlzLmdsLCBvcHRpb25zKTtcblxuXHRcdFx0dGhpcy50ZXh0Q3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAodWlFbGVtZW50LnBvc2l0aW9uLnggLSB0aGlzLm9yaWdpbi54KSp0aGlzLnpvb20sICh1aUVsZW1lbnQucG9zaXRpb24ueSAtIHRoaXMub3JpZ2luLnkpKnRoaXMuem9vbSk7XG5cdFx0XHR0aGlzLnRleHRDdHgucm90YXRlKC11aUVsZW1lbnQucm90YXRpb24pO1xuXHRcdFx0bGV0IGdsb2JhbEFscGhhID0gdGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhO1xuXHRcdFx0dGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhID0gdWlFbGVtZW50LmFscGhhO1xuXG5cdFx0XHQvLyBSZW5kZXIgdGV4dFxuXHRcdFx0dGhpcy50ZXh0Q3R4LmZvbnQgPSB1aUVsZW1lbnQuZ2V0Rm9udFN0cmluZygpO1xuXHRcdFx0bGV0IG9mZnNldCA9IHVpRWxlbWVudC5jYWxjdWxhdGVUZXh0T2Zmc2V0KHRoaXMudGV4dEN0eCk7XG5cdFx0XHR0aGlzLnRleHRDdHguZmlsbFN0eWxlID0gdWlFbGVtZW50LmNhbGN1bGF0ZVRleHRDb2xvcigpO1xuXHRcdFx0dGhpcy50ZXh0Q3R4Lmdsb2JhbEFscGhhID0gdWlFbGVtZW50LnRleHRDb2xvci5hO1xuXHRcdFx0dGhpcy50ZXh0Q3R4LmZpbGxUZXh0KHVpRWxlbWVudC50ZXh0LCBvZmZzZXQueCAtIHVpRWxlbWVudC5zaXplLngvMiwgb2Zmc2V0LnkgLSB1aUVsZW1lbnQuc2l6ZS55LzIpO1xuXG5cdFx0XHR0aGlzLnRleHRDdHguZ2xvYmFsQWxwaGEgPSBnbG9iYWxBbHBoYTtcbiAgICAgICAgXHR0aGlzLnRleHRDdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApO1xuXHRcdH1cblx0fVxuXG5cdHByb3RlY3RlZCByZW5kZXJDdXN0b20obm9kZTogQ2FudmFzTm9kZSk6IHZvaWQge1xuXHRcdGxldCBzaGFkZXIgPSBSZWdpc3RyeU1hbmFnZXIuc2hhZGVycy5nZXQobm9kZS5jdXN0b21TaGFkZXJLZXkpO1xuXHRcdGxldCBvcHRpb25zID0gdGhpcy5hZGRPcHRpb25zKHNoYWRlci5nZXRPcHRpb25zKG5vZGUpLCBub2RlKTtcblx0XHRzaGFkZXIucmVuZGVyKHRoaXMuZ2wsIG9wdGlvbnMpO1xuXHR9XG5cblx0cHJvdGVjdGVkIGFkZE9wdGlvbnMob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Piwgbm9kZTogQ2FudmFzTm9kZSk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdC8vIEdpdmUgdGhlIHNoYWRlciBhY2Nlc3MgdG8gdGhlIHdvcmxkIHNpemVcblx0XHRvcHRpb25zLndvcmxkU2l6ZSA9IHRoaXMud29ybGRTaXplO1xuXG5cdFx0Ly8gQWRqdXN0IHRoZSBvcmlnaW4gcG9zaXRpb24gdG8gdGhlIHBhcmFsbGF4XG5cdFx0bGV0IGxheWVyID0gbm9kZS5nZXRMYXllcigpO1xuXHRcdGxldCBwYXJhbGxheCA9IG5ldyBWZWMyKDEsIDEpO1xuXHRcdGlmKGxheWVyIGluc3RhbmNlb2YgUGFyYWxsYXhMYXllcil7XG5cdFx0XHRwYXJhbGxheCA9ICg8UGFyYWxsYXhMYXllcj5sYXllcikucGFyYWxsYXg7XG5cdFx0fVxuXG5cdFx0b3B0aW9ucy5vcmlnaW4gPSB0aGlzLm9yaWdpbi5jbG9uZSgpLm11bHQocGFyYWxsYXgpO1xuXG5cdFx0cmV0dXJuIG9wdGlvbnM7XG5cdH1cblxufSIsImltcG9ydCBNYXAgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9NYXBcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi8uLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5cbi8qKlxuICogQSB3cmFwcGVyIGNsYXNzIGZvciBXZWJHTCBzaGFkZXJzLlxuICogVGhpcyBjbGFzcyBpcyBhIHNpbmdsZXRvbiwgYW5kIHRoZXJlIGlzIG9ubHkgb25lIGZvciBlYWNoIHNoYWRlciB0eXBlLlxuICogQWxsIG9iamVjdHMgdGhhdCB1c2UgdGhpcyBzaGFkZXIgdHlwZSB3aWxsIHJlZmVyIHRvIGFuZCBtb2RpZnkgdGhpcyBzYW1lIHR5cGUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFNoYWRlclR5cGUge1xuXHQvKiogVGhlIG5hbWUgb2YgdGhpcyBzaGFkZXIgKi9cblx0cHJvdGVjdGVkIG5hbWU6IHN0cmluZztcblxuXHQvKiogVGhlIGtleSB0byB0aGUgV2ViR0xQcm9ncmFtIGluIHRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHByb2dyYW1LZXk6IHN0cmluZztcblxuXHQvKiogQSByZWZlcmVuY2UgdG8gdGhlIHJlc291cmNlIG1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdGNvbnN0cnVjdG9yKHByb2dyYW1LZXk6IHN0cmluZyl7XG5cdFx0dGhpcy5wcm9ncmFtS2V5ID0gcHJvZ3JhbUtleTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRpYWxpemVzIGFueSBidWZmZXIgb2JqZWN0cyBhc3NvY2lhdGVkIHdpdGggdGhpcyBzaGFkZXIgdHlwZS5cblx0ICogQHBhcmFtIGdsIFRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dFxuXHQgKi9cblx0YWJzdHJhY3QgaW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBMb2FkcyBhbnkgdW5pZm9ybXNcblx0ICogQHBhcmFtIGdsIFRoZSBXZWJHTCByZW5kZXJpbmcgY29udGV4dFxuXHQgKiBAcGFyYW0gb3B0aW9ucyBJbmZvcm1hdGlvbiBhYm91dCB0aGUgb2JqZWN0IHdlJ3JlIGN1cnJlbnRseSByZW5kZXJpbmdcblx0ICovXG5cdGFic3RyYWN0IHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZDtcblxuXHQvKipcblx0ICogRXh0cmFjdHMgdGhlIG9wdGlvbnMgZnJvbSB0aGUgQ2FudmFzTm9kZSBhbmQgZ2l2ZXMgdGhlbSB0byB0aGUgcmVuZGVyIGZ1bmN0aW9uXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGdldCBvcHRpb25zIGZyb21cblx0ICogQHJldHVybnMgQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG9wdGlvbnMgdGhhdCBzaG91bGQgYmUgcGFzc2VkIHRvIHRoZSByZW5kZXIgZnVuY3Rpb25cblx0ICovXG5cdGdldE9wdGlvbnMobm9kZTogQ2FudmFzTm9kZSk6IFJlY29yZDxzdHJpbmcsIGFueT4ge3JldHVybiB7fTt9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uLy4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUXVhZFNoYWRlclR5cGUgZnJvbSBcIi4vUXVhZFNoYWRlclR5cGVcIjtcblxuLyoqICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMYWJlbFNoYWRlclR5cGUgZXh0ZW5kcyBRdWFkU2hhZGVyVHlwZSB7XG5cblx0Y29uc3RydWN0b3IocHJvZ3JhbUtleTogc3RyaW5nKXtcblx0XHRzdXBlcihwcm9ncmFtS2V5KTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlciA9IFJlc291cmNlTWFuYWdlci5nZXRJbnN0YW5jZSgpO1xuXHR9XG5cblx0aW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkIHtcblx0XHR0aGlzLmJ1ZmZlck9iamVjdEtleSA9IFwibGFiZWxcIjtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5jcmVhdGVCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXHR9XG5cblx0cmVuZGVyKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRjb25zdCBiYWNrZ3JvdW5kQ29sb3IgPSBvcHRpb25zLmJhY2tncm91bmRDb2xvci50b1dlYkdMKCk7XG5cdFx0Y29uc3QgYm9yZGVyQ29sb3IgPSBvcHRpb25zLmJvcmRlckNvbG9yLnRvV2ViR0woKTtcblxuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCAyICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHQvLyBVbmlmb3Jtc1xuXHRcdGNvbnN0IHVfQmFja2dyb3VuZENvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9CYWNrZ3JvdW5kQ29sb3JcIik7XG5cdFx0Z2wudW5pZm9ybTRmdih1X0JhY2tncm91bmRDb2xvciwgYmFja2dyb3VuZENvbG9yKTtcblxuICAgICAgICBjb25zdCB1X0JvcmRlckNvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Cb3JkZXJDb2xvclwiKTtcblx0XHRnbC51bmlmb3JtNGZ2KHVfQm9yZGVyQ29sb3IsIGJvcmRlckNvbG9yKTtcblxuICAgICAgICBjb25zdCB1X01heFNpemUgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X01heFNpemVcIik7XG4gICAgICAgIGdsLnVuaWZvcm0yZih1X01heFNpemUsIC12ZXJ0ZXhEYXRhWzBdLCB2ZXJ0ZXhEYXRhWzFdKTtcblxuXHRcdC8vIEdldCB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHQvLyBXZSB3YW50IGEgc3F1YXJlIGZvciBvdXIgcmVuZGVyaW5nIHNwYWNlLCBzbyBnZXQgdGhlIG1heGltdW0gZGltZW5zaW9uIG9mIG91ciBxdWFkXG5cdFx0bGV0IG1heERpbWVuc2lvbiA9IE1hdGgubWF4KG9wdGlvbnMuc2l6ZS54LCBvcHRpb25zLnNpemUueSk7XG5cbiAgICAgICAgY29uc3QgdV9Cb3JkZXJXaWR0aCA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQm9yZGVyV2lkdGhcIik7XG5cdFx0Z2wudW5pZm9ybTFmKHVfQm9yZGVyV2lkdGgsIG9wdGlvbnMuYm9yZGVyV2lkdGgvbWF4RGltZW5zaW9uKTtcblxuICAgICAgICBjb25zdCB1X0JvcmRlclJhZGl1cyA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfQm9yZGVyUmFkaXVzXCIpO1xuXHRcdGdsLnVuaWZvcm0xZih1X0JvcmRlclJhZGl1cywgb3B0aW9ucy5ib3JkZXJSYWRpdXMvbWF4RGltZW5zaW9uKTtcblxuXHRcdC8vIFRoZSBzaXplIG9mIHRoZSByZW5kZXJpbmcgc3BhY2Ugd2lsbCBiZSBhIHNxdWFyZSB3aXRoIHRoaXMgbWF4aW11bSBkaW1lbnNpb25cblx0XHRsZXQgc2l6ZSA9IG5ldyBWZWMyKG1heERpbWVuc2lvbiwgbWF4RGltZW5zaW9uKS5zY2FsZSgyL29wdGlvbnMud29ybGRTaXplLngsIDIvb3B0aW9ucy53b3JsZFNpemUueSk7XG5cblx0XHQvLyBDZW50ZXIgb3VyIHRyYW5zbGF0aW9ucyBhcm91bmQgKDAsIDApXG5cdFx0Y29uc3QgdHJhbnNsYXRlWCA9IChvcHRpb25zLnBvc2l0aW9uLnggLSBvcHRpb25zLm9yaWdpbi54IC0gb3B0aW9ucy53b3JsZFNpemUueC8yKS9tYXhEaW1lbnNpb247XG5cdFx0Y29uc3QgdHJhbnNsYXRlWSA9IC0ob3B0aW9ucy5wb3NpdGlvbi55IC0gb3B0aW9ucy5vcmlnaW4ueSAtIG9wdGlvbnMud29ybGRTaXplLnkvMikvbWF4RGltZW5zaW9uO1xuXG5cdFx0Ly8gQ3JlYXRlIG91ciB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHR0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShuZXcgRmxvYXQzMkFycmF5KFt0cmFuc2xhdGVYLCB0cmFuc2xhdGVZXSkpO1xuXHRcdHRoaXMuc2NhbGUuc2NhbGUoc2l6ZSk7XG5cdFx0dGhpcy5yb3RhdGlvbi5yb3RhdGUob3B0aW9ucy5yb3RhdGlvbik7XG5cdFx0bGV0IHRyYW5zZm9ybWF0aW9uID0gTWF0NHg0Lk1VTFQodGhpcy50cmFuc2xhdGlvbiwgdGhpcy5zY2FsZSwgdGhpcy5yb3RhdGlvbik7XG5cblx0XHQvLyBQYXNzIHRoZSB0cmFuc2xhdGlvbiBtYXRyaXggdG8gb3VyIHNoYWRlclxuXHRcdGNvbnN0IHVfVHJhbnNmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9UcmFuc2Zvcm1cIik7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDRmdih1X1RyYW5zZm9ybSwgZmFsc2UsIHRyYW5zZm9ybWF0aW9uLnRvQXJyYXkoKSk7XG5cblx0XHQvLyBEcmF3IHRoZSBxdWFkXG5cdFx0Z2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHJlbmRlcmluZyBzcGFjZSBhbHdheXMgaGFzIHRvIGJlIGEgc3F1YXJlLCBzbyBtYWtlIHN1cmUgaXRzIHNxdWFyZSB3LnIudCB0byB0aGUgbGFyZ2VzdCBkaW1lbnNpb25cblx0ICogQHBhcmFtIHcgVGhlIHdpZHRoIG9mIHRoZSBxdWFkIGluIHBpeGVsc1xuXHQgKiBAcGFyYW0gaCBUaGUgaGVpZ2h0IG9mIHRoZSBxdWFkIGluIHBpeGVsc1xuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBvZiB0aGUgdmVydGljZXMgb2YgdGhlIHF1YWRcblx0ICovXG5cdGdldFZlcnRpY2VzKHc6IG51bWJlciwgaDogbnVtYmVyKTogRmxvYXQzMkFycmF5IHtcblx0XHRsZXQgeCwgeTtcblxuXHRcdGlmKGggPiB3KXtcblx0XHRcdHkgPSAwLjU7XG5cdFx0XHR4ID0gdy8oMipoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0eCA9IDAuNTtcblx0XHRcdHkgPSBoLygyKncpO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdC14LCAgeSxcblx0XHRcdC14LCAteSxcblx0XHRcdCB4LCAgeSxcblx0XHRcdCB4LCAteVxuXHRcdF0pO1xuXHR9XG5cblx0Z2V0T3B0aW9ucyhyZWN0OiBMYWJlbCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHJlY3QucG9zaXRpb24sXG5cdFx0XHRiYWNrZ3JvdW5kQ29sb3I6IHJlY3QuY2FsY3VsYXRlQmFja2dyb3VuZENvbG9yKCksXG4gICAgICAgICAgICBib3JkZXJDb2xvcjogcmVjdC5jYWxjdWxhdGVCb3JkZXJDb2xvcigpLFxuICAgICAgICAgICAgYm9yZGVyV2lkdGg6IHJlY3QuYm9yZGVyV2lkdGgsXG4gICAgICAgICAgICBib3JkZXJSYWRpdXM6IHJlY3QuYm9yZGVyUmFkaXVzLFxuXHRcdFx0c2l6ZTogcmVjdC5zaXplLFxuXHRcdFx0cm90YXRpb246IHJlY3Qucm90YXRpb25cblx0XHR9XG5cblx0XHRyZXR1cm4gb3B0aW9ucztcblx0fVxufSIsImltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBSZW5kZXJpbmdVdGlscyBmcm9tIFwiLi4vLi4vLi4vVXRpbHMvUmVuZGVyaW5nVXRpbHNcIjtcbmltcG9ydCBTaGFkZXJUeXBlIGZyb20gXCIuLi9TaGFkZXJUeXBlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvaW50U2hhZGVyVHlwZSBleHRlbmRzIFNoYWRlclR5cGUge1xuXG5cdHByb3RlY3RlZCBidWZmZXJPYmplY3RLZXk6IHN0cmluZztcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXHR9XG5cblx0aW5pdEJ1ZmZlck9iamVjdCgpOiB2b2lkIHtcblx0XHR0aGlzLmJ1ZmZlck9iamVjdEtleSA9IFwicG9pbnRcIjtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5jcmVhdGVCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXHR9XG5cblx0cmVuZGVyKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRsZXQgcG9zaXRpb24gPSBSZW5kZXJpbmdVdGlscy50b1dlYkdMQ29vcmRzKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMub3JpZ2luLCBvcHRpb25zLndvcmxkU2l6ZSk7XG5cdFx0bGV0IGNvbG9yID0gUmVuZGVyaW5nVXRpbHMudG9XZWJHTENvbG9yKG9wdGlvbnMuY29sb3IpO1xuXG5cdFx0Y29uc3QgcHJvZ3JhbSA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldFNoYWRlclByb2dyYW0odGhpcy5wcm9ncmFtS2V5KTtcblx0XHRjb25zdCBidWZmZXIgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRCdWZmZXIodGhpcy5idWZmZXJPYmplY3RLZXkpO1xuXG5cdFx0Z2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcblxuXHRcdGNvbnN0IHZlcnRleERhdGEgPSBwb3NpdGlvbjtcblxuXHRcdGNvbnN0IEZTSVpFID0gdmVydGV4RGF0YS5CWVRFU19QRVJfRUxFTUVOVDtcblxuXHRcdC8vIEJpbmQgdGhlIGJ1ZmZlclxuXHRcdGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBidWZmZXIpO1xuXHRcdGdsLmJ1ZmZlckRhdGEoZ2wuQVJSQVlfQlVGRkVSLCB2ZXJ0ZXhEYXRhLCBnbC5TVEFUSUNfRFJBVyk7XG5cblx0XHQvLyBBdHRyaWJ1dGVzXG5cdFx0Y29uc3QgYV9Qb3NpdGlvbiA9IGdsLmdldEF0dHJpYkxvY2F0aW9uKHByb2dyYW0sIFwiYV9Qb3NpdGlvblwiKTtcblx0XHRnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKGFfUG9zaXRpb24sIDIsIGdsLkZMT0FULCBmYWxzZSwgMiAqIEZTSVpFLCAwICogRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfUG9zaXRpb24pO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHRjb25zdCB1X0NvbG9yID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Db2xvclwiKTtcblx0XHRnbC51bmlmb3JtNGZ2KHVfQ29sb3IsIGNvbG9yKTtcblxuXHRcdGNvbnN0IHVfUG9pbnRTaXplID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9Qb2ludFNpemVcIik7XG5cdFx0Z2wudW5pZm9ybTFmKHVfUG9pbnRTaXplLCBvcHRpb25zLnBvaW50U2l6ZSk7XG5cblx0XHRnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgMSk7XG5cdH1cblxuXHRnZXRPcHRpb25zKHBvaW50OiBQb2ludCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHBvaW50LnBvc2l0aW9uLFxuXHRcdFx0Y29sb3I6IHBvaW50LmNvbG9yLFxuXHRcdFx0cG9pbnRTaXplOiBwb2ludC5zaXplLFxuXHRcdH1cblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG59IiwiaW1wb3J0IE1hdDR4NCBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL01hdDR4NFwiO1xuaW1wb3J0IFNoYWRlclR5cGUgZnJvbSBcIi4uL1NoYWRlclR5cGVcIjtcblxuLyoqIFJlcHJlc2VudHMgYW55IFdlYkdMIG9iamVjdHMgdGhhdCBoYXZlIGEgcXVhZCBtZXNoIChpLmUuIGEgcmVjdGFuZ3VsYXIgZ2FtZSBvYmplY3QgY29tcG9zZWQgb2Ygb25seSB0d28gdHJpYW5nbGVzKSAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUXVhZFNoYWRlclR5cGUgZXh0ZW5kcyBTaGFkZXJUeXBlIHtcblx0LyoqIFRoZSBrZXkgdG8gdGhlIGJ1ZmZlciBvYmplY3QgZm9yIHRoaXMgc2hhZGVyICovXG5cdHByb3RlY3RlZCBidWZmZXJPYmplY3RLZXk6IHN0cmluZztcblxuXHQvKiogVGhlIHNjYWxlIG1hdHJpYyAqL1xuXHRwcm90ZWN0ZWQgc2NhbGU6IE1hdDR4NDtcblxuXHQvKiogVGhlIHJvdGF0aW9uIG1hdHJpeCAqL1xuXHRwcm90ZWN0ZWQgcm90YXRpb246IE1hdDR4NDtcblxuXHQvKiogVGhlIHRyYW5zbGF0aW9uIG1hdHJpeCAqL1xuXHRwcm90ZWN0ZWQgdHJhbnNsYXRpb246IE1hdDR4NDtcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXG5cdFx0dGhpcy5zY2FsZSA9IE1hdDR4NC5JREVOVElUWTtcblx0XHR0aGlzLnJvdGF0aW9uID0gTWF0NHg0LklERU5USVRZO1xuXHRcdHRoaXMudHJhbnNsYXRpb24gPSBNYXQ0eDQuSURFTlRJVFk7XG5cdH1cbn0iLCJpbXBvcnQgTWF0NHg0IGZyb20gXCIuLi8uLi8uLi9EYXRhVHlwZXMvTWF0NHg0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi8uLi9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgUXVhZFNoYWRlclR5cGUgZnJvbSBcIi4vUXVhZFNoYWRlclR5cGVcIjtcblxuLyoqICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWN0U2hhZGVyVHlwZSBleHRlbmRzIFF1YWRTaGFkZXJUeXBlIHtcblxuXHRjb25zdHJ1Y3Rvcihwcm9ncmFtS2V5OiBzdHJpbmcpe1xuXHRcdHN1cGVyKHByb2dyYW1LZXkpO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHRpbml0QnVmZmVyT2JqZWN0KCk6IHZvaWQge1xuXHRcdHRoaXMuYnVmZmVyT2JqZWN0S2V5ID0gXCJyZWN0XCI7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIuY3JlYXRlQnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0fVxuXG5cdHJlbmRlcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Y29uc3QgY29sb3IgPSBvcHRpb25zLmNvbG9yLnRvV2ViR0woKTtcblxuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCAyICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHQvLyBVbmlmb3Jtc1xuXHRcdGNvbnN0IHVfQ29sb3IgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X0NvbG9yXCIpO1xuXHRcdGdsLnVuaWZvcm00ZnYodV9Db2xvciwgY29sb3IpO1xuXG5cdFx0Ly8gR2V0IHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxuXHRcdC8vIFdlIHdhbnQgYSBzcXVhcmUgZm9yIG91ciByZW5kZXJpbmcgc3BhY2UsIHNvIGdldCB0aGUgbWF4aW11bSBkaW1lbnNpb24gb2Ygb3VyIHF1YWRcblx0XHRsZXQgbWF4RGltZW5zaW9uID0gTWF0aC5tYXgob3B0aW9ucy5zaXplLngsIG9wdGlvbnMuc2l6ZS55KTtcblxuXHRcdC8vIFRoZSBzaXplIG9mIHRoZSByZW5kZXJpbmcgc3BhY2Ugd2lsbCBiZSBhIHNxdWFyZSB3aXRoIHRoaXMgbWF4aW11bSBkaW1lbnNpb25cblx0XHRsZXQgc2l6ZSA9IG5ldyBWZWMyKG1heERpbWVuc2lvbiwgbWF4RGltZW5zaW9uKS5zY2FsZSgyL29wdGlvbnMud29ybGRTaXplLngsIDIvb3B0aW9ucy53b3JsZFNpemUueSk7XG5cblx0XHQvLyBDZW50ZXIgb3VyIHRyYW5zbGF0aW9ucyBhcm91bmQgKDAsIDApXG5cdFx0Y29uc3QgdHJhbnNsYXRlWCA9IChvcHRpb25zLnBvc2l0aW9uLnggLSBvcHRpb25zLm9yaWdpbi54IC0gb3B0aW9ucy53b3JsZFNpemUueC8yKS9tYXhEaW1lbnNpb247XG5cdFx0Y29uc3QgdHJhbnNsYXRlWSA9IC0ob3B0aW9ucy5wb3NpdGlvbi55IC0gb3B0aW9ucy5vcmlnaW4ueSAtIG9wdGlvbnMud29ybGRTaXplLnkvMikvbWF4RGltZW5zaW9uO1xuXG5cdFx0Ly8gQ3JlYXRlIG91ciB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcblx0XHR0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShuZXcgRmxvYXQzMkFycmF5KFt0cmFuc2xhdGVYLCB0cmFuc2xhdGVZXSkpO1xuXHRcdHRoaXMuc2NhbGUuc2NhbGUoc2l6ZSk7XG5cdFx0dGhpcy5yb3RhdGlvbi5yb3RhdGUob3B0aW9ucy5yb3RhdGlvbik7XG5cdFx0bGV0IHRyYW5zZm9ybWF0aW9uID0gTWF0NHg0Lk1VTFQodGhpcy50cmFuc2xhdGlvbiwgdGhpcy5zY2FsZSwgdGhpcy5yb3RhdGlvbik7XG5cblx0XHQvLyBQYXNzIHRoZSB0cmFuc2xhdGlvbiBtYXRyaXggdG8gb3VyIHNoYWRlclxuXHRcdGNvbnN0IHVfVHJhbnNmb3JtID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV9UcmFuc2Zvcm1cIik7XG5cdFx0Z2wudW5pZm9ybU1hdHJpeDRmdih1X1RyYW5zZm9ybSwgZmFsc2UsIHRyYW5zZm9ybWF0aW9uLnRvQXJyYXkoKSk7XG5cblx0XHQvLyBEcmF3IHRoZSBxdWFkXG5cdFx0Z2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG5cdH1cblxuXG5cdC8qXG5cdFx0U28gYXMgaXQgdHVybnMgb3V0LCBXZWJHTCBoYXMgYW4gaXNzdWUgd2l0aCBub24tc3F1YXJlIHF1YWRzLlxuXHRcdEl0IGRvZXNuJ3QgbGlrZSB3aGVuIHlvdSBkb24ndCBoYXZlIGEgMS0xIHNjYWxlLCBhbmQgcm90YXRpb25zIGFyZSBlbnRpcmVseSBtZXNzZWQgdXAgaWYgdGhpcyBpcyBub3QgdGhlIGNhc2UuXG5cdFx0VG8gc29sdmUgdGhpcywgSSB1c2VkIHRoZSBzY2FsZSBvZiB0aGUgTEFSR0VTVCBkaW1lbnNpb24gb2YgdGhlIHF1YWQgdG8gbWFrZSBhIHNxdWFyZSwgdGhlbiBhZGp1c3RlZCB0aGUgdmVydGV4IGNvb3JkaW5hdGVzIGluc2lkZSBvZiB0aGF0LlxuXHRcdEEgZGlhZ3JhbSBvZiB0aGUgc29sdXRpb24gZm9sbG93cy5cblxuXHRcdFRoZXJlIGlzIGEgYm91bmRpbmcgc3F1YXJlIGZvciB0aGUgcXVhZCB3aXRoIGRpbWVuc2lvbnMgaHhoIChpbiB0aGlzIGNhc2UsIHNpbmNlIGhlaWdodCBpcyB0aGUgbGFyZ2VzdCBkaW1lbnNpb24pLlxuXHRcdFRoZSBvZmZzZXQgaW4gdGhlIHZlcnRpY2FsIGRpcmVjdGlvbiBpcyB0aGVyZWZvcmUgMC41LCBhcyBpdCBpcyBub3JtYWxseS5cblx0XHRIb3dldmVyLCB0aGUgb2Zmc2V0IGluIHRoZSBob3Jpem9udGFsIGRpcmVjdGlvbiBpcyBub3Qgc28gc3RyYWlnaHRmb3J3YXJkLCBidXQgaXNuJ3QgY29uY2VwdHVhbGx5IGhhcmQuXG5cdFx0QWxsIHdlIHJlYWxseSBoYXZlIHRvIGRvIGlzIGEgcmFuZ2UgY2hhbmdlIGZyb20gWzAsIGhlaWdodC8yXSB0byBbMCwgMC41XSwgd2hlcmUgb3VyIHZhbHVlIGlzIHQgPSB3aWR0aC8yLCBhbmQgMCA8PSB0IDw9IGhlaWdodC8yLlxuXG5cdFx0U28gbm93IHdlIGhhdmUgb3VyIHJlY3QsIGluIGEgc3BhY2Ugc2NhbGVkIHdpdGggcmVzcGVjdCB0byB0aGUgbGFyZ2VzdCBkaW1lbnNpb24uXG5cdFx0Um90YXRpb25zIHdvcmsgYXMgeW91IHdvdWxkIGV4cGVjdCwgZXZlbiBmb3IgbG9uZyByZWN0YW5nbGVzLlxuXG5cdFx0XHRcdFx0MC41XG5cdFx0XHRfXyBfXyBfXyBfXyBfXyBfXyBfX1xuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdFx0fFx0fDg4ODg4ODg4ODg4fFx0fFxuXHRcdC0wLjV8XyBffDg4ODg4ODg4ODg4fF8gX3wwLjVcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0XHRcdHxcdHw4ODg4ODg4ODg4OHxcdHxcblx0ICBcdFx0fF9fX3w4ODg4ODg4ODg4OHxfX198XG5cdFx0XHQgIFx0XHQtMC41XG5cblx0XHRUaGUgZ2V0VmVydGljZXMgZnVuY3Rpb24gYmVsb3cgZG9lcyBhcyBkZXNjcmliZWQsIGFuZCBjb252ZXJ0cyB0aGUgcmFuZ2Vcblx0Ki9cblx0LyoqXG5cdCAqIFRoZSByZW5kZXJpbmcgc3BhY2UgYWx3YXlzIGhhcyB0byBiZSBhIHNxdWFyZSwgc28gbWFrZSBzdXJlIGl0cyBzcXVhcmUgdy5yLnQgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uXG5cdCAqIEBwYXJhbSB3IFRoZSB3aWR0aCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHBhcmFtIGggVGhlIGhlaWdodCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgdGhlIHZlcnRpY2VzIG9mIHRoZSBxdWFkXG5cdCAqL1xuXHRnZXRWZXJ0aWNlcyh3OiBudW1iZXIsIGg6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XG5cdFx0bGV0IHgsIHk7XG5cblx0XHRpZihoID4gdyl7XG5cdFx0XHR5ID0gMC41O1xuXHRcdFx0eCA9IHcvKDIqaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSAwLjU7XG5cdFx0XHR5ID0gaC8oMip3KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IEZsb2F0MzJBcnJheShbXG5cdFx0XHQteCwgIHksXG5cdFx0XHQteCwgLXksXG5cdFx0XHQgeCwgIHksXG5cdFx0XHQgeCwgLXlcblx0XHRdKTtcblx0fVxuXG5cdGdldE9wdGlvbnMocmVjdDogUmVjdCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHJlY3QucG9zaXRpb24sXG5cdFx0XHRjb2xvcjogcmVjdC5jb2xvcixcblx0XHRcdHNpemU6IHJlY3Quc2l6ZSxcblx0XHRcdHJvdGF0aW9uOiByZWN0LnJvdGF0aW9uXG5cdFx0fVxuXG5cdFx0cmV0dXJuIG9wdGlvbnM7XG5cdH1cbn0iLCJpbXBvcnQgTWF0NHg0IGZyb20gXCIuLi8uLi8uLi9EYXRhVHlwZXMvTWF0NHg0XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vLi4vRGVidWcvRGVidWdcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBRdWFkU2hhZGVyVHlwZSBmcm9tIFwiLi9RdWFkU2hhZGVyVHlwZVwiO1xuXG4vKiogQSBzaGFkZXIgZm9yIHNwcml0ZXMgYW5kIGFuaW1hdGVkIHNwcml0ZXMgKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwcml0ZVNoYWRlclR5cGUgZXh0ZW5kcyBRdWFkU2hhZGVyVHlwZSB7XG5cdGNvbnN0cnVjdG9yKHByb2dyYW1LZXk6IHN0cmluZyl7XG5cdFx0c3VwZXIocHJvZ3JhbUtleSk7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcblx0fVxuXG5cdGluaXRCdWZmZXJPYmplY3QoKTogdm9pZCB7XG5cdFx0dGhpcy5idWZmZXJPYmplY3RLZXkgPSBcInNwcml0ZVwiO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyLmNyZWF0ZUJ1ZmZlcih0aGlzLmJ1ZmZlck9iamVjdEtleSk7XG5cdH1cblxuXHRyZW5kZXIoZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuXHRcdGNvbnN0IHByb2dyYW0gPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRTaGFkZXJQcm9ncmFtKHRoaXMucHJvZ3JhbUtleSk7XG5cdFx0Y29uc3QgYnVmZmVyID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0QnVmZmVyKHRoaXMuYnVmZmVyT2JqZWN0S2V5KTtcblx0XHRjb25zdCB0ZXh0dXJlID0gdGhpcy5yZXNvdXJjZU1hbmFnZXIuZ2V0VGV4dHVyZShvcHRpb25zLmltYWdlS2V5KTtcblxuXHRcdGdsLnVzZVByb2dyYW0ocHJvZ3JhbSk7XG5cblx0XHRjb25zdCB2ZXJ0ZXhEYXRhID0gdGhpcy5nZXRWZXJ0aWNlcyhvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnksIG9wdGlvbnMuc2NhbGUpO1xuXG5cdFx0Y29uc3QgRlNJWkUgPSB2ZXJ0ZXhEYXRhLkJZVEVTX1BFUl9FTEVNRU5UO1xuXG5cdFx0Ly8gQmluZCB0aGUgYnVmZmVyXG5cdFx0Z2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG5cdFx0Z2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIHZlcnRleERhdGEsIGdsLlNUQVRJQ19EUkFXKTtcblxuXHRcdC8vIEF0dHJpYnV0ZXNcblx0XHRjb25zdCBhX1Bvc2l0aW9uID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1Bvc2l0aW9uXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9Qb3NpdGlvbiwgMiwgZ2wuRkxPQVQsIGZhbHNlLCA0ICogRlNJWkUsIDAgKiBGU0laRSk7XG5cdFx0Z2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYV9Qb3NpdGlvbik7XG5cblx0XHRjb25zdCBhX1RleENvb3JkID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgXCJhX1RleENvb3JkXCIpO1xuXHRcdGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoYV9UZXhDb29yZCwgMiwgZ2wuRkxPQVQsIGZhbHNlLCA0ICogRlNJWkUsIDIqRlNJWkUpO1xuXHRcdGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGFfVGV4Q29vcmQpO1xuXG5cdFx0Ly8gVW5pZm9ybXNcblx0XHQvLyBHZXQgdHJhbnNmb3JtYXRpb24gbWF0cml4XG5cdFx0Ly8gV2Ugd2FudCBhIHNxdWFyZSBmb3Igb3VyIHJlbmRlcmluZyBzcGFjZSwgc28gZ2V0IHRoZSBtYXhpbXVtIGRpbWVuc2lvbiBvZiBvdXIgcXVhZFxuXHRcdGxldCBtYXhEaW1lbnNpb24gPSBNYXRoLm1heChvcHRpb25zLnNpemUueCwgb3B0aW9ucy5zaXplLnkpO1xuXG5cdFx0Ly8gVGhlIHNpemUgb2YgdGhlIHJlbmRlcmluZyBzcGFjZSB3aWxsIGJlIGEgc3F1YXJlIHdpdGggdGhpcyBtYXhpbXVtIGRpbWVuc2lvblxuXHRcdGxldCBzaXplID0gbmV3IFZlYzIobWF4RGltZW5zaW9uLCBtYXhEaW1lbnNpb24pLnNjYWxlKDIvb3B0aW9ucy53b3JsZFNpemUueCwgMi9vcHRpb25zLndvcmxkU2l6ZS55KTtcblxuXHRcdC8vIENlbnRlciBvdXIgdHJhbnNsYXRpb25zIGFyb3VuZCAoMCwgMClcblx0XHRjb25zdCB0cmFuc2xhdGVYID0gKG9wdGlvbnMucG9zaXRpb24ueCAtIG9wdGlvbnMub3JpZ2luLnggLSBvcHRpb25zLndvcmxkU2l6ZS54LzIpL21heERpbWVuc2lvbjtcblx0XHRjb25zdCB0cmFuc2xhdGVZID0gLShvcHRpb25zLnBvc2l0aW9uLnkgLSBvcHRpb25zLm9yaWdpbi55IC0gb3B0aW9ucy53b3JsZFNpemUueS8yKS9tYXhEaW1lbnNpb247XG5cblx0XHQvLyBDcmVhdGUgb3VyIHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxuXHRcdHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKG5ldyBGbG9hdDMyQXJyYXkoW3RyYW5zbGF0ZVgsIHRyYW5zbGF0ZVldKSk7XG5cdFx0dGhpcy5zY2FsZS5zY2FsZShzaXplKTtcblx0XHR0aGlzLnJvdGF0aW9uLnJvdGF0ZShvcHRpb25zLnJvdGF0aW9uKTtcblx0XHRsZXQgdHJhbnNmb3JtYXRpb24gPSBNYXQ0eDQuTVVMVCh0aGlzLnRyYW5zbGF0aW9uLCB0aGlzLnNjYWxlLCB0aGlzLnJvdGF0aW9uKTtcblxuXHRcdC8vIFBhc3MgdGhlIHRyYW5zbGF0aW9uIG1hdHJpeCB0byBvdXIgc2hhZGVyXG5cdFx0Y29uc3QgdV9UcmFuc2Zvcm0gPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X1RyYW5zZm9ybVwiKTtcblx0XHRnbC51bmlmb3JtTWF0cml4NGZ2KHVfVHJhbnNmb3JtLCBmYWxzZSwgdHJhbnNmb3JtYXRpb24udG9BcnJheSgpKTtcblxuXHRcdC8vIFNldCB1cCBvdXIgc2FtcGxlciB3aXRoIG91ciBhc3NpZ25lZCB0ZXh0dXJlIHVuaXRcblx0XHRjb25zdCB1X1NhbXBsZXIgPSBnbC5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgXCJ1X1NhbXBsZXJcIik7XG5cdFx0Z2wudW5pZm9ybTFpKHVfU2FtcGxlciwgdGV4dHVyZSk7XG5cblx0XHQvLyBQYXNzIGluIHRleFNoaWZ0XG5cdFx0Y29uc3QgdV90ZXhTaGlmdCA9IGdsLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBcInVfdGV4U2hpZnRcIik7XG5cdFx0Z2wudW5pZm9ybTJmdih1X3RleFNoaWZ0LCBvcHRpb25zLnRleFNoaWZ0KTtcblxuXHRcdC8vIFBhc3MgaW4gdGV4U2NhbGVcblx0XHRjb25zdCB1X3RleFNjYWxlID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIFwidV90ZXhTY2FsZVwiKTtcblx0XHRnbC51bmlmb3JtMmZ2KHVfdGV4U2NhbGUsIG9wdGlvbnMudGV4U2NhbGUpO1xuXG5cdFx0Ly8gRHJhdyB0aGUgcXVhZFxuXHRcdGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSByZW5kZXJpbmcgc3BhY2UgYWx3YXlzIGhhcyB0byBiZSBhIHNxdWFyZSwgc28gbWFrZSBzdXJlIGl0cyBzcXVhcmUgdy5yLnQgdG8gdGhlIGxhcmdlc3QgZGltZW5zaW9uXG5cdCAqIEBwYXJhbSB3IFRoZSB3aWR0aCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHBhcmFtIGggVGhlIGhlaWdodCBvZiB0aGUgcXVhZCBpbiBwaXhlbHNcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2YgdGhlIHZlcnRpY2VzIG9mIHRoZSBxdWFkXG5cdCAqL1xuXHRnZXRWZXJ0aWNlcyh3OiBudW1iZXIsIGg6IG51bWJlciwgc2NhbGU6IEZsb2F0MzJBcnJheSk6IEZsb2F0MzJBcnJheSB7XG5cdFx0bGV0IHgsIHk7XG5cblx0XHRpZihoID4gdyl7XG5cdFx0XHR5ID0gMC41O1xuXHRcdFx0eCA9IHcvKDIqaCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSAwLjU7XG5cdFx0XHR5ID0gaC8oMip3KTtcblx0XHR9XG5cblx0XHQvLyBTY2FsZSB0aGUgcmVuZGVyaW5nIHNwYWNlIGlmIG5lZWRlZFxuXHRcdHggKj0gc2NhbGVbMF07XG5cdFx0eSAqPSBzY2FsZVsxXTtcblxuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdC14LCAgeSwgMC4wLCAwLjAsXG5cdFx0XHQteCwgLXksIDAuMCwgMS4wLFxuXHRcdFx0IHgsICB5LCAxLjAsIDAuMCxcblx0XHRcdCB4LCAteSwgMS4wLCAxLjBcblx0XHRdKTtcblx0fVxuXG5cdGdldE9wdGlvbnMoc3ByaXRlOiBTcHJpdGUpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRsZXQgdGV4U2hpZnQ7XG5cdFx0bGV0IHRleFNjYWxlO1xuXG5cdFx0aWYoc3ByaXRlIGluc3RhbmNlb2YgQW5pbWF0ZWRTcHJpdGUpe1xuXHRcdFx0bGV0IGFuaW1hdGlvbkluZGV4ID0gc3ByaXRlLmFuaW1hdGlvbi5nZXRJbmRleEFuZEFkdmFuY2VBbmltYXRpb24oKTtcblx0XHRcdGxldCBvZmZzZXQgPSBzcHJpdGUuZ2V0QW5pbWF0aW9uT2Zmc2V0KGFuaW1hdGlvbkluZGV4KTtcblx0XHRcdHRleFNoaWZ0ID0gbmV3IEZsb2F0MzJBcnJheShbb2Zmc2V0LnggLyAoc3ByaXRlLmNvbHMgKiBzcHJpdGUuc2l6ZS54KSwgb2Zmc2V0LnkgLyAoc3ByaXRlLnJvd3MgKiBzcHJpdGUuc2l6ZS55KV0pO1xuXHRcdFx0dGV4U2NhbGUgPSBuZXcgRmxvYXQzMkFycmF5KFsxLyhzcHJpdGUuY29scyksIDEvKHNwcml0ZS5yb3dzKV0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0ZXhTaGlmdCA9IG5ldyBGbG9hdDMyQXJyYXkoWzAsIDBdKTtcblx0XHRcdHRleFNjYWxlID0gbmV3IEZsb2F0MzJBcnJheShbMSwgMV0pO1xuXHRcdH1cblxuXHRcdGxldCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuXHRcdFx0cG9zaXRpb246IHNwcml0ZS5wb3NpdGlvbixcblx0XHRcdHJvdGF0aW9uOiBzcHJpdGUucm90YXRpb24sXG5cdFx0XHRzaXplOiBzcHJpdGUuc2l6ZSxcblx0XHRcdHNjYWxlOiBzcHJpdGUuc2NhbGUudG9BcnJheSgpLFxuXHRcdFx0aW1hZ2VLZXk6IHNwcml0ZS5pbWFnZUlkLFxuXHRcdFx0dGV4U2hpZnQsXG5cdFx0XHR0ZXhTY2FsZVxuXHRcdH1cblxuXHRcdHJldHVybiBvcHRpb25zO1xuXHR9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFF1ZXVlIGZyb20gXCIuLi9EYXRhVHlwZXMvUXVldWVcIjtcbmltcG9ydCB7IFRpbGVkVGlsZW1hcERhdGEgfSBmcm9tIFwiLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVkRGF0YVwiO1xuaW1wb3J0IFN0cmluZ1V0aWxzIGZyb20gXCIuLi9VdGlscy9TdHJpbmdVdGlsc1wiO1xuaW1wb3J0IEF1ZGlvTWFuYWdlciBmcm9tIFwiLi4vU291bmQvQXVkaW9NYW5hZ2VyXCI7XG5pbXBvcnQgU3ByaXRlc2hlZXQgZnJvbSBcIi4uL0RhdGFUeXBlcy9TcHJpdGVzaGVldFwiO1xuaW1wb3J0IFdlYkdMUHJvZ3JhbVR5cGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9SZW5kZXJpbmcvV2ViR0xQcm9ncmFtVHlwZVwiO1xuXG4vKipcbiAqIFRoZSByZXNvdXJjZSBtYW5hZ2VyIGZvciB0aGUgZ2FtZSBlbmdpbmUuXG4gKiBUaGUgcmVzb3VyY2UgbWFuYWdlciBpbnRlcmZhY2VzIHdpdGggdGhlIGxvYWRhYmxlIGFzc2V0cyBvZiBhIGdhbWUgc3VjaCBhcyBpbWFnZXMsIGRhdGEgZmlsZXMsXG4gKiBhbmQgc291bmRzLCB3aGljaCBhcmUgYWxsIGZvdW5kIGluIHRoZSBkaXN0IGZvbGRlci5cbiAqIFRoaXMgY2xhc3MgY29udHJvbHMgbG9hZGluZyBhbmQgdXBkYXRlcyB0aGUgQHJlZmVyZW5jZVtTY2VuZV0gd2l0aCB0aGUgbG9hZGluZyBwcm9ncmVzcywgc28gdGhhdCB0aGUgc2NlbmUgZG9lcyBcbiAqIG5vdCBzdGFydCBiZWZvcmUgYWxsIG5lY2Vzc2FyeSBhc3NldHMgYXJlIGxvYWRlZC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVzb3VyY2VNYW5hZ2VyIHtcbiAgICAvLyBJbnN0YW5jZSBmb3IgdGhlIHNpbmdsZXRvbiBjbGFzc1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvLyBCb29sZWFucyB0byBrZWVwIHRyYWNrIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBSZXNvdXJjZU1hbmFnZXIgaXMgY3VycmVudGx5IGxvYWRpbmcgc29tZXRoaW5nXG4gICAgLyoqIFdoZXRoZXIgb3Igbm90IGFueSByZXNvdXJjZXMgYXJlIGxvYWRpbmcgKi9cbiAgICBwcml2YXRlIGxvYWRpbmc6IGJvb2xlYW47XG4gICAgLyoqIEEgYm9vbGVhbiB0byBpbmRpY2F0ZSB0aGF0IHRoZSBhc3NldHMganVzdCBmaW5pc2hlZCBsb2FkaW5nICovXG4gICAgcHJpdmF0ZSBqdXN0TG9hZGVkOiBib29sZWFuO1xuXG4gICAgLy8gRnVuY3Rpb25zIHRvIGRvIHNvbWV0aGluZyB3aGVuIGxvYWRpbmcgcHJvZ3Jlc3NlcyBvciBpcyBjb21wbGV0ZWQgc3VjaCBhcyByZW5kZXIgYSBsb2FkaW5nIHNjcmVlblxuICAgIC8qKiBBIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gbG9hZGluZyBwcm9ncmVzc2VzICovXG4gICAgcHVibGljIG9uTG9hZFByb2dyZXNzOiBGdW5jdGlvbjtcbiAgICAvKiogQSBmdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIGxvYWRpbmcgY29tcGxldGVzICovXG4gICAgcHVibGljIG9uTG9hZENvbXBsZXRlOiBGdW5jdGlvbjtcblxuXG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IGltYWdlcyBuZWVkIHRvIGJlIGxvYWRlZCovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9pbWFnZXNMb2FkZWQ6IG51bWJlcjtcbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgaW1hZ2VzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2ltYWdlc1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2YgaW1hZ2VzIHdlIG11c3QgbG9hZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIGltYWdlcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGVkIGFuZCBiZWluZyB1c2VkIGJ5IHRoZSBzY2VuZS4gVGhlIHJlZmVyZW5jZSB0byB0aGVzZSBpbWFnZXMgb25seSBleGlzdCBoZXJlIGZvciBlYXN5IGNsZWFudXAuICovXG4gICAgcHJpdmF0ZSBpbWFnZXM6IE1hcDxIVE1MSW1hZ2VFbGVtZW50PjtcblxuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSB0aWxlbWFwcyBuZWVkIHRvIGJlIGxvYWRlZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRpbGVtYXBzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2YgdGlsZW1hcHMgd2UgbXVzdCBsb2FkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZTogUXVldWU8S2V5UGF0aFBhaXI+O1xuICAgIC8qKiBBIG1hcCBvZiB0aGUgdGlsZW1hcHMgdGhhdCBhcmUgY3VycmVudGx5IGxvYWRlZCBhbmQgKHByZXN1bWFibHkpIGJlaW5nIHVzZWQgYnkgdGhlIHNjZW5lICovXG4gICAgcHJpdmF0ZSBzcHJpdGVzaGVldHM6IE1hcDxTcHJpdGVzaGVldD47XG5cbiAgICAvKiogTnVtYmVyIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdGlsZW1hcHMgbmVlZCB0byBiZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRpbGVtYXBzIGFyZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkOiBudW1iZXI7XG4gICAgLyoqIFRoZSBxdWV1ZSBvZiB0aWxlbWFwcyB3ZSBtdXN0IGxvYWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIHRpbGVtYXBzIHRoYXQgYXJlIGN1cnJlbnRseSBsb2FkZWQgYW5kIChwcmVzdW1hYmx5KSBiZWluZyB1c2VkIGJ5IHRoZSBzY2VuZSAqL1xuICAgIHByaXZhdGUgdGlsZW1hcHM6IE1hcDxUaWxlZFRpbGVtYXBEYXRhPjtcblxuICAgIC8qKiBOdW1iZXIgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBzb3VuZHMgbmVlZCB0byBiZSBsb2FkZWQgKi9cbiAgICBwcml2YXRlIGxvYWRvbmx5X2F1ZGlvTG9hZGVkOiBudW1iZXI7XG4gICAgLyoqIE51bWJlciB0byBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHNvdW5kcyBhcmUgbG9hZGVkICovXG4gICAgcHJpdmF0ZSBsb2Fkb25seV9hdWRpb1RvTG9hZDogbnVtYmVyO1xuICAgIC8qKiBUaGUgcXVldWUgb2Ygc291bmRzIHdlIG11c3QgbG9hZCAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhQYWlyPjtcbiAgICAvKiogQSBtYXAgb2YgdGhlIHNvdW5kcyB0aGF0IGFyZSBjdXJyZW50bHkgbG9hZGVkIGFuZCAocHJlc3VtYWJseSkgYmVpbmcgdXNlZCBieSB0aGUgc2NlbmUgKi9cbiAgICBwcml2YXRlIGF1ZGlvQnVmZmVyczogTWFwPEF1ZGlvQnVmZmVyPjtcblxuICAgIC8qKiBUaGUgdG90YWwgbnVtYmVyIG9mIFwidHlwZXNcIiBvZiB0aGluZ3MgdGhhdCBuZWVkIHRvIGJlIGxvYWRlZCAoaS5lLiBpbWFnZXMgYW5kIHRpbGVtYXBzKSAqL1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdHlwZXNUb0xvYWQ6IG51bWJlcjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvbkxvYWRlZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvblRvTG9hZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZTogUXVldWU8S2V5UGF0aFBhaXI+O1xuICAgIHByaXZhdGUganNvbk9iamVjdHM6IE1hcDxSZWNvcmQ8c3RyaW5nLCBhbnk+PjtcblxuICAgIC8qICMjIyMjIyMjIyMgSU5GT1JNQVRJT04gU1BFQ0lBTCBUTyBXRUJHTCAjIyMjIyMjIyMjICovXG4gICAgcHJpdmF0ZSBnbF9XZWJHTEFjdGl2ZTogYm9vbGVhbjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBsb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWU6IFF1ZXVlPEtleVBhdGhfU2hhZGVyPjtcblxuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdFRvTG9hZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRlZDogbnVtYmVyO1xuICAgIHByaXZhdGUgbG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZTogUXVldWU8S2V5TWFwUGFpcj47XG5cbiAgICBwcml2YXRlIGdsX1NoYWRlclByb2dyYW1zOiBNYXA8V2ViR0xQcm9ncmFtVHlwZT47XG5cbiAgICBwcml2YXRlIGdsX1RleHR1cmVzOiBNYXA8bnVtYmVyPjtcbiAgICBwcml2YXRlIGdsX05leHRUZXh0dXJlSUQ6IG51bWJlcjtcbiAgICBwcml2YXRlIGdsX0J1ZmZlcnM6IE1hcDxXZWJHTEJ1ZmZlcj47XG5cbiAgICBwcml2YXRlIGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQ7XG5cbiAgICAvKiAjIyMjIyMjIyMjIFVOTE9BRElORyBBTkQgRVhDTFVTSU9OIExJU1QgIyMjIyMjIyMjIyAqL1xuICAgIC8qKiBBIGxpc3Qgb2YgcmVzb3VyY2VzIHRoYXQgd2lsbCBiZSB1bmxvYWRlZCBhdCB0aGUgZW5kIG9mIHRoZSBjdXJyZW50IHNjZW5lICovXG4gICAgcHJpdmF0ZSByZXNvdXJjZXNUb1VubG9hZDogQXJyYXk8UmVzb3VyY2VSZWZlcmVuY2U+O1xuXG4gICAgLyoqIEEgbGlzdCBvZiByZXNvdXJjZXMgdG8ga2VlcCB1bnRpbCBmdXJ0aGVyIG5vdGljZSAqL1xuICAgIHByaXZhdGUgcmVzb3VyY2VzVG9LZWVwOiBBcnJheTxSZXNvdXJjZVJlZmVyZW5jZT47XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5qdXN0TG9hZGVkID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZXNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5pbWFnZXMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5zcHJpdGVzaGVldHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwc0xvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy50aWxlbWFwcyA9IG5ldyBNYXAoKTtcblxuICAgICAgICB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICAgICAgdGhpcy5hdWRpb0J1ZmZlcnMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGVkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uVG9Mb2FkID0gMDtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlID0gbmV3IFF1ZXVlKCk7XG4gICAgICAgIHRoaXMuanNvbk9iamVjdHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc0xvYWRlZCA9IDA7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZSA9IG5ldyBRdWV1ZSgpO1xuXG4gICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5nbF9UZXh0dXJlcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5nbF9OZXh0VGV4dHVyZUlEID0gMDtcbiAgICAgICAgdGhpcy5nbF9CdWZmZXJzID0gbmV3IE1hcCgpO1xuXG4gICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5yZXNvdXJjZXNUb0tlZXAgPSBuZXcgQXJyYXkoKTtcblxuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQgPSAwO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUgPSBuZXcgUXVldWUoKTtcbiAgICB9O1xuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBTSU5HTEVUT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzIG9yIGEgbmV3IGluc3RhbmNlIGlmIG5vbmUgZXhpc3RcbiAgICAgKiBAcmV0dXJucyBUaGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBSZXNvdXJjZU1hbmFnZXIge1xuICAgICAgICBpZiAoIXRoaXMuaW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuaW5zdGFuY2UgPSBuZXcgUmVzb3VyY2VNYW5hZ2VyKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvKiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIFBVQkxJQyBGVU5DVElPTiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjKi9cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgb3IgZGVhY3RpdmF0ZXMgdGhlIHVzZSBvZiBXZWJHTFxuICAgICAqIEBwYXJhbSBmbGFnIFRydWUgaWYgV2ViR0wgc2hvdWxkIGJlIHVzZWQsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqIEBwYXJhbSBnbCBUaGUgaW5zdGFuY2Ugb2YgdGhlIGdyYXBoaWNzIGNvbnRleHQsIGlmIGFwcGxpY2FibGVcbiAgICAgKi9cbiAgICBwdWJsaWMgdXNlV2ViR0woZmxhZzogYm9vbGVhbiwgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dCk6IHZvaWQge1xuICAgICAgICB0aGlzLmdsX1dlYkdMQWN0aXZlID0gZmxhZztcblxuICAgICAgICBpZiAodGhpcy5nbF9XZWJHTEFjdGl2ZSkge1xuICAgICAgICAgICAgdGhpcy5nbCA9IGdsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYW4gaW1hZ2UgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIGFzc29jaWF0ZSB0aGUgbG9hZGVkIGltYWdlIHdpdGhcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgaW1hZ2UgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBpbWFnZShrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcEltYWdlKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLklNQUdFKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBsb2FkZWQgaW1hZ2VcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCBpbWFnZVxuICAgICAqIEByZXR1cm5zIFRoZSBpbWFnZSBlbGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIGtleVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRJbWFnZShrZXk6IHN0cmluZyk6IEhUTUxJbWFnZUVsZW1lbnQge1xuICAgICAgICBsZXQgaW1hZ2UgPSB0aGlzLmltYWdlcy5nZXQoa2V5KTtcbiAgICAgICAgLy8gaWYgKGltYWdlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gICAgIHRocm93IGBUaGVyZSBpcyBubyBpbWFnZSBhc3NvY2lhdGVkIHdpdGgga2V5IFwiJHtrZXl9XCJgXG4gICAgICAgIC8vIH1cbiAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGEgc3ByaXRlc2hlZXQgZnJvbSBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIGFzc29jaWF0ZSB0aGUgbG9hZGVkIHNwcml0ZXNoZWV0IHdpdGhcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgc3ByaXRlc2hlZXQgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBzcHJpdGVzaGVldChrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFNwcml0ZXNoZWV0KGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMua2VlcFJlc291cmNlKGtleSwgUmVzb3VyY2VUeXBlLlNQUklURVNIRUVUKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBsb2FkZWQgc3ByaXRlc2hlZXRcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKiBAcmV0dXJucyBUaGUgbG9hZGVkIFNwcml0ZXNoZWV0XG4gICAgICovXG4gICAgcHVibGljIGdldFNwcml0ZXNoZWV0KGtleTogc3RyaW5nKTogU3ByaXRlc2hlZXQge1xuICAgICAgICByZXR1cm4gdGhpcy5zcHJpdGVzaGVldHMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYW4gYXVkaW8gZmlsZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIGF1ZGlvIGZpbGVcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICovXG4gICAgcHVibGljIGF1ZGlvKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIHBhdGg6IHBhdGggfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVsbHMgdGhlIHJlc291cmNlIG1hbmFnZXIgdG8ga2VlcCB0aGlzIHJlc291cmNlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSByZXNvdXJjZVxuICAgICAqL1xuICAgIHB1YmxpYyBrZWVwQXVkaW8oa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuQVVESU8pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhIGxvYWRlZCBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKiBAcmV0dXJucyBUaGUgQXVkaW9CdWZmZXIgY3JlYXRlZCBmcm9tIHRoZSBsb2FkZWQgYXVkaW8gZmxlXG4gICAgICovXG4gICAgcHVibGljIGdldEF1ZGlvKGtleTogc3RyaW5nKTogQXVkaW9CdWZmZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hdWRpb0J1ZmZlcnMuZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZCBhIHRpbGVtYXAgZnJvbSBhIGpzb24gZmlsZS4gQXV0b21hdGljYWxseSBsb2FkcyByZWxhdGVkIGltYWdlc1xuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgdGlsZW1hcCB0byBsb2FkXG4gICAgICovXG4gICAgcHVibGljIHRpbGVtYXAoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFRpbGVtYXAoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5rZWVwUmVzb3VyY2Uoa2V5LCBSZXNvdXJjZVR5cGUuVElMRU1BUCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmVpdmVzIGEgbG9hZGVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCB0aWxlbWFwXG4gICAgICogQHJldHVybnMgVGhlIHRpbGVtYXAgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIGtleVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRUaWxlbWFwKGtleTogc3RyaW5nKTogVGlsZWRUaWxlbWFwRGF0YSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRpbGVtYXBzLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFuIG9iamVjdCBmcm9tIGEganNvbiBmaWxlLlxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgbG9hZGVkIG9iamVjdFxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBqc29uIGZpbGUgdG8gbG9hZFxuICAgICAqL1xuICAgIHB1YmxpYyBvYmplY3Qoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZykge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcE9iamVjdChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5KU09OKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgYSBsb2FkZWQgb2JqZWN0XG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBsb2FkZWQgb2JqZWN0XG4gICAgICogQHJldHVybnMgVGhlIG9iamVjdCBkYXRhIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5XG4gICAgICovXG4gICAgcHVibGljIGdldE9iamVjdChrZXk6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gdGhpcy5qc29uT2JqZWN0cy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICAvKiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIExPQUQgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIHJlc291cmNlcyBjdXJyZW50bHkgaW4gdGhlIHF1ZXVlXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWwgd2hlbiB0aGUgcmVzb3VyY2VzIGFyZSBmaW5pc2hlZCBsb2FkaW5nXG4gICAgICovXG4gICAgbG9hZFJlc291cmNlc0Zyb21RdWV1ZShjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90eXBlc1RvTG9hZCA9IDU7XG5cbiAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcblxuICAgICAgICAvLyBMb2FkIGV2ZXJ5dGhpbmcgaW4gdGhlIHF1ZXVlcy4gVGlsZW1hcHMgaGF2ZSB0byBjb21lIGJlZm9yZSBpbWFnZXMgYmVjYXVzZSB0aGV5IHdpbGwgYWRkIG5ldyBpbWFnZXMgdG8gdGhlIHF1ZXVlXG5cbiAgICAgICAgdGhpcy5sb2FkVGlsZW1hcE9iamVjdEZyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBUaWxlbWFwT2JqZWN0c1wiKTtcbiAgICAgICAgICAgIHRoaXMubG9hZFRpbGVtYXBzRnJvbVF1ZXVlKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBUaWxlbWFwc1wiKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRTcHJpdGVzaGVldHNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBTcHJpdGVzaGVldHNcIik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZEltYWdlc0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBJbWFnZXNcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRBdWRpb0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkZWQgQXVkaW9cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkT2JqZWN0c0Zyb21RdWV1ZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGVkIE9iamVjdHNcIik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2xfV2ViR0xBY3RpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xfTG9hZFNoYWRlcnNGcm9tUXVldWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGVkIFNoYWRlcnNcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nKGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nKGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICAvLyBEb25lIGxvYWRpbmdcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuanVzdExvYWRlZCA9IHRydWU7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBVTkxPQUQgRlVOQ1RJT04gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyovXG5cbiAgICBwcml2YXRlIGtlZXBSZXNvdXJjZShrZXk6IHN0cmluZywgdHlwZTogUmVzb3VyY2VUeXBlKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiS2VlcCByZXNvdXJjZS4uLlwiKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnJlc291cmNlc1RvVW5sb2FkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgcmVzb3VyY2UgPSB0aGlzLnJlc291cmNlc1RvVW5sb2FkW2ldO1xuICAgICAgICAgICAgaWYgKHJlc291cmNlLmtleSA9PT0ga2V5ICYmIHJlc291cmNlLnJlc291cmNlVHlwZSA9PT0gdHlwZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRm91bmQgcmVzb3VyY2UgXCIgKyBrZXkgKyBcIiBvZiB0eXBlIFwiICsgdHlwZSArIFwiLiBLZWVwaW5nLlwiKTtcbiAgICAgICAgICAgICAgICBsZXQgcmVzb3VyY2VUb01vdmUgPSB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvS2VlcC5wdXNoKC4uLnJlc291cmNlVG9Nb3ZlKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGVzIHJlZmVyZW5jZXMgdG8gYWxsIHJlc291cmNlcyBpbiB0aGUgcmVzb3VyY2UgbWFuYWdlclxuICAgICAqL1xuICAgIHVubG9hZEFsbFJlc291cmNlcygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuanVzdExvYWRlZCA9IGZhbHNlO1xuXG4gICAgICAgIGZvciAobGV0IHJlc291cmNlIG9mIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQpIHtcbiAgICAgICAgICAgIC8vIFVubG9hZCB0aGUgcmVzb3VyY2VcbiAgICAgICAgICAgIHRoaXMudW5sb2FkUmVzb3VyY2UocmVzb3VyY2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1bmxvYWRSZXNvdXJjZShyZXNvdXJjZTogUmVzb3VyY2VSZWZlcmVuY2UpOiB2b2lkIHtcbiAgICAgICAgLy8gRGVsZXRlIHRoZSByZXNvdXJjZSBpdHNlbGZcbiAgICAgICAgc3dpdGNoIChyZXNvdXJjZS5yZXNvdXJjZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLklNQUdFOlxuICAgICAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2xfVGV4dHVyZXMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSZXNvdXJjZVR5cGUuVElMRU1BUDpcbiAgICAgICAgICAgICAgICB0aGlzLnRpbGVtYXBzLmRlbGV0ZShyZXNvdXJjZS5rZXkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBSZXNvdXJjZVR5cGUuU1BSSVRFU0hFRVQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zcHJpdGVzaGVldHMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFJlc291cmNlVHlwZS5BVURJTzpcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQnVmZmVycy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgUmVzb3VyY2VUeXBlLkpTT046XG4gICAgICAgICAgICAgICAgdGhpcy5qc29uT2JqZWN0cy5kZWxldGUocmVzb3VyY2Uua2V5KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIC8qY2FzZSBSZXNvdXJjZVR5cGUuU0hBREVSOlxuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuZ2V0KHJlc291cmNlLmtleSkuZGVsZXRlKHRoaXMuZ2wpO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuZGVsZXRlKHJlc291cmNlLmtleSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7Ki9cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlbGV0ZSBhbnkgZGVwZW5kZW5jaWVzXG4gICAgICAgIGZvciAobGV0IGRlcGVuZGVuY3kgb2YgcmVzb3VyY2UuZGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICB0aGlzLnVubG9hZFJlc291cmNlKGRlcGVuZGVuY3kpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBXT1JLIEZVTkNUSU9OUyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjKi9cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgdGlsZW1hcHMgY3VycmVudGx5IGluIHRoZSB0aWxlbWFwIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gbG9hZGluZyBpcyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZFRpbGVtYXBzRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwc1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfdGlsZW1hcExvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBzVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IHRpbGVtYXAgPSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkVGlsZW1hcCh0aWxlbWFwLmtleSwgdGlsZW1hcC5wYXRoLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYSBzaW5ndWxhciB0aWxlbWFwIFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgdGlsZW1hcFxuICAgICAqIEBwYXJhbSBwYXRoVG9UaWxlbWFwSlNPTiBUaGUgcGF0aCB0byB0aGUgdGlsZW1hcCBKU09OIGZpbGVcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRUaWxlbWFwKGtleTogc3RyaW5nLCBwYXRoVG9UaWxlbWFwSlNPTjogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUocGF0aFRvVGlsZW1hcEpTT04sIChmaWxlVGV4dDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBsZXQgdGlsZW1hcE9iamVjdCA9IDxUaWxlZFRpbGVtYXBEYXRhPkpTT04ucGFyc2UoZmlsZVRleHQpO1xuXG4gICAgICAgICAgICAvLyBXZSBjYW4gcGFyc2UgdGhlIG9iamVjdCBsYXRlciAtIGl0J3MgbXVjaCBmYXN0ZXIgdGhhbiBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLnRpbGVtYXBzLmFkZChrZXksIHRpbGVtYXBPYmplY3QpO1xuICAgICAgICAgICAgbGV0IHJlc291cmNlID0gbmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLlRJTEVNQVApO1xuXG4gICAgICAgICAgICAvLyBHcmFiIHRoZSB0aWxlc2V0IGltYWdlcyB3ZSBuZWVkIHRvIGxvYWQgYW5kIGFkZCB0aGVtIHRvIHRoZSBpbWFnZWxvYWRpbmcgcXVldWVcbiAgICAgICAgICAgIGZvciAobGV0IHRpbGVzZXQgb2YgdGlsZW1hcE9iamVjdC50aWxlc2V0cykge1xuICAgICAgICAgICAgICAgIGlmICh0aWxlc2V0LmltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSB0aWxlc2V0LmltYWdlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgcGF0aCA9IFN0cmluZ1V0aWxzLmdldFBhdGhGcm9tRmlsZVBhdGgocGF0aFRvVGlsZW1hcEpTT04pICsga2V5O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmVucXVldWUoeyBrZXk6IGtleSwgcGF0aDogcGF0aCwgaXNEZXBlbmRlbmN5OiB0cnVlIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgICAgICByZXNvdXJjZS5hZGREZXBlbmRlbmN5KG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGlsZXNldC50aWxlcykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB0aWxlIG9mIHRpbGVzZXQudGlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrZXkgPSB0aWxlLmltYWdlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhdGggPSBTdHJpbmdVdGlscy5nZXRQYXRoRnJvbUZpbGVQYXRoKHBhdGhUb1RpbGVtYXBKU09OKSArIGtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleToga2V5LCBwYXRoOiBwYXRoLCBpc0RlcGVuZGVuY3k6IHRydWUgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2UuYWRkRGVwZW5kZW5jeShuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIHRoZSByZXNvdXJjZSByZWZlcmVuY2UgdG8gdGhlIGxpc3Qgb2YgcmVzb3VyY2UgdG8gdW5sb2FkXG4gICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gocmVzb3VyY2UpO1xuXG4gICAgICAgICAgICAvLyBGaW5pc2ggbG9hZGluZ1xuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nVGlsZW1hcChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGEgdGlsZW1hcC4gQ2FsbHMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlmIHRoaXMgaXMgdGhlIGxhc3QgdGlsZW1hcCBiZWluZyBsb2FkZWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdUaWxlbWFwKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBzTG9hZGVkICs9IDE7XG5cbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfdGlsZW1hcHNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyB0aWxlbWFwc1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGFsbCBzcHJpdGVzaGVldHMgY3VycmVudGx5IGluIHRoZSBzcHJpdGVzaGVldCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZSBzcHJpdGVzaGVldHMgYXJlIGRvbmUgbG9hZGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZFNwcml0ZXNoZWV0c0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzVG9Mb2FkID0gdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNUb0xvYWQgPT09IDApIHtcbiAgICAgICAgICAgIG9uRmluaXNoTG9hZGluZygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IHNwcml0ZXNoZWV0ID0gdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldExvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRTcHJpdGVzaGVldChzcHJpdGVzaGVldC5rZXksIHNwcml0ZXNoZWV0LnBhdGgsIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNpbmd1bGFyIHNwcml0ZXNoZWV0IFxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgc3ByaXRlc2hlZXQgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBwYXRoVG9TcHJpdGVzaGVldEpTT04gVGhlIHBhdGggdG8gdGhlIHNwcml0ZXNoZWV0IEpTT04gZmlsZVxuICAgICAqIEBwYXJhbSBjYWxsYmFja0lmTGFzdCBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0XG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkU3ByaXRlc2hlZXQoa2V5OiBzdHJpbmcsIHBhdGhUb1Nwcml0ZXNoZWV0SlNPTjogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUocGF0aFRvU3ByaXRlc2hlZXRKU09OLCAoZmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHNwcml0ZXNoZWV0ID0gPFNwcml0ZXNoZWV0PkpTT04ucGFyc2UoZmlsZVRleHQpO1xuXG4gICAgICAgICAgICAvLyBXZSBjYW4gcGFyc2UgdGhlIG9iamVjdCBsYXRlciAtIGl0J3MgbXVjaCBmYXN0ZXIgdGhhbiBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLnNwcml0ZXNoZWV0cy5hZGQoa2V5LCBzcHJpdGVzaGVldCk7XG5cbiAgICAgICAgICAgIGxldCByZXNvdXJjZSA9IG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5TUFJJVEVTSEVFVCk7XG5cbiAgICAgICAgICAgIC8vIEdyYWIgdGhlIGltYWdlIHdlIG5lZWQgdG8gbG9hZCBhbmQgYWRkIGl0IHRvIHRoZSBpbWFnZWxvYWRpbmcgcXVldWVcbiAgICAgICAgICAgIGxldCBwYXRoID0gU3RyaW5nVXRpbHMuZ2V0UGF0aEZyb21GaWxlUGF0aChwYXRoVG9TcHJpdGVzaGVldEpTT04pICsgc3ByaXRlc2hlZXQuc3ByaXRlU2hlZXRJbWFnZTtcbiAgICAgICAgICAgIHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZW5xdWV1ZSh7IGtleTogc3ByaXRlc2hlZXQubmFtZSwgcGF0aDogcGF0aCwgaXNEZXBlbmRlbmN5OiB0cnVlIH0pO1xuXG4gICAgICAgICAgICByZXNvdXJjZS5hZGREZXBlbmRlbmN5KG5ldyBSZXNvdXJjZVJlZmVyZW5jZShzcHJpdGVzaGVldC5uYW1lLCBSZXNvdXJjZVR5cGUuSU1BR0UpKTtcbiAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChyZXNvdXJjZSk7XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdTcHJpdGVzaGVldChjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGEgc3ByaXRlc2hlZXQuIENhbGxzIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0IGJlaW5nIGxvYWRlZFxuICAgICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IHNwcml0ZXNoZWV0IHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdTcHJpdGVzaGVldChjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgPT09IHRoaXMubG9hZG9ubHlfc3ByaXRlc2hlZXRzVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgc3ByaXRlc2hlZXRzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9hZHMgYWxsIGltYWdlcyBjdXJyZW50bHkgaW4gdGhlIGltYWdlIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gdGhlcmUgYXJlIG5vIG1vcmUgaW1hZ2VzIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGxvYWRJbWFnZXNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCA9IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gaXRlbXMgdG8gbG9hZCwgd2UncmUgZmluaXNoZWRcbiAgICAgICAgaWYgKHRoaXMubG9hZG9ubHlfaW1hZ2VzVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X2ltYWdlTG9hZGluZ1F1ZXVlLmhhc0l0ZW1zKCkpIHtcbiAgICAgICAgICAgIGxldCBpbWFnZSA9IHRoaXMubG9hZG9ubHlfaW1hZ2VMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5sb2FkSW1hZ2UoaW1hZ2Uua2V5LCBpbWFnZS5wYXRoLCBpbWFnZS5pc0RlcGVuZGVuY3ksIG9uRmluaXNoTG9hZGluZyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIHNpbmd1bGFyIGltYWdlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpbWFnZSB0byBsb2FkXG4gICAgICogQHBhcmFtIHBhdGggVGhlIHBhdGggdG8gdGhlIGltYWdlIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tJZkxhc3QgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBpbWFnZVxuICAgICAqL1xuICAgIHB1YmxpYyBsb2FkSW1hZ2Uoa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZywgaXNEZXBlbmRlbmN5OiBib29sZWFuLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQWRkIHRvIGxvYWRlZCBpbWFnZXNcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmFkZChrZXksIGltYWdlKTtcblxuICAgICAgICAgICAgLy8gSWYgbm90IGEgZGVwZW5kZW5jeSwgcHVzaCBpdCB0byB0aGUgdW5sb2FkIGxpc3QuIE90aGVyd2lzZSBpdCdzIG1hbmFnZWQgYnkgc29tZXRoaW5nIGVsc2VcbiAgICAgICAgICAgIGlmICghaXNEZXBlbmRlbmN5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiBXZWJHTCBpcyBhY3RpdmUsIGNyZWF0ZSBhIHRleHR1cmVcbiAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVXZWJHTFRleHR1cmUoa2V5LCBpbWFnZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBpbWFnZSBsb2FkXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdJbWFnZShjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpbWFnZS5zcmMgPSBwYXRoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGFuIGltYWdlLiBJZiB0aGlzIGlzIHRoZSBsYXN0IGltYWdlLCBpdCBjYWxscyB0aGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBpbWFnZVxuICAgICAqL1xuICAgIHByaXZhdGUgZmluaXNoTG9hZGluZ0ltYWdlKGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCArPSAxO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9pbWFnZXNUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyBpbWFnZXNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgYXVkaW8gY3VycmVudGx5IGluIHRoZSB0aWxlbWFwIGxvYWRpbmcgcXVldWVcbiAgICAgKiBAcGFyYW0gb25GaW5pc2hMb2FkaW5nIFRoZSBmdW5jdGlvbiB0byBjYWxsIHdoZW4gdGlsZW1hcHMgYXJlIGRvbmUgbG9hZGluZ1xuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZEF1ZGlvRnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9IHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9hdWRpb1RvTG9hZCA9PT0gMCkge1xuICAgICAgICAgICAgb25GaW5pc2hMb2FkaW5nKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAodGhpcy5sb2Fkb25seV9hdWRpb0xvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgYXVkaW8gPSB0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZEF1ZGlvKGF1ZGlvLmtleSwgYXVkaW8ucGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWQgYSBzaW5ndWxhciBhdWRpbyBmaWxlXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IHRvIHRoZSBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gcGF0aCBUaGUgcGF0aCB0byB0aGUgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICogQHBhcmFtIGNhbGxiYWNrSWZMYXN0IFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3QgYXVkaW8gZmlsZSB0byBsb2FkXG4gICAgICovXG4gICAgcHJpdmF0ZSBsb2FkQXVkaW8oa2V5OiBzdHJpbmcsIHBhdGg6IHN0cmluZywgY2FsbGJhY2tJZkxhc3Q6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIGxldCBhdWRpb0N0eCA9IEF1ZGlvTWFuYWdlci5nZXRJbnN0YW5jZSgpLmdldEF1ZGlvQ29udGV4dCgpO1xuXG4gICAgICAgIGxldCByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHJlcXVlc3Qub3BlbignR0VUJywgcGF0aCwgdHJ1ZSk7XG4gICAgICAgIHJlcXVlc3QucmVzcG9uc2VUeXBlID0gJ2FycmF5YnVmZmVyJztcblxuICAgICAgICByZXF1ZXN0Lm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgICAgIGF1ZGlvQ3R4LmRlY29kZUF1ZGlvRGF0YShyZXF1ZXN0LnJlc3BvbnNlLCAoYnVmZmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIHRvIGxpc3Qgb2YgYXVkaW8gYnVmZmVyc1xuICAgICAgICAgICAgICAgIHRoaXMuYXVkaW9CdWZmZXJzLmFkZChrZXksIGJ1ZmZlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5BVURJTykpO1xuXG4gICAgICAgICAgICAgICAgLy8gRmluaXNoIGxvYWRpbmcgc291bmRcbiAgICAgICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdBdWRpbyhjYWxsYmFja0lmTGFzdCk7XG4gICAgICAgICAgICB9LCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkVycm9yIGxvYWRpbmcgc291bmRcIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJlcXVlc3Quc2VuZCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmlzaCBsb2FkaW5nIGFuIGF1ZGlvIGZpbGUuIENhbGxzIHRoZSBjYWxsYmFjayBmdW5jdG9uIGlmIHRoaXMgaXMgdGhlIGxhc3QgYXVkaW8gc2FtcGxlIGJlaW5nIGxvYWRlZC5cbiAgICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNhbGwgaWYgdGhpcyBpcyB0aGUgbGFzdCBhdWRpbyBmaWxlIHRvIGxvYWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdBdWRpbyhjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV9hdWRpb0xvYWRlZCArPSAxO1xuXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2F1ZGlvTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X2F1ZGlvVG9Mb2FkKSB7XG4gICAgICAgICAgICAvLyBXZSdyZSBkb25lIGxvYWRpbmcgYXVkaW9cbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhbGwgb2JqZWN0cyBjdXJyZW50bHkgaW4gdGhlIG9iamVjdCBsb2FkaW5nIHF1ZXVlXG4gICAgICogQHBhcmFtIG9uRmluaXNoTG9hZGluZyBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoZXJlIGFyZSBubyBtb3JlIG9iamVjdHMgdG8gbG9hZFxuICAgICAqL1xuICAgIHByaXZhdGUgbG9hZE9iamVjdHNGcm9tUXVldWUob25GaW5pc2hMb2FkaW5nOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQgPSB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkaW5nUXVldWUuZ2V0U2l6ZSgpO1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICh0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQgPT09IDApIHtcbiAgICAgICAgICAgIG9uRmluaXNoTG9hZGluZygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgd2hpbGUgKHRoaXMubG9hZG9ubHlfanNvbkxvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgb2JqID0gdGhpcy5sb2Fkb25seV9qc29uTG9hZGluZ1F1ZXVlLmRlcXVldWUoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZE9iamVjdChvYmoua2V5LCBvYmoucGF0aCwgb25GaW5pc2hMb2FkaW5nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvYWRzIGEgc2luZ3VsYXIgb2JqZWN0XG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBvYmplY3QgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIHRvIHRoZSBvYmplY3QgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBjYWxsYmFja0lmTGFzdCBUaGUgZnVuY3Rpb24gdG8gY2FsbCBpZiB0aGlzIGlzIHRoZSBsYXN0IG9iamVjdFxuICAgICAqL1xuICAgIHB1YmxpYyBsb2FkT2JqZWN0KGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGNhbGxiYWNrSWZMYXN0OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRUZXh0RmlsZShwYXRoLCAoZmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IG9iaiA9IEpTT04ucGFyc2UoZmlsZVRleHQpO1xuICAgICAgICAgICAgdGhpcy5qc29uT2JqZWN0cy5hZGQoa2V5LCBvYmopO1xuXG4gICAgICAgICAgICB0aGlzLnJlc291cmNlc1RvVW5sb2FkLnB1c2gobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLkpTT04pKTtcblxuICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluaXNoIGxvYWRpbmcgYW4gb2JqZWN0LiBJZiB0aGlzIGlzIHRoZSBsYXN0IG9iamVjdCwgaXQgY2FsbHMgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBjYWxsIGlmIHRoaXMgaXMgdGhlIGxhc3Qgb2JqZWN0XG4gICAgICovXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X2pzb25Mb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9qc29uTG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X2pzb25Ub0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyBvYmplY3RzXG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyBXRUJHTCBTUEVDSUZJQyBGVU5DVElPTlMgIyMjIyMjIyMjIyAqL1xuXG4gICAgcHVibGljIGdldFRleHR1cmUoa2V5OiBzdHJpbmcpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5nbF9UZXh0dXJlcy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2hhZGVyUHJvZ3JhbShrZXk6IHN0cmluZyk6IFdlYkdMUHJvZ3JhbSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdsX1NoYWRlclByb2dyYW1zLmdldChrZXkpLnByb2dyYW07XG4gICAgfVxuXG4gICAgcHVibGljIGdldEJ1ZmZlcihrZXk6IHN0cmluZyk6IFdlYkdMQnVmZmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2xfQnVmZmVycy5nZXQoa2V5KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVdlYkdMVGV4dHVyZShpbWFnZUtleTogc3RyaW5nLCBpbWFnZTogSFRNTEltYWdlRWxlbWVudCk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIHRleHR1cmUgSURcbiAgICAgICAgY29uc3QgdGV4dHVyZUlEID0gdGhpcy5nZXRUZXh0dXJlSUQodGhpcy5nbF9OZXh0VGV4dHVyZUlEKTtcblxuICAgICAgICAvLyBDcmVhdGUgdGhlIHRleHR1cmVcbiAgICAgICAgY29uc3QgdGV4dHVyZSA9IHRoaXMuZ2wuY3JlYXRlVGV4dHVyZSgpO1xuXG4gICAgICAgIC8vIFNldCB1cCB0aGUgdGV4dHVyZVxuICAgICAgICAvLyBFbmFibGUgdGV4dHVyZTBcbiAgICAgICAgdGhpcy5nbC5hY3RpdmVUZXh0dXJlKHRleHR1cmVJRCk7XG5cbiAgICAgICAgLy8gQmluZCBvdXIgdGV4dHVyZSB0byB0ZXh0dXJlIDBcbiAgICAgICAgdGhpcy5nbC5iaW5kVGV4dHVyZSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgdGV4dHVyZSBwYXJhbWV0ZXJzXG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9NSU5fRklMVEVSLCB0aGlzLmdsLkxJTkVBUik7XG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1MsIHRoaXMuZ2wuQ0xBTVBfVE9fRURHRSk7XG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1QsIHRoaXMuZ2wuQ0xBTVBfVE9fRURHRSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSB0ZXh0dXJlIGltYWdlXG4gICAgICAgIHRoaXMuZ2wudGV4SW1hZ2UyRCh0aGlzLmdsLlRFWFRVUkVfMkQsIDAsIHRoaXMuZ2wuUkdCQSwgdGhpcy5nbC5SR0JBLCB0aGlzLmdsLlVOU0lHTkVEX0JZVEUsIGltYWdlKTtcblxuICAgICAgICAvLyBBZGQgdGhlIHRleHR1cmUgdG8gb3VyIG1hcCB3aXRoIHRoZSBzYW1lIGtleSBhcyB0aGUgaW1hZ2VcbiAgICAgICAgdGhpcy5nbF9UZXh0dXJlcy5hZGQoaW1hZ2VLZXksIHRoaXMuZ2xfTmV4dFRleHR1cmVJRCk7XG5cbiAgICAgICAgLy8gSW5jcmVtZW50IHRoZSBrZXlcbiAgICAgICAgdGhpcy5nbF9OZXh0VGV4dHVyZUlEICs9IDE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRUZXh0dXJlSUQoaWQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIC8vIFN0YXJ0IHdpdGggOSBjYXNlcyAtIHRoaXMgY2FuIGJlIGV4cGFuZGVkIGlmIG5lZWRlZCwgYnV0IGZvciB0aGUgYmVzdCBwZXJmb3JtYW5jZSxcbiAgICAgICAgLy8gVGV4dHVyZXMgc2hvdWxkIGJlIHN0aXRjaGVkIGludG8gYW4gYXRsYXNcbiAgICAgICAgc3dpdGNoIChpZCkge1xuICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gdGhpcy5nbC5URVhUVVJFMDtcbiAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTE7XG4gICAgICAgICAgICBjYXNlIDI6IHJldHVybiB0aGlzLmdsLlRFWFRVUkUyO1xuICAgICAgICAgICAgY2FzZSAzOiByZXR1cm4gdGhpcy5nbC5URVhUVVJFMztcbiAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTQ7XG4gICAgICAgICAgICBjYXNlIDU6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU1O1xuICAgICAgICAgICAgY2FzZSA2OiByZXR1cm4gdGhpcy5nbC5URVhUVVJFNjtcbiAgICAgICAgICAgIGNhc2UgNzogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTc7XG4gICAgICAgICAgICBjYXNlIDg6IHJldHVybiB0aGlzLmdsLlRFWFRVUkU4O1xuICAgICAgICAgICAgZGVmYXVsdDogcmV0dXJuIHRoaXMuZ2wuVEVYVFVSRTk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlQnVmZmVyKGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICBsZXQgYnVmZmVyID0gdGhpcy5nbC5jcmVhdGVCdWZmZXIoKTtcblxuICAgICAgICAgICAgdGhpcy5nbF9CdWZmZXJzLmFkZChrZXksIGJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbnF1ZXVlcyBsb2FkaW5nIG9mIGEgbmV3IHNoYWRlciBwcm9ncmFtXG4gICAgICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBzaGFkZXIgcHJvZ3JhbVxuICAgICAqIEBwYXJhbSB2U2hhZGVyRmlsZXBhdGggXG4gICAgICogQHBhcmFtIGZTaGFkZXJGaWxlcGF0aCBcbiAgICAgKi9cbiAgICBwdWJsaWMgc2hhZGVyKGtleTogc3RyaW5nLCB2U2hhZGVyRmlsZXBhdGg6IHN0cmluZywgZlNoYWRlckZpbGVwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgbGV0IHNwbGl0UGF0aCA9IHZTaGFkZXJGaWxlcGF0aC5zcGxpdChcIi5cIik7XG4gICAgICAgIGxldCBlbmQgPSBzcGxpdFBhdGhbc3BsaXRQYXRoLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgIGlmIChlbmQgIT09IFwidnNoYWRlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBgJHt2U2hhZGVyRmlsZXBhdGh9IGlzIG5vdCBhIHZhbGlkIHZlcnRleCBzaGFkZXIgLSBtdXN0IGVuZCBpbiBcIi52c2hhZGVyYDtcbiAgICAgICAgfVxuXG4gICAgICAgIHNwbGl0UGF0aCA9IGZTaGFkZXJGaWxlcGF0aC5zcGxpdChcIi5cIik7XG4gICAgICAgIGVuZCA9IHNwbGl0UGF0aFtzcGxpdFBhdGgubGVuZ3RoIC0gMV07XG5cbiAgICAgICAgaWYgKGVuZCAhPT0gXCJmc2hhZGVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IGAke2ZTaGFkZXJGaWxlcGF0aH0gaXMgbm90IGEgdmFsaWQgdmVydGV4IHNoYWRlciAtIG11c3QgZW5kIGluIFwiLmZzaGFkZXJgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHBhdGhzID0gbmV3IEtleVBhdGhfU2hhZGVyKCk7XG4gICAgICAgIHBhdGhzLmtleSA9IGtleTtcbiAgICAgICAgcGF0aHMudnBhdGggPSB2U2hhZGVyRmlsZXBhdGg7XG4gICAgICAgIHBhdGhzLmZwYXRoID0gZlNoYWRlckZpbGVwYXRoO1xuXG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyTG9hZGluZ1F1ZXVlLmVucXVldWUocGF0aHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlbGxzIHRoZSByZXNvdXJjZSBtYW5hZ2VyIHRvIGtlZXAgdGhpcyByZXNvdXJjZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgcmVzb3VyY2VcbiAgICAgKi9cbiAgICBwdWJsaWMga2VlcFNoYWRlcihrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmtlZXBSZXNvdXJjZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnbF9Mb2FkU2hhZGVyc0Zyb21RdWV1ZShvbkZpbmlzaExvYWRpbmc6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNUb0xvYWQgPSB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZS5nZXRTaXplKCk7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgPSAwO1xuXG4gICAgICAgIC8vIElmIHdlYkdMIGlzbidhY3RpdmUgb3IgdGhlcmUgYXJlIG5vIGl0ZW1zIHRvIGxvYWQsIHdlJ3JlIGZpbmlzaGVkXG4gICAgICAgIGlmICghdGhpcy5nbF9XZWJHTEFjdGl2ZSB8fCB0aGlzLmxvYWRvbmx5X2dsX1NoYWRlclByb2dyYW1zVG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X2dsX1NoYWRlckxvYWRpbmdRdWV1ZS5oYXNJdGVtcygpKSB7XG4gICAgICAgICAgICBsZXQgc2hhZGVyID0gdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJMb2FkaW5nUXVldWUuZGVxdWV1ZSgpO1xuICAgICAgICAgICAgdGhpcy5nbF9Mb2FkU2hhZGVyKHNoYWRlci5rZXksIHNoYWRlci52cGF0aCwgc2hhZGVyLmZwYXRoLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnbF9Mb2FkU2hhZGVyKGtleTogc3RyaW5nLCB2cGF0aDogc3RyaW5nLCBmcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUodnBhdGgsICh2RmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3QgdlNoYWRlciA9IHZGaWxlVGV4dDtcblxuICAgICAgICAgICAgdGhpcy5sb2FkVGV4dEZpbGUoZnBhdGgsIChmRmlsZVRleHQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZTaGFkZXIgPSBmRmlsZVRleHRcblxuICAgICAgICAgICAgICAgIC8vIEV4dHJhY3QgdGhlIHByb2dyYW0gYW5kIHNoYWRlcnNcbiAgICAgICAgICAgICAgICBjb25zdCBbc2hhZGVyUHJvZ3JhbSwgdmVydGV4U2hhZGVyLCBmcmFnbWVudFNoYWRlcl0gPSB0aGlzLmNyZWF0ZVNoYWRlclByb2dyYW0odlNoYWRlciwgZlNoYWRlcik7XG5cbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSB3cmFwcGVyIHR5cGVcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9ncmFtV3JhcHBlciA9IG5ldyBXZWJHTFByb2dyYW1UeXBlKCk7XG4gICAgICAgICAgICAgICAgcHJvZ3JhbVdyYXBwZXIucHJvZ3JhbSA9IHNoYWRlclByb2dyYW07XG4gICAgICAgICAgICAgICAgcHJvZ3JhbVdyYXBwZXIudmVydGV4U2hhZGVyID0gdmVydGV4U2hhZGVyO1xuICAgICAgICAgICAgICAgIHByb2dyYW1XcmFwcGVyLmZyYWdtZW50U2hhZGVyID0gZnJhZ21lbnRTaGFkZXI7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgdG8gb3VyIG1hcFxuICAgICAgICAgICAgICAgIHRoaXMuZ2xfU2hhZGVyUHJvZ3JhbXMuYWRkKGtleSwgcHJvZ3JhbVdyYXBwZXIpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5TSEFERVIpKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nXG4gICAgICAgICAgICAgICAgdGhpcy5nbF9GaW5pc2hMb2FkaW5nU2hhZGVyKGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdsX0ZpbmlzaExvYWRpbmdTaGFkZXIoY2FsbGJhY2s6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfZ2xfU2hhZGVyUHJvZ3JhbXNMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc0xvYWRlZCA9PT0gdGhpcy5sb2Fkb25seV9nbF9TaGFkZXJQcm9ncmFtc1RvTG9hZCkge1xuICAgICAgICAgICAgLy8gV2UncmUgZG9uZSBsb2FkaW5nIHNoYWRlcnNcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVNoYWRlclByb2dyYW0odlNoYWRlclNvdXJjZTogc3RyaW5nLCBmU2hhZGVyU291cmNlOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgdmVydGV4U2hhZGVyID0gdGhpcy5sb2FkVmVydGV4U2hhZGVyKHZTaGFkZXJTb3VyY2UpO1xuICAgICAgICBjb25zdCBmcmFnbWVudFNoYWRlciA9IHRoaXMubG9hZEZyYWdtZW50U2hhZGVyKGZTaGFkZXJTb3VyY2UpO1xuXG4gICAgICAgIGlmICh2ZXJ0ZXhTaGFkZXIgPT09IG51bGwgfHwgZnJhZ21lbnRTaGFkZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIFdlIGhhZCBhIHByb2JsZW0gaW50aWFsaXppbmcgLSBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgYSBzaGFkZXIgcHJvZ3JhbVxuICAgICAgICBjb25zdCBwcm9ncmFtID0gdGhpcy5nbC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgICAgIGlmICghcHJvZ3JhbSkge1xuICAgICAgICAgICAgLy8gRXJyb3IgY3JlYXRpbmdcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBjcmVhdGUgcHJvZ3JhbVwiKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXR0YWNoIG91ciB2ZXJ0ZXggYW5kIGZyYWdtZW50IHNoYWRlclxuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCB2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBmcmFnbWVudFNoYWRlcik7XG5cbiAgICAgICAgLy8gTGlua1xuICAgICAgICB0aGlzLmdsLmxpbmtQcm9ncmFtKHByb2dyYW0pO1xuICAgICAgICBpZiAoIXRoaXMuZ2wuZ2V0UHJvZ3JhbVBhcmFtZXRlcihwcm9ncmFtLCB0aGlzLmdsLkxJTktfU1RBVFVTKSkge1xuICAgICAgICAgICAgLy8gRXJyb3IgbGlua2luZ1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFwiRmFpbGVkIHRvIGxpbmsgcHJvZ3JhbTogXCIgKyBlcnJvcik7XG5cbiAgICAgICAgICAgIC8vIENsZWFuIHVwXG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVNoYWRlcih2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgICAgICAgdGhpcy5nbC5kZWxldGVTaGFkZXIoZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBzdWNjZXNzZnVsbHkgY3JlYXRlIGEgcHJvZ3JhbVxuICAgICAgICByZXR1cm4gW3Byb2dyYW0sIHZlcnRleFNoYWRlciwgZnJhZ21lbnRTaGFkZXJdO1xuICAgIH1cblxuICAgIHByaXZhdGUgbG9hZFZlcnRleFNoYWRlcihzaGFkZXJTb3VyY2U6IHN0cmluZyk6IFdlYkdMU2hhZGVyIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHZlcnRleCBzaGFkZXJcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZFNoYWRlcih0aGlzLmdsLlZFUlRFWF9TSEFERVIsIHNoYWRlclNvdXJjZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkRnJhZ21lbnRTaGFkZXIoc2hhZGVyU291cmNlOiBzdHJpbmcpOiBXZWJHTFNoYWRlciB7XG4gICAgICAgIC8vIENyZWF0ZSBhIG5ldyBmcmFnbWVudCBzaGFkZXJcbiAgICAgICAgcmV0dXJuIHRoaXMubG9hZFNoYWRlcih0aGlzLmdsLkZSQUdNRU5UX1NIQURFUiwgc2hhZGVyU291cmNlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRTaGFkZXIodHlwZTogbnVtYmVyLCBzaGFkZXJTb3VyY2U6IHN0cmluZyk6IFdlYkdMU2hhZGVyIHtcbiAgICAgICAgY29uc3Qgc2hhZGVyID0gdGhpcy5nbC5jcmVhdGVTaGFkZXIodHlwZSk7XG5cbiAgICAgICAgLy8gSWYgd2UgY291bGRuJ3QgY3JlYXRlIHRoZSBzaGFkZXIsIGVycm9yXG4gICAgICAgIGlmIChzaGFkZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlVuYWJsZSB0byBjcmVhdGUgc2hhZGVyXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIHNvdXJjZSB0byB0aGUgc2hhZGVyIGFuZCBjb21waWxlXG4gICAgICAgIHRoaXMuZ2wuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyU291cmNlKTtcbiAgICAgICAgdGhpcy5nbC5jb21waWxlU2hhZGVyKHNoYWRlcik7XG5cbiAgICAgICAgLy8gTWFrZSBzdXJlIHRoZXJlIHdlcmUgbm8gZXJyb3JzIGR1cmluZyB0aGlzIHByb2Nlc3NcbiAgICAgICAgaWYgKCF0aGlzLmdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIHRoaXMuZ2wuQ09NUElMRV9TVEFUVVMpKSB7XG4gICAgICAgICAgICAvLyBOb3QgY29tcGlsZWQgLSBlcnJvclxuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0aGlzLmdsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBjb21waWxlIHNoYWRlcjogXCIgKyBlcnJvcik7XG5cbiAgICAgICAgICAgIC8vIENsZWFuIHVwXG4gICAgICAgICAgICB0aGlzLmdsLmRlbGV0ZVNoYWRlcihzaGFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdWNlc3MsIHNvIHJldHVybiB0aGUgc2hhZGVyXG4gICAgICAgIHJldHVybiBzaGFkZXI7XG4gICAgfVxuXG4gICAgLyogIyMjIyMjIyMjIyBHRU5FUkFMIExPQURJTkcgRlVOQ1RJT05TICMjIyMjIyMjIyMgKi9cblxuICAgIHByaXZhdGUgbG9hZFRleHRGaWxlKHRleHRGaWxlUGF0aDogc3RyaW5nLCBjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgbGV0IHhvYmo6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHhvYmoub3ZlcnJpZGVNaW1lVHlwZShcImFwcGxpY2F0aW9uL2pzb25cIik7XG4gICAgICAgIHhvYmoub3BlbignR0VUJywgdGV4dEZpbGVQYXRoLCB0cnVlKTtcbiAgICAgICAgeG9iai5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoKHhvYmoucmVhZHlTdGF0ZSA9PSA0KSAmJiAoeG9iai5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKHhvYmoucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgeG9iai5zZW5kKG51bGwpO1xuICAgIH1cblxuICAgIC8qICMjIyMjIyMjIyMgTE9BRElORyBCQVIgSU5GTyAjIyMjIyMjIyMjICovXG5cbiAgICBwcml2YXRlIGdldExvYWRQZXJjZW50KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAodGhpcy5sb2Fkb25seV90aWxlbWFwc0xvYWRlZCAvIHRoaXMubG9hZG9ubHlfdGlsZW1hcHNUb0xvYWRcbiAgICAgICAgICAgICsgdGhpcy5sb2Fkb25seV9zcHJpdGVzaGVldHNMb2FkZWQgLyB0aGlzLmxvYWRvbmx5X3Nwcml0ZXNoZWV0c1RvTG9hZFxuICAgICAgICAgICAgKyB0aGlzLmxvYWRvbmx5X2ltYWdlc0xvYWRlZCAvIHRoaXMubG9hZG9ubHlfaW1hZ2VzVG9Mb2FkXG4gICAgICAgICAgICArIHRoaXMubG9hZG9ubHlfYXVkaW9Mb2FkZWQgLyB0aGlzLmxvYWRvbmx5X2F1ZGlvVG9Mb2FkKVxuICAgICAgICAgICAgLyB0aGlzLmxvYWRvbmx5X3R5cGVzVG9Mb2FkO1xuICAgIH1cblxuICAgIC8vIEN1c3RvbWl6ZWQgZnVudGlvbnMgYmVsb3dcbiAgICAvLyBUaGVzZSBmdW50aW9ucyBhcmUgTk9UIHdlbGwgdGVzdGVkISEhXG4gICAgLy8gT25seSB1c2VkIGZvciBzaGF0dGVyZWQgc3dvcmQgc3BlY2lmaWMgcHVycG9zZSEhIVxuICAgIC8vIFVzZSB0aGVtIGNhcmVmdWxseSEhIVxuXG4gICAgcHVibGljIHRpbGVtYXBGcm9tT2JqZWN0KGtleTogc3RyaW5nLCB0aWxlbWFwOiBUaWxlZFRpbGVtYXBEYXRhKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIG1hcDogdGlsZW1hcCB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRUaWxlbWFwT2JqZWN0RnJvbVF1ZXVlKG9uRmluaXNoTG9hZGluZzogRnVuY3Rpb24pIHtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID0gdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGluZ1F1ZXVlLmdldFNpemUoKTtcbiAgICAgICAgdGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGVkID0gMDtcblxuICAgICAgICAvLyBJZiBubyBpdGVtcyB0byBsb2FkLCB3ZSdyZSBmaW5pc2hlZFxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0VG9Mb2FkID09PSAwKSB7XG4gICAgICAgICAgICBvbkZpbmlzaExvYWRpbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlICh0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkaW5nUXVldWUuaGFzSXRlbXMoKSkge1xuICAgICAgICAgICAgbGV0IG1hcCA9IHRoaXMubG9hZG9ubHlfdGlsZW1hcE9iamVjdExvYWRpbmdRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRUaWxlbWFwRnJvbU9iamVjdChtYXAua2V5LCBtYXAubWFwLCBvbkZpbmlzaExvYWRpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkVGlsZW1hcEZyb21PYmplY3Qoa2V5OiBzdHJpbmcsIHRpbGVkTWFwOiBUaWxlZFRpbGVtYXBEYXRhLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgLy8gV2UgY2FuIHBhcnNlIHRoZSBvYmplY3QgbGF0ZXIgLSBpdCdzIG11Y2ggZmFzdGVyIHRoYW4gbG9hZGluZ1xuXG4gICAgICAgIHRoaXMudGlsZW1hcHMuYWRkKGtleSwgdGlsZWRNYXApO1xuICAgICAgICBsZXQgcmVzb3VyY2UgPSBuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuVElMRU1BUCk7XG5cbiAgICAgICAgLy8gR3JhYiB0aGUgdGlsZXNldCBpbWFnZXMgd2UgbmVlZCB0byBsb2FkIGFuZCBhZGQgdGhlbSB0byB0aGUgaW1hZ2Vsb2FkaW5nIHF1ZXVlXG4gICAgICAgIGZvciAobGV0IHRpbGVzZXQgb2YgdGlsZWRNYXAudGlsZXNldHMpIHtcbiAgICAgICAgICAgIGlmICh0aWxlc2V0LmltYWdlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGtleSA9IHRpbGVzZXQuaW1hZ2U7XG4gICAgICAgICAgICAgICAgbGV0IHBhdGggPSBrZXk7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2Fkb25seV9pbWFnZUxvYWRpbmdRdWV1ZS5lbnF1ZXVlKHsga2V5OiBrZXksIHBhdGg6IHBhdGgsIGlzRGVwZW5kZW5jeTogdHJ1ZSB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGltYWdlIGFzIGEgZGVwZW5kZW5jeSB0byB0aGUgdGlsZW1hcFxuICAgICAgICAgICAgICAgIHJlc291cmNlLmFkZERlcGVuZGVuY3kobmV3IFJlc291cmNlUmVmZXJlbmNlKGtleSwgUmVzb3VyY2VUeXBlLklNQUdFKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIHJlc291cmNlIHJlZmVyZW5jZSB0byB0aGUgbGlzdCBvZiByZXNvdXJjZSB0byB1bmxvYWRcbiAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKHJlc291cmNlKTtcblxuICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdUaWxlbWFwT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmlzaExvYWRpbmdUaWxlbWFwT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RMb2FkZWQgKz0gMTtcblxuICAgICAgICBpZiAodGhpcy5sb2Fkb25seV90aWxlbWFwT2JqZWN0TG9hZGVkID09PSB0aGlzLmxvYWRvbmx5X3RpbGVtYXBPYmplY3RUb0xvYWQpIHtcbiAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgbG9hZGluZyB0aWxlbWFwc1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzaW5nbGVJbWFnZShrZXk6IHN0cmluZywgcGF0aDogc3RyaW5nLCBjYWxsYmFja0lmTGFzdDogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdmFyIGltYWdlID0gbmV3IEltYWdlKCk7XG5cbiAgICAgICAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQWRkIHRvIGxvYWRlZCBpbWFnZXNcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VzLmFkZChrZXksIGltYWdlKTtcblxuICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXNUb1VubG9hZC5wdXNoKG5ldyBSZXNvdXJjZVJlZmVyZW5jZShrZXksIFJlc291cmNlVHlwZS5JTUFHRSkpO1xuXG4gICAgICAgICAgICAvLyBJZiBXZWJHTCBpcyBhY3RpdmUsIGNyZWF0ZSBhIHRleHR1cmVcbiAgICAgICAgICAgIGlmICh0aGlzLmdsX1dlYkdMQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVXZWJHTFRleHR1cmUoa2V5LCBpbWFnZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbmlzaCBpbWFnZSBsb2FkXG4gICAgICAgICAgICB0aGlzLmZpbmlzaExvYWRpbmdTaW5nbGVPYmplY3QoY2FsbGJhY2tJZkxhc3QpO1xuICAgICAgICB9XG4gICAgICAgIGltYWdlLnNyYyA9IHBhdGg7XG4gICAgfVxuXG4gICAgcHVibGljIHNpbmdsZUF1ZGlvKGtleTogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGNhbGxiYWNrSWZMYXN0OiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBsZXQgYXVkaW9DdHggPSBBdWRpb01hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRBdWRpb0NvbnRleHQoKTtcblxuICAgICAgICBsZXQgcmVxdWVzdCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICByZXF1ZXN0Lm9wZW4oJ0dFVCcsIHBhdGgsIHRydWUpO1xuICAgICAgICByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG5cbiAgICAgICAgcmVxdWVzdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICBhdWRpb0N0eC5kZWNvZGVBdWRpb0RhdGEocmVxdWVzdC5yZXNwb25zZSwgKGJ1ZmZlcikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEFkZCB0byBsaXN0IG9mIGF1ZGlvIGJ1ZmZlcnNcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvQnVmZmVycy5hZGQoa2V5LCBidWZmZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzVG9VbmxvYWQucHVzaChuZXcgUmVzb3VyY2VSZWZlcmVuY2Uoa2V5LCBSZXNvdXJjZVR5cGUuQVVESU8pKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmlzaCBsb2FkaW5nIHNvdW5kXG4gICAgICAgICAgICAgICAgdGhpcy5maW5pc2hMb2FkaW5nU2luZ2xlT2JqZWN0KGNhbGxiYWNrSWZMYXN0KTtcbiAgICAgICAgICAgIH0sIChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IFwiRXJyb3IgbG9hZGluZyBzb3VuZFwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVxdWVzdC5zZW5kKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5pc2hMb2FkaW5nU2luZ2xlT2JqZWN0KGNhbGxiYWNrOiBGdW5jdGlvbik6IHZvaWQge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5sb2FkaW5nKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vbkxvYWRQcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIHRoaXMub25Mb2FkUHJvZ3Jlc3ModGhpcy5nZXRMb2FkUGVyY2VudCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmp1c3RMb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuanVzdExvYWRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMub25Mb2FkQ29tcGxldGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uTG9hZENvbXBsZXRlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQSBjbGFzcyByZXByZXNlbnRpbmcgYSByZWZlcmVuY2UgdG8gYSByZXNvdXJjZS5cbiAqIFRoaXMgaXMgdXNlZCBmb3IgdGhlIGV4ZW1wdGlvbiBsaXN0IHRvIGFzc3VyZSBhc3NldHMgYW5kIHRoZWlyIGRlcGVuZGVuY2llcyBkb24ndCBnZXRcbiAqIGRlc3Ryb3llZCBpZiB0aGV5IGFyZSBzdGlsbCBuZWVkZWQuXG4gKi9cbmNsYXNzIFJlc291cmNlUmVmZXJlbmNlIHtcbiAgICBrZXk6IHN0cmluZztcbiAgICByZXNvdXJjZVR5cGU6IFJlc291cmNlVHlwZTtcbiAgICBkZXBlbmRlbmNpZXM6IEFycmF5PFJlc291cmNlUmVmZXJlbmNlPjtcblxuICAgIGNvbnN0cnVjdG9yKGtleTogc3RyaW5nLCByZXNvdXJjZVR5cGU6IFJlc291cmNlVHlwZSkge1xuICAgICAgICB0aGlzLmtleSA9IGtleTtcbiAgICAgICAgdGhpcy5yZXNvdXJjZVR5cGUgPSByZXNvdXJjZVR5cGU7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gbmV3IEFycmF5KCk7XG4gICAgfVxuXG4gICAgYWRkRGVwZW5kZW5jeShyZXNvdXJjZTogUmVzb3VyY2VSZWZlcmVuY2UpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMucHVzaChyZXNvdXJjZSk7XG4gICAgfVxufVxuXG5cbmVudW0gUmVzb3VyY2VUeXBlIHtcbiAgICBJTUFHRSA9IFwiSU1BR0VcIixcbiAgICBUSUxFTUFQID0gXCJUSUxFTUFQXCIsXG4gICAgU1BSSVRFU0hFRVQgPSBcIlNQUklURVNIRUVUXCIsXG4gICAgQVVESU8gPSBcIkFVRElPXCIsXG4gICAgSlNPTiA9IFwiSlNPTlwiLFxuICAgIFNIQURFUiA9IFwiU0hBREVSXCJcbn1cblxuLyoqXG4gKiBBIHBhaXIgcmVwcmVzZW50aW5nIGEga2V5IGFuZCB0aGUgcGF0aCBvZiB0aGUgcmVzb3VyY2UgdG8gbG9hZFxuICovXG5jbGFzcyBLZXlQYXRoUGFpciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIGlzRGVwZW5kZW5jeT86IGJvb2xlYW4gPSBmYWxzZTtcbn1cblxuY2xhc3MgS2V5TWFwUGFpciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgbWFwOiBUaWxlZFRpbGVtYXBEYXRhO1xufVxuXG5jbGFzcyBLZXlQYXRoX1NoYWRlciB7XG4gICAga2V5OiBzdHJpbmc7XG4gICAgdnBhdGg6IHN0cmluZztcbiAgICBmcGF0aDogc3RyaW5nO1xufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgUG9pbnQgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1BvaW50XCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBTbGlkZXIgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvU2xpZGVyXCI7XG5pbXBvcnQgVGV4dElucHV0IGZyb20gXCIuLi8uLi9Ob2Rlcy9VSUVsZW1lbnRzL1RleHRJbnB1dFwiO1xuaW1wb3J0IFJlY3QgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1JlY3RcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBMaW5lIGZyb20gXCIuLi8uLi9Ob2Rlcy9HcmFwaGljcy9MaW5lXCI7XG5pbXBvcnQgUGFydGljbGUgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL1BhcnRpY2xlXCI7XG5cbi8vIEBpZ25vcmVQYWdlXG5cbi8qKlxuICogQSBmYWN0b3J5IHRoYXQgYWJzdHJhY3RzIGFkZGluZyBAcmVmZXJlbmNlW0NhbnZhc05vZGVdcyB0byB0aGUgQHJlZmVyZW5jZVtTY2VuZV0uXG4gKiBBY2Nlc3MgbWV0aG9kcyBpbiB0aGlzIGZhY3RvcnkgdGhyb3VnaCBTY2VuZS5hZGQuW21ldGhvZE5hbWVdKCkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhbnZhc05vZGVGYWN0b3J5IHtcblx0cHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdGluaXQoc2NlbmU6IFNjZW5lKTogdm9pZCB7XG5cdFx0dGhpcy5zY2VuZSA9IHNjZW5lO1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdH1cblxuXHQvKipcblx0ICogQWRkcyBhbiBpbnN0YW5jZSBvZiBhIFVJRWxlbWVudCB0byB0aGUgY3VycmVudCBzY2VuZSAtIGkuZS4gYW55IGNsYXNzIHRoYXQgZXh0ZW5kcyBVSUVsZW1lbnRcblx0ICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb2YgVUlFbGVtZW50IHRvIGFkZFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciB0byBhZGQgdGhlIFVJRWxlbWVudCB0b1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gZmVlZCB0byB0aGUgY29uc3RydWN0b3Jcblx0ICogQHJldHVybnMgQSBuZXcgVUlFbGVtZW50XG5cdCAqL1xuXHRhZGRVSUVsZW1lbnQgPSAodHlwZTogc3RyaW5nIHwgVUlFbGVtZW50VHlwZSwgbGF5ZXJOYW1lOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogVUlFbGVtZW50ID0+IHtcblx0XHQvLyBHZXQgdGhlIGxheWVyXG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXG5cdFx0bGV0IGluc3RhbmNlOiBVSUVsZW1lbnQ7XG5cblx0XHRzd2l0Y2godHlwZSl7XG5cdFx0XHRjYXNlIFVJRWxlbWVudFR5cGUuQlVUVE9OOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRCdXR0b24ob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGNhc2UgVUlFbGVtZW50VHlwZS5MQUJFTDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkTGFiZWwob3B0aW9ucyk7XG5cdFx0XHRicmVhaztcblx0XHRcdGNhc2UgVUlFbGVtZW50VHlwZS5TTElERVI6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFNsaWRlcihvcHRpb25zKTtcblx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBVSUVsZW1lbnRUeXBlLlRFWFRfSU5QVVQ6XG5cdFx0XHRcdGluc3RhbmNlID0gdGhpcy5idWlsZFRleHRJbnB1dChvcHRpb25zKTtcblx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0dGhyb3cgYFVJRWxlbWVudFR5cGUgJyR7dHlwZX0nIGRvZXMgbm90IGV4aXN0LCBvciBpcyByZWdpc3RlcmVkIGluY29ycmVjdGx5LmBcblx0XHR9XG5cblx0XHRpbnN0YW5jZS5zZXRTY2VuZSh0aGlzLnNjZW5lKTtcblx0XHRpbnN0YW5jZS5pZCA9IHRoaXMuc2NlbmUuZ2VuZXJhdGVJZCgpO1xuXHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0Ly8gQWRkIGluc3RhbmNlIHRvIGxheWVyXG5cdFx0bGF5ZXIuYWRkTm9kZShpbnN0YW5jZSlcblxuXHRcdHJldHVybiBpbnN0YW5jZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgc3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBTcHJpdGVcblx0ICovXG5cdGFkZFNwcml0ZSA9IChrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBTcHJpdGUgPT4ge1xuXHRcdGxldCBsYXllciA9IHRoaXMuc2NlbmUuZ2V0TGF5ZXIobGF5ZXJOYW1lKTtcblxuXHRcdGxldCBpbnN0YW5jZSA9IG5ldyBTcHJpdGUoa2V5KTtcblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cblx0XHRpZighKHRoaXMuc2NlbmUuaXNQYXJhbGxheExheWVyKGxheWVyTmFtZSkgfHwgdGhpcy5zY2VuZS5pc1VJTGF5ZXIobGF5ZXJOYW1lKSkpe1xuXHRcdFx0dGhpcy5zY2VuZS5nZXRTY2VuZUdyYXBoKCkuYWRkTm9kZShpbnN0YW5jZSk7XG5cdFx0fVxuXHRcdFxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYW4gQW5pbWF0ZWRTcHJpdGUgdG8gdGhlIGN1cnJlbnQgc2NlbmVcblx0ICogQHBhcmFtIGtleSBUaGUga2V5IG9mIHRoZSBpbWFnZSB0aGUgc3ByaXRlIHdpbGwgcmVwcmVzZW50XG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgc3ByaXRlXG5cdCAqIEByZXR1cm5zIEEgbmV3IEFuaW1hdGVkU3ByaXRlXG5cdCAqL1xuXHRhZGRBbmltYXRlZFNwcml0ZSA9IChrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBBbmltYXRlZFNwcml0ZSA9PiB7XG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXHRcdGxldCBzcHJpdGVzaGVldCA9IHRoaXMucmVzb3VyY2VNYW5hZ2VyLmdldFNwcml0ZXNoZWV0KGtleSk7XG5cdFx0bGV0IGluc3RhbmNlID0gbmV3IEFuaW1hdGVkU3ByaXRlKHNwcml0ZXNoZWV0KTtcblxuXHRcdC8vIEFkZCBpbnN0YW5jZSBmbyBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cdFx0XG5cdFx0aWYoISh0aGlzLnNjZW5lLmlzUGFyYWxsYXhMYXllcihsYXllck5hbWUpIHx8IHRoaXMuc2NlbmUuaXNVSUxheWVyKGxheWVyTmFtZSkpKXtcblx0XHRcdHRoaXMuc2NlbmUuZ2V0U2NlbmVHcmFwaCgpLmFkZE5vZGUoaW5zdGFuY2UpO1xuXHRcdH1cblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBsYXllclxuXHRcdGxheWVyLmFkZE5vZGUoaW5zdGFuY2UpO1xuXG5cdFx0cmV0dXJuIGluc3RhbmNlO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFkZHMgYSBuZXcgZ3JhcGhpYyBlbGVtZW50IHRvIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIGdyYXBoaWMgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgZ3JhcGhpY1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgZ3JhcGhpYyBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBHcmFwaGljXG5cdCAqL1xuXHRhZGRHcmFwaGljID0gKHR5cGU6IEdyYXBoaWNUeXBlIHwgc3RyaW5nLCBsYXllck5hbWU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBHcmFwaGljID0+IHtcblx0XHQvLyBHZXQgdGhlIGxheWVyXG5cdFx0bGV0IGxheWVyID0gdGhpcy5zY2VuZS5nZXRMYXllcihsYXllck5hbWUpO1xuXG5cdFx0bGV0IGluc3RhbmNlOiBHcmFwaGljO1xuXG5cdFx0c3dpdGNoKHR5cGUpe1xuXHRcdFx0Y2FzZSBHcmFwaGljVHlwZS5QT0lOVDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkUG9pbnQob3B0aW9ucyk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBHcmFwaGljVHlwZS5MSU5FOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRMaW5lKG9wdGlvbnMpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgR3JhcGhpY1R5cGUuUkVDVDpcblx0XHRcdFx0aW5zdGFuY2UgPSB0aGlzLmJ1aWxkUmVjdChvcHRpb25zKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIEdyYXBoaWNUeXBlLlBBUlRJQ0xFOlxuXHRcdFx0XHRpbnN0YW5jZSA9IHRoaXMuYnVpbGRQYXJ0aWNsZShvcHRpb25zKTtcblx0XHRcdFx0YnJlYWs7XHRcdFx0XHRcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHRocm93IGBHcmFwaGljVHlwZSAnJHt0eXBlfScgZG9lcyBub3QgZXhpc3QsIG9yIGlzIHJlZ2lzdGVyZWQgaW5jb3JyZWN0bHkuYFxuXHRcdH1cblxuXHRcdC8vIEFkZCBpbnN0YW5jZSB0byBzY2VuZVxuXHRcdGluc3RhbmNlLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuXHRcdGluc3RhbmNlLmlkID0gdGhpcy5zY2VuZS5nZW5lcmF0ZUlkKCk7XG5cblx0XHRpZighKHRoaXMuc2NlbmUuaXNQYXJhbGxheExheWVyKGxheWVyTmFtZSkgfHwgdGhpcy5zY2VuZS5pc1VJTGF5ZXIobGF5ZXJOYW1lKSkpe1xuXHRcdFx0dGhpcy5zY2VuZS5nZXRTY2VuZUdyYXBoKCkuYWRkTm9kZShpbnN0YW5jZSk7XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIGluc3RhbmNlIHRvIGxheWVyXG5cdFx0bGF5ZXIuYWRkTm9kZShpbnN0YW5jZSk7XG5cblx0XHRyZXR1cm4gaW5zdGFuY2U7XG5cdH1cblxuXHQvKiAtLS0tLS0tLS0tIEJVSUxERVJTIC0tLS0tLS0tLS0gKi9cblxuXHRidWlsZEJ1dHRvbihvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IEJ1dHRvbiB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIkJ1dHRvblwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiQnV0dG9uXCIsIG9wdGlvbnMsIFwidGV4dFwiLCBcInN0cmluZ1wiKTtcblxuXHRcdHJldHVybiBuZXcgQnV0dG9uKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMudGV4dCk7XG5cdH1cblxuXHRidWlsZExhYmVsKG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogTGFiZWwge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJMYWJlbFwiLCBvcHRpb25zLCBcInBvc2l0aW9uXCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGFiZWxcIiwgb3B0aW9ucywgXCJ0ZXh0XCIsIFwic3RyaW5nXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBMYWJlbChvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnRleHQpXG5cdH1cblxuXHRidWlsZFNsaWRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogU2xpZGVyIHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiU2xpZGVyXCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0bGV0IGluaXRWYWx1ZSA9IDA7XG5cdFx0aWYob3B0aW9ucy52YWx1ZSAhPT0gdW5kZWZpbmVkKXtcblx0XHRcdGluaXRWYWx1ZSA9IG9wdGlvbnMudmFsdWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG5ldyBTbGlkZXIob3B0aW9ucy5wb3NpdGlvbiwgaW5pdFZhbHVlKTtcblx0fVxuXG5cdGJ1aWxkVGV4dElucHV0KG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiBUZXh0SW5wdXQge1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJUZXh0SW5wdXRcIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cblx0XHRyZXR1cm4gbmV3IFRleHRJbnB1dChvcHRpb25zLnBvc2l0aW9uKTtcblx0fVxuXG5cdGJ1aWxkUG9pbnQob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQb2ludCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlBvaW50XCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXG5cdFx0cmV0dXJuIG5ldyBQb2ludChvcHRpb25zLnBvc2l0aW9uKTtcblx0fVxuXG5cdGJ1aWxkUGFydGljbGUob3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBQb2ludCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlBhcnRpY2xlXCIsIG9wdGlvbnMsIFwicG9zaXRpb25cIiwgVmVjMiwgXCJWZWMyXCIpO1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQYXJ0aWNsZVwiLCBvcHRpb25zLCBcInNpemVcIiwgVmVjMiwgXCJWZWMyXCIpO1xuXHRcdHRoaXMuY2hlY2tJZlByb3BFeGlzdHMoXCJQYXJ0aWNsZVwiLCBvcHRpb25zLCBcIm1hc3NcIiwgXCJudW1iZXJcIiwgXCJudW1iZXJcIik7XG5cblx0XHQvL0NoYW5nZWQgZm9yIHRlc3Rpbmdcblx0XHRyZXR1cm4gbmV3IFBhcnRpY2xlKG9wdGlvbnMucG9zaXRpb24sIG9wdGlvbnMuc2l6ZSwgb3B0aW9ucy5tYXNzKTtcblx0fVxuXG5cdGJ1aWxkTGluZShvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFBvaW50IHtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGluZVwiLCBvcHRpb25zLCBcInN0YXJ0XCIsIFZlYzIsIFwiVmVjMlwiKTtcblx0XHR0aGlzLmNoZWNrSWZQcm9wRXhpc3RzKFwiTGluZVwiLCBvcHRpb25zLCBcImVuZFwiLCBWZWMyLCBcIlZlYzJcIik7XG5cblx0XHRyZXR1cm4gbmV3IExpbmUob3B0aW9ucy5zdGFydCwgb3B0aW9ucy5lbmQpO1xuXHR9XG5cblx0YnVpbGRSZWN0KG9wdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogUmVjdCB7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlJlY3RcIiwgb3B0aW9ucywgXCJwb3NpdGlvblwiLCBWZWMyLCBcIlZlYzJcIik7XG5cdFx0dGhpcy5jaGVja0lmUHJvcEV4aXN0cyhcIlJlY3RcIiwgb3B0aW9ucywgXCJzaXplXCIsIFZlYzIsIFwiVmVjMlwiKTtcblxuXHRcdHJldHVybiBuZXcgUmVjdChvcHRpb25zLnBvc2l0aW9uLCBvcHRpb25zLnNpemUpO1xuXHR9XG5cblx0LyogLS0tLS0tLS0tLSBFUlJPUiBIQU5ETElORyAtLS0tLS0tLS0tICovXG5cblx0Y2hlY2tJZlByb3BFeGlzdHM8VD4ob2JqZWN0TmFtZTogc3RyaW5nLCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBwcm9wOiBzdHJpbmcsIHR5cGU6IChuZXcgKC4uLmFyZ3M6IGFueSkgPT4gVCkgfCBzdHJpbmcsIHR5cGVOYW1lPzogc3RyaW5nKXtcblx0XHRpZighb3B0aW9ucyB8fCBvcHRpb25zW3Byb3BdID09PSB1bmRlZmluZWQpe1xuXHRcdFx0Ly8gQ2hlY2sgdGhhdCB0aGUgb3B0aW9ucyBvYmplY3QgaGFzIHRoZSBwcm9wZXJ0eVxuXHRcdFx0dGhyb3cgYCR7b2JqZWN0TmFtZX0gb2JqZWN0IHJlcXVpcmVzIGFyZ3VtZW50ICR7cHJvcH0gb2YgdHlwZSAke3R5cGVOYW1lfSwgYnV0IG5vbmUgd2FzIHByb3ZpZGVkLmA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIENoZWNrIHRoYXQgdGhlIHByb3BlcnR5IGhhcyB0aGUgY29ycmVjdCB0eXBlXG5cdFx0XHRpZigodHlwZW9mIHR5cGUpID09PSBcInN0cmluZ1wiKXtcblx0XHRcdFx0aWYoISh0eXBlb2Ygb3B0aW9uc1twcm9wXSA9PT0gdHlwZSkpe1xuXHRcdFx0XHRcdHRocm93IGAke29iamVjdE5hbWV9IG9iamVjdCByZXF1aXJlcyBhcmd1bWVudCAke3Byb3B9IG9mIHR5cGUgJHt0eXBlfSwgYnV0IHByb3ZpZGVkICR7cHJvcH0gd2FzIG5vdCBvZiB0eXBlICR7dHlwZX0uYDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmKHR5cGUgaW5zdGFuY2VvZiBGdW5jdGlvbil7XG5cdFx0XHRcdC8vIElmIHR5cGUgaXMgYSBjb25zdHJ1Y3RvciwgY2hlY2sgYWdhaW5zdCB0aGF0XG5cdFx0XHRcdGlmKCEob3B0aW9uc1twcm9wXSBpbnN0YW5jZW9mIHR5cGUpKXtcblx0XHRcdFx0XHR0aHJvdyBgJHtvYmplY3ROYW1lfSBvYmplY3QgcmVxdWlyZXMgYXJndW1lbnQgJHtwcm9wfSBvZiB0eXBlICR7dHlwZU5hbWV9LCBidXQgcHJvdmlkZWQgJHtwcm9wfSB3YXMgbm90IG9mIHR5cGUgJHt0eXBlTmFtZX0uYDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhyb3cgYCR7b2JqZWN0TmFtZX0gb2JqZWN0IHJlcXVpcmVzIGFyZ3VtZW50ICR7cHJvcH0gb2YgdHlwZSAke3R5cGVOYW1lfSwgYnV0IHByb3ZpZGVkICR7cHJvcH0gd2FzIG5vdCBvZiB0eXBlICR7dHlwZU5hbWV9LmA7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuaW1wb3J0IENhbnZhc05vZGVGYWN0b3J5IGZyb20gXCIuL0NhbnZhc05vZGVGYWN0b3J5XCI7XG5pbXBvcnQgVGlsZW1hcEZhY3RvcnkgZnJvbSBcIi4vVGlsZW1hcEZhY3RvcnlcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBVSUVsZW1lbnQgZnJvbSBcIi4uLy4uL05vZGVzL1VJRWxlbWVudFwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCB7IEdyYXBoaWNUeXBlIH0gZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNzL0dyYXBoaWNUeXBlc1wiO1xuaW1wb3J0IEdyYXBoaWMgZnJvbSBcIi4uLy4uL05vZGVzL0dyYXBoaWNcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL0xheWVyXCI7XG5cbi8qKlxuICogVGhlIG1hbmFnZXIgb2YgYWxsIGZhY3RvcmllcyB1c2VkIGZvciBhZGRpbmcgQHJlZmVyZW5jZVtHYW1lTm9kZV1zIHRvIHRoZSBAcmVmZXJlbmNlW1NjZW5lXS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFjdG9yeU1hbmFnZXIge1xuXG4gICAgLy8gQ29uc3RydWN0b3JzIGFyZSBjYWxsZWQgaGVyZSB0byBhbGxvdyBhc3NpZ25tZW50IG9mIHRoZWlyIGZ1bmN0aW9ucyB0byBmdW5jdGlvbnMgaW4gdGhpcyBjbGFzc1xuICAgIHByaXZhdGUgY2FudmFzTm9kZUZhY3Rvcnk6IENhbnZhc05vZGVGYWN0b3J5ID0gbmV3IENhbnZhc05vZGVGYWN0b3J5KCk7XG4gICAgcHJpdmF0ZSB0aWxlbWFwRmFjdG9yeTogVGlsZW1hcEZhY3RvcnkgPSBuZXcgVGlsZW1hcEZhY3RvcnkoKTtcblxuICAgIGNvbnN0cnVjdG9yKHNjZW5lOiBTY2VuZSwgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+KXtcbiAgICAgICAgdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5pbml0KHNjZW5lKTtcbiAgICAgICAgdGhpcy50aWxlbWFwRmFjdG9yeS5pbml0KHNjZW5lLCB0aWxlbWFwcyk7XG4gICAgfVxuXG4gICAgLy8gRXhwb3NlIGFsbCBvZiB0aGUgZmFjdG9yaWVzIHRocm91Z2ggdGhlIGZhY3RvcnkgbWFuYWdlclxuICAgIC8qKlxuXHQgKiBBZGRzIGFuIGluc3RhbmNlIG9mIGEgVUlFbGVtZW50IHRvIHRoZSBjdXJyZW50IHNjZW5lIC0gaS5lLiBhbnkgY2xhc3MgdGhhdCBleHRlbmRzIFVJRWxlbWVudFxuXHQgKiBAcGFyYW0gdHlwZSBUaGUgdHlwZSBvZiBVSUVsZW1lbnQgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIHRvIGFkZCB0aGUgVUlFbGVtZW50IHRvXG5cdCAqIEBwYXJhbSBvcHRpb25zIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBmZWVkIHRvIHRoZSBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBVSUVsZW1lbnRcblx0ICovXG4gICAgdWlFbGVtZW50KHR5cGU6IHN0cmluZyB8IFVJRWxlbWVudFR5cGUsIGxheWVyTmFtZTogc3RyaW5nLCBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55Pik6IFVJRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhc05vZGVGYWN0b3J5LmFkZFVJRWxlbWVudCh0eXBlLCBsYXllck5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBBZGRzIGEgc3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBTcHJpdGVcblx0ICovXG5cdHNwcml0ZShrZXk6IHN0cmluZywgbGF5ZXJOYW1lOiBzdHJpbmcpOiBTcHJpdGUge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5hZGRTcHJpdGUoa2V5LCBsYXllck5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuXHQgKiBBZGRzIGFuIEFuaW1hdGVkU3ByaXRlIHRvIHRoZSBjdXJyZW50IHNjZW5lXG5cdCAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgaW1hZ2UgdGhlIHNwcml0ZSB3aWxsIHJlcHJlc2VudFxuXHQgKiBAcGFyYW0gbGF5ZXJOYW1lIFRoZSBsYXllciBvbiB3aGljaCB0byBhZGQgdGhlIHNwcml0ZVxuXHQgKiBAcmV0dXJucyBBIG5ldyBBbmltYXRlZFNwcml0ZVxuXHQgKi9cblx0YW5pbWF0ZWRTcHJpdGUoa2V5OiBzdHJpbmcsIGxheWVyTmFtZTogc3RyaW5nKTogQW5pbWF0ZWRTcHJpdGUge1xuICAgICAgICByZXR1cm4gdGhpcy5jYW52YXNOb2RlRmFjdG9yeS5hZGRBbmltYXRlZFNwcml0ZShrZXksIGxheWVyTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG5cdCAqIEFkZHMgYSBuZXcgZ3JhcGhpYyBlbGVtZW50IHRvIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSB0eXBlIFRoZSB0eXBlIG9mIGdyYXBoaWMgdG8gYWRkXG5cdCAqIEBwYXJhbSBsYXllck5hbWUgVGhlIGxheWVyIG9uIHdoaWNoIHRvIGFkZCB0aGUgZ3JhcGhpY1xuXHQgKiBAcGFyYW0gb3B0aW9ucyBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgZ3JhcGhpYyBjb25zdHJ1Y3RvclxuXHQgKiBAcmV0dXJucyBBIG5ldyBHcmFwaGljXG5cdCAqL1xuXHRncmFwaGljKHR5cGU6IEdyYXBoaWNUeXBlIHwgc3RyaW5nLCBsYXllck5hbWU6IHN0cmluZywgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBHcmFwaGljIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FudmFzTm9kZUZhY3RvcnkuYWRkR3JhcGhpYyh0eXBlLCBsYXllck5hbWUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSB0aWxlbWFwIHRvIHRoZSBzY2VuZVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgbG9hZGVkIHRpbGVtYXAgdG8gbG9hZFxuICAgICAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBkZXNpcmVkIHRpbGVtYXBcbiAgICAgKiBAcGFyYW0gYXJncyBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBzZW5kIHRvIHRoZSB0aWxlbWFwIGNvbnN0cnVjdG9yXG4gICAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgTGF5ZXJzLCBlYWNoIG9mIHdoaWNoIGNvbnRhaW5zIGEgbGF5ZXIgb2YgdGhlIHRpbGVtYXAgYXMgaXRzIG93biBUaWxlbWFwIGluc3RhbmNlLlxuICAgICAqL1xuXHR0aWxlbWFwKGtleTogc3RyaW5nLCBzY2FsZT86IFZlYzIpOiBBcnJheTxMYXllcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy50aWxlbWFwRmFjdG9yeS5hZGQoa2V5LCBzY2FsZSk7XG4gICAgfVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi4vU2NlbmVcIjtcbmltcG9ydCBUaWxlbWFwIGZyb20gXCIuLi8uLi9Ob2Rlcy9UaWxlbWFwXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi8uLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uL0xheWVyXCI7XG5pbXBvcnQgVGlsZXNldCBmcm9tIFwiLi4vLi4vRGF0YVR5cGVzL1RpbGVzZXRzL1RpbGVzZXRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgVGlsZWRDb2xsZWN0aW9uVGlsZSB9IGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFBvc2l0aW9uR3JhcGggZnJvbSBcIi4uLy4uL0RhdGFUeXBlcy9HcmFwaHMvUG9zaXRpb25HcmFwaFwiO1xuaW1wb3J0IE5hdm1lc2ggZnJvbSBcIi4uLy4uL1BhdGhmaW5kaW5nL05hdm1lc2hcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBBIGZhY3RvcnkgdGhhdCBhYnN0cmFjdHMgYWRkaW5nIEByZWZlcmVuY2VbVGlsZW1hcF1zIHRvIHRoZSBAcmVmZXJlbmNlW1NjZW5lXS5cbiAqIEFjY2VzcyBtZXRob2RzIGluIHRoaXMgZmFjdG9yeSB0aHJvdWdoIFNjZW5lLmFkZC5bbWV0aG9kTmFtZV0oKS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGlsZW1hcEZhY3Rvcnkge1xuICAgIHByaXZhdGUgc2NlbmU6IFNjZW5lO1xuICAgIHByaXZhdGUgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+O1xuICAgIHByaXZhdGUgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG4gICAgXG4gICAgaW5pdChzY2VuZTogU2NlbmUsIHRpbGVtYXBzOiBBcnJheTxUaWxlbWFwPik6IHZvaWQge1xuICAgICAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgICAgIHRoaXMudGlsZW1hcHMgPSB0aWxlbWFwcztcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIC0gVGhpcyBpcyBzcGVjaWZpY2FsbHkgY2F0ZXJlZCB0byBUaWxlZCB0aWxlbWFwcyByaWdodCBub3cuIEluIHRoZSBmdXR1cmUsXG4gICAgLy8gaXQgd291bGQgYmUgZ29vZCB0byBoYXZlIGEgXCJwYXJzZVRpbGVtYXBcIiBmdW5jdGlvbiB0aGF0IHdvdWxkIGNvbnZlcnQgdGhlIHRpbGVtYXBcbiAgICAvLyBkYXRhIGludG8gYSBzdGFuZGFyZCBmb3JtYXQuIFRoaXMgY291bGQgYWxsb3cgZm9yIHN1cHBvcnQgZnJvbSBvdGhlciBwcm9ncmFtc1xuICAgIC8vIG9yIHRoZSBkZXZlbG9wbWVudCBvZiBhbiBpbnRlcm5hbCBsZXZlbCBidWlsZGVyIHRvb2xcbiAgICAvKipcbiAgICAgKiBBZGRzIGEgdGlsZW1hcCB0byB0aGUgc2NlbmVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCB0aWxlbWFwIHRvIGxvYWRcbiAgICAgKiBAcGFyYW0gY29uc3RyIFRoZSBjb25zdHJ1Y3RvciBvZiB0aGUgZGVzaXJlZCB0aWxlbWFwXG4gICAgICogQHBhcmFtIGFyZ3MgQWRkaXRpb25hbCBhcmd1bWVudHMgdG8gc2VuZCB0byB0aGUgdGlsZW1hcCBjb25zdHJ1Y3RvclxuICAgICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIExheWVycywgZWFjaCBvZiB3aGljaCBjb250YWlucyBhIGxheWVyIG9mIHRoZSB0aWxlbWFwIGFzIGl0cyBvd24gVGlsZW1hcCBpbnN0YW5jZS5cbiAgICAgKi9cblx0YWRkID0gKGtleTogc3RyaW5nLCBzY2FsZTogVmVjMiA9IG5ldyBWZWMyKDEsIDEpKTogQXJyYXk8TGF5ZXI+ID0+IHtcbiAgICAgICAgLy8gR2V0IFRpbGVtYXAgRGF0YVxuICAgICAgICBsZXQgdGlsZW1hcERhdGEgPSB0aGlzLnJlc291cmNlTWFuYWdlci5nZXRUaWxlbWFwKGtleSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBjb25zdHJ1Y3RvciBmb3IgdGhpcyB0aWxlbWFwIHRvIGVpdGhlciBiZSBvcnRob2dyYXBoaWMgb3IgaXNvbWV0cmljXG4gICAgICAgIGxldCBjb25zdHI6IG5ldyguLi5hcmdzOiBhbnkpID0+IFRpbGVtYXA7XG4gICAgICAgIGlmKHRpbGVtYXBEYXRhLm9yaWVudGF0aW9uID09PSBcIm9ydGhvZ3JhcGhpY1wiKXtcbiAgICAgICAgICAgIGNvbnN0ciA9IE9ydGhvZ29uYWxUaWxlbWFwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gaXNvbWV0cmljIHRpbGVtYXAgc3VwcG9ydCByaWdodCBub3csIHNvIE9ydGhvZ3JhcGhpYyB0aWxlbWFwXG4gICAgICAgICAgICBjb25zdHIgPSBPcnRob2dvbmFsVGlsZW1hcDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHJldHVybiB2YWx1ZSBhcnJheVxuICAgICAgICBsZXQgc2NlbmVMYXllcnMgPSBuZXcgQXJyYXk8TGF5ZXI+KCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFsbCBvZiB0aGUgdGlsZXNldHMgZm9yIHRoaXMgdGlsZW1hcFxuICAgICAgICBsZXQgdGlsZXNldHMgPSBuZXcgQXJyYXk8VGlsZXNldD4oKTtcblxuICAgICAgICBsZXQgY29sbGVjdGlvblRpbGVzID0gbmV3IEFycmF5PFRpbGVkQ29sbGVjdGlvblRpbGU+KCk7XG5cbiAgICAgICAgZm9yKGxldCB0aWxlc2V0IG9mIHRpbGVtYXBEYXRhLnRpbGVzZXRzKXtcbiAgICAgICAgICAgIGlmKHRpbGVzZXQuaW1hZ2Upe1xuICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgYSBzdGFuZGFyZCB0aWxlc2V0IGFuZCBub3QgYSBjb2xsZWN0aW9uLCBjcmVhdGUgYSB0aWxlc2V0IGZvciBpdC5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIC0gV2UgYXJlIGlnbm9yaW5nIGNvbGxlY3Rpb24gdGlsZXNldHMgZm9yIG5vdy4gVGhpcyBpcyBsaWtlbHkgbm90IGEgZ3JlYXQgaWRlYSBpbiBwcmFjdGljZSxcbiAgICAgICAgICAgICAgICAvLyBhcyB0aGVvcmV0aWNhbGx5IHNvbWVvbmUgY291bGQgd2FudCB0byB1c2Ugb25lIGZvciBhIHN0YW5kYXJkIHRpbGVtYXAuIFdlIGFyZSBhc3N1bWluZyBmb3Igbm93XG4gICAgICAgICAgICAgICAgLy8gdGhhdCB3ZSBvbmx5IHdhbnQgdG8gdXNlIHRoZW0gZm9yIG9iamVjdCBsYXllcnNcbiAgICAgICAgICAgICAgICB0aWxlc2V0cy5wdXNoKG5ldyBUaWxlc2V0KHRpbGVzZXQpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGlsZXNldC50aWxlcy5mb3JFYWNoKHRpbGUgPT4gdGlsZS5pZCArPSB0aWxlc2V0LmZpcnN0Z2lkKTtcbiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uVGlsZXMucHVzaCguLi50aWxlc2V0LnRpbGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExvb3Agb3ZlciB0aGUgbGF5ZXJzIG9mIHRoZSB0aWxlbWFwIGFuZCBjcmVhdGUgdGlsZWRsYXllcnMgb3Igb2JqZWN0IGxheWVyc1xuICAgICAgICBmb3IobGV0IGxheWVyIG9mIHRpbGVtYXBEYXRhLmxheWVycyl7XG5cbiAgICAgICAgICAgIGxldCBzY2VuZUxheWVyO1xuICAgICAgICAgICAgbGV0IGlzUGFyYWxsYXhMYXllciA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGRlcHRoID0gMDtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYobGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgZm9yKGxldCBwcm9wIG9mIGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICBpZihwcm9wLm5hbWUgPT09IFwiUGFyYWxsYXhcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICBpc1BhcmFsbGF4TGF5ZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIkRlcHRoXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaXNQYXJhbGxheExheWVyKXtcbiAgICAgICAgICAgICAgICBzY2VuZUxheWVyID0gdGhpcy5zY2VuZS5hZGRQYXJhbGxheExheWVyKGxheWVyLm5hbWUsIG5ldyBWZWMyKDEsIDEpLCBkZXB0aCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNjZW5lTGF5ZXIgPSB0aGlzLnNjZW5lLmFkZExheWVyKGxheWVyLm5hbWUsIGRlcHRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYobGF5ZXIudHlwZSA9PT0gXCJ0aWxlbGF5ZXJcIil7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IHRpbGVtYXAgb2JqZWN0IGZvciB0aGUgbGF5ZXJcbiAgICAgICAgICAgICAgICBsZXQgdGlsZW1hcCA9IG5ldyBjb25zdHIodGlsZW1hcERhdGEsIGxheWVyLCB0aWxlc2V0cywgc2NhbGUpO1xuICAgICAgICAgICAgICAgIHRpbGVtYXAuaWQgPSB0aGlzLnNjZW5lLmdlbmVyYXRlSWQoKTtcbiAgICAgICAgICAgICAgICB0aWxlbWFwLnNldFNjZW5lKHRoaXMuc2NlbmUpO1xuICAgIFxuICAgICAgICAgICAgICAgIC8vIEFkZCB0aWxlbWFwIHRvIHNjZW5lXG4gICAgICAgICAgICAgICAgdGhpcy50aWxlbWFwcy5wdXNoKHRpbGVtYXApO1xuICAgIFxuICAgICAgICAgICAgICAgIHNjZW5lTGF5ZXIuYWRkTm9kZSh0aWxlbWFwKTtcbiAgICBcbiAgICAgICAgICAgICAgICAvLyBSZWdpc3RlciB0aWxlbWFwIHdpdGggcGh5c2ljcyBpZiBpdCdzIGNvbGxpZGFibGVcbiAgICAgICAgICAgICAgICBpZih0aWxlbWFwLmlzQ29sbGlkYWJsZSl7XG4gICAgICAgICAgICAgICAgICAgIHRpbGVtYXAuYWRkUGh5c2ljcygpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpdGVtIG9mIGxheWVyLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGl0ZW0ubmFtZSA9PT0gXCJHcm91cFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcC5zZXRHcm91cChpdGVtLnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgbGV0IGlzTmF2bWVzaFBvaW50cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGxldCBuYXZtZXNoTmFtZTtcbiAgICAgICAgICAgICAgICBsZXQgZWRnZXM7XG4gICAgICAgICAgICAgICAgaWYobGF5ZXIucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgcHJvcCBvZiBsYXllci5wcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHByb3AubmFtZSA9PT0gXCJOYXZtZXNoUG9pbnRzXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTmF2bWVzaFBvaW50cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIm5hbWVcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2bWVzaE5hbWUgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJlZGdlc1wiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGdlcyA9IHByb3AudmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBpZihpc05hdm1lc2hQb2ludHMpe1xuICAgICAgICAgICAgICAgICAgICBsZXQgZyA9IG5ldyBQb3NpdGlvbkdyYXBoKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBvYmogb2YgbGF5ZXIub2JqZWN0cyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBnLmFkZFBvc2l0aW9uZWROb2RlKG5ldyBWZWMyKG9iai54LCBvYmoueSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBlZGdlIG9mIGVkZ2VzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIGcuYWRkRWRnZShlZGdlLmZyb20sIGVkZ2UudG8pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2VuZS5nZXROYXZpZ2F0aW9uTWFuYWdlcigpLmFkZE5hdmlnYWJsZUVudGl0eShuYXZtZXNoTmFtZSwgbmV3IE5hdm1lc2goZykpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIExheWVyIGlzIGFuIG9iamVjdCBsYXllciwgc28gYWRkIGVhY2ggb2JqZWN0IGFzIGEgc3ByaXRlIHRvIGEgbmV3IGxheWVyXG4gICAgICAgICAgICAgICAgZm9yKGxldCBvYmogb2YgbGF5ZXIub2JqZWN0cyl7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIG9iaiBpcyBjb2xsaWRhYmxlXG4gICAgICAgICAgICAgICAgICAgIGxldCBoYXNQaHlzaWNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGxldCBpc0NvbGxpZGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGlzVHJpZ2dlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBsZXQgb25FbnRlciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvbkV4aXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBsZXQgdHJpZ2dlckdyb3VwID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGdyb3VwID0gXCJcIjtcblxuICAgICAgICAgICAgICAgICAgICBpZihvYmoucHJvcGVydGllcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHByb3Agb2Ygb2JqLnByb3BlcnRpZXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHByb3AubmFtZSA9PT0gXCJIYXNQaHlzaWNzXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNQaHlzaWNzID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHJvcC5uYW1lID09PSBcIkNvbGxpZGFibGVcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQ29sbGlkYWJsZSA9IHByb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHByb3AubmFtZSA9PT0gXCJHcm91cFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiSXNUcmlnZ2VyXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1RyaWdnZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlckdyb3VwXCIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyR3JvdXAgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlck9uRW50ZXJcIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRW50ZXIgPSBwcm9wLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihwcm9wLm5hbWUgPT09IFwiVHJpZ2dlck9uRXhpdFwiKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25FeGl0ID0gcHJvcC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBsZXQgc3ByaXRlOiBTcHJpdGU7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgb2JqIGlzIGEgdGlsZSBmcm9tIGEgdGlsZXNldFxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHRpbGVzZXQgb2YgdGlsZXNldHMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGlsZXNldC5oYXNUaWxlKG9iai5naWQpKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgb2JqZWN0IGlzIGEgdGlsZSBmcm9tIHRoaXMgc2V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltYWdlS2V5ID0gdGlsZXNldC5nZXRJbWFnZUtleSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXQgPSB0aWxlc2V0LmdldEltYWdlT2Zmc2V0Rm9yVGlsZShvYmouZ2lkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUgPSB0aGlzLnNjZW5lLmFkZC5zcHJpdGUoaW1hZ2VLZXksIGxheWVyLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzaXplID0gdGlsZXNldC5nZXRUaWxlU2l6ZSgpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnBvc2l0aW9uLnNldCgob2JqLnggKyBzaXplLngvMikqc2NhbGUueCwgKG9iai55IC0gc2l6ZS55LzIpKnNjYWxlLnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zZXRJbWFnZU9mZnNldChvZmZzZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5zaXplLmNvcHkoc2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNjYWxlLnNldChzY2FsZS54LCBzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdCBpbiBhIHRpbGVzZXQsIG11c3QgY29ycmVzcG9uZCB0byBhIGNvbGxlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgaWYoIXNwcml0ZSl7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IobGV0IHRpbGUgb2YgY29sbGVjdGlvblRpbGVzKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihvYmouZ2lkID09PSB0aWxlLmlkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltYWdlS2V5ID0gdGlsZS5pbWFnZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlID0gdGhpcy5zY2VuZS5hZGQuc3ByaXRlKGltYWdlS2V5LCBsYXllci5uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnBvc2l0aW9uLnNldCgob2JqLnggKyB0aWxlLmltYWdld2lkdGgvMikqc2NhbGUueCwgKG9iai55IC0gdGlsZS5pbWFnZWhlaWdodC8yKSpzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNjYWxlLnNldChzY2FsZS54LCBzY2FsZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBOb3cgd2UgaGF2ZSBzcHJpdGUuIEFzc29jaWF0ZSBpdCB3aXRoIG91ciBwaHlzaWNzIG9iamVjdCBpZiB0aGVyZSBpcyBvbmVcbiAgICAgICAgICAgICAgICAgICAgaWYoaGFzUGh5c2ljcyl7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIHRoZSBzcHJpdGUgYSBzdGF0aWMgcGh5c2ljcyBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwcml0ZS5hZGRQaHlzaWNzKHNwcml0ZS5ib3VuZGFyeS5jbG9uZSgpLCBWZWMyLlpFUk8sIGlzQ29sbGlkYWJsZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzcHJpdGUuc2V0R3JvdXAoZ3JvdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaXNUcmlnZ2VyICYmIHRyaWdnZXJHcm91cCAhPT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaXRlLnNldFRyaWdnZXIodHJpZ2dlckdyb3VwLCBvbkVudGVyLCBvbkV4aXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJldHVybiB2YWx1ZVxuICAgICAgICAgICAgc2NlbmVMYXllcnMucHVzaChzY2VuZUxheWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzY2VuZUxheWVycztcblx0fVxufSIsImltcG9ydCBTY2VuZSBmcm9tIFwiLi9TY2VuZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5cblxuLyoqXG4gKiBBIGxheWVyIGluIHRoZSBzY2VuZS4gTGF5ZXJzIGFyZSB1c2VkIGZvciBzb3J0aW5nIEByZWZlcmVuY2VbR2FtZU5vZGVdcyBieSBkZXB0aC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGF5ZXIge1xuICAgIC8qKiBUaGUgc2NlbmUgdGhpcyBsYXllciBiZWxvbmdzIHRvICovXG4gICAgcHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblxuICAgIC8qKiBUaGUgbmFtZSBvZiB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIG5hbWU6IHN0cmluZztcblxuICAgIC8qKiBXaGV0aGVyIHRoaXMgbGF5ZXIgaXMgcGF1c2VkIG9yIG5vdCAqL1xuICAgIHByb3RlY3RlZCBwYXVzZWQ6IGJvb2xlYW47XG5cbiAgICAvKiogV2hldGhlciB0aGlzIGxheWVyIGlzIGhpZGRlbiBmcm9tIGJlaW5nIHJlbmRlcmVkIG9yIG5vdCAqL1xuICAgIHByb3RlY3RlZCBoaWRkZW46IGJvb2xlYW47XG5cbiAgICAvKiogVGhlIGdsb2JhbCBhbHBoYSBsZXZlbCBvZiB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIGFscGhhOiBudW1iZXI7XG5cbiAgICAvKiogQW4gYXJyYXkgb2YgdGhlIEdhbWVOb2RlcyB0aGF0IGJlbG9uZyB0byB0aGlzIGxheWVyICovXG4gICAgcHJvdGVjdGVkIGl0ZW1zOiBBcnJheTxHYW1lTm9kZT47XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyBsYXllciBzaG91bGQgYmUgeXNvcnRlZCAqL1xuICAgIHByb3RlY3RlZCB5U29ydDogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgZGVwdGggb2YgdGhpcyBsYXllciBjb21wYXJlZCB0byBvdGhlciBsYXllcnMgKi9cbiAgICBwcm90ZWN0ZWQgZGVwdGg6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgbGF5ZXIuIFRvIGRvIHRoaXMgaW4gYSBnYW1lLCB1c2UgdGhlIGFkZExheWVyKCkgbWV0aG9kIGluIEByZWZyZW5jZVtTY2VuZV1cbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRvIGFkZCB0aGUgbGF5ZXIgdG9cbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIG5hbWU6IHN0cmluZyl7XG4gICAgICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5oaWRkZW4gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hbHBoYSA9IDE7XG4gICAgICAgIHRoaXMuaXRlbXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy55U29ydCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlcHRoID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgdGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICovXG4gICAgZ2V0TmFtZSgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhdXNlcy9VbnBhdXNlcyB0aGUgbGF5ZXIuIEFmZmVjdHMgYWxsIGVsZW1lbnRzIGluIHRoaXMgbGF5ZXJcbiAgICAgKiBAcGFyYW0gcGF1c2VWYWx1ZSBUcnVlIGlmIHRoZSBsYXllciBzaG91bGQgYmUgcGF1c2VkLCBmYWxzZSBpZiBub3RcbiAgICAgKi9cbiAgICBzZXRQYXVzZWQocGF1c2VWYWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHBhdXNlVmFsdWU7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIGxheWVyIGlzIHBhdXNlZFxuICAgICAqL1xuICAgIGlzUGF1c2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXVzZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgb3BhY2l0eSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcGFyYW0gYWxwaGEgVGhlIG5ldyBvcGFjaXR5IHZhbHVlIGluIHRoZSByYW5nZSBbMCwgMV1cbiAgICAgKi9cbiAgICBzZXRBbHBoYShhbHBoYTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWxwaGEgPSBNYXRoVXRpbHMuY2xhbXAoYWxwaGEsIDAsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIG9wYWNpdHkgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG9wYWNpdHlcbiAgICAgKi9cbiAgICBnZXRBbHBoYSgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hbHBoYTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBsYXllcidzIGhpZGRlbiB2YWx1ZS4gSWYgaGlkZGVuLCBhIGxheWVyIHdpbGwgbm90IGJlIHJlbmRlcmVkLCBidXQgd2lsbCBzdGlsbCB1cGRhdGVcbiAgICAgKiBAcGFyYW0gaGlkZGVuIFRoZSBoaWRkZW4gdmFsdWUgb2YgdGhlIGxheWVyXG4gICAgICovXG4gICAgc2V0SGlkZGVuKGhpZGRlbjogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmhpZGRlbiA9IGhpZGRlbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBoaWRlZW4gdmFsdWUgb2YgdGhlIGx5YWVyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgc2NlbmUgaXMgaGlkZGVuLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBpc0hpZGRlbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGlkZGVuO1xuICAgIH1cblxuICAgIC8qKiBQYXVzZXMgdGhpcyBzY2VuZSBhbmQgaGlkZXMgaXQgKi9cbiAgICBkaXNhYmxlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnBhdXNlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuaGlkZGVuID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKiogVW5wYXVzZXMgdGhpcyBsYXllciBhbmQgbWFrZXMgaXQgdmlzaWJsZSAqL1xuICAgIGVuYWJsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5oaWRkZW4gPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHdoZXRoZXIgb3Igbm90IHRoZSBzY2VuZSB3aWxsIHlTb3J0IGF1dG9tYXRpY2FsbHkuXG4gICAgICogeVNvcnRpbmcgbWVhbnMgdGhhdCBDYW52YXNOb2RlcyBvbiB0aGlzIGxheWVyIHdpbGwgaGF2ZSB0aGVpciBkZXB0aCBzb3J0ZWQgZGVwZW5kaW5nIG9uIHRoZWlyIHktdmFsdWUuXG4gICAgICogVGhpcyBtZWFucyB0aGF0IGlmIGFuIG9iamVjdCBpcyBcImhpZ2hlclwiIGluIHRoZSBzY2VuZSwgaXQgd2lsbCBzb3J0IGJlaGluZCBvYmplY3RzIHRoYXQgYXJlIFwibG93ZXJcIi5cbiAgICAgKiBUaGlzIGlzIHVzZWZ1bCBmb3IgMy80IHZpZXcgZ2FtZXMsIG9yIHNpbWlsYXIgc2l0dWF0aW9ucywgd2hlcmUgeW91IHNvbWV0aW1lcyB3YW50IHRvIGJlIGluIGZyb250IG9mIG9iamVjdHMsXG4gICAgICogYW5kIG90aGVyIHRpbWVzIHdhbnQgdG8gYmUgYmVoaW5kIHRoZSBzYW1lIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHlTb3J0IFRydWUgaWYgeVNvcnRpbmcgc2hvdWxkIGJlIGFjdGl2ZSwgZmFsc2UgaWYgbm90XG4gICAgICovXG4gICAgc2V0WVNvcnQoeVNvcnQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy55U29ydCA9IHlTb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHlTb3J0IHN0YXR1cyBvZiB0aGUgc2NlbmVcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHlTb3J0aW5nIGlzIG9jY3VycmluZywgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgZ2V0WVNvcnQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnlTb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIGRlcHRoIG9mIHRoZSBsYXllciBjb21wYXJlZCB0byBvdGhlciBsYXllcnMuIEEgbGFyZ2VyIG51bWJlciBtZWFucyB0aGUgbGF5ZXIgd2lsbCBiZSBjbG9zZXIgdG8gdGhlIHNjcmVlbi5cbiAgICAgKiBAcGFyYW0gZGVwdGggVGhlIGRlcHRoIG9mIHRoZSBsYXllci5cbiAgICAgKi9cbiAgICBzZXREZXB0aChkZXB0aDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGVwdGggPSBkZXB0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGRlcHRoIG9mIHRoZSBsYXllci5cbiAgICAgKiBAcmV0dXJucyBUaGUgZGVwdGhcbiAgICAgKi9cbiAgICBnZXREZXB0aCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5kZXB0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbm9kZSB0byB0aGlzIGxheWVyXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gYWRkIHRvIHRoaXMgbGF5ZXIuXG4gICAgICovXG4gICAgYWRkTm9kZShub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuICAgICAgICB0aGlzLml0ZW1zLnB1c2gobm9kZSk7XG4gICAgICAgIG5vZGUuc2V0TGF5ZXIodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIG5vZGUgZnJvbSB0aGlzIGxheWVyXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgbm9kZSB3YXMgcmVtb3ZlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgcmVtb3ZlTm9kZShub2RlOiBHYW1lTm9kZSk6IHZvaWQge1xuICAgICAgICAvLyBGaW5kIGFuZCByZW1vdmUgdGhlIG5vZGVcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5pdGVtcy5pbmRleE9mKG5vZGUpO1xuXG4gICAgICAgIGlmKGluZGV4ICE9PSAtMSl7XG4gICAgICAgICAgICB0aGlzLml0ZW1zLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICBub2RlLnNldExheWVyKHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyZWl2ZXMgYWxsIEdhbWVOb2RlcyBmcm9tIHRoaXMgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBhbiBBcnJheSB0aGF0IGNvbnRhaW5zIGFsbCBvZiB0aGUgR2FtZU5vZGVzIGluIHRoaXMgbGF5ZXIuXG4gICAgICovXG4gICAgZ2V0SXRlbXMoKTogQXJyYXk8R2FtZU5vZGU+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXM7XG4gICAgfVxufSIsImltcG9ydCBMYXllciBmcm9tIFwiLi4vTGF5ZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuXG4vKipcbiAqIEFuIGV4dGVuc2lvbiBvZiBhIExheWVyIHRoYXQgaGFzIGEgcGFyYWxsYXggdmFsdWUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBhcmFsbGF4TGF5ZXIgZXh0ZW5kcyBMYXllciB7XG5cdC8qKiBUaGUgdmFsdWUgb2YgdGhlIHBhcmFsbGF4IG9mIHRoZSBMYXllciAqL1xuXHRwYXJhbGxheDogVmVjMjtcblx0XG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IFBhcmFsbGF4TGF5ZXIuXG5cdCAqIFVzZSBhZGRQYXJhbGxheExheWVyKCkgaW4gQHJlZmVyZW5jZVtTY2VuZV0gdG8gYWRkIGEgbGF5ZXIgb2YgdGhpcyB0eXBlIHRvIHlvdXIgZ2FtZS5cblx0ICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0byBhZGQgdGhpcyBQYXJhbGxheExheWVyIHRvXG5cdCAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBQYXJhbGxheExheWVyXG5cdCAqIEBwYXJhbSBwYXJhbGxheCBUaGUgcGFyYWxsYXggbGV2ZWxcblx0ICovXG5cdGNvbnN0cnVjdG9yKHNjZW5lOiBTY2VuZSwgbmFtZTogc3RyaW5nLCBwYXJhbGxheDogVmVjMil7XG5cdFx0c3VwZXIoc2NlbmUsIG5hbWUpO1xuXHRcdHRoaXMucGFyYWxsYXggPSBwYXJhbGxheDtcblx0fVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi9TY2VuZVwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4vUGFyYWxsYXhMYXllclwiO1xuXG4vKipcbiAqIEEgTGF5ZXIgc3RyaWN0bHkgdG8gYmUgdXNlZCBmb3IgbWFuYWdpbmcgVUlFbGVtZW50cy5cbiAqIFRoaXMgaXMgaW50ZW5kZWQgdG8gYmUgYSBMYXllciB0aGF0IGFsd2F5cyBzdGF5cyBpbiB0aGUgc2FtZSBwbGFjZSxcbiAqIGFuZCB0aHVzIHJlbmRlcnMgdGhpbmdzIGxpa2UgYSBIVUQgb3IgYW4gaW52ZW50b3J5IHdpdGhvdXQgdGFraW5nIGludG8gY29uc2lkZXJhdGlvbiB0aGUgXFxyZWZlcmVuY2VbVmlld3BvcnRdIHNjcm9sbC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVUlMYXllciBleHRlbmRzIFBhcmFsbGF4TGF5ZXIge1xuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBVSUxheWVyLlxuXHQgKiBVc2UgYWRkVUlMYXllcigpIGluIEByZWZlcmVuY2VbU2NlbmVdIHRvIGFkZCBhIGxheWVyIG9mIHRoaXMgdHlwZSB0byB5b3VyIGdhbWUuXG5cdCAqIEBwYXJhbSBzY2VuZSBUaGUgU2NlbmUgdG8gYWRkIHRoaXMgVUlMYXllciB0b1xuXHQgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgVUlMYXllclxuXHQgKi9cblx0Y29uc3RydWN0b3Ioc2NlbmU6IFNjZW5lLCBuYW1lOiBzdHJpbmcpe1xuXHRcdHN1cGVyKHNjZW5lLCBuYW1lLCBWZWMyLlpFUk8pO1xuXHR9XG59IiwiaW1wb3J0IExheWVyIGZyb20gXCIuL0xheWVyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFNjZW5lR3JhcGggZnJvbSBcIi4uL1NjZW5lR3JhcGgvU2NlbmVHcmFwaFwiO1xuaW1wb3J0IFBoeXNpY3NNYW5hZ2VyIGZyb20gXCIuLi9QaHlzaWNzL1BoeXNpY3NNYW5hZ2VyXCI7XG5pbXBvcnQgQmFzaWNQaHlzaWNzTWFuYWdlciBmcm9tIFwiLi4vUGh5c2ljcy9CYXNpY1BoeXNpY3NNYW5hZ2VyXCI7XG5pbXBvcnQgU2NlbmVHcmFwaEFycmF5IGZyb20gXCIuLi9TY2VuZUdyYXBoL1NjZW5lR3JhcGhBcnJheVwiO1xuaW1wb3J0IEZhY3RvcnlNYW5hZ2VyIGZyb20gXCIuL0ZhY3Rvcmllcy9GYWN0b3J5TWFuYWdlclwiO1xuaW1wb3J0IFRpbGVtYXAgZnJvbSBcIi4uL05vZGVzL1RpbGVtYXBcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCBHYW1lIGZyb20gXCIuLi9Mb29wL0dhbWVcIjtcbmltcG9ydCBTY2VuZU1hbmFnZXIgZnJvbSBcIi4vU2NlbmVNYW5hZ2VyXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uL0V2ZW50cy9SZWNlaXZlclwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgVXBkYXRlYWJsZSBmcm9tIFwiLi4vRGF0YVR5cGVzL0ludGVyZmFjZXMvVXBkYXRlYWJsZVwiO1xuaW1wb3J0IE5hdmlnYXRpb25NYW5hZ2VyIGZyb20gXCIuLi9QYXRoZmluZGluZy9OYXZpZ2F0aW9uTWFuYWdlclwiO1xuaW1wb3J0IEFJTWFuYWdlciBmcm9tIFwiLi4vQUkvQUlNYW5hZ2VyXCI7XG5pbXBvcnQgTWFwIGZyb20gXCIuLi9EYXRhVHlwZXMvTWFwXCI7XG5pbXBvcnQgUGFyYWxsYXhMYXllciBmcm9tIFwiLi9MYXllcnMvUGFyYWxsYXhMYXllclwiO1xuaW1wb3J0IFVJTGF5ZXIgZnJvbSBcIi4vTGF5ZXJzL1VJTGF5ZXJcIjtcbmltcG9ydCBDYW52YXNOb2RlIGZyb20gXCIuLi9Ob2Rlcy9DYW52YXNOb2RlXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU2NlbmVPcHRpb25zIGZyb20gXCIuL1NjZW5lT3B0aW9uc1wiO1xuaW1wb3J0IFJlbmRlcmluZ01hbmFnZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9SZW5kZXJpbmdNYW5hZ2VyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgVGltZXJNYW5hZ2VyIGZyb20gXCIuLi9UaW1pbmcvVGltZXJNYW5hZ2VyXCI7XG5pbXBvcnQgVHdlZW5NYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvQW5pbWF0aW9ucy9Ud2Vlbk1hbmFnZXJcIjtcbmltcG9ydCBQYXJ0aWNsZVN5c3RlbU1hbmFnZXIgZnJvbSBcIi4uL1JlbmRlcmluZy9BbmltYXRpb25zL1BhcnRpY2xlU3lzdGVtTWFuYWdlclwiO1xuXG4vKipcbiAqIFNjZW5lcyBhcmUgdGhlIG1haW4gY29udGFpbmVyIGluIHRoZSBnYW1lIGVuZ2luZS5cbiAqIFlvdXIgbWFpbiBzY2VuZSBpcyB0aGUgY3VycmVudCBsZXZlbCBvciBtZW51IG9mIHRoZSBnYW1lLCBhbmQgd2lsbCBjb250YWluIGFsbCBvZiB0aGUgR2FtZU5vZGVzIG5lZWRlZC5cbiAqIFNjZW5lcyBwcm92aWRlIGFuIGVhc3kgd2F5IHRvIGxvYWQgYXNzZXRzLCBhZGQgYXNzZXRzIHRvIHRoZSBnYW1lIHdvcmxkLCBhbmQgdW5sb2FkIGFzc2V0cyxcbiAqIGFuZCBoYXZlIGxpZmVjeWNsZSBtZXRob2RzIGV4cG9zZWQgZm9yIHRoZXNlIGZ1bmN0aW9ucy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NlbmUgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcbiAgICAvKiogVGhlIHNpemUgb2YgdGhlIGdhbWUgd29ybGQuICovXG4gICAgcHJvdGVjdGVkIHdvcmxkU2l6ZTogVmVjMjtcblxuICAgIC8qKiBUaGUgdmlld3BvcnQuICovXG4gICAgcHJvdGVjdGVkIHZpZXdwb3J0OiBWaWV3cG9ydDtcblxuICAgIC8qKiBBIGZsYWcgdGhhdCByZXByZXNlbnRzIHdoZXRoZXIgdGhpcyBzY2VuZSBpcyBydW5uaW5nIG9yIG5vdC4gKi9cbiAgICBwcm90ZWN0ZWQgcnVubmluZzogYm9vbGVhbjtcblxuICAgIC8qKiBUaGUgbWFuYWdlciBvZiB0aGlzIHNjZW5lLiAqL1xuICAgIHByb3RlY3RlZCBzY2VuZU1hbmFnZXI6IFNjZW5lTWFuYWdlcjtcblxuICAgIC8qKiBUaGUgcmVjZWl2ZXIgZm9yIHRoaXMgc2NlbmUuICovXG4gICAgcHJvdGVjdGVkIHJlY2VpdmVyOiBSZWNlaXZlcjtcblxuICAgIC8qKiBUaGUgZW1pdHRlciBmb3IgdGhpcyBzY2VuZS4gKi9cbiAgICBwcm90ZWN0ZWQgZW1pdHRlcjogRW1pdHRlcjtcblxuICAgIC8qKiBUaGlzIGxpc3Qgb2YgdGlsZW1hcHMgaW4gdGhpcyBzY2VuZS4gKi9cbiAgICBwcm90ZWN0ZWQgdGlsZW1hcHM6IEFycmF5PFRpbGVtYXA+O1xuXG4gICAgLyoqIEEgbWFwIGZyb20gbGF5ZXIgbmFtZXMgdG8gdGhlIGxheWVycyB0aGVtc2VsdmVzICovXG4gICAgcHJvdGVjdGVkIGxheWVyczogTWFwPExheWVyPjtcblxuICAgIC8qKiBBIG1hcCBmcm9tIHBhcmFsbGF4IGxheWVyIG5hbWVzIHRvIHRoZSBwYXJhbGxheCBsYXllcnMgdGhlbXNlbHZlcyAqL1xuICAgIHByb3RlY3RlZCBwYXJhbGxheExheWVyczogTWFwPFBhcmFsbGF4TGF5ZXI+O1xuXG4gICAgLyoqIEEgbWFwIGZyb20gdWlMYXllciBuYW1lcyB0byB0aGUgdWlMYXllcnMgdGhlbXNlbHZlcyAqL1xuICAgIHByb3RlY3RlZCB1aUxheWVyczogTWFwPFVJTGF5ZXI+O1xuXG4gICAgLyoqIFRoZSBzY2VuZSBncmFwaCBvZiB0aGUgU2NlbmUqL1xuICAgIHByb3RlY3RlZCBzY2VuZUdyYXBoOiBTY2VuZUdyYXBoO1xuXG4gICAgLyoqIFRoZSBwaHlzaWNzIG1hbmFnZXIgb2YgdGhlIFNjZW5lICovXG4gICAgcHJvdGVjdGVkIHBoeXNpY3NNYW5hZ2VyOiBQaHlzaWNzTWFuYWdlcjtcbiAgICBcbiAgICAvKiogVGhlIG5hdmlnYXRpb24gbWFuYWdlciBvZiB0aGUgU2NlbmUgKi9cbiAgICBwcm90ZWN0ZWQgbmF2TWFuYWdlcjogTmF2aWdhdGlvbk1hbmFnZXI7XG5cbiAgICAvKiogVGhlIEFJIG1hbmFnZXIgb2YgdGhlIFNjZW5lICovXG4gICAgcHJvdGVjdGVkIGFpTWFuYWdlcjogQUlNYW5hZ2VyO1xuXG4gICAgLyoqIFRoZSByZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBzY2VuZSAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyO1xuXG4gICAgLyoqIEFuIGludGVyZmFjZSB0aGF0IGFsbG93cyB0aGUgYWRkaW5nIG9mIGRpZmZlcmVudCBub2RlcyB0byB0aGUgc2NlbmUgKi9cbiAgICBwdWJsaWMgYWRkOiBGYWN0b3J5TWFuYWdlcjtcblxuICAgIC8qKiBBbiBpbnRlcmZhY2UgdGhhdCBhbGxvd3MgdGhlIGxvYWRpbmcgb2YgZGlmZmVyZW50IGZpbGVzIGZvciB1c2UgaW4gdGhlIHNjZW5lLiBBbiBhbGlhcyBmb3IgcmVzb3VyY2VNYW5hZ2VyICovXG4gICAgcHVibGljIGxvYWQ6IFJlc291cmNlTWFuYWdlcjtcblxuICAgIC8qKiBBbiBpbnRlcmZhY2UgdGhhdCBhbGxvd3MgdGhlIGxvYWRpbmcgYW5kIHVubG9hZGluZyBvZiBkaWZmZXJlbnQgZmlsZXMgZm9yIHVzZSBpbiB0aGUgc2NlbmUgKi9cbiAgICBwdWJsaWMgcmVzb3VyY2VNYW5hZ2VyOiBSZXNvdXJjZU1hbmFnZXI7XG5cbiAgICAvKiogVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhpcyBzY2VuZSAqL1xuICAgIHB1YmxpYyBzY2VuZU9wdGlvbnM6IFNjZW5lT3B0aW9ucztcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgU2NlbmUuIFRvIGFkZCBhIG5ldyBTY2VuZSBpbiB5b3VyIGdhbWUsIHVzZSBjaGFuZ2VUb1NjZW5lKCkgaW4gQHJlZmVyZW5jZVtTY2VuZU1hbmFnZXJdXG4gICAgICogQHBhcmFtIHZpZXdwb3J0IFRoZSB2aWV3cG9ydCBvZiB0aGUgZ2FtZVxuICAgICAqIEBwYXJhbSBzY2VuZU1hbmFnZXIgVGhlIFNjZW5lTWFuYWdlciB0aGF0IG93bnMgdGhpcyBTY2VuZVxuICAgICAqIEBwYXJhbSByZW5kZXJpbmdNYW5hZ2VyIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIHRoYXQgd2lsbCBoYW5kbGUgdGhpcyBTY2VuZSdzIHJlbmRlcmluZ1xuICAgICAqIEBwYXJhbSBnYW1lIFRoZSBpbnN0YW5jZSBvZiB0aGUgR2FtZVxuICAgICAqIEBwYXJhbSBvcHRpb25zIFRoZSBvcHRpb25zIGZvciBTY2VuZSBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZXdwb3J0OiBWaWV3cG9ydCwgc2NlbmVNYW5hZ2VyOiBTY2VuZU1hbmFnZXIsIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXIsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pe1xuICAgICAgICB0aGlzLnNjZW5lT3B0aW9ucyA9IFNjZW5lT3B0aW9ucy5wYXJzZShvcHRpb25zID09PSB1bmRlZmluZWQgPyB7fSA6IG9wdGlvbnMpO1xuXG4gICAgICAgIHRoaXMud29ybGRTaXplID0gbmV3IFZlYzIoNTAwLCA1MDApO1xuICAgICAgICB0aGlzLnZpZXdwb3J0ID0gdmlld3BvcnQ7XG4gICAgICAgIHRoaXMudmlld3BvcnQuc2V0Qm91bmRzKDAsIDAsIDI1NjAsIDEyODApO1xuICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIgPSBzY2VuZU1hbmFnZXI7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIgPSBuZXcgUmVjZWl2ZXIoKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IEVtaXR0ZXIoKTtcblxuICAgICAgICB0aGlzLnRpbGVtYXBzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMuc2NlbmVHcmFwaCA9IG5ldyBTY2VuZUdyYXBoQXJyYXkodGhpcy52aWV3cG9ydCwgdGhpcyk7XG5cbiAgICAgICAgdGhpcy5sYXllcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMudWlMYXllcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMucGFyYWxsYXhMYXllcnMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5waHlzaWNzTWFuYWdlciA9IG5ldyBCYXNpY1BoeXNpY3NNYW5hZ2VyKHRoaXMuc2NlbmVPcHRpb25zLnBoeXNpY3MpO1xuICAgICAgICB0aGlzLm5hdk1hbmFnZXIgPSBuZXcgTmF2aWdhdGlvbk1hbmFnZXIoKTtcbiAgICAgICAgdGhpcy5haU1hbmFnZXIgPSBuZXcgQUlNYW5hZ2VyKCk7XG4gICAgICAgIHRoaXMucmVuZGVyaW5nTWFuYWdlciA9IHJlbmRlcmluZ01hbmFnZXI7XG5cbiAgICAgICAgdGhpcy5hZGQgPSBuZXcgRmFjdG9yeU1hbmFnZXIodGhpcywgdGhpcy50aWxlbWFwcyk7XG5cbiAgICAgICAgdGhpcy5sb2FkID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKClcbiAgICAgICAgdGhpcy5yZXNvdXJjZU1hbmFnZXIgPSB0aGlzLmxvYWQ7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0aW1lciBtYW5hZ2VyIGFuZCBjbGVhciBhbnkgZXhpc3RpbmcgdGltZXJzXG4gICAgICAgIFRpbWVyTWFuYWdlci5nZXRJbnN0YW5jZSgpLmNsZWFyVGltZXJzKCk7XG4gICAgfVxuXG4gICAgLyoqIEEgbGlmZWN5Y2xlIG1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIGltbWVkaWF0ZWx5IGFmdGVyIGEgbmV3IHNjZW5lIGlzIGNyZWF0ZWQsIGJlZm9yZSBhbnl0aGluZyBlbHNlLiAqL1xuICAgIGluaXRTY2VuZShpbml0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG4gICAgLyoqIEEgbGlmZWN5Y2xlIG1ldGhvZCB0aGF0IGdldHMgY2FsbGVkIHdoZW4gYSBuZXcgc2NlbmUgaXMgY3JlYXRlZC4gTG9hZCBhbGwgZmlsZXMgeW91IHdpc2ggdG8gYWNjZXNzIGluIHRoZSBzY2VuZSBoZXJlLiAqL1xuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHt9XG5cbiAgICAvKiogQSBsaWZlY3ljbGUgbWV0aG9kIGNhbGxlZCBzdHJpY3RseSBhZnRlciBsb2FkU2NlbmUoKS4gQ3JlYXRlIGFueSBnYW1lIG9iamVjdHMgeW91IHdpc2ggdG8gdXNlIGluIHRoZSBzY2VuZSBoZXJlLiAqL1xuICAgIHN0YXJ0U2NlbmUoKTogdm9pZCB7fVxuXG4gICAgLyoqXG4gICAgICogQSBsaWZlY3ljbGUgbWV0aG9kIGNhbGxlZCBldmVyeSBmcmFtZSBvZiB0aGUgZ2FtZS4gVGhpcyBpcyB3aGVyZSB5b3UgY2FuIGR5bmFtaWNhbGx5IGRvIHRoaW5ncyBsaWtlIGFkZCBpbiBuZXcgZW5lbWllc1xuICAgICAqIEBwYXJhbSBkZWx0YSBUaGUgdGltZSB0aGlzIGZyYW1lIHJlcHJlc2VudHNcbiAgICAgKi9cbiAgICB1cGRhdGVTY2VuZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge31cblxuICAgIC8qKiBBIGxpZmVjeWNsZSBtZXRob2QgdGhhdCBnZXRzIGNhbGxlZCBvbiBzY2VuZSBkZXN0cnVjdGlvbi4gU3BlY2lmeSB3aGljaCBmaWxlcyB5b3Ugbm8gbG9uZ2VyIG5lZWQgZm9yIGdhcmJhZ2UgY29sbGVjdGlvbi4gKi9cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHt9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cGRhdGVTY2VuZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIERvIHRpbWUgdXBkYXRlc1xuICAgICAgICBUaW1lck1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBEbyBhbGwgQUkgdXBkYXRlc1xuICAgICAgICB0aGlzLmFpTWFuYWdlci51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIHBoeXNpY3Mgb2JqZWN0c1xuICAgICAgICB0aGlzLnBoeXNpY3NNYW5hZ2VyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBhbGwgY2FudmFzIG9iamVjdHNcbiAgICAgICAgdGhpcy5zY2VuZUdyYXBoLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBhbGwgdGlsZW1hcHNcbiAgICAgICAgdGhpcy50aWxlbWFwcy5mb3JFYWNoKHRpbGVtYXAgPT4ge1xuICAgICAgICAgICAgaWYoIXRpbGVtYXAuZ2V0TGF5ZXIoKS5pc1BhdXNlZCgpKXtcbiAgICAgICAgICAgICAgICB0aWxlbWFwLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICAgICAgfSBcbiAgICAgICAgfSk7XG4gICAgICAgIFxuICAgICAgICAvLyBVcGRhdGUgYWxsIHR3ZWVuc1xuICAgICAgICBUd2Vlbk1hbmFnZXIuZ2V0SW5zdGFuY2UoKS51cGRhdGUoZGVsdGFUKTtcblxuICAgICAgICAvLyBVcGRhdGUgYWxsIHBhcnRpY2xlIHN5c3RlbXNcbiAgICAgICAgUGFydGljbGVTeXN0ZW1NYW5hZ2VyLmdldEluc3RhbmNlKCkudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHZpZXdwb3J0XG4gICAgICAgIHRoaXMudmlld3BvcnQudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29sbGVjdHMgcmVuZGVyYWJsZSBzZXRzIGFuZCBjb29yZGluYXRlcyB3aXRoIHRoZSBSZW5kZXJpbmdNYW5hZ2VyIHRvIGRyYXcgdGhlIFNjZW5lXG4gICAgICovXG4gICAgcmVuZGVyKCk6IHZvaWQge1xuICAgICAgICAvLyBHZXQgdGhlIHZpc2libGUgc2V0IG9mIG5vZGVzXG4gICAgICAgIGxldCB2aXNpYmxlU2V0ID0gdGhpcy5zY2VuZUdyYXBoLmdldFZpc2libGVTZXQoKTtcblxuICAgICAgICAvLyBBZGQgcGFyYWxsYXggbGF5ZXIgaXRlbXMgdG8gdGhlIHZpc2libGUgc2V0ICh3ZSdyZSByZW5kZXJpbmcgdGhlbSBhbGwgZm9yIG5vdylcbiAgICAgICAgdGhpcy5wYXJhbGxheExheWVycy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICBsZXQgcExheWVyID0gdGhpcy5wYXJhbGxheExheWVycy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGZvcihsZXQgbm9kZSBvZiBwTGF5ZXIuZ2V0SXRlbXMoKSl7XG4gICAgICAgICAgICAgICAgaWYobm9kZSBpbnN0YW5jZW9mIENhbnZhc05vZGUpe1xuICAgICAgICAgICAgICAgICAgICB2aXNpYmxlU2V0LnB1c2gobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTZW5kIHRoZSB2aXNpYmxlIHNldCwgdGlsZW1hcHMsIGFuZCB1aUxheWVycyB0byB0aGUgcmVuZGVyZXJcbiAgICAgICAgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyLnJlbmRlcih2aXNpYmxlU2V0LCB0aGlzLnRpbGVtYXBzLCB0aGlzLnVpTGF5ZXJzKTtcblxuICAgICAgICBsZXQgbm9kZXMgPSB0aGlzLnNjZW5lR3JhcGguZ2V0QWxsTm9kZXMoKTtcbiAgICAgICAgdGhpcy50aWxlbWFwcy5mb3JFYWNoKHRpbGVtYXAgPT4gdGlsZW1hcC52aXNpYmxlID8gbm9kZXMucHVzaCh0aWxlbWFwKSA6IDApO1xuICAgICAgICBEZWJ1Zy5zZXROb2Rlcyhub2Rlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2NlbmUgYXMgcnVubmluZyBvciBub3RcbiAgICAgKiBAcGFyYW0gcnVubmluZyBUcnVlIGlmIHRoZSBTY2VuZSBzaG91bGQgYmUgcnVubmluZywgZmFsc2UgaWYgbm90XG4gICAgICovXG4gICAgc2V0UnVubmluZyhydW5uaW5nOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMucnVubmluZyA9IHJ1bm5pbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgU2NlbmUgaXMgcnVubmluZ1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHNjZW5lIGlzIHJ1bm5pbmcsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIGlzUnVubmluZygpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucnVubmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGEgbm9kZSBmcm9tIHRoaXMgU2NlbmVcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byByZW1vdmVcbiAgICAgKi9cbiAgICByZW1vdmUobm9kZTogR2FtZU5vZGUpOiB2b2lkIHtcbiAgICAgICAgLy8gUmVtb3ZlIGZyb20gdGhlIHNjZW5lIGdyYXBoXG4gICAgICAgIGlmKG5vZGUgaW5zdGFuY2VvZiBDYW52YXNOb2RlKXtcbiAgICAgICAgICAgIHRoaXMuc2NlbmVHcmFwaC5yZW1vdmVOb2RlKG5vZGUpO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICAvKiogRGVzdHJveXMgdGhpcyBzY2VuZSBhbmQgYWxsIG5vZGVzIGluIGl0ICovXG4gICAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMuc2NlbmVHcmFwaC5nZXRBbGxOb2RlcygpKXtcbiAgICAgICAgICAgIG5vZGUuZGVzdHJveSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGxldCB0aWxlbWFwIG9mIHRoaXMudGlsZW1hcHMpe1xuICAgICAgICAgICAgdGlsZW1hcC5kZXN0cm95KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlY2VpdmVyLmRlc3Ryb3koKTtcblxuICAgICAgICBkZWxldGUgdGhpcy5zY2VuZUdyYXBoO1xuICAgICAgICBkZWxldGUgdGhpcy5waHlzaWNzTWFuYWdlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMubmF2TWFuYWdlcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuYWlNYW5hZ2VyO1xuICAgICAgICBkZWxldGUgdGhpcy5yZWNlaXZlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbmV3IGxheWVyIHRvIHRoZSBzY2VuZSBhbmQgcmV0dXJucyBpdFxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBuZXcgbGF5ZXJcbiAgICAgKiBAcGFyYW0gZGVwdGggVGhlIGRlcHRoIG9mIHRoZSBsYXllclxuICAgICAqIEByZXR1cm5zIFRoZSBuZXdseSBjcmVhdGVkIExheWVyXG4gICAgICovXG4gICAgYWRkTGF5ZXIobmFtZTogc3RyaW5nLCBkZXB0aD86IG51bWJlcik6IExheWVyIHtcbiAgICAgICAgaWYodGhpcy5sYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMudWlMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHRocm93IGBMYXllciB3aXRoIG5hbWUgJHtuYW1lfSBhbHJlYWR5IGV4aXN0c2A7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbGF5ZXIgPSBuZXcgTGF5ZXIodGhpcywgbmFtZSk7XG5cbiAgICAgICAgdGhpcy5sYXllcnMuYWRkKG5hbWUsIGxheWVyKTtcblxuICAgICAgICBpZihkZXB0aCl7XG4gICAgICAgICAgICBsYXllci5zZXREZXB0aChkZXB0aCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5ldyBwYXJhbGxheCBsYXllciB0byB0aGlzIHNjZW5lIGFuZCByZXR1cm5zIGl0XG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIHBhcmFsbGF4IGxheWVyXG4gICAgICogQHBhcmFtIHBhcmFsbGF4IFRoZSBwYXJhbGxheCBsZXZlbFxuICAgICAqIEBwYXJhbSBkZXB0aCBUaGUgZGVwdGggb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgUGFyYWxsYXhMYXllclxuICAgICAqL1xuICAgIGFkZFBhcmFsbGF4TGF5ZXIobmFtZTogc3RyaW5nLCBwYXJhbGxheDogVmVjMiwgZGVwdGg/OiBudW1iZXIpOiBQYXJhbGxheExheWVyIHtcbiAgICAgICAgaWYodGhpcy5sYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMucGFyYWxsYXhMYXllcnMuaGFzKG5hbWUpIHx8IHRoaXMudWlMYXllcnMuaGFzKG5hbWUpKXtcbiAgICAgICAgICAgIHRocm93IGBMYXllciB3aXRoIG5hbWUgJHtuYW1lfSBhbHJlYWR5IGV4aXN0c2A7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbGF5ZXIgPSBuZXcgUGFyYWxsYXhMYXllcih0aGlzLCBuYW1lLCBwYXJhbGxheCk7XG5cbiAgICAgICAgdGhpcy5wYXJhbGxheExheWVycy5hZGQobmFtZSwgbGF5ZXIpO1xuXG4gICAgICAgIGlmKGRlcHRoKXtcbiAgICAgICAgICAgIGxheWVyLnNldERlcHRoKGRlcHRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsYXllcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbmV3IFVJTGF5ZXIgdG8gdGhlIHNjZW5lXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIG5ldyBVSWxheWVyXG4gICAgICogQHJldHVybnMgVGhlIG5ld2x5IGNyZWF0ZWQgVUlMYXllclxuICAgICAqL1xuICAgIGFkZFVJTGF5ZXIobmFtZTogc3RyaW5nKTogVUlMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnBhcmFsbGF4TGF5ZXJzLmhhcyhuYW1lKSB8fCB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICB0aHJvdyBgTGF5ZXIgd2l0aCBuYW1lICR7bmFtZX0gYWxyZWFkeSBleGlzdHNgO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxheWVyID0gbmV3IFVJTGF5ZXIodGhpcywgbmFtZSk7XG5cbiAgICAgICAgdGhpcy51aUxheWVycy5hZGQobmFtZSwgbGF5ZXIpO1xuXG4gICAgICAgIHJldHVybiBsYXllcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgbGF5ZXIgZnJvbSB0aGUgc2NlbmUgYnkgbmFtZSBpZiBpdCBleGlzdHMuXG4gICAgICogVGhpcyBjYW4gYmUgYSBMYXllciBvciBhbnkgb2YgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBUaGUgTGF5ZXIgZm91bmQgd2l0aCB0aGF0IG5hbWVcbiAgICAgKi9cbiAgICBnZXRMYXllcihuYW1lOiBzdHJpbmcpOiBMYXllciB7XG4gICAgICAgIGlmKHRoaXMubGF5ZXJzLmhhcyhuYW1lKSl7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYodGhpcy5wYXJhbGxheExheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyYWxsYXhMYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYodGhpcy51aUxheWVycy5oYXMobmFtZSkpe1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudWlMYXllcnMuZ2V0KG5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgYFJlcXVlc3RlZCBsYXllciAke25hbWV9IGRvZXMgbm90IGV4aXN0LmA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBsYXllciBpcyBhIFBhcmFsbGF4TGF5ZXJcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbGF5ZXJcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoaXMgbGF5ZXIgaXMgYSBQYXJhbGxheExheWVyXG4gICAgICovXG4gICAgaXNQYXJhbGxheExheWVyKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5wYXJhbGxheExheWVycy5oYXMobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoaXMgbGF5ZXIgaXMgYSBVSUxheWVyXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIGxheWVyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIGxheWVyIGlzIFBhcmFsbGF4TGF5ZXJcbiAgICAgKi9cbiAgICBpc1VJTGF5ZXIobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnVpTGF5ZXJzLmhhcyhuYW1lKTtcbiAgICB9ICAgIFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdHJhbnNsYXRpb24gb2YgdGhpcyBub2RlIHdpdGggcmVzcGVjdCB0byBjYW1lcmEgc3BhY2UgKGR1ZSB0byB0aGUgdmlld3BvcnQgbW92aW5nKS5cbiAgICAgKiBUaGlzIHZhbHVlIGlzIGFmZmVjdGVkIGJ5IHRoZSBwYXJhbGxheCBsZXZlbCBvZiB0aGUgQHJlZmVyZW5jZVtMYXllcl0gdGhlIG5vZGUgaXMgb24uXG4gICAgICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gY2hlY2sgdGhlIHZpZXdwb3J0IHdpdGggcmVzcGVjdCB0b1xuICAgICAqIEByZXR1cm5zIEEgVmVjMiBjb250YWluaW5nIHRoZSB0cmFuc2xhdGlvbiBvZiB2aWV3cG9ydCB3aXRoIHJlc3BlY3QgdG8gdGhpcyBub2RlLlxuICAgICAqL1xuICAgIGdldFZpZXdUcmFuc2xhdGlvbihub2RlOiBHYW1lTm9kZSk6IFZlYzIge1xuICAgICAgICBsZXQgbGF5ZXIgPSBub2RlLmdldExheWVyKCk7XG5cbiAgICAgICAgaWYobGF5ZXIgaW5zdGFuY2VvZiBQYXJhbGxheExheWVyIHx8IGxheWVyIGluc3RhbmNlb2YgVUlMYXllcil7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52aWV3cG9ydC5nZXRPcmlnaW4oKS5tdWx0KGxheWVyLnBhcmFsbGF4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZpZXdwb3J0LmdldE9yaWdpbigpO1xuICAgICAgICB9XG5cdH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNjYWxlIGxldmVsIG9mIHRoZSB2aWV3XG4gICAgICogQHJldHVybnMgVGhlIHpvb20gbGV2ZWwgb2YgdGhlIHZpZXdwb3J0XG4gICAgKi9cblx0Z2V0Vmlld1NjYWxlKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMudmlld3BvcnQuZ2V0Wm9vbUxldmVsKCk7XG5cdH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIFZpZXdwb3J0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgVmlld3BvcnRcbiAgICAgKi9cbiAgICBnZXRWaWV3cG9ydCgpOiBWaWV3cG9ydCB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXdwb3J0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHdvcmxkIHNpemUgb2YgdGhpcyBTY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSB3b3JsZCBzaXplIGluIGEgVmVjMlxuICAgICAqL1xuICAgIGdldFdvcmxkU2l6ZSgpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud29ybGRTaXplO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIFNjZW5lR3JhcGggYXNzb2NpYXRlZCB3aXRoIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgU2NlbmVHcmFwaFxuICAgICAqL1xuICAgIGdldFNjZW5lR3JhcGgoKTogU2NlbmVHcmFwaCB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjZW5lR3JhcGg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgUGh5c2ljc01hbmFnZXIgYXNzb2NpYXRlZCB3aXRoIHRoaXMgU2NlbmVcbiAgICAgKiBAcmV0dXJucyBUaGUgUGh5c2ljc01hbmFnZXJcbiAgICAgKi9cbiAgICBnZXRQaHlzaWNzTWFuYWdlcigpOiBQaHlzaWNzTWFuYWdlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnBoeXNpY3NNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIE5hdmlnYXRpb25NYW5hZ2VyIGFzc29jaWF0ZWQgd2l0aCB0aGlzIFNjZW5lXG4gICAgICogQHJldHVybnMgVGhlIE5hdmlnYXRpb25NYW5hZ2VyXG4gICAgICovXG4gICAgZ2V0TmF2aWdhdGlvbk1hbmFnZXIoKTogTmF2aWdhdGlvbk1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5uYXZNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIEFJTWFuYWdlciBhc3NvY2lhdGVkIHdpdGggdGhpcyBTY2VuZVxuICAgICAqIEByZXR1cm5zIFRoZSBBSU1hbmFnZXJcbiAgICAgKi9cbiAgICBnZXRBSU1hbmFnZXIoKTogQUlNYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWlNYW5hZ2VyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlcyBhbiBJRCBmb3IgYSBHYW1lTm9kZVxuICAgICAqIEByZXR1cm5zIFRoZSBuZXcgSURcbiAgICAgKi9cbiAgICBnZW5lcmF0ZUlkKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLnNjZW5lTWFuYWdlci5nZW5lcmF0ZUlkKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgVGlsZW1hcCBpbiB0aGlzIFNjZW5lXG4gICAgICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIFRpbGVtYXBcbiAgICAgKiBAcmV0dXJucyBUaGUgVGlsZW1hcCwgaWYgb25lIHRoaXMgbmFtZSBleGlzdHMsIG90aGVyd2lzZSBudWxsXG4gICAgICovXG4gICAgZ2V0VGlsZW1hcChuYW1lOiBzdHJpbmcpOiBUaWxlbWFwIHtcbiAgICAgICAgZm9yKGxldCB0aWxlbWFwIG9mIHRoaXMgLnRpbGVtYXBzKXtcbiAgICAgICAgICAgIGlmKHRpbGVtYXAubmFtZSA9PT0gbmFtZSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbGVtYXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuL1NjZW5lXCI7XG5pbXBvcnQgUmVzb3VyY2VNYW5hZ2VyIGZyb20gXCIuLi9SZXNvdXJjZU1hbmFnZXIvUmVzb3VyY2VNYW5hZ2VyXCI7XG5pbXBvcnQgVmlld3BvcnQgZnJvbSBcIi4uL1NjZW5lR3JhcGgvVmlld3BvcnRcIjtcbmltcG9ydCBSZW5kZXJpbmdNYW5hZ2VyIGZyb20gXCIuLi9SZW5kZXJpbmcvUmVuZGVyaW5nTWFuYWdlclwiO1xuaW1wb3J0IE1lbW9yeVV0aWxzIGZyb20gXCIuLi9VdGlscy9NZW1vcnlVdGlsc1wiO1xuXG4vKipcbiAqIFRoZSBTY2VuZU1hbmFnZXIgYWN0cyBhcyBhbiBpbnRlcmZhY2UgdG8gY3JlYXRlIFNjZW5lcywgYW5kIGhhbmRsZXMgdGhlIGxpZmVjeWNsZSBtZXRob2RzIG9mIFNjZW5lcy5cbiAqIEl0IGdpdmVzIFNjZW5lcyBhY2Nlc3MgdG8gaW5mb3JtYXRpb24gdGhleSBuZWVkIGZyb20gdGhlIEByZWZlcmVuY2VbR2FtZV0gY2xhc3Mgd2hpbGUga2VlcGluZyBhIGxheWVyIG9mIHNlcGFyYXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lTWFuYWdlciB7XG5cdC8qKiBUaGUgY3VycmVudCBTY2VuZSBvZiB0aGUgZ2FtZSAqL1xuXHRwcm90ZWN0ZWQgY3VycmVudFNjZW5lOiBTY2VuZTtcblxuXHQvKiogVGhlIFZpZXdwb3J0IG9mIHRoZSBnYW1lICovXG5cdHByb3RlY3RlZCB2aWV3cG9ydDogVmlld3BvcnQ7XG5cblx0LyoqIEEgcmVmZXJlbmNlIHRvIHRoZSBSZXNvdXJjZU1hbmFnZXIgKi9cblx0cHJvdGVjdGVkIHJlc291cmNlTWFuYWdlcjogUmVzb3VyY2VNYW5hZ2VyO1xuXG5cdC8qKiBBIGNvdW50ZXIgdG8ga2VlcCB0cmFjayBvZiBnYW1lIGlkcyAqL1xuXHRwcm90ZWN0ZWQgaWRDb3VudGVyOiBudW1iZXI7XG5cblx0LyoqIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBnYW1lICovXG5cdHByb3RlY3RlZCByZW5kZXJpbmdNYW5hZ2VyOiBSZW5kZXJpbmdNYW5hZ2VyO1xuXG5cdC8qKiBGb3IgY29uc2lzdGVuY3ksIG9ubHkgY2hhbmdlIHNjZW5lcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB1cGRhdGUgY3ljbGUgKi9cblx0cHJvdGVjdGVkIHBlbmRpbmdTY2VuZTogU2NlbmU7XG5cdHByb3RlY3RlZCBwZW5kaW5nU2NlbmVJbml0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGEgbmV3IFNjZW5lTWFuYWdlclxuXHQgKiBAcGFyYW0gdmlld3BvcnQgVGhlIFZpZXdwb3J0IG9mIHRoZSBnYW1lXG5cdCAqIEBwYXJhbSBnYW1lIFRoZSBHYW1lIGluc3RhbmNlXG5cdCAqIEBwYXJhbSByZW5kZXJpbmdNYW5hZ2VyIFRoZSBSZW5kZXJpbmdNYW5hZ2VyIG9mIHRoZSBnYW1lXG5cdCAqL1xuXHRjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHJlbmRlcmluZ01hbmFnZXI6IFJlbmRlcmluZ01hbmFnZXIpe1xuXHRcdHRoaXMucmVzb3VyY2VNYW5hZ2VyID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cdFx0dGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0O1xuXHRcdHRoaXMucmVuZGVyaW5nTWFuYWdlciA9IHJlbmRlcmluZ01hbmFnZXI7XG5cdFx0dGhpcy5pZENvdW50ZXIgPSAwO1xuXHRcdHRoaXMucGVuZGluZ1NjZW5lID0gbnVsbDtcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGQgYSBzY2VuZSBhcyB0aGUgbWFpbiBzY2VuZS5cblx0ICogVXNlIHRoaXMgbWV0aG9kIGlmIHlvdSd2ZSBjcmVhdGVkIGEgc3ViY2xhc3Mgb2YgU2NlbmUsIGFuZCB5b3Ugd2FudCB0byBhZGQgaXQgYXMgdGhlIG1haW4gU2NlbmUuXG5cdCAqIEBwYXJhbSBjb25zdHIgVGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBzY2VuZSB0byBhZGRcblx0ICogQHBhcmFtIGluaXQgQW4gb2JqZWN0IHRvIHBhc3MgdG8gdGhlIGluaXQgZnVuY3Rpb24gb2YgdGhlIG5ldyBzY2VuZVxuXHQgKi9cblx0cHVibGljIGNoYW5nZVRvU2NlbmU8VCBleHRlbmRzIFNjZW5lPihjb25zdHI6IG5ldyAoLi4uYXJnczogYW55KSA9PiBULCBpbml0PzogUmVjb3JkPHN0cmluZywgYW55Piwgb3B0aW9ucz86IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHRjb25zb2xlLmxvZyhcIkNyZWF0aW5nIHRoZSBuZXcgc2NlbmUgLSBjaGFuZ2UgaXMgcGVuZGluZyB1bnRpbCBuZXh0IHVwZGF0ZVwiKTtcblx0XHR0aGlzLnBlbmRpbmdTY2VuZSA9IG5ldyBjb25zdHIodGhpcy52aWV3cG9ydCwgdGhpcywgdGhpcy5yZW5kZXJpbmdNYW5hZ2VyLCBvcHRpb25zKTtcblx0XHR0aGlzLnBlbmRpbmdTY2VuZUluaXQgPSBpbml0O1xuXHR9XG5cblx0cHJvdGVjdGVkIGRvU2NlbmVDaGFuZ2UoKXtcblx0XHRjb25zb2xlLmxvZyhcIlBlcmZvcm1pbmcgc2NlbmUgY2hhbmdlXCIpO1xuXHRcdHRoaXMudmlld3BvcnQuc2V0Q2VudGVyKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54LCB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSk7XG5cdFx0XG5cdFx0aWYodGhpcy5jdXJyZW50U2NlbmUpe1xuXHRcdFx0Y29uc29sZS5sb2coXCJVbmxvYWRpbmcgb2xkIHNjZW5lXCIpXG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS51bmxvYWRTY2VuZSgpO1xuXG5cdFx0XHRjb25zb2xlLmxvZyhcIkRlc3Ryb3lpbmcgb2xkIHNjZW5lXCIpO1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUuZGVzdHJveSgpO1xuXHRcdH1cblxuXHRcdGNvbnNvbGUubG9nKFwiVW5sb2FkaW5nIG9sZCByZXNvdXJjZXMuLi5cIik7XG5cdFx0dGhpcy5yZXNvdXJjZU1hbmFnZXIudW5sb2FkQWxsUmVzb3VyY2VzKCk7XG5cblx0XHQvLyBNYWtlIHRoZSBwZW5kaW5nIHNjZW5lIHRoZSBjdXJyZW50IG9uZVxuXHRcdHRoaXMuY3VycmVudFNjZW5lID0gdGhpcy5wZW5kaW5nU2NlbmU7XG5cblx0XHQvLyBNYWtlIHRoZSBwZW5kaW5nIHNjZW5lIG51bGxcblx0XHR0aGlzLnBlbmRpbmdTY2VuZSA9IG51bGw7XG5cblx0XHQvLyBJbml0IHRoZSBzY2VuZVxuXHRcdHRoaXMuY3VycmVudFNjZW5lLmluaXRTY2VuZSh0aGlzLnBlbmRpbmdTY2VuZUluaXQpO1xuXG5cdFx0Ly8gRW5xdWV1ZSBhbGwgc2NlbmUgYXNzZXQgbG9hZHNcblx0XHR0aGlzLmN1cnJlbnRTY2VuZS5sb2FkU2NlbmUoKTtcblxuXHRcdC8vIExvYWQgYWxsIGFzc2V0c1xuXHRcdGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgU2NlbmUgTG9hZFwiKTtcblx0XHR0aGlzLnJlc291cmNlTWFuYWdlci5sb2FkUmVzb3VyY2VzRnJvbVF1ZXVlKCgpID0+IHtcblx0XHRcdGNvbnNvbGUubG9nKFwiU3RhcnRpbmcgU2NlbmVcIik7XG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS5zdGFydFNjZW5lKCk7XG5cdFx0XHR0aGlzLmN1cnJlbnRTY2VuZS5zZXRSdW5uaW5nKHRydWUpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5yZW5kZXJpbmdNYW5hZ2VyLnNldFNjZW5lKHRoaXMuY3VycmVudFNjZW5lKTtcblx0fVxuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBJRFxuXHQgKiBAcmV0dXJucyBBIG5ldyBJRFxuXHQgKi9cblx0cHVibGljIGdlbmVyYXRlSWQoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5pZENvdW50ZXIrKztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW5kZXJzIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqL1xuXHRwdWJsaWMgcmVuZGVyKCk6IHZvaWQge1xuXHRcdGlmKHRoaXMuY3VycmVudFNjZW5lKXtcblx0XHRcdHRoaXMuY3VycmVudFNjZW5lLnJlbmRlcigpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoZSBjdXJyZW50IFNjZW5lXG5cdCAqIEBwYXJhbSBkZWx0YVQgVGhlIHRpbWVzdGVwIG9mIHRoZSBTY2VuZVxuXHQgKi9cblx0cHVibGljIHVwZGF0ZShkZWx0YVQ6IG51bWJlcil7XG5cdFx0aWYodGhpcy5wZW5kaW5nU2NlbmUgIT09IG51bGwpe1xuXHRcdFx0dGhpcy5kb1NjZW5lQ2hhbmdlKCk7XG5cdFx0fVxuXG5cdFx0aWYodGhpcy5jdXJyZW50U2NlbmUgJiYgdGhpcy5jdXJyZW50U2NlbmUuaXNSdW5uaW5nKCkpe1xuXHRcdFx0dGhpcy5jdXJyZW50U2NlbmUudXBkYXRlKGRlbHRhVCk7XG5cdFx0fVxuXHR9XG59IiwiaW1wb3J0IEFycmF5VXRpbHMgZnJvbSBcIi4uL1V0aWxzL0FycmF5VXRpbHNcIjtcblxuLy8gQGlnbm9yZVBhZ2VcblxuLyoqXG4gKiBUaGUgb3B0aW9ucyB0byBnaXZlIGEgQHJlZmVyZW5jZVtTY2VuZV0gZm9yIGluaXRpYWxpemF0aW9uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNjZW5lT3B0aW9ucyB7XG4gICAgcGh5c2ljczoge1xuICAgICAgICBncm91cHM6IEFycmF5PHN0cmluZz4sXG4gICAgICAgIGNvbGxpc2lvbnM6IEFycmF5PEFycmF5PG51bWJlcj4+O1xuICAgIH1cblxuICAgIHN0YXRpYyBwYXJzZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogU2NlbmVPcHRpb25ze1xuICAgICAgICBsZXQgc09wdCA9IG5ldyBTY2VuZU9wdGlvbnMoKTtcblxuICAgICAgICBpZihvcHRpb25zLnBoeXNpY3MgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICBzT3B0LnBoeXNpY3MgPSB7Z3JvdXBzOiB1bmRlZmluZWQsIGNvbGxpc2lvbnM6IHVuZGVmaW5lZH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzT3B0LnBoeXNpY3MgPSBvcHRpb25zLnBoeXNpY3M7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc09wdDtcbiAgICB9XG59IiwiaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuL1ZpZXdwb3J0XCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5cbi8qKlxuICogQW4gYWJzdHJhY3QgaW50ZXJmYWNlIG9mIGEgU2NlbmVHcmFwaC5cbiAqIEV4cG9zZXMgbWV0aG9kcyBmb3IgdXNlIGJ5IG90aGVyIGNvZGUsIGJ1dCBsZWF2ZXMgdGhlIGltcGxlbWVudGF0aW9uIHVwIHRvIHRoZSBzdWJjbGFzc2VzLlxuICogVGhlIFNjZW5lR3JhcGggbWFuYWdlcyB0aGUgcG9zaXRpb25zIG9mIGFsbCBHYW1lTm9kZXMsIGFuZCBjYW4gZWFzaWx5IHBydW5lIGEgdmlzaWJsZSBzZXQgZm9yIHJlbmRlcmluZy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgU2NlbmVHcmFwaCB7XG5cdC8qKlx0QSByZWZlcmVuY2UgdG8gdGhlIHZpZXdwb3J0ICovXG5cdHByb3RlY3RlZCB2aWV3cG9ydDogVmlld3BvcnQ7XG5cdC8qKlx0QSBtYXAgb2YgQ2FudmFzTm9kZXMgaW4gdGhpcyBTY2VuZUdyYXBoICovXG5cdHByb3RlY3RlZCBub2RlTWFwOiBBcnJheTxDYW52YXNOb2RlPjtcblx0LyoqIEEgY291bnRlciBvZiBJRHMgZm9yIG5vZGVzIGluIHRoaXMgU2NlbmVHcmFwaCAqL1xuXHRwcm90ZWN0ZWQgaWRDb3VudGVyOiBudW1iZXI7XG5cdC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgU2NlbmUgdGhpcyBTY2VuZUdyYXBoIGJlbG9uZ3MgdG8gKi9cblx0cHJvdGVjdGVkIHNjZW5lOiBTY2VuZTtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBTY2VuZUdyYXBoXG5cdCAqIEBwYXJhbSB2aWV3cG9ydCBUaGUgdmlld3BvcnRcblx0ICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0aGlzIFNjZW5lR3JhcGggYmVsb25ncyB0b1xuXHQgKi9cbiAgICBjb25zdHJ1Y3Rvcih2aWV3cG9ydDogVmlld3BvcnQsIHNjZW5lOiBTY2VuZSl7XG5cdFx0dGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0O1xuXHRcdHRoaXMuc2NlbmUgPSBzY2VuZTtcblx0XHR0aGlzLm5vZGVNYXAgPSBuZXcgQXJyYXkoKTtcblx0XHR0aGlzLmlkQ291bnRlciA9IDA7XG4gICAgfVxuXG5cdC8qKlxuXHQgKiBBZGQgYSBub2RlIHRvIHRoZSBTY2VuZUdyYXBoXG5cdCAqIEBwYXJhbSBub2RlIFRoZSBDYW52YXNOb2RlIHRvIGFkZCB0byB0aGUgU2NlbmVHcmFwaFxuXHQgKiBAcmV0dXJucyBUaGUgU2NlbmVHcmFwaCBJRCBvZiB0aGlzIG5ld2x5IGFkZGVkIENhbnZhc05vZGVcblx0ICovXG4gICAgYWRkTm9kZShub2RlOiBDYW52YXNOb2RlKTogbnVtYmVyIHtcblx0XHR0aGlzLm5vZGVNYXBbbm9kZS5pZF0gPSBub2RlO1xuXHRcdHRoaXMuYWRkTm9kZVNwZWNpZmljKG5vZGUsIHRoaXMuaWRDb3VudGVyKTtcblx0XHR0aGlzLmlkQ291bnRlciArPSAxO1xuXHRcdHJldHVybiB0aGlzLmlkQ291bnRlciAtIDE7XG5cdH07XG5cblx0LyoqXG5cdCAqIEFuIG92ZXJyaWRhYmxlIG1ldGhvZCB0byBhZGQgYSBDYW52YXNOb2RlIHRvIHRoZSBzcGVjaWZpYyBkYXRhIHN0cnVjdHVyZSBvZiB0aGUgU2NlbmVHcmFwaFxuXHQgKiBAcGFyYW0gbm9kZSBUaGUgbm9kZSB0byBhZGQgdG8gdGhlIGRhdGEgc3RydWN0dXJlXG5cdCAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIENhbnZhc05vZGVcblx0ICovXG5cdHByb3RlY3RlZCBhYnN0cmFjdCBhZGROb2RlU3BlY2lmaWMobm9kZTogQ2FudmFzTm9kZSwgaWQ6IG51bWJlcik6IHZvaWQ7XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgYSBub2RlIGZyb20gdGhlIFNjZW5lR3JhcGhcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqL1xuICAgIHJlbW92ZU5vZGUobm9kZTogQ2FudmFzTm9kZSk6IHZvaWQge1xuXHRcdC8vIEZpbmQgYW5kIHJlbW92ZSBub2RlIGluIE8obilcblx0XHR0aGlzLm5vZGVNYXBbbm9kZS5pZF0gPSB1bmRlZmluZWQ7XG5cdFx0dGhpcy5yZW1vdmVOb2RlU3BlY2lmaWMobm9kZSwgbm9kZS5pZCk7XG5cdH07XG5cblx0LyoqXG5cdCAqIFRoZSBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvbiBvZiByZW1vdmluZyBhIG5vZGVcblx0ICogQHBhcmFtIG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIG5vZGUgdG8gcmVtb3ZlXG5cdCAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgcmVtb3ZlTm9kZVNwZWNpZmljKG5vZGU6IENhbnZhc05vZGUsIGlkOiBudW1iZXIpOiB2b2lkO1xuXG5cdC8qKlxuXHQgKiBHZXQgYSBzcGVjaWZpYyBub2RlIHVzaW5nIGl0cyBpZFxuXHQgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBDYW52YXNOb2RlIHRvIHJldHJpZXZlXG5cdCAqIEByZXR1cm5zIFRoZSBub2RlIHdpdGggdGhpcyBJRFxuXHQgKi9cblx0Z2V0Tm9kZShpZDogbnVtYmVyKTogQ2FudmFzTm9kZSB7XG5cdFx0cmV0dXJuIHRoaXMubm9kZU1hcFtpZF07XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbm9kZXMgYXQgc3BlY2lmaWMgY29vcmRpbmF0ZXNcblx0ICogQHBhcmFtIHZlY09yWCBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSBwb3NpdGlvbiwgb3IgdGhlIGNvb3JkaW5hdGVzIGluIGEgVmVjMlxuXHQgKiBAcGFyYW0geSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBwb3NpdGlvblxuXHQgKiBAcmV0dXJucyBBbiBhcnJheSBvZiBub2RlcyBmb3VuZCBhdCB0aGUgcG9zaXRpb24gcHJvdmlkZWRcblx0ICovXG4gICAgZ2V0Tm9kZXNBdCh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiBBcnJheTxDYW52YXNOb2RlPiB7XG5cdFx0aWYodmVjT3JYIGluc3RhbmNlb2YgVmVjMil7XG5cdFx0XHRyZXR1cm4gdGhpcy5nZXROb2Rlc0F0Q29vcmRzKHZlY09yWC54LCB2ZWNPclgueSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiB0aGlzLmdldE5vZGVzQXRDb29yZHModmVjT3JYLCB5KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbm9kZXMgdGhhdCBvdmVybGFwIGEgc3BlY2lmaWMgYm91bmRhcnlcblx0ICogQHBhcmFtIGJvdW5kYXJ5IFRoZSByZWdpb24gdG8gY2hlY2tcblx0ICogQHJldHVybnMgQW4gYXJyYXkgb2Ygbm9kZXMgZm91bmQgb3ZlcmxhcHBpbmcgdGhlIHByb3ZpZGVkIGJvdW5kYXJ5XG5cdCAqL1xuXHRhYnN0cmFjdCBnZXROb2Rlc0luUmVnaW9uKGJvdW5kYXJ5OiBBQUJCKTogQXJyYXk8Q2FudmFzTm9kZT47XG5cdFxuXHQvKipcblx0ICogUmV0dXJucyBhbGwgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICogQHJldHVybnMgQW4gQXJyYXkgY29udGFpbmluZyBhbGwgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICovXG5cdGdldEFsbE5vZGVzKCk6IEFycmF5PENhbnZhc05vZGU+IHtcblx0XHRsZXQgYXJyID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG5cdFx0Zm9yKGxldCBpID0gMDsgaSA8IHRoaXMubm9kZU1hcC5sZW5ndGg7IGkrKyl7XG5cdFx0XHRpZih0aGlzLm5vZGVNYXBbaV0gIT09IHVuZGVmaW5lZCl7XG5cdFx0XHRcdGFyci5wdXNoKHRoaXMubm9kZU1hcFtpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBhcnI7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIHNwZWNpZmljIGltcGxlbWVudGF0aW9uIG9mIGdldHRpbmcgYSBub2RlIGF0IGNlcnRhaW4gY29vcmRpbmF0ZXNcblx0ICogQHBhcmFtIHggVGhlIHgtY29vcmRpbmF0ZXMgb2YgdGhlIG5vZGVcblx0ICogQHBhcmFtIHkgVGhlIHktY29vcmRpbmF0ZXMgb2YgdGhlIG5vZGVcblx0ICovXG4gICAgcHJvdGVjdGVkIGFic3RyYWN0IGdldE5vZGVzQXRDb29yZHMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBBcnJheTxDYW52YXNOb2RlPjtcblxuXHRhYnN0cmFjdCB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkO1xuXHRcblx0YWJzdHJhY3QgcmVuZGVyKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZDtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgdmlzaWJsZSBzZXQgb2YgQ2FudmFzTm9kZXMgYmFzZWQgb24gdGhlIEByZWZlcmVuY2VbVmlld3BvcnRdXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHZpc2libGUgbm9kZXMgaW4gdGhlIFNjZW5lR3JhcGhcblx0ICovXG4gICAgYWJzdHJhY3QgZ2V0VmlzaWJsZVNldCgpOiBBcnJheTxDYW52YXNOb2RlPjtcbn0iLCJpbXBvcnQgU2NlbmVHcmFwaCBmcm9tIFwiLi9TY2VuZUdyYXBoXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IFZpZXdwb3J0IGZyb20gXCIuL1ZpZXdwb3J0XCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgU3RhdHMgZnJvbSBcIi4uL0RlYnVnL1N0YXRzXCI7XG5cbi8qKlxuICogQW4gaW1wbGVtZW50YXRpb24gb2YgYSBTY2VuZUdyYXBoIHRoYXQgc2ltcGx5IHN0b3JlZCBDYW52YXNOb2RlcyBpbiBhbiBhcnJheS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2NlbmVHcmFwaEFycmF5IGV4dGVuZHMgU2NlbmVHcmFwaCB7XG4gICAgLyoqIFRoZSBsaXN0IG9mIENhbnZhc05vZGVzIGluIHRoaXMgU2NlbmVHcmFwaCAqL1xuICAgIHByaXZhdGUgbm9kZUxpc3Q6IEFycmF5PENhbnZhc05vZGU+O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBTY2VuZUdyYXBoQXJyYXlcbiAgICAgKiBAcGFyYW0gdmlld3BvcnQgVGhlIFZpZXdwb3J0XG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBTY2VuZSB0aGlzIFNjZW5lR3JhcGggYmVsb25ncyB0b1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZXdwb3J0OiBWaWV3cG9ydCwgc2NlbmU6IFNjZW5lKXtcbiAgICAgICAgc3VwZXIodmlld3BvcnQsIHNjZW5lKTtcblxuICAgICAgICB0aGlzLm5vZGVMaXN0ID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgcHJvdGVjdGVkIGFkZE5vZGVTcGVjaWZpYyhub2RlOiBDYW52YXNOb2RlLCBpZDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMubm9kZUxpc3QucHVzaChub2RlKTtcbiAgICB9XG5cbiAgICAvLyBAb3ZlcnJpZGVcbiAgICBwcm90ZWN0ZWQgcmVtb3ZlTm9kZVNwZWNpZmljKG5vZGU6IENhbnZhc05vZGUsIGlkOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5ub2RlTGlzdC5pbmRleE9mKG5vZGUpO1xuICAgICAgICBpZihpbmRleCA+IC0xKXtcbiAgICAgICAgICAgIHRoaXMubm9kZUxpc3Quc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIGdldE5vZGVzQXRDb29yZHMoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBBcnJheTxDYW52YXNOb2RlPiB7XG4gICAgICAgIGxldCByZXN1bHRzID0gW107XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYobm9kZS5jb250YWlucyh4LCB5KSl7XG4gICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZ2V0Tm9kZXNJblJlZ2lvbihib3VuZGFyeTogQUFCQik6IEFycmF5PENhbnZhc05vZGU+IHtcbiAgICAgICAgbGV0IHQwID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIGxldCByZXN1bHRzID0gW107XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYoYm91bmRhcnkub3ZlcmxhcHMobm9kZS5ib3VuZGFyeSkpe1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdDEgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgU3RhdHMubG9nKFwic2dxdWVyeVwiLCAodDEtdDApKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IHQwID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIGZvcihsZXQgbm9kZSBvZiB0aGlzLm5vZGVMaXN0KXtcbiAgICAgICAgICAgIGlmKCFub2RlLmdldExheWVyKCkuaXNQYXVzZWQoKSl7XG4gICAgICAgICAgICAgICAgbm9kZS51cGRhdGUoZGVsdGFUKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgdDEgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgU3RhdHMubG9nKFwic2d1cGRhdGVcIiwgKHQxLXQwKSk7XG4gICAgfVxuXG4gICAgcmVuZGVyKGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZCB7fVxuXG4gICAgLy8gQG92ZXJyaWRlXG4gICAgZ2V0VmlzaWJsZVNldCgpOiBBcnJheTxDYW52YXNOb2RlPiB7XG4gICAgICAgIGxldCB2aXNpYmxlU2V0ID0gbmV3IEFycmF5PENhbnZhc05vZGU+KCk7XG5cbiAgICAgICAgZm9yKGxldCBub2RlIG9mIHRoaXMubm9kZUxpc3Qpe1xuICAgICAgICAgICAgaWYoIW5vZGUuZ2V0TGF5ZXIoKS5pc0hpZGRlbigpICYmIG5vZGUudmlzaWJsZSAmJiB0aGlzLnZpZXdwb3J0LmluY2x1ZGVzKG5vZGUpKXtcbiAgICAgICAgICAgICAgICB2aXNpYmxlU2V0LnB1c2gobm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmlzaWJsZVNldDtcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQ2FudmFzTm9kZSBmcm9tIFwiLi4vTm9kZXMvQ2FudmFzTm9kZVwiO1xuaW1wb3J0IE1hdGhVdGlscyBmcm9tIFwiLi4vVXRpbHMvTWF0aFV0aWxzXCI7XG5pbXBvcnQgUXVldWUgZnJvbSBcIi4uL0RhdGFUeXBlcy9RdWV1ZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IElucHV0IGZyb20gXCIuLi9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IFBhcmFsbGF4TGF5ZXIgZnJvbSBcIi4uL1NjZW5lL0xheWVycy9QYXJhbGxheExheWVyXCI7XG5pbXBvcnQgVUlMYXllciBmcm9tIFwiLi4vU2NlbmUvTGF5ZXJzL1VJTGF5ZXJcIjtcblxuLyoqXG4gKiBUaGUgdmlld3BvcnQgb2YgdGhlIGdhbWUuIENvcnJlc3BvbmRzIHRvIHRoZSB2aXNpYmxlIHdpbmRvdyBkaXNwbGF5ZWQgaW4gdGhlIGJyb3dzZXIuXG4gKiBUaGUgdmlld3BvcnQga2VlcHMgdHJhY2sgb2YgaXRzIHBvc2l0aW9uIGluIHRoZSBnYW1lIHdvcmxkLCBhbmQgY2FuIGFjdCBhcyBhIGNhbWVyYSB0byBmb2xsb3cgb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmlld3BvcnQge1xuICAgIC8qKiBUaGUgQUFCQiB0aGF0IGNvbnRhaW5zIHRoZSBwb3NpdGlvbiBhbmQgc2l6ZSBvZiB0aGUgdmlld3BvcnQgdmlldyAqL1xuICAgIHByaXZhdGUgdmlldzogQUFCQjtcbiAgICAvKiogVGhlIGJvdW5kYXJ5IGZvciB0aGUgdmlld3BvcnQuIFRoaXMgcmVwcmVzZW50cyB0aGUgbGltaXRzIHRvIHdoZXJlIHRoZSB2aWV3cG9ydCBjYW4gZ28gKi9cbiAgICBwcml2YXRlIGJvdW5kYXJ5OiBBQUJCO1xuICAgIC8qKiBUaGUgR2FtZU5vZGUgdGhlIFZpZXdwb3J0IGlzIGZvbGxvd2luZyAqL1xuICAgIHByaXZhdGUgZm9sbG93aW5nOiBHYW1lTm9kZTtcbiAgICAvKiogVGhlIHBvc2l0aW9uIHRoZSBHYW1lTm9kZSBpcyBmb2N1c2luZyBvbi4gVGhpcyBpcyBvdmVycmlkZGVuIGlmIFwiZm9sbG93aW5nXCIgaXMgc2V0LiAqL1xuICAgIHByaXZhdGUgZm9jdXM6IFZlYzI7XG5cbiAgICAvKiogQSBxdWV1ZSBvZiBwcmV2aW91cyBwb3NpdGlvbnMgb2Ygd2hhdCB0aGlzIHZpZXdwb3J0IGlzIGZvbGxvd2luZy4gVXNlZCBmb3Igc21vb3RoaW5nIHZpZXdwb3J0IG1vdmVtZW50ICovXG4gICAgcHJpdmF0ZSBsYXN0UG9zaXRpb25zOiBRdWV1ZTxWZWMyPjtcblxuICAgIC8qKiBUaGUgbnVtYmVyIG9mIHByZXZpb3VzIHBvc2l0aW9ucyB0aGlzIHZpZXdwb3J0IHRyYWNrcyAqL1xuICAgIHByaXZhdGUgc21vb3RoaW5nRmFjdG9yOiBudW1iZXI7XG5cbiAgICAvKiogQSBib29sZWFuIHRoYSByZXByZXNlbnRzIHdoZXRoZXIgdGhlIHBsYXllciBjYW4gem9vbSBieSBzY3JvbGxpbmcgd2l0aCB0aGUgbW91c2Ugd2hlZWwgKi9cbiAgICBwcml2YXRlIHNjcm9sbFpvb21FbmFibGVkOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSBhbW91bnQgdGhhdCBpcyB6b29tZWQgaW4gb3Igb3V0LiAqL1xuICAgIHByaXZhdGUgWk9PTV9GQUNUT1I6IG51bWJlciA9IDEuMjtcblxuICAgIC8qKiBUaGUgc2l6ZSBvZiB0aGUgY2FudmFzICovXG4gICAgcHJpdmF0ZSBjYW52YXNTaXplOiBWZWMyO1xuXG4gICAgY29uc3RydWN0b3IoY2FudmFzU2l6ZTogVmVjMiwgem9vbUxldmVsOiBudW1iZXIpe1xuICAgICAgICB0aGlzLnZpZXcgPSBuZXcgQUFCQihWZWMyLlpFUk8sIFZlYzIuWkVSTyk7XG4gICAgICAgIHRoaXMuYm91bmRhcnkgPSBuZXcgQUFCQihWZWMyLlpFUk8sIFZlYzIuWkVSTyk7XG4gICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucyA9IG5ldyBRdWV1ZSgpO1xuICAgICAgICB0aGlzLnNtb290aGluZ0ZhY3RvciA9IDEwO1xuICAgICAgICB0aGlzLnNjcm9sbFpvb21FbmFibGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2FudmFzU2l6ZSA9IFZlYzIuWkVSTztcbiAgICAgICAgdGhpcy5mb2N1cyA9IFZlYzIuWkVSTztcblxuICAgICAgICAvLyBTZXQgdGhlIHNpemUgb2YgdGhlIGNhbnZhc1xuICAgICAgICB0aGlzLnNldENhbnZhc1NpemUoY2FudmFzU2l6ZSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydFxuICAgICAgICB0aGlzLnNldFNpemUoY2FudmFzU2l6ZSk7XG4gICAgICAgIHRoaXMuc2V0Wm9vbUxldmVsKHpvb21MZXZlbCk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBjZW50ZXIgKGFuZCBtYWtlIHRoZSB2aWV3cG9ydCBzdGF5IHRoZXJlKVxuICAgICAgICB0aGlzLnNldENlbnRlcih0aGlzLnZpZXcuaGFsZlNpemUuY2xvbmUoKSk7XG4gICAgICAgIHRoaXMuc2V0Rm9jdXModGhpcy52aWV3LmhhbGZTaXplLmNsb25lKCkpO1xuICAgIH1cblxuICAgIC8qKiBFbmFibGVzIHRoZSB2aWV3cG9ydCB0byB6b29tIGluIGFuZCBvdXQgKi9cbiAgICBlbmFibGVab29tKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNjcm9sbFpvb21FbmFibGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcmV0dXJucyBUaGUgY2VudGVyIG9mIHRoZSB2aWV3cG9ydCBhcyBhIFZlYzJcbiAgICAgKi9cbiAgICBnZXRDZW50ZXIoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZpZXcuY2VudGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBuZXcgVmVjMiB3aXRoIHRoZSBvcmlnaW4gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHJldHVybnMgVGhlIHRvcCBsZWZ0IGNvcm5kZXIgb2YgdGhlIFZpZXBvcnQgYXMgYSBWZWMyXG4gICAgICovXG4gICAgZ2V0T3JpZ2luKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gbmV3IFZlYzIodGhpcy52aWV3LmxlZnQsIHRoaXMudmlldy50b3ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHJlZ2lvbiB2aXNpYmxlIHRvIHRoaXMgdmlld3BvcnRcbiAgICAgKiBAcmV0dXJucyBUaGUgQUFCQiBjb250YWluaW5nIHRoZSByZWdpb24gdmlzaWJsZSB0byB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBnZXRWaWV3KCk6IEFBQkIge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgcG9zaXRpb24gb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IHBvc2l0aW9uIG9yIHRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIG5ldyBwb3NpdGlvblxuICAgICAqIEBwYXJhbSB5IFRoZSB5LWNvb3JkaW5hdGUgb2YgdGhlIG5ldyBwb3NpdGlvblxuICAgICAqL1xuICAgIHNldENlbnRlcih2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcbiAgICAgICAgbGV0IHBvczogVmVjMjtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcbiAgICAgICAgICAgIHBvcyA9IHZlY09yWDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBvcyA9IG5ldyBWZWMyKHZlY09yWCwgeSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnZpZXcuY2VudGVyID0gcG9zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0IGFzIGEgVmVjMlxuICAgICAqIEByZXR1cm5zIFRoZSBoYWxmLXNpemUgb2YgdGhlIHZpZXdwb3J0IGFzIGEgVmVjMlxuICAgICAqL1xuICAgIGdldEhhbGZTaXplKCk6IFZlYzIge1xuICAgICAgICByZXR1cm4gdGhpcy52aWV3LmdldEhhbGZTaXplKCk7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IHdpZHRoIG9mIHRoZSB2aWV3cG9ydCBvciB0aGUgbmV3IHNpemUgYXMgYSBWZWMyXG4gICAgICogQHBhcmFtIHkgVGhlIG5ldyBoZWlnaHQgb2YgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgc2V0U2l6ZSh2ZWNPclg6IFZlYzIgfCBudW1iZXIsIHk6IG51bWJlciA9IG51bGwpOiB2b2lkIHtcblx0XHRpZih2ZWNPclggaW5zdGFuY2VvZiBWZWMyKXtcblx0XHRcdHRoaXMudmlldy5zZXRIYWxmU2l6ZSh2ZWNPclguc2NhbGVkKDEvMikpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnZpZXcuc2V0SGFsZlNpemUobmV3IFZlYzIodmVjT3JYLzIsIHkvMikpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBoYWxmLXNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHZlY09yWCBUaGUgbmV3IGhhbGYtd2lkdGggb2YgdGhlIHZpZXdwb3J0IG9yIHRoZSBuZXcgaGFsZi1zaXplIGFzIGEgVmVjMlxuICAgICAqIEBwYXJhbSB5IFRoZSBuZXcgaGVpZ2h0IG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHNldEhhbGZTaXplKHZlY09yWDogVmVjMiB8IG51bWJlciwgeTogbnVtYmVyID0gbnVsbCk6IHZvaWQge1xuXHRcdGlmKHZlY09yWCBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0dGhpcy52aWV3LnNldEhhbGZTaXplKHZlY09yWC5jbG9uZSgpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy52aWV3LnNldEhhbGZTaXplKG5ldyBWZWMyKHZlY09yWCwgeSkpO1xuXHRcdH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHRoZSB2aWV3cG9ydCB3aXRoIHRoZSBzaXplIG9mIHRoZSBjdXJyZW50IENhbnZhc1xuICAgICAqIEBwYXJhbSB2ZWNPclggVGhlIHdpZHRoIG9mIHRoZSBjYW52YXMsIG9yIHRoZSBjYW52YXMgc2l6ZSBhcyBhIFZlYzJcbiAgICAgKiBAcGFyYW0geSBUaGUgaGVpZ2h0IG9mIHRoZSBjYW52YXNcbiAgICAgKi9cbiAgICBzZXRDYW52YXNTaXplKHZlY09yWDogVmVjMiB8IG51bWJlciwgeTogbnVtYmVyID0gbnVsbCk6IHZvaWQge1xuXHRcdGlmKHZlY09yWCBpbnN0YW5jZW9mIFZlYzIpe1xuXHRcdFx0dGhpcy5jYW52YXNTaXplID0gdmVjT3JYLmNsb25lKCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuY2FudmFzU2l6ZSA9IG5ldyBWZWMyKHZlY09yWCwgeSk7XG5cdFx0fVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHZpZXdwb3J0XG4gICAgICogQHBhcmFtIHpvb20gVGhlIHpvb20gbGV2ZWxcbiAgICAgKi9cbiAgICBzZXRab29tTGV2ZWwoem9vbTogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMudmlldy5oYWxmU2l6ZS5jb3B5KHRoaXMuY2FudmFzU2l6ZS5zY2FsZWQoMS96b29tLzIpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEByZXR1cm5zIFRoZSB6b29tIGxldmVsXG4gICAgICovXG4gICAgZ2V0Wm9vbUxldmVsKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbnZhc1NpemUueC90aGlzLnZpZXcuaHcvMlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHNtb290aGluZyBmYWN0b3IgZm9yIHRoZSB2aWV3cG9ydCBtb3ZlbWVudC5cbiAgICAgKiBAcGFyYW0gc21vb3RoaW5nRmFjdG9yIFRoZSBzbW9vdGhpbmcgZmFjdG9yIGZvciB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBzZXRTbW9vdGhpbmdGYWN0b3Ioc21vb3RoaW5nRmFjdG9yOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYoc21vb3RoaW5nRmFjdG9yIDwgMSkgc21vb3RoaW5nRmFjdG9yID0gMTtcbiAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgPSBzbW9vdGhpbmdGYWN0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVsbHMgdGhlIHZpZXdwb3J0IHRvIGZvY3VzIG9uIGEgcG9pbnQuIE92ZXJpZGRlbiBieSBcImZvbGxvd2luZ1wiLlxuICAgICAqIEBwYXJhbSBmb2N1cyBUaGUgcG9pbnQgdGhlICB2aWV3cG9ydCBzaG91bGQgZm9jdXMgb25cbiAgICAgKi9cbiAgICBzZXRGb2N1cyhmb2N1czogVmVjMik6IHZvaWQge1xuICAgICAgICB0aGlzLmZvY3VzLmNvcHkoZm9jdXMpO1xuICAgIH1cbiAgICBcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIENhbnZhc05vZGUgaXMgaW5zaWRlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBub2RlIHRvIGNoZWNrXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgbm9kZSBpcyBjdXJyZW50bHkgdmlzaWJsZSBpbiB0aGUgdmlld3BvcnQsIGZhbHNlIGlmIG5vdFxuICAgICAqL1xuICAgIGluY2x1ZGVzKG5vZGU6IENhbnZhc05vZGUpOiBib29sZWFuIHtcbiAgICAgICAgbGV0IHBhcmFsbGF4ID0gbm9kZS5nZXRMYXllcigpIGluc3RhbmNlb2YgUGFyYWxsYXhMYXllciB8fCBub2RlLmdldExheWVyKCkgaW5zdGFuY2VvZiBVSUxheWVyID8gKDxQYXJhbGxheExheWVyPm5vZGUuZ2V0TGF5ZXIoKSkucGFyYWxsYXggOiBuZXcgVmVjMigxLCAxKTtcbiAgICAgICAgbGV0IGNlbnRlciA9IHRoaXMudmlldy5jZW50ZXIuY2xvbmUoKTtcbiAgICAgICAgdGhpcy52aWV3LmNlbnRlci5tdWx0KHBhcmFsbGF4KTtcbiAgICAgICAgbGV0IG92ZXJsYXBzID0gdGhpcy52aWV3Lm92ZXJsYXBzKG5vZGUuYm91bmRhcnkpO1xuICAgICAgICB0aGlzLnZpZXcuY2VudGVyID0gY2VudGVyXG4gICAgICAgIHJldHVybiBvdmVybGFwcztcbiAgICB9XG5cblx0Ly8gVE9ETzogUHV0IHNvbWUgZXJyb3IgaGFuZGxpbmcgb24gdGhpcyBmb3IgdHJ5aW5nIHRvIG1ha2UgdGhlIGJvdW5kcyB0b28gc21hbGwgZm9yIHRoZSB2aWV3cG9ydFxuICAgIC8vIFRPRE86IFRoaXMgc2hvdWxkIHByb2JhYmx5IGJlIGRvbmUgYXV0b21hdGljYWxseSwgb3Igc2hvdWxkIGNvbnNpZGVyIHRoZSBhc3BlY3QgcmF0aW8gb3Igc29tZXRoaW5nXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYm91bmRzIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSBsb3dlclggVGhlIGxlZnQgZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gbG93ZXJZIFRoZSB0b3AgZWRnZSBvZiB0aGUgdmlld3BvcnRcbiAgICAgKiBAcGFyYW0gdXBwZXJYIFRoZSByaWdodCBlZGdlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB1cHBlclkgVGhlIGJvdHRvbSBlZGdlIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqL1xuICAgIHNldEJvdW5kcyhsb3dlclg6IG51bWJlciwgbG93ZXJZOiBudW1iZXIsIHVwcGVyWDogbnVtYmVyLCB1cHBlclk6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBsZXQgaHdpZHRoID0gKHVwcGVyWCAtIGxvd2VyWCkvMjtcbiAgICAgICAgbGV0IGhoZWlnaHQgPSAodXBwZXJZIC0gbG93ZXJZKS8yO1xuICAgICAgICBsZXQgeCA9IGxvd2VyWCArIGh3aWR0aDtcbiAgICAgICAgbGV0IHkgPSBsb3dlclkgKyBoaGVpZ2h0O1xuICAgICAgICB0aGlzLmJvdW5kYXJ5LmNlbnRlci5zZXQoeCwgeSk7XG4gICAgICAgIHRoaXMuYm91bmRhcnkuaGFsZlNpemUuc2V0KGh3aWR0aCwgaGhlaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZSB0aGUgdmlld3BvcnQgZm9sbG93IHRoZSBzcGVjaWZpZWQgR2FtZU5vZGVcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgR2FtZU5vZGUgdG8gZm9sbG93XG4gICAgICovXG4gICAgZm9sbG93KG5vZGU6IEdhbWVOb2RlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9sbG93aW5nID0gbm9kZTtcbiAgICB9XG5cbiAgICB1cGRhdGVWaWV3KCk6IHZvaWQge1xuICAgICAgICBpZih0aGlzLmxhc3RQb3NpdGlvbnMuZ2V0U2l6ZSgpID4gdGhpcy5zbW9vdGhpbmdGYWN0b3Ipe1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb25zLmRlcXVldWUoKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gR2V0IHRoZSBhdmVyYWdlIG9mIHRoZSBsYXN0IDEwIHBvc2l0aW9uc1xuICAgICAgICBsZXQgcG9zID0gVmVjMi5aRVJPO1xuICAgICAgICB0aGlzLmxhc3RQb3NpdGlvbnMuZm9yRWFjaChwb3NpdGlvbiA9PiBwb3MuYWRkKHBvc2l0aW9uKSk7XG4gICAgICAgIHBvcy5zY2FsZSgxL3RoaXMubGFzdFBvc2l0aW9ucy5nZXRTaXplKCkpO1xuXG4gICAgICAgIC8vIFNldCB0aGlzIHBvc2l0aW9uIGVpdGhlciB0byB0aGUgb2JqZWN0IG9yIHRvIGl0cyBib3VuZHNcbiAgICAgICAgcG9zLnggPSBNYXRoVXRpbHMuY2xhbXAocG9zLngsIHRoaXMuYm91bmRhcnkubGVmdCArIHRoaXMudmlldy5odywgdGhpcy5ib3VuZGFyeS5yaWdodCAtIHRoaXMudmlldy5odyk7XG4gICAgICAgIHBvcy55ID0gTWF0aFV0aWxzLmNsYW1wKHBvcy55LCB0aGlzLmJvdW5kYXJ5LnRvcCArIHRoaXMudmlldy5oaCwgdGhpcy5ib3VuZGFyeS5ib3R0b20gLSB0aGlzLnZpZXcuaGgpO1xuXG4gICAgICAgIC8vIEFzc3VyZSB0aGVyZSBhcmUgbm8gbGluZXMgaW4gdGhlIHRpbGVtYXBcbiAgICAgICAgcG9zLnggPSBNYXRoLmZsb29yKHBvcy54KTtcbiAgICAgICAgcG9zLnkgPSBNYXRoLmZsb29yKHBvcy55KTtcbiAgICAgICAgXG4gICAgICAgIHRoaXMudmlldy5jZW50ZXIuY29weShwb3MpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBJZiB6b29tIGlzIGVuYWJsZWRcbiAgICAgICAgaWYodGhpcy5zY3JvbGxab29tRW5hYmxlZCl7XG4gICAgICAgICAgICBpZihJbnB1dC5kaWRKdXN0U2Nyb2xsKCkpe1xuICAgICAgICAgICAgICAgIGxldCBjdXJyZW50U2l6ZSA9IHRoaXMudmlldy5nZXRIYWxmU2l6ZSgpLmNsb25lKCk7XG4gICAgICAgICAgICAgICAgaWYoSW5wdXQuZ2V0U2Nyb2xsRGlyZWN0aW9uKCkgPCAwKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gWm9vbSBpblxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2l6ZS5zY2FsZSgxL3RoaXMuWk9PTV9GQUNUT1IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFpvb20gb3V0XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnNjYWxlKHRoaXMuWk9PTV9GQUNUT1IpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRTaXplLnggPiB0aGlzLmJvdW5kYXJ5Lmh3KXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZhY3RvciA9IHRoaXMuYm91bmRhcnkuaHcvY3VycmVudFNpemUueDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNpemUueCA9IHRoaXMuYm91bmRhcnkuaHc7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnkgKj0gZmFjdG9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRTaXplLnkgPiB0aGlzLmJvdW5kYXJ5LmhoKXtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZhY3RvciA9IHRoaXMuYm91bmRhcnkuaGgvY3VycmVudFNpemUueTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNpemUueSA9IHRoaXMuYm91bmRhcnkuaGg7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTaXplLnggKj0gZmFjdG9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmlldy5zZXRIYWxmU2l6ZShjdXJyZW50U2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB2aWV3cG9ydCBpcyBmb2xsb3dpbmcgYW4gb2JqZWN0XG4gICAgICAgIGlmKHRoaXMuZm9sbG93aW5nKXtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBvdXIgbGlzdCBvZiBwcmV2aW91cyBwb3NpdGlvbnNcbiAgICAgICAgICAgIHRoaXMubGFzdFBvc2l0aW9ucy5lbnF1ZXVlKHRoaXMuZm9sbG93aW5nLnBvc2l0aW9uLmNsb25lKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sYXN0UG9zaXRpb25zLmVucXVldWUodGhpcy5mb2N1cyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZVZpZXcoKTtcbiAgICB9XG59IiwiaW1wb3J0IE1hcCBmcm9tIFwiLi4vRGF0YVR5cGVzL01hcFwiO1xuaW1wb3J0IFJlY2VpdmVyIGZyb20gXCIuLi9FdmVudHMvUmVjZWl2ZXJcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcblxuLyoqXG4gKiBNYW5hZ2VzIGFueSBzb3VuZHMgb3IgbXVzaWMgbmVlZGVkIGZvciB0aGUgZ2FtZS5cbiAqIFRocm91Z2ggdGhlIEV2ZW50UXVldWUsIGV4cG9zZXMgaW50ZXJmYWNlIHRvIHBsYXkgc291bmRzIHNvIEdhbWVOb2RlcyBjYW4gYWN0aXZhdGUgc291bmRzIHdpdGhvdXRcbiAqIG5lZWRpbmcgZGlyZWN0IHJlZmVyZW5jZXMgdG8gdGhlIGF1ZGlvIHN5c3RlbVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBdWRpb01hbmFnZXIge1xuICAgIHByaXZhdGUgc3RhdGljIGluc3RhbmNlOiBBdWRpb01hbmFnZXI7XG5cbiAgICAvKiogVGhlIGV2ZW50IHJlY2VpdmVyIG9mIHRoaXMgQXVkaW9NYW5hZ2VyICovXG4gICAgcHJpdmF0ZSByZWNlaXZlcjogUmVjZWl2ZXI7XG5cbiAgICAvKiogQSBNYXAgb2YgdGhlIG5hbWVzIG9mIGN1cnJlbnRseSBwbGF5aW5nIChvciBwYXVzZWQpIHNvdW5kcyB0byB0aGVpciBBdWRpb0J1ZmZlcnMgKi9cbiAgICBwcml2YXRlIGN1cnJlbnRTb3VuZHM6IE1hcDxBdWRpb0J1ZmZlclNvdXJjZU5vZGU+O1xuXG4gICAgcHJpdmF0ZSBhdWRpb0N0eDogQXVkaW9Db250ZXh0O1xuXG4gICAgcHJpdmF0ZSBnYWluTm9kZXM6IEFycmF5PEdhaW5Ob2RlPjtcblxuICAgIHByaXZhdGUgY29uc3RydWN0b3IoKXtcbiAgICAgICAgdGhpcy5pbml0QXVkaW8oKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlciA9IG5ldyBSZWNlaXZlcigpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShbXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlNUT1BfU09VTkQsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfTVVTSUMsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlBMQVlfU0ZYLFxuICAgICAgICAgICAgR2FtZUV2ZW50VHlwZS5NVVRFX0NIQU5ORUwsXG4gICAgICAgICAgICBHYW1lRXZlbnRUeXBlLlVOTVVURV9DSEFOTkVMXG4gICAgICAgIF0pO1xuICAgICAgICB0aGlzLmN1cnJlbnRTb3VuZHMgPSBuZXcgTWFwKCk7XG5cbiAgICAgICAgdGhpcy5nYWluTm9kZXMgPSBuZXcgQXJyYXk8R2Fpbk5vZGU+KE1BWF9BVURJT19DSEFOTkVMUyk7XG4gICAgICAgIHRoaXMuaW5pdEdhaW5Ob2RlcygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgaW5zdGFuY2Ugb2YgdGhlIEF1ZGlvTWFuYWdlciBjbGFzcyBvciBjcmVhdGUgYSBuZXcgb25lIGlmIG5vbmUgZXhpc3RzXG4gICAgICogQHJldHVybnMgVGhlIEF1ZGlvTWFuYWdlclxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgZ2V0SW5zdGFuY2UoKTogQXVkaW9NYW5hZ2VyIHtcbiAgICAgICAgaWYoIXRoaXMuaW5zdGFuY2Upe1xuICAgICAgICAgICAgdGhpcy5pbnN0YW5jZSA9IG5ldyBBdWRpb01hbmFnZXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgd2ViQXVkaW8gY29udGV4dFxuICAgICAqL1xuICAgIHByaXZhdGUgaW5pdEF1ZGlvKCk6IHZvaWQge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgd2luZG93LkF1ZGlvQ29udGV4dCA9IHdpbmRvdy5BdWRpb0NvbnRleHQ7Ly8gfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDsgXG4gICAgICAgICAgICB0aGlzLmF1ZGlvQ3R4ID0gbmV3IEF1ZGlvQ29udGV4dCgpOyBcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdXZWIgQXVkaW8gQVBJIHN1Y2Nlc3NmdWxseSBsb2FkZWQnKTtcbiAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1dlYiBBdWRpbyBBUEkgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKTsgXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRHYWluTm9kZXMoKTogdm9pZCB7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBNQVhfQVVESU9fQ0hBTk5FTFM7IGkrKyl7XG4gICAgICAgICAgICB0aGlzLmdhaW5Ob2Rlc1tpXSA9IHRoaXMuYXVkaW9DdHguY3JlYXRlR2FpbigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCBhdWRpbyBjb250ZXh0XG4gICAgICogQHJldHVybnMgVGhlIEF1ZGlvQ29udGV4dFxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRBdWRpb0NvbnRleHQoKTogQXVkaW9Db250ZXh0IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXVkaW9DdHg7XG4gICAgfVxuXG4gICAgLypcbiAgICAgICAgQWNjb3JkaW5nIHRvIHRoZSBNRE4sIGNyZWF0ZSBhIG5ldyBzb3VuZCBmb3IgZXZlcnkgY2FsbDpcblxuICAgICAgICBBbiBBdWRpb0J1ZmZlclNvdXJjZU5vZGUgY2FuIG9ubHkgYmUgcGxheWVkIG9uY2U7IGFmdGVyIGVhY2ggY2FsbCB0byBzdGFydCgpLCB5b3UgaGF2ZSB0byBjcmVhdGUgYSBuZXcgbm9kZVxuICAgICAgICBpZiB5b3Ugd2FudCB0byBwbGF5IHRoZSBzYW1lIHNvdW5kIGFnYWluLiBGb3J0dW5hdGVseSwgdGhlc2Ugbm9kZXMgYXJlIHZlcnkgaW5leHBlbnNpdmUgdG8gY3JlYXRlLCBhbmQgdGhlXG4gICAgICAgIGFjdHVhbCBBdWRpb0J1ZmZlcnMgY2FuIGJlIHJldXNlZCBmb3IgbXVsdGlwbGUgcGxheXMgb2YgdGhlIHNvdW5kLiBJbmRlZWQsIHlvdSBjYW4gdXNlIHRoZXNlIG5vZGVzIGluIGFcbiAgICAgICAgXCJmaXJlIGFuZCBmb3JnZXRcIiBtYW5uZXI6IGNyZWF0ZSB0aGUgbm9kZSwgY2FsbCBzdGFydCgpIHRvIGJlZ2luIHBsYXlpbmcgdGhlIHNvdW5kLCBhbmQgZG9uJ3QgZXZlbiBib3RoZXIgdG9cbiAgICAgICAgaG9sZCBhIHJlZmVyZW5jZSB0byBpdC4gSXQgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIGdhcmJhZ2UtY29sbGVjdGVkIGF0IGFuIGFwcHJvcHJpYXRlIHRpbWUsIHdoaWNoIHdvbid0IGJlXG4gICAgICAgIHVudGlsIHNvbWV0aW1lIGFmdGVyIHRoZSBzb3VuZCBoYXMgZmluaXNoZWQgcGxheWluZy5cbiAgICAqL1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgc291bmQgZnJvbSB0aGUga2V5IG9mIGEgbG9hZGVkIGF1ZGlvIGZpbGVcbiAgICAgKiBAcGFyYW0ga2V5IFRoZSBrZXkgb2YgdGhlIGxvYWRlZCBhdWRpbyBmaWxlIHRvIGNyZWF0ZSBhIG5ldyBzb3VuZCBmb3JcbiAgICAgKiBAcmV0dXJucyBUaGUgbmV3bHkgY3JlYXRlZCBBdWRpb0J1ZmZlclxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVTb3VuZChrZXk6IHN0cmluZywgaG9sZFJlZmVyZW5jZTogYm9vbGVhbiwgY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSwgb3B0aW9uczogTWFwPGFueT4pOiBBdWRpb0J1ZmZlclNvdXJjZU5vZGUge1xuICAgICAgICAvLyBHZXQgYXVkaW8gYnVmZmVyXG4gICAgICAgIGxldCBidWZmZXIgPSBSZXNvdXJjZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKS5nZXRBdWRpbyhrZXkpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhIHNvdW5kIHNvdXJjZVxuICAgICAgICB2YXIgc291cmNlID0gdGhpcy5hdWRpb0N0eC5jcmVhdGVCdWZmZXJTb3VyY2UoKTsgXG4gICAgICBcbiAgICAgICAgLy8gVGVsbCB0aGUgc291cmNlIHdoaWNoIHNvdW5kIHRvIHBsYXlcbiAgICAgICAgc291cmNlLmJ1ZmZlciA9IGJ1ZmZlcjsgICAgICAgICAgICAgICBcbiAgICAgIFxuICAgICAgICAvLyBBZGQgYW55IGFkZGl0aW9uYWwgbm9kZXNcbiAgICAgICAgY29uc3Qgbm9kZXM6IEFycmF5PEF1ZGlvTm9kZT4gPSBbc291cmNlXTtcblxuICAgICAgICAvLyBEbyBhbnkgYWRkaXRpb25hbCBub2RlcyBoZXJlP1xuICAgICAgICAvLyBPZiBjb3Vyc2UsIHRoZXJlIGFyZW4ndCBhbnkgc3VwcG9ydGVkIHlldC4uLlxuXG4gICAgICAgIC8vIEFkZCB0aGUgZ2FpbiBub2RlIGZvciB0aGlzIGNoYW5uZWxcbiAgICAgICAgbm9kZXMucHVzaCh0aGlzLmdhaW5Ob2Rlc1tjaGFubmVsXSk7XG5cbiAgICAgICAgLy8gQ29ubmVjdCBhbnkgbm9kZXMgYWxvbmcgdGhlIHBhdGhcbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgIG5vZGVzW2ktMV0uY29ubmVjdChub2Rlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb25uZWN0IHRoZSBzb3VyY2UgdG8gdGhlIGNvbnRleHQncyBkZXN0aW5hdGlvblxuICAgICAgICBub2Rlc1tub2Rlcy5sZW5ndGggLSAxXS5jb25uZWN0KHRoaXMuYXVkaW9DdHguZGVzdGluYXRpb24pO1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQbGF5IHRoZSBzb3VuZCBzcGVjaWZpZWQgYnkgdGhlIGtleVxuICAgICAqIEBwYXJhbSBrZXkgVGhlIGtleSBvZiB0aGUgc291bmQgdG8gcGxheVxuICAgICAqIEBwYXJhbSBsb29wIEEgYm9vbGVhbiBmb3Igd2hldGhlciBvciBub3QgdG8gbG9vcCB0aGUgc291bmRcbiAgICAgKiBAcGFyYW0gaG9sZFJlZmVyZW5jZSBBIGJvb2xlYW4gZm9yIHdoZXRoZXIgb3Igbm90IHdlIHdhbnQgdG8gaG9sZCBvbiB0byBhIHJlZmVyZW5jZSBvZiB0aGUgYXVkaW8gbm9kZS4gVGhpcyBpcyBnb29kIGZvciBwbGF5aW5nIG11c2ljIG9uIGEgbG9vcCB0aGF0IHdpbGwgZXZlbnR1YWxseSBuZWVkIHRvIGJlIHN0b3BwZWQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHBsYXlTb3VuZChrZXk6IHN0cmluZywgbG9vcDogYm9vbGVhbiwgaG9sZFJlZmVyZW5jZTogYm9vbGVhbiwgY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSwgb3B0aW9uczogTWFwPGFueT4pOiB2b2lkIHtcbiAgICAgICAgbGV0IHNvdW5kID0gdGhpcy5jcmVhdGVTb3VuZChrZXksIGhvbGRSZWZlcmVuY2UsIGNoYW5uZWwsIG9wdGlvbnMpO1xuXG4gICAgICAgIGlmKGxvb3Ape1xuICAgICAgICAgICAgc291bmQubG9vcCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYSByZWZlcmVuY2Ugb2YgdGhlIG5ldyBzb3VuZCB0byBhIG1hcC4gVGhpcyB3aWxsIGFsbG93IHVzIHRvIHN0b3AgYSBsb29waW5nIG9yIGxvbmcgc291bmQgYXQgYSBsYXRlciB0aW1lXG4gICAgICAgIGlmKGhvbGRSZWZlcmVuY2Upe1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50U291bmRzLmFkZChrZXksIHNvdW5kKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgc291bmQuc3RhcnQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdG9wIHRoZSBzb3VuZCBzcGVjaWZpZWQgYnkgdGhlIGtleVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdG9wU291bmQoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgbGV0IHNvdW5kID0gdGhpcy5jdXJyZW50U291bmRzLmdldChrZXkpO1xuICAgICAgICBpZihzb3VuZCl7XG4gICAgICAgICAgICBzb3VuZC5zdG9wKCk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRTb3VuZHMuZGVsZXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbXV0ZUNoYW5uZWwoY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSl7XG4gICAgICAgIHRoaXMuZ2Fpbk5vZGVzW2NoYW5uZWxdLmdhaW4uc2V0VmFsdWVBdFRpbWUoMCwgdGhpcy5hdWRpb0N0eC5jdXJyZW50VGltZSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHVubXV0ZUNoYW5uZWwoY2hhbm5lbDogQXVkaW9DaGFubmVsVHlwZSl7XG4gICAgICAgIHRoaXMuZ2Fpbk5vZGVzW2NoYW5uZWxdLmdhaW4uc2V0VmFsdWVBdFRpbWUoMSwgdGhpcy5hdWRpb0N0eC5jdXJyZW50VGltZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgdm9sdW1lIG9mIGEgY2hhbm5lbCB1c2luZyB0aGUgR2Fpbk5vZGUgZm9yIHRoYXQgY2hhbm5lbC4gRm9yIG1vcmVcbiAgICAgKiBpbmZvcm1hdGlvbiBvbiBHYWluTm9kZXMsIHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvR2Fpbk5vZGVcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgYXVkaW8gY2hhbm5lbCB0byBzZXQgdGhlIHZvbHVtZSBmb3JcbiAgICAgKiBAcGFyYW0gdm9sdW1lIFRoZSB2b2x1bWUgb2YgdGhlIGNoYW5uZWwuIDAgaXMgbXV0ZWQuIFZhbHVlcyBiZWxvdyB6ZXJvIHdpbGwgYmUgc2V0IHRvIHplcm8uXG4gICAgICovXG4gICAgc3RhdGljIHNldFZvbHVtZShjaGFubmVsOiBBdWRpb0NoYW5uZWxUeXBlLCB2b2x1bWU6IG51bWJlcil7XG4gICAgICAgIGlmKHZvbHVtZSA8IDApe1xuICAgICAgICAgICAgdm9sdW1lID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFtID0gQXVkaW9NYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgICAgIGFtLmdhaW5Ob2Rlc1tjaGFubmVsXS5nYWluLnNldFZhbHVlQXRUaW1lKHZvbHVtZSwgYW0uYXVkaW9DdHguY3VycmVudFRpbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIEdhaW5Ob2RlIGZvciB0aGlzIGNoYW5uZWwuXG4gICAgICogTGVhcm4gbW9yZSBhYm91dCBHYWluTm9kZXMgaGVyZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvR2Fpbk5vZGVcbiAgICAgKiBET04nVCBVU0UgVEhJUyBVTkxFU1MgWU9VIEtOT1cgV0hBVCBZT1UnUkUgRE9JTkdcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgY2hhbm5lbFxuICAgICAqIEByZXR1cm5zIFRoZSBHYWluTm9kZSBmb3IgdGhlIHNwZWNpZmllZCBjaGFubmVsXG4gICAgICovXG4gICAgZ2V0Q2hhbm5lbEdhaW5Ob2RlKGNoYW5uZWw6IEF1ZGlvQ2hhbm5lbFR5cGUpe1xuICAgICAgICByZXR1cm4gdGhpcy5nYWluTm9kZXNbY2hhbm5lbF07XG4gICAgfVxuICAgIFxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBQbGF5IGVhY2ggYXVkaW8gY2xpcCByZXF1ZXN0ZWRcbiAgICAgICAgLy8gVE9ETyAtIEFkZCBsb2dpYyB0byBtZXJnZSBzb3VuZHMgaWYgdGhlcmUgYXJlIG11bHRpcGxlIG9mIHRoZSBzYW1lIGtleVxuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQgfHwgZXZlbnQudHlwZSA9PT0gR2FtZUV2ZW50VHlwZS5QTEFZX01VU0lDIHx8IGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuUExBWV9TRlgpe1xuICAgICAgICAgICAgICAgIGxldCBzb3VuZEtleSA9IGV2ZW50LmRhdGEuZ2V0KFwia2V5XCIpO1xuICAgICAgICAgICAgICAgIGxldCBsb29wID0gZXZlbnQuZGF0YS5nZXQoXCJsb29wXCIpO1xuICAgICAgICAgICAgICAgIGxldCBob2xkUmVmZXJlbmNlID0gZXZlbnQuZGF0YS5nZXQoXCJob2xkUmVmZXJlbmNlXCIpO1xuXG4gICAgICAgICAgICAgICAgbGV0IGNoYW5uZWwgPSBBdWRpb0NoYW5uZWxUeXBlLkRFRkFVTFQ7XG5cbiAgICAgICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlBMQVlfTVVTSUMpe1xuICAgICAgICAgICAgICAgICAgICBjaGFubmVsID0gQXVkaW9DaGFubmVsVHlwZS5NVVNJQztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoR2FtZUV2ZW50VHlwZS5QTEFZX1NGWCl7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5uZWwgPSBBdWRpb0NoYW5uZWxUeXBlLlNGWDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZXZlbnQuZGF0YS5oYXMoXCJjaGFubmVsXCIpKXtcbiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbCA9IGV2ZW50LmRhdGEuZ2V0KFwiY2hhbm5lbFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBsYXlTb3VuZChzb3VuZEtleSwgbG9vcCwgaG9sZFJlZmVyZW5jZSwgY2hhbm5lbCwgZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IEdhbWVFdmVudFR5cGUuU1RPUF9TT1VORCl7XG4gICAgICAgICAgICAgICAgbGV0IHNvdW5kS2V5ID0gZXZlbnQuZGF0YS5nZXQoXCJrZXlcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9wU291bmQoc291bmRLZXkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLk1VVEVfQ0hBTk5FTCl7XG4gICAgICAgICAgICAgICAgdGhpcy5tdXRlQ2hhbm5lbChldmVudC5kYXRhLmdldChcImNoYW5uZWxcIikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBHYW1lRXZlbnRUeXBlLlVOTVVURV9DSEFOTkVMKXtcbiAgICAgICAgICAgICAgICB0aGlzLnVubXV0ZUNoYW5uZWwoZXZlbnQuZGF0YS5nZXQoXCJjaGFubmVsXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGVudW0gQXVkaW9DaGFubmVsVHlwZSB7XG4gICAgREVGQVVMVCA9IDAsXG4gICAgU0ZYID0gMSxcbiAgICBNVVNJQyA9IDIsXG4gICAgQ1VTVE9NXzEgPSAzLFxuICAgIENVU1RPTV8yID0gNCxcbiAgICBDVVNUT01fMyA9IDUsXG4gICAgQ1VTVE9NXzQgPSA2LFxuICAgIENVU1RPTV81ID0gNyxcbiAgICBDVVNUT01fNiA9IDgsXG4gICAgQ1VTVE9NXzcgPSA5LFxuICAgIENVU1RPTV84ID0gMTAsXG4gICAgQ1VTVE9NXzkgPSAxMSxcbn1cblxuZXhwb3J0IGNvbnN0IE1BWF9BVURJT19DSEFOTkVMUyA9IDEyOyIsImltcG9ydCB7IEdhbWVTdGF0ZSB9IGZyb20gXCIuLi8uLi9zaGF0dGVyZWRfc3dvcmQvc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL3NoYXR0ZXJlZF9zd29yZC9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCBUaW1lck1hbmFnZXIgZnJvbSBcIi4vVGltZXJNYW5hZ2VyXCI7XG5cbi8qKiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGltZXIgaW1wbGVtZW50cyBVcGRhdGVhYmxlIHtcblxuICAgIC8qKiBUaGUgY3VycmVudCBzdGF0ZSBvZiB0aGlzIHRpbWVyICovXG4gICAgcHJvdGVjdGVkIHN0YXRlOiBUaW1lclN0YXRlO1xuICAgIFxuICAgIC8qKiBUaGUgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHRoaXMgdGltZXIgZW5kcyAqL1xuICAgIHByb3RlY3RlZCBvbkVuZDogRnVuY3Rpb247XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdGhpcyB0aW1lciBzaG91bGQgbG9vcCAqL1xuICAgIHByb3RlY3RlZCBsb29wOiBib29sZWFuO1xuXG4gICAgLyoqIFRoZSB0b3RhbCBhbW91bnQgb2YgdGltZSB0aGlzIHRpbWVyIHJ1bnMgZm9yICovXG4gICAgcHJvdGVjdGVkIHRvdGFsVGltZTogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBhbW91bnQgb2YgdGltZSBsZWZ0IG9uIHRoZSBjdXJyZW50IHJ1biAqL1xuICAgIHByb3RlY3RlZCB0aW1lTGVmdDogbnVtYmVyO1xuXG4gICAgLyoqIFRoZSBudW1iZXIgb2YgdGltZXMgdGhpcyB0aW1lciBoYXMgYmVlbiBydW4gKi9cbiAgICBwcm90ZWN0ZWQgbnVtUnVuczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IodGltZTogbnVtYmVyLCBvbkVuZD86IEZ1bmN0aW9uLCBsb29wOiBib29sZWFuID0gZmFsc2Upe1xuICAgICAgICAvLyBSZWdpc3RlciB0aGlzIHRpbWVyXG4gICAgICAgIFRpbWVyTWFuYWdlci5nZXRJbnN0YW5jZSgpLmFkZFRpbWVyKHRoaXMpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy50b3RhbFRpbWUgPSB0aW1lO1xuICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gMDtcbiAgICAgICAgdGhpcy5vbkVuZCA9IG9uRW5kO1xuICAgICAgICB0aGlzLmxvb3AgPSBsb29wO1xuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgICAgICB0aGlzLm51bVJ1bnMgPSAwO1xuICAgIH1cblxuICAgIGlzU3RvcHBlZCgpe1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZSA9PT0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgIH1cblxuICAgIGlzUGF1c2VkKCl7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlID09PSBUaW1lclN0YXRlLlBBVVNFRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoaXMgdGltZXIgaGFzIGJlZW4gcnVuIGJlZm9yZVxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgaXQgaGFzIGJlZW4gcnVuIGF0IGxlYXN0IG9uY2UgKGFmdGVyIHRoZSBsYXRlc3QgcmVzZXQpLCBhbmQgZmFsc2Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgaGFzUnVuKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5udW1SdW5zID4gMDtcbiAgICB9XG5cbiAgICBzdGFydCh0aW1lPzogbnVtYmVyKXtcbiAgICAgICAgaWYodGltZSAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHRoaXMudG90YWxUaW1lID0gdGltZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5BQ1RJVkU7XG4gICAgICAgIHRoaXMudGltZUxlZnQgPSB0aGlzLnRvdGFsVGltZTtcbiAgICB9XG5cbiAgICAvKiogUmVzZXRzIHRoaXMgdGltZXIuIFNldHMgdGhlIHByb2dyZXNzIGJhY2sgdG8gemVybywgYW5kIHNldHMgdGhlIG51bWJlciBvZiBydW5zIGJhY2sgdG8gemVybyAqL1xuICAgIHJlc2V0KCl7XG4gICAgICAgIHRoaXMudGltZUxlZnQgPSB0aGlzLnRvdGFsVGltZTtcbiAgICAgICAgdGhpcy5udW1SdW5zID0gMDtcbiAgICB9XG5cbiAgICBwYXVzZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IFRpbWVyU3RhdGUuUEFVU0VEO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcil7XG4gICAgICAgIGlmKHRoaXMuc3RhdGUgPT09IFRpbWVyU3RhdGUuQUNUSVZFICYmIElucHV0V3JhcHBlci5nZXRTdGF0ZSgpID09PSBHYW1lU3RhdGUuR0FNSU5HKXtcbiAgICAgICAgICAgIHRoaXMudGltZUxlZnQgLT0gZGVsdGFUKjEwMDA7XG5cbiAgICAgICAgICAgIGlmKHRoaXMudGltZUxlZnQgPD0gMCl7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lTGVmdCA9IE1hdGhVdGlscy5jbGFtcExvdzAodGhpcy50aW1lTGVmdCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBlbmQoKXtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBzdGF0ZVxuICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5TVE9QUEVEO1xuICAgICAgICB0aGlzLm51bVJ1bnMgKz0gMTtcblxuICAgICAgICAvLyBDYWxsIHRoZSBlbmQgZnVuY3Rpb24gaWYgdGhlcmUgaXMgb25lXG4gICAgICAgIGlmKHRoaXMub25FbmQpe1xuICAgICAgICAgICAgdGhpcy5vbkVuZCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTG9vcCBpZiB3ZSB3YW50IHRvXG4gICAgICAgIGlmKHRoaXMubG9vcCl7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gVGltZXJTdGF0ZS5BQ1RJVkU7XG4gICAgICAgICAgICB0aGlzLnRpbWVMZWZ0ID0gdGhpcy50b3RhbFRpbWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0b1N0cmluZygpOiBzdHJpbmd7XG4gICAgICAgIHJldHVybiBcIlRpbWVyOiBcIiArIHRoaXMuc3RhdGUgKyBcIiAtIFRpbWUgTGVmdDogXCIgKyB0aGlzLnRpbWVMZWZ0ICsgXCJtcyBvZiBcIiArIHRoaXMudG90YWxUaW1lICsgXCJtc1wiO1xuICAgIH1cbn1cblxuZXhwb3J0IGVudW0gVGltZXJTdGF0ZSB7XG4gICAgQUNUSVZFID0gXCJBQ1RJVkVcIixcbiAgICBQQVVTRUQgPSBcIlBBVVNFRFwiLFxuICAgIFNUT1BQRUQgPSBcIlNUT1BQRURcIlxufSIsImltcG9ydCBVcGRhdGVhYmxlIGZyb20gXCIuLi9EYXRhVHlwZXMvSW50ZXJmYWNlcy9VcGRhdGVhYmxlXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4vVGltZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGltZXJNYW5hZ2VyIGltcGxlbWVudHMgVXBkYXRlYWJsZSB7XG5cbiAgICBwcm90ZWN0ZWQgdGltZXJzOiBBcnJheTxUaW1lcj47XG5cbiAgICBjb25zdHJ1Y3Rvcigpe1xuICAgICAgICB0aGlzLnRpbWVycyA9IG5ldyBBcnJheSgpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzdGF0aWMgaW5zdGFuY2U6IFRpbWVyTWFuYWdlcjtcblxuICAgIHN0YXRpYyBnZXRJbnN0YW5jZSgpOiBUaW1lck1hbmFnZXIge1xuICAgICAgICBpZighdGhpcy5pbnN0YW5jZSl7XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlID0gbmV3IFRpbWVyTWFuYWdlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgYWRkVGltZXIodGltZXI6IFRpbWVyKXtcbiAgICAgICAgdGhpcy50aW1lcnMucHVzaCh0aW1lcik7XG4gICAgfVxuXG4gICAgY2xlYXJUaW1lcnMoKXtcbiAgICAgICAgdGhpcy50aW1lcnMgPSBuZXcgQXJyYXkoKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy50aW1lcnMuZm9yRWFjaCh0aW1lciA9PiB0aW1lci51cGRhdGUoZGVsdGFUKSk7XG4gICAgfVxufSIsImltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4vTWF0aFV0aWxzXCI7XG5cbi8vIFRPRE86IFRoaXMgc2hvdWxkIGJlIG1vdmVkIHRvIHRoZSBkYXRhdHlwZXMgZm9sZGVyXG4vKipcbiAqIEEgQ29sb3IgdXRpbCBjbGFzcyB0aGF0IGtlZXBzIHRyYWNrIG9mIGNvbG9ycyBsaWtlIGEgdmVjdG9yLCBidXQgY2FuIGJlIGNvbnZlcnRlZCBpbnRvIGEgc3RyaW5nIGZvcm1hdFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xvciB7XG5cdC8qKiBUaGUgcmVkIHZhbHVlICovXG5cdHB1YmxpYyByOiBudW1iZXI7XG5cdC8qKiBUaGUgZ3JlZW4gdmFsdWUgKi9cblx0cHVibGljIGc6IG51bWJlcjtcblx0LyoqIFRoZSBibHVlIHZhbHVlICovXG5cdHB1YmxpYyBiOiBudW1iZXI7XG5cdC8qKiBUaGUgYWxwaGEgdmFsdWUgKi9cblx0cHVibGljIGE6IG51bWJlcjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBjb2xvclxuXHQgKiBAcGFyYW0gciBSZWRcblx0ICogQHBhcmFtIGcgR3JlZW5cblx0ICogQHBhcmFtIGIgQmx1ZVxuXHQgKiBAcGFyYW0gYSBBbHBoYVxuXHQgKi9cblx0Y29uc3RydWN0b3IocjogbnVtYmVyID0gMCwgZzogbnVtYmVyID0gMCwgYjogbnVtYmVyID0gMCwgYTogbnVtYmVyID0gMSl7XG4gICAgICAgIHRoaXMuciA9IHI7XG4gICAgICAgIHRoaXMuZyA9IGc7XG4gICAgICAgIHRoaXMuYiA9IGI7XG4gICAgICAgIHRoaXMuYSA9IGE7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBUcmFuc3BhcmVudCBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2JhKDAsIDAsIDAsIDApXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IFRSQU5TUEFSRU5UKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuXHR9XG5cdFxuXHQvKipcdFxuXHQgKiBSZWQgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMCwgMClcblx0ICovXG5cdHN0YXRpYyBnZXQgUkVEKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMCwgMCwgMSk7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBHcmVlbiBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMjU1LCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBHUkVFTigpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAyNTUsIDAsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogQmx1ZSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMCwgMjU1KVxuXHQgKi9cblx0c3RhdGljIGdldCBCTFVFKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDAsIDAsIDI1NSwgMSk7XG5cdH1cblxuXHQvKipcdFxuXHQgKiBZZWxsb3cgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMjU1LCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBZRUxMT1coKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMjU1LCAyNTUsIDAsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogTWFnZW50YSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMjU1LCAwLCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IE1BR0VOVEEoKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMjU1LCAwLCAyNTUsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogQ3lhbiBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMCwgMjU1LCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IENZQU4oKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoMCwgMjU1LCAyNTUsIDEpO1xuXHR9XG5cblx0LyoqXHRcblx0ICogV2hpdGUgY29sb3Jcblx0ICogQHJldHVybnMgcmdiKDI1NSwgMjU1LCAyNTUpXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IFdISVRFKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKDI1NSwgMjU1LCAyNTUsIDEpO1xuXHR9IFxuXG5cdC8qKlx0XG5cdCAqIEJsYWNrIGNvbG9yXG5cdCAqIEByZXR1cm5zIHJnYigwLCAwLCAwKVxuXHQgKi9cblx0c3RhdGljIGdldCBCTEFDSygpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigwLCAwLCAwLCAxKTtcblx0fVxuXG5cdC8qKlx0XG5cdCAqIE9yYW5nZSBjb2xvclxuXHQgKiBAcmV0dXJucyByZ2IoMjU1LCAxMDAsIDApXG5cdCAqL1xuXHRzdGF0aWMgZ2V0IE9SQU5HRSgpOiBDb2xvciB7XG5cdFx0cmV0dXJuIG5ldyBDb2xvcigyNTUsIDEwMCwgMCwgMSk7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGUgY29sb3IgdG8gdGhlIHZhbHVlcyBwcm92aWRlZFxuXHQgKiBAcGFyYW0gciBSZWRcblx0ICogQHBhcmFtIGcgR3JlZW5cblx0ICogQHBhcmFtIGIgQmx1ZVxuXHQgKiBAcGFyYW0gYSBBbHBoYVxuXHQgKi9cblx0c2V0KHI6IG51bWJlciwgZzogbnVtYmVyLCBiOiBudW1iZXIsIGE6IG51bWJlciA9IDEpOiB2b2lkIHtcblx0XHR0aGlzLnIgPSByO1xuXHRcdHRoaXMuZyA9IGc7XG5cdFx0dGhpcy5iID0gYjtcblx0XHR0aGlzLmEgPSBhO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgYSBuZXcgY29sb3Igc2xpZ2h0bHkgbGlnaHRlciB0aGFuIHRoZSBjdXJyZW50IGNvbG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IGxpZ2h0ZXIgQ29sb3Jcblx0ICovXG5cdGxpZ2h0ZW4oKTogQ29sb3Ige1xuXHRcdHJldHVybiBuZXcgQ29sb3IoTWF0aFV0aWxzLmNsYW1wKHRoaXMuciArIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5nICsgNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmIgKyA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuYSArIDEwLCAwLCAyNTUpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIGEgbmV3IGNvbG9yIHNsaWdodGx5IGRhcmtlciB0aGFuIHRoZSBjdXJyZW50IGNvbG9yXG5cdCAqIEByZXR1cm5zIEEgbmV3IGRhcmtlciBDb2xvclxuXHQgKi9cblx0ZGFya2VuKCk6IENvbG9yIHtcblx0XHRyZXR1cm4gbmV3IENvbG9yKE1hdGhVdGlscy5jbGFtcCh0aGlzLnIgLSA0MCwgMCwgMjU1KSwgTWF0aFV0aWxzLmNsYW1wKHRoaXMuZyAtIDQwLCAwLCAyNTUpLCBNYXRoVXRpbHMuY2xhbXAodGhpcy5iIC0gNDAsIDAsIDI1NSksIE1hdGhVdGlscy5jbGFtcCh0aGlzLmEgKyAxMCwgMCwgMjU1KSk7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoaXMgY29sb3IgYXMgYW4gYXJyYXlcblx0ICogQHJldHVybnMgW3IsIGcsIGIsIGFdXG5cdCAqL1xuXHR0b0FycmF5KCk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcblx0XHRyZXR1cm4gW3RoaXMuciwgdGhpcy5nLCB0aGlzLmIsIHRoaXMuYV07XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjb2xvciBhcyBhIHN0cmluZyBvZiB0aGUgZm9ybSAjUlJHR0JCXG5cdCAqIEByZXR1cm5zICNSUkdHQkJcblx0ICovXG5cdHRvU3RyaW5nKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwiI1wiICsgTWF0aFV0aWxzLnRvSGV4KHRoaXMuciwgMikgKyBNYXRoVXRpbHMudG9IZXgodGhpcy5nLCAyKSArIE1hdGhVdGlscy50b0hleCh0aGlzLmIsIDIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGNvbG9yIGFzIGEgc3RyaW5nIG9mIHRoZSBmb3JtIHJnYihyLCBnLCBiKVxuXHQgKiBAcmV0dXJucyByZ2IociwgZywgYilcblx0ICovXG5cdHRvU3RyaW5nUkdCKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIFwicmdiKFwiICsgdGhpcy5yLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmcudG9TdHJpbmcoKSArIFwiLCBcIiArIHRoaXMuYi50b1N0cmluZygpICsgXCIpXCI7XG5cdH1cblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY29sb3IgYXMgYSBzdHJpbmcgb2YgdGhlIGZvcm0gcmdiYShyLCBnLCBiLCBhKVxuXHQgKiBAcmV0dXJucyByZ2JhKHIsIGcsIGIsIGEpXG5cdCAqL1xuXHR0b1N0cmluZ1JHQkEoKTogc3RyaW5nIHtcblx0XHRpZih0aGlzLmEgPT09IDApe1xuXHRcdFx0cmV0dXJuIHRoaXMudG9TdHJpbmdSR0IoKTtcblx0XHR9XG5cdFx0cmV0dXJuIFwicmdiYShcIiArIHRoaXMuci50b1N0cmluZygpICsgXCIsIFwiICsgdGhpcy5nLnRvU3RyaW5nKCkgKyBcIiwgXCIgKyB0aGlzLmIudG9TdHJpbmcoKSArIFwiLCBcIiArIHRoaXMuYS50b1N0cmluZygpICtcIilcIlxuXHR9XG5cblx0LyoqXG5cdCAqIFR1cm5zIHRoaXMgY29sb3IgaW50byBhIGZsb2F0MzJBcnJheSBhbmQgY2hhbmdlcyBjb2xvciByYW5nZSB0byBbMC4wLCAxLjBdXG5cdCAqIEByZXR1cm5zIGEgRmxvYXQzMkFycmF5IGNvbnRhaW5pbmcgdGhlIGNvbG9yXG5cdCAqL1xuXHR0b1dlYkdMKCk6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0dGhpcy5yLzI1NSxcblx0XHRcdHRoaXMuZy8yNTUsXG5cdFx0XHR0aGlzLmIvMjU1LFxuXHRcdFx0dGhpcy5hXG5cdFx0XSk7XG5cdH1cblxuXHRzdGF0aWMgZnJvbVN0cmluZ0hleChzdHI6IHN0cmluZyk6IENvbG9yIHtcblx0XHRsZXQgaSA9IDA7XG5cdFx0aWYoc3RyLmNoYXJBdCgwKSA9PSBcIiNcIikgaSs9IDE7XG5cdFx0bGV0IHIgPSBNYXRoVXRpbHMuZnJvbUhleChzdHIuc3Vic3RyaW5nKGksIGkrMikpO1xuXHRcdGxldCBnID0gTWF0aFV0aWxzLmZyb21IZXgoc3RyLnN1YnN0cmluZyhpKzIsIGkrNCkpO1xuXHRcdGxldCBiID0gTWF0aFV0aWxzLmZyb21IZXgoc3RyLnN1YnN0cmluZyhpKzQsIGkrNikpO1xuXHRcdHJldHVybiBuZXcgQ29sb3IociwgZywgYik7XG5cdH1cbn0iLCIvLyBAaWdub3JlUGFnZVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFYXNlRnVuY3Rpb25zIHtcblxuICAgIHN0YXRpYyBlYXNlSW5PdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiAtKE1hdGguY29zKE1hdGguUEkgKiB4KSAtIDEpIC8gMjtcbiAgICB9XG5cbiAgICBzdGF0aWMgZWFzZU91dEluU2luZSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IC1NYXRoLmNvcyhNYXRoLlBJKih4ICsgMC41KSkvMiA6IC1NYXRoLmNvcyhNYXRoLlBJKih4IC0gMC41KSkvMiArIDE7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VPdXRTaW5lKHg6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoLnNpbigoeCAqIE1hdGguUEkpIC8gMik7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VJblNpbmUoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIDEgLSBNYXRoLmNvcygoeCAqIE1hdGguUEkpIC8gMik7IFxuICAgIH1cblxuICAgIHN0YXRpYyBlYXNlSW5PdXRRdWludCh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IDE2ICogeCAqIHggKiB4ICogeCAqIHggOiAxIC0gTWF0aC5wb3coLTIgKiB4ICsgMiwgNSkgLyAyOyAgICBcbiAgICB9XG5cbiAgICBzdGF0aWMgZWFzZUluT3V0UXVhZCh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4geCA8IDAuNSA/IDIgKiB4ICogeCA6IDEgLSBNYXRoLnBvdygtMiAqIHggKyAyLCAyKSAvIDI7XG4gICAgfVxuXG4gICAgc3RhdGljIGVhc2VPdXRJblF1YWQoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwLjUgPyB0aGlzLmVhc2VPdXRJbl9PdXRQb3coeCwgMikgOiB0aGlzLmVhc2VPdXRJbl9JblBvdyh4LCAyKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBlYXNlT3V0SW5fT3V0UG93KHg6IG51bWJlciwgcG93OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gMC41IC0gTWF0aC5wb3coLTIgKiB4ICsgMSwgcG93KSAvIDI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZWFzZU91dEluX0luUG93KHg6IG51bWJlciwgcG93OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gMC41ICsgTWF0aC5wb3coMiAqIHggLSAxLCBwb3cpIC8gMjtcbiAgICB9XG59XG5cbmV4cG9ydCBlbnVtIEVhc2VGdW5jdGlvblR5cGUge1xuICAgIC8vIFNJTkVcbiAgICBJTl9PVVRfU0lORSA9IFwiZWFzZUluT3V0U2luZVwiLFxuICAgIE9VVF9JTl9TSU5FID0gXCJlYXNlT3V0SW5TaW5lXCIsXG4gICAgSU5fU0lORSA9IFwiZWFzZUluU2luZVwiLFxuICAgIE9VVF9TSU5FID0gXCJlYXNlT3V0U2luZVwiLFxuXG4gICAgLy8gUVVBRFxuICAgIElOX09VVF9RVUFEID0gXCJlYXNlSW5PdXRRdWFkXCIsXG4gICAgT1VUX0lOX1FVQUQgPSBcImVhc2VPdXRJblF1YWRcIixcblxuICAgIC8vIFFVSU5UXG4gICAgSU5fT1VUX1FVSU5UID0gXCJlYXNlSW5PdXRRdWludFwiXG59IiwiaW1wb3J0IEdyYXBoIGZyb20gXCIuLi9EYXRhVHlwZXMvR3JhcGhzL0dyYXBoXCI7XG5pbXBvcnQgRWRnZU5vZGUgZnJvbSBcIi4uL0RhdGFUeXBlcy9HcmFwaHMvRWRnZU5vZGVcIjtcblxuLyoqIEEgY2xhc3MgdG8gcHJvdmlkZXMgc29tZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgZ3JhcGhzICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHcmFwaFV0aWxzIHtcblxuXHQvKipcblx0ICogQW4gaW1wbGVtZW50YXRpb24gb2YgRGppa3N0cmEncyBzaG9ydGVzdCBwYXRoIGFsZ29yaXRobSBiYXNlZCBvbiB0aGUgb25lIGRlc2NyaWJlZCBpbiBUaGUgQWxnb3JpdGhtIERlc2lnbiBNYW51YWwuXG5cdCAqIEBwYXJhbSBnIFRoZSBncmFwaFxuXHQgKiBAcGFyYW0gc3RhcnQgVGhlIG51bWJlciB0byBzdGFydCB0aGUgc2hvcnRlc3QgcGF0aCBmcm9tXG5cdCAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHBhcmVudCBvZiBlYWNoIG5vZGUgb2YgdGhlIEdyYXBoIGluIHRoZSBzaG9ydGVzdCBwYXRoLlxuXHQgKi9cblx0c3RhdGljIGRqaWtzdHJhKGc6IEdyYXBoLCBzdGFydDogbnVtYmVyKTogQXJyYXk8bnVtYmVyPiB7XG5cdFx0bGV0IGk6IG51bWJlcjtcdFx0Ly8gQ291bnRlclxuXHRcdGxldCBwOiBFZGdlTm9kZTtcdC8vIFBvaW50ZXIgdG8gZWRnZW5vZGVcblx0XHRsZXQgaW5UcmVlOiBBcnJheTxib29sZWFuPiA9IG5ldyBBcnJheShnLm51bVZlcnRpY2VzKTtcblx0XHRsZXQgZGlzdGFuY2U6IEFycmF5PG51bWJlcj4gPSBuZXcgQXJyYXkoZy5udW1WZXJ0aWNlcyk7XG5cdFx0bGV0IHBhcmVudDogQXJyYXk8bnVtYmVyPiA9IG5ldyBBcnJheShnLm51bVZlcnRpY2VzKTtcblx0XHRsZXQgdjogbnVtYmVyO1x0XHQvLyBDdXJyZW50IHZlcnRleCB0byBwcm9jZXNzXG5cdFx0bGV0IHc6IG51bWJlcjsgXHRcdC8vIENhbmRpZGF0ZSBmb3IgbmV4dCB2ZXJ0ZXhcblx0XHRsZXQgd2VpZ2h0OiBudW1iZXI7XHQvLyBFZGdlIHdlaWdodFxuXHRcdGxldCBkaXN0O1x0XHRcdC8vIEJlc3QgY3VycmVudCBkaXN0YW5jZSBmcm9tIHN0YXJ0XG5cblx0XHRmb3IoaSA9IDA7IGkgPCBnLm51bVZlcnRpY2VzOyBpKyspe1xuXHRcdFx0aW5UcmVlW2ldID0gZmFsc2U7XG5cdFx0XHRkaXN0YW5jZVtpXSA9IEluZmluaXR5O1xuXHRcdFx0cGFyZW50W2ldID0gLTE7XG5cdFx0fVxuXG5cdFx0ZGlzdGFuY2Vbc3RhcnRdID0gMDtcblx0XHR2ID0gc3RhcnQ7XG5cblx0XHR3aGlsZSghaW5UcmVlW3ZdKXtcblx0XHRcdGluVHJlZVt2XSA9IHRydWU7XG5cdFx0XHRwID0gZy5lZGdlc1t2XTtcblxuXHRcdFx0d2hpbGUocCAhPT0gbnVsbCl7XG5cdFx0XHRcdHcgPSBwLnk7XG5cdFx0XHRcdHdlaWdodCA9IHAud2VpZ2h0O1xuXG5cdFx0XHRcdGlmKGRpc3RhbmNlW3ddID4gZGlzdGFuY2Vbdl0gKyB3ZWlnaHQpe1xuXHRcdFx0XHRcdGRpc3RhbmNlW3ddID0gZGlzdGFuY2Vbdl0gKyB3ZWlnaHQ7XG5cdFx0XHRcdFx0cGFyZW50W3ddID0gdjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHAgPSBwLm5leHQ7XG5cdFx0XHR9XG5cblx0XHRcdHYgPSAwO1xuXG5cdFx0XHRkaXN0ID0gSW5maW5pdHk7XG5cblx0XHRcdGZvcihpID0gMDsgaSA8PSBnLm51bVZlcnRpY2VzOyBpKyspe1xuXHRcdFx0XHRpZighaW5UcmVlW2ldICYmIGRpc3QgPiBkaXN0YW5jZVtpXSl7XG5cdFx0XHRcdFx0ZGlzdCA9IGRpc3RhbmNlO1xuXHRcdFx0XHRcdHYgPSBpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHBhcmVudDtcblxuXHR9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uL0RhdGFUeXBlcy9WZWMyXCI7XG5cbi8qKiBBIGNsYXNzIGNvbnRhaW5pbmcgc29tZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgbWF0aCBvcGVyYXRpb25zICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNYXRoVXRpbHMge1xuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHNpZ24gb2YgdGhlIHZhbHVlIHByb3ZpZGVkXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGV4dHJhY3QgdGhlIHNpZ24gZnJvbVxuICAgICAqIEByZXR1cm5zIC0xIGlmIHRoZSBudW1iZXIgaXMgbGVzcyB0aGFuIDAsIDEgb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc3RhdGljIHNpZ24oeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCAwID8gLTEgOiAxO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgd2hldGhlciBvciBub3QgeCBpcyBiZXR3ZWVuIGEgYW5kIGJcbiAgICAgKiBAcGFyYW0gYSBUaGUgbWluIGJvdW5kXG4gICAgICogQHBhcmFtIGIgVGhlIG1heCBib3VuZFxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBjaGVja1xuICAgICAqIEBwYXJhbSBleGNsdXNpdmUgV2hldGhlciBvciBub3QgYSBhbmQgYiBhcmUgZXhjbHVzaXZlIGJvdW5kc1xuICAgICAqIEByZXR1cm5zIFRydWUgaWYgeCBpcyBiZXR3ZWVuIGEgYW5kIGIsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqL1xuICAgIHN0YXRpYyBiZXR3ZWVuKGE6IG51bWJlciwgYjogbnVtYmVyLCB4OiBudW1iZXIsIGV4Y2x1c2l2ZT86IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICAgICAgaWYoZXhjbHVzaXZlKXtcbiAgICAgICAgICAgIHJldHVybiAoYSA8IHgpICYmICh4IDwgYik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKGEgPD0geCkgJiYgKHggPD0gYik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIHZhbHVlIHggdG8gdGhlIHJhbmdlIFttaW4sIG1heF0sIHJvdW5kaW5nIHVwIG9yIGRvd24gaWYgbmVlZGVkXG4gICAgICogQHBhcmFtIHggVGhlIHZhbHVlIHRvIGJlIGNsYW1wZWRcbiAgICAgKiBAcGFyYW0gbWluIFRoZSBtaW4gb2YgdGhlIHJhbmdlXG4gICAgICogQHBhcmFtIG1heCBUaGUgbWF4IG9mIHRoZSByYW5nZVxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGJldHdlZW4gbWluIGFuZCBtYXgsIG9yIG1pbi9tYXggaWYgaXQgZXhjZWVkcyB0aGVpciBib3VuZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXAoeDogbnVtYmVyLCBtaW46IG51bWJlciwgbWF4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZih4IDwgbWluKSByZXR1cm4gbWluO1xuICAgICAgICBpZih4ID4gbWF4KSByZXR1cm4gbWF4O1xuICAgICAgICByZXR1cm4geDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgdGhlIHZhbHVlIHggdG8gdGhlIHJhbmdlIGJldHdlZW4gMCBhbmQgMVxuICAgICAqIEBwYXJhbSB4IFRoZSB2YWx1ZSB0byBiZSBjbGFtcGVkXG4gICAgICogQHJldHVybnMgeCwgaWYgaXQgaXMgYmV0d2VlbiAwIGFuZCAxLCBvciAwLzEgaWYgaXQgZXhjZWVkcyB0aGVpciBib3VuZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXAwMSh4OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aFV0aWxzLmNsYW1wKHgsIDAsIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyB0aGUgbG93ZXIgZW5kIG9mIHRoZSB2YWx1ZSBvZiB4IHRvIHRoZSByYW5nZSB0byBtaW5cbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEBwYXJhbSBtaW4gVGhlIG1pbmltdW0gYWxsb3dlZCB2YWx1ZSBvZiB4XG4gICAgICogQHJldHVybnMgeCwgaWYgaXQgaXMgZ3JlYXRlciB0aGFuIG1pbiwgb3RoZXJ3aXNlIG1pblxuICAgICAqL1xuICAgIHN0YXRpYyBjbGFtcExvdyh4OiBudW1iZXIsIG1pbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHggPCBtaW4gPyBtaW4gOiB4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsYW1wcyB0aGUgbG93ZXIgZW5kIG9mIHRoZSB2YWx1ZSBvZiB4IHRvIHplcm9cbiAgICAgKiBAcGFyYW0geCBUaGUgdmFsdWUgdG8gYmUgY2xhbXBlZFxuICAgICAqIEByZXR1cm5zIHgsIGlmIGl0IGlzIGdyZWF0ZXIgdGhhbiAwLCBvdGhlcndpc2UgMFxuICAgICAqL1xuICAgIHN0YXRpYyBjbGFtcExvdzAoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIE1hdGhVdGlscy5jbGFtcExvdyh4LCAwKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2xhbXBNYWduaXR1ZGUodjogVmVjMiwgbTogbnVtYmVyKTogVmVjMiB7XG4gICAgICAgIGlmKHYubWFnU3EoKSA+IG0qbSl7XG4gICAgICAgICAgICByZXR1cm4gdi5zY2FsZVRvKG0pO1xuICAgICAgICB9IGVsc2V7XG4gICAgICAgICAgICByZXR1cm4gdjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBjaGFuZ2VSYW5nZSh4OiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlciwgbmV3TWluOiBudW1iZXIsIG5ld01heDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGVycChuZXdNaW4sIG5ld01heCwgdGhpcy5pbnZMZXJwKG1pbiwgbWF4LCB4KSk7XG4gICAgfVxuXG4gICAgLyoqXG5cdCAqIExpbmVhciBJbnRlcnBvbGF0aW9uXG5cdCAqIEBwYXJhbSBhIFRoZSBmaXJzdCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcblx0ICogQHBhcmFtIGIgVGhlIHNlY29uZCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcblx0ICogQHBhcmFtIHQgVGhlIHRpbWUgd2UgYXJlIGludGVycG9sYXRpbmcgdG9cbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgYmV0d2VlbiBhIGFuZCBiIGF0IHRpbWUgdFxuXHQgKi9cblx0c3RhdGljIGxlcnAoYTogbnVtYmVyLCBiOiBudW1iZXIsIHQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBhICsgdCAqIChiIC0gYSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW52ZXJzZSBMaW5lYXIgSW50ZXJwb2xhdGlvbi4gRmluZHMgdGhlIHRpbWUgYXQgd2hpY2ggYSB2YWx1ZSBiZXR3ZWVuIGEgYW5kIGIgd291bGQgb2NjdXJcbiAgICAgKiBAcGFyYW0gYSBUaGUgZmlyc3QgdmFsdWUgZm9yIHRoZSBpbnRlcnBvbGF0aW9uIGJvdW5kXG4gICAgICogQHBhcmFtIGIgVGhlIHNlY29uZCB2YWx1ZSBmb3IgdGhlIGludGVycG9sYXRpb24gYm91bmRcbiAgICAgKiBAcGFyYW0gdmFsdWUgVGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgKiBAcmV0dXJucyBUaGUgdGltZSBhdCB3aGljaCB0aGUgY3VycmVudCB2YWx1ZSBvY2N1cnMgYmV0d2VlbiBhIGFuZCBiXG4gICAgICovXG4gICAgc3RhdGljIGludkxlcnAoYTogbnVtYmVyLCBiOiBudW1iZXIsIHZhbHVlOiBudW1iZXIpe1xuICAgICAgICByZXR1cm4gKHZhbHVlIC0gYSkvKGIgLSBhKTtcbiAgICB9XG4gICAgXG4gICAgLyoqXG4gICAgICogQ3V0cyBvZmYgZGVjaW1hbCBwb2ludHMgb2YgYSBudW1iZXIgYWZ0ZXIgYSBzcGVjaWZpZWQgcGxhY2VcbiAgICAgKiBAcGFyYW0gbnVtIFRoZSBudW1iZXIgdG8gZmxvb3JcbiAgICAgKiBAcGFyYW0gcGxhY2UgVGhlIGxhc3QgZGVjaW1hbCBwbGFjZSBvZiB0aGUgbmV3IG51bWJlclxuICAgICAqIEByZXR1cm5zIFRoZSBmbG9vcmVkIG51bWJlclxuICAgICAqL1xuICAgIHN0YXRpYyBmbG9vclRvUGxhY2UobnVtOiBudW1iZXIsIHBsYWNlOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICBpZihwbGFjZSA9PT0gMCl7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihudW0pO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZhY3RvciA9IDEwO1xuICAgICAgICB3aGlsZShwbGFjZSA+IDEpe1xuICAgICAgICAgICAgZmFjdG9yICE9IDEwO1xuICAgICAgICAgICAgcGxhY2UtLTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bSpmYWN0b3IpL2ZhY3RvcjtcblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBudW1iZXIgZnJvbSBhIGhleCBzdHJpbmdcbiAgICAgKiBAcGFyYW0gc3RyIHRoZSBzdHJpbmcgY29udGFpbmluZyB0aGUgaGV4IG51bWJlclxuICAgICAqIEByZXR1cm5zIHRoZSBudW1iZXIgaW4gZGVjaW1hbCByZXByZXNlbnRlZCBieSB0aGUgaGV4IHN0cmluZ1xuICAgICAqL1xuICAgIHN0YXRpYyBmcm9tSGV4KHN0cjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHN0ciwgMTYpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG51bWJlciBhcyBhIGhleGFkZWNpbWFsXG4gICAgICogQHBhcmFtIG51bSBUaGUgbnVtYmVyIHRvIGNvbnZlcnQgdG8gaGV4XG4gICAgICogQHBhcmFtIG1pbkxlbmd0aCBUaGUgbGVuZ3RoIG9mIHRoZSByZXR1cm5lZCBoZXggc3RyaW5nIChhZGRzIHplcm8gcGFkZGluZyBpZiBuZWVkZWQpXG4gICAgICogQHJldHVybnMgVGhlIGhleCByZXByZXNlbnRhdGlvbiBvZiB0aGUgbnVtYmVyIGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgc3RhdGljIHRvSGV4KG51bTogbnVtYmVyLCBtaW5MZW5ndGg6IG51bWJlciA9IG51bGwpOiBzdHJpbmcge1xuICAgICAgICBsZXQgZmFjdG9yID0gMTtcbiAgICAgICAgd2hpbGUoZmFjdG9yKjE2IDwgbnVtKXtcbiAgICAgICAgICAgIGZhY3RvciAqPSAxNjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaGV4U3RyID0gXCJcIjtcbiAgICAgICAgd2hpbGUoZmFjdG9yID49IDEpe1xuICAgICAgICAgICAgbGV0IGRpZ2l0ID0gTWF0aC5mbG9vcihudW0vZmFjdG9yKTtcbiAgICAgICAgICAgIGhleFN0ciArPSBNYXRoVXRpbHMudG9IZXhEaWdpdChkaWdpdCk7XG4gICAgICAgICAgICBudW0gLT0gZGlnaXQgKiBmYWN0b3I7XG4gICAgICAgICAgICBmYWN0b3IgLz0gMTY7XG5cdFx0fVxuXHRcdFxuXHRcdGlmKG1pbkxlbmd0aCAhPT0gbnVsbCl7XG5cdFx0XHR3aGlsZShoZXhTdHIubGVuZ3RoIDwgbWluTGVuZ3RoKXtcblx0XHRcdFx0aGV4U3RyID0gXCIwXCIgKyBoZXhTdHI7XG5cdFx0XHR9XG5cdFx0fVxuXG4gICAgICAgIHJldHVybiBoZXhTdHI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYSBkaWdpdCB0byBoZXhhZGVjaW1hbC4gSW4gdGhpcyBjYXNlLCBhIGRpZ2l0IGlzIGJldHdlZW4gMCBhbmQgMTUgaW5jbHVzaXZlXG4gICAgICogQHBhcmFtIG51bSBUaGUgZGlnaXQgdG8gY29udmVydCB0byBoZXhhZGVjaW1hbFxuICAgICAqIEByZXR1cm5zIFRoZSBoZXggcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpZ2l0IGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgc3RhdGljIHRvSGV4RGlnaXQobnVtOiBudW1iZXIpOiBzdHJpbmcge1xuICAgICAgICBpZihudW0gPCAxMCl7XG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIG51bTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDY1ICsgbnVtIC0gMTApO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuL0NvbG9yXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuL01hdGhVdGlsc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZW5kZXJpbmdVdGlscyB7XG5cdHN0YXRpYyB0b1dlYkdMQ29vcmRzKHBvaW50OiBWZWMyLCBvcmlnaW46IFZlYzIsIHdvcmxkU2l6ZTogVmVjMik6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKHBvaW50LngsIG9yaWdpbi54LCBvcmlnaW4ueCArIHdvcmxkU2l6ZS54LCAtMSwgMSksXG5cdFx0XHRNYXRoVXRpbHMuY2hhbmdlUmFuZ2UocG9pbnQueSwgb3JpZ2luLnksIG9yaWdpbi55ICsgd29ybGRTaXplLnksIDEsIC0xKVxuXHRcdF0pO1xuXHR9XG5cblx0c3RhdGljIHRvV2ViR0xTY2FsZShzaXplOiBWZWMyLCB3b3JsZFNpemU6IFZlYzIpOiBGbG9hdDMyQXJyYXkge1xuXHRcdHJldHVybiBuZXcgRmxvYXQzMkFycmF5KFtcblx0XHRcdDIqc2l6ZS54L3dvcmxkU2l6ZS54LFxuXHRcdFx0MipzaXplLnkvd29ybGRTaXplLnksXG5cdFx0XSk7XG5cdH1cblxuXHRzdGF0aWMgdG9XZWJHTENvbG9yKGNvbG9yOiBDb2xvcik6IEZsb2F0MzJBcnJheSB7XG5cdFx0cmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuXHRcdFx0TWF0aFV0aWxzLmNoYW5nZVJhbmdlKGNvbG9yLnIsIDAsIDI1NSwgMCwgMSksXG5cdFx0XHRNYXRoVXRpbHMuY2hhbmdlUmFuZ2UoY29sb3IuZywgMCwgMjU1LCAwLCAxKSxcblx0XHRcdE1hdGhVdGlscy5jaGFuZ2VSYW5nZShjb2xvci5iLCAwLCAyNTUsIDAsIDEpLFxuXHRcdFx0Y29sb3IuYVxuXHRcdF0pO1xuXHR9XG59IiwiLyoqIFNvbWUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIGRlYWxpbmcgd2l0aCBzdHJpbmdzICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTdHJpbmdVdGlscyB7XG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgdGhlIHBhdGggZnJvbSBhIGZpbGVwYXRoIHRoYXQgaW5jbHVkZXMgdGhlIGZpbGVcbiAgICAgKiBAcGFyYW0gZmlsZVBhdGggdGhlIGZpbGVwYXRoIHRvIGV4dHJhY3QgdGhlIHBhdGggZnJvbVxuICAgICAqIEByZXR1cm5zIFRoZSBwYXRoIHBvcnRpb24gb2YgdGhlIGZpbGVwYXRoIHByb3ZpZGVkXG4gICAgICovXG4gICAgc3RhdGljIGdldFBhdGhGcm9tRmlsZVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGxldCBzcGxpdFBhdGggPSBmaWxlUGF0aC5zcGxpdChcIi9cIik7XG4gICAgICAgIHNwbGl0UGF0aC5wb3AoKTtcbiAgICAgICAgc3BsaXRQYXRoLnB1c2goXCJcIik7XG4gICAgICAgIHJldHVybiBzcGxpdFBhdGguam9pbihcIi9cIik7XG4gICAgfVxufSIsIlxuaW1wb3J0IEdhbWUgZnJvbSBcIi4vV29sZmllMkQvTG9vcC9HYW1lXCI7XG5pbXBvcnQgTWFpbk1lbnUgZnJvbSBcIi4vc2hhdHRlcmVkX3N3b3JkL1NjZW5lcy9NYWluTWVudVwiO1xuaW1wb3J0IFJlZ2lzdHJ5TWFuYWdlciBmcm9tIFwiLi9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyeU1hbmFnZXJcIjtcbmltcG9ydCBXZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5IGZyb20gXCIuL3NoYXR0ZXJlZF9zd29yZC9SZWdpc3RyeS9XZWFwb25SZWdpc3RyeVwiO1xuaW1wb3J0IFdlYXBvblR5cGVSZWdpc3RyeSBmcm9tIFwiLi9zaGF0dGVyZWRfc3dvcmQvUmVnaXN0cnkvV2VhcG9uVHlwZVJlZ2lzdHJ5XCI7XG5pbXBvcnQgU3BsYXNoU2NyZWVuIGZyb20gXCIuL3NoYXR0ZXJlZF9zd29yZC9TY2VuZXMvU3BsYXNoU2NyZWVuXCI7XG4vLyBUaGUgbWFpbiBmdW5jdGlvbiBpcyB5b3VyIGVudHJ5cG9pbnQgaW50byBXb2xmaWUyRC4gU3BlY2lmeSB5b3VyIGZpcnN0IHNjZW5lIGFuZCBhbnkgb3B0aW9ucyBoZXJlLlxuKGZ1bmN0aW9uIG1haW4oKXtcbiAgICAvLyBSdW4gYW55IHRlc3RzXG4gICAgcnVuVGVzdHMoKTtcblxuICAgIC8vIFNldCB1cCBvcHRpb25zIGZvciBvdXIgZ2FtZVxuICAgIGxldCBvcHRpb25zID0ge1xuICAgICAgICBjYW52YXNTaXplOiB7eCA6IDEyODAsIHk6NzIwfSxcbiAgICAgICAgLy9jYW52YXNTaXplOiB7eDogd2luZG93LmlubmVyV2lkdGgsIHk6IHdpbmRvdy5pbm5lckhlaWdodH0sICAgICAgICAgIC8vIFRoZSBzaXplIG9mIHRoZSBnYW1lXG4gICAgICAgIGNsZWFyQ29sb3I6IHtyOiAwLCBnOiAwLCBiOiAwfSwgICAvLyBUaGUgY29sb3IgdGhlIGdhbWUgY2xlYXJzIHRvXG4gICAgICAgIGlucHV0czogW1xuICAgICAgICAgICAge25hbWU6IFwibGVmdFwiLCBrZXlzOiBbXCJhXCIsIFwiYXJyb3dsZWZ0XCJdfSwgICAgLy9UT0RPIC0gYWRkIGFycm93IGtleXNcbiAgICAgICAgICAgIHtuYW1lOiBcInJpZ2h0XCIsIGtleXM6IFtcImRcIiwgXCJhcnJvd3JpZ2h0XCJdfSxcbiAgICAgICAgICAgIHtuYW1lOiBcInVwXCIsIGtleXM6IFtcIndcIiwgXCJhcnJvd3VwXCJdfSxcbiAgICAgICAgICAgIHtuYW1lOiBcImRvd25cIiwga2V5czogW1wic1wiLCBcImFycm93ZG93blwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJqdW1wXCIsIGtleXM6IFtcInpcIiwgXCJzcGFjZVwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJhdHRhY2tcIiwga2V5czogW1wialwiLFwieFwiLFwiZW50ZXJcIl19LCAgXG4gICAgICAgICAgICB7bmFtZTogXCJkYXNoXCIsIGtleXM6IFtcImtcIixcImNcIl19LCAgICAvL1xuICAgICAgICAgICAge25hbWU6IFwic2tpbGxcIiwga2V5czogW1wibFwiLFwidlwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJpbnZlbnRvcnlcIiwga2V5czogW1wiaVwiLFwiYlwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJwYXVzZVwiLCBrZXlzOiBbXCJlc2NhcGVcIl19LCAgICBcbiAgICAgICAgICAgIHtuYW1lOiBcInRhYlwiLCBrZXlzOiBbXCJ0YWJcIl19LFxuICAgICAgICAgICAge25hbWU6IFwiYnVmZjFcIiwga2V5czogW1wiMVwiXX0sXG4gICAgICAgICAgICB7bmFtZTogXCJidWZmMlwiLCBrZXlzOiBbXCIyXCJdfSxcbiAgICAgICAgICAgIHtuYW1lOiBcImJ1ZmYzXCIsIGtleXM6IFtcIjNcIl19XG4gICAgICAgIF0sXG4gICAgICAgIHVzZVdlYkdMOiBmYWxzZSwgICAgICAgICAgICAgICAgICAgICAgICAvLyBUZWxsIHRoZSBnYW1lIHdlIHdhbnQgdG8gdXNlIHdlYmdsXG4gICAgICAgIHNob3dEZWJ1ZzogZmFsc2UgICAgICAgICAgICAgICAgICAgICAgLy8gV2hldGhlciB0byBzaG93IGRlYnVnIG1lc3NhZ2VzLiBZb3UgY2FuIGNoYW5nZSB0aGlzIHRvIHRydWUgaWYgeW91IHdhbnRcbiAgICB9XG5cblxuICAgIC8vIFNldCB1cCBjdXN0b20gcmVnaXN0cmllc1xuICAgIGxldCB3ZWFwb25UZW1wbGF0ZVJlZ2lzdHJ5ID0gbmV3IFdlYXBvblRlbXBsYXRlUmVnaXN0cnkoKTtcbiAgICBSZWdpc3RyeU1hbmFnZXIuYWRkQ3VzdG9tUmVnaXN0cnkoXCJ3ZWFwb25UZW1wbGF0ZXNcIiwgd2VhcG9uVGVtcGxhdGVSZWdpc3RyeSk7XG4gICAgXG4gICAgbGV0IHdlYXBvblR5cGVSZWdpc3RyeSA9IG5ldyBXZWFwb25UeXBlUmVnaXN0cnkoKTtcbiAgICBSZWdpc3RyeU1hbmFnZXIuYWRkQ3VzdG9tUmVnaXN0cnkoXCJ3ZWFwb25UeXBlc1wiLCB3ZWFwb25UeXBlUmVnaXN0cnkpO1xuXG4gICAgLy8gQ3JlYXRlIGEgZ2FtZSB3aXRoIHRoZSBvcHRpb25zIHNwZWNpZmllZFxuICAgIGNvbnN0IGdhbWUgPSBuZXcgR2FtZShvcHRpb25zKTtcblxuICAgIC8vIFN0YXJ0IG91ciBnYW1lXG4gICAgZ2FtZS5zdGFydChTcGxhc2hTY3JlZW4sIHt9KTsgICBcbiAgICAvL1RPRE8gLSBjaGFuZ2UgdG8gc3BsYXNoIHNjcmVlbiBvbmNlIGF2YWlsYWJsZVxuICAgIC8vZ2FtZS5zdGFydChTcGxhc2hTY3JlZW4se30pO1xufSkoKTtcblxuZnVuY3Rpb24gcnVuVGVzdHMoKXt9OyIsImltcG9ydCBTdGF0ZU1hY2hpbmVBSSBmcm9tIFwiLi4vLi4vV29sZmllMkQvQUkvU3RhdGVNYWNoaW5lQUlcIjtcbmltcG9ydCBBQUJCIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuL0JhdHRsZXJBSVwiO1xuXG5pbXBvcnQgUGF0cm9sIGZyb20gXCIuL0VuZW15U3RhdGVzL1BhdHJvbFwiO1xuaW1wb3J0IEFsZXJ0IGZyb20gXCIuL0VuZW15U3RhdGVzL0FsZXJ0XCI7XG5pbXBvcnQgU2xpbWVBdHRhY2sgZnJvbSBcIi4vRW5lbXlTdGF0ZXMvU2xpbWVBdHRhY2tcIjtcbmltcG9ydCB7IEdhbWVTdGF0ZSwgU3RhdHVzZXMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcblxuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcblxuaW1wb3J0IHsgUGxheWVyX0V2ZW50cyB9IGZyb20gXCIuLi9zd29yZF9lbnVtc1wiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1RpbWluZy9UaW1lclwiO1xuaW1wb3J0IFBsYXllckNvbnRyb2xsZXIgZnJvbSBcIi4uL1BsYXllci9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgUmVjdCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUmVjdFwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRW5lbXlBSSBleHRlbmRzIFN0YXRlTWFjaGluZUFJIGltcGxlbWVudHMgQmF0dGxlckFJIHtcbiAgICAvKiogVGhlIG93bmVyIG9mIHRoaXMgQUkgKi9cbiAgICBvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cbiAgICAvKiogVGhlIHRvdGFsIHBvc3NpYmxlIGFtb3VudCBvZiBoZWFsdGggdGhpcyBlbnRpdHkgaGFzICovXG4gICAgbWF4SGVhbHRoOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIGN1cnJlbnQgYW1vdW50IG9mIGhlYWx0aCB0aGlzIGVudGl0eSBoYXMgKi9cbiAgICBDVVJSRU5UX0hQOiBudW1iZXI7XG5cbiAgICAvKiogVGhlIGRlZmF1bHQgbW92ZW1lbnQgc3BlZWQgb2YgdGhpcyBBSSAqL1xuICAgIHNwZWVkOiBudW1iZXIgPSAyMDtcblxuICAgIG1heFNwZWVkOiBudW1iZXIgPSA0MDtcblxuICAgIC8qKiBBIHJlZmVyZW5jZSB0byB0aGUgcGxheWVyIG9iamVjdCAqL1xuICAgIHBsYXllcjogR2FtZU5vZGU7XG5cbiAgICAvLyBUaGUgY3VycmVudCBrbm93biBwb3NpdGlvbiBvZiB0aGUgcGxheWVyXG4gICAgcGxheWVyUG9zOiBWZWMyO1xuXG4gICAgdGlsZW1hcDogT3J0aG9nb25hbFRpbGVtYXA7XG5cbiAgICB2ZWxvY2l0eTogVmVjMiA9IFZlYzIuWkVSTztcblxuICAgIGRpcmVjdGlvbjogbnVtYmVyOyAvLzEgZm9yIHJpZ2h0LCAtMSBmb3IgbGVmdFxuXG4gICAgZXhwX3ZhbDogbnVtYmVyID0gMTAwOyAvL2V4cCB2YWx1ZSB0byBnaXZlIHBsYXllciB3aGVuIHRoaXMgZGllc1xuXG4gICAgcG9pc29uVGltZXIgOiBUaW1lcjtcbiAgICBwb2lzb25Db3VudGVyIDogbnVtYmVyID0gMDtcblxuICAgIGJ1cm5UaW1lciA6IFRpbWVyIDtcbiAgICBidXJuQ291bnRlciA6IG51bWJlciA9MDtcblxuICAgIGJsZWVkVGltZXIgOiBUaW1lcjtcbiAgICBibGVlZENvdW50ZXIgOm51bWJlciA9IDA7XG5cbiAgICBoZWFsdGhCYXI6IFJlY3Q7XG4gICAgcG9pc29uU3RhdDogU3ByaXRlO1xuICAgIGJ1cm5TdGF0OiBTcHJpdGU7XG4gICAgYmxlZWRTdGF0OiBTcHJpdGU7XG5cbiAgICBhdHRhY2tUaW1lciA6IFRpbWVyO1xuICAgIGlzQXR0YWtpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBkYW1hZ2VUaW1lcjogVGltZXI7XG5cblxuICAgIGluaXRpYWxpemVBSShvd25lcjogQW5pbWF0ZWRTcHJpdGUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHsgXG4gICAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcblxuICAgICAgICAvL2FkZCBzdGF0ZXNcbiAgICAgICAgIC8vIFBhdHJvbCBtb2RlXG4gICAgICAgIHRoaXMuYWRkU3RhdGUoRW5lbXlTdGF0ZXMuUEFUUk9MLCBuZXcgUGF0cm9sKHRoaXMsIG93bmVyKSk7XG4gICAgICAgIHRoaXMuYWRkU3RhdGUoRW5lbXlTdGF0ZXMuQUxFUlQsIG5ldyBBbGVydCh0aGlzLCBvd25lcikpO1xuICAgICAgICB0aGlzLmFkZFN0YXRlKEVuZW15U3RhdGVzLkFUVEFDSywgbmV3IFNsaW1lQXR0YWNrKHRoaXMsIG93bmVyKSk7XG4gICAgICAgIFxuICAgICAgICB0aGlzLm1heEhlYWx0aCA9IG9wdGlvbnMuaGVhbHRoO1xuXG4gICAgICAgIHRoaXMuQ1VSUkVOVF9IUCA9IG9wdGlvbnMuaGVhbHRoO1xuXG4gICAgICAgIHRoaXMucGxheWVyID0gb3B0aW9ucy5wbGF5ZXI7XG5cbiAgICAgICAgdGhpcy5leHBfdmFsID0gb3B0aW9ucy5leHA7XG5cbiAgICAgICAgLy9UT0RPIC0gZ2V0IGNvcnJlY3QgdGlsZW1hcFxuICAgICAgICB0aGlzLnRpbGVtYXAgPSA8T3J0aG9nb25hbFRpbGVtYXA+dGhpcy5vd25lci5nZXRTY2VuZSgpLmdldExheWVyKFwiV2FsbFwiKS5nZXRJdGVtcygpWzBdO1xuICAgICAgICAvLyBJbml0aWFsaXplIHRvIHRoZSBkZWZhdWx0IHN0YXRlXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZShFbmVteVN0YXRlcy5QQVRST0wpO1xuXG4gICAgICAgIHRoaXMuZGlyZWN0aW9uID0gMTsgLy9kZWZhdWx0IG1vdmluZyB0byB0aGUgcmlnaHRcblxuICAgICAgICAvL1RPRE8gLSBkb3RzIGV2ZXJ5IDEgc2VjPyBjYW4gY2hhbmdlXG4gICAgICAgIHRoaXMuYnVyblRpbWVyID0gbmV3IFRpbWVyKDEwMDApO1xuICAgICAgICB0aGlzLmJsZWVkVGltZXIgPSBuZXcgVGltZXIoMTAwMCk7XG4gICAgICAgIHRoaXMucG9pc29uVGltZXIgPSBuZXcgVGltZXIoMTAwMCk7XG5cbiAgICAgICAgdGhpcy5hdHRhY2tUaW1lciA9IG5ldyBUaW1lcigyNTAwKTtcbiAgICAgICAgdGhpcy5kYW1hZ2VUaW1lciA9IG5ldyBUaW1lcig0MDApO1xuICAgIH1cblxuICAgIGRhbWFnZShkYW1hZ2U6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBlbmVteSBhbHJlYWR5IGRlYWQsIGRvIG5vdCBzZW5kIG5ldyBldmVudFxuICAgICAgICBpZiAodGhpcy5DVVJSRU5UX0hQIDw9IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhkYW1hZ2UgK1wiIGRhbWFnZSB0YWtlbiwgXCIrdGhpcy5DVVJSRU5UX0hQK1wiIGhwIGxlZnRcIik7XG4gICAgICAgIHRoaXMuQ1VSUkVOVF9IUCAtPSBkYW1hZ2U7XG4gICAgICAgIC8vVE9ETyAtXG4gICAgICAgIGlmICghdGhpcy5pc0F0dGFraW5nKSB7XG4gICAgICAgICAgICB0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5KFwiSFVSVFwiLGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgY29uc29sZS5sb2coZGFtYWdlICtcIiBkYW1hZ2UgdGFrZW4sIFwiK3RoaXMuQ1VSUkVOVF9IUCtcIiBocCBsZWZ0XCIpO1xuXG4gICAgICAgIC8vIElmIGhlYWx0aCBnb2VzIGJlbG93IDAsIGRpc2FibGUgQUkgYW5kIGZpcmUgZW5lbXlEaWVkIGV2ZW50XG4gICAgICAgIGlmICh0aGlzLkNVUlJFTlRfSFAgPD0gMCkge1xuICAgICAgICAgICAgdGhpcy5vd25lci5zZXRBSUFjdGl2ZShmYWxzZSwge30pO1xuICAgICAgICAgICAgdGhpcy5vd25lci5pc0NvbGxpZGFibGUgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMub3duZXIudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGVhbHRoQmFyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMucG9pc29uU3RhdCkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9pc29uU3RhdC5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wb2lzb25TdGF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuYnVyblN0YXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmJ1cm5TdGF0LmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLmJ1cm5TdGF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuYmxlZWRTdGF0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ibGVlZFN0YXQuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuYmxlZWRTdGF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuRU5FTVlfS0lMTEVELCB7b3duZXI6IHRoaXMub3duZXIuaWQsIGFpOnRoaXN9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRhbWFnZVRpbWVyLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgY29sbGlkZVdpdGhQbGF5ZXIocGxheWVyOiBQbGF5ZXJDb250cm9sbGVyKTogdm9pZCB7XG4gICAgICAgIHBsYXllci5kYW1hZ2UoMTApO1xuICAgIH1cblxuICAgIGNhbkF0dGFjayhwb3NpdGlvbjogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdHRhY2tUaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLm93bmVyLnBvc2l0aW9uLmRpc3RhbmNlVG8ocG9zaXRpb24pPD0zMjtcbiAgICB9XG5cbiAgICAvL1RPRE8gLSBuZWVkIHRvIG1vZGlmeSBmb3Igc2lkZSB2aWV3XG4gICAgaXNQbGF5ZXJWaXNpYmxlKHBvczogVmVjMik6IFZlYzJ7XG4gICAgICAgIC8vQ2hlY2sgaWZwbGF5ZXIgaXMgdmlzaWJsZSwgdGFraW5nIGludG8gYWNjb3VudCB3YWxsc1xuXG4gICAgICAgIC8vIEdldCB0aGUgbmV3IHBsYXllciBsb2NhdGlvblxuICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLm93bmVyLnBvc2l0aW9uLmNsb25lKCk7XG4gICAgICAgIGxldCBkZWx0YSA9IHBvcy5jbG9uZSgpLnN1YihzdGFydCk7XG5cbiAgICAgICAgaWYgKGRlbHRhLm1hZygpID49IDY0MCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggdGhlIHRpbGVtYXAgcmVnaW9uIHVudGlsIHdlIGZpbmQgYSBjb2xsaXNpb25cbiAgICAgICAgbGV0IG1pblggPSBNYXRoLm1pbihzdGFydC54LCBwb3MueCk7XG4gICAgICAgIGxldCBtYXhYID0gTWF0aC5tYXgoc3RhcnQueCwgcG9zLngpO1xuICAgICAgICBsZXQgbWluWSA9IE1hdGgubWluKHN0YXJ0LnksIHBvcy55KTtcbiAgICAgICAgbGV0IG1heFkgPSBNYXRoLm1heChzdGFydC55LCBwb3MueSk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB3YWxsIHRpbGVtYXBcbiAgICAgICAgbGV0IHdhbGxzID0gdGhpcy50aWxlbWFwXG5cbiAgICAgICAgbGV0IG1pbkluZGV4ID0gd2FsbHMuZ2V0Q29sUm93QXQobmV3IFZlYzIobWluWCwgbWluWSkpO1xuICAgICAgICBsZXQgbWF4SW5kZXggPSB3YWxscy5nZXRDb2xSb3dBdChuZXcgVmVjMihtYXhYLCBtYXhZKSk7XG5cbiAgICAgICAgbGV0IHRpbGVTaXplID0gd2FsbHMuZ2V0VGlsZVNpemUoKTtcblxuICAgICAgICBmb3IgKGxldCBjb2wgPSBtaW5JbmRleC54OyBjb2wgPD0gbWF4SW5kZXgueDsgY29sKyspIHtcbiAgICAgICAgICAgIGZvciAobGV0IHJvdyA9IG1pbkluZGV4Lnk7IHJvdyA8PSBtYXhJbmRleC55OyByb3crKykge1xuICAgICAgICAgICAgICAgIGlmICh3YWxscy5pc1RpbGVDb2xsaWRhYmxlKGNvbCwgcm93KSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHBvc2l0aW9uIG9mIHRoaXMgdGlsZVxuICAgICAgICAgICAgICAgICAgICBsZXQgdGlsZVBvcyA9IG5ldyBWZWMyKGNvbCAqIHRpbGVTaXplLnggKyB0aWxlU2l6ZS54IC8gMiwgcm93ICogdGlsZVNpemUueSArIHRpbGVTaXplLnkgLyAyKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBjb2xsaWRlciBmb3IgdGhpcyB0aWxlXG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2xsaWRlciA9IG5ldyBBQUJCKHRpbGVQb3MsIHRpbGVTaXplLnNjYWxlZCgxIC8gMikpO1xuXG4gICAgICAgICAgICAgICAgICAgIGxldCBoaXQgPSBjb2xsaWRlci5pbnRlcnNlY3RTZWdtZW50KHN0YXJ0LCBkZWx0YSwgVmVjMi5aRVJPKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoaGl0ICE9PSBudWxsICYmIHN0YXJ0LmRpc3RhbmNlU3FUbyhoaXQucG9zKSA8IHN0YXJ0LmRpc3RhbmNlU3FUbyhwb3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBoaXQgYSB3YWxsLCB3ZSBjYW4ndCBzZWUgdGhlIHBsYXllclxuICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcInBsYXllciBub3QgdmlzaWJsZVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBvcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnZXRzIHRoZSBwb3NpdGlvbiBvZiB0aGUgcGxheWVyXG4gICAgICogQHJldHVybnMgcG9zaXRpb24gb2YgdGhlIHBsYXllciBpZiB2aXNpYmxlLCBlbHNlIG51bGxcbiAgICAgKi9cbiAgICBnZXRQbGF5ZXJQb3NpdGlvbigpOiBWZWMyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNQbGF5ZXJWaXNpYmxlKHRoaXMucGxheWVyLnBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpe1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdldFN0YXRlKCkgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgdGhpcy5vd25lci5hbmltYXRpb24ucGF1c2UoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm93bmVyLmFuaW1hdGlvbi5yZXN1bWUoKTtcbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cbiAgICAgICAgaWYodGhpcy5idXJuVGltZXIuaXNTdG9wcGVkKCkgJiYgdGhpcy5idXJuQ291bnRlciA+MCl7XG4gICAgICAgICAgICB0aGlzLmJ1cm5Db3VudGVyIC0tO1xuICAgICAgICAgICAgdGhpcy5idXJuVGltZXIuc3RhcnQoKTtcbiAgICAgICAgICAgIHRoaXMuZGFtYWdlKDEyICsgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZXh0cmFEb3REbWcgKTtcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLnBvaXNvblRpbWVyLmlzU3RvcHBlZCgpICYmIHRoaXMucG9pc29uQ291bnRlciA+MCl7XG4gICAgICAgICAgICB0aGlzLnBvaXNvbkNvdW50ZXIgLS07XG4gICAgICAgICAgICB0aGlzLnBvaXNvblRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICB0aGlzLmRhbWFnZSggTWF0aC5yb3VuZCh0aGlzLkNVUlJFTlRfSFAvMjApICsgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZXh0cmFEb3REbWcgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuYmxlZWRUaW1lci5pc1N0b3BwZWQoKSAmJiB0aGlzLmJsZWVkQ291bnRlciA+MCl7XG4gICAgICAgICAgICB0aGlzLmJsZWVkQ291bnRlciAtLTtcbiAgICAgICAgICAgIHRoaXMuYmxlZWRUaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5kYW1hZ2UoMyArTWF0aC5yb3VuZCh0aGlzLkNVUlJFTlRfSFAvMzMpICsgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZXh0cmFEb3REbWcgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmhlYWx0aEJhcikge1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIucG9zaXRpb24gPSB0aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlLmNlbnRlci5jbG9uZSgpLmFkZChuZXcgVmVjMigwLCAtKCg8QUFCQj50aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlKS5oaCs1KSkpO1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIuZmlsbFdpZHRoID0gdGhpcy5DVVJSRU5UX0hQL3RoaXMubWF4SGVhbHRoICogdGhpcy5vd25lci5jb2xsaXNpb25TaGFwZS5odyAqIDM7XG4gICAgICAgICAgICBpZiAodGhpcy5DVVJSRU5UX0hQL3RoaXMubWF4SGVhbHRoID49IDIvMykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmNvbG9yID0gQ29sb3IuR1JFRU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICh0aGlzLkNVUlJFTlRfSFAvdGhpcy5tYXhIZWFsdGggPj0gMS8zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5ZRUxMT1c7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhlYWx0aEJhci5jb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wb2lzb25TdGF0KSB7XG4gICAgICAgICAgICB0aGlzLnBvaXNvblN0YXQucG9zaXRpb24gPSB0aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlLmNlbnRlci5jbG9uZSgpLmFkZChuZXcgVmVjMigtKCg8QUFCQj50aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlKS5odykqMS41KzEwLCAtKCg8QUFCQj50aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlKS5oaCsxNSkpKTtcbiAgICAgICAgICAgIHRoaXMucG9pc29uU3RhdC52aXNpYmxlID0gdGhpcy5wb2lzb25Db3VudGVyID4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5idXJuU3RhdCkge1xuICAgICAgICAgICAgdGhpcy5idXJuU3RhdC5wb3NpdGlvbiA9IHRoaXMucG9pc29uU3RhdC5wb3NpdGlvbi5jbG9uZSgpLmFkZChuZXcgVmVjMigxNSwgMCkpO1xuICAgICAgICAgICAgdGhpcy5idXJuU3RhdC52aXNpYmxlID0gdGhpcy5idXJuQ291bnRlciA+IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuYmxlZWRTdGF0KSB7XG4gICAgICAgICAgICB0aGlzLmJsZWVkU3RhdC5wb3NpdGlvbiA9IHRoaXMucG9pc29uU3RhdC5wb3NpdGlvbi5jbG9uZSgpLmFkZChuZXcgVmVjMigzMCwgMCkpO1xuICAgICAgICAgICAgdGhpcy5ibGVlZFN0YXQudmlzaWJsZSA9IHRoaXMuYmxlZWRDb3VudGVyID4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm93bmVyLnBvc2l0aW9uLnkgPiB0aGlzLnRpbGVtYXAuZ2V0RGltZW5zaW9ucygpLnkgKiB0aGlzLnRpbGVtYXAuZ2V0VGlsZVNpemUoKS55KSB7XG4gICAgICAgICAgICB0aGlzLkNVUlJFTlRfSFAgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5FTkVNWV9LSUxMRUQsIHtvd25lcjogdGhpcy5vd25lci5pZCwgYWk6dGhpc30pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZW51bSBFbmVteVN0YXRlcyB7XG4gICAgUEFUUk9MID0gXCJwYXRyb2xcIixcbiAgICBBTEVSVCA9IFwiYWxlcnRcIixcbiAgICBBVFRBQ0sgPSBcImF0dGFja1wiXG59IiwiaW1wb3J0IEVuZW15QUksIHsgRW5lbXlTdGF0ZXMgfSBmcm9tIFwiLi4vRW5lbXlBSVwiO1xuaW1wb3J0IEVuZW15U3RhdGUgZnJvbSBcIi4vRW5lbXlTdGF0ZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbGVydCBleHRlbmRzIEVuZW15U3RhdGUge1xuICAgIG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiV0FMS1wiLCB0cnVlKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgbGV0IHBvc2l0aW9uID0gdGhpcy5wYXJlbnQuZ2V0UGxheWVyUG9zaXRpb24oKTtcbiAgICAgICAgaWYgKHBvc2l0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gdGhpcy5wYXJlbnQubWF4U3BlZWQgKiBNYXRoLnNpZ24ocG9zaXRpb24ueCAtIHRoaXMub3duZXIucG9zaXRpb24ueCk7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC5kaXJlY3Rpb24gPSB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID49IDAgPyAxIDogLTE7XG4gICAgICAgICAgICBpZiAodGhpcy5wYXJlbnQuY2FuQXR0YWNrKHBvc2l0aW9uKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoZWQoRW5lbXlTdGF0ZXMuQVRUQUNLKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucGFyZW50LnZlbG9jaXR5LnggPSAwO1xuICAgICAgICAgICAgdGhpcy5maW5pc2hlZChFbmVteVN0YXRlcy5QQVRST0wpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmNhbldhbGsoKSkge1xuICAgICAgICAgICAgdGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID0gdGhpcy5wYXJlbnQuZGlyZWN0aW9uID09PSAxID8gdHJ1ZSA6IGZhbHNlIDtcbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxuXG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5zdG9wKCk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn0iLCJpbXBvcnQgRW5lbXlBSSwgeyBFbmVteVN0YXRlcyB9IGZyb20gXCIuLi9FbmVteUFJXCI7XG5pbXBvcnQgRW5lbXlTdGF0ZSBmcm9tIFwiLi9FbmVteVN0YXRlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXR0YWNrIGV4dGVuZHMgRW5lbXlTdGF0ZSB7XG4gICAgcHJvdGVjdGVkIGNoYXJnZWQ6IHN0cmluZztcbiAgICBwcm90ZWN0ZWQgYXR0YWNrZWQ6IHN0cmluZztcblxuICAgIG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICB0aGlzLnBhcmVudC5hdHRhY2tUaW1lci5zdGFydCgpO1xuICAgICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gMDtcbiAgICAgICAgdGhpcy5wYXJlbnQuaXNBdHRha2luZyA9IHRydWU7XG4gICAgICAgIHRoaXMuY2hhcmdlZCA9IHRoaXMub3duZXIuaWQrXCJjaGFyZ2VkXCI7XG4gICAgICAgIHRoaXMuYXR0YWNrZWQgPSB0aGlzLm93bmVyLmlkK1wiYXR0YWNrZWRcIjtcblxuICAgICAgICAvLyBUT0RPIHJlcGxhY2UgRFlJTkcgd2l0aCBDSEFSR0lOR1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5KFwiQ0hBUkdFXCIsIGZhbHNlLCB0aGlzLmNoYXJnZWQpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZSh0aGlzLmNoYXJnZWQpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZSh0aGlzLmF0dGFja2VkKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgc3VwZXIudXBkYXRlKGRlbHRhVCk7XG4gICAgfVxuXG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgICAgICB0aGlzLnBhcmVudC5pc0F0dGFraW5nID0gZmFsc2U7XG4gICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnN0b3AoKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufSIsImltcG9ydCBBQUJCIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvU2hhcGVzL0FBQkJcIjtcbmltcG9ydCBTdGF0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBFbmVteUFJIGZyb20gXCIuLi9FbmVteUFJXCI7XG5pbXBvcnQgUmVjZWl2ZXIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9SZWNlaXZlclwiO1xuXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBFbmVteVN0YXRlIGV4dGVuZHMgU3RhdGUge1xuICBwcm90ZWN0ZWQgcGFyZW50OiBFbmVteUFJO1xuICBwcm90ZWN0ZWQgb3duZXI6IEdhbWVOb2RlO1xuICBwcm90ZWN0ZWQgcmVjZWl2ZXI6IFJlY2VpdmVyO1xuICBncmF2aXR5OiBudW1iZXIgPSAxNTAwOyAvL1RPRE8gLSBjYW4gY2hhbmdlIGxhdGVyXG5cbiAgY29uc3RydWN0b3IocGFyZW50OiBFbmVteUFJLCBvd25lcjogR2FtZU5vZGUpIHtcbiAgICBzdXBlcihwYXJlbnQpO1xuICAgIHRoaXMub3duZXIgPSBvd25lcjtcbiAgICB0aGlzLnJlY2VpdmVyID0gbmV3IFJlY2VpdmVyKCk7XG4gIH1cblxuICBoYW5kbGVJbnB1dChldmVudDogR2FtZUV2ZW50KTogdm9pZCB7IH1cblxuICBjYW5XYWxrKCkge1xuICAgIGxldCBjb2xsaXNpb24gPSA8QUFCQj50aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlO1xuICAgIGxldCBjb2xyb3cgPSB0aGlzLnBhcmVudC50aWxlbWFwLmdldENvbFJvd0F0KGNvbGxpc2lvbi5jZW50ZXIuY2xvbmUoKS5hZGQobmV3IFZlYzIodGhpcy5wYXJlbnQuZGlyZWN0aW9uICogKGNvbGxpc2lvbi5odysyKSkpKTtcbiAgICByZXR1cm4gIXRoaXMucGFyZW50LnRpbGVtYXAuaXNUaWxlQ29sbGlkYWJsZShjb2xyb3cueCwgY29scm93LnkpICYmIHRoaXMucGFyZW50LnRpbGVtYXAuaXNUaWxlQ29sbGlkYWJsZShjb2xyb3cueCxjb2xyb3cueSsxKTtcbiAgfVxuXG4gIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5wYXJlbnQuZGFtYWdlVGltZXIuaXNTdG9wcGVkKCkgJiYgIXRoaXMucGFyZW50LmlzQXR0YWtpbmcpIHtcbiAgICAgIHRoaXMucGFyZW50LnZlbG9jaXR5LnggPSAwO1xuICAgIH1cbiAgICAvLyBEbyBncmF2aXR5XG4gICAgdGhpcy5wYXJlbnQudmVsb2NpdHkueSArPSB0aGlzLmdyYXZpdHkgKiBkZWx0YVQ7XG4gICAgdGhpcy5vd25lci5tb3ZlKHRoaXMucGFyZW50LnZlbG9jaXR5LnNjYWxlZChkZWx0YVQpKTtcbiAgfVxufVxuXG4iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBOYXZpZ2F0aW9uUGF0aCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvUGF0aGZpbmRpbmcvTmF2aWdhdGlvblBhdGhcIjtcblxuaW1wb3J0IEVuZW15QUksIHsgRW5lbXlTdGF0ZXMgfSBmcm9tIFwiLi4vRW5lbXlBSVwiO1xuaW1wb3J0IEVuZW15U3RhdGUgZnJvbSBcIi4vRW5lbXlTdGF0ZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBhdHJvbCBleHRlbmRzIEVuZW15U3RhdGUge1xuICAgIG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSURMRVwiLCB0cnVlKTtcbiAgICB9XG5cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYoIXRoaXMuY2FuV2FsaygpKXtcbiAgICAgICAgICAgIHRoaXMucGFyZW50LmRpcmVjdGlvbiAqPSAtMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vbW92ZVxuICAgICAgICB0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gdGhpcy5wYXJlbnQuZGlyZWN0aW9uICogdGhpcy5wYXJlbnQuc3BlZWQ7XG4gICAgICAgICg8U3ByaXRlPnRoaXMub3duZXIpLmludmVydFggPSB0aGlzLnBhcmVudC5kaXJlY3Rpb24gPT09IDEgPyB0cnVlIDogZmFsc2UgO1xuXG4gICAgICAgIGlmICh0aGlzLnBhcmVudC5nZXRQbGF5ZXJQb3NpdGlvbigpKSB7XG4gICAgICAgICAgICB0aGlzLmZpbmlzaGVkKEVuZW15U3RhdGVzLkFMRVJUKTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlci51cGRhdGUoZGVsdGFUKTtcbiAgICB9XG5cbiAgICBvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnN0b3AoKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufSIsImltcG9ydCBFbmVteUFJLCB7IEVuZW15U3RhdGVzIH0gZnJvbSBcIi4uL0VuZW15QUlcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEF0dGFjayBmcm9tIFwiLi9BdHRhY2tcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2xpbWVBdHRhY2sgZXh0ZW5kcyBBdHRhY2sge1xuICAgIG9uRW50ZXIob3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgIH1cbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5maW5pc2hlZChFbmVteVN0YXRlcy5BTEVSVCk7XG4gICAgfVxuICAgIG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufSIsImltcG9ydCBFbmVteUFJLCB7IEVuZW15U3RhdGVzIH0gZnJvbSBcIi4uL0VuZW15QUlcIjtcbmltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBBdHRhY2sgZnJvbSBcIi4vQXR0YWNrXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNuYWtlQXR0YWNrIGV4dGVuZHMgQXR0YWNrIHtcbiAgICB1cGRhdGUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgd2hpbGUgKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpIHtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCkudHlwZTtcbiAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIHRoaXMuY2hhcmdlZDpcbiAgICAgICAgICAgICAgICAgICAgKDxBbmltYXRlZFNwcml0ZT50aGlzLm93bmVyKS5hbmltYXRpb24ucGxheShcIkFUVEFDS1wiLCBmYWxzZSwgdGhpcy5hdHRhY2tlZCk7XG4gICAgICAgICAgICAgICAgICAgICg8QUFCQj50aGlzLm93bmVyLmNvbGxpc2lvblNoYXBlKS5oYWxmU2l6ZS54ICs9IDMuNTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSB0aGlzLmF0dGFja2VkOlxuICAgICAgICAgICAgICAgICAgICAoPEFBQkI+dGhpcy5vd25lci5jb2xsaXNpb25TaGFwZSkuaGFsZlNpemUueCAtPSAzLjU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmluaXNoZWQoRW5lbXlTdGF0ZXMuQUxFUlQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAoPFNwcml0ZT50aGlzLm93bmVyKS5pbnZlcnRYID0gdGhpcy5wYXJlbnQuZGlyZWN0aW9uID09PSAxID8gdHJ1ZSA6IGZhbHNlIDtcbiAgICB9XG59IiwiaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgRW5lbXlBSSwgeyBFbmVteVN0YXRlcyB9IGZyb20gXCIuL0VuZW15QUlcIjtcbmltcG9ydCBTbGltZUF0dGFjayBmcm9tIFwiLi9FbmVteVN0YXRlcy9TbGltZUF0dGFja1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTbGltZUFJIGV4dGVuZHMgRW5lbXlBSSB7XG4gICAgaW5pdGlhbGl6ZUFJKG93bmVyOiBBbmltYXRlZFNwcml0ZSwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICBzdXBlci5pbml0aWFsaXplQUkob3duZXIsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLmFkZFN0YXRlKEVuZW15U3RhdGVzLkFUVEFDSywgbmV3IFNsaW1lQXR0YWNrKHRoaXMsIG93bmVyKSk7XG4gICAgfVxufSIsImltcG9ydCBBbmltYXRlZFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9BbmltYXRlZFNwcml0ZVwiO1xuaW1wb3J0IEVuZW15QUksIHsgRW5lbXlTdGF0ZXMgfSBmcm9tIFwiLi9FbmVteUFJXCI7XG5pbXBvcnQgU25ha2VBdHRhY2sgZnJvbSBcIi4vRW5lbXlTdGF0ZXMvU25ha2VBdHRhY2tcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU25ha2VBSSBleHRlbmRzIEVuZW15QUkge1xuICAgIGluaXRpYWxpemVBSShvd25lcjogQW5pbWF0ZWRTcHJpdGUsIG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICAgICAgc3VwZXIuaW5pdGlhbGl6ZUFJKG93bmVyLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShFbmVteVN0YXRlcy5BVFRBQ0ssIG5ldyBTbmFrZUF0dGFjayh0aGlzLCBvd25lcikpO1xuICAgIH1cbn0iLCJcbmltcG9ydCBHYW1lTm9kZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR2FtZU5vZGVcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi9pdGVtcy9XZWFwb25cIjtcbmltcG9ydCBQbGF5ZXJDb250cm9sbGVyIGZyb20gXCIuLi9QbGF5ZXIvUGxheWVyQ29udHJvbGxlclwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0FJL0VuZW15QUlcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmF0dGxlTWFuYWdlciB7XG4gICAgcGxheWVyczogQXJyYXk8QmF0dGxlckFJPjtcblxuICAgIGVuZW1pZXM6IEFycmF5PEJhdHRsZXJBST47XG5cbiAgICBoYW5kbGVJbnRlcmFjdGlvbihhdHRhY2tlclR5cGU6IHN0cmluZywgd2VhcG9uOiBXZWFwb24sIHVzZXI/OiBHYW1lTm9kZSkge1xuICAgICAgICAvL21heSBiZSB1bm5lZWRlZCBzaW5jZSB3ZSBhcmUgY29udHJvbGxpbmcgdGhlIHBsYXllciAtIFxuICAgICAgICAvL3dlIGRldGVybWluZSBlbmVteSBjb2xsaXNpb24gdGhlcmVcbiAgICAgICAgXG4gICAgICAgIGlmIChhdHRhY2tlclR5cGUgPT09IFwicGxheWVyXCIpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGZvciBjb2xsaXNpb25zIHdpdGggZW5lbWllc1xuICAgICAgICAgICAgaWYodGhpcy5lbmVtaWVzLmxlbmd0aCAhPSAwKXtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBlbmVteSBvZiB0aGlzLmVuZW1pZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdlYXBvbi5oaXRzKGVuZW15Lm93bmVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBsYXllciA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllcnNbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihwbGF5ZXIuZnVsbEhwQm9udXMpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZW15LmRhbWFnZShNYXRoLnJvdW5kKCB3ZWFwb24udHlwZS5kYW1hZ2UgKiAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXJzWzBdKS5DVVJSRU5UX0FUSy8xMCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmVteS5kYW1hZ2UoTWF0aC5yb3VuZCh3ZWFwb24udHlwZS5kYW1hZ2UgKiAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXJzWzBdKS5DVVJSRU5UX0FUSy8xMDApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJlbmVteSB0b29rIGRtZ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9hZGQgY2hlY2tpbmcgZm9yIGVhY2ggb25oaXQgYnVmZiBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vRE9UU1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYocGxheWVyLmhhc0JsZWVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPEVuZW15QUk+ZW5lbXkpLmJsZWVkQ291bnRlciArPTM7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihwbGF5ZXIuaGFzUG9pc29uKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPEVuZW15QUk+ZW5lbXkpLnBvaXNvbkNvdW50ZXIgPTUgO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocGxheWVyLmhhc0J1cm4pe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8RW5lbXlBST5lbmVteSkuYnVybkNvdW50ZXIgPTUgO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHBsYXllci5oYXNMaWZlc3RlYWwpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllci5hZGRIZWFsdGgoTWF0aC5yb3VuZCh3ZWFwb24udHlwZS5kYW1hZ2UgKiBwbGF5ZXIuQ1VSUkVOVF9BVEsvMTAwICogcGxheWVyLmxpZmVzdGVhbHJhdGlvKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgY29sbGlzaW9uIHdpdGggcGxheWVyXG4gICAgICAgICAgICBmb3IgKGxldCBwbGF5ZXIgb2YgdGhpcy5wbGF5ZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdlYXBvbi5oaXRzKHBsYXllci5vd25lcikpIHtcbiAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnBsYXllcikuZGFtYWdlKHdlYXBvbi50eXBlLmRhbWFnZSwgdXNlcik7XG4gICAgICAgICAgICAgICAgICAgIGlmKCg8UGxheWVyQ29udHJvbGxlcj5wbGF5ZXIpLmhhc1NoaWVsZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+cGxheWVyKS5hZGRTaGllbGQod2VhcG9uLnR5cGUuZGFtYWdlICogLjUpOyAgLy9oYWxmIG9mIGRtZyB0YWtlbiBpcyBjb252ZXJ0ZWQgdG8gc2hpZWxkXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXG5cbiAgICB9XG5cbiAgICBzZXRQbGF5ZXJzKHBsYXllcjogQXJyYXk8QmF0dGxlckFJPik6IHZvaWQge1xuICAgICAgICB0aGlzLnBsYXllcnMgPSBwbGF5ZXI7XG4gICAgfVxuXG4gICAgc2V0RW5lbWllcyhlbmVtaWVzOiBBcnJheTxCYXR0bGVyQUk+KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZW5lbWllcyA9IGVuZW1pZXM7XG4gICAgfVxuXG4gICAgYWRkRW5lbXkoZW5lbXkgOiBCYXR0bGVyQUkpe1xuICAgICAgICB0aGlzLmVuZW1pZXMucHVzaChlbmVteSk7XG4gICAgfVxuXG4gICAgcmVtb3ZlRW5lbXkoZW5lbXkgOiBCYXR0bGVyQUkpe1xuICAgICAgIFxuICAgICAgICBcbiAgICAgICAgdGhpcy5lbmVtaWVzID0gdGhpcy5lbmVtaWVzLmZpbHRlcihpdGVtID0+IGl0ZW0gIT09IGVuZW15KVxuICAgICAgICBpZih0aGlzLmVuZW1pZXMubGVuZ3RoID09IDApe1xuICAgICAgICAgICAgdGhpcy5lbmVtaWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZW5lbWllcztcbiAgICAgICAgICBcbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4vaXRlbXMvSXRlbVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnZlbnRvcnlNYW5hZ2VyIHtcblxuICAgIHByaXZhdGUgcG9zaXRpb246IFZlYzI7XG4gICAgcHJpdmF0ZSBpdGVtczogQXJyYXk8SXRlbT47XG4gICAgcHJpdmF0ZSBpbnZlbnRvcnlTbG90czogQXJyYXk8U3ByaXRlPjtcbiAgICBwcml2YXRlIHNsb3RTaXplOiBWZWMyO1xuICAgIHByaXZhdGUgcGFkZGluZzogbnVtYmVyO1xuICAgIHByaXZhdGUgY3VycmVudFNsb3Q6IG51bWJlcjtcbiAgICBwcml2YXRlIHNsb3RMYXllcjogc3RyaW5nO1xuICAgIHByaXZhdGUgaXRlbUxheWVyOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBzZWxlY3RlZFNsb3Q6IFJlY3Q7XG5cbiAgICBjb25zdHJ1Y3RvcihzY2VuZTogU2NlbmUsIHNpemU6IG51bWJlciwgaW52ZW50b3J5U2xvdDogc3RyaW5nLCBwb3NpdGlvbjogVmVjMiwgcGFkZGluZzogbnVtYmVyLCBzbG90TGF5ZXI6IHN0cmluZywgaXRlbUxheWVyOiBzdHJpbmcpe1xuICAgICAgICB0aGlzLml0ZW1zID0gbmV3IEFycmF5KHNpemUpO1xuICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzID0gbmV3IEFycmF5KHNpemUpO1xuICAgICAgICB0aGlzLnBhZGRpbmcgPSBwYWRkaW5nO1xuICAgICAgICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG4gICAgICAgIHRoaXMuY3VycmVudFNsb3QgPSAwO1xuXG4gICAgICAgIC8vIEFkZCBsYXllcnNcbiAgICAgICAgdGhpcy5zbG90TGF5ZXIgPSBzbG90TGF5ZXI7XG4gICAgICAgIHNjZW5lLmFkZFVJTGF5ZXIodGhpcy5zbG90TGF5ZXIpLnNldERlcHRoKDEwMCk7XG4gICAgICAgIHRoaXMuaXRlbUxheWVyID0gaXRlbUxheWVyO1xuICAgICAgICBzY2VuZS5hZGRVSUxheWVyKHRoaXMuaXRlbUxheWVyKS5zZXREZXB0aCgxMDEpO1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgaW52ZW50b3J5IHNsb3RzXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspe1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90c1tpXSA9IHNjZW5lLmFkZC5zcHJpdGUoaW52ZW50b3J5U2xvdCwgdGhpcy5zbG90TGF5ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zbG90U2l6ZSA9IHRoaXMuaW52ZW50b3J5U2xvdHNbMF0uc2l6ZS5jbG9uZSgpO1xuXG4gICAgICAgIC8vIFBvc2l0aW9uIHRoZSBpbnZlbnRvcnkgc2xvdHNcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHNpemU7IGkrKyl7XG4gICAgICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzW2ldLnBvc2l0aW9uLnNldChwb3NpdGlvbi54ICsgaSoodGhpcy5zbG90U2l6ZS54ICsgdGhpcy5wYWRkaW5nKSwgcG9zaXRpb24ueSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYSByZWN0IGZvciB0aGUgc2VsZWN0ZWQgc2xvdFxuICAgICAgICB0aGlzLnNlbGVjdGVkU2xvdCA9IDxSZWN0PnNjZW5lLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIHNsb3RMYXllciwge3Bvc2l0aW9uOiB0aGlzLnBvc2l0aW9uLmNsb25lKCksIHNpemU6IHRoaXMuc2xvdFNpemUuY2xvbmUoKS5pbmMoLTIpfSk7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTbG90LmNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRTbG90LmNvbG9yLmEgPSAwLjI7XG4gICAgfVxuXG4gICAgZ2V0SXRlbSgpOiBJdGVtIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3RcbiAgICAgKi9cbiAgICBjaGFuZ2VTbG90KHNsb3Q6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmN1cnJlbnRTbG90ID0gc2xvdDtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFNsb3QucG9zaXRpb24uY29weSh0aGlzLmludmVudG9yeVNsb3RzW3Nsb3RdLnBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgc2xvdFxuICAgICAqL1xuICAgIGdldFNsb3QoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFNsb3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhbiBpdGVtIHRvIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgc2xvdFxuICAgICAqL1xuICAgIGFkZEl0ZW0oaXRlbTogSXRlbSk6IGJvb2xlYW4ge1xuICAgICAgICBpZighdGhpcy5pdGVtc1t0aGlzLmN1cnJlbnRTbG90XSl7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIGl0ZW0gdG8gdGhlIGludmVudG9yeVxuICAgICAgICAgICAgdGhpcy5pdGVtc1t0aGlzLmN1cnJlbnRTbG90XSA9IGl0ZW07XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgZ3VpXG4gICAgICAgICAgICBpdGVtLm1vdmVTcHJpdGUobmV3IFZlYzIodGhpcy5wb3NpdGlvbi54ICsgdGhpcy5jdXJyZW50U2xvdCoodGhpcy5zbG90U2l6ZS54ICsgdGhpcy5wYWRkaW5nKSwgdGhpcy5wb3NpdGlvbi55KSwgdGhpcy5pdGVtTGF5ZXIpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gRmFpbGVkIHRvIGFkZCBpdGVtLCBzb21ldGhpbmcgd2FzIGFscmVhZHkgaW4gdGhlIHNsb3RcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYW5kIHJldHVybnMgYW4gaXRlbSBmcm9tIHRoZSB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHNsb3QsIGlmIHBvc3NpYmxlXG4gICAgICovXG4gICAgcmVtb3ZlSXRlbSgpOiBJdGVtIHtcbiAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLml0ZW1zW3RoaXMuY3VycmVudFNsb3RdO1xuXG4gICAgICAgIHRoaXMuaXRlbXNbdGhpcy5jdXJyZW50U2xvdF0gPSBudWxsO1xuXG4gICAgICAgIGlmKGl0ZW0pe1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldEFjdGl2ZShhY3RpdmU6IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKGFjdGl2ZSl7XG4gICAgICAgICAgICB0aGlzLmludmVudG9yeVNsb3RzLmZvckVhY2goc2xvdCA9PiBzbG90LmFscGhhID0gMS4wKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgdGhpcy5pbnZlbnRvcnlTbG90cy5mb3JFYWNoKHNsb3QgPT4gc2xvdC5hbHBoYSA9IDAuNSk7XG4gICAgICAgIH1cbiAgICB9XG59IiwiaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBhYnN0cmFjdCBjbGFzcyBJdGVtIHtcbiAgICAvKiogVGhlIHNwcml0ZSB0aGF0IHJlcHJlc2VudHMgdGhpcyB3ZWFwb24gaW4gdGhlIHdvcmxkIG9yIGluIGFuIGludmVudG9yeSAqL1xuICAgIHNwcml0ZTogU3ByaXRlO1xuXG4gICAgY29uc3RydWN0b3Ioc3ByaXRlOiBTcHJpdGUpe1xuICAgICAgICB0aGlzLnNwcml0ZSA9IHNwcml0ZTtcbiAgICB9XG5cbiAgICBtb3ZlU3ByaXRlKHBvc2l0aW9uOiBWZWMyLCBsYXllcj86IHN0cmluZyl7XG4gICAgICAgIC8vIENoYW5nZSB0aGUgbGF5ZXIgaWYgbmVlZGVkXG4gICAgICAgIGlmKGxheWVyKXtcbiAgICAgICAgICAgIGxldCBjdXJyZW50TGF5ZXIgPSB0aGlzLnNwcml0ZS5nZXRMYXllcigpO1xuICAgICAgICAgICAgY3VycmVudExheWVyLnJlbW92ZU5vZGUodGhpcy5zcHJpdGUpO1xuICAgICAgICAgICAgbGV0IG5ld0xheWVyID0gdGhpcy5zcHJpdGUuZ2V0U2NlbmUoKS5nZXRMYXllcihsYXllcik7XG4gICAgICAgICAgICBuZXdMYXllci5hZGROb2RlKHRoaXMuc3ByaXRlKTtcbiAgICAgICAgICAgIHRoaXMuc3ByaXRlLnNldExheWVyKG5ld0xheWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1vdmUgdGhlIHNwcml0ZVxuICAgICAgICB0aGlzLnNwcml0ZS5wb3NpdGlvbi5jb3B5KHBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICBhYnN0cmFjdCB1c2UodXNlcjogR2FtZU5vZGUsIC4uLmFyZ3M6IGFueSk6IHZvaWQ7XG59IiwiLy9UT0RPIGltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEVtaXR0ZXIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9FbWl0dGVyXCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFRpbWVyIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9UaW1pbmcvVGltZXJcIjtcbmltcG9ydCBCYXR0bGVNYW5hZ2VyIGZyb20gXCIuLi9CYXR0bGVNYW5hZ2VyXCI7XG5pbXBvcnQgSXRlbSBmcm9tIFwiLi9JdGVtXCI7XG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi9XZWFwb25UeXBlcy9XZWFwb25UeXBlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcblxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWFwb24gZXh0ZW5kcyBJdGVtIHtcbiAgICAvKiogVGhlIHR5cGUgb2YgdGhpcyB3ZWFwb24gKi9cbiAgICB0eXBlOiBXZWFwb25UeXBlO1xuXG4gICAgLyoqIEEgbGlzdCBvZiBhc3NldHMgdGhpcyB3ZWFwb24gbmVlZHMgdG8gYmUgYW5pbWF0ZWQgKi9cbiAgICBhc3NldHM6IEFycmF5PGFueT47XG5cbiAgICAvKiogQW4gZXZlbnQgZW1pdHRlciB0byBob29rIGludG8gdGhlIEV2ZW50UXVldWUgKi9cbiAgICBlbWl0dGVyOiBFbWl0dGVyXG5cbiAgICAvKiogVGhlIGJhdHRsZSBtYW5hZ2VyICovXG4gICAgYmF0dGxlTWFuYWdlcjogQmF0dGxlTWFuYWdlcjtcblxuICAgIGNvb2xkb3duIDogbnVtYmVyID0gMDtcbiAgICAvKiogVGhlIGNvb2xkb3duIHRpbWVyIGZvciB0aGlzIHdlYXBvbidzIHVzZSAqL1xuICAgIGNvb2xkb3duVGltZXI6IFRpbWVyO1xuXG4gICAgRVhUUkFfREFNQUdFIDogbnVtYmVyOyAgLy9mbGF0IGV4dHJhIGRhbWFnZSB2YWx1ZVxuXG4gICAgRVhUUkFfUkFOR0U6IG51bWJlciA7ICAgLy9wZXJjZW50YWdlIHZhbHVlIC0+IC4xID0gMTAlIGV4dHJhIHJhbmdlXG5cbiAgICBjb25zdHJ1Y3RvcihzcHJpdGU6IFNwcml0ZSwgdHlwZTogV2VhcG9uVHlwZSwgYmF0dGxlTWFuYWdlcjogQmF0dGxlTWFuYWdlcil7XG4gICAgICAgIHN1cGVyKHNwcml0ZSk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlLmNsb25lKCk7XG5cbiAgICAgICAgLy8gS2VlcCBhIHJlZmVyZW5jZSB0byB0aGUgc3ByaXRlIG9mIHRoaXMgd2VhcG9uXG4gICAgICAgIHRoaXMuc3ByaXRlID0gc3ByaXRlO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhbiBldmVudCBlbWl0dGVyXG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBFbWl0dGVyKCk7XG5cbiAgICAgICAgLy8gU2F2ZSBhIHJlZmVyZW5jZSB0byB0aGUgYmF0dGxlciBtYW5hZ2VyXG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlciA9IGJhdHRsZU1hbmFnZXI7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBjb29sZG93biB0aW1lclxuICAgICAgICB0aGlzLmNvb2xkb3duVGltZXIgPSBuZXcgVGltZXIodHlwZS5jb29sZG93bik7ICBcbiAgICAgICAgdGhpcy5jb29sZG93biA9IHR5cGUuY29vbGRvd247XG5cbiAgICAgICAgdGhpcy5FWFRSQV9EQU1BR0UgPSAwO1xuICAgICAgICB0aGlzLkVYVFJBX1JBTkdFPTA7IFxuICAgIH1cblxuICAgIC8vIEBvdmVycmlkZVxuICAgIC8qKlxuICAgICAqIFVzZXMgdGhpcyB3ZWFwb24gaW4gdGhlIHNwZWNpZmllZCBkaXJlY3Rpb24uXG4gICAgICogVGhpcyBvbmx5IHdvcmtzIGlmIHRoZSBjb29sZG93biB0aW1lciBoYXMgZW5kZWRcbiAgICAgKi9cbiAgICB1c2UodXNlcjogR2FtZU5vZGUsIHVzZXJUeXBlOiBzdHJpbmcsIGRpcmVjdGlvbjogVmVjMik6IGJvb2xlYW4ge1xuICAgICAgICAvLyBJZiB0aGUgY29vbGRvd24gdGltZXIgaXMgc3RpbGwgcnVubmluZywgd2UgY2FuJ3QgdXNlIHRoZSB3ZWFwb25cbiAgICAgICAgaWYoIXRoaXMuY29vbGRvd25UaW1lci5pc1N0b3BwZWQoKSl7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVseSBvbiB0aGUgd2VhcG9uIHR5cGUgdG8gY3JlYXRlIGFueSBuZWNlc3NhcnkgYXNzZXRzXG4gICAgICAgIHRoaXMuYXNzZXRzID0gdGhpcy50eXBlLmNyZWF0ZVJlcXVpcmVkQXNzZXRzKHRoaXMuc3ByaXRlLmdldFNjZW5lKCkpO1xuXG4gICAgICAgIC8vIERvIGEgdHlwZSBzcGVjaWZpYyB3ZWFwb24gYW5pbWF0aW9uXG4gICAgICAgIHRoaXMudHlwZS5kb0FuaW1hdGlvbih1c2VyLCBkaXJlY3Rpb24sIHRoaXMuRVhUUkFfUkFOR0UsIC4uLnRoaXMuYXNzZXRzKTtcblxuICAgICAgICAvLyBBcHBseSBkYW1hZ2VcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLmhhbmRsZUludGVyYWN0aW9uKHVzZXJUeXBlLCB0aGlzLCB1c2VyKTtcbiAgICBcbiAgICAgICAgLy8gUmVzZXQgdGhlIGNvb2xkb3duIHRpbWVyXG4gICAgICAgIHRoaXMuY29vbGRvd25UaW1lci5zdGFydCgpO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgY2hlY2sgZm9yIHdoZXRoZXIgb3Igbm90IHRoaXMgd2VhcG9uIGhpdCBhIG5vZGVcbiAgICAgKi9cbiAgICBoaXRzKG5vZGU6IEdhbWVOb2RlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnR5cGUuaGl0cyhub2RlLCAuLi50aGlzLmFzc2V0cyk7XG4gICAgfVxufSIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IEdhbWVOb2RlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HYW1lTm9kZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgU3ByaXRlIGZyb20gXCIuLi8uLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL1Nwcml0ZVwiO1xuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4vV2VhcG9uVHlwZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTbGljZSBleHRlbmRzIFdlYXBvblR5cGUge1xuXG4gICAgaW5pdGlhbGl6ZShvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGFtYWdlID0gb3B0aW9ucy5kYW1hZ2U7XG4gICAgICAgIHRoaXMuY29vbGRvd24gPSBvcHRpb25zLmNvb2xkb3duO1xuICAgICAgICB0aGlzLmRpc3BsYXlOYW1lID0gb3B0aW9ucy5kaXNwbGF5TmFtZTtcbiAgICAgICAgdGhpcy5zcHJpdGVLZXkgPSBvcHRpb25zLnNwcml0ZUtleTtcbiAgICAgICAgdGhpcy51c2VWb2x1bWUgPSBvcHRpb25zLnVzZVZvbHVtZTtcbiAgICB9XG5cbiAgICBkb0FuaW1hdGlvbihhdHRhY2tlcjogR2FtZU5vZGUsIGRpcmVjdGlvbjogVmVjMiwgZXh0cmFSYW5nZTpudW1iZXIsc2xpY2VTcHJpdGU6IEFuaW1hdGVkU3ByaXRlKTogdm9pZCB7XG4gICAgICAgIFxuICAgICAgICAvLyBSb3RhdGUgdGhpcyB3aXRoIHRoZSBnYW1lIG5vZGVcbiAgICAgICAgLy8gVE9ETyAtIG5lZWQgdG8gcm90YXRlIHRoZSBhbmltIHByb3Blcmx5XG4gICAgICAgIC8vc2xpY2VTcHJpdGUucm90YXRpb24gPSBhdHRhY2tlci5yb3RhdGlvbjtcbiAgICAgICAgLy9zbGljZVNwcml0ZS5yb3RhdGlvbiA9ICg8U3ByaXRlPmF0dGFja2VyKS5pbnZlcnRYPyAuNSogTWF0aC5QSSA6IDEuNSAqIE1hdGguUEk7XG4gICAgICAgIHNsaWNlU3ByaXRlLmludmVydFggPSAoPFNwcml0ZT5hdHRhY2tlcikuaW52ZXJ0WDtcbiAgICAgICAgXG4gICAgICAgIC8vVE9ETy0gXG4gICAgICAgIC8vNCB0byBzY2FsZSB1cCB0aGUgZGVmYXVsdCBzcHJpdGUgLSBtYXkgYmUgZGlmZmVyZW50IGxhdGVyIGRlcGVuZGluZyBvbiBhdGsgYW5pbVxuICAgICAgICBzbGljZVNwcml0ZS5zY2FsZVggPSAyKigxK2V4dHJhUmFuZ2UpOyAvL21pZ2h0IGhhdmUgdG8gYWRkIGV4dHJhIHJhbmdlIHRvIHkgYXMgd2VsbFxuICAgICAgICBzbGljZVNwcml0ZS5zY2FsZVkgPSAyO1xuXG4gICAgICAgIFxuICAgICAgICAvLyBNb3ZlIHRoZSBzbGljZSBvdXQgZnJvbSB0aGUgcGxheWVyXG4gICAgICAgIC8vc2NhbGUgPSBudW0gb2YgcGl4ZWxzIGJldHdlZW4gY2VudGVyIG9mIHNwcml0ZSBhbmQgYXRrIGFuaW1cbiAgICAgICAgc2xpY2VTcHJpdGUucG9zaXRpb24gPSBhdHRhY2tlci5wb3NpdGlvbi5jbG9uZSgpLmFkZChkaXJlY3Rpb24uc2NhbGVkKDMyKSk7IFxuICAgICAgICBzbGljZVNwcml0ZS5wb3NpdGlvbiA9ICBzbGljZVNwcml0ZS5wb3NpdGlvbi5hZGQobmV3IFZlYzIoMCwxNikpOyAgICAvL21ha2UgaXQgZ28gZG93biBhIGJpdFxuICAgICAgICBcbiAgICAgICAgLy8gUGxheSB0aGUgc2xpY2UgYW5pbWF0aW9uIHcvbyBsb29wLCBidXQgcXVldWUgdGhlIG5vcm1hbCBhbmltYXRpb25cbiAgICAgICAgc2xpY2VTcHJpdGUuYW5pbWF0aW9uLnBsYXkoXCJTTElDRVwiKTtcbiAgICAgICAgc2xpY2VTcHJpdGUuYW5pbWF0aW9uLnF1ZXVlKFwiTk9STUFMXCIsIHRydWUpO1xuICAgIH1cblxuICAgIGNyZWF0ZVJlcXVpcmVkQXNzZXRzKHNjZW5lOiBTY2VuZSk6IFtBbmltYXRlZFNwcml0ZV0ge1xuICAgICAgICBsZXQgc2xpY2UgPSBzY2VuZS5hZGQuYW5pbWF0ZWRTcHJpdGUoXCJzbGljZVwiLCBcInByaW1hcnlcIik7XG4gICAgICAgIHNsaWNlLmFuaW1hdGlvbi5wbGF5KFwiTk9STUFMXCIsIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBbc2xpY2VdO1xuICAgIH1cblxuICAgIGhpdHMobm9kZTogR2FtZU5vZGUsIHNsaWNlU3ByaXRlOiBBbmltYXRlZFNwcml0ZSk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gc2xpY2VTcHJpdGUuYm91bmRhcnkub3ZlcmxhcHMobm9kZS5jb2xsaXNpb25TaGFwZSk7XG4gICAgfVxuXG4gICAgY2xvbmUoKTogV2VhcG9uVHlwZSB7XG4gICAgICAgIGxldCBuZXdUeXBlID0gbmV3IFNsaWNlKCk7XG4gICAgICAgIG5ld1R5cGUuaW5pdGlhbGl6ZSh7ZGFtYWdlOiB0aGlzLmRhbWFnZSwgY29vbGRvd246IHRoaXMuY29vbGRvd24sIGRpc3BsYXlOYW1lOiB0aGlzLmRpc3BsYXlOYW1lLCBzcHJpdGVLZXk6IHRoaXMuc3ByaXRlS2V5LCB1c2VWb2x1bWU6IHRoaXMudXNlVm9sdW1lfSk7XG4gICAgICAgIHJldHVybiBuZXdUeXBlO1xuICAgIH1cbn0iLCJpbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uLy4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIFdlYXBvblR5cGUge1xuICAgIC8qKiBUaGUga2V5IGZvciB0aGlzIHNwcml0ZSBpbWFnZSAqL1xuICAgIHNwcml0ZUtleTogc3RyaW5nO1xuXG4gICAgLyoqIEhvdyBtdWNoIGRhbWFnZSB0aGlzIHdlYXBvbiBkb2VzICovXG4gICAgZGFtYWdlOiBudW1iZXI7XG5cbiAgICAvKiogRGlzcGxheSBuYW1lICovXG4gICAgZGlzcGxheU5hbWU6IHN0cmluZztcblxuICAgIC8qKiBUaGUgdXNlIGNvb2xkb3duIG9mIHRoZSB3ZWFwb24gKi9cbiAgICBjb29sZG93bjogbnVtYmVyO1xuXG4gICAgLyoqIEhvdyBsb3VkIGl0IGlzIHRvIHVzZSB0aGlzIHdlYXBvbiAqL1xuICAgIHVzZVZvbHVtZTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgdGhpcyB3ZWFwb24gdHlwZSB3aXRoIGRhdGFcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBpbml0aWFsaXplKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFuaW1hdGlvbiB0byBkbyB3aGVuIHRoaXMgd2VhcG9uIGlzIHVzZWRcbiAgICAgKi9cbiAgICBhYnN0cmFjdCBkb0FuaW1hdGlvbiguLi5hcmdzOiBhbnkpOiB2b2lkO1xuXG4gICAgYWJzdHJhY3QgY3JlYXRlUmVxdWlyZWRBc3NldHMoc2NlbmU6IFNjZW5lKTogQXJyYXk8YW55PjtcblxuICAgIGFic3RyYWN0IGhpdHMobm9kZTogR2FtZU5vZGUsIC4uLmFyZ3M6IGFueSk6IGJvb2xlYW47XG5cbiAgICBhYnN0cmFjdCBjbG9uZSgpOiBXZWFwb25UeXBlO1xufSIsImltcG9ydCBTdGF0ZU1hY2hpbmVBSSBmcm9tIFwiLi4vLi4vV29sZmllMkQvQUkvU3RhdGVNYWNoaW5lQUlcIjtcbmltcG9ydCBHYW1lTm9kZSwgeyBUd2VlbmFibGVQcm9wZXJ0aWVzIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgT3J0aG9nb25hbFRpbGVtYXAgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1RpbGVtYXBzL09ydGhvZ29uYWxUaWxlbWFwXCI7XG5pbXBvcnQgeyBQbGF5ZXJfRXZlbnRzIH0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgRmFsbCBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvRmFsbFwiO1xuaW1wb3J0IElkbGUgZnJvbSBcIi4vUGxheWVyU3RhdGVzL0lkbGVcIjtcbmltcG9ydCBJbkFpciBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvSW5BaXJcIjtcbmltcG9ydCBKdW1wIGZyb20gXCIuL1BsYXllclN0YXRlcy9KdW1wXCI7XG5pbXBvcnQgV2FsayBmcm9tIFwiLi9QbGF5ZXJTdGF0ZXMvV2Fsa1wiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IEl0ZW0gZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL0l0ZW1cIjtcbmltcG9ydCBJbnZlbnRvcnlNYW5hZ2VyIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9JbnZlbnRvcnlNYW5hZ2VyXCI7XG5pbXBvcnQgQmF0dGxlckFJIGZyb20gXCIuLi9BSS9CYXR0bGVyQUlcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IFdlYXBvbiBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0FJL0VuZW15QUlcIjtcbmltcG9ydCBUaW1lciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVGltaW5nL1RpbWVyXCI7XG5pbXBvcnQgUGxheWVyU3RhdGUgZnJvbSBcIi4vUGxheWVyU3RhdGVzL1BsYXllclN0YXRlXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5cbmV4cG9ydCBlbnVtIFBsYXllclR5cGUge1xuICAgIFBMQVRGT1JNRVIgPSBcInBsYXRmb3JtZXJcIixcbiAgICBUT1BET1dOID0gXCJ0b3Bkb3duXCJcbn1cblxuZXhwb3J0IGVudW0gUGxheWVyU3RhdGVzIHtcbiAgICBJRExFID0gXCJpZGxlXCIsXG4gICAgV0FMSyA9IFwid2Fsa1wiLFxuXHRKVU1QID0gXCJqdW1wXCIsXG4gICAgRkFMTCA9IFwiZmFsbFwiLFxuXHRQUkVWSU9VUyA9IFwicHJldmlvdXNcIlxufVxuXG5leHBvcnQgZW51bSBCdWZmVHlwZSB7XG4gICAgRkxBVF9BVEsgID0gXCJhdHRhY2tcIixcbiAgICBQRVJDRU5UX0FUSyA9IFwicGVyY2VudF9hdHRhY2tcIixcbiAgICBERUYgPSBcImRlZmVuY2VcIixcbiAgICBGTEFUX0hFQUxUSCA9IFwiaGVhbHRoXCIsXG4gICAgUEVSQ0VOVF9IRUFMVEggPSBcInBlcmNlbnRfaGVhbHRoXCIsXG4gICAgU1BFRUQgPSBcInNwZWVkXCIsXG4gICAgUkFOR0UgPSBcInJhbmdlXCIsXG4gICAgQVRLU1BFRUQgPSBcImF0dGFja3NwZWVkXCIsXG4gICAgUE9JU09OID0gXCJwb2lzb25cIixcbiAgICBCTEVFRCA9IFwiYmxlZWRcIixcbiAgICBCVVJOID0gXCJidXJuXCIsXG4gICAgRVhUUkFfRE9UID0gXCJleHRyYWRvdFwiLFxuICAgIFNISUVMRCA9IFwic2hpZWxkXCIsXG4gICAgU0hJRUxEX0RNRyA9IFwic2hpZWxkZG1nXCIsICAgLy9pbmNyZWFzZSBzaGllbGQgZG1nIHJhdGlvXG4gICAgTElGRVNURUFMID0gXCJsaWZlc3RlYWxcIixcbiAgICBMSUZFU1RFQUxCVUZGID0gXCJsaWZlc3RlYWxidWZmXCIsXG4gICAgRVhUUkFMSUZFPSBcImV4dHJhbGlmZVwiLFxuICAgIE9ORVNIT1QgPSBcIm9uZXNob3RcIixcbiAgICBGVUxMSFBCT05VU0RNRyA9IFwiZnVsbGhwYm9udXNkbWdcIlxufVxuXG5cbmV4cG9ydCBjbGFzcyBCdWZmICB7XG4gICAgXCJ0eXBlXCI6IEJ1ZmZUeXBlO1xuICAgIFwidmFsdWVcIjogbnVtYmVyO1xuICAgIC8vXCJib251c1wiOiBib29sZWFuLCAgICAgICAgIC8vbmVlZCB0byBkZXRlcm1pbmUgd2hhdCBib251cyBnaXZlc1xuICAgIFwic3RyaW5nXCI/IDogc3RyaW5nO1xuICAgIFwiY2F0ZWdvcnlcIiA6IEJ1ZmZDYXRlZ29yeVxufVxuXG5cblxuLy9UT0RPIC0gbmVlZCBiZXR0ZXIgbmFtZXMgXG5leHBvcnQgZW51bSBCdWZmQ2F0ZWdvcnl7XG4gICAgQVRUQUNLID0gXCJBVFRBQ0tcIixcbiAgICBET1QgPSBcIkRPVFwiLFxuICAgIFNISUVMRCA9IFwiU0hJRUxEXCIsXG4gICAgSEVBTFRIID0gXCJIRUFMVEhcIixcbiAgICBFWFRSQSA9IFwiRVhUUkFcIlxufVxuXG4vL1RPRE8gLSBkaXNjdXNzIG1heCBzdGF0cyBkdXJpbmcgcmVmaW5lbWVudCwgdW51c2VkIGZvciBub3dcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBsYXllckNvbnRyb2xsZXIgZXh0ZW5kcyBTdGF0ZU1hY2hpbmVBSSBpbXBsZW1lbnRzIEJhdHRsZXJBSXtcbiAgICBvd25lcjogR2FtZU5vZGU7XG4gICAgdmVsb2NpdHk6IFZlYzIgPSBWZWMyLlpFUk87XG4gICAgLy93aWxsIG5lZWQgdG8gZGlzY3VzcyByZWR1bmRhbnQgc3RhdHNcblx0c3BlZWQ6IG51bWJlciA9IDIwMDtcblx0TUlOX1NQRUVEOiBudW1iZXIgPSAyMDA7XG4gICAgTUFYX1NQRUVEOiBudW1iZXIgPSAzMDA7XG4gICAgQkFTRV9IUDogbnVtYmVyID0gMTAwO1xuICAgIE1BWF9IUDogbnVtYmVyID0gMTAwO1xuICAgIENVUlJFTlRfSFA6IG51bWJlciA9IDEwMDtcbiAgICBCQVNFX0FUSzogbnVtYmVyID0gMTAwO1xuICAgIENVUlJFTlRfQVRLOiBudW1iZXIgPSAxMDA7XG4gICAgZGFtYWdlX211bHRpcGxpZXI6IG51bWJlciA9IDE7XG4gICAgQ1VSUkVOVF9FWFAgOiBudW1iZXIgPSAwO1xuICAgIE1BWF9FWFAgOiBudW1iZXIgPSAxMDA7XG4gICAgQ1VSUkVOVF9TSElFTEQgOiBudW1iZXIgPTA7XG4gICAgTUFYX1NISUVMRCA6IG51bWJlciA9IDIwO1xuICAgIGludmluY2libGUgOiBib29sZWFuID0gZmFsc2U7XG4gICAgbGV2ZWwgOiBudW1iZXIgPSAxO1xuXG4gICAgZ29kTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgdGlsZW1hcDogT3J0aG9nb25hbFRpbGVtYXA7XG5cbiAgICAvL2ZvciBkb3VibGVqdW1wcyBtYXliZSA9ICMgb2YganVtcHMgaW4gYWlyIGFsbG93ZWRcbiAgICBNQVhfYWlyanVtcHM6IG51bWJlciA9IDE7XG4gICAgYWlyanVtcHM6bnVtYmVyID0gMDtcbiAgICBcbiAgICBwcml2YXRlIGxvb2tEaXJlY3Rpb246IFZlYzI7XG4gICAgLyoqIEEgbGlzdCBvZiBpdGVtcyBpbiB0aGUgZ2FtZSB3b3JsZCAqL1xuICAgIHByaXZhdGUgaXRlbXM6IEFycmF5PEl0ZW0+O1xuXG4gICAgLy8gVGhlIGludmVudG9yeSBvZiB0aGUgcGxheWVyXG4gICAgaW52ZW50b3J5OiBJbnZlbnRvcnlNYW5hZ2VyO1xuXG5cdHN0YXRpYyBpbnZpbmNpYmlsaXR5VGltZXI6IFRpbWVyO1xuICAgIFxuICAgIHN0YXRpYyBidWZmUG9vbCA6IEFycmF5PEJ1ZmZDYXRlZ29yeT4gPSBuZXcgQXJyYXkoKTtcblxuICAgIHN0YXRpYyBhcHBsaWVkQnVmZnM6IEFycmF5PEJ1ZmY+ID0gbmV3IEFycmF5KCk7XG5cbiAgICAvL2FkZCB0byBjdXJyZW50X2J1ZmZzIGxhdGVyXG4gICAgaGFzQmxlZWQgOiBCb29sZWFuID0gZmFsc2U7XG4gICAgaGFzUG9pc29uIDogQm9vbGVhbiA9IGZhbHNlO1xuICAgIGhhc0J1cm4gOiBCb29sZWFuID0gZmFsc2U7XG4gICAgaGFzU2hpZWxkIDogQm9vbGVhbiA9IGZhbHNlO1xuICAgIHNoaWVsZERhbWFnZSA6IG51bWJlciA9IDE7XG4gICAgaGFzTGlmZXN0ZWFsIDogQm9vbGVhbiA9IGZhbHNlO1xuICAgIGxpZmVzdGVhbHJhdGlvIDogbnVtYmVyID0gMDsgLy9wZXJjZW50IG9mIGRhbWFnZSB0byBzdGVhbFxuICAgIGhhc09uZVNob3Q6IEJvb2xlYW4gPSBmYWxzZTtcbiAgICBleHRyYURvdERtZyA6IG51bWJlciA9MDtcbiAgICBsaXZlczogbnVtYmVyID0gMTtcbiAgICBjb29sZG93bk11bHRpcGxpZXIgOiBudW1iZXIgPSAxO1xuICAgIGZ1bGxIcEJvbnVzOiBCb29sZWFuID0gZmFsc2U7XG5cbiAgICBwb2lzb25UaW1lciA6IFRpbWVyO1xuICAgIHBvaXNvbkNvdW50ZXIgOiBudW1iZXIgPSAwO1xuXG4gICAgYnVyblRpbWVyIDogVGltZXIgO1xuICAgIGJ1cm5Db3VudGVyIDogbnVtYmVyID0wO1xuXG4gICAgYmxlZWRUaW1lciA6IFRpbWVyO1xuICAgIGJsZWVkQ291bnRlciA6bnVtYmVyID0gMDtcblxuICAgIGVuZW1pZXNLaWxsZWQgOiBudW1iZXIgPTA7XG5cblxuICAgIC8vVE9ETyAtIGdldCB0aGUgY29ycmVjdCB0aWxlbWFwXG4gICAgaW5pdGlhbGl6ZUFJKG93bmVyOiBHYW1lTm9kZSwgb3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pil7XG4gICAgICAgIHRoaXMub3duZXIgPSBvd25lcjtcblxuICAgICAgICB0aGlzLmluaXRpYWxpemVQbGF0Zm9ybWVyKCk7XG5cbiAgICAgICAgdGhpcy50aWxlbWFwID0gdGhpcy5vd25lci5nZXRTY2VuZSgpLmdldFRpbGVtYXAob3B0aW9ucy50aWxlbWFwKSBhcyBPcnRob2dvbmFsVGlsZW1hcDtcbiAgICAgIFxuICAgICAgICB0aGlzLmludmVudG9yeSAgPSBvcHRpb25zLmludmVudG9yeTtcblxuICAgICAgICB0aGlzLmxvb2tEaXJlY3Rpb24gPSBuZXcgVmVjMigpO1xuICAgICAgICBcbiAgICAgICAgLy9pIGZyYW1lIHRpbWVyXG4gICAgICAgIFBsYXllckNvbnRyb2xsZXIuaW52aW5jaWJpbGl0eVRpbWVyID0gbmV3IFRpbWVyKDIwMDApO1xuXG4gICAgICAgIC8vaW5pdGlhbGl6ZSB0aGUgYnVmZiBwb29sIC0gZWFjaCBoYXMgc2FtZSB3ZWlnaHQgYXQgZmlyc3QgXG4gICAgICAgIFBsYXllckNvbnRyb2xsZXIuYnVmZlBvb2wgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgZm9yKCBsZXQgaT0wIDsgaTwgNDsgaSsrKXtcbiAgICAgICAgICAgIFBsYXllckNvbnRyb2xsZXIuYnVmZlBvb2wucHVzaChCdWZmQ2F0ZWdvcnkuQVRUQUNLKTtcbiAgICAgICAgICAgIFBsYXllckNvbnRyb2xsZXIuYnVmZlBvb2wucHVzaChCdWZmQ2F0ZWdvcnkuRVhUUkEpO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKEJ1ZmZDYXRlZ29yeS5ET1QpO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKEJ1ZmZDYXRlZ29yeS5TSElFTEQpO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKEJ1ZmZDYXRlZ29yeS5IRUFMVEgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9pbml0aWFsaXplIGRvdCB0aW1lcnNcbiAgICAgICAgdGhpcy5idXJuVGltZXIgPSBuZXcgVGltZXIoMTAwMCk7XG4gICAgICAgIHRoaXMuYmxlZWRUaW1lciA9IG5ldyBUaW1lcigxMDAwKTtcbiAgICAgICAgdGhpcy5wb2lzb25UaW1lciA9IG5ldyBUaW1lcigxMDAwKTtcblxuICAgICAgICAvL3RvIHRlc3QgdGhlIGJ1ZmZzXG4gICAgICAgIC8vdGhpcy5hZGRCdWZmKCB7dHlwZTpCdWZmVHlwZS5IRUFMVEgsIHZhbHVlOjF9ICk7XG4gICAgICAgIC8vdGhpcy5hZGRCdWZmKHt0eXBlOkJ1ZmZUeXBlLkJVUk4sIHZhbHVlOjEsIGNhdGVnb3J5OkJ1ZmZDYXRlZ29yeS5ET1R9KTtcbiAgICAgICAgLy90aGlzLmFkZEJ1ZmYoe3R5cGU6QnVmZlR5cGUuQkxFRUQsIHZhbHVlOjEsIGNhdGVnb3J5OkJ1ZmZDYXRlZ29yeS5ET1R9KTtcbiAgICAgICAgLy90aGlzLmFkZEJ1ZmYoe3R5cGU6QnVmZlR5cGUuUE9JU09OLCB2YWx1ZToxLCBjYXRlZ29yeTpCdWZmQ2F0ZWdvcnkuRE9UfSk7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG5cbiAgICBpbml0aWFsaXplUGxhdGZvcm1lcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zcGVlZCA9IDQwMDtcblxuICAgICAgICBsZXQgaWRsZSA9IG5ldyBJZGxlKHRoaXMsIHRoaXMub3duZXIpO1xuXHRcdHRoaXMuYWRkU3RhdGUoUGxheWVyU3RhdGVzLklETEUsIGlkbGUpO1xuXHRcdGxldCB3YWxrID0gbmV3IFdhbGsodGhpcywgdGhpcy5vd25lcik7XG5cdFx0dGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuV0FMSywgd2Fsayk7XG5cdFx0bGV0IGp1bXAgPSBuZXcgSnVtcCh0aGlzLCB0aGlzLm93bmVyKTtcbiAgICAgICAgdGhpcy5hZGRTdGF0ZShQbGF5ZXJTdGF0ZXMuSlVNUCwganVtcCk7XG4gICAgICAgIGxldCBmYWxsID0gbmV3IEZhbGwodGhpcywgdGhpcy5vd25lcik7XG4gICAgICAgIHRoaXMuYWRkU3RhdGUoUGxheWVyU3RhdGVzLkZBTEwsIGZhbGwpO1xuICAgICAgICBcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKFBsYXllclN0YXRlcy5JRExFKTtcbiAgICB9XG5cbiAgICBjaGFuZ2VTdGF0ZShzdGF0ZU5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICAvLyBJZiB3ZSBqdW1wIG9yIGZhbGwsIHB1c2ggdGhlIHN0YXRlIHNvIHdlIGNhbiBnbyBiYWNrIHRvIG91ciBjdXJyZW50IHN0YXRlIGxhdGVyXG4gICAgICAgIC8vIHVubGVzcyB3ZSdyZSBnb2luZyBmcm9tIGp1bXAgdG8gZmFsbCBvciBzb21ldGhpbmdcbiAgICAgICAgaWYoKHN0YXRlTmFtZSA9PT0gUGxheWVyU3RhdGVzLkpVTVAgfHwgc3RhdGVOYW1lID09PSBQbGF5ZXJTdGF0ZXMuRkFMTCkgJiYgISh0aGlzLnN0YWNrLnBlZWsoKSBpbnN0YW5jZW9mIEluQWlyKSl7XG4gICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2godGhpcy5zdGF0ZU1hcC5nZXQoc3RhdGVOYW1lKSk7XG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci5jaGFuZ2VTdGF0ZShzdGF0ZU5hbWUpO1xuICAgIH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuICAgICAgICBpZihQbGF5ZXJDb250cm9sbGVyLmludmluY2liaWxpdHlUaW1lci5pc1N0b3BwZWQoKSl7XG4gICAgICAgICAgICB0aGlzLmludmluY2libGUgPSBmYWxzZTtcbiAgICAgICAgfVxuXG5cdFx0aWYodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBKdW1wKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBKdW1wXCIpO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBXYWxrKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBXYWxrXCIpO1xuXHRcdH0gZWxzZSBpZiAodGhpcy5jdXJyZW50U3RhdGUgaW5zdGFuY2VvZiBJZGxlKXtcblx0XHRcdERlYnVnLmxvZyhcInBsYXllcnN0YXRlXCIsIFwiUGxheWVyIFN0YXRlOiBJZGxlXCIpO1xuXHRcdH0gZWxzZSBpZih0aGlzLmN1cnJlbnRTdGF0ZSBpbnN0YW5jZW9mIEZhbGwpe1xuICAgICAgICAgICAgRGVidWcubG9nKFwicGxheWVyc3RhdGVcIiwgXCJQbGF5ZXIgU3RhdGU6IEZhbGxcIik7XG4gICAgICAgIH1cbiAgICAgICAgRGVidWcubG9nKFwicGxheWVyIHNwZWVkXCIsIFwicGxheWVyIHNwZWVkOiB4OiBcIiArIHRoaXMudmVsb2NpdHkueCArIFwiLCB5OlwiICsgdGhpcy52ZWxvY2l0eS55KTtcbiAgICAgICAgRGVidWcubG9nKFwicGxheWVyIENvb3JkczpcIiwgXCJQbGF5ZXIgQ29vcmRzOlwiICt0aGlzLm93bmVyLnBvc2l0aW9uICk7XG5cbiAgICAgICAgLy90ZXN0aW5nIHRoZSBhdHRhY2tzIGhlcmUsIG1heSBiZSBtb3ZlZCB0byBhbm90aGVyIHBsYWNlIGxhdGVyXG4gICAgICAgIGlmKElucHV0V3JhcHBlci5pc0F0dGFja0p1c3RQcmVzc2VkKCkpe1xuICAgICAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLmludmVudG9yeS5nZXRJdGVtKCk7XG4gICAgICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5KFwiQVRUQUNLXCIsIHRydWUpO1xuICAgICAgICAgICAgLy9UT0RPIC0gZ2V0IHByb3BlciBsb29rIGRpcmVjdGlvbiBcbiAgICAgICAgICAgIHRoaXMubG9va0RpcmVjdGlvbi54ID0gKDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA/IC0xIDogMTtcbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGFuIGl0ZW0gaW4gdGhlIGN1cnJlbnQgc2xvdCwgdXNlIGl0XG4gICAgICAgICAgICBpZiAoaXRlbSkge1xuICAgICAgICAgICAgICAgIGl0ZW0udXNlKHRoaXMub3duZXIsIFwicGxheWVyXCIsIHRoaXMubG9va0RpcmVjdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL2NoZWNrIGRvdCBlZmZlY3RzXG4gICAgICAgIGlmKHRoaXMuYnVyblRpbWVyLmlzU3RvcHBlZCgpICYmIHRoaXMuYnVybkNvdW50ZXIgPjApe1xuICAgICAgICAgICAgdGhpcy5idXJuQ291bnRlciAtLTtcbiAgICAgICAgICAgIHRoaXMuYnVyblRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICB0aGlzLmRhbWFnZSg1KTtcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLnBvaXNvblRpbWVyLmlzU3RvcHBlZCgpICYmIHRoaXMucG9pc29uQ291bnRlciA+MCl7XG4gICAgICAgICAgICB0aGlzLnBvaXNvbkNvdW50ZXIgLS07XG4gICAgICAgICAgICB0aGlzLnBvaXNvblRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICB0aGlzLmRhbWFnZSggTWF0aC5yb3VuZCh0aGlzLkNVUlJFTlRfSFAvMzMpICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodGhpcy5ibGVlZFRpbWVyLmlzU3RvcHBlZCgpICYmIHRoaXMuYmxlZWRDb3VudGVyID4wKXtcbiAgICAgICAgICAgIHRoaXMuYmxlZWRDb3VudGVyIC0tO1xuICAgICAgICAgICAgdGhpcy5ibGVlZFRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICB0aGlzLmRhbWFnZSggMiArIE1hdGgucm91bmQodGhpcy5DVVJSRU5UX0hQLzUwKSApO1xuICAgICAgICB9XG4gICAgICAgIFxuXHR9XG5cbiAgICBcbiAgICAvLyBUT0RPIC0gZmlndXJlIG91dCBhdHRhY2tlciBcbiAgICBkYW1hZ2UoZGFtYWdlOiBudW1iZXIsIGF0dGFja2VyPzogR2FtZU5vZGUpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZ29kTW9kZSkge1xuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcImdvZG1vZGVcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYoICF0aGlzLmludmluY2libGUgJiYgUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKXtcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJ0YWtlIGRhbWFnZVwiKTtcbiAgICAgICAgICAgIC8vaSBmcmFtZSBoZXJlXG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmludmluY2liaWxpdHlUaW1lci5zdGFydCgpO1xuICAgICAgICAgICAgdGhpcy5pbnZpbmNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vc2hpZWxkIGFic29yYnMgdGhlIGRhbWFnZSBhbmQgc2VuZHMgZG1nIGJhY2sgdG8gYXR0YWNrZXJcbiAgICAgICAgICAgIGlmKHRoaXMuQ1VSUkVOVF9TSElFTEQgPiAwKXtcbiAgICAgICAgICAgICAgICBsZXQgbmV3c2hpZWxkID0gTWF0aC5tYXgoMCwgdGhpcy5DVVJSRU5UX1NISUVMRCAtIGRhbWFnZSApOyAvL2NhbGN1bGF0ZSB0aGUgbmV3IHNoaWVsZCB2YWx1ZVxuICAgICAgICAgICAgICAgIGlmKCBhdHRhY2tlciAhPT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgKDxFbmVteUFJPmF0dGFja2VyLl9haSkuZGFtYWdlKCh0aGlzLkNVUlJFTlRfU0hJRUxEIC0gbmV3c2hpZWxkKSAqIHRoaXMuc2hpZWxkRGFtYWdlKTsgLy9kYW1hZ2UgdGhlIGF0dGFja2VyIHRoZSBkbWcgdGFrZW4gdG8gc2hpZWxkXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9TSElFTEQgPSBuZXdzaGllbGQ7IC8vdXBkYXRlIHNoaWVsZCB2YWx1ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAvL2kgZnJhbWUgaGVyZVxuICAgICAgICAgICAgICAgIFBsYXllckNvbnRyb2xsZXIuaW52aW5jaWJpbGl0eVRpbWVyLnN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnZpbmNpYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiaHVydCBhbmltXCIpO1xuICAgICAgICAgICAgICAgICg8QW5pbWF0ZWRTcHJpdGU+dGhpcy5vd25lcikuYW5pbWF0aW9uLnBsYXkoXCJIVVJUXCIgKTtcbiAgICAgICAgICAgICAgICBkYW1hZ2UgKj0gdGhpcy5kYW1hZ2VfbXVsdGlwbGllcjtcbiAgICAgICAgICAgICAgICBkYW1hZ2UgPSBwYXJzZUZsb2F0KGRhbWFnZS50b1ByZWNpc2lvbigyKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0hQIC09IGRhbWFnZTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJodXJ0XCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuXG4gICAgICAgICAgICAgICAgLy9pZiBwbGF5ZXIgaGFzIHNoaWVsZCBidWZmIGdpdmUgdGhlbSBzaGllbGQgd2hlbiBkYW1hZ2VkXG4gICAgICAgICAgICAgICAgaWYodGhpcy5oYXNTaGllbGQpe1xuICAgICAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfU0hJRUxEICs9IGRhbWFnZSAqIC41O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJwbGF5ZXIgaXMgaW52aW5jaWJsZVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMuQ1VSUkVOVF9IUCA8PSAwKXtcbiAgICAgICAgICAgIHRoaXMubGl2ZXMgLS07XG4gICAgICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5wbGF5KFwiRFlJTkdcIik7XG4gICAgICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMub3duZXIpLmFuaW1hdGlvbi5xdWV1ZShcIkRFQURcIiwgdHJ1ZSwgUGxheWVyX0V2ZW50cy5QTEFZRVJfS0lMTEVEKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5QTEFZRVJfS0lMTEVEKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGdpdmVzIHRoZSBwbGF5ZXIgYSBjZXJ0YWluIGFtb3VudCBvZiBzaGllbGRcbiAgICAgKiBAcGFyYW0gc2hpZWxkIGFtb3VudCBvZiBzaGllbGQgdG8gYWRkIHRvIHBsYXllclxuICAgICAqL1xuICAgIGFkZFNoaWVsZChzaGllbGQgOiBudW1iZXIpe1xuICAgICAgICB0aGlzLkNVUlJFTlRfU0hJRUxEID0gKHRoaXMuQ1VSUkVOVF9TSElFTEQgKyBzaGllbGQpICUgdGhpcy5NQVhfU0hJRUxEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGdpdmVzIGhlYWx0aCB0byB0aGUgcGxheWVyXG4gICAgICogQHBhcmFtIGhlYWx0aCBoZWFsdGggdG8gZ2l2ZSBwbGF5ZXJcbiAgICAgKi9cbiAgICBhZGRIZWFsdGgoaGVhbHRoIDogbnVtYmVyKXtcbiAgICAgICAgdGhpcy5DVVJSRU5UX0hQICs9IGhlYWx0aDtcbiAgICAgICAgaWYodGhpcy5DVVJSRU5UX0hQID4gdGhpcy5NQVhfSFAgKXtcbiAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9IUCA9IHRoaXMuTUFYX0hQIDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGdpdmVzIHRoZSBwbGF5ZXIgZXhwXG4gICAgICogQHBhcmFtIGV4cCBhbW91bnQgb2YgZXhwIHRvIGdpdmUgdGhlIHBsYXllclxuICAgICAqL1xuICAgIGdpdmVFeHAoZXhwOiBudW1iZXIpe1xuICAgICAgICB0aGlzLkNVUlJFTlRfRVhQICs9IGV4cDtcbiAgICAgICAgLy9pZiA+IHRoYW4gbWF4IGV4cCBsZXZlbCB1cCAoZ2l2ZSBidWZmKVxuICAgICAgICBpZih0aGlzLkNVUlJFTlRfRVhQID49IHRoaXMuTUFYX0VYUCl7XG4gICAgICAgICAgICB0aGlzLkNVUlJFTlRfRVhQIC09IHRoaXMuTUFYX0VYUDtcbiAgICAgICAgICAgIHRoaXMuTUFYX0VYUCArPSA1MDsgLy9pbmNyZWFzZSBtYXggZXhwIG5lZWRlZCBmb3IgbGV2ZWwgdXBcbiAgICAgICAgICAgIHRoaXMubGV2ZWwrKyA7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJsZXZlbF91cFwiLCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogZmFsc2V9KTtcbiAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5HSVZFX1JFR1VMQVJfQlVGRik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG5cbiAgICAvKipcbiAgICAgKiBnZW5lcmF0ZXMgYW4gYXJyYXkgb2YgcmVndWxhciBidWZmc1xuICAgICAqIEBwYXJhbSB2YWwgb3B0aW9uYWwgdmFsdWUgdG8gZ2l2ZSBidWZmXG4gICAgICogQHJldHVybnMgYXJyYXkgb2YgdGhyZWUgYnVmZnNcbiAgICAgKi9cbiAgICBnZW5lcmF0ZVJlZ3VsYXJCdWZmcyggdmFsPyA6IG51bWJlcikgOiBCdWZmW117XG5cbiAgICAgICAgLy9yYW5kb20gbnVtYmVyIGZyb20gNSB0byAxNSBpZiBubyB2YWx1ZSBnaXZlblxuICAgICAgICBsZXQgbnVtID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICoxMCkgKzU7XG4gICAgICAgIG51bSA9IE1hdGgucm91bmQobnVtKTtcbiAgICAgICAgaWYodHlwZW9mIHZhbCAhPT0gJ3VuZGVmaW5lZCcpe1xuICAgICAgICAgICAgbnVtID0gdmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGJ1ZmZzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIGJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuRkxBVF9BVEssIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5FWFRSQX0sXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5TUEVFRCwgdmFsdWU6bnVtLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkVYVFJBfSxcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLkZMQVRfSEVBTFRILCB2YWx1ZTpudW0sIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuU0hJRUxEfSxcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLlJBTkdFLCB2YWx1ZTpudW0vMTAwLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkFUVEFDSywgc3RyaW5nOiBcIlxcblxcbkluY3JlYXNlIHJhbmdlIFxcbmJ5IFwiK251bStcIiVcIn0sXG4gICAgICAgICAgICB7dHlwZTpCdWZmVHlwZS5BVEtTUEVFRCwgdmFsdWU6bnVtLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkFUVEFDS30sXG4gICAgICAgICk7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLy9zaHVmZmxlIHBvb2wgb2YgYnVmZnNcbiAgICAgICAgYnVmZnMuc29ydCgoKSA9PiAwLjUgLSBNYXRoLnJhbmRvbSgpKTtcbiAgICAgICAgLy8gR2V0IHN1Yi1hcnJheSBvZiBmaXJzdCAzIGVsZW1lbnRzIGFmdGVyIHNodWZmbGVkXG4gICAgICAgIGxldCBzZWxlY3RlZCA9IGJ1ZmZzLnNsaWNlKDAsIDMpOyAvLzMgYnVmZiBjYXRlZ29yaWVzXG4gICAgICAgIHJldHVybiBzZWxlY3RlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnZW5lcmF0ZXMgYW4gYXJyYXkgb2Ygc3BlY2lhbCBidWZmc1xuICAgICAqIEBwYXJhbSB2YWwgb3B0aW9uYWwgdmFsdWUgdG8gZ2l2ZSB0aGUgYnVmZlxuICAgICAqIEByZXR1cm5zIGFycmF5IG9mIDMgQnVmZnNcbiAgICAgKi9cbiAgICBnZW5lcmF0ZVNwZWNpYWxCdWZmcyggdmFsPyA6IG51bWJlcikgOiBCdWZmW117XG4gICAgICAgIC8vc2h1ZmZsZSBwb29sIG9mIGJ1ZmYgY2F0ZWdvcmllcyBcbiAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpO1xuXG4gICAgICAgIC8vIEdldCBzdWItYXJyYXkgb2YgZmlyc3QgMyBlbGVtZW50cyBhZnRlciBzaHVmZmxlZFxuICAgICAgICBsZXQgc2h1ZmZsZWQgPSBQbGF5ZXJDb250cm9sbGVyLmJ1ZmZQb29sLnNsaWNlKDAsIDMpOyAvLzMgYnVmZiBjYXRlZ29yaWVzXG5cbiAgICAgICAgLy9yYW5kb20gbnVtYmVyIGZyb20gNSB0byAxNSBpZiBubyB2YWx1ZSBnaXZlblxuICAgICAgICBsZXQgbnVtID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICoxMCkgKzU7XG4gICAgICAgIG51bSA9IE1hdGgucm91bmQobnVtKTtcbiAgICAgICAgaWYodHlwZW9mIHZhbCAhPT0gJ3VuZGVmaW5lZCcpe1xuICAgICAgICAgICAgbnVtID0gdmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9UT0RPIC0gaW1wbGVtZW50IGJldHRlciBidWZmIGdlbmVydGlvbiAtIHNvbWUgYnVmZnMgZG9udCB3YW50IG11bHRpcGxlIG9mXG4gICAgICAgIGxldCBhdHRhY2tCdWZmcyA6IEJ1ZmZbXSA9IFtcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLlBFUkNFTlRfQVRLLCB2YWx1ZTpudW0vMTAwLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkFUVEFDSywgc3RyaW5nOlwiXFxuXFxuSW5jcmVhc2UgQXR0YWNrIFxcbmJ5XCIrbnVtK1wiJVwifVxuICAgICAgICBdO1xuXG4gICAgICAgIGxldCBkb3RCdWZmcyA6IEJ1ZmZbXSA9IFtcbiAgICAgICAgXTtcbiAgICAgICAgaWYoIXRoaXMuaGFzQmxlZWQpe1xuICAgICAgICAgICAgZG90QnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5CTEVFRCwgdmFsdWU6MSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5ET1QsIHN0cmluZzogXCJcXG5cXG5Zb3VyIGhpdHMgXFxuYXBwbHkgQmxlZWRcIn0pO1xuICAgICAgICB9XG4gICAgICAgIGlmKCF0aGlzLmhhc0J1cm4pe1xuICAgICAgICAgICAgZG90QnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5CVVJOLCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkRPVCwgc3RyaW5nOiBcIlxcblxcbllvdXIgaGl0cyBcXG5hcHBseSBCdXJuXCJ9KTtcbiAgICAgICAgfVxuICAgICAgICBpZighdGhpcy5oYXNQb2lzb24pe1xuICAgICAgICAgICAgZG90QnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5QT0lTT04sIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRE9ULCBzdHJpbmc6IFwiXFxuXFxuWW91ciBoaXRzIFxcbmFwcGx5IHBvaXNvblwifSk7XG4gICAgICAgIH1cblxuICAgICAgICAvL29ubHkgYWRkIGV4dHJhIGRvdCBpZiBhdCBsZWFzdCBvbmUgZG90IGlzIGFjcXVpcmVkXG4gICAgICAgIGZvcihsZXQgaT1kb3RCdWZmcy5sZW5ndGg7IGk8IDMgOyBpKyspe1xuICAgICAgICAgICAgZG90QnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5FWFRSQV9ET1QsIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5ET1QsIHN0cmluZzogXCJcXG5cXG5JbmNyZWFzZSB5b3VyIFxcbkRPVCBkYW1hZ2VcIn0pO1xuICAgICAgICB9XG5cbiAgICAgICAgXG4gICAgICAgIGxldCBzaGllbGRCdWZmcyA6IEJ1ZmZbXSA9IFtcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLlBFUkNFTlRfSEVBTFRILCB2YWx1ZTpudW0vMTAwLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LlNISUVMRCwgc3RyaW5nOiBcIlxcblxcbkluY3JlYXNlIG1heCBocCBcXG5ieSBcIitudW0rXCIlXCJ9LFxuICAgICAgICBdO1xuICAgICAgICAvL2lmIHBsYXllciBkb2VzbnQgaGF2ZSBzaGllbGQgYnVmZiwgZ2l2ZSB0aGVtIHRoZSBvcHRpb24sIG90aGVyd2lzZSBnaXZlIGJ1ZmYgc2hpZWxkIG9wdGlvblxuICAgICAgICBpZighdGhpcy5oYXNTaGllbGQpe1xuICAgICAgICAgICAgc2hpZWxkQnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5TSElFTEQsIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuU0hJRUxELCBzdHJpbmc6IFwiXFxuXFxuR2FpbiBTaGllbGQgXFxuV2hlbiBEYW1hZ2VkIFxcbiBTaGllbGRzIHJldHVybiBcXG50aGUgZGFtYWdlIHRha2VuIFxcbnRvIGF0dGFja2VyXCJ9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgc2hpZWxkQnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5TSElFTERfRE1HLCB2YWx1ZTpudW0sIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuU0hJRUxELCBzdHJpbmc6IFwiXFxuXFxuSW5jcmVhc2UgZGFtYWdlIFxcbnJldHVybmVkIGJ5IHNoaWVsZFwifSk7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGxldCBoZWFsdGhCdWZmcyA6IEJ1ZmZbXSA9IFtcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLkRFRiwgdmFsdWU6IG51bS8xMDAsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuSEVBTFRILCBzdHJpbmc6IFwiXFxuXFxuRGVjcmVhc2UgZGFtYWdlIFxcbnRha2VuIGJ5IFwiK251bStcIiVcIn1cbiAgICAgICAgXTtcbiAgICAgICAgaWYoIXRoaXMuZnVsbEhwQm9udXMpe1xuICAgICAgICAgICAgaGVhbHRoQnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5GVUxMSFBCT05VU0RNRywgdmFsdWU6MSwgY2F0ZWdvcnk6QnVmZkNhdGVnb3J5LkhFQUxUSCwgc3RyaW5nOlwiXFxuXFxuRGVhbCAxMHggZGFtYWdlIFxcbiB3aGVuIGF0IGZ1bGwgSFBcIn0pXG5cbiAgICAgICAgfVxuICAgICAgICBpZighdGhpcy5oYXNMaWZlc3RlYWwpe1xuICAgICAgICAgICAgaGVhbHRoQnVmZnMucHVzaCh7dHlwZTpCdWZmVHlwZS5MSUZFU1RFQUwsIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuSEVBTFRILCBzdHJpbmc6XCJcXG5cXG5HYWluIGxpZmVzdGVhbFwifSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZXtcbiAgICAgICAgICAgIGhlYWx0aEJ1ZmZzLnB1c2goe3R5cGU6QnVmZlR5cGUuTElGRVNURUFMQlVGRiwgdmFsdWU6bnVtLzEwMCwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5IRUFMVEgsIHN0cmluZzpcIlxcblxcbkluY3JlYXNlIExpZmVzdGVhbCBcXG5zdHJlbmd0aCBieSBcIisgbnVtKyBcIiVcIn0pO1xuICAgICAgICB9XG5cblxuICAgICAgICBsZXQgZXh0cmFCdWZmcyA6IEJ1ZmZbXSA9IFtcbiAgICAgICAgICAgIHt0eXBlOkJ1ZmZUeXBlLkVYVFJBTElGRSwgdmFsdWU6MSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5FWFRSQSwgc3RyaW5nOiBcIlxcblxcbkdhaW4gYW4gXFxuRXh0cmEgTGlmZVwifSxcbiAgICAgICAgXTtcbiAgICAgICAgaWYoIXRoaXMuaGFzT25lU2hvdCl7ICAgLy9vbmx5IGFkZCBvbmVzaG90IGJ1ZmYgaWYgaXQgaXNudCBhbHJlYWR5IGluY2x1ZGVkIFxuICAgICAgICAgICAgZXh0cmFCdWZmcy5wdXNoKHt0eXBlOkJ1ZmZUeXBlLk9ORVNIT1QsIHZhbHVlOjEsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuRVhUUkEsIHN0cmluZzogXCJcXG5cXG5Zb3VyIGhpdHMgaHVydCBcXG4xMDB4IG1vcmUgYnV0IFxcbnlvdXIgbWF4IGhlYWx0aCBcXG5pcyBzZXQgdG8gMSBcIn0pO1xuICAgICAgICB9O1xuXG5cbiAgICAgICAgbGV0IHNlbGVjdGVkID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHdoaWxlKCBzaHVmZmxlZC5sZW5ndGggIT0gMCl7XG4gICAgICAgICAgICBsZXQgY2F0ID0gc2h1ZmZsZWQucG9wKCk7XG4gICAgICAgICAgICBzd2l0Y2goY2F0KXtcbiAgICAgICAgICAgICAgICBjYXNlIEJ1ZmZDYXRlZ29yeS5BVFRBQ0s6XG4gICAgICAgICAgICAgICAgICAgIGF0dGFja0J1ZmZzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGF0dGFja0J1ZmZzLmxlbmd0aCA9PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goe3R5cGU6QnVmZlR5cGUuUEVSQ0VOVF9IRUFMVEgsIHZhbHVlOm51bS8xMDAsIGNhdGVnb3J5OiBCdWZmQ2F0ZWdvcnkuQVRUQUNLLCBzdHJpbmc6IFwiXFxuXFxuSW5jcmVhc2UgYXR0YWNrIFxcbmJ5XCIrbnVtK1wiJVwifSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goYXR0YWNrQnVmZnMucG9wKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQnVmZkNhdGVnb3J5LkRPVDpcbiAgICAgICAgICAgICAgICAgICAgZG90QnVmZnMuc29ydCgoKSA9PiAwLjUgLSBNYXRoLnJhbmRvbSgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZG90QnVmZnMubGVuZ3RoID09IDApe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQucHVzaCh7dHlwZTpCdWZmVHlwZS5FWFRSQV9ET1QsIHZhbHVlOm51bSwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5ET1QsIHN0cmluZzogXCJcXG5cXG5JbmNyZWFzZSB5b3VyIFxcbkRPVCBkYW1hZ2VcIn0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKGRvdEJ1ZmZzLnBvcCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEJ1ZmZDYXRlZ29yeS5FWFRSQTpcbiAgICAgICAgICAgICAgICAgICAgZXh0cmFCdWZmcy5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpO1xuICAgICAgICAgICAgICAgICAgICBpZihleHRyYUJ1ZmZzLmxlbmd0aCA9PTAgKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goe3R5cGU6QnVmZlR5cGUuRVhUUkFMSUZFLCB2YWx1ZToxLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LkVYVFJBLCBzdHJpbmc6IFwiXFxuXFxuR2FpbiBhbiBcXG5FeHRyYSBMaWZlXCJ9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQucHVzaChleHRyYUJ1ZmZzLnBvcCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEJ1ZmZDYXRlZ29yeS5IRUFMVEg6XG4gICAgICAgICAgICAgICAgICAgIGhlYWx0aEJ1ZmZzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGhlYWx0aEJ1ZmZzLmxlbmd0aCA9PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goe3R5cGU6QnVmZlR5cGUuREVGLCB2YWx1ZTogbnVtLzEwMCwgY2F0ZWdvcnk6IEJ1ZmZDYXRlZ29yeS5IRUFMVEgsIHN0cmluZzogXCJcXG5cXG5EZWNyZWFzZSBkYW1hZ2VcXG4gdGFrZW4gYnkgXCIrbnVtK1wiJVwifSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkLnB1c2goaGVhbHRoQnVmZnMucG9wKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQnVmZkNhdGVnb3J5LlNISUVMRDpcbiAgICAgICAgICAgICAgICAgICAgc2hpZWxkQnVmZnMuc29ydCgoKSA9PiAwLjUgLSBNYXRoLnJhbmRvbSgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2hpZWxkQnVmZnMubGVuZ3RoID09MCApe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQucHVzaCh7dHlwZTpCdWZmVHlwZS5GTEFUX0hFQUxUSCwgdmFsdWU6bnVtLCBjYXRlZ29yeTogQnVmZkNhdGVnb3J5LlNISUVMRH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHNoaWVsZEJ1ZmZzLnBvcCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWxlY3RlZDtcbiAgICB9XG5cblxuXG4gICAgXG4gICAgLyoqXG5cdCAqIEFkZCBnaXZlbiBidWZmIHRvIHRoZSBwbGF5ZXJcblx0ICogQHBhcmFtIGJ1ZmYgR2l2ZW4gYnVmZlxuICAgICAqIEBwYXJhbSBpbml0IHdoZXRoZXIgb3Igbm90IHRoaXMgaXMgYmVpbmcgdXNlZCBkdXJpbmcgdGhlIGluaXRpYWxpemF0aW9uIG9mIHRoZSBwbGF5ZXJcblx0ICovXG4gICAgYWRkQnVmZihidWZmOiBCdWZmLCBpbml0PyA6Qm9vbGVhbiApOiB2b2lkIHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICAvL2FkZCBidWZmIHRvIGFycmF5IG9mIGFwcGxpZWQgYnVmZnMgaWYgbm90IGJlaW5nIHVzZWQgdG8gaW5pdFxuICAgICAgICBpZihpbml0ID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgLy9pbmNyZWFzZSB3ZWlnaHQgb2Ygc2VsZWN0ZWQgYnVmZiBjYXRlZ29yeVxuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5idWZmUG9vbC5wdXNoKGJ1ZmYuY2F0ZWdvcnkpO1xuICAgICAgICAgICAgUGxheWVyQ29udHJvbGxlci5hcHBsaWVkQnVmZnMucHVzaChidWZmKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaW5pdCl7XG4gICAgICAgICAgICAvL2luY3JlYXNlIHdlaWdodCBvZiBzZWxlY3RlZCBidWZmIGNhdGVnb3J5XG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmJ1ZmZQb29sLnB1c2goYnVmZi5jYXRlZ29yeSk7XG4gICAgICAgICAgICBQbGF5ZXJDb250cm9sbGVyLmFwcGxpZWRCdWZmcy5wdXNoKGJ1ZmYpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRPRE9cbiAgICAgICAgbGV0IGl0ZW0gPSB0aGlzLmludmVudG9yeS5nZXRJdGVtKCk7XG4gICAgICAgIHN3aXRjaChidWZmLnR5cGUpe1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5GTEFUX0hFQUxUSDpcbiAgICAgICAgICAgICAgICAvL3RoaXMuQ1VSUkVOVF9CVUZGUy5ocCArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9IUCArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIHRoaXMuTUFYX0hQICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlBFUkNFTlRfSEVBTFRIOlxuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9IUCAqPSAoMStidWZmLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLk1BWF9IUCAqPSAoMStidWZmLnZhbHVlKSA7XG4gICAgICAgICAgICAgICAgdGhpcy5DVVJSRU5UX0hQID0gTWF0aC5yb3VuZCh0aGlzLkNVUlJFTlRfSFApO1xuICAgICAgICAgICAgICAgIHRoaXMuTUFYX0hQID0gTWF0aC5yb3VuZCh0aGlzLk1BWF9IUCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkZMQVRfQVRLOlxuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9BVEsgKz1idWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5QRVJDRU5UX0FUSzpcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfQVRLICo9YnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfQVRLID0gTWF0aC5yb3VuZCh0aGlzLkNVUlJFTlRfQVRLKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuU1BFRUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5zcGVlZCArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5ERUY6XG4gICAgICAgICAgICAgICAgdGhpcy5kYW1hZ2VfbXVsdGlwbGllciAqPSAoMS1idWZmLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuUkFOR0U6XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgKDxXZWFwb24+aXRlbSkuRVhUUkFfUkFOR0UgKz0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkJMRUVEOlxuICAgICAgICAgICAgICAgIHRoaXMuaGFzQmxlZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5CVVJOOlxuICAgICAgICAgICAgICAgIHRoaXMuaGFzQnVybiA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlBPSVNPTjpcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1BvaXNvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkVYVFJBX0RPVDpcbiAgICAgICAgICAgICAgICB0aGlzLmV4dHJhRG90RG1nICs9IGJ1ZmYudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlNISUVMRDpcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1NoaWVsZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgQnVmZlR5cGUuQVRLU1BFRUQ6XG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb29sZG93bk11bHRpcGxpZXIgLT0gYnVmZi52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgLy9yZWR1Y2UgY29vbGRvd250aW1lciBcbiAgICAgICAgICAgICAgICAgICAgKDxXZWFwb24+aXRlbSkuY29vbGRvd25UaW1lciA9IG5ldyBUaW1lcigoPFdlYXBvbj5pdGVtKS5jb29sZG93biAqIHRoaXMuY29vbGRvd25NdWx0aXBsaWVyIClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLlNISUVMRF9ETUc6XG4gICAgICAgICAgICAgICAgdGhpcy5zaGllbGREYW1hZ2UgKz0gYnVmZi52YWx1ZSA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkVYVFJBTElGRTpcbiAgICAgICAgICAgICAgICB0aGlzLmxpdmVzICsrO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5MSUZFU1RFQUw6XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNMaWZlc3RlYWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMubGlmZXN0ZWFscmF0aW8gPSAuMjsgLy8yMCUgbGlmZXN0ZWFsXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEJ1ZmZUeXBlLkxJRkVTVEVBTEJVRkY6XG4gICAgICAgICAgICAgICAgdGhpcy5saWZlc3RlYWxyYXRpbyArPSBidWZmLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5PTkVTSE9UOlxuICAgICAgICAgICAgICAgIHRoaXMuTUFYX0hQID0gMTtcbiAgICAgICAgICAgICAgICB0aGlzLkNVUlJFTlRfSFAgPSAxO1xuICAgICAgICAgICAgICAgIHRoaXMuQ1VSUkVOVF9BVEsgKj0gMTAwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBCdWZmVHlwZS5GVUxMSFBCT05VU0RNRzpcbiAgICAgICAgICAgICAgICB0aGlzLmZ1bGxIcEJvbnVzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFxuICAgICAqIEByZXR1cm5zIHJlY29yZCBvZiB0aGUgcGxheWVyIHN0YXRzXG4gICAgICovXG4gICAgZ2V0U3RhdHMoKTogUmVjb3JkPHN0cmluZywgYW55PntcbiAgICAgICAgbGV0IHN0YXRzID0ge30gYXMgUmVjb3JkPHN0cmluZyxhbnk+O1xuICAgICAgICBzdGF0cy5DVVJSRU5UX0hQID0gdGhpcy5DVVJSRU5UX0hQO1xuICAgICAgICBzdGF0cy5DVVJSRU5UX0FUSyA9IHRoaXMuQ1VSUkVOVF9BVEs7XG4gICAgICAgIHN0YXRzLkNVUlJFTlRfU0hJRUxEID0gdGhpcy5DVVJSRU5UX1NISUVMRDtcbiAgICAgICAgc3RhdHMuQ1VSUkVOVF9FWFAgPSB0aGlzLkNVUlJFTlRfRVhQO1xuXG4gICAgICAgIHJldHVybiBcbiAgICB9XG4gICAgICAgIFxuXG4gICAgdG9TdHJpbmcoKTogc3RyaW5ne1xuICAgICAgICBsZXQgcyA9IFwiSFA6IFwiICsgdGhpcy5DVVJSRU5UX0hQICtcIi9cIit0aGlzLk1BWF9IUCtcbiAgICAgICAgICAgICAgICBcIlxcbkFUSzogXCIgKyB0aGlzLkNVUlJFTlRfQVRLICtcbiAgICAgICAgICAgICAgICBcIlxcblNwZWVkOiBcIiArIHRoaXMuc3BlZWQgK1xuICAgICAgICAgICAgICAgIFwiXFxuRGFtYWdlIFJhdGlvOiBcIiArIHRoaXMuZGFtYWdlX211bHRpcGxpZXIgK1xuICAgICAgICAgICAgICAgIFwiXFxuRW5lbWllcyBLaWxsZWQ6IFwiICsgdGhpcy5lbmVtaWVzS2lsbGVkICsgXG4gICAgICAgICAgICAgICAgXCJcXG5Td29yZCBFZmZlY3RzOlwiICtcbiAgICAgICAgICAgICAgICAodGhpcy5oYXNCbGVlZCA/IFwiXFxuICBCbGVlZCxcIiA6IFwiICBcIikgKyBcbiAgICAgICAgICAgICAgICAodGhpcy5oYXNCdXJuID8gXCIgQnVybixcIiA6IFwiXCIpICsgXG4gICAgICAgICAgICAgICAgKHRoaXMuaGFzUG9pc29uID8gXCIgUG9pc29uLFwiIDogXCJcIikgKyBcbiAgICAgICAgICAgICAgICAodGhpcy5oYXNTaGllbGQgPyBcIiBTaGllbGQsXCIgOlwiXCIpICsgXG4gICAgICAgICAgICAgICAgKHRoaXMuZnVsbEhwQm9udXMgPyBcIiBGdWxsSGVhbHRoIGRlYWwgeDEwIERtZ1wiIDogXCJcIikgK1xuICAgICAgICAgICAgICAgICh0aGlzLmhhc0xpZmVzdGVhbCA/IFwiIExpZmVzdGVhbCxcIiA6IFwiXCIpICtcbiAgICAgICAgICAgICAgICAodGhpcy5oYXNPbmVTaG90ID8gXCIgQXRrIHggMTAwLCBtYXhocCBzZXQgdG8gMVwiIDogXCJcIikgO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbn0iLCJpbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBJbkFpciBmcm9tIFwiLi9JbkFpclwiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgUGxheWVyU3RhdGUgZnJvbSBcIi4vUGxheWVyU3RhdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFsbCBleHRlbmRzIEluQWlyIHtcbiAgICBvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0Ly8gdGhpcy5vd25lci5hbmltYXRpb24ucGxheShcIkZBTExcIiwgdHJ1ZSk7XG5cdH1cblxuICAgIHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiREFTSFwiKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5wYXJlbnQuaW52aW5jaWJsZSkge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSFVSVFwiKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiRkFMTFwiLCB0cnVlKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0Ly9UT0RPIC0gdGVzdGluZyBkb3VibGVqdW1wLCBtYXkgaGF2ZSB0byBtb3ZlIHRvIEluQWlyIGluc3RlYWRcblx0XHQvLyBJZiB3ZSBqdW1wLCBtb3ZlIHRvIHRoZSBKdW1wIHN0YXRlLCBnaXZlIGEgYnVyc3Qgb2YgdXB3YXJkcyB2ZWxvY2l0eVxuXHRcdGlmKCB0aGlzLnBhcmVudC5haXJqdW1wcz4wICYmIElucHV0V3JhcHBlci5pc0p1bXBKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMucGFyZW50LmFpcmp1bXBzIC0tO1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdH0gXG5cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcbiAgICB9XG4gICAgb25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnN0b3AoKTtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbn0iLCJpbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgT25Hcm91bmQgZnJvbSBcIi4vT25Hcm91bmRcIjtcbmltcG9ydCBQbGF5ZXJTdGF0ZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJZGxlIGV4dGVuZHMgT25Hcm91bmQge1xuXHRvd25lcjogQW5pbWF0ZWRTcHJpdGU7XG5cblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG5cdFx0dGhpcy5wYXJlbnQuc3BlZWQgPSB0aGlzLnBhcmVudC5NSU5fU1BFRUQ7XG5cdH1cblxuXHRcblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0XG4gICAgICAgIC8vKFwiaWRsZSBhbmltXCIpO1xuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcIlBsYXlpbmcgZGFzaFwiKTtcblx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJEQVNIXCIpO1xuXHRcdH1cblx0XHRlbHNlIHtcbiAgICAgICAgXHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSURMRVwiLCB0cnVlKTtcblx0XHR9XG5cblx0XHRsZXQgZGlyID0gdGhpcy5nZXRJbnB1dERpcmVjdGlvbigpO1xuXG5cdFx0aWYoIWRpci5pc1plcm8oKSAmJiBkaXIueSA9PT0gMCl7XG5cdFx0XHR0aGlzLmZpbmlzaGVkKFBsYXllclN0YXRlcy5XQUxLKTtcblx0XHR9XG5cdFx0XG5cdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueCA9IDA7XG5cdFx0c3VwZXIudXBkYXRlKGRlbHRhVCk7XG5cdH1cblxuXHRvbkV4aXQoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG5cdFx0dGhpcy5vd25lci5hbmltYXRpb24uc3RvcCgpO1xuXHRcdHJldHVybiB7fTtcblx0fVxufSIsImltcG9ydCBHYW1lRXZlbnQgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgTWF0aFV0aWxzIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9VdGlscy9NYXRoVXRpbHNcIjtcbmltcG9ydCB7IFBsYXllclN0YXRlcyB9IGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5pbXBvcnQgUGxheWVyU3RhdGUgZnJvbSBcIi4vUGxheWVyU3RhdGVcIjtcblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgSW5BaXIgZXh0ZW5kcyBQbGF5ZXJTdGF0ZSB7XG4gICAgXG4gICAgdXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXG4gICAgICAgIGxldCBkaXIgPSB0aGlzLmdldElucHV0RGlyZWN0aW9uKCk7XG5cbiAgICAgICAgaWYoZGlyLnggIT09IDApe1xuXHRcdFx0KDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IE1hdGhVdGlscy5zaWduKGRpci54KSA8IDA7XG5cdFx0fVxuICAgICAgICBcblx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ICs9IGRpci54ICogKHRoaXMucGFyZW50LnNwZWVkKS8zLjUgLSAwLjMqdGhpcy5wYXJlbnQudmVsb2NpdHkueDtcblxuXG4gICAgICAgIGlmKHRoaXMub3duZXIub25Hcm91bmQpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChQbGF5ZXJTdGF0ZXMuUFJFVklPVVMpO1xuXHRcdH1cbiAgICB9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgeyBFYXNlRnVuY3Rpb25UeXBlIH0gZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL0Vhc2VGdW5jdGlvbnNcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBJbkFpciBmcm9tIFwiLi9JbkFpclwiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEp1bXAgZXh0ZW5kcyBJbkFpciB7XG5cdG93bmVyOiBBbmltYXRlZFNwcml0ZTtcblxuXHRvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHR0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJqdW1wXCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuXHR9XG5cblx0XG5cblx0dXBkYXRlKGRlbHRhVDogbnVtYmVyKTogdm9pZCB7XG5cdFx0aWYgKCFQbGF5ZXJTdGF0ZS5kYXNoVGltZXIuaXNTdG9wcGVkKCkpIHtcblx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJEQVNIXCIpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmICh0aGlzLnBhcmVudC5pbnZpbmNpYmxlKSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJIVVJUXCIpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnBsYXlJZk5vdEFscmVhZHkoXCJKVU1QXCIsIHRydWUpO1xuXHRcdFx0fVxuXHRcdH1cblxuXG5cdFx0aWYodGhpcy5vd25lci5vbkNlaWxpbmcpe1xuXHRcdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSA9IDA7XG5cdFx0fVxuXG5cdFx0Ly9UT0RPIC0gdGVzdGluZyBkb3VibGVqdW1wLCBtYXkgaGF2ZSB0byBtb3ZlIHRvIEluQWlyIGluc3RlYWRcblx0XHQvLyBJZiB3ZSBqdW1wLCBtb3ZlIHRvIHRoZSBKdW1wIHN0YXRlLCBnaXZlIGEgYnVyc3Qgb2YgdXB3YXJkcyB2ZWxvY2l0eVxuXHRcdGlmKCB0aGlzLnBhcmVudC5haXJqdW1wcz4wICYmIElucHV0V3JhcHBlci5pc0p1bXBKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMucGFyZW50LmFpcmp1bXBzIC0tO1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdFx0XG5cdFx0fSBcblxuXHRcdC8vIElmIHdlJ3JlIGZhbGxpbmcsIGdvIHRvIHRoZSBmYWxsIHN0YXRlXG5cdFx0aWYodGhpcy5wYXJlbnQudmVsb2NpdHkueSA+PSAwKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoUGxheWVyU3RhdGVzLkZBTEwpO1xuXHRcdH1cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblx0fVxuXG5cdG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5zdG9wKCk7XG5cdFx0cmV0dXJuIHt9O1xuXHR9XG59IiwiaW1wb3J0IEdhbWVFdmVudCBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFwiO1xuaW1wb3J0IEdhbWUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0xvb3AvR2FtZVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBNYXRoVXRpbHMgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1V0aWxzL01hdGhVdGlsc1wiO1xuaW1wb3J0IHsgR2FtZVN0YXRlIH0gZnJvbSBcIi4uLy4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi8uLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBQbGF5ZXJTdGF0ZSBmcm9tIFwiLi9QbGF5ZXJTdGF0ZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBPbkdyb3VuZCBleHRlbmRzIFBsYXllclN0YXRlIHtcblx0b25FbnRlcihvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7fVxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vcmVzZXQgYWlyanVtcHNcblx0XHR0aGlzLnBhcmVudC5haXJqdW1wcyA9IHRoaXMucGFyZW50Lk1BWF9haXJqdW1wcztcblxuXHRcdGlmKHRoaXMucGFyZW50LnZlbG9jaXR5LnkgPiAwKXtcblx0XHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnkgPSAwO1xuXHRcdH1cblxuXG5cdFx0XG5cblx0XHRsZXQgZGlyZWN0aW9uID0gdGhpcy5nZXRJbnB1dERpcmVjdGlvbigpO1xuXG5cdFx0aWYoZGlyZWN0aW9uLnggIT09IDApe1xuXHRcdFx0KDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA9IE1hdGhVdGlscy5zaWduKGRpcmVjdGlvbi54KSA8IDA7XG5cdFx0fVxuXG5cdFxuXHRcdC8vIElmIHdlIGp1bXAsIG1vdmUgdG8gdGhlIEp1bXAgc3RhdGUsIGdpdmUgYSBidXJzdCBvZiB1cHdhcmRzIHZlbG9jaXR5XG5cdFx0aWYoSW5wdXRXcmFwcGVyLmlzSnVtcEp1c3RQcmVzc2VkKCkpe1xuXHRcdFx0dGhpcy5maW5pc2hlZChcImp1bXBcIik7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS55ID0gLTYwMDtcdC8vIGJhc2ljYWxseSBqdW1wIGhlaWdodFxuXHRcdFx0XG5cdFx0fSBcblx0XHRlbHNlIGlmKCF0aGlzLm93bmVyLm9uR3JvdW5kICYmIElucHV0V3JhcHBlci5nZXRTdGF0ZSgpID09PSBHYW1lU3RhdGUuR0FNSU5HKXtcblx0XHRcdHRoaXMuZmluaXNoZWQoXCJmYWxsXCIpO1xuXHRcdH1cblx0XHRzdXBlci51cGRhdGUoZGVsdGFUKTtcblx0XHRcblx0fVxuXG5cdG9uRXhpdCgpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcblx0XHRyZXR1cm4ge307XG5cdH1cbn0iLCJpbXBvcnQgU3RhdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGF0ZS9TdGF0ZVwiO1xuaW1wb3J0IFN0YXRlTWFjaGluZSBmcm9tIFwiLi4vLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1N0YXRlL1N0YXRlTWFjaGluZVwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgR2FtZUV2ZW50IGZyb20gXCIuLi8uLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50XCI7XG5pbXBvcnQgR2FtZU5vZGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvU3ByaXRlXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL1RpbWluZy9UaW1lclwiO1xuaW1wb3J0IHsgR2FtZVN0YXRlLCBQbGF5ZXJfRXZlbnRzIH0gZnJvbSBcIi4uLy4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi8uLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcbmltcG9ydCBQbGF5ZXJDb250cm9sbGVyIGZyb20gXCIuLi9QbGF5ZXJDb250cm9sbGVyXCI7XG5cblxuZXhwb3J0IGRlZmF1bHQgYWJzdHJhY3QgY2xhc3MgUGxheWVyU3RhdGUgZXh0ZW5kcyBTdGF0ZSB7XG5cdG93bmVyOiBHYW1lTm9kZTtcblx0Z3Jhdml0eTogbnVtYmVyID0gMTUwMDsgLy9UT0RPIC0gY2FuIGNoYW5nZSBsYXRlclxuXHRwYXJlbnQ6IFBsYXllckNvbnRyb2xsZXI7XG5cdHBvc2l0aW9uVGltZXI6IFRpbWVyO1xuXHRzdGF0aWMgZGFzaFRpbWVyOiBUaW1lcjtcblx0c3RhdGljIGRhc2hDb29sRG93blRpbWVyOiBUaW1lcjtcblxuXHRjb25zdHJ1Y3RvcihwYXJlbnQ6IFN0YXRlTWFjaGluZSwgb3duZXI6IEdhbWVOb2RlKXtcblx0XHRzdXBlcihwYXJlbnQpO1xuXHRcdHRoaXMub3duZXIgPSBvd25lcjtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIgPSBuZXcgVGltZXIoMjUwKTtcblx0XHR0aGlzLnBvc2l0aW9uVGltZXIuc3RhcnQoKTtcblx0XHRQbGF5ZXJTdGF0ZS5kYXNoVGltZXIgPSBuZXcgVGltZXIoMTAwKTtcblx0XHRQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lciA9IG5ldyBUaW1lcig2MDApO1xuXG5cdH1cblxuXHRcblx0aGFuZGxlSW5wdXQoZXZlbnQ6IEdhbWVFdmVudCk6IHZvaWQge1xuXHRcdFxuXHR9XG5cblx0ZG9EYXNoKCk6IHZvaWQge1xuXHRcdGlmIChQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lci5pc1N0b3BwZWQoKSkge1xuXHRcdFx0Ly9UT0RPIC0gZGVjaWRlIGhvdyB0byBpbXBsZW1lbnQgZGFzaCAtIGNvdWxkIGJlIGEgZmxhc2ggLSBtYXliZSBhbGxvdyBpbiBhaXIgYXMgd2VsbFxuXHRcdFx0Ly9wbGF5IGRhc2ggYW5pbSBtYXliZVxuXHRcdFx0Ly9UT0RPIC0gbWlnaHQgZ2l2ZSBidWZmZWQgc3BlZWQgc3RhdCB0byBkYXNoIHNwZWVkXG5cdFx0XHQvL1RPRE8gLSBnaXZlIHBsYXllciBpIGZyYW1lXG5cdFx0XHRQbGF5ZXJTdGF0ZS5kYXNoQ29vbERvd25UaW1lci5zdGFydCgpO1xuXHRcdFx0UGxheWVyU3RhdGUuZGFzaFRpbWVyLnN0YXJ0KCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqIFxuXHQgKiBHZXQgdGhlIGlucHV0cyBmcm9tIHRoZSBrZXlib2FyZCwgb3IgVmVjMi5aZXJvIGlmIG5vdGhpbmcgaXMgYmVpbmcgcHJlc3NlZFxuXHQgKi9cblx0Z2V0SW5wdXREaXJlY3Rpb24oKTogVmVjMiB7XG5cdFx0bGV0IGRpcmVjdGlvbiA9IFZlYzIuWkVSTztcblx0XHRkaXJlY3Rpb24ueCA9IChJbnB1dFdyYXBwZXIuaXNMZWZ0UHJlc3NlZCgpID8gLTEgOiAwKSArIChJbnB1dFdyYXBwZXIuaXNSaWdodFByZXNzZWQoKSA/IDEgOiAwKTtcblx0XHRkaXJlY3Rpb24ueSA9IChJbnB1dFdyYXBwZXIuaXNKdW1wSnVzdFByZXNzZWQoKSA/IC0xIDogMCk7XG5cdFx0cmV0dXJuIGRpcmVjdGlvbjtcblx0fVxuXG5cdFxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdC8vIERvIGdyYXZpdHlcblx0XHRcblx0XHRpZiAodGhpcy5wb3NpdGlvblRpbWVyLmlzU3RvcHBlZCgpKXtcblx0XHRcdHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5QTEFZRVJfTU9WRSwge3Bvc2l0aW9uOiB0aGlzLm93bmVyLnBvc2l0aW9uLmNsb25lKCl9KTtcblx0XHRcdHRoaXMucG9zaXRpb25UaW1lci5zdGFydCgpO1xuXHRcdH1cblx0XHRcblxuXHRcdGlmKElucHV0V3JhcHBlci5pc0Rhc2hKdXN0UHJlc3NlZCgpKXtcblx0XHRcdHRoaXMuZG9EYXNoKCk7XG5cdFx0fVxuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHR0aGlzLnBhcmVudC52ZWxvY2l0eS54ID0gKDxTcHJpdGU+dGhpcy5vd25lcikuaW52ZXJ0WCA/IC04MDAgOiA4MDA7XG5cdFx0fVxuXHRcdGlmIChJbnB1dFdyYXBwZXIuZ2V0U3RhdGUoKSA9PT0gR2FtZVN0YXRlLkdBTUlORykge1xuXHRcdFx0KDxBbmltYXRlZFNwcml0ZT50aGlzLnBhcmVudC5vd25lcikuYW5pbWF0aW9uLnJlc3VtZSgpO1xuXHRcdFx0dGhpcy5wYXJlbnQudmVsb2NpdHkueSArPSB0aGlzLmdyYXZpdHkqZGVsdGFUO1xuXHRcdFx0dGhpcy5vd25lci5tb3ZlKHRoaXMucGFyZW50LnZlbG9jaXR5LnNjYWxlZChkZWx0YVQpKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQoPEFuaW1hdGVkU3ByaXRlPnRoaXMucGFyZW50Lm93bmVyKS5hbmltYXRpb24ucGF1c2UoKTtcblx0XHR9XG5cdH1cbn0iLCJpbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCB7IFBsYXllcl9FdmVudHMgfSBmcm9tIFwiLi4vLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uLy4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IHsgUGxheWVyU3RhdGVzIH0gZnJvbSBcIi4uL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCBPbkdyb3VuZCBmcm9tIFwiLi9Pbkdyb3VuZFwiO1xuaW1wb3J0IFBsYXllclN0YXRlIGZyb20gXCIuL1BsYXllclN0YXRlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFdhbGsgZXh0ZW5kcyBPbkdyb3VuZCB7XG5cdG93bmVyOiBBbmltYXRlZFNwcml0ZTtcblxuXHRvbkVudGVyKG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcblx0XHR0aGlzLnBhcmVudC5zcGVlZCA9IHRoaXMucGFyZW50Lk1JTl9TUEVFRDtcbiAgICAgICAgXG5cdH1cblxuXG5cdHVwZGF0ZShkZWx0YVQ6IG51bWJlcik6IHZvaWQge1xuXHRcdGlmICghUGxheWVyU3RhdGUuZGFzaFRpbWVyLmlzU3RvcHBlZCgpKSB7XG5cdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiREFTSFwiKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5wYXJlbnQuaW52aW5jaWJsZSkge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiSFVSVFwiKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR0aGlzLm93bmVyLmFuaW1hdGlvbi5wbGF5SWZOb3RBbHJlYWR5KFwiV0FMS1wiLCB0cnVlKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0bGV0IGRpciA9IHRoaXMuZ2V0SW5wdXREaXJlY3Rpb24oKTtcblxuXHRcdGlmKGRpci5pc1plcm8oKSl7XG5cdFx0XHR0aGlzLmZpbmlzaGVkKFBsYXllclN0YXRlcy5JRExFKTtcblx0XHR9IFxuXHRcdFxuXHRcdHRoaXMucGFyZW50LnZlbG9jaXR5LnggPSBkaXIueCAqICh0aGlzLnBhcmVudC5zcGVlZCApO1xuXHRcdFxuXHRcdHN1cGVyLnVwZGF0ZShkZWx0YVQpO1xuXHR9XG5cblx0b25FeGl0KCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdHRoaXMub3duZXIuYW5pbWF0aW9uLnN0b3AoKTtcblx0XHRyZXR1cm4ge307XG5cdH1cbn0iLCJpbXBvcnQgUmVnaXN0cnkgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJpZXMvUmVnaXN0cnlcIjtcbmltcG9ydCBSZXNvdXJjZU1hbmFnZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1Jlc291cmNlTWFuYWdlci9SZXNvdXJjZU1hbmFnZXJcIjtcblxuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGVcIjtcbmltcG9ydCBTbGljZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvU2xpY2VcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2VhcG9uVGVtcGxhdGVSZWdpc3RyeSBleHRlbmRzIFJlZ2lzdHJ5PFdlYXBvbkNvbnN0cnVjdG9yPiB7XG4gICAgXG4gICAgcHVibGljIHByZWxvYWQoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJtID0gUmVzb3VyY2VNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG5cbiAgICAgICAgLy9UT0RPIC0gXG4gICAgICAgIC8vIExvYWQgc3ByaXRlcyBmb3IgZWFjaCB3ZWFwb24gXG4gICAgICAgIC8vcm0uaW1hZ2UoXCJzb21ldGhpbmdcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMvc29tZXRoaW5nLnBuZ1wiKTtcbiAgICAgICAgcm0uaW1hZ2UoXCJrbmlmZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlcy9rbmlmZS5wbmdcIik7XG5cbiAgICAgICAgLy8gTG9hZCBzcHJpdGVzaGVldHNcbiAgICAgICAgLy9ybS5zcHJpdGVzaGVldChcIndlYXBvbiBhbmltXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvd2VhcG9uIGFuaW0uanNvblwiKTtcbiAgICAgICAgcm0uc3ByaXRlc2hlZXQoXCJzbGljZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3NsaWNlLmpzb25cIik7XG5cbiAgICAgICAgLy8gUmVnaXN0ZXIgZGVmYXVsdCB0eXBlc1xuICAgICAgICAvL3RoaXMucmVnaXN0ZXJJdGVtKFwiaXRlbXR5cGVcIiwgaXRlbVR5cGVmaWxlKTtcbiAgICAgICAgdGhpcy5yZWdpc3Rlckl0ZW0oXCJzbGljZVwiLCBTbGljZSk7XG4gICAgICAgIFxuICAgIH1cblxuICAgIFxuICAgIHB1YmxpYyByZWdpc3RlckFuZFByZWxvYWRJdGVtKGtleTogc3RyaW5nKTogdm9pZCB7fVxuXG4gICAgcHVibGljIHJlZ2lzdGVySXRlbShrZXk6IHN0cmluZywgY29uc3RyOiBXZWFwb25Db25zdHJ1Y3Rvcik6IHZvaWQge1xuICAgICAgICB0aGlzLmFkZChrZXksIGNvbnN0cik7XG4gICAgfVxufVxuXG50eXBlIFdlYXBvbkNvbnN0cnVjdG9yID0gbmV3ICguLi5hcmdzOiBhbnkpID0+IFdlYXBvblR5cGU7IiwiaW1wb3J0IFJlZ2lzdHJ5IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9SZWdpc3RyeS9SZWdpc3RyaWVzL1JlZ2lzdHJ5XCI7XG5pbXBvcnQgV2VhcG9uVHlwZSBmcm9tIFwiLi4vR2FtZVN5c3RlbXMvaXRlbXMvV2VhcG9uVHlwZXMvV2VhcG9uVHlwZVwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWFwb25UeXBlUmVnaXN0cnkgZXh0ZW5kcyBSZWdpc3RyeTxXZWFwb25UeXBlPiB7XG4gICAgXG4gICAgcHVibGljIHByZWxvYWQoKTogdm9pZCB7fVxuXG4gICAgLy8gV2UgZG9uJ3QgbmVlZCB0aGlzIGZvciB0aGlzIGFzc2lnbm1lbnRcbiAgICBwdWJsaWMgcmVnaXN0ZXJBbmRQcmVsb2FkSXRlbShrZXk6IHN0cmluZyk6IHZvaWQge31cblxuICAgIHB1YmxpYyByZWdpc3Rlckl0ZW0oa2V5OiBzdHJpbmcsIHR5cGU6IFdlYXBvblR5cGUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hZGQoa2V5LCB0eXBlKTtcbiAgICB9XG59IiwiaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgRGVidWcgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RlYnVnL0RlYnVnXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgeyBUd2VlbmFibGVQcm9wZXJ0aWVzIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0dhbWVOb2RlXCI7XG5pbXBvcnQgeyBHcmFwaGljVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9HcmFwaGljVHlwZXNcIjtcbmltcG9ydCBQb2ludCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvR3JhcGhpY3MvUG9pbnRcIjtcbmltcG9ydCBSZWN0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9HcmFwaGljcy9SZWN0XCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBMYWJlbCwgeyBIQWxpZ24gfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgVGltZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1RpbWluZy9UaW1lclwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IHsgRWFzZUZ1bmN0aW9uVHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9FYXNlRnVuY3Rpb25zXCI7XG5pbXBvcnQgUGxheWVyQ29udHJvbGxlciBmcm9tIFwiLi4vUGxheWVyL1BsYXllckNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IEdhbWVTdGF0ZSwgUGxheWVyX0V2ZW50cywgU3RhdHVzZXMgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBSZWdpc3RyeU1hbmFnZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1JlZ2lzdHJ5L1JlZ2lzdHJ5TWFuYWdlclwiO1xuaW1wb3J0IFdlYXBvblR5cGUgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblR5cGVzL1dlYXBvblR5cGVcIjtcbmltcG9ydCBXZWFwb24gZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL2l0ZW1zL1dlYXBvblwiO1xuaW1wb3J0IEJhdHRsZU1hbmFnZXIgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL0JhdHRsZU1hbmFnZXJcIjtcbmltcG9ydCBFbmVteUFJIGZyb20gXCIuLi9BSS9FbmVteUFJXCI7XG5pbXBvcnQgU25ha2VBSSBmcm9tIFwiLi4vQUkvU25ha2VBSVwiO1xuaW1wb3J0IFNsaW1lQUkgZnJvbSBcIi4uL0FJL1NsaW1lQUlcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IEludmVudG9yeU1hbmFnZXIgZnJvbSBcIi4uL0dhbWVTeXN0ZW1zL0ludmVudG9yeU1hbmFnZXJcIjtcbmltcG9ydCBJdGVtIGZyb20gXCIuLi9HYW1lU3lzdGVtcy9pdGVtcy9JdGVtXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IHsgQnVmZiB9IGZyb20gXCIuLi9QbGF5ZXIvUGxheWVyQ29udHJvbGxlclwiO1xuaW1wb3J0IENhbnZhc05vZGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL0NhbnZhc05vZGVcIjtcbmltcG9ydCBSYW5kb21NYXBHZW5lcmF0b3IsIHsgRW5lbXkgfSBmcm9tIFwiLi4vVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yXCI7XG5pbXBvcnQgU3RhY2sgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TdGFja1wiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5pbXBvcnQgU3RvcnkgZnJvbSBcIi4uL1Rvb2xzL0RhdGFUeXBlcy9TdG9yeVwiO1xuaW1wb3J0IFNwcml0ZSBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvU3ByaXRlcy9TcHJpdGVcIjtcbmltcG9ydCBUZXh0SW5wdXQgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVGV4dElucHV0XCI7XG5pbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBHYW1lT3ZlciBmcm9tIFwiLi9HYW1lT3ZlclwiO1xuaW1wb3J0IFBvcmNlbGFpbiBmcm9tIFwiLi9Qb3JjZWxhaW5cIjtcbmltcG9ydCBUdXRvcmlhbCBmcm9tIFwiLi9UdXRvcmlhbFwiO1xuaW1wb3J0IEdyZWF0d2FsbCBmcm9tIFwiLi9HcmVhdHdhbGxcIjtcbmltcG9ydCBNYWluTWVudSBmcm9tIFwiLi9NYWluTWVudVwiO1xuXG4vLyAgVE9ET1xuLyoqXG4gKiBBZGQgaW4gc29tZSBsZXZlbCBtdXNpYy5cbiAqIFRoaXMgY2FuIGJlIGRvbmUgaGVyZSBpbiB0aGUgYmFzZSBHYW1lTGV2ZWwgY2xhc3Mgb3IgaW5kaXZpZHVhbCBsZXZlbCBmaWxlc1xuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHYW1lTGV2ZWwgZXh0ZW5kcyBTY2VuZSB7XG4gICAgLy8gRXZlcnkgbGV2ZWwgd2lsbCBoYXZlIGEgcGxheWVyLCB3aGljaCB3aWxsIGJlIGFuIGFuaW1hdGVkIHNwcml0ZVxuICAgIHByb3RlY3RlZCBwbGF5ZXJTcGF3bjogVmVjMjtcbiAgICBwcm90ZWN0ZWQgcGxheWVyOiBBbmltYXRlZFNwcml0ZTtcbiAgICBwcm90ZWN0ZWQgcmVzcGF3blRpbWVyOiBUaW1lcjtcblxuICAgIC8vIExhYmVscyBmb3IgdGhlIFVJXG4gICAgLy9UT0RPIC0gbGl2ZXMgaGVyZSBvciBpbiBwbGF5ZXJjb250cm9sbGVyXG4gICAgcHJvdGVjdGVkIHN0YXRpYyBsaXZlc0NvdW50OiBudW1iZXIgPSAzO1xuICAgIHByb3RlY3RlZCBsaXZlc0NvdW50TGFiZWw6IExhYmVsO1xuXG4gICAgLy8gU3R1ZmYgdG8gZW5kIHRoZSBsZXZlbCBhbmQgZ28gdG8gdGhlIG5leHQgbGV2ZWxcbiAgICBwcm90ZWN0ZWQgbGV2ZWxFbmRBcmVhOiBSZWN0O1xuICAgIHByb3RlY3RlZCBuZXh0TGV2ZWw6IG5ldyAoLi4uYXJnczogYW55KSA9PiBHYW1lTGV2ZWw7XG4gICAgcHJvdGVjdGVkIGxldmVsRW5kVGltZXI6IFRpbWVyO1xuICAgIHByb3RlY3RlZCBsZXZlbEVuZExhYmVsOiBMYWJlbDtcbiAgICBcbiAgICAvLyBTY3JlZW4gZmFkZSBpbi9vdXQgZm9yIGxldmVsIHN0YXJ0IGFuZCBlbmRcbiAgICBwcm90ZWN0ZWQgbGV2ZWxUcmFuc2l0aW9uVGltZXI6IFRpbWVyO1xuICAgIHByb3RlY3RlZCBsZXZlbFRyYW5zaXRpb25TY3JlZW46IFJlY3Q7XG5cbiAgICAvLyBUaGUgYmF0dGxlIG1hbmFnZXIgZm9yIHRoZSBzY2VuZVxuICAgIHByb3RlY3RlZCBiYXR0bGVNYW5hZ2VyOiBCYXR0bGVNYW5hZ2VyO1xuXG4gICAgLy8gSGVhbHRoIFVJXG4gICAgcHJvdGVjdGVkIGhlYWx0aExhYmVsOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgaGVhbHRoQmFyOiBSZWN0O1xuICAgIC8vZXhwIGxhYmVsXG4gICAgcHJvdGVjdGVkIGV4cExhYmVsIDogTGFiZWw7XG4gICAgcHJvdGVjdGVkIGV4cEJhcjogUmVjdDtcblxuICAgIC8vbGV2ZWwgbGFiZWxcbiAgICBwcm90ZWN0ZWQgcGxheWVyTGV2ZWxMYWJlbCA6IExhYmVsO1xuXG4gICAgLy9zaGllbGQgbGFiZWxcbiAgICBwcm90ZWN0ZWQgc2hpZWxkTGFiZWwgOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgc2hpZWxkQmFyOiBSZWN0O1xuXG4gICAgcHJvdGVjdGVkIHBvaXNvblN0YXQ6IFNwcml0ZTtcbiAgICBwcm90ZWN0ZWQgYnVyblN0YXQ6IFNwcml0ZTtcbiAgICBwcm90ZWN0ZWQgYmxlZWRTdGF0OiBTcHJpdGU7XG5cbiAgICAvL3NlZWQgVUlcbiAgICBwcm90ZWN0ZWQgc2VlZExhYmVsOiBMYWJlbDsgICBcblxuICAgIC8vIEEgbGlzdCBvZiBpdGVtcyBpbiB0aGUgc2NlbmVcbiAgICBwcm90ZWN0ZWQgaXRlbXM6IEFycmF5PEl0ZW0+O1xuXG4gICAgIC8vIEEgbGlzdCBvZiBlbmVtaWVzXG4gICAgcHJvdGVjdGVkIGVuZW1pZXM6IEFycmF5PEFuaW1hdGVkU3ByaXRlPjtcblxuICAgIHByb3RlY3RlZCBnYW1lU3RhdGVTdGFjazogU3RhY2s8R2FtZVN0YXRlPjtcblxuICAgIC8vIFN0b3J5XG4gICAgcHJvdGVjdGVkIHN0b3J5dGV4dExhYmVsOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgc3RvcnlMYXllcjogTGF5ZXI7XG4gICAgcHJvdGVjdGVkIHN0b3J5OiBTdG9yeTtcbiAgICBwcm90ZWN0ZWQgc3RvcnlQcm9ncmVzczogbnVtYmVyO1xuICAgIHByb3RlY3RlZCBzdG9yeVNwcml0ZXM6IEFycmF5PFNwcml0ZT47XG4gICAgcHJvdGVjdGVkIHN0b3J5QkdNczogQXJyYXk8c3RyaW5nPjtcbiAgICBwcm90ZWN0ZWQgY3VycmVudFNwZWFrZXI6IHN0cmluZztcbiAgICBwcm90ZWN0ZWQgY3VycmVudENvbnRlbnQ6IHN0cmluZztcblxuICAgIC8vYnVmZnMgbGF5ZXJcbiAgICBwcm90ZWN0ZWQgYnVmZkxheWVyOiBMYXllcjtcbiAgICBwcm90ZWN0ZWQgYnVmZkJ1dHRvbjEgOiBCdXR0b247XG4gICAgcHJvdGVjdGVkIGJ1ZmZMYWJlbDEgOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgYnVmZkJ1dHRvbjIgOiBCdXR0b247XG4gICAgcHJvdGVjdGVkIGJ1ZmZMYWJlbDIgOiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgYnVmZkJ1dHRvbjMgOiBCdXR0b247XG4gICAgcHJvdGVjdGVkIGJ1ZmZMYWJlbDM6IExhYmVsO1xuICAgIHByb3RlY3RlZCBidWZmczogQXJyYXk8QnVmZj47XG5cbiAgICAvL3BhdXNlIGxheWVyXG4gICAgcHJvdGVjdGVkIHBhdXNlTGF5ZXI6IExheWVyO1xuICAgIHByb3RlY3RlZCBwYXVzZVRleHQ6IExhYmVsO1xuICAgIHByb3RlY3RlZCBwYXVzZUlucHV0OiBUZXh0SW5wdXQ7XG4gICAgcHJvdGVjdGVkIHBhdXNlU3VibWl0OiBMYWJlbDtcbiAgICBwcm90ZWN0ZWQgcGF1c2VDaGVhdFRleHQ6IExhYmVsO1xuICAgIHByb3RlY3RlZCBtYWluTWVudUJ1dHRvbjogQnV0dG9uO1xuXG4gICAgcHJvdGVjdGVkIHJtZzogUmFuZG9tTWFwR2VuZXJhdG9yO1xuICAgIHByb3RlY3RlZCBtYXA6IFRpbGVkVGlsZW1hcERhdGE7XG5cbiAgICBwcm90ZWN0ZWQgc3RhcnRDaGVja1BvaW50OiBSZWN0O1xuICAgIHByb3RlY3RlZCBlbmRDaGVja1BvaW50OiBSZWN0O1xuICAgIHByb3RlY3RlZCB0b3VjaGVkU3RhcnRDaGVja1BvaW50OiBib29sZWFuID0gZmFsc2U7XG4gICAgcHJvdGVjdGVkIHRvdWNoZWRFbmRDaGVja1BvaW50OiBib29sZWFuID0gZmFsc2U7XG4gICAgc3RhdGljIGdhbWVUaW1lcjogbnVtYmVyID0gMDtcbiAgICBwcm90ZWN0ZWQgZ2FtZVN0YXJ0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgdGltZXJMYWJsZTogTGFiZWw7XG4gICAgcHJvdGVjdGVkIGxldmVsRW5kZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHN0YXJ0cG9zOiBWZWMyOyBcbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIC8vY2FuIGxvYWQgcGxheWVyIHNwcml0ZSBoZXJlXG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcInBsYXllclwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL0hpcm8uanNvblwiKVxuICAgICAgICAvLyBUT0RPIC0gY2hhbmdlIHdoZW4gZG9uZSB0ZXN0aW5nXG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcInNsaWNlXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvc2xpY2UuanNvblwiKTtcblxuICAgICAgICAvLyBMb2FkIHRoZSBzY2VuZSBpbmZvXG4gICAgICAgIHRoaXMubG9hZC5vYmplY3QoXCJ3ZWFwb25EYXRhXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9kYXRhL3dlYXBvbkRhdGEuanNvblwiKTtcblxuICAgICAgICAvLyBMb2FkIGluIHRoZSBlbmVteSBpbmZvXG4gICAgICAgIC8vdGhpcy5sb2FkLm9iamVjdChcImVuZW15RGF0YVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvZGF0YS9lbmVteS5qc29uXCIpO1xuXG4gICAgICAgIC8vIExvYWQgaW4gaXRlbSBpbmZvXG4gICAgICAgIC8vdGhpcy5sb2FkLm9iamVjdChcIml0ZW1EYXRhXCIsIFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9kYXRhL2l0ZW1zLmpzb25cIik7XG5cbiAgICAgICAgdGhpcy5sb2FkLmF1ZGlvKFwianVtcFwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL2p1bXAyLndhdlwiKTtcbiAgICAgICAgdGhpcy5sb2FkLmF1ZGlvKFwiaHVydFwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL2h1cnQud2F2XCIpO1xuICAgICAgICB0aGlzLmxvYWQuYXVkaW8oXCJkaWVcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3NvdW5kcy9kaWUud2F2XCIpO1xuICAgICAgICB0aGlzLmxvYWQuYXVkaW8oXCJsZXZlbF91cFwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zb3VuZHMvbGV2ZWxfdXAud2F2XCIpO1xuICAgICAgICAvL+elnuekvu+8iOOBmOOCk+OBmOOCg++8ieelre+8iOOBvuOBpOOCiu+8ieOAgGJ5IFNlY29uZCBEaW1lbnNpb24gSW1hZ2luYXRpb24gR3JvdXBcbiAgICAgICAgdGhpcy5sb2FkLmF1ZGlvKFwibGV2ZWxfbXVzaWNcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc291bmRzL2JnbTEubXAzXCIpXG5cblxuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJrbmlmZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlcy9rbmlmZS5wbmdcIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImludmVudG9yeVNsb3RcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXMvaW52ZW50b3J5LnBuZ1wiKTtcbiAgICAgICAgdGhpcy5sb2FkLmltYWdlKFwiYmxhY2tcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2ltYWdlcy9ibGFjay5wbmdcIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcInBvaXNvbmluZ1wiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvaW1hZ2VzL3BvaXNvbmluZy5wbmdcIik7XG4gICAgICAgIHRoaXMubG9hZC5pbWFnZShcImJ1cm5pbmdcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2ltYWdlcy9idXJuaW5nLnBuZ1wiKTtcbiAgICAgICAgdGhpcy5sb2FkLmltYWdlKFwiYmxlZWRpbmdcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2ltYWdlcy9ibGVlZGluZy5wbmdcIik7XG5cbiAgICAgICAgLy9UT0RPIC0gY2hvb3NlIHNwcml0ZXNoZWV0IGZvciBzbGljZSAtIG1vZGlmeSB0aGUgc2xpY2UuanNvblxuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJzbGljZVwiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3NsaWNlLmpzb25cIik7XG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcInRlc3RfZHVtbXlcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3Rlc3RfZHVtbXkuanNvblwiKVxuICAgICAgICB0aGlzLmVuZW1pZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyID0gbmV3IEJhdHRsZU1hbmFnZXIoKTtcbiAgICB9XG5cbiAgICB1bmxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlNUT1BfU09VTkQsIHtrZXk6IFwibGV2ZWxfbXVzaWNcIn0pO1xuICAgICB9XG5cbiAgICBzdGFydFNjZW5lKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmFkZC50aWxlbWFwKFwibWFwXCIsIG5ldyBWZWMyKDIsIDIpKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJ3aWR0aCxoZWlnaHQ6XCIgKyB0aGlzLm1hcC53aWR0aCwgdGhpcy5tYXAuaGVpZ2h0KTtcbiAgICAgICAgdGhpcy52aWV3cG9ydC5zZXRCb3VuZHMoMCwgMCwgdGhpcy5tYXAud2lkdGggKiAzMiwgdGhpcy5tYXAuaGVpZ2h0ICogMzIpO1xuICAgICAgICB0aGlzLnZpZXdwb3J0LmZvbGxvdyh0aGlzLnBsYXllcik7XG5cbiAgICAgICAgdGhpcy5wbGF5ZXJTcGF3biA9IHRoaXMucm1nLmdldFBsYXllcigpLnNjYWxlKDMyKTtcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5wbGF5ZXJTcGF3bilcblxuICAgICAgICB0aGlzLnN0YXJ0cG9zID0gdGhpcy5ybWcuZ2V0UGxheWVyKCkuc2NhbGUoMzIpO1xuXG5cbiAgICAgICAgXG4gICAgICAgIC8vIERvIHRoZSBnYW1lIGxldmVsIHN0YW5kYXJkIGluaXRpYWxpemF0aW9uc1xuICAgICAgICB0aGlzLmluaXRWaWV3cG9ydCgpO1xuICAgICAgICB0aGlzLmluaXRMYXllcnMoKTtcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBiYXR0bGUgbWFuYWdlclxuXG4gICAgICAgIC8vIFRPRE9cbiAgICAgICAgdGhpcy5pbml0aWFsaXplV2VhcG9ucygpO1xuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBpdGVtcyBhcnJheSAtIHRoaXMgcmVwcmVzZW50cyBpdGVtcyB0aGF0IGFyZSBpbiB0aGUgZ2FtZSB3b3JsZFxuICAgICAgICB0aGlzLml0ZW1zID0gbmV3IEFycmF5KCk7XG5cbiAgICAgICAgdGhpcy5pbml0UGxheWVyKCk7XG4gICAgICAgIC8vc3Vic2NyaWJlIHRvIHJlbGV2YW50IGV2ZW50c1xuICAgICAgICB0aGlzLnN1YnNjcmliZVRvRXZlbnRzKCk7XG4gICAgICAgIHRoaXMuYWRkVUkoKTtcblxuICAgICAgICBsZXQgc3RhcnRDaGVja1BvaW50ID0gdGhpcy5ybWcuZ2V0U3RhcnRDaGVja1BvaW50KCk7XG4gICAgICAgIHRoaXMuc3RhcnRDaGVja1BvaW50ID0gdGhpcy5hZGRDaGVja1BvaW50KG5ldyBWZWMyKHN0YXJ0Q2hlY2tQb2ludFswXSwgc3RhcnRDaGVja1BvaW50WzFdKSwgbmV3IFZlYzIoc3RhcnRDaGVja1BvaW50WzJdLCBzdGFydENoZWNrUG9pbnRbM10pLCBcInN0YXJ0U3RvcnlcIiwgXCJzdGFydFRpbWVyXCIpO1xuICAgICAgICBsZXQgZW5kQ2hlY2tQb2ludCA9IHRoaXMucm1nLmdldEVuZENoZWNrUG9pbnQoKTtcbiAgICAgICAgdGhpcy5lbmRDaGVja1BvaW50ID0gdGhpcy5hZGRDaGVja1BvaW50KG5ldyBWZWMyKGVuZENoZWNrUG9pbnRbMF0sIGVuZENoZWNrUG9pbnRbMV0pLCBuZXcgVmVjMihlbmRDaGVja1BvaW50WzJdLCBlbmRDaGVja1BvaW50WzNdKSwgXCJlbmRTdG9yeVwiLCBcIm5leHRMZXZlbFwiKTtcbiAgICAgICAgXG4gICAgICAgIC8vIENyZWF0ZSBhbiBlbmVtaWVzIGFycmF5XG4gICAgICAgIC8vIFNlbmQgdGhlIHBsYXllciBhbmQgZW5lbWllcyB0byB0aGUgYmF0dGxlIG1hbmFnZXJcbiAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLnNldFBsYXllcnMoWzxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haV0pO1xuICAgICAgICAvLyBJbml0aWFsaXplIGFsbCBlbmVtaWVzXG4gICAgICAgIC8vdGhpcy5pbml0aWFsaXplRW5lbWllcygpO1xuICAgICAgICB0aGlzLmJhdHRsZU1hbmFnZXIuc2V0RW5lbWllcyh0aGlzLmVuZW1pZXMubWFwKGVuZW15ID0+IDxCYXR0bGVyQUk+ZW5lbXkuX2FpKSk7XG5cblxuICAgICAgICBsZXQgZW5lbWllcyA9IHRoaXMucm1nLmdldEVuZW1pZXMoKTtcbiAgICAgICAgLy9tYXkgaGF2ZSB0byBtb3ZlIHRoaXMgdG8gc3RhcnQgc2NlbmUgaW4gZ2FtZUxldmVsXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZUVuZW1pZXMoZW5lbWllcyk7XG5cblxuICAgICAgICB0aGlzLmdhbWVTdGF0ZVN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKEdhbWVTdGF0ZS5HQU1JTkcpO1xuICAgICAgICBJbnB1dFdyYXBwZXIuZW5hYmxlSW5wdXQoKTtcblxuICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJsZXZlbF9tdXNpY1wiLCBsb29wOiB0cnVlLCBob2xkUmVmZXJlbmNlOiB0cnVlfSk7XG4gICAgfVxuXG5cbiAgICB1cGRhdGVTY2VuZShkZWx0YVQ6IG51bWJlcil7XG5cbiAgICAgICAgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5nYW1lU3RhcnRlZCkge1xuICAgICAgICAgICAgICAgIEdhbWVMZXZlbC5nYW1lVGltZXIgKz0gZGVsdGFUO1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJMYWJsZS50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJMYWJsZS50ZXh0Q29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgbWludXRlcyA9IE1hdGguZmxvb3IoR2FtZUxldmVsLmdhbWVUaW1lciAvIDYwKTtcbiAgICAgICAgICAgIGlmIChtaW51dGVzID49IDEwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lckxhYmxlLnRleHQgPSBtaW51dGVzLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVyTGFibGUudGV4dCA9IFwiMFwiICsgbWludXRlcy50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IHNlY29uZHMgPSBNYXRoLmZsb29yKEdhbWVMZXZlbC5nYW1lVGltZXIgJSA2MCk7XG4gICAgICAgICAgICBpZiAoc2Vjb25kcyA+PSAxMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGltZXJMYWJsZS50ZXh0ICs9IFwiOlwiICsgc2Vjb25kcy50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lckxhYmxlLnRleHQgKz0gXCI6MFwiICsgc2Vjb25kcy50b1N0cmluZygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgXG4gICAgICAgIC8vIEhhbmRsZSBldmVudHMgYW5kIHVwZGF0ZSB0aGUgVUkgaWYgbmVlZGVkXG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoKGV2ZW50LnR5cGUpe1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFBsYXllcl9FdmVudHMuUExBWUVSX0NPTExJREU6XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbiA9IHRoaXMuc2NlbmVHcmFwaC5nZXROb2RlKGV2ZW50LmRhdGEuZ2V0KFwibm9kZVwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3RoZXIgPSB0aGlzLnNjZW5lR3JhcGguZ2V0Tm9kZShldmVudC5kYXRhLmdldChcIm90aGVyXCIpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYobiA9PT0gdGhpcy5wbGF5ZXIpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vZGUgaXMgcGxheWVyLCBvdGhlciBpcyBlbmVteVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlUGxheWVyRW5lbXlDb2xsaXNpb24oPEFuaW1hdGVkU3ByaXRlPm4sIDxBbmltYXRlZFNwcml0ZT5vdGhlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyIGlzIHBsYXllciwgbm9kZSBpcyBiYWxsb29uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVQbGF5ZXJFbmVteUNvbGxpc2lvbig8QW5pbWF0ZWRTcHJpdGU+b3RoZXIsPEFuaW1hdGVkU3ByaXRlPm4pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBQbGF5ZXJfRXZlbnRzLkVORU1ZX0tJTExFRDpcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG5vZGUgPSB0aGlzLnNjZW5lR3JhcGguZ2V0Tm9kZShldmVudC5kYXRhLmdldChcIm93bmVyXCIpKTsvL2dldCBlbmVteSBpZCBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vcmVtb3ZlIGVuZW15IGZyb20gZW5lbWllc1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmVtaWVzID0gdGhpcy5lbmVtaWVzLmZpbHRlcihpdGVtID0+IGl0ZW0gIT09IGV2ZW50LmRhdGEuZ2V0KFwiYWlcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iYXR0bGVNYW5hZ2VyLnJlbW92ZUVuZW15KGV2ZW50LmRhdGEuZ2V0KFwiYWlcIikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy9naXZlIHRoZSBwbGF5ZXIgdGhlIGV4cCB2YWx1ZSBvZiB0aGUgZW5lbXkga2lsbGVkXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihldmVudC5kYXRhLmdldChcImFpXCIpLmV4cF92YWwgIT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuZ2l2ZUV4cChldmVudC5kYXRhLmdldChcImFpXCIpLmV4cF92YWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5kZXN0cm95KCk7IC8vZGVzdHJveSBlbmVteSBub2RlXG4gICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5lbmVtaWVzS2lsbGVkKysgO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSBQbGF5ZXJfRXZlbnRzLkdJVkVfUkVHVUxBUl9CVUZGOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmcyA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmdlbmVyYXRlUmVndWxhckJ1ZmZzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmJ1ZmZzWzBdLnN0cmluZyA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDEudGV4dCA9IFwiXFxuXFxuSW5jcmVhc2UgXCIrdGhpcy5idWZmc1swXS50eXBlICsgXCJcXG4gYnkgXCIrdGhpcy5idWZmc1swXS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwxLnRleHQgPSB0aGlzLmJ1ZmZzWzBdLnN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5idWZmc1sxXS5zdHJpbmcgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwyLnRleHQgPSBcIlxcblxcbkluY3JlYXNlIFwiK3RoaXMuYnVmZnNbMV0udHlwZSArIFwiXFxuIGJ5IFwiK3RoaXMuYnVmZnNbMV0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMi50ZXh0ID0gdGhpcy5idWZmc1sxXS5zdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRoaXMuYnVmZnNbMl0uc3RyaW5nID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMy50ZXh0ID0gXCJcXG5cXG5JbmNyZWFzZSBcIit0aGlzLmJ1ZmZzWzJdLnR5cGUgKyBcIlxcbiBieSBcIit0aGlzLmJ1ZmZzWzJdLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDMudGV4dCA9IHRoaXMuYnVmZnNbMl0uc3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICAvL3BhdXNlIGdhbWUgaGVyZSBcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKEdhbWVTdGF0ZS5CVUZGKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxheWVyLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgUGxheWVyX0V2ZW50cy5HSVZFX1NQRUNJQUxfQlVGRjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZnMgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5nZW5lcmF0ZVNwZWNpYWxCdWZmcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5idWZmc1swXS5zdHJpbmcgPT09IHVuZGVmaW5lZCl7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwxLnRleHQgPSBcIlxcblxcbkluY3JlYXNlIFwiK3RoaXMuYnVmZnNbMF0udHlwZSArIFwiXFxuIGJ5IFwiK3RoaXMuYnVmZnNbMF0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMS50ZXh0ID0gdGhpcy5idWZmc1swXS5zdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRoaXMuYnVmZnNbMV0uc3RyaW5nID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxhYmVsMi50ZXh0ID0gXCJcXG5cXG5JbmNyZWFzZSBcIit0aGlzLmJ1ZmZzWzFdLnR5cGUgKyBcIlxcbiBieSBcIit0aGlzLmJ1ZmZzWzFdLnZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDIudGV4dCA9IHRoaXMuYnVmZnNbMV0uc3RyaW5nO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmJ1ZmZzWzJdLnN0cmluZyA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYWJlbDMudGV4dCA9IFwiXFxuXFxuSW5jcmVhc2UgXCIrdGhpcy5idWZmc1syXS50eXBlICsgXCJcXG4gYnkgXCIrdGhpcy5idWZmc1syXS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGFiZWwzLnRleHQgPSB0aGlzLmJ1ZmZzWzJdLnN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9wYXVzZSBnYW1lIGhlcmUgXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZShHYW1lU3RhdGUuQlVGRik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYXllci5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vcmVzcGF3biBwbGF5ZXIgaWYgaGUgaGFzIGxpdmVzLCBvdGhlcndpc2UgZW5kIGdhbWVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwicGxheWVyIERpZWRcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICAoPEFuaW1hdGVkU3ByaXRlPnRoaXMucGxheWVyKS5hbmltYXRpb24ucGxheShcIkRFQURcIiwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgSW5wdXRXcmFwcGVyLmRpc2FibGVJbnB1dCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkubGl2ZXMgPjApe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzcGF3blBsYXllcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXsgLy9ubyBtb3JlIGxpdmVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3cG9ydC5zZXRab29tTGV2ZWwoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShHYW1lT3Zlciwge30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIElucHV0V3JhcHBlci5lbmFibGVJbnB1dCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzdGFydFN0b3J5XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsYXlTdGFydFN0b3J5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImVuZFN0b3J5XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsYXlFbmRTdG9yeSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzdGFydFRpbWVyXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VGltZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwibmV4dExldmVsXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdvVG9OZXh0TGV2ZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09IEdhbWVTdGF0ZS5CVUZGKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoKGV2ZW50LnR5cGUpe1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiYnVmZjFcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmFkZEJ1ZmYodGhpcy5idWZmc1swXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZMYXllci5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubGV2ZWxFbmRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ29Ub05leHRMZXZlbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJidWZmMlwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuYWRkQnVmZih0aGlzLmJ1ZmZzWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZkxheWVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sZXZlbEVuZGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nb1RvTmV4dExldmVsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImJ1ZmYzXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5hZGRCdWZmKHRoaXMuYnVmZnNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmTGF5ZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHYW1lU3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmxldmVsRW5kZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdvVG9OZXh0TGV2ZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChldmVudC50eXBlID09PSBcImNoZWF0XCIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUNoZWF0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcIk1haW5NZW51XCIpe1xuICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnQuc2V0Wm9vbUxldmVsKDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoTWFpbk1lbnUsIHt9KTtcbiAgICAgICAgICAgICAgICBJbnB1dFdyYXBwZXIuZW5hYmxlSW5wdXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09IEdhbWVTdGF0ZS5TVE9SWSkge1xuICAgICAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc05leHRKdXN0UHJlc3NlZCgpICYmIHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuU1RPUlkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0b3J5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc1BhdXNlSnVzdFByZXNzZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5wYXVzZVRleHQudGV4dCA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09IEdhbWVTdGF0ZS5HQU1JTkcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZShHYW1lU3RhdGUuUEFVU0UpO1xuICAgICAgICAgICAgICAgIHRoaXMucGF1c2VMYXllci5lbmFibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMuZ2FtZVN0YXRlU3RhY2sucGVlaygpID09PSBHYW1lU3RhdGUuUEFVU0UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZSgpOyAgICBcbiAgICAgICAgICAgICAgICB0aGlzLnBhdXNlTGF5ZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc0J1ZmYxSnVzdFByZXNlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFwiYnVmZjFcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc0J1ZmYySnVzdFByZXNlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFwiYnVmZjJcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc0J1ZmYzSnVzdFByZXNlZCgpKSB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFwiYnVmZjNcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvL3VwZGF0ZSBoZWFsdGggVUkgXG4gICAgICAgIGxldCBwbGF5ZXJBSSA9ICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5haSk7XG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwudGV4dCA9IFwiSGVhbHRoOiBcIisgTWF0aC5yb3VuZChwbGF5ZXJBSS5DVVJSRU5UX0hQKSArJy8nICsgTWF0aC5yb3VuZChwbGF5ZXJBSS5NQVhfSFAgKTtcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIuc2l6ZS5zZXQocGxheWVyQUkuTUFYX0hQKjEuNSwgMTApO1xuICAgICAgICB0aGlzLmhlYWx0aEJhci5wb3NpdGlvbi5zZXQocGxheWVyQUkuTUFYX0hQKjAuNzUrMjAsIDIwKTtcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIuZmlsbFdpZHRoID0gcGxheWVyQUkuQ1VSUkVOVF9IUCoxLjU7XG4gICAgICAgIGlmIChwbGF5ZXJBSS5DVVJSRU5UX0hQL3BsYXllckFJLk1BWF9IUCA+PSAyLzMpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmNvbG9yID0gQ29sb3IuR1JFRU47XG4gICAgICAgICAgICB0aGlzLmhlYWx0aExhYmVsLnRleHRDb2xvciA9IENvbG9yLkdSRUVOO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBsYXllckFJLkNVUlJFTlRfSFAvcGxheWVyQUkuTUFYX0hQID49IDEvMykge1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5ZRUxMT1c7XG4gICAgICAgICAgICB0aGlzLmhlYWx0aExhYmVsLnRleHRDb2xvciA9IENvbG9yLllFTExPVztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuaGVhbHRoQmFyLmNvbG9yID0gQ29sb3IuUkVEO1xuICAgICAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5SRUQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhpcy5oZWFsdGhMYWJlbC5zaXplVG9UZXh0KCk7XG5cbiAgICAgICAgLy91cGRhdGUgc2hpZWxkIHVpXG4gICAgICAgIHRoaXMuc2hpZWxkTGFiZWwudGV4dCA9IFwiU2hpZWxkOiBcIisgTWF0aC5yb3VuZChwbGF5ZXJBSS5DVVJSRU5UX1NISUVMRCkgKycvJyArIE1hdGgucm91bmQocGxheWVyQUkuTUFYX1NISUVMRCk7XG4gICAgICAgIHRoaXMuc2hpZWxkQmFyLnNpemUuc2V0KHBsYXllckFJLkNVUlJFTlRfU0hJRUxEKjEuNSwgMTApO1xuICAgICAgICB0aGlzLnNoaWVsZEJhci5wb3NpdGlvbi5zZXQocGxheWVyQUkuQ1VSUkVOVF9TSElFTEQqMC43NSsyMCwgNTApO1xuICAgICAgICAvLyB0aGlzLnNoaWVsZExhYmVsLnNpemVUb1RleHQoKTtcblxuICAgICAgICAvL3VwZGF0ZSBleHAgdWlcbiAgICAgICAgdGhpcy5leHBMYWJlbC50ZXh0ID0gXCJFWFA6IFwiKyBNYXRoLnJvdW5kKHBsYXllckFJLkNVUlJFTlRfRVhQKSArJy8nICsgTWF0aC5yb3VuZChwbGF5ZXJBSS5NQVhfRVhQKTtcbiAgICAgICAgdGhpcy5leHBCYXIuZmlsbFdpZHRoID0gKHBsYXllckFJLkNVUlJFTlRfRVhQL3BsYXllckFJLk1BWF9FWFApKjE1MDtcbiAgICAgICAgLy8gdGhpcy5leHBMYWJlbC5zaXplVG9UZXh0KCk7XG5cbiAgICAgICAgLy91cGRhdGUgbGV2ZWwgdWlcbiAgICAgICAgdGhpcy5wbGF5ZXJMZXZlbExhYmVsLnRleHQgPSBcIkx2LlwiICsgcGxheWVyQUkubGV2ZWw7XG4gICAgICAgIC8vdXBkYXRlIGxpdmVzIHVpXG4gICAgICAgIHRoaXMubGl2ZXNDb3VudExhYmVsLnRleHQgPSBcIkxpdmVzOiBcIiArIHBsYXllckFJLmxpdmVzO1xuXG5cbiAgICAgICAgLy9tb3ZlIGJhY2tncm91bmRcblxuICAgICAgICAvLyBHZXQgdGhlIHZpZXdwb3J0IGNlbnRlciBhbmQgcGFkZGVkIHNpemVcblx0XHRjb25zdCB2aWV3cG9ydENlbnRlciA9IHRoaXMudmlld3BvcnQuZ2V0Q2VudGVyKCkuY2xvbmUoKTtcblx0XHRjb25zdCBiYXNlVmlld3BvcnRTaXplID0gdGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnNjYWxlZCgyKTtcbiAgICAgICAgLy9jaGVjayBwb3NpdGlvbiBvZiBwbGF5ZXJcbiAgICAgICAgdGhpcy5wbGF5ZXJGYWxsb2ZmKHZpZXdwb3J0Q2VudGVyLCBiYXNlVmlld3BvcnRTaXplKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPIHB1dCBVSSBjaGFuZ2VzIGluIGhlcmVcbiAgICBwcm90ZWN0ZWQgc2V0R2FtZVN0YXRlKGdhbWVTdGF0ZT86IEdhbWVTdGF0ZSkge1xuICAgICAgICBpZiAoZ2FtZVN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLmdhbWVTdGF0ZVN0YWNrLnB1c2goZ2FtZVN0YXRlKTtcbiAgICAgICAgICAgIElucHV0V3JhcHBlci5zZXRTdGF0ZShnYW1lU3RhdGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5nYW1lU3RhdGVTdGFjay5wb3AoKTtcbiAgICAgICAgICAgIElucHV0V3JhcHBlci5zZXRTdGF0ZSh0aGlzLmdhbWVTdGF0ZVN0YWNrLnBlZWsoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsemVzIHRoZSBsYXllcnNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdExheWVycygpOiB2b2lkIHtcbiAgICAgICAgLy8gQWRkIGEgbGF5ZXIgZm9yIFVJXG4gICAgICAgIHRoaXMuYWRkVUlMYXllcihcIlVJXCIpO1xuXG4gICAgICAgIC8vIEFkZCBhIGxheWVyIGZvciBwbGF5ZXJzIGFuZCBlbmVtaWVzXG4gICAgICAgIHRoaXMuYWRkTGF5ZXIoXCJwcmltYXJ5XCIsIDEpO1xuXG4gICAgICAgIHRoaXMuYnVmZkxheWVyID0gdGhpcy5hZGRVSUxheWVyKFwiYnVmZkxheWVyXCIpOyAgXG4gICAgXG5cbiAgICAgICAgdGhpcy5zdG9yeUxheWVyID0gdGhpcy5hZGRVSUxheWVyKFwic3RvcnlcIik7XG4gICAgICAgIHRoaXMuc3RvcnlMYXllci5kaXNhYmxlKCk7XG5cbiAgICAgICAgdGhpcy5wYXVzZUxheWVyID0gdGhpcy5hZGRVSUxheWVyKFwicGF1c2VcIik7XG4gICAgICAgIHRoaXMucGF1c2VMYXllci5kaXNhYmxlKCk7XG5cblxuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImxvYWRTdG9yeVwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgdmlld3BvcnRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdFZpZXdwb3J0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldFpvb21MZXZlbCgyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGFsbCBzdWJzY3JpcHRpb25zIHRvIGV2ZW50c1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBzdWJzY3JpYmVUb0V2ZW50cygpe1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShbXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLlBMQVlFUl9DT0xMSURFLFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5QTEFZRVJfSElUX0VORU1ZLFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5FTkVNWV9LSUxMRUQsXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLkxFVkVMX1NUQVJULFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5MRVZFTF9FTkQsXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLlBMQVlFUl9LSUxMRUQsXG4gICAgICAgICAgICBQbGF5ZXJfRXZlbnRzLkdJVkVfUkVHVUxBUl9CVUZGLFxuICAgICAgICAgICAgUGxheWVyX0V2ZW50cy5HSVZFX1NQRUNJQUxfQlVGRlxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJidWZmMVwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJidWZmMlwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJidWZmM1wiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJjaGVhdFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJzdGFydFN0b3J5XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcInN0YXJ0VGltZXJcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwiZW5kU3RvcnlcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwibmV4dExldmVsXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcIk1haW5NZW51XCIpO1xuICAgIH1cblxuICAgIC8vIFRPRE8gLSBcbiAgICAvKipcbiAgICAgKiBBZGRzIGluIGFueSBuZWNlc3NhcnkgVUkgdG8gdGhlIGdhbWVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWRkVUkoKXtcbiAgICAgICAgLy8gSW4tZ2FtZSBsYWJlbHNcbiAgICAgICAgdGhpcy5oZWFsdGhMYWJlbCA9IDxMYWJlbD4gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIix7cG9zaXRpb246IG5ldyBWZWMyKDcwLCAzNSksIHRleHQ6IFwiUGxheWVyIEhlYWx0aDogXCIrICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5haSkuQ1VSUkVOVF9IUCB9KTtcbiAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgdGhpcy5oZWFsdGhMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLnRleHRDb2xvciA9IENvbG9yLkdSRUVOO1xuICAgICAgICB0aGlzLmhlYWx0aExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICAgIHRoaXMuaGVhbHRoTGFiZWwuZm9udFNpemUgPSAyNTtcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIgPSA8UmVjdD50aGlzLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIFwiVUlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMigwLCAwKSwgc2l6ZTogbmV3IFZlYzIoMCwgMCl9KTtcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIuYm9yZGVyQ29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5oZWFsdGhCYXIuYm9yZGVyV2lkdGggPSAzO1xuICAgICAgICB0aGlzLmhlYWx0aEJhci5jb2xvciA9IENvbG9yLkdSRUVOO1xuXG4gICAgICAgIC8vIHRoaXMucG9pc29uU3RhdCA9IHRoaXMuYWRkLnNwcml0ZShcInBvaXNvbmluZ1wiLCBcIlVJXCIpO1xuICAgICAgICAvLyB0aGlzLnBvaXNvblN0YXQucG9zaXRpb24uc2V0KDU1LCAyNSk7XG4gICAgICAgIC8vIHRoaXMucG9pc29uU3RhdC5zY2FsZS5zZXQoMC4zLCAwLjMpO1xuICAgICAgICAvLyB0aGlzLmJ1cm5TdGF0ID0gdGhpcy5hZGQuc3ByaXRlKFwiYnVybmluZ1wiLCBcIlVJXCIpO1xuICAgICAgICAvLyB0aGlzLmJ1cm5TdGF0LnBvc2l0aW9uLnNldCg3MCwgMjUpO1xuICAgICAgICAvLyB0aGlzLmJ1cm5TdGF0LnNjYWxlLnNldCgwLjMsIDAuMyk7XG4gICAgICAgIC8vIHRoaXMuYmxlZWRTdGF0ID0gdGhpcy5hZGQuc3ByaXRlKFwiYmxlZWRpbmdcIiwgXCJVSVwiKTtcbiAgICAgICAgLy8gdGhpcy5ibGVlZFN0YXQucG9zaXRpb24uc2V0KDg1LCAyNSk7XG4gICAgICAgIC8vIHRoaXMuYmxlZWRTdGF0LnNjYWxlLnNldCgwLjMsIDAuMyk7XG5cbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbCA9IDxMYWJlbD4gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIix7cG9zaXRpb246IG5ldyBWZWMyKDcwLCA2NSksIHRleHQ6IFwic2hpZWxkOiBcIisgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLmFpKS5DVVJSRU5UX1NISUVMRCB9KTtcbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnNoaWVsZExhYmVsLnRleHRDb2xvciA9IENvbG9yLk9SQU5HRTtcbiAgICAgICAgdGhpcy5zaGllbGRMYWJlbC5mb250ID0gXCJQaXhlbFNpbXBsZVwiO1xuICAgICAgICB0aGlzLnNoaWVsZExhYmVsLmZvbnRTaXplID0gMjU7XG4gICAgICAgIHRoaXMuc2hpZWxkQmFyID0gPFJlY3Q+dGhpcy5hZGQuZ3JhcGhpYyhHcmFwaGljVHlwZS5SRUNULCBcIlVJXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoMCwgMCksIHNpemU6IG5ldyBWZWMyKDAsIDApfSk7XG4gICAgICAgIHRoaXMuc2hpZWxkQmFyLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuc2hpZWxkQmFyLmJvcmRlcldpZHRoID0gMztcbiAgICAgICAgdGhpcy5zaGllbGRCYXIuY29sb3IgPSBDb2xvci5PUkFOR0U7XG5cblxuXG4gICAgICAgIHRoaXMucGxheWVyTGV2ZWxMYWJlbCA9IDxMYWJlbD4gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIix7cG9zaXRpb246IG5ldyBWZWMyKDIwLCA5NSksIHRleHQ6IFwiTHYuIFwiKyAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuYWkpLmxldmVsIH0pO1xuICAgICAgICB0aGlzLnBsYXllckxldmVsTGFiZWwuc2l6ZS5zZXQoMCwgNTApO1xuICAgICAgICB0aGlzLnBsYXllckxldmVsTGFiZWwuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5wbGF5ZXJMZXZlbExhYmVsLnRleHRDb2xvciA9IENvbG9yLkJMVUU7XG4gICAgICAgIHRoaXMucGxheWVyTGV2ZWxMYWJlbC5mb250ID0gXCJQaXhlbFNpbXBsZVwiO1xuICAgICAgICB0aGlzLnBsYXllckxldmVsTGFiZWwuZm9udFNpemUgPSAyNTtcblxuICAgICAgICB0aGlzLmV4cExhYmVsID0gPExhYmVsPiB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJVSVwiLHtwb3NpdGlvbjogbmV3IFZlYzIoMTAwLCA5NSksIHRleHQ6IFwiRVhQOiBcIisgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLmFpKS5DVVJSRU5UX0VYUCB9KTtcbiAgICAgICAgdGhpcy5leHBMYWJlbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgdGhpcy5leHBMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLmV4cExhYmVsLnRleHRDb2xvciA9IENvbG9yLkJMVUU7XG4gICAgICAgIHRoaXMuZXhwTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcbiAgICAgICAgdGhpcy5leHBMYWJlbC5mb250U2l6ZSA9IDI1O1xuICAgICAgICB0aGlzLmV4cEJhciA9IDxSZWN0PnRoaXMuYWRkLmdyYXBoaWMoR3JhcGhpY1R5cGUuUkVDVCwgXCJVSVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKDk1LCA4MCksIHNpemU6IG5ldyBWZWMyKDE1MCwgMTApfSk7XG4gICAgICAgIHRoaXMuZXhwQmFyLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMuZXhwQmFyLmJvcmRlcldpZHRoID0gMztcbiAgICAgICAgdGhpcy5leHBCYXIuY29sb3IgPSBDb2xvci5CTFVFO1xuXG4gICAgICAgIC8vc2VlZCBsYWJlbFxuICAgICAgICAvL3dvcmxkc2l6ZS54IGRvZXNudCB3b3JrIGhvdyBpIHdhbnQgaXQgdG9cbiAgICAgICAgdGhpcy5zZWVkTGFiZWwgPSA8TGFiZWw+IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIse3Bvc2l0aW9uOiBuZXcgVmVjMig3MCwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSoyIC0gMzApKSwgdGV4dDogXCJTZWVkOiBcIisgSW5wdXRXcmFwcGVyLnJhbmRvbVNlZWQgfSk7XG4gICAgICAgIHRoaXMuc2VlZExhYmVsLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICB0aGlzLnNlZWRMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnNlZWRMYWJlbC50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5zZWVkTGFiZWwuZm9udCA9IFwiUGl4ZWxTaW1wbGVcIjtcbiAgICAgIFxuXG5cbiAgICAgICAgdGhpcy5hZGQuc3ByaXRlKFwiYmxhY2tcIiwgXCJwYXVzZVwiKTtcbiAgICAgICAgdGhpcy5hZGQuc3ByaXRlKFwiYmxhY2tcIiwgXCJzdG9yeVwiKTtcbiAgICAgICAgdGhpcy5hZGQuc3ByaXRlKFwiYmxhY2tcIiwgXCJidWZmTGF5ZXJcIik7XG5cbiAgICAgICAgLy9UT0RPIC0gXG4gICAgICAgIC8vZGV0ZXJtaW5lIGJ1dHRvbiBsb2NhdGlvbiBcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMSA9IDxCdXR0b24+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcImJ1ZmZMYXllclwiLCB7cG9zaXRpb246IG5ldyBWZWMyKE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLngqMi8zLTE4MC8yKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSkpLHRleHQ6XCJcIn0pO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24xLnNpemUuc2V0KDE4MCwyMDApO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24xLmJvcmRlcldpZHRoID0gNTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5ib3JkZXJDb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5vbkNsaWNrRXZlbnRJZCA9IFwiYnVmZjFcIjtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMS5mb250U2l6ZSA9IDIwO1xuICAgICAgICB0aGlzLmJ1ZmZMYWJlbDEgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYnVmZkxheWVyXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIodGhpcy5idWZmQnV0dG9uMS5wb3NpdGlvbi54LCB0aGlzLmJ1ZmZCdXR0b24xLnBvc2l0aW9uLnkgLSA0MCksdGV4dDpcImJ1ZmZMYWJlbDFcIn0pO1xuICAgICAgICB0aGlzLmJ1ZmZMYWJlbDEuZm9udFNpemUgPSAyMDtcblxuXG4gICAgICAgIHRoaXMuYnVmZkJ1dHRvbjIgPSA8QnV0dG9uPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJidWZmTGF5ZXJcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54KSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSkpLHRleHQ6XCJcIn0pO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24yLnNpemUuc2V0KDE4MCwyMDApO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24yLmJvcmRlcldpZHRoID0gNTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5ib3JkZXJDb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5vbkNsaWNrRXZlbnRJZCA9IFwiYnVmZjJcIjtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMi5mb250U2l6ZSA9IDIwO1xuICAgICAgICB0aGlzLmJ1ZmZMYWJlbDIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYnVmZkxheWVyXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIodGhpcy5idWZmQnV0dG9uMi5wb3NpdGlvbi54LCB0aGlzLmJ1ZmZCdXR0b24yLnBvc2l0aW9uLnkgLSA0MCksdGV4dDpcImJ1ZmZMYWJlbDJcIn0pO1xuICAgICAgICB0aGlzLmJ1ZmZMYWJlbDIuZm9udFNpemUgPSAyMDtcblxuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24zID0gPEJ1dHRvbj50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiYnVmZkxheWVyXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCo0LzMrMTgwLzIpLCBNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS55KSksIHRleHQ6XCJcIn0pO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24zLnNpemUuc2V0KDE4MCwyMDApO1xuICAgICAgICB0aGlzLmJ1ZmZCdXR0b24zLmJvcmRlcldpZHRoID0gNTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5ib3JkZXJDb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5vbkNsaWNrRXZlbnRJZCA9IFwiYnVmZjNcIjtcbiAgICAgICAgdGhpcy5idWZmQnV0dG9uMy5mb250U2l6ZSA9IDIwO1xuICAgICAgICB0aGlzLmJ1ZmZMYWJlbDMgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYnVmZkxheWVyXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIodGhpcy5idWZmQnV0dG9uMy5wb3NpdGlvbi54LCB0aGlzLmJ1ZmZCdXR0b24zLnBvc2l0aW9uLnkgLSA0MCksIHRleHQ6XCJidWZmTGFiZWwzXCJ9KTtcbiAgICAgICAgdGhpcy5idWZmTGFiZWwzLmZvbnRTaXplID0gMjA7XG5cbiAgICAgICAgdGhpcy5idWZmcyA9ICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5nZW5lcmF0ZVJlZ3VsYXJCdWZmcygpO1xuXG4gICAgICAgIHRoaXMuYnVmZkxheWVyLmRpc2FibGUoKTtcblxuICAgICAgICB0aGlzLnBhdXNlVGV4dCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJwYXVzZVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnggLSAxMjApLCBNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS55IC0gMTAwKSksIHRleHQ6IFwiXCJ9KTtcbiAgICAgICAgdGhpcy5wYXVzZUlucHV0ID0gPFRleHRJbnB1dD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5URVhUX0lOUFVULCBcInBhdXNlXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueCAtIDIwKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSArIDEwMCkpLCB0ZXh0OiBcIlwifSk7XG4gICAgICAgIHRoaXMucGF1c2VDaGVhdFRleHQgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicGF1c2VcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54IC0gMTIwKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSArIDgwKSksIHRleHQ6IFwi4qyH77iP4qyH77iP4qyH77iPQ2hlYXQgQ29kZeKsh++4j+Ksh++4j+Ksh++4j1wifSk7XG4gICAgICAgIHRoaXMucGF1c2VTdWJtaXQgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwicGF1c2VcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54ICsgMTIwKSwgTWF0aC5mbG9vcih0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSArIDEwMCkpLCB0ZXh0OiBcIlN1Ym1pdFwifSk7XG5cbiAgICAgICAgXG4gICAgICAgIHRoaXMucGF1c2VMYXllci5zZXRBbHBoYSgwLjUpO1xuICAgICAgICB0aGlzLnBhdXNlVGV4dC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5wYXVzZVRleHQuc2V0SEFsaWduKEhBbGlnbi5MRUZUKTtcbiAgICAgICAgdGhpcy5wYXVzZVRleHQuc2l6ZSA9IG5ldyBWZWMyKDAsIDQwKTtcbiAgICAgICAgdGhpcy5wYXVzZVRleHQudGV4dCA9IFwiSFA6XFxuQVRLOlxcbkRhbWFnZSBSYXRpbzpcXG5CdWZmMTpcXG5CdWZmMjpcXG5CdWZmMzpcXG5CdWZmNDpcXG5CdWZmNTpcXG5CdWZmNjpcXG5FbmVteSBLaWxsZWQ6XFxuXCJcbiAgICAgICAgdGhpcy5wYXVzZUNoZWF0VGV4dC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgdGhpcy5wYXVzZUNoZWF0VGV4dC5zaXplID0gbmV3IFZlYzIoMCwgNDApO1xuICAgICAgICB0aGlzLnBhdXNlQ2hlYXRUZXh0LnNldEhBbGlnbihIQWxpZ24uTEVGVCk7XG4gICAgICAgIHRoaXMucGF1c2VJbnB1dC5zaXplLnNldCg0MDAsIDMwKTtcbiAgICAgICAgdGhpcy5wYXVzZVN1Ym1pdC50ZXh0Q29sb3IgPSBDb2xvci5CTEFDSztcbiAgICAgICAgdGhpcy5wYXVzZVN1Ym1pdC5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICB0aGlzLnBhdXNlU3VibWl0LmJhY2tncm91bmRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLnBhdXNlU3VibWl0Lm9uQ2xpY2tFdmVudElkID0gXCJjaGVhdFwiO1xuICAgICAgICB0aGlzLnBhdXNlU3VibWl0LmJvcmRlcldpZHRoID0gMztcblxuICAgICAgICB0aGlzLm1haW5NZW51QnV0dG9uID0gPEJ1dHRvbj50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwicGF1c2VcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54ICksIE1hdGguZmxvb3IodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLnkgKyAxNDApKSwgdGV4dDpcIk1haW4gTWVudVwifSk7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uc2l6ZS5zZXQoMTgwLDEwMCk7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uYm9yZGVyV2lkdGggPSA1O1xuICAgICAgICB0aGlzLm1haW5NZW51QnV0dG9uLmJvcmRlckNvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uYmFja2dyb3VuZENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24udGV4dENvbG9yID0gQ29sb3IuQkxBQ0s7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24ub25DbGlja0V2ZW50SWQgPSBcIk1haW5NZW51XCI7XG4gICAgICAgIHRoaXMubWFpbk1lbnVCdXR0b24uZm9udFNpemUgPSAyMDtcbiAgICAgICAgXG5cbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwgPSAgPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcIlVJXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIodGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpLngqMiAtIDEwMCwgMzApLCB0ZXh0OlwiTGl2ZXM6IFwifSk7XG4gICAgICAgIHRoaXMubGl2ZXNDb3VudExhYmVsLnRleHRDb2xvciA9IENvbG9yLllFTExPVztcbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwuZm9udFNpemUgPSAyNTtcblxuICAgICAgICB0aGlzLnRpbWVyTGFibGUgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiVUlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihNYXRoLmZsb29yKHRoaXMudmlld3BvcnQuZ2V0SGFsZlNpemUoKS54KSwgMzApLCB0ZXh0OiBcIjAwOjAwXCJ9KTtcbiAgICAgICAgdGhpcy50aW1lckxhYmxlLmZvbnRTaXplID0gNjA7XG59XG5cbiAgICAvL1RPRE8gLSBkZXRlcm1pbmUgd2hldGhlciB3ZSB3aWxsIGhhdmUgd2VhcG9uIGRhdGF0eXBlXG4gICAgLyoqXG4gICAgICogXG4gICAgICogQ3JlYXRlcyBhbmQgcmV0dXJucyBhIG5ldyB3ZWFwb25cbiAgICAgKiBAcGFyYW0gdHlwZSBUaGUgd2VhcG9uVHlwZSBvZiB0aGUgd2VhcG9uLCBhcyBhIHN0cmluZ1xuICAgICAqL1xuICAgICBjcmVhdGVXZWFwb24odHlwZTogc3RyaW5nKTogV2VhcG9uIHtcbiAgICAgICAgbGV0IHdlYXBvblR5cGUgPSA8V2VhcG9uVHlwZT5SZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UeXBlc1wiKS5nZXQodHlwZSk7XG5cbiAgICAgICAgbGV0IHNwcml0ZSA9IHRoaXMuYWRkLnNwcml0ZSh3ZWFwb25UeXBlLnNwcml0ZUtleSwgXCJwcmltYXJ5XCIpO1xuXG4gICAgICAgIHJldHVybiBuZXcgV2VhcG9uKHNwcml0ZSwgd2VhcG9uVHlwZSwgdGhpcy5iYXR0bGVNYW5hZ2VyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0YWxpemVzIGFsbCB3ZWFwb24gdHlwZXMgYmFzZWQgb2YgZGF0YSBmcm9tIHdlYXBvbkRhdGEuanNvblxuICAgICAqL1xuICAgICBpbml0aWFsaXplV2VhcG9ucygpOiB2b2lke1xuICAgICAgICBsZXQgd2VhcG9uRGF0YSA9IHRoaXMubG9hZC5nZXRPYmplY3QoXCJ3ZWFwb25EYXRhXCIpO1xuXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB3ZWFwb25EYXRhLm51bVdlYXBvbnM7IGkrKyl7XG4gICAgICAgICAgICBsZXQgd2VhcG9uID0gd2VhcG9uRGF0YS53ZWFwb25zW2ldO1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBwcm90b3R5cGVcbiAgICAgICAgICAgIGxldCBjb25zdHIgPSBSZWdpc3RyeU1hbmFnZXIuZ2V0UmVnaXN0cnkoXCJ3ZWFwb25UZW1wbGF0ZXNcIikuZ2V0KHdlYXBvbi53ZWFwb25UeXBlKTtcblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgd2VhcG9uIHR5cGVcbiAgICAgICAgICAgIGxldCB3ZWFwb25UeXBlID0gbmV3IGNvbnN0cigpO1xuXG4gICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgd2VhcG9uVHlwZS5pbml0aWFsaXplKHdlYXBvbik7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIHRoZSB3ZWFwb24gdHlwZVxuICAgICAgICAgICAgUmVnaXN0cnlNYW5hZ2VyLmdldFJlZ2lzdHJ5KFwid2VhcG9uVHlwZXNcIikucmVnaXN0ZXJJdGVtKHdlYXBvbi5uYW1lLCB3ZWFwb25UeXBlKVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIHRoZSBwbGF5ZXJcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdFBsYXllcigpOiB2b2lkIHtcbiAgICAgICAgLy9jcmVhdGUgdGhlIGludmVudG9yeVxuICAgICAgICBsZXQgaW52ZW50b3J5ID0gbmV3IEludmVudG9yeU1hbmFnZXIodGhpcywgMSwgXCJpbnZlbnRvcnlTbG90XCIsIG5ldyBWZWMyKDE2LCAxNiksIDQsIFwic2xvdHMxXCIsIFwiaXRlbXMxXCIpO1xuICAgICAgICBcblxuICAgICAgICAvL2FkZCBzdGFydGluZyB3ZWFwb24gdG8gaW52ZW50b3J5XG4gICAgICAgIGxldCBzdGFydGluZ1dlYXBvbiA9IHRoaXMuY3JlYXRlV2VhcG9uKFwia25pZmVcIik7XG4gICAgICAgIGludmVudG9yeS5hZGRJdGVtKHN0YXJ0aW5nV2VhcG9uKTsgICAgICAgICAgICAgIC8vdXNpbmcgc2xpY2UgdG8gdGVzdCByaWdodCBub3dcblxuXG4gICAgICAgIC8vIEFkZCB0aGUgcGxheWVyXG4gICAgICAgIHRoaXMucGxheWVyID0gdGhpcy5hZGQuYW5pbWF0ZWRTcHJpdGUoXCJwbGF5ZXJcIiwgXCJwcmltYXJ5XCIpO1xuICAgICAgICB0aGlzLnBsYXllci5zY2FsZS5zZXQoMSwgMSk7XG4gICAgICAgIGlmKCF0aGlzLnBsYXllclNwYXduKXtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlBsYXllciBzcGF3biB3YXMgbmV2ZXIgc2V0IC0gc2V0dGluZyBzcGF3biB0byAoMCwgMClcIik7XG4gICAgICAgICAgICB0aGlzLnBsYXllclNwYXduID0gVmVjMi5aRVJPO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhcnRwb3MgPSB0aGlzLnBsYXllclNwYXduO1xuICAgICAgICB0aGlzLnBsYXllci5wb3NpdGlvbi5jb3B5KHRoaXMucGxheWVyU3Bhd24pO1xuICAgICAgICB0aGlzLnBsYXllci5hZGRQaHlzaWNzKG5ldyBBQUJCKFZlYzIuWkVSTywgbmV3IFZlYzIoMTQsIDE2KSkpOyAgLy9zZXRzIHRoZSBjb2xsaXNpb24gc2hhcGVcbiAgICAgICAgdGhpcy5wbGF5ZXIuY29sbGlkZXJPZmZzZXQuc2V0KDAsIDE2KTtcbiAgICAgICAgdGhpcy5wbGF5ZXIuYWRkQUkoUGxheWVyQ29udHJvbGxlciwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGxheWVyVHlwZTogXCJwbGF0Zm9ybWVyXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcDogXCJNYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGVlZDogMTAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoOiAxMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGludmVudG9yeTogaW52ZW50b3J5LFxuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXM6IHRoaXMuaXRlbXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dEVuYWJsZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IDEwMFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnBsYXllci5zZXRHcm91cChcInBsYXllclwiKTtcblxuICAgICAgICB0aGlzLnZpZXdwb3J0LmZvbGxvdyh0aGlzLnBsYXllcik7XG4gICAgfVxuXG4gICAgXG4gICAgLy9UT0RPIC0gXG4gICAgLyoqXG4gICAgICogQWRkcyBhbiBFbmVteSBpbnRvIHRoZSBnYW1lXG4gICAgICogQHBhcmFtIHNwcml0ZUtleSBUaGUga2V5IG9mIHRoZSBFbmVteSBzcHJpdGVcbiAgICAgKiBAcGFyYW0gdGlsZVBvcyBUaGUgdGlsZW1hcCBwb3NpdGlvbiB0byBhZGQgdGhlIEVuZW15IHRvXG4gICAgICogQHBhcmFtIGFpT3B0aW9ucyBUaGUgb3B0aW9ucyBmb3IgdGhlIEVuZW15IEFJXG4gICAgICovXG4gICAgXG4gICAgcHJvdGVjdGVkIGFkZEVuZW15PFQgZXh0ZW5kcyBFbmVteUFJPihzcHJpdGVLZXk6IHN0cmluZywgdGlsZVBvczogVmVjMiwgYWk6IG5ldygpID0+IFQsIGFpT3B0aW9uczogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgICAgICBsZXQgZW5lbXkgPSB0aGlzLmFkZC5hbmltYXRlZFNwcml0ZShzcHJpdGVLZXksIFwicHJpbWFyeVwiKTtcbiAgICAgICAgLy9lbmVteS5wb3NpdGlvbi5zZXQodGlsZVBvcy54KjMyLCB0aWxlUG9zLnkqMzIpO1xuICAgICAgICBlbmVteS5wb3NpdGlvbi5jb3B5KHRpbGVQb3MpO1xuICAgICAgICBcbiAgICAgICAgaWYoIFwic2NhbGVcIiBpbiBhaU9wdGlvbnMpe1xuICAgICAgICAgICAgZW5lbXkuc2NhbGUuc2V0KGFpT3B0aW9ucy5zY2FsZSxhaU9wdGlvbnMuc2NhbGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2V7XG4gICAgICAgICAgICBlbmVteS5zY2FsZS5zZXQoMiwgMik7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gLSBhZGQgY3VzdG9tIGNvbGxpc2lvbiBzaGFwZSBmb3IgZWFjaCBlbmVteSBpbiBhbiBvcHRpb24gdmFyaWFibGUgXG4gICAgICAgIGlmKCBcInNpemVcIiBpbiBhaU9wdGlvbnMpe1xuICAgICAgICAgICAgZW5lbXkuYWRkUGh5c2ljcyhuZXcgQUFCQihWZWMyLlpFUk8sIGFpT3B0aW9ucy5zaXplLmNsb25lKCkpKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgZW5lbXkuYWRkUGh5c2ljcyhuZXcgQUFCQihWZWMyLlpFUk8sIG5ldyBWZWMyKDE2LCAyNSkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFwib2Zmc2V0XCIgaW4gYWlPcHRpb25zKXtcbiAgICAgICAgICAgIGVuZW15LmNvbGxpZGVyT2Zmc2V0LnNldChhaU9wdGlvbnMub2Zmc2V0LngsYWlPcHRpb25zLm9mZnNldC55KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNle1xuICAgICAgICAgICAgZW5lbXkuY29sbGlkZXJPZmZzZXQuc2V0KDAsIDYpO1xuICAgICAgICB9XG5cbiAgICAgICAgZW5lbXkuYWRkQUkoYWksIGFpT3B0aW9ucyk7IC8vVE9ETyAtIGFkZCBpbmRpdmlkdWFsIGVuZW15IEFJXG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmhlYWx0aEJhciA9IDxSZWN0PnRoaXMuYWRkLmdyYXBoaWMoR3JhcGhpY1R5cGUuUkVDVCwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogZW5lbXkuY29sbGlzaW9uU2hhcGUuY2VudGVyLmNsb25lKCkuYWRkKG5ldyBWZWMyKDAsIC0oKDxBQUJCPmVuZW15LmNvbGxpc2lvblNoYXBlKS5oaCs1KSkpLCBzaXplOiBuZXcgVmVjMigoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmh3KjMsIDUpfSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmhlYWx0aEJhci5ib3JkZXJDb2xvciA9IENvbG9yLkJMQUNLO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5oZWFsdGhCYXIuYm9yZGVyV2lkdGggPSAxO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5oZWFsdGhCYXIuY29sb3IgPSBDb2xvci5HUkVFTjtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkucG9pc29uU3RhdCA9IHRoaXMuYWRkLnNwcml0ZShcInBvaXNvbmluZ1wiLCBcInByaW1hcnlcIik7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLnBvaXNvblN0YXQucG9zaXRpb24gPSBlbmVteS5jb2xsaXNpb25TaGFwZS5jZW50ZXIuY2xvbmUoKS5hZGQobmV3IFZlYzIoKCgoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmh3KSotMSwgLSgoPEFBQkI+ZW5lbXkuY29sbGlzaW9uU2hhcGUpLmhoKzUpKSkpO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnNjYWxlLnNldCgxLCAxKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYnVyblN0YXQgPSB0aGlzLmFkZC5zcHJpdGUoXCJidXJuaW5nXCIsIFwicHJpbWFyeVwiKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYnVyblN0YXQucG9zaXRpb24gPSAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnBvc2l0aW9uLmNsb25lKCkuYWRkKG5ldyBWZWMyKDE1LCAwKSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmJ1cm5TdGF0LnNjYWxlLnNldCgxLCAxKTtcbiAgICAgICAgKDxFbmVteUFJPmVuZW15Ll9haSkuYmxlZWRTdGF0ID0gdGhpcy5hZGQuc3ByaXRlKFwiYmxlZWRpbmdcIiwgXCJwcmltYXJ5XCIpO1xuICAgICAgICAoPEVuZW15QUk+ZW5lbXkuX2FpKS5ibGVlZFN0YXQucG9zaXRpb24gPSAoPEVuZW15QUk+ZW5lbXkuX2FpKS5wb2lzb25TdGF0LnBvc2l0aW9uLmNsb25lKCkuYWRkKG5ldyBWZWMyKDMwLCAwKSk7XG4gICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmJsZWVkU3RhdC5zY2FsZS5zZXQoMSwgMSk7XG4gICAgICAgIGVuZW15LnNldEdyb3VwKFwiRW5lbXlcIik7XG4gICAgICAgIGVuZW15LnNldFRyaWdnZXIoXCJwbGF5ZXJcIiwgUGxheWVyX0V2ZW50cy5QTEFZRVJfQ09MTElERSwgbnVsbCk7XG5cbiAgICAgICAgLy9hZGQgZW5lbXkgdG8gdGhlIGVuZW15IGFycmF5XG4gICAgICAgIHRoaXMuZW5lbWllcy5wdXNoKGVuZW15KTtcbiAgICAgICAgLy90aGlzLmJhdHRsZU1hbmFnZXIuc2V0RW5lbWllcyh0aGlzLmVuZW1pZXMubWFwKGVuZW15ID0+IDxCYXR0bGVyQUk+ZW5lbXkuX2FpKSk7XG4gICAgICAgIHRoaXMuYmF0dGxlTWFuYWdlci5hZGRFbmVteSg8QmF0dGxlckFJPmVuZW15Ll9haSk7XG4gICAgfVxuICAgIFxuXG4gICAgLy9UT0RPIC0gZ2l2ZSBlYWNoIGVuZW15IHVuaXF1ZSB3ZWFwb25cbiAgICBwcm90ZWN0ZWQgaW5pdGlhbGl6ZUVuZW1pZXMoIGVuZW1pZXM6IEVuZW15W10pe1xuICAgICAgICBmb3IgKGxldCBlbmVteSBvZiBlbmVtaWVzKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKGVuZW15LnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIFwiU25ha2VcIjogICAgICAgLy9TbmFrZSBlbmVtaWVzIGRyb3AgZnJvbSBza3koXCJ0cmVlc1wiKT8gb3IgY291bGQganVzdCBiZSB2ZXJ5IGFidW5kYW50XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRW5lbXkoXCJTbmFrZVwiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIFNuYWtlQUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDUwLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGlsZW1hcDogXCJNYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplOiBuZXcgVmVjMigxNCwxMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgOiBuZXcgVmVjMigwLCAyMiksXG4gICAgICAgICAgICAgICAgICAgICAgICBleHA6IDUwLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIFwiVGlnZXJcIjogICAgICAgLy9UaWdlciBjYW4gYmUgbWluaWJvc3MgZm9yIG5vdz8gXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRW5lbXkoXCJUaWdlclwiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIEVuZW15QUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDIwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXA6IFwiTWFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwOiAxMDAsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSBcInJlbXVzX3dlcmV3b2xmXCI6ICAgICAgIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEVuZW15KFwicmVtdXNfd2VyZXdvbGZcIiwgZW5lbXkucG9zaXRpb24uc2NhbGUoMzIpLCBFbmVteUFJLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwbGF5ZXI6IHRoaXMucGxheWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoOiAyMDAsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aWxlbWFwOiBcIk1haW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cDogNTAsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJibGFja19wdWRkaW5nXCI6ICAgICAgIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEVuZW15KFwiYmxhY2tfcHVkZGluZ1wiLCBlbmVteS5wb3NpdGlvbi5zY2FsZSgzMiksIFNsaW1lQUksIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYXllcjogdGhpcy5wbGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFsdGg6IDIwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXA6IFwiTWFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy9hY3Rpb25zOmFjdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZTogLjI1LFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogbmV3IFZlYzIoMTYsMTApLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0IDogbmV3IFZlYzIoMCw2KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cDogNTAsXG4gICAgICAgICAgICAgICAgICAgICAgICB3ZWFwb24gOiB0aGlzLmNyZWF0ZVdlYXBvbihcImtuaWZlXCIpLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFkZENoZWNrUG9pbnQoc3RhcnRpbmdUaWxlOiBWZWMyLCBzaXplOiBWZWMyLCBlbnRlcjogc3RyaW5nLCBleGl0OiBzdHJpbmcpOiBSZWN0IHtcbiAgICAgICAgbGV0IGNoZWNrUG9pbnQgPSA8UmVjdD50aGlzLmFkZC5ncmFwaGljKEdyYXBoaWNUeXBlLlJFQ1QsIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IHN0YXJ0aW5nVGlsZS5zY2FsZSgzMiksIHNpemU6IHNpemUuc2NhbGUoMzIpfSk7XG4gICAgICAgIGNoZWNrUG9pbnQuYWRkUGh5c2ljcyh1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIHRydWUpO1xuICAgICAgICBjaGVja1BvaW50LnNldFRyaWdnZXIoXCJwbGF5ZXJcIiwgZW50ZXIsIG51bGwpO1xuICAgICAgICBjaGVja1BvaW50LmNvbG9yID0gbmV3IENvbG9yKDAsIDAsIDAsIDApO1xuICAgICAgICByZXR1cm4gY2hlY2tQb2ludDtcbiAgICB9XG5cbiAgIFxuICAgIC8qKlxuICAgICAqIGRhbWFnZXMgdGhlIHBsYXllciBpZiB0aGV5IGNvbGxpZGUgd2l0aCBhbiBlbmVteVxuICAgICAqIEBwYXJhbSBwbGF5ZXIgcGxheWVyIHNwcml0ZVxuICAgICAqIEBwYXJhbSBlbmVteSBlbmVteSBzcHJpdGVcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaGFuZGxlUGxheWVyRW5lbXlDb2xsaXNpb24ocGxheWVyOiBBbmltYXRlZFNwcml0ZSwgZW5lbXk6IEFuaW1hdGVkU3ByaXRlKSB7XG4gICAgICAgIGlmKGVuZW15ID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJ1bmRlZmluZWQgZW5lbXlcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYoIHBsYXllciA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidW5kZWZpbmVkIHBsYXllclwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZih0eXBlb2YgZW5lbXkgIT0gdW5kZWZpbmVkICYmIHR5cGVvZiBwbGF5ZXIgIT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgICAgICAvL2RhbWFnZSB0aGUgcGxheWVyIFxuICAgICAgICAgICAgICAgICg8RW5lbXlBST5lbmVteS5fYWkpLmNvbGxpZGVXaXRoUGxheWVyKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudHMgdGhlIGFtb3VudCBvZiBsaWZlIHRoZSBwbGF5ZXIgaGFzXG4gICAgICogQHBhcmFtIGFtdCBUaGUgYW1vdW50IHRvIGFkZCB0byB0aGUgcGxheWVyIGxpZmVcbiAgICAgKi9cbiAgICAvKlxuICAgIHByb3RlY3RlZCBpbmNQbGF5ZXJMaWZlKGFtdDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIEdhbWVMZXZlbC5saXZlc0NvdW50ICs9IGFtdDtcbiAgICAgICAgdGhpcy5saXZlc0NvdW50TGFiZWwudGV4dCA9IFwiTGl2ZXM6IFwiICsgR2FtZUxldmVsLmxpdmVzQ291bnQ7XG4gICAgICAgIGlmIChHYW1lTGV2ZWwubGl2ZXNDb3VudCA9PT0gMCl7XG4gICAgICAgICAgICBJbnB1dFdyYXBwZXIuZGlzYWJsZUlucHV0KCk7XG4gICAgICAgICAgICB0aGlzLnBsYXllci5kaXNhYmxlUGh5c2ljcygpO1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHtrZXk6IFwicGxheWVyX2RlYXRoXCIsIGxvb3A6IGZhbHNlLCBob2xkUmVmZXJlbmNlOiBmYWxzZX0pO1xuICAgICAgICAgICAgdGhpcy5wbGF5ZXIudHdlZW5zLnBsYXkoXCJkZWF0aFwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAqL1xuXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBwbGF5ZXIgdG8gc3Bhd25cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzcGF3blBsYXllcigpOiB2b2lkIHtcbiAgICAgICAgSW5wdXRXcmFwcGVyLmVuYWJsZUlucHV0KCk7XG4gICAgICAgIHRoaXMucGxheWVyLnBvc2l0aW9uLmNvcHkodGhpcy5zdGFydHBvcyk7XG4gICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfSFAgPSAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5NQVhfSFAgO1xuICAgICAgICAvLyg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmxpdmVzIC0tO1xuXG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBcbiAgICAgKiBoYW5kbGVzIHRoZSBwbGF5ZXIgZmFsbGluZyBvZmYgdGhlIG1hcFxuICAgICAqIFxuICAgICAqIEBwYXJhbSB2aWV3cG9ydENlbnRlciBUaGUgY2VudGVyIG9mIHRoZSB2aWV3cG9ydFxuICAgICAqIEBwYXJhbSB2aWV3cG9ydFNpemUgVGhlIHNpemUgb2YgdGhlIHZpZXdwb3J0XG4gICAgICovXG4gICAgcHJvdGVjdGVkIHBsYXllckZhbGxvZmYodmlld3BvcnRDZW50ZXI6IFZlYzIsIHZpZXdwb3J0U2l6ZTogVmVjMik6dm9pZHtcbiAgICAgICAgIGlmKHRoaXMucGxheWVyLnBvc2l0aW9uLnkgPj0gdmlld3BvcnRDZW50ZXIueSArdmlld3BvcnRTaXplLnkvMi4wKXtcblx0XHRcdFxuXHRcdFx0dGhpcy5wbGF5ZXIucG9zaXRpb24uc2V0KHRoaXMucGxheWVyU3Bhd24ueCx0aGlzLnBsYXllclNwYXduLnkpO1xuXG4gICAgICAgICAgICAvL1RPRE8gLSBkZWNyZWFzZSBwbGF5ZXIgaGVhbHRoIG9yIGNhbiBraWxsIHBsYXllciBoZXJlXG4gICAgICAgICAgICAvLyg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfSFAgKj0gLjc1O1xuICAgICAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KFBsYXllcl9FdmVudHMuUExBWUVSX0tJTExFRCk7XG5cdFx0fVxuICAgICAgICBcbiAgICB9XG5cblxuICAgIHByb3RlY3RlZCBwbGF5U3RhcnRTdG9yeSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRvdWNoZWRTdGFydENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMudG91Y2hlZFN0YXJ0Q2hlY2tQb2ludCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnN0b3J5TG9hZGVyKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9zdG9yeS5qc29uXCIpO1xuICAgICAgICAgICAgdGhpcy5zdGFydFRpbWVyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcGxheUVuZFN0b3J5KCkge1xuICAgICAgICBpZiAoIXRoaXMudG91Y2hlZEVuZENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMudG91Y2hlZEVuZENoZWNrUG9pbnQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zdG9yeUxvYWRlcihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvc3RvcnkuanNvblwiKTtcbiAgICAgICAgICAgIHRoaXMuZW5kVGltZXIoKTtcbiAgICAgICAgICAgIHRoaXMubGV2ZWxFbmRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc3RhcnRUaW1lcigpIHtcbiAgICAgICAgdGhpcy5nYW1lU3RhcnRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGVuZFRpbWVyKCkge1xuICAgICAgICB0aGlzLmdhbWVTdGFydGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGdvVG9OZXh0TGV2ZWwoKSB7XG4gICAgICAgIC8vIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoUG9yY2VsYWluKTtcbiAgICB9XG5cblxuICAgIHByb3RlY3RlZCBhc3luYyBzdG9yeUxvYWRlcihzdG9yeVBhdGg6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09IEdhbWVTdGF0ZS5TVE9SWSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0R2FtZVN0YXRlKEdhbWVTdGF0ZS5TVE9SWSk7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgKGF3YWl0IGZldGNoKHN0b3J5UGF0aCkpLmpzb24oKTtcbiAgICAgICAgdGhpcy5zdG9yeSA9IDxTdG9yeT5yZXNwb25zZTtcbiAgICAgICAgY29uc29sZS5sb2coXCJzdG9yeTpcIiwgdGhpcy5zdG9yeSk7XG4gICAgICAgIGlmICh0aGlzLnN0b3J5LmJnbSkge1xuICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMgPSBuZXcgQXJyYXk7XG4gICAgICAgICAgICB0aGlzLnN0b3J5LmJnbS5mb3JFYWNoKChiZ20pID0+IHtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxvYWQuZ2V0QXVkaW8oYmdtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHsga2V5OiBiZ20ua2V5LCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZC5zaW5nbGVBdWRpbyhiZ20ua2V5LCBiZ20ucGF0aCwgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmZpcmVFdmVudChHYW1lRXZlbnRUeXBlLlBMQVlfU09VTkQsIHsga2V5OiBiZ20ua2V5LCBsb29wOiBmYWxzZSwgaG9sZFJlZmVyZW5jZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMucHVzaChiZ20ua2V5KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jdXJyZW50U3BlYWtlciA9IHRoaXMuc3RvcnkudGV4dHNbMF0uc3BlYWtlcjtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udGVudCA9IHRoaXMuc3RvcnkudGV4dHNbMF0uY29udGVudDtcbiAgICAgICAgdGhpcy5zdG9yeUxheWVyLmVuYWJsZSgpO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcInN0b3J5XCIsIHsgcG9zaXRpb246IG5ldyBWZWMyKDUwLCB0aGlzLnZpZXdwb3J0LmdldEhhbGZTaXplKCkueSArIDgwKSwgdGV4dDogXCJcIiB9KTtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5zaXplID0gbmV3IFZlYzIoMCwgMjUpO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLmZvbnQgPSBcIlBpeGVsU2ltcGxlXCI7XG4gICAgICAgIHRoaXMuc3Rvcnl0ZXh0TGFiZWwuZm9udFNpemUgPSAyNTtcbiAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC5zZXRIQWxpZ24oSEFsaWduLkxFRlQpO1xuICAgICAgICB0aGlzLnN0b3J5UHJvZ3Jlc3MgPSAtMTtcbiAgICAgICAgdGhpcy5zdG9yeVNwcml0ZXMgPSBuZXcgQXJyYXk7XG4gICAgICAgIHRoaXMudXBkYXRlU3RvcnkoKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgaGFzTmV4dFN0b3J5KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nYW1lU3RhdGVTdGFjay5wZWVrKCkgPT09ICBHYW1lU3RhdGUuU1RPUlkgJiYgdGhpcy5zdG9yeVByb2dyZXNzICsgMSA8IHRoaXMuc3RvcnkudGV4dHMubGVuZ3RoO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVTdG9yeSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzTmV4dFN0b3J5KCkpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcnlQcm9ncmVzcysrO1xuICAgICAgICAgICAgbGV0IHRtcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5LnRleHRzW3RoaXMuc3RvcnlQcm9ncmVzc10uYWN0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5hY3Rpb25zLmZvckVhY2goYWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24udHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcImxvYWRTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5sb2FkLmdldEltYWdlKGFjdGlvbi5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAucG9zaXRpb24uc2V0KGFjdGlvbi5wb3NpdG9uWzBdLCBhY3Rpb24ucG9zaXRvblsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5zY2FsZS5zZXQoYWN0aW9uLnNjYWxlWzBdLCBhY3Rpb24uc2NhbGVbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWQuc2luZ2xlSW1hZ2UoYWN0aW9uLmtleSwgYWN0aW9uLnBhdGgsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuYWRkLnNwcml0ZShhY3Rpb24ua2V5LCBcInN0b3J5XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnBvc2l0aW9uLnNldChhY3Rpb24ucG9zaXRvblswXSwgYWN0aW9uLnBvc2l0b25bMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnNjYWxlLnNldChhY3Rpb24uc2NhbGVbMF0sIGFjdGlvbi5zY2FsZVsxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIm1vdmVTcHJpdGVcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSB0aGlzLnN0b3J5U3ByaXRlcy5maW5kKGZ1bmN0aW9uIChzcHJpdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNwcml0ZS5pbWFnZUlkID09PSBhY3Rpb24ua2V5O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcC5wb3NpdGlvbi5zZXQoYWN0aW9uLnBvc2l0b25bMF0sIGFjdGlvbi5wb3NpdG9uWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAuc2NhbGUuc2V0KGFjdGlvbi5zY2FsZVswXSwgYWN0aW9uLnNjYWxlWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgXCJzaG93U3ByaXRlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gdGhpcy5zdG9yeVNwcml0ZXMuZmluZChmdW5jdGlvbiAoc3ByaXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzcHJpdGUuaW1hZ2VJZCA9PT0gYWN0aW9uLmtleTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAudmlzaWJsZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaGlkZVNwcml0ZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRoaXMuc3RvcnlTcHJpdGVzLmZpbmQoZnVuY3Rpb24gKHNwcml0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ByaXRlLmltYWdlSWQgPT09IGFjdGlvbi5rZXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jdXJyZW50U3BlYWtlciA9IHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5zcGVha2VyO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Q29udGVudCA9IHRoaXMuc3RvcnkudGV4dHNbdGhpcy5zdG9yeVByb2dyZXNzXS5jb250ZW50O1xuICAgICAgICAgICAgdGhpcy5zdG9yeXRleHRMYWJlbC50ZXh0ID0gKHRoaXMuY3VycmVudFNwZWFrZXI/KHRoaXMuY3VycmVudFNwZWFrZXIrXCI6XCIpOihcIlwiKSkgKyAnXFxuJyArIHRoaXMuY3VycmVudENvbnRlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldEdhbWVTdGF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5zdG9yeVByb2dyZXNzID0gSW5maW5pdHk7XG4gICAgICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsLmRlc3Ryb3koKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0b3J5U3ByaXRlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcnlTcHJpdGVzLmZvckVhY2goKHNwcml0ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzcHJpdGUudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBzcHJpdGUuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RvcnlCR01zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMuZm9yRWFjaCgoYmdtKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoR2FtZUV2ZW50VHlwZS5TVE9QX1NPVU5ELCB7IGtleTogYmdtIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInNvdW5kIHN0b3BwZWQ6XCIsIGJnbSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0b3J5TGF5ZXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgdGhpcy5zdG9yeUJHTXMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5U3ByaXRlcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuc3RvcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnN0b3J5dGV4dExhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgLy8gdGhpcy5zdG9yeUxheWVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKHRoaXMubGV2ZWxFbmRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdHRlci5maXJlRXZlbnQoUGxheWVyX0V2ZW50cy5HSVZFX1NQRUNJQUxfQlVGRiwge30pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlYXRcbiAgICBwcm90ZWN0ZWQgZW5hYmxlQ2hlYXQoKSB7XG4gICAgICAgIGlmICh0aGlzLnBhdXNlSW5wdXQudGV4dC50b1VwcGVyQ2FzZSgpID09PSBcIlVVRERMUkxSQkFCQVwiKSB7XG4gICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5nb2RNb2RlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGxldCBjb21tYW5kcyA9IHRoaXMucGF1c2VJbnB1dC50ZXh0LnNwbGl0KCcgJyk7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhjb21tYW5kcyk7XG4gICAgICAgICAgICBpZiAoY29tbWFuZHMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbW1hbmRzWzBdLnRvVXBwZXJDYXNlKCkgPT09IFwiU0VUXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjb21tYW5kc1sxXS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiQVRLXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKDxQbGF5ZXJDb250cm9sbGVyPnRoaXMucGxheWVyLl9haSkuQ1VSUkVOVF9BVEsgPSBwYXJzZUludChjb21tYW5kc1syXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiSFBcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoPFBsYXllckNvbnRyb2xsZXI+dGhpcy5wbGF5ZXIuX2FpKS5DVVJSRU5UX0hQID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkVYUFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfRVhQID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcIlNMRFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLkNVUlJFTlRfU0hJRUxEID0gcGFyc2VJbnQoY29tbWFuZHNbMl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICg8UGxheWVyQ29udHJvbGxlcj50aGlzLnBsYXllci5fYWkpLmdvZE1vZGUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhdXNlSW5wdXQudGV4dCA9IFwiXCI7XG4gICAgfVxufVxuICAgIFxuXG4iLCJpbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBHYW1lU3RhdGUgfSBmcm9tIFwiLi4vc3dvcmRfZW51bXNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL01haW5NZW51XCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEdhbWVPdmVyIGV4dGVuZHMgU2NlbmUge1xuXG4gICAgc3RhcnRTY2VuZSgpIHtcbiAgICAgICAgSW5wdXRXcmFwcGVyLnNldFN0YXRlKEdhbWVTdGF0ZS5QQVVTRSk7XG4gICAgICAgIGNvbnN0IGNlbnRlciA9IHRoaXMudmlld3BvcnQuZ2V0Q2VudGVyKCk7XG5cbiAgICAgICAgdGhpcy5hZGRVSUxheWVyKFwicHJpbWFyeVwiKTtcblxuICAgICAgICBjb25zdCBnYW1lT3ZlciA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJZT1UgRElFRFwifSk7XG4gICAgICAgIGdhbWVPdmVyLnRleHRDb2xvciA9IENvbG9yLlJFRDtcbiAgICAgICAgZ2FtZU92ZXIuZm9udFNpemUgPSAxMDA7XG5cbiAgICAgICAgY29uc3QgaGludCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJwcmltYXJ5XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTAwKSwgdGV4dDogXCJDbGljayB0byBnbyBiYWNrIHRvIE1haW4gTWVudVwifSk7XG4gICAgICAgIGhpbnQudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgfVxuXG4gICAgdXBkYXRlU2NlbmUoKXtcbiAgICAgICAgaWYoSW5wdXRXcmFwcGVyLmlzTGVmdE1vdXNlSnVzdFByZXNzZWQoKSl7XG4gICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51KTtcbiAgICAgICAgfVxuICAgIH1cbn0iLCJpbXBvcnQgeyBUaWxlZFRpbGVtYXBEYXRhIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9UaWxlc2V0cy9UaWxlZERhdGFcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IERlYnVnIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EZWJ1Zy9EZWJ1Z1wiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IFJhbmRvbU1hcEdlbmVyYXRvciBmcm9tIFwiLi4vVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yXCI7XG5pbXBvcnQgR2FtZUxldmVsIGZyb20gXCIuL0dhbWVMZXZlbFwiO1xuaW1wb3J0IExhYmVsIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0xhYmVsXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCB7IFN0YXR1c2VzIH0gZnJvbSBcIi4uL3N3b3JkX2VudW1zXCI7XG5pbXBvcnQgQUFCQiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1NoYXBlcy9BQUJCXCI7XG5pbXBvcnQgRW5lbXlBSSBmcm9tIFwiLi4vQUkvRW5lbXlBSVwiO1xuaW1wb3J0IEJhdHRsZXJBSSBmcm9tIFwiLi4vQUkvQmF0dGxlckFJXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR3JlYXR3YWxsIGV4dGVuZHMgR2FtZUxldmVsIHtcbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIHN1cGVyLmxvYWRTY2VuZSgpO1xuICAgICAgICB0aGlzLnJtZyA9IG5ldyBSYW5kb21NYXBHZW5lcmF0b3IoXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL2dyZWF0d2FsbF90ZW1wbGF0ZS5qc29uXCIsIElucHV0V3JhcHBlci5yYW5kb21TZWVkKTtcbiAgICAgICAgdGhpcy5tYXAgPSB0aGlzLnJtZy5nZXRNYXAoKTtcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5tYXApO1xuICAgICAgICB0aGlzLmxvYWQudGlsZW1hcEZyb21PYmplY3QoXCJtYXBcIiwgdGhpcy5tYXApO1xuXG4gICAgICAgIC8vbG9hZCBlbmVtaWVzXG5cbiAgICAgICAgLy9jYW4gbG9hZCBlbmVteSBzcHJpdGUgaGVyZVxuICAgICAgICAvL3Nwcml0ZXMgb2J0YWluZWQgZnJvbSBjc2UzODAgc3ByaXRlIHdlc2JpdGVcbiAgICAgICAgLy8gdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwiYmxhY2tfcHVkZGluZ1wiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvYmxhY2tfcHVkZGluZy5qc29uXCIpO1xuXG4gICAgICAgIC8vbG9hZCBtdXNpYyBoZXJlXG4gICAgfVxufSIsIlxuaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IENvbmZpZ01hbmFnZXIgZnJvbSBcIi4uL1Rvb2xzL0NvbmZpZ01hbmFnZXJcIjtcbmltcG9ydCBTYXZlTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvU2F2ZU1hbmFnZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBNYWluTWVudSBmcm9tIFwiLi9NYWluTWVudVwiO1xuaW1wb3J0IFR1dG9yaWFsIGZyb20gXCIuL1R1dG9yaWFsXCI7XG5pbXBvcnQgUG9yY2VsYWluIGZyb20gXCIuL1BvcmNlbGFpblwiO1xuaW1wb3J0IEdyZWF0d2FsbCBmcm9tICcuL0dyZWF0d2FsbCc7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcblxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMZXZlbHMgZXh0ZW5kcyBTY2VuZSB7XG4gICAgcHJpdmF0ZSBwcmltYXJ5OiBMYXllcjtcbiAgICAvLyBUT0RPXG4gICAgbG9hZFNjZW5lKCl7fVxuICAgIHN0YXJ0U2NlbmUoKXtcbiAgICAgICAgY29uc3QgY2VudGVyID0gdGhpcy52aWV3cG9ydC5nZXRDZW50ZXIoKTtcblxuICAgICAgICAvLyBUaGUgbWFpbiBtZW51XG4gICAgICAgIHRoaXMucHJpbWFyeSA9IHRoaXMuYWRkVUlMYXllcihcInByaW1hcnlcIik7XG5cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHR1dG9yaWFsID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAxMDApLCB0ZXh0OiBcIlN0YXJ0IEdhbWVcIn0pO1xuICAgICAgICB0dXRvcmlhbC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgdHV0b3JpYWwuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICB0dXRvcmlhbC5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICB0dXRvcmlhbC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgdHV0b3JpYWwub25DbGlja0V2ZW50SWQgPSBcInN0YXJ0XCI7XG5cbiAgICAgICAgY29uc3QgcG9yY2VsYWluID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcInByaW1hcnlcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkpLCB0ZXh0OiBcInBvcmNlbGFpbihUZXN0KVwifSk7XG4gICAgICAgIHBvcmNlbGFpbi5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgcG9yY2VsYWluLmJvcmRlcldpZHRoID0gMjtcbiAgICAgICAgcG9yY2VsYWluLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIHBvcmNlbGFpbi5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgcG9yY2VsYWluLm9uQ2xpY2tFdmVudElkID0gXCJwb3JjZWxhaW5cIjtcblxuICAgICAgICBjb25zdCBncmVhdHdhbGwgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDEwMCksIHRleHQ6IFwiZ3JlYXR3YWxsKFRlc3QpXCJ9KTtcbiAgICAgICAgZ3JlYXR3YWxsLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBncmVhdHdhbGwuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBncmVhdHdhbGwuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgZ3JlYXR3YWxsLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBncmVhdHdhbGwub25DbGlja0V2ZW50SWQgPSBcImdyZWF0d2FsbFwiO1xuXG4gICAgICAgIGNvbnN0IGJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwicHJpbWFyeVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDIwMCksIHRleHQ6IFwiQmFja1wifSk7XG4gICAgICAgIGJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGJhY2suYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBiYWNrLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGJhY2sub25DbGlja0V2ZW50SWQgPSBcImJhY2tcIjtcbiAgICAgICAgXG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwic3RhcnRcIik7XG4gICAgICAgIHRoaXMucmVjZWl2ZXIuc3Vic2NyaWJlKFwicG9yY2VsYWluXCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImdyZWF0d2FsbFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJiYWNrXCIpO1xuICAgIH1cblxuICAgIHVwZGF0ZVNjZW5lKCl7XG4gICAgICAgIHdoaWxlKHRoaXMucmVjZWl2ZXIuaGFzTmV4dEV2ZW50KCkpe1xuICAgICAgICAgICAgbGV0IGV2ZW50ID0gdGhpcy5yZWNlaXZlci5nZXROZXh0RXZlbnQoKTtcblxuICAgICAgICAgICAgY29uc29sZS5sb2coZXZlbnQpO1xuXG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwic3RhcnRcIil7XG4gICAgICAgICAgICAgICAgSW5wdXRXcmFwcGVyLnJhbmRvbVNlZWQgPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAxMDAwMDAwMDAwMCkudG9TdHJpbmcoKTs7XG4gICAgICAgICAgICAgICAgbGV0IHNjZW5lT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgcGh5c2ljczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBOYW1lczogW1wiZ3JvdW5kXCIsIFwicGxheWVyXCIsIFwiZW5lbWllc1wiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbnM6XG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsIDEsIDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAwLCAwXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMSwgMCwgMF1cbiAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKFR1dG9yaWFsLCB7fSwgc2NlbmVPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJwb3JjZWxhaW5cIil7XG4gICAgICAgICAgICAgICAgbGV0IHNjZW5lT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICAgICAgcGh5c2ljczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBOYW1lczogW1wiZ3JvdW5kXCIsIFwicGxheWVyXCIsIFwiZW5lbWllc1wiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxpc2lvbnM6XG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsIDEsIDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsxLCAwLCAwXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMSwgMCwgMF1cbiAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKFBvcmNlbGFpbiwge30sIHNjZW5lT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwiZ3JlYXR3YWxsXCIpe1xuICAgICAgICAgICAgICAgIGxldCBzY2VuZU9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHBoeXNpY3M6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwTmFtZXM6IFtcImdyb3VuZFwiLCBcInBsYXllclwiLCBcImVuZW1pZXNcIl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xsaXNpb25zOlxuICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLCAxLCAxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMSwgMCwgMF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWzEsIDAsIDBdXG4gICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShHcmVhdHdhbGwsIHt9LCBzY2VuZU9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihldmVudC50eXBlID09PSBcImJhY2tcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShNYWluTWVudSwge30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIFxuICAgICAgICB9XG4gICAgfVxuXG59IiwiaW1wb3J0IFNjZW5lIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9TY2VuZS9TY2VuZVwiO1xuaW1wb3J0IENvbmZpZ01hbmFnZXIgZnJvbSBcIi4uL1Rvb2xzL0NvbmZpZ01hbmFnZXJcIjtcbmltcG9ydCBTYXZlTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvU2F2ZU1hbmFnZXJcIjtcbmltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IHsgR2FtZUV2ZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9FdmVudHMvR2FtZUV2ZW50VHlwZVwiO1xuaW1wb3J0IEFuaW1hdGVkU3ByaXRlIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9TcHJpdGVzL0FuaW1hdGVkU3ByaXRlXCI7XG5pbXBvcnQgQnV0dG9uIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL0J1dHRvblwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgQ29sb3IgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1V0aWxzL0NvbG9yXCI7XG5pbXBvcnQgTGF5ZXIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL0xheWVyXCI7XG5pbXBvcnQgTGFiZWwgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvTGFiZWxcIjtcbmltcG9ydCBMZXZlbHMgZnJvbSBcIi4vTGV2ZWxzXCI7XG5pbXBvcnQgUmFuZG9tTWFwR2VuZXJhdG9yIGZyb20gXCIuLi9Ub29scy9SYW5kb21NYXBHZW5lcmF0b3JcIjtcbmltcG9ydCBHYW1lTGV2ZWwgZnJvbSBcIi4vR2FtZUxldmVsXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1haW5NZW51IGV4dGVuZHMgU2NlbmUge1xuICAgIHByb3RlY3RlZCBjb25maWc6IENvbmZpZ01hbmFnZXI7XG4gICAgcHJvdGVjdGVkIHNhdmU6IFNhdmVNYW5hZ2VyO1xuXG4gICAgLy8gTGF5ZXJzLCBmb3IgbXVsdGlwbGUgbWFpbiBtZW51IHNjcmVlbnNcbiAgICBwcml2YXRlIG1haW5NZW51OiBMYXllcjtcbiAgICBwcml2YXRlIGFib3V0OiBMYXllcjtcbiAgICBwcml2YXRlIGNvbnRyb2w6IExheWVyO1xuICAgIC8vIHByaXZhdGUgcm1nOiBSYW5kb21NYXBHZW5lcmF0b3I7XG5cbiAgICBsb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIC8vIExvYWQgdGhlIG1lbnUgc29uZ1xuICAgICAgICAvL3RoaXMubG9hZC5hdWRpbyhcIm1lbnVcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL211c2ljL21lbnUubXAzXCIpO1xuICAgIH1cblxuICAgIC8vVE9ETyBcbiAgICBcbiAgICBzdGFydFNjZW5lKCk6IHZvaWR7XG4gICAgICAgIEdhbWVMZXZlbC5nYW1lVGltZXIgPSAwO1xuICAgICAgICBjb25zdCBjZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpO1xuXG4gICAgICAgIC8vIFRoZSBtYWluIG1lbnVcbiAgICAgICAgdGhpcy5tYWluTWVudSA9IHRoaXMuYWRkVUlMYXllcihcIm1haW5NZW51XCIpO1xuXG4gICAgICAgIC8vIEFkZCBtYXAgYnV0dG9uLCBhbmQgZ2l2ZSBpdCBhbiBldmVudCB0byBlbWl0IG9uIHByZXNzXG4gICAgICAgIGNvbnN0IG1hcCA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJtYWluTWVudVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDEwMCksIHRleHQ6IFwiTWFwXCJ9KTtcbiAgICAgICAgbWFwLnNpemUuc2V0KDIwMCwgNTApO1xuICAgICAgICBtYXAuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBtYXAuYm9yZGVyQ29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgbWFwLmJhY2tncm91bmRDb2xvciA9IENvbG9yLlRSQU5TUEFSRU5UO1xuICAgICAgICBtYXAub25DbGlja0V2ZW50SWQgPSBcIm1hcFwiO1xuXG5cbiAgICAgICAgLy8gQWRkIGFib3V0IGJ1dHRvblxuICAgICAgICBjb25zdCBhYm91dCA9IHRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkJVVFRPTiwgXCJtYWluTWVudVwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDEwMCksIHRleHQ6IFwiQWJvdXRcIn0pO1xuICAgICAgICBhYm91dC5zaXplLnNldCgyMDAsIDUwKTtcbiAgICAgICAgYWJvdXQuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBhYm91dC5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBhYm91dC5iYWNrZ3JvdW5kQ29sb3IgPSBDb2xvci5UUkFOU1BBUkVOVDtcbiAgICAgICAgYWJvdXQub25DbGlja0V2ZW50SWQgPSBcImFib3V0XCI7XG5cbiAgICAgICAgLy8gQWRkIGFib3V0IGJ1dHRvblxuICAgICAgICBjb25zdCBmb3JtID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcIm1haW5NZW51XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMjAwKSwgdGV4dDogXCJHb29nbGUgRm9ybVwifSk7XG4gICAgICAgIGZvcm0uc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGZvcm0uYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBmb3JtLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGZvcm0uYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGZvcm0ub25DbGljayA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgd2luZG93Lm9wZW4oXCJodHRwczovL2Zvcm1zLmdsZS9LdTdSbVVkTm43YjltNWNoNlwiKTtcbiAgICAgICAgfTtcbiAgICAgICAgXG4gICAgICAgIC8vIEFkZCBjb250cm9sIGJ1dHRvbiwgYW5kIGdpdmUgaXQgYW4gZXZlbnQgdG8gZW1pdCBvbiBwcmVzc1xuICAgICAgICBjb25zdCBjb250cm9sID0gdGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuQlVUVE9OLCBcIm1haW5NZW51XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogXCJDb250cm9sc1wifSk7XG4gICAgICAgIGNvbnRyb2wuc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGNvbnRyb2wuYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBjb250cm9sLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnRyb2wuYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGNvbnRyb2wub25DbGlja0V2ZW50SWQgPSBcImNvbnRyb2xcIjtcblxuICAgICAgICAvKiAjIyMjIyMjIyMjIEFCT1VUIFNDUkVFTiAjIyMjIyMjIyMjICovXG4gICAgICAgIHRoaXMuYWJvdXQgPSB0aGlzLmFkZFVJTGF5ZXIoXCJhYm91dFwiKTtcbiAgICAgICAgdGhpcy5hYm91dC5zZXRIaWRkZW4odHJ1ZSk7XG5cbiAgICAgICAgY29uc3QgYWJvdXRIZWFkZXIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAyNTApLCB0ZXh0OiBcIkFib3V0XCJ9KTtcbiAgICAgICAgYWJvdXRIZWFkZXIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG5cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHRleHQxID0gXCJUaGlzIGdhbWUgd2FzIGNyZWF0ZWQgYnkgSGVucnkgQ2hlbiwgS2VsbHkgUGVuZywgYW5kIFJlbmdlXCI7XG4gICAgICAgIGNvbnN0IHRleHQyID0gXCJ1c2luZyB0aGUgV29sZmllMkQgZ2FtZSBlbmdpbmUsIGEgVHlwZVNjcmlwdCBnYW1lIGVuZ2luZSBjcmVhdGVkIGJ5XCI7XG4gICAgICAgIGNvbnN0IHRleHQzID0gXCJKb2UgV2VhdmVyIGFuZCBSaWNoYXJkIE1jS2VubmEuXCI7XG5cbiAgICAgICAgY29uc3QgbGluZTEgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSA1MCksIHRleHQ6IHRleHQxfSk7XG4gICAgICAgIGNvbnN0IGxpbmUyID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImFib3V0XCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55KSwgdGV4dDogdGV4dDJ9KTtcbiAgICAgICAgY29uc3QgbGluZTMgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyA1MCksIHRleHQ6IHRleHQzfSk7XG5cbiAgICAgICAgbGluZTEudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGxpbmUyLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBsaW5lMy50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcblxuICAgICAgICBjb25zdCBhYm91dEJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiYWJvdXRcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyAyNTApLCB0ZXh0OiBcIkJhY2tcIn0pO1xuICAgICAgICBhYm91dEJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGFib3V0QmFjay5ib3JkZXJXaWR0aCA9IDI7XG4gICAgICAgIGFib3V0QmFjay5ib3JkZXJDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBhYm91dEJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGFib3V0QmFjay5vbkNsaWNrRXZlbnRJZCA9IFwibWVudVwiO1xuXG4gICAgICAgIC8vIFN1YnNjcmliZSB0byB0aGUgYnV0dG9uIGV2ZW50c1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcIm1hcFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJhYm91dFwiKTtcbiAgICAgICAgdGhpcy5yZWNlaXZlci5zdWJzY3JpYmUoXCJtZW51XCIpO1xuICAgICAgICB0aGlzLnJlY2VpdmVyLnN1YnNjcmliZShcImNvbnRyb2xcIik7XG5cbiAgICAgICBcbiAgICAgICAgLy9Db250cm9sIHNjcmVlblxuICAgICAgICB0aGlzLmNvbnRyb2wgPSB0aGlzLmFkZFVJTGF5ZXIoXCJjb250cm9sXCIpO1xuICAgICAgICB0aGlzLmNvbnRyb2wuc2V0SGlkZGVuKHRydWUpO1xuXG4gICAgXG4gICAgICAgIFxuICAgICAgICBjb25zdCBoZWFkZXIgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSAtIDI1MCksIHRleHQ6IFwiQ29udHJvbHNcIn0pO1xuICAgICAgICBoZWFkZXIudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IGxjID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgLSAxNTApLCB0ZXh0OiBcIkEvRCAtIE1vdmUgTGVmdC9SaWdodFwifSk7XG4gICAgICAgIGxjLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCByYyA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gMTAwKSwgdGV4dDogXCJXL1MgLSBMb29rIFVwL0Rvd25cIn0pO1xuICAgICAgICByYy50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgY29uc3Qgd2FzZCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55IC0gNTApLCB0ZXh0OiBcIkovWi9FbnRlciAtIENvbmZpcm0gQXR0YWNrXCJ9KTtcbiAgICAgICAgd2FzZC50ZXh0Q29sb3IgPSBDb2xvci5XSElURTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGUgPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSksIHRleHQ6IFwiU1BBQ0UvWCAtIEp1bXBcIn0pO1xuICAgICAgICBlLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCBxID0gPExhYmVsPnRoaXMuYWRkLnVpRWxlbWVudChVSUVsZW1lbnRUeXBlLkxBQkVMLCBcImNvbnRyb2xcIiwge3Bvc2l0aW9uOiBuZXcgVmVjMihjZW50ZXIueCwgY2VudGVyLnkgKyA1MCksIHRleHQ6IFwiSy9DIC0gRGFzaFwifSk7XG4gICAgICAgIHEudGV4dENvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGNvbnN0IG9uZVR3byA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMTAwKSwgdGV4dDogXCJML1YgLSBVc2UgU2tpbGxcIn0pO1xuICAgICAgICBvbmVUd28udGV4dENvbG9yID0gQ29sb3IuV0hJVEVcbiAgICAgICAgY29uc3QgenggPSA8TGFiZWw+dGhpcy5hZGQudWlFbGVtZW50KFVJRWxlbWVudFR5cGUuTEFCRUwsIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDE1MCksIHRleHQ6IFwiSS9CIC0gb3BlbiBCYWNrcGFja1wifSk7XG4gICAgICAgIHp4LnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuICAgICAgICBjb25zdCB0YiA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJjb250cm9sXCIsIHtwb3NpdGlvbjogbmV3IFZlYzIoY2VudGVyLngsIGNlbnRlci55ICsgMjAwKSwgdGV4dDogXCJFU0MgLSBQYXVzZVwifSk7XG4gICAgICAgIHRiLnRleHRDb2xvciA9IENvbG9yLldISVRFO1xuXG4gICAgICAgIGNvbnN0IGJhY2sgPSB0aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5CVVRUT04sIFwiY29udHJvbFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKGNlbnRlci54LCBjZW50ZXIueSArIDMwMCksIHRleHQ6IFwiQmFja1wifSk7XG4gICAgICAgIGJhY2suc2l6ZS5zZXQoMjAwLCA1MCk7XG4gICAgICAgIGJhY2suYm9yZGVyV2lkdGggPSAyO1xuICAgICAgICBiYWNrLmJvcmRlckNvbG9yID0gQ29sb3IuV0hJVEU7XG4gICAgICAgIGJhY2suYmFja2dyb3VuZENvbG9yID0gQ29sb3IuVFJBTlNQQVJFTlQ7XG4gICAgICAgIGJhY2sub25DbGlja0V2ZW50SWQgPSBcIm1lbnVcIjtcbiAgICAgICAgXG4gICAgfVxuXG4gICAgdW5sb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIC8vIFRoZSBzY2VuZSBpcyBiZWluZyBkZXN0cm95ZWQsIHNvIHdlIGNhbiBzdG9wIHBsYXlpbmcgdGhlIHNvbmdcbiAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuU1RPUF9TT1VORCwge2tleTogXCJtZW51XCJ9KTtcbiAgICB9XG5cbiAgICBcbiAgICB1cGRhdGVTY2VuZSgpe1xuICAgICAgICB3aGlsZSh0aGlzLnJlY2VpdmVyLmhhc05leHRFdmVudCgpKXtcbiAgICAgICAgICAgIGxldCBldmVudCA9IHRoaXMucmVjZWl2ZXIuZ2V0TmV4dEV2ZW50KCk7XG5cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGV2ZW50KTtcblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJtYXBcIil7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2VuZU1hbmFnZXIuY2hhbmdlVG9TY2VuZShMZXZlbHMsIHt9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZXZlbnQudHlwZSA9PT0gXCJhYm91dFwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLmFib3V0LnNldEhpZGRlbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5tYWluTWVudS5zZXRIaWRkZW4odHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwibWVudVwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW5NZW51LnNldEhpZGRlbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hYm91dC5zZXRIaWRkZW4odHJ1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sLnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGV2ZW50LnR5cGUgPT09IFwiY29udHJvbFwiKXtcbiAgICAgICAgICAgICAgICB0aGlzLm1haW5NZW51LnNldEhpZGRlbih0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2wuc2V0SGlkZGVuKGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgVGlsZWRUaWxlbWFwRGF0YSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBEZWJ1ZyBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGVidWcvRGVidWdcIjtcbmltcG9ydCB7IEdhbWVFdmVudFR5cGUgfSBmcm9tIFwiLi4vLi4vV29sZmllMkQvRXZlbnRzL0dhbWVFdmVudFR5cGVcIjtcbmltcG9ydCBSYW5kb21NYXBHZW5lcmF0b3IgZnJvbSBcIi4uL1Rvb2xzL1JhbmRvbU1hcEdlbmVyYXRvclwiO1xuaW1wb3J0IEdhbWVMZXZlbCBmcm9tIFwiLi9HYW1lTGV2ZWxcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IENvbG9yIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9VdGlscy9Db2xvclwiO1xuaW1wb3J0IHsgVUlFbGVtZW50VHlwZSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9Ob2Rlcy9VSUVsZW1lbnRzL1VJRWxlbWVudFR5cGVzXCI7XG5pbXBvcnQgeyBTdGF0dXNlcyB9IGZyb20gXCIuLi9zd29yZF9lbnVtc1wiO1xuaW1wb3J0IEFBQkIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9TaGFwZXMvQUFCQlwiO1xuaW1wb3J0IEVuZW15QUkgZnJvbSBcIi4uL0FJL0VuZW15QUlcIjtcbmltcG9ydCBCYXR0bGVyQUkgZnJvbSBcIi4uL0FJL0JhdHRsZXJBSVwiO1xuaW1wb3J0IElucHV0V3JhcHBlciBmcm9tIFwiLi4vVG9vbHMvSW5wdXRXcmFwcGVyXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvcmNlbGFpbiBleHRlbmRzIEdhbWVMZXZlbCB7XG4gICAgbG9hZFNjZW5lKCk6IHZvaWQge1xuICAgICAgICBzdXBlci5sb2FkU2NlbmUoKTtcbiAgICAgICAgdGhpcy5ybWcgPSBuZXcgUmFuZG9tTWFwR2VuZXJhdG9yKFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9qc29ucy9wb3JjZWxhaW5fdGVtcGxhdGUuanNvblwiLCBJbnB1dFdyYXBwZXIucmFuZG9tU2VlZCk7XG4gICAgICAgIHRoaXMubWFwID0gdGhpcy5ybWcuZ2V0TWFwKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMubWFwKTtcbiAgICAgICAgdGhpcy5sb2FkLnRpbGVtYXBGcm9tT2JqZWN0KFwibWFwXCIsIHRoaXMubWFwKTtcblxuICAgICAgICAvLyAvL2xvYWQgZW5lbWllc1xuICAgICAgICAvLyB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJTbmFrZVwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvU25ha2UuanNvblwiKTtcbiAgICAgICAgLy8gdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwiVGlnZXJcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL1RpZ2VyLmpzb25cIik7XG5cbiAgICAgICAgLy8gLy9jYW4gbG9hZCBlbmVteSBzcHJpdGUgaGVyZVxuICAgICAgICAvLyAvL3Nwcml0ZXMgb2J0YWluZWQgZnJvbSBjc2UzODAgc3ByaXRlIHdlc2JpdGVcbiAgICAgICAgLy8gdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwicmVtdXNfd2VyZXdvbGZcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL3JlbXVzX3dlcmV3b2xmLmpzb25cIik7XG4gICAgICAgIC8vIHRoaXMubG9hZC5zcHJpdGVzaGVldChcImJsYWNrX3B1ZGRpbmdcIixcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvc3ByaXRlc2hlZXRzL2JsYWNrX3B1ZGRpbmcuanNvblwiKTtcblxuICAgICAgICAvL2xvYWQgbXVzaWMgaGVyZVxuICAgIH1cbn0iLCJpbXBvcnQgU2NlbmUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL1NjZW5lL1NjZW5lXCI7XG5pbXBvcnQgQ29uZmlnTWFuYWdlciBmcm9tIFwiLi4vVG9vbHMvQ29uZmlnTWFuYWdlclwiO1xuaW1wb3J0IFNhdmVNYW5hZ2VyIGZyb20gXCIuLi9Ub29scy9TYXZlTWFuYWdlclwiO1xuaW1wb3J0IFZlYzIgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0RhdGFUeXBlcy9WZWMyXCI7XG5pbXBvcnQgeyBHYW1lRXZlbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL0V2ZW50cy9HYW1lRXZlbnRUeXBlXCI7XG5pbXBvcnQgQW5pbWF0ZWRTcHJpdGUgZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1Nwcml0ZXMvQW5pbWF0ZWRTcHJpdGVcIjtcbmltcG9ydCBCdXR0b24gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvQnV0dG9uXCI7XG5pbXBvcnQgeyBVSUVsZW1lbnRUeXBlIH0gZnJvbSBcIi4uLy4uL1dvbGZpZTJEL05vZGVzL1VJRWxlbWVudHMvVUlFbGVtZW50VHlwZXNcIjtcbmltcG9ydCBDb2xvciBmcm9tIFwiLi4vLi4vV29sZmllMkQvVXRpbHMvQ29sb3JcIjtcbmltcG9ydCBMYXllciBmcm9tIFwiLi4vLi4vV29sZmllMkQvU2NlbmUvTGF5ZXJcIjtcbmltcG9ydCBMYWJlbCBmcm9tIFwiLi4vLi4vV29sZmllMkQvTm9kZXMvVUlFbGVtZW50cy9MYWJlbFwiO1xuaW1wb3J0IExldmVscyBmcm9tIFwiLi9MZXZlbHNcIjtcbmltcG9ydCBJbnB1dFdyYXBwZXIgZnJvbSBcIi4uL1Rvb2xzL0lucHV0V3JhcHBlclwiO1xuaW1wb3J0IE1haW5NZW51IGZyb20gXCIuL01haW5NZW51XCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwbGFzaFNjcmVlbiBleHRlbmRzIFNjZW5lIHtcbiAgICBwcm90ZWN0ZWQgY29uZmlnOiBDb25maWdNYW5hZ2VyO1xuICAgIHByb3RlY3RlZCBzYXZlOiBTYXZlTWFuYWdlcjtcblxuICAgIGFuaW1hdGVkU3ByaXRlOiBBbmltYXRlZFNwcml0ZTtcbiAgICBjbGlja0xhYmVsOiBMYWJlbDtcblxuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgLy9sb2FkIGltYWdlc1xuICAgICAgICB0aGlzLmxvYWQuaW1hZ2UoXCJiYWNrZ3JvdW5kSW1hZ2VcIiwgXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2ltYWdlcy9sb2dvLnBuZ1wiKTtcbiAgICAgICAgdGhpcy5sb2FkLmltYWdlKFwibG9nb1wiLCBcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvaW1hZ2VzL2Jyb3duLnBuZ1wiKTtcbiAgICAgICAgLy8gTG9hZCB0aGUgbWVudSBzb25nXG4gICAgICAgIC8vdGhpcy5sb2FkLmF1ZGlvKFwibWVudVwiLCBcImFzc2V0cy9tdXNpYy9tZW51Lm1wM1wiKTtcbiAgICB9XG5cbiAgICAvL1RPRE8gXG4gICAgXG4gICAgc3RhcnRTY2VuZSgpOiB2b2lke1xuICAgICAgICB0aGlzLmNvbmZpZyA9IG5ldyBDb25maWdNYW5hZ2VyKCk7XG4gICAgICAgIHRoaXMuc2F2ZSA9IG5ldyBTYXZlTWFuYWdlcigpO1xuXG5cbiAgICAgICAgLy8gU2NlbmUgaGFzIHN0YXJ0ZWQsIHNvIHN0YXJ0IHBsYXlpbmcgbXVzaWNcbiAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuUExBWV9TT1VORCwge2tleTogXCJtZW51XCIsIGxvb3A6IHRydWUsIGhvbGRSZWZlcmVuY2U6IHRydWV9KTtcblxuICAgICAgICBjb25zdCBjZW50ZXIgPSB0aGlzLnZpZXdwb3J0LmdldENlbnRlcigpO1xuXG4gICAgICAgIGxldCBzaXplID0gdGhpcy52aWV3cG9ydC5nZXRIYWxmU2l6ZSgpO1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldEZvY3VzKHNpemUpO1xuICAgICAgICB0aGlzLnZpZXdwb3J0LnNldFpvb21MZXZlbCgxKTtcblxuICAgICAgICBsZXQgYmFja2dyb3VuZExheWVyID0gdGhpcy5hZGRVSUxheWVyKFwiYmFja2dyb3VuZFwiKTtcbiAgICAgICAgYmFja2dyb3VuZExheWVyLnNldERlcHRoKDApO1xuICAgICAgICBsZXQgZnJvbnRMYXllciA9IHRoaXMuYWRkVUlMYXllcihcImZyb250Z3JvdW5kXCIpO1xuICAgICAgICBmcm9udExheWVyLnNldERlcHRoKDEpO1xuXG4gICAgICAgIHRoaXMuY2xpY2tMYWJlbCA9IDxMYWJlbD50aGlzLmFkZC51aUVsZW1lbnQoVUlFbGVtZW50VHlwZS5MQUJFTCwgXCJmcm9udGdyb3VuZFwiLCB7cG9zaXRpb246IG5ldyBWZWMyKHNpemUueCwgc2l6ZS55ICsgMzAwKSwgdGV4dDogXCJcXFwiQ2xpY2sgYW55d2hlcmUgdG8gc3RhcnRcXFwiXCJ9KTtcbiAgICAgICAgdGhpcy5jbGlja0xhYmVsLnRleHRDb2xvciA9IG5ldyBDb2xvcigwLCAwLCAwLCAxKTtcbiAgICAgICAgdGhpcy5jbGlja0xhYmVsLmZvbnQgPSBcIkFyaWFsXCI7XG4gICAgICAgIHRoaXMuY2xpY2tMYWJlbC5mb250U2l6ZSA9IDcwO1xuXG4gICAgICAgIGxldCBiYWNrZ3JvdW5kID0gdGhpcy5hZGQuc3ByaXRlKFwiYmFja2dyb3VuZEltYWdlXCIsIFwiYmFja2dyb3VuZFwiKTtcbiAgICAgICAgYmFja2dyb3VuZC5wb3NpdGlvbi5zZXQoc2l6ZS54LCBzaXplLnkpO1xuXG4gICAgICAgIGxldCBsb2dvID0gdGhpcy5hZGQuc3ByaXRlKFwibG9nb1wiLCBcImZyb250Z3JvdW5kXCIpO1xuICAgICAgICBsb2dvLnBvc2l0aW9uLnNldChzaXplLngsIHNpemUueSArIDIwKTtcbiAgICAgICAgbG9nby5zY2FsZS5zZXQoNCwgNCk7IFxuXG4gICAgfVxuXG4gICAgdW5sb2FkU2NlbmUoKTogdm9pZCB7XG4gICAgICAgIC8vIFRoZSBzY2VuZSBpcyBiZWluZyBkZXN0cm95ZWQsIHNvIHdlIGNhbiBzdG9wIHBsYXlpbmcgdGhlIHNvbmdcbiAgICAgICAgLy90aGlzLmVtaXR0ZXIuZmlyZUV2ZW50KEdhbWVFdmVudFR5cGUuU1RPUF9TT1VORCwge2tleTogXCJtZW51XCJ9KTtcbiAgICB9XG5cbiAgICBcbiAgICB1cGRhdGVTY2VuZSgpe1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmlzTGVmdE1vdXNlSnVzdFByZXNzZWQoKSkgeyAgLy9pZiBsZWZ0IGNsaWNrXG4gICAgICAgICAgICB0aGlzLnNjZW5lTWFuYWdlci5jaGFuZ2VUb1NjZW5lKE1haW5NZW51LCB7fSwge30pO1xuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUodGhpcy5yZWNlaXZlci5oYXNOZXh0RXZlbnQoKSl7XG4gICAgICAgICAgICBsZXQgZXZlbnQgPSB0aGlzLnJlY2VpdmVyLmdldE5leHRFdmVudCgpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coZXZlbnQpO1xuICAgICAgICAgICAgaWYgKElucHV0V3JhcHBlci5pc0xlZnRNb3VzZUp1c3RQcmVzc2VkKCkpIHsgIC8vaWYgbGVmdCBjbGlja1xuICAgICAgICAgICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoTWFpbk1lbnUsIHt9LCB7fSk7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfVxuICAgIH1cbn1cbiIsImltcG9ydCBWZWMyIGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVmVjMlwiO1xuaW1wb3J0IFJhbmRvbU1hcEdlbmVyYXRvciBmcm9tIFwiLi4vVG9vbHMvUmFuZG9tTWFwR2VuZXJhdG9yXCI7XG5pbXBvcnQgR2FtZUxldmVsIGZyb20gXCIuL0dhbWVMZXZlbFwiO1xuaW1wb3J0IFNuYWtlQUkgZnJvbSBcIi4uL0FJL1NuYWtlQUlcIjtcbmltcG9ydCBQb3JjZWxhaW4gZnJvbSBcIi4vUG9yY2VsYWluXCI7XG5pbXBvcnQgSW5wdXRXcmFwcGVyIGZyb20gXCIuLi9Ub29scy9JbnB1dFdyYXBwZXJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVHV0b3JpYWwgZXh0ZW5kcyBHYW1lTGV2ZWwge1xuICAgIGxvYWRTY2VuZSgpOiB2b2lkIHtcbiAgICAgICAgc3VwZXIubG9hZFNjZW5lKCk7XG4gICAgICAgIHRoaXMucm1nID0gbmV3IFJhbmRvbU1hcEdlbmVyYXRvcihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvZm9yZXN0X3RlbXBsYXRlLmpzb25cIiwgSW5wdXRXcmFwcGVyLnJhbmRvbVNlZWQpO1xuICAgICAgICB0aGlzLm1hcCA9IHRoaXMucm1nLmdldE1hcCgpO1xuICAgICAgICB0aGlzLmxvYWQudGlsZW1hcEZyb21PYmplY3QoXCJtYXBcIiwgdGhpcy5tYXApO1xuXG4gICAgICAgIC8vbG9hZCBlbmVtaWVzXG4gICAgICAgIHRoaXMubG9hZC5zcHJpdGVzaGVldChcIlNuYWtlXCIsXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL3Nwcml0ZXNoZWV0cy9TbmFrZS5qc29uXCIpO1xuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJUaWdlclwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvVGlnZXIuanNvblwiKTtcblxuICAgICAgICAvL2NhbiBsb2FkIGVuZW15IHNwcml0ZSBoZXJlXG4gICAgICAgIC8vc3ByaXRlcyBvYnRhaW5lZCBmcm9tIGNzZTM4MCBzcHJpdGUgd2VzYml0ZVxuICAgICAgICB0aGlzLmxvYWQuc3ByaXRlc2hlZXQoXCJyZW11c193ZXJld29sZlwiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvcmVtdXNfd2VyZXdvbGYuanNvblwiKTtcbiAgICAgICAgdGhpcy5sb2FkLnNwcml0ZXNoZWV0KFwiYmxhY2tfcHVkZGluZ1wiLFwic2hhdHRlcmVkX3N3b3JkX2Fzc2V0cy9zcHJpdGVzaGVldHMvYmxhY2tfcHVkZGluZy5qc29uXCIpO1xuXG4gICAgICAgIC8vbG9hZCBtdXNpYyBoZXJlXG4gICAgfVxuXG4gICAgdXBkYXRlU2NlbmUoZGVsdGFUOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgc3VwZXIudXBkYXRlU2NlbmUoZGVsdGFUKTtcbiAgICAgICAgXG4gICAgICAgIC8vc3Bhd24gc25ha2UoKVxuICAgICAgICBpZihNYXRoLnJhbmRvbSgpIDwgLjAwMDEgJiYgdGhpcy5nYW1lU3RhcnRlZCl7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlJBTkRPTSBTTkFLRSFcIik7XG4gICAgICAgICAgICB0aGlzLmFkZEVuZW15KFwiU25ha2VcIiwgdGhpcy5wbGF5ZXIucG9zaXRpb24uY2xvbmUoKS5hZGQobmV3IFZlYzIoMCwtMzIwKSksIFNuYWtlQUksIHtcbiAgICAgICAgICAgICAgICBwbGF5ZXI6IHRoaXMucGxheWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhbHRoOiA1MCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVtYXA6IFwiTWFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogbmV3IFZlYzIoMTQsMTApLFxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0IDogbmV3IFZlYzIoMCwgMjIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwOiA1MCxcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZ29Ub05leHRMZXZlbCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy52aWV3cG9ydC5zZXRab29tTGV2ZWwoMSk7XG4gICAgICAgIHRoaXMuc2NlbmVNYW5hZ2VyLmNoYW5nZVRvU2NlbmUoUG9yY2VsYWluKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcGxheVN0YXJ0U3RvcnkoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy50b3VjaGVkU3RhcnRDaGVja1BvaW50KSB7XG4gICAgICAgICAgICB0aGlzLnRvdWNoZWRTdGFydENoZWNrUG9pbnQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5zdG9yeUxvYWRlcihcInNoYXR0ZXJlZF9zd29yZF9hc3NldHMvanNvbnMvbGV2ZWwxc3RvcnkuanNvblwiKTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRUaW1lcigpO1xuICAgICAgICB9XG4gICAgfVxufSIsImltcG9ydCBDb25maWcgZnJvbSBcIi4vRGF0YVR5cGVzL0NvbmZpZ1wiO1xuaW1wb3J0IExvY2FsU3RvcmFnZURCIGZyb20gXCIuL0xvY2FsU3RvcmFnZURCXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENvbmZpZ01hbmFnZXIge1xuICAgIHByaXZhdGUgc3RhdGljIGNvbmZpZzogQ29uZmlnO1xuICAgIHByaXZhdGUgZGI6IExvY2FsU3RvcmFnZURCO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuZGIgPSBuZXcgTG9jYWxTdG9yYWdlREIoXCJjb25maWdcIik7XG4gICAgICAgIHRoaXMubG9hZENvbmZpZygpO1xuXG4gICAgICAgIGlmICghQ29uZmlnTWFuYWdlci5jb25maWcpXG4gICAgICAgICAgICB0aGlzLmluaXRDb25maWcoKTtcbiAgICB9XG5cbiAgICBnZXRWb2x1bWUoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIENvbmZpZ01hbmFnZXIuY29uZmlnLnZvbHVtZTtcbiAgICB9XG5cbiAgICBzZXRWb2x1bWUodm9sdW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgQ29uZmlnTWFuYWdlci5jb25maWcudm9sdW1lID0gdm9sdW1lO1xuICAgICAgICB0aGlzLnNhdmVDb25maWcoKTtcbiAgICB9XG5cbiAgICAvLyBUT0RPc1xuICAgIC8vIGFkZCBtb3JlIGZ1bmN0aW9ucyBpZiBuZWVkZWRcblxuICAgIHJlc2V0Q29uZmlnKGNhbGxiYWNrPzogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pbml0Q29uZmlnKCk7XG4gICAgICAgIGNhbGxiYWNrKENvbmZpZ01hbmFnZXIuY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWRDb25maWcoKTogdm9pZCB7XG4gICAgICAgIENvbmZpZ01hbmFnZXIuY29uZmlnID0gPENvbmZpZz50aGlzLmRiLmxvYWRKU09OKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzYXZlQ29uZmlnKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRiLnNhdmVKU09OKENvbmZpZ01hbmFnZXIuY29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRDb25maWcoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGIucmVhZEpTT04oXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL3NhbXBsZWNvbmZpZy5qc29uXCIsIChjb25maWc6IG9iamVjdCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjb25maWcpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbCB0byBsb2FkIGNvbmZpZyBmaWxlXCIpO1xuICAgICAgICAgICAgQ29uZmlnTWFuYWdlci5jb25maWcgPSA8Q29uZmlnPmNvbmZpZztcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiSW5pdGlhbGl6aW5nIExvY2FsIFN0b3JhZ2UoY29uZmlnKTogXCIsIENvbmZpZ01hbmFnZXIuY29uZmlnKTtcbiAgICAgICAgICAgIHRoaXMuc2F2ZUNvbmZpZygpO1xuICAgICAgICB9KTtcbiAgICB9XG59IiwiaW1wb3J0IElucHV0IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9JbnB1dC9JbnB1dFwiO1xuaW1wb3J0IHtHYW1lU3RhdGV9IGZyb20gXCIuLi9zd29yZF9lbnVtc1wiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnB1dFdyYXBwZXIge1xuICAgIHByaXZhdGUgc3RhdGljIGdhbWVTdGF0ZTogR2FtZVN0YXRlID0gR2FtZVN0YXRlLkdBTUlORztcbiAgICBzdGF0aWMgcmFuZG9tU2VlZDogc3RyaW5nO1xuXG4gICAgc3RhdGljIGlzVXBQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc1ByZXNzZWQoXCJ1cFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBzdGF0aWMgaXNEb3duUHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNQcmVzc2VkKFwiZG93blwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBzdGF0aWMgaXNMZWZ0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNQcmVzc2VkKFwibGVmdFwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBzdGF0aWMgaXNSaWdodFByZXNzZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5HQU1JTkcpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKElucHV0LmlzUHJlc3NlZChcInJpZ2h0XCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHN0YXRpYyBpc0p1bXBKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNKdXN0UHJlc3NlZChcImp1bXBcIikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcblx0ICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgYXR0YWNrIGtleSBpcyBjdXJyZW50bHkgcHJlc3NlZFxuXHQgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBhdHRhY2sga2V5IGlzIHByZXNzZWQsIGZhbHNlIG90aGVyd2lzZVxuXHQgKi9cbiAgICBzdGF0aWMgaXNBdHRhY2tKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNKdXN0UHJlc3NlZChcImF0dGFja1wiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc0Rhc2hKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNKdXN0UHJlc3NlZChcImRhc2hcIikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNTa2lsbEp1c3RQcmVzc2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuR0FNSU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwic2tpbGxcIikpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNJbnZlbnRvcnlKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkdBTUlORykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoSW5wdXQuaXNKdXN0UHJlc3NlZChcImludmVudG9yeVwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc0J1ZmYxSnVzdFByZXNlZCgpOiBib29sZWFue1xuICAgICAgICBpZiAoSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuQlVGRikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBJbnB1dC5pc0p1c3RQcmVzc2VkKFwiYnVmZjFcIik7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzQnVmZjJKdXN0UHJlc2VkKCk6IGJvb2xlYW57XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5CVUZGKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIElucHV0LmlzSnVzdFByZXNzZWQoXCJidWZmMlwiKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNCdWZmM0p1c3RQcmVzZWQoKTogYm9vbGVhbntcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLkJVRkYpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gSW5wdXQuaXNKdXN0UHJlc3NlZChcImJ1ZmYzXCIpO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc1BhdXNlSnVzdFByZXNzZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIGlmIChJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlICE9IEdhbWVTdGF0ZS5HQU1JTkcgJiYgSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZSAhPSBHYW1lU3RhdGUuUEFVU0UpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKElucHV0LmlzSnVzdFByZXNzZWQoXCJwYXVzZVwiKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc05leHRKdXN0UHJlc3NlZCgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKElucHV0V3JhcHBlci5nYW1lU3RhdGUgIT0gR2FtZVN0YXRlLlNUT1JZKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmIChJbnB1dC5pc0p1c3RQcmVzc2VkKFwiYXR0YWNrXCIpIHx8IElucHV0LmlzTW91c2VKdXN0UHJlc3NlZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzTGVmdE1vdXNlSnVzdFByZXNzZWQoKTogYm9vbGVhbntcbiAgICAgICAgcmV0dXJuIElucHV0LmlzTW91c2VKdXN0UHJlc3NlZCgwKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZGlzYWJsZUlucHV0KCkge1xuICAgICAgICBJbnB1dC5kaXNhYmxlSW5wdXQoKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZW5hYmxlSW5wdXQoKSB7XG4gICAgICAgIElucHV0LmVuYWJsZUlucHV0KCk7XG4gICAgfVxuXG4gICAgLy8gRE8gTk9UIGNhbGwgdGhpcyBmdW5jdGlvbiBkaXJlY3RseVxuICAgIHN0YXRpYyBzZXRTdGF0ZShnYW1lU3RhdGU6IEdhbWVTdGF0ZSk6IHZvaWQge1xuICAgICAgICBJbnB1dFdyYXBwZXIuZ2FtZVN0YXRlID0gZ2FtZVN0YXRlO1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRTdGF0ZSgpOiBHYW1lU3RhdGUge1xuICAgICAgICByZXR1cm4gSW5wdXRXcmFwcGVyLmdhbWVTdGF0ZTtcbiAgICB9XG59IiwiZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG9jYWxTdG9yYWdlREIge1xuICAgIHByaXZhdGUga2V5OiBzdHJpbmc7XG4gICAgY29uc3RydWN0b3Ioa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5rZXkgPSBrZXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZCBhIGpzb24gZmlsZSBmcm9tIGEgcGF0aFxuICAgICAqIEBwYXJhbSBKU09ORmlsZVBhdGggVGhlIHBhdGggdG8gdGhlIEpTT04gZmlsZVxuICAgICAqIEBwYXJhbSBjYWxsYmFjayBGdW5jdGlvbiB0byBydW4gYWZ0ZXIgZ2V0dGluZyB0aGUgSlNPTlxuICAgICAqL1xuICAgIHJlYWRKU09OKEpTT05GaWxlUGF0aDogc3RyaW5nLCBjYWxsYmFjazogRnVuY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgbGV0IHhvYmo6IFhNTEh0dHBSZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgIHhvYmoub3ZlcnJpZGVNaW1lVHlwZShcImFwcGxpY2F0aW9uL2pzb25cIik7XG4gICAgICAgIHhvYmoub3BlbignR0VUJywgSlNPTkZpbGVQYXRoLCBmYWxzZSk7XG4gICAgICAgIC8vIHhvYmoub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyAgICAgaWYgKCh4b2JqLnJlYWR5U3RhdGUgPT0gNCkgJiYgKHhvYmouc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgLy8gICAgICAgICBjYWxsYmFjayhKU09OLnBhcnNlKHhvYmoucmVzcG9uc2VUZXh0KSk7XG4gICAgICAgIC8vICAgICB9XG4gICAgICAgIC8vIH07XG4gICAgICAgIHhvYmouc2VuZChudWxsKTtcbiAgICAgICAgY2FsbGJhY2soSlNPTi5wYXJzZSh4b2JqLnJlc3BvbnNlVGV4dCkpO1xuICAgIH1cblxuICAgIGxvYWRKU09OKCk6IG9iamVjdCB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMua2V5KSk7XG4gICAgfVxuXG4gICAgc2F2ZUpTT04odmFsdWU6IG9iamVjdCk6IHZvaWQge1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLmtleSwgSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcbiAgICB9XG5cbn0iLCJpbXBvcnQgeyBUaWxlZExheWVyRGF0YSwgVGlsZWRUaWxlbWFwRGF0YSB9IGZyb20gXCIuLi8uLi9Xb2xmaWUyRC9EYXRhVHlwZXMvVGlsZXNldHMvVGlsZWREYXRhXCI7XG5pbXBvcnQgVmVjMiBmcm9tIFwiLi4vLi4vV29sZmllMkQvRGF0YVR5cGVzL1ZlYzJcIjtcbmltcG9ydCBNYXBUZW1wbGF0ZSwgeyBFbnRyYW5jZSwgUm9vbVRlbXBsYXRlIH0gZnJvbSBcIi4vRGF0YVR5cGVzL01hcFRlbXBsYXRlXCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJhbmRvbU1hcEdlbmVyYXRvciB7XG4gICAgcHJpdmF0ZSB0ZW1wbGF0ZTogTWFwVGVtcGxhdGU7XG4gICAgcHJpdmF0ZSBtaW5YOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBtYXhYOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBtaW5ZOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBtYXhZOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBtYXA6IFRpbGVkVGlsZW1hcERhdGE7XG4gICAgcHJpdmF0ZSByb29tV2l0aExlZnRFbnRyYW5jZTogQXJyYXk8Um9vbVRlbXBsYXRlPjtcbiAgICBwcml2YXRlIHJvb21XaXRoTGVmdEVudHJhbmNlV2VpZ2h0OiBudW1iZXI7XG4gICAgcHJpdmF0ZSByb29tV2l0aFJpZ2h0RW50cmFuY2U6IEFycmF5PFJvb21UZW1wbGF0ZT47XG4gICAgcHJpdmF0ZSByb29tV2l0aFJpZ2h0RW50cmFuY2VXZWlnaHQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJvb21XaXRoVXBFbnRyYW5jZTogQXJyYXk8Um9vbVRlbXBsYXRlPjtcbiAgICBwcml2YXRlIHJvb21XaXRoVXBFbnRyYW5jZVdlaWdodDogbnVtYmVyO1xuICAgIHByaXZhdGUgcm9vbVdpdGhEb3duRW50cmFuY2U6IEFycmF5PFJvb21UZW1wbGF0ZT47XG4gICAgcHJpdmF0ZSByb29tV2l0aERvd25FbnRyYW5jZVdlaWdodDogbnVtYmVyO1xuICAgIHByaXZhdGUgcm9vbXM6IEFycmF5PFJvb20+XG4gICAgcHJpdmF0ZSBnZW46IGFueTtcbiAgICBwcml2YXRlIGhhc0V4aXQ6IGJvb2xlYW47XG4gICAgcHJpdmF0ZSBtaW5Sb29tOiBudW1iZXI7XG4gICAgcHJpdmF0ZSByb29tUGxhY2VkOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBleGl0RmFjaW5nOiBGYWNpbmc7XG4gICAgcHJpdmF0ZSBlbmVtaWVzOiBBcnJheTxFbmVteT47XG4gICAgcHJpdmF0ZSBwbGF5ZXI6IFZlYzI7XG4gICAgcHJpdmF0ZSBzdGFydENoZWNrUG9pbnQ6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgIHByaXZhdGUgZW5kQ2hlY2tQb2ludDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG5cbiAgICBjb25zdHJ1Y3RvcihKU09ORmlsZVBhdGg6IHN0cmluZywgc2VlZDogYW55KSB7XG4gICAgICAgIGxldCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgeGhyLm92ZXJyaWRlTWltZVR5cGUoXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuICAgICAgICB4aHIub3BlbignR0VUJywgSlNPTkZpbGVQYXRoLCBmYWxzZSk7XG4gICAgICAgIHhoci5zZW5kKG51bGwpO1xuICAgICAgICB0aGlzLnRlbXBsYXRlID0gSlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZSA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZSA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZSA9IG5ldyBBcnJheSgpO1xuICAgICAgICB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMubWluWCA9IHRoaXMubWluWSA9IHRoaXMubWF4WCA9IHRoaXMubWF4WSA9XG4gICAgICAgICAgICB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlV2VpZ2h0ID0gdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2VXZWlnaHQgPVxuICAgICAgICAgICAgdGhpcy5yb29tV2l0aFVwRW50cmFuY2VXZWlnaHQgPSB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlV2VpZ2h0ID0gMDtcblxuICAgICAgICB0aGlzLm1hcCA9IG5ldyBUaWxlZFRpbGVtYXBEYXRhKCk7XG4gICAgICAgIHRoaXMucm9vbXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgdGhpcy5lbmVtaWVzID0gbmV3IEFycmF5KCk7XG4gICAgICAgIHRoaXMucGxheWVyID0gbmV3IFZlYzIoKTtcbiAgICAgICAgdGhpcy5zdGFydENoZWNrUG9pbnQgPSBbMCwwLDAsMF07XG4gICAgICAgIHRoaXMuZW5kQ2hlY2tQb2ludCA9IFswLCAwLCAwLCAwXTtcbiAgICAgICAgbGV0IGdlbiA9IHJlcXVpcmUoJ3JhbmRvbS1zZWVkJyk7XG4gICAgICAgIHRoaXMuZ2VuID0gbmV3IGdlbihzZWVkKTtcbiAgICAgICAgdGhpcy5oYXNFeGl0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMubWluUm9vbSA9IHRoaXMudGVtcGxhdGUubWlucm9vbTtcbiAgICAgICAgdGhpcy5yb29tUGxhY2VkID0gMDtcbiAgICAgICAgdGhpcy5leGl0RmFjaW5nID0gdGhpcy5nZXRFbnRyYW5jZUZhY2luZyh0aGlzLnRlbXBsYXRlLmV4aXQuZW50cmFuY2VzWzBdLCB0aGlzLnRlbXBsYXRlLmV4aXQud2lkdGgpO1xuXG5cbiAgICAgICAgZm9yIChsZXQgcm9vbSBvZiB0aGlzLnRlbXBsYXRlLnJvb21zKSB7XG4gICAgICAgICAgICBsZXQgbGVmdCA9IGZhbHNlLCByaWdodCA9IGZhbHNlLCB1cCA9IGZhbHNlLCBkb3duID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGxldCBlbnRyYW5jZSBvZiByb29tLmVudHJhbmNlcykge1xuICAgICAgICAgICAgICAgIGxldCBmYWNpbmcgPSB0aGlzLmdldEVudHJhbmNlRmFjaW5nKGVudHJhbmNlLCByb29tLndpZHRoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGZhY2luZykge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEZhY2luZy5MRUZUOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGYWNpbmcuUklHSFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByaWdodCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGYWNpbmcuVVA6XG4gICAgICAgICAgICAgICAgICAgICAgICB1cCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGYWNpbmcuRE9XTjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvd24gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobGVmdCkge1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhMZWZ0RW50cmFuY2UucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoTGVmdEVudHJhbmNlV2VpZ2h0ICs9IHJvb20ud2VpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aFJpZ2h0RW50cmFuY2UucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZVdlaWdodCArPSByb29tLndlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh1cCkge1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhVcEVudHJhbmNlLnB1c2gocm9vbSk7XG4gICAgICAgICAgICAgICAgdGhpcy5yb29tV2l0aFVwRW50cmFuY2VXZWlnaHQgKz0gcm9vbS53ZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZG93bikge1xuICAgICAgICAgICAgICAgIHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2UucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJvb21XaXRoRG93bkVudHJhbmNlV2VpZ2h0ICs9IHJvb20ud2VpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0TWFwKCk6IFRpbGVkVGlsZW1hcERhdGEge1xuICAgICAgICBsZXQgcm9vbSA9IHRoaXMuY29weVJvb20odGhpcy50ZW1wbGF0ZS5lbnRyYW5jZSwgMCwgMCk7XG4gICAgICAgIGxldCBmYWNpbmcgPSB0aGlzLmdldEVudHJhbmNlRmFjaW5nKHRoaXMudGVtcGxhdGUuZW50cmFuY2UuZW50cmFuY2VzWzBdLCB0aGlzLnRlbXBsYXRlLmVudHJhbmNlLndpZHRoKTtcbiAgICAgICAgbGV0IHBvc2l0aW9uID0gbmV3IFZlYzIodGhpcy50ZW1wbGF0ZS5lbnRyYW5jZS5lbnRyYW5jZXNbMF0ueCwgdGhpcy50ZW1wbGF0ZS5lbnRyYW5jZS5lbnRyYW5jZXNbMF0ueSk7XG4gICAgICAgIC8vIHRoaXMucmVtb3ZlRW50cmFuY2Uocm9vbSwgdGhpcy50ZW1wbGF0ZS5lbnRyYW5jZS5lbnRyYW5jZXNbMF0sIGZhY2luZyk7XG4gICAgICAgIHRoaXMucm9vbXMucHVzaChyb29tKTtcblxuICAgICAgICBcblxuICAgICAgICB0aGlzLnB1dE5leHRSb29tKHBvc2l0aW9uLCB0aGlzLmdldE9wcG9zaXRlRmFjaW5nKGZhY2luZykpO1xuXG4gICAgICAgIGlmICghdGhpcy5oYXNFeGl0KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbCB0byBnZW5lcmF0ZSBhIG1hcCB3aXRoIGV4aXQhXCIpO1xuXG4gICAgICAgIHRoaXMuZmlsbERhdGEoKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJHZW5lcmF0ZWQgbWFwOlwiLCB0aGlzLm1hcCk7XG4gICAgICAgIHJldHVybiB0aGlzLm1hcDtcbiAgICB9XG5cbiAgICBnZXRQbGF5ZXIoKTogVmVjMiB7XG4gICAgICAgIHJldHVybiBuZXcgVmVjMih0aGlzLnBsYXllci54IC0gdGhpcy5taW5YLCB0aGlzLnBsYXllci55IC0gdGhpcy5taW5ZKTtcbiAgICB9XG5cbiAgICBnZXRTdGFydENoZWNrUG9pbnQoKTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0ge1xuICAgICAgICByZXR1cm4gW3RoaXMuc3RhcnRDaGVja1BvaW50WzBdIC0gdGhpcy5taW5YLCB0aGlzLnN0YXJ0Q2hlY2tQb2ludFsxXSAtIHRoaXMubWluWSwgdGhpcy5zdGFydENoZWNrUG9pbnRbMl0sIHRoaXMuc3RhcnRDaGVja1BvaW50WzNdXTtcbiAgICB9XG5cbiAgICBnZXRFbmRDaGVja1BvaW50KCk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcbiAgICAgICAgcmV0dXJuIFt0aGlzLmVuZENoZWNrUG9pbnRbMF0gLSB0aGlzLm1pblgsIHRoaXMuZW5kQ2hlY2tQb2ludFsxXSAtIHRoaXMubWluWSwgdGhpcy5lbmRDaGVja1BvaW50WzJdLCB0aGlzLmVuZENoZWNrUG9pbnRbM11dO1xuICAgIH1cblxuICAgIGdldEVuZW1pZXMoKTogQXJyYXk8RW5lbXk+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5lbWllcztcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1dE5leHRSb29tKHBvc2l0aW9uOiBWZWMyLCBmYWNpbmc6IEZhY2luZyk6IGJvb2xlYW4ge1xuICAgICAgICBzd2l0Y2ggKGZhY2luZykge1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuTEVGVDpcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi54ICs9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5SSUdIVDpcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi54IC09IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5VUDpcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi55ICs9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEZhY2luZy5ET1dOOlxuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnkgLT0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucm9vbVBsYWNlZCA+PSB0aGlzLm1pblJvb20gJiYgZmFjaW5nID09IHRoaXMuZXhpdEZhY2luZyAmJiAhdGhpcy5oYXNFeGl0KSB7XG4gICAgICAgICAgICB0aGlzLnB1dEV4aXRSb29tKHBvc2l0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5leHRSb29tID0gdGhpcy5nZXRSYW5kb21Sb29tKGZhY2luZyk7XG4gICAgICAgIGxldCBuZXh0UG9zaXRpb246IFZlYzIgPSB1bmRlZmluZWQ7XG4gICAgICAgIGxldCB0aGlzRW50cmFuY2U6IEVudHJhbmNlID0gdW5kZWZpbmVkO1xuICAgICAgICBmb3IgKGxldCBlbnRyYW5jZSBvZiBuZXh0Um9vbS5lbnRyYW5jZXMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldEVudHJhbmNlRmFjaW5nKGVudHJhbmNlLCBuZXh0Um9vbS53aWR0aCkgPT0gZmFjaW5nKSB7XG4gICAgICAgICAgICAgICAgbGV0IHRtcFBvc2l0aW9uID0gbmV3IFZlYzIocG9zaXRpb24ueCAtIGVudHJhbmNlLngsIHBvc2l0aW9uLnkgLSBlbnRyYW5jZS55KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1ZhbGlkUm9vbSh0bXBQb3NpdGlvbiwgbmV3IFZlYzIodG1wUG9zaXRpb24ueCArIG5leHRSb29tLndpZHRoIC0gMSwgdG1wUG9zaXRpb24ueSArIG5leHRSb29tLmhlaWdodCAtIDEpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzRW50cmFuY2UgPSBlbnRyYW5jZTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dFBvc2l0aW9uID0gdG1wUG9zaXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpc0VudHJhbmNlKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFzRXhpdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIldyb25nIG9yZGVyIGluIG1hcCB0ZW1wbGF0ZVwiICsgZmFjaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcm9vbSA9IHRoaXMuY29weVJvb20obmV4dFJvb20sIG5leHRQb3NpdGlvbi54LCBuZXh0UG9zaXRpb24ueSk7XG4gICAgICAgIHRoaXMucmVtb3ZlRW50cmFuY2Uocm9vbSwgdGhpc0VudHJhbmNlLCBmYWNpbmcpO1xuICAgICAgICB0aGlzLnJvb21zLnB1c2gocm9vbSk7XG4gICAgICAgIHRoaXMucm9vbVBsYWNlZCArPSAxO1xuICAgICAgICBpZiAodGhpcy5oYXNFeGl0ICYmIHRoaXMuZ2VuLnJhbmRvbSgpIDw9IDAuMykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgZW50cmFuY2Ugb2YgbmV4dFJvb20uZW50cmFuY2VzKSB7XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UgIT0gdGhpc0VudHJhbmNlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGZhY2luZyA9IHRoaXMuZ2V0RW50cmFuY2VGYWNpbmcoZW50cmFuY2UsIG5leHRSb29tLndpZHRoKTtcbiAgICAgICAgICAgICAgICBsZXQgcG9zaXRpb24gPSBuZXcgVmVjMihuZXh0UG9zaXRpb24ueCArIGVudHJhbmNlLngsIG5leHRQb3NpdGlvbi55ICsgZW50cmFuY2UueSk7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wdXROZXh0Um9vbShwb3NpdGlvbiwgdGhpcy5nZXRPcHBvc2l0ZUZhY2luZyhmYWNpbmcpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUVudHJhbmNlKHJvb20sIGVudHJhbmNlLCBmYWNpbmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHB1dEV4aXRSb29tKHBvc2l0aW9uOiBWZWMyKTogdm9pZCB7XG4gICAgICAgIHBvc2l0aW9uID0gbmV3IFZlYzIocG9zaXRpb24ueCAtIHRoaXMudGVtcGxhdGUuZXhpdC5lbnRyYW5jZXNbMF0ueCwgcG9zaXRpb24ueSAtIHRoaXMudGVtcGxhdGUuZXhpdC5lbnRyYW5jZXNbMF0ueSk7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkUm9vbShwb3NpdGlvbiwgbmV3IFZlYzIocG9zaXRpb24ueCArIHRoaXMudGVtcGxhdGUuZXhpdC53aWR0aCAtIDEsIHBvc2l0aW9uLnkgKyB0aGlzLnRlbXBsYXRlLmV4aXQuaGVpZ2h0IC0gMSkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgcHV0IGV4aXQgcm9vbSEhISBQb3NpdGlvbiBpcyBpbnZhbGlkISEhIFBsZWFzZSBjaGVjayBvcmRlciBvZiBlbnRyYW5jZXMgaW4gbWFwIHRlbXBsYXRlLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcm9vbSA9IHRoaXMuY29weVJvb20odGhpcy50ZW1wbGF0ZS5leGl0LCBwb3NpdGlvbi54LCBwb3NpdGlvbi55KTtcbiAgICAgICAgdGhpcy5yb29tcy5wdXNoKHJvb20pO1xuICAgICAgICB0aGlzLmhhc0V4aXQgPSB0cnVlO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVtb3ZlRW50cmFuY2Uocm9vbTogUm9vbSwgZW50cmFuY2U6IEVudHJhbmNlLCBmYWNpbmc6IEZhY2luZyk6IHZvaWQge1xuICAgICAgICBsZXQgd2lkdGggPSByb29tLmJvdHRvbVJpZ2h0LnggLSByb29tLnRvcExlZnQueCArIDE7XG4gICAgICAgIGlmIChmYWNpbmcgPT0gRmFjaW5nLkxFRlQgfHwgZmFjaW5nID09IEZhY2luZy5SSUdIVCkge1xuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGVudHJhbmNlLndpZHRoOyBpbmRleCsrKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkgKyBpbmRleCkgKiB3aWR0aCArIGVudHJhbmNlLnhdID0gMDtcbiAgICAgICAgICAgIGlmIChlbnRyYW5jZS55ID4gMClcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55IC0gMSkgKiB3aWR0aCArIGVudHJhbmNlLnhdID0gZW50cmFuY2UuYWx0X3RpbGVbMF07XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UueSArIGVudHJhbmNlLndpZHRoIDw9IChyb29tLmJvdHRvbVJpZ2h0LnkgLSByb29tLnRvcExlZnQueSkpXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSArIGVudHJhbmNlLndpZHRoKSAqIHdpZHRoICsgZW50cmFuY2UueF0gPSBlbnRyYW5jZS5hbHRfdGlsZVsxXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBlbnRyYW5jZS53aWR0aDsgaW5kZXgrKylcbiAgICAgICAgICAgICAgICByb29tLnRvcExheWVyWyhlbnRyYW5jZS55KSAqIHdpZHRoICsgZW50cmFuY2UueCArIGluZGV4XSA9IDA7XG4gICAgICAgICAgICBpZiAoZW50cmFuY2UueCA+IDApXG4gICAgICAgICAgICAgICAgcm9vbS50b3BMYXllclsoZW50cmFuY2UueSkgKiB3aWR0aCArIGVudHJhbmNlLnggLSAxXSA9IGVudHJhbmNlLmFsdF90aWxlWzBdO1xuICAgICAgICAgICAgaWYgKGVudHJhbmNlLnggKyBlbnRyYW5jZS53aWR0aCA8PSAocm9vbS5ib3R0b21SaWdodC54IC0gcm9vbS50b3BMZWZ0LngpKVxuICAgICAgICAgICAgICAgIHJvb20udG9wTGF5ZXJbKGVudHJhbmNlLnkpICogd2lkdGggKyBlbnRyYW5jZS54ICsgZW50cmFuY2Uud2lkdGhdID0gZW50cmFuY2UuYWx0X3RpbGVbMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbGxEYXRhKCkge1xuICAgICAgICBsZXQgd2lkdGggPSB0aGlzLm1heFggLSB0aGlzLm1pblggKyAxO1xuICAgICAgICBsZXQgaGVpZ2h0ID0gdGhpcy5tYXhZIC0gdGhpcy5taW5ZICsgMTtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzID0gbmV3IEFycmF5KDIpO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0gPSBuZXcgVGlsZWRMYXllckRhdGE7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXSA9IG5ldyBUaWxlZExheWVyRGF0YTtcbiAgICAgICAgdGhpcy5tYXAud2lkdGggPSB0aGlzLm1hcC5sYXllcnNbMF0ud2lkdGggPSB0aGlzLm1hcC5sYXllcnNbMV0ud2lkdGggPSB3aWR0aDtcbiAgICAgICAgdGhpcy5tYXAuaGVpZ2h0ID0gdGhpcy5tYXAubGF5ZXJzWzBdLmhlaWdodCA9IHRoaXMubWFwLmxheWVyc1sxXS5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIHRoaXMubWFwLnRpbGVoZWlnaHQgPSB0aGlzLnRlbXBsYXRlLnRpbGVoZWlnaHQ7XG4gICAgICAgIHRoaXMubWFwLnRpbGV3aWR0aCA9IHRoaXMudGVtcGxhdGUudGlsZXdpZHRoO1xuICAgICAgICB0aGlzLm1hcC5vcmllbnRhdGlvbiA9IFwib3J0aG9nb25hbFwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0ueCA9IHRoaXMubWFwLmxheWVyc1swXS55ID0gdGhpcy5tYXAubGF5ZXJzWzFdLnggPSB0aGlzLm1hcC5sYXllcnNbMV0ueSA9IDA7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5vcGFjaXR5ID0gdGhpcy5tYXAubGF5ZXJzWzFdLm9wYWNpdHkgPSAxO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0udmlzaWJsZSA9IHRoaXMubWFwLmxheWVyc1sxXS52aXNpYmxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tYXAubGF5ZXJzWzBdLnR5cGUgPSB0aGlzLm1hcC5sYXllcnNbMV0udHlwZSA9IFwidGlsZWxheWVyXCI7XG4gICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5uYW1lID0gXCJGbG9vclwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMV0ubmFtZSA9IFwiV2FsbFwiO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0ucHJvcGVydGllcyA9IFt7XG4gICAgICAgICAgICBuYW1lOiBcIkNvbGxpZGFibGVcIixcbiAgICAgICAgICAgIHR5cGU6IFwiYm9vbFwiLFxuICAgICAgICAgICAgdmFsdWU6IGZhbHNlXG4gICAgICAgIH1dXG4gICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5wcm9wZXJ0aWVzID0gW3tcbiAgICAgICAgICAgIG5hbWU6IFwiQ29sbGlkYWJsZVwiLFxuICAgICAgICAgICAgdHlwZTogXCJib29sXCIsXG4gICAgICAgICAgICB2YWx1ZTogdHJ1ZVxuICAgICAgICB9XVxuICAgICAgICB0aGlzLm1hcC50aWxlc2V0cyA9IFt7XG4gICAgICAgICAgICBjb2x1bW5zOiB0aGlzLnRlbXBsYXRlLmNvbHVtbnMsXG4gICAgICAgICAgICB0aWxld2lkdGg6IHRoaXMudGVtcGxhdGUudGlsZXdpZHRoLFxuICAgICAgICAgICAgdGlsZWhlaWdodDogdGhpcy50ZW1wbGF0ZS50aWxlaGVpZ2h0LFxuICAgICAgICAgICAgdGlsZWNvdW50OiB0aGlzLnRlbXBsYXRlLnRpbGVjb3VudCxcbiAgICAgICAgICAgIGZpcnN0Z2lkOiB0aGlzLnRlbXBsYXRlLmZpcnN0Z2lkLFxuICAgICAgICAgICAgaW1hZ2VoZWlnaHQ6IHRoaXMudGVtcGxhdGUuaW1hZ2VoZWlnaHQsXG4gICAgICAgICAgICBpbWFnZXdpZHRoOiB0aGlzLnRlbXBsYXRlLmltYWdld2lkdGgsXG4gICAgICAgICAgICBtYXJnaW46IHRoaXMudGVtcGxhdGUubWFyZ2luLFxuICAgICAgICAgICAgc3BhY2luZzogdGhpcy50ZW1wbGF0ZS5zcGFjaW5nLFxuICAgICAgICAgICAgbmFtZTogdGhpcy50ZW1wbGF0ZS5uYW1lLFxuICAgICAgICAgICAgaW1hZ2U6IHRoaXMudGVtcGxhdGUuaW1hZ2VcbiAgICAgICAgfV1cblxuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMF0uZGF0YSA9IG5ldyBBcnJheSh3aWR0aCAqIGhlaWdodCkuZmlsbCh0aGlzLnRlbXBsYXRlLmJhY2tncm91bmQpO1xuICAgICAgICB0aGlzLm1hcC5sYXllcnNbMV0uZGF0YSA9IG5ldyBBcnJheSh3aWR0aCAqIGhlaWdodCk7XG5cbiAgICAgICAgZm9yIChsZXQgcm9vbSBvZiB0aGlzLnJvb21zKSB7XG4gICAgICAgICAgICBsZXQgcm9vbVdpZHRoID0gcm9vbS5ib3R0b21SaWdodC54IC0gcm9vbS50b3BMZWZ0LnggKyAxO1xuICAgICAgICAgICAgbGV0IHJvb21IZWlnaHQgPSByb29tLmJvdHRvbVJpZ2h0LnkgLSByb29tLnRvcExlZnQueSArIDE7XG4gICAgICAgICAgICByb29tLnRvcExlZnQueCAtPSB0aGlzLm1pblg7XG4gICAgICAgICAgICByb29tLnRvcExlZnQueSAtPSB0aGlzLm1pblk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvb21IZWlnaHQ7IGkrKylcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJvb21XaWR0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWFwLmxheWVyc1swXS5kYXRhWyhyb29tLnRvcExlZnQueSArIGkpICogd2lkdGggKyByb29tLnRvcExlZnQueCArIGpdID0gcm9vbS5ib3R0b21MYXllcltpICogcm9vbVdpZHRoICsgal07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWFwLmxheWVyc1sxXS5kYXRhWyhyb29tLnRvcExlZnQueSArIGkpICogd2lkdGggKyByb29tLnRvcExlZnQueCArIGpdID0gcm9vbS50b3BMYXllcltpICogcm9vbVdpZHRoICsgal07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJvb20uZW5lbWllcylcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBlbmVteSBvZiByb29tLmVuZW1pZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZW5lbXkucG9zaXRpb24ueCArPSByb29tLnRvcExlZnQueDtcbiAgICAgICAgICAgICAgICAgICAgZW5lbXkucG9zaXRpb24ueSArPSByb29tLnRvcExlZnQueTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmVtaWVzLnB1c2goZW5lbXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaXNWYWxpZFJvb20odG9wTGVmdDogVmVjMiwgYm90dG9tUmlnaHQ6IFZlYzIpOiBib29sZWFuIHtcbiAgICAgICAgZm9yIChsZXQgcm9vbSBvZiB0aGlzLnJvb21zKSB7XG4gICAgICAgICAgICBpZiAocm9vbS50b3BMZWZ0LnggPD0gYm90dG9tUmlnaHQueCAmJlxuICAgICAgICAgICAgICAgIHJvb20uYm90dG9tUmlnaHQueCA+PSB0b3BMZWZ0LnggJiZcbiAgICAgICAgICAgICAgICByb29tLnRvcExlZnQueSA8PSBib3R0b21SaWdodC55ICYmXG4gICAgICAgICAgICAgICAgcm9vbS5ib3R0b21SaWdodC55ID49IHRvcExlZnQueSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcIkZvdW5kIGFuIGludmFsaWQgcm9vbSEgVG9wTGVmdDpcIiwgdG9wTGVmdC50b1N0cmluZygpLCBcIkJvdHRvbVJpZ2h0OlwiLCBib3R0b21SaWdodC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRFbnRyYW5jZUZhY2luZyhlbnRyYW5jZTogRW50cmFuY2UsIHdpZHRoOiBudW1iZXIpOiBGYWNpbmcge1xuICAgICAgICBpZiAoZW50cmFuY2UueCA9PT0gMClcbiAgICAgICAgICAgIHJldHVybiBGYWNpbmcuTEVGVDtcbiAgICAgICAgZWxzZSBpZiAoZW50cmFuY2UueCA9PT0gd2lkdGggLSAxKVxuICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5SSUdIVFxuICAgICAgICBlbHNlIGlmIChlbnRyYW5jZS55ID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5VUDtcbiAgICAgICAgcmV0dXJuIEZhY2luZy5ET1dOO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0T3Bwb3NpdGVGYWNpbmcoZmFjaW5nOiBGYWNpbmcpOiBGYWNpbmcge1xuICAgICAgICBzd2l0Y2ggKGZhY2luZykge1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuTEVGVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gRmFjaW5nLlJJR0hUO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuUklHSFQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5MRUZUO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuVVA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhY2luZy5ET1dOO1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuRE9XTjpcbiAgICAgICAgICAgICAgICByZXR1cm4gRmFjaW5nLlVQO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSYW5kb21Sb29tKGZhY2luZzogRmFjaW5nKTogUm9vbVRlbXBsYXRlIHtcbiAgICAgICAgbGV0IGFycmF5ID0gdGhpcy5nZXRSb29tQXJyYXkoZmFjaW5nKSwgd2VpZ2h0ID0gdGhpcy5nZXRSb29tV2VpZ2h0KGZhY2luZyk7XG4gICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuZ2VuKHdlaWdodCk7XG5cbiAgICAgICAgaWYgKHZhbHVlID49IHdlaWdodClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJhbmRvbSBudW1iZXIgXCIgKyB2YWx1ZSArIFwiIGlzIGxhcmdlciB0aGFuIHRvdGFsIHdlaWdodCBcIiArIHdlaWdodCk7XG5cbiAgICAgICAgZm9yIChsZXQgcm9vbSBvZiBhcnJheSkge1xuICAgICAgICAgICAgaWYgKHZhbHVlIDwgcm9vbS53ZWlnaHQpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb207XG4gICAgICAgICAgICB2YWx1ZSAtPSByb29tLndlaWdodDtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBSb29tISBcXG5WYWx1ZTogXCIgKyB2YWx1ZSArIFwiXFxuUm9vbXM6IFwiICsgSlNPTi5zdHJpbmdpZnkoYXJyYXkpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFJvb21BcnJheShmYWNpbmc6IEZhY2luZyk6IEFycmF5PFJvb21UZW1wbGF0ZT4ge1xuICAgICAgICBzd2l0Y2ggKGZhY2luZykge1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuTEVGVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZTtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlJJR0hUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZTtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlVQOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZTtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkRPV046XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFJvb21XZWlnaHQoZmFjaW5nOiBGYWNpbmcpOiBudW1iZXIge1xuICAgICAgICBzd2l0Y2ggKGZhY2luZykge1xuICAgICAgICAgICAgY2FzZSBGYWNpbmcuTEVGVDpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tV2l0aExlZnRFbnRyYW5jZVdlaWdodDtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlJJR0hUOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoUmlnaHRFbnRyYW5jZVdlaWdodDtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLlVQOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21XaXRoVXBFbnRyYW5jZVdlaWdodDtcbiAgICAgICAgICAgIGNhc2UgRmFjaW5nLkRPV046XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucm9vbVdpdGhEb3duRW50cmFuY2VXZWlnaHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNvcHlSb29tKG9sZDogUm9vbVRlbXBsYXRlLCBwb3NYOiBudW1iZXIsIHBvc1k6IG51bWJlcik6IFJvb20ge1xuICAgICAgICBsZXQgcm9vbSA9IG5ldyBSb29tKCk7XG4gICAgICAgIHJvb20udG9wTGVmdCA9IG5ldyBWZWMyKHBvc1gsIHBvc1kpO1xuICAgICAgICByb29tLmJvdHRvbVJpZ2h0ID0gbmV3IFZlYzIocG9zWCArIG9sZC53aWR0aCAtIDEsIHBvc1kgKyBvbGQuaGVpZ2h0IC0gMSk7XG4gICAgICAgIHJvb20udG9wTGF5ZXIgPSBbLi4ub2xkLnRvcExheWVyXTtcbiAgICAgICAgcm9vbS5ib3R0b21MYXllciA9IFsuLi5vbGQuYm90dG9tTGF5ZXJdO1xuICAgICAgICByb29tLmVuZW1pZXMgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgaWYgKG9sZC5zcHJpdGVzKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBzcHJpdGUgb2Ygb2xkLnNwcml0ZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3ByaXRlLnR5cGUgPT09ICdwbGF5ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGxheWVyLnggPSBzcHJpdGUueCArIHBvc1g7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGxheWVyLnkgPSBzcHJpdGUueSArIHBvc1k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5nZW4ucmFuZG9tKCkgPD0gc3ByaXRlLnBvc3NpYmlsaXR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdG1wID0gbmV3IEVuZW15KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0bXAudHlwZSA9IHNwcml0ZS50eXBlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdG1wLnBvc2l0aW9uID0gbmV3IFZlYzIoc3ByaXRlLngsIHNwcml0ZS55KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb20uZW5lbWllcy5wdXNoKHRtcCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZC5zdGFydENoZWNrUG9pbnQpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRDaGVja1BvaW50ID0gWy4uLm9sZC5zdGFydENoZWNrUG9pbnRdO1xuICAgICAgICAgICAgdGhpcy5zdGFydENoZWNrUG9pbnRbMF0gKz0gcG9zWDtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRDaGVja1BvaW50WzFdICs9IHBvc1k7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZC5lbmRDaGVja1BvaW50KSB7XG4gICAgICAgICAgICB0aGlzLmVuZENoZWNrUG9pbnQgPSBbLi4ub2xkLmVuZENoZWNrUG9pbnRdO1xuICAgICAgICAgICAgdGhpcy5lbmRDaGVja1BvaW50WzBdICs9IHBvc1g7XG4gICAgICAgICAgICB0aGlzLmVuZENoZWNrUG9pbnRbMV0gKz0gcG9zWTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocG9zWCA8IHRoaXMubWluWClcbiAgICAgICAgICAgIHRoaXMubWluWCA9IHBvc1g7XG4gICAgICAgIGlmIChwb3NZIDwgdGhpcy5taW5ZKVxuICAgICAgICAgICAgdGhpcy5taW5ZID0gcG9zWTtcbiAgICAgICAgaWYgKHBvc1ggKyBvbGQud2lkdGggLSAxID4gdGhpcy5tYXhYKVxuICAgICAgICAgICAgdGhpcy5tYXhYID0gcG9zWCArIG9sZC53aWR0aCAtIDE7XG4gICAgICAgIGlmIChwb3NZICsgb2xkLmhlaWdodCAtIDEgPiB0aGlzLm1heFkpXG4gICAgICAgICAgICB0aGlzLm1heFkgPSBwb3NZICsgb2xkLmhlaWdodCAtIDE7XG4gICAgICAgIHJldHVybiByb29tO1xuICAgIH1cbn1cblxuY2xhc3MgUm9vbSB7XG4gICAgdG9wTGVmdDogVmVjMjtcbiAgICBib3R0b21SaWdodDogVmVjMjtcbiAgICB0b3BMYXllcjogQXJyYXk8bnVtYmVyPjtcbiAgICBib3R0b21MYXllcjogQXJyYXk8bnVtYmVyPjtcbiAgICBlbmVtaWVzOiBBcnJheTxFbmVteT5cbn1cblxuZXhwb3J0IGNsYXNzIEVuZW15IHtcbiAgICB0eXBlOiBTdHJpbmc7XG4gICAgcG9zaXRpb246IFZlYzI7XG59XG5cbmVudW0gRmFjaW5nIHtcbiAgICBMRUZUID0gXCJsZWZ0XCIsXG4gICAgUklHSFQgPSBcInJpZ2h0XCIsXG4gICAgVVAgPSBcInVwXCIsXG4gICAgRE9XTiA9IFwiZG93blwiXG59IiwiaW1wb3J0IFNhdmUgZnJvbSBcIi4vRGF0YVR5cGVzL1NhdmVcIjtcbmltcG9ydCBMb2NhbFN0b3JhZ2VEQiBmcm9tIFwiLi9Mb2NhbFN0b3JhZ2VEQlwiO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTYXZlTWFuYWdlciB7XG4gICAgcHJpdmF0ZSBzdGF0aWMgc2F2ZTogU2F2ZTtcbiAgICBwcml2YXRlIGRiOiBMb2NhbFN0b3JhZ2VEQjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmRiID0gbmV3IExvY2FsU3RvcmFnZURCKFwic2F2ZVwiKTtcbiAgICAgICAgdGhpcy5sb2FkU2F2ZSgpO1xuXG4gICAgICAgIGlmICghU2F2ZU1hbmFnZXIuc2F2ZSlcbiAgICAgICAgICAgIHRoaXMuaW5pdFNhdmUoKTtcbiAgICB9XG5cbiAgICBnZXRMZXZlbCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gU2F2ZU1hbmFnZXIuc2F2ZS5sZXZlbDtcbiAgICB9XG5cbiAgICBzZXRMZXZlbChsZXZlbDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIFNhdmVNYW5hZ2VyLnNhdmUubGV2ZWwgPSBsZXZlbDtcbiAgICAgICAgdGhpcy5zYXZlU2F2ZSgpO1xuICAgIH1cblxuICAgIGdldE5hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIFNhdmVNYW5hZ2VyLnNhdmUubmFtZTtcbiAgICB9XG5cbiAgICBzZXROYW1lKG5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBTYXZlTWFuYWdlci5zYXZlLm5hbWUgPSBuYW1lO1xuICAgICAgICB0aGlzLnNhdmVTYXZlKCk7XG4gICAgfVxuXG4gICAgLy8gVE9ET3NcbiAgICAvLyBhZGQgbW9yZSBmdW5jdGlvbnMgaWYgbmVlZGVkXG5cblxuICAgIHJlc2V0U2F2ZShjYWxsYmFjaz86IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdFNhdmUoKTtcbiAgICAgICAgY2FsbGJhY2soU2F2ZU1hbmFnZXIuc2F2ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBsb2FkU2F2ZSgpOiB2b2lkIHtcbiAgICAgICAgU2F2ZU1hbmFnZXIuc2F2ZSA9IDxTYXZlPnRoaXMuZGIubG9hZEpTT04oKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNhdmVTYXZlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRiLnNhdmVKU09OKFNhdmVNYW5hZ2VyLnNhdmUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFNhdmUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGIucmVhZEpTT04oXCJzaGF0dGVyZWRfc3dvcmRfYXNzZXRzL2pzb25zL3NhbXBsZXNhdmUuanNvblwiLCAoc2F2ZTogb2JqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXNhdmUpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbCB0byBsb2FkIHNhdmUgZmlsZVwiKTtcbiAgICAgICAgICAgIFNhdmVNYW5hZ2VyLnNhdmUgPSA8U2F2ZT5zYXZlO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJbml0aWFsaXppbmcgTG9jYWwgU3RvcmFnZShzYXZlKTogXCIsIFNhdmVNYW5hZ2VyLnNhdmUpO1xuICAgICAgICAgICAgdGhpcy5zYXZlU2F2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG59IiwiZXhwb3J0IGVudW0gUGxheWVyX0V2ZW50cyB7XG4gICAgUExBWUVSX01PVkUgPSBcIlBsYXllck1vdmVcIixcbiAgICBQTEFZRVJfSlVNUCA9IFwiUGxheWVySnVtcFwiLFxuICAgIFBMQVlFUl9BVFRBQ0sgPSBcIlBsYXllckF0dGFja1wiLFxuICAgIFBMQVlFUl9EQVNIID0gXCJQbGF5ZXJEYXNoXCIsXG4gICAgUExBWUVSX0hFQUwgPSBcIlBsYXllckhlYWxcIixcbiAgICBMRVZFTF9TVEFSVCA9IFwiTGV2ZWxTdGFydFwiLFxuICAgIExFVkVMX0VORCA9IFwiTGV2ZWxFbmRcIixcbiAgICBQTEFZRVJfS0lMTEVEID0gXCJQbGF5ZXJLaWxsZWRcIixcbiAgICBFTkVNWV9LSUxMRUQgPSBcIkVuZW15S2lsbGVkXCIsXG4gICAgUExBWUVSX0hJVF9FTkVNWSA9IFwiUGxheWVySGl0RW5lbXlcIixcbiAgICBCT1NTX0tJTExFRCA9IFwiQm9zc0tpbGxlZFwiLFxuICAgIEdJVkVfUkVHVUxBUl9CVUZGID0gXCJHaXZlUmVndWxhckJ1ZmZcIixcbiAgICBHSVZFX1NQRUNJQUxfQlVGRiA9IFwiR2l2ZVNwZWNpYWxCdWZmXCIsXG4gICAgUExBWUVSX0NPTExJREUgPSBcIlBsYXllckNvbGxpZGVcIlxufVxuZXhwb3J0IGVudW0gRGFtYWdlX1R5cGUge1xuICAgIE5PUk1BTF9EQU1BR0UgPSBcIk5vcm1hbERhbWFnZVwiLFxuICAgIEVOVklST05NRU5UX0RBTUFHRSA9IFwiRW52aXJvbm1lbnREYW1hZ2VcIixcbiAgICBET1RfREFNQUdFID0gXCJET1REYW1hZ2VcIixcbn1cblxuZXhwb3J0IGVudW0gU3RhdHVzZXMge1xuICAgIElOX1JBTkdFID0gXCJJTl9SQU5HRVwiLFxuICAgIExPV19IRUFMVEggPSBcIkxPV19IRUFMVEhcIixcbiAgICBDQU5fUkVUUkVBVCA9IFwiQ0FOX1JFVFJFQVRcIixcbiAgICBSRUFDSEVEX0dPQUwgPSBcIkdPQUxcIixcbiAgICBDQU5fQkVSU0VSSyA9IFwiQ0FOX0JFUlNFUktcIlxufVxuXG5leHBvcnQgZW51bSBHYW1lU3RhdGUge1xuICAgIEdBTUlORyA9IFwiZ2FtaW5nXCIsXG4gICAgU1RPUlkgPSBcInN0b3J5XCIsXG4gICAgQlVGRiA9IFwiYnVmZlwiLFxuICAgIFBBVVNFID0gXCJwYXVzZVwiXG59Il19 diff --git a/public/shattered_sword_assets2/data/weaponData.json b/public/shattered_sword_assets/data/weaponData.json similarity index 91% rename from public/shattered_sword_assets2/data/weaponData.json rename to public/shattered_sword_assets/data/weaponData.json index f66b7fd..4861da6 100644 --- a/public/shattered_sword_assets2/data/weaponData.json +++ b/public/shattered_sword_assets/data/weaponData.json @@ -8,7 +8,7 @@ "animationSprite": "slice", "spriteKey": "knife", "damage": 50, - "cooldown": 3, + "cooldown": 500, "useVolume": 0 } ] diff --git a/public/shattered_sword_assets2/fonts/PixelSimple.ttf b/public/shattered_sword_assets/fonts/PixelSimple.ttf similarity index 100% rename from public/shattered_sword_assets2/fonts/PixelSimple.ttf rename to public/shattered_sword_assets/fonts/PixelSimple.ttf diff --git a/public/shattered_sword_assets/images/black.png b/public/shattered_sword_assets/images/black.png new file mode 100644 index 0000000..1aa90e8 Binary files /dev/null and b/public/shattered_sword_assets/images/black.png differ diff --git a/public/shattered_sword_assets/images/bleeding.png b/public/shattered_sword_assets/images/bleeding.png new file mode 100644 index 0000000..da46bad Binary files /dev/null and b/public/shattered_sword_assets/images/bleeding.png differ diff --git a/public/shattered_sword_assets/images/brown.png b/public/shattered_sword_assets/images/brown.png new file mode 100644 index 0000000..d926359 Binary files /dev/null and b/public/shattered_sword_assets/images/brown.png differ diff --git a/public/shattered_sword_assets/images/burning.png b/public/shattered_sword_assets/images/burning.png new file mode 100644 index 0000000..fba9e6f Binary files /dev/null and b/public/shattered_sword_assets/images/burning.png differ diff --git a/public/shattered_sword_assets/images/controls.png b/public/shattered_sword_assets/images/controls.png new file mode 100644 index 0000000..c9fc0cf Binary files /dev/null and b/public/shattered_sword_assets/images/controls.png differ diff --git a/public/shattered_sword_assets/images/guide1.png b/public/shattered_sword_assets/images/guide1.png new file mode 100644 index 0000000..66732bd Binary files /dev/null and b/public/shattered_sword_assets/images/guide1.png differ diff --git a/public/shattered_sword_assets/images/guide2.png b/public/shattered_sword_assets/images/guide2.png new file mode 100644 index 0000000..971ddc9 Binary files /dev/null and b/public/shattered_sword_assets/images/guide2.png differ diff --git a/public/shattered_sword_assets/images/guide3.png b/public/shattered_sword_assets/images/guide3.png new file mode 100644 index 0000000..a5fc641 Binary files /dev/null and b/public/shattered_sword_assets/images/guide3.png differ diff --git a/public/shattered_sword_assets/images/guide4.png b/public/shattered_sword_assets/images/guide4.png new file mode 100644 index 0000000..742a9f4 Binary files /dev/null and b/public/shattered_sword_assets/images/guide4.png differ diff --git a/public/shattered_sword_assets2/images/Logo.png b/public/shattered_sword_assets/images/logo.png similarity index 100% rename from public/shattered_sword_assets2/images/Logo.png rename to public/shattered_sword_assets/images/logo.png diff --git a/public/shattered_sword_assets/images/poisoning.png b/public/shattered_sword_assets/images/poisoning.png new file mode 100644 index 0000000..30f8ed2 Binary files /dev/null and b/public/shattered_sword_assets/images/poisoning.png differ diff --git a/public/shattered_sword_assets2/images/story1.png b/public/shattered_sword_assets/images/story1.png similarity index 100% rename from public/shattered_sword_assets2/images/story1.png rename to public/shattered_sword_assets/images/story1.png diff --git a/public/shattered_sword_assets2/images/story2.png b/public/shattered_sword_assets/images/story2.png similarity index 100% rename from public/shattered_sword_assets2/images/story2.png rename to public/shattered_sword_assets/images/story2.png diff --git a/public/shattered_sword_assets2/images/story3.png b/public/shattered_sword_assets/images/story3.png similarity index 100% rename from public/shattered_sword_assets2/images/story3.png rename to public/shattered_sword_assets/images/story3.png diff --git a/public/shattered_sword_assets2/images/story4.png b/public/shattered_sword_assets/images/story4.png similarity index 100% rename from public/shattered_sword_assets2/images/story4.png rename to public/shattered_sword_assets/images/story4.png diff --git a/public/shattered_sword_assets2/jsons/forest_template.json b/public/shattered_sword_assets/jsons/forest_template.json similarity index 78% rename from public/shattered_sword_assets2/jsons/forest_template.json rename to public/shattered_sword_assets/jsons/forest_template.json index 11e2f91..44edb61 100644 --- a/public/shattered_sword_assets2/jsons/forest_template.json +++ b/public/shattered_sword_assets/jsons/forest_template.json @@ -15,28 +15,57 @@ "height": 30, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 410, 410, 410, 410, 410, 410, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 70, 70, 70, 70, 70, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 478, 478, 478, 478, 478, 478, 478, 478, 478, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 7, + "y": 19 + }, + { + "x": 18, + "y": 17 + } + ], "entrances": [ { "x": 29, "y": 17, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] } - ] + ], + "sprites": [ + { + "type": "player", + "x": 5, + "y": 19 + } + ], + "startCheckPoint": [15, 15, 15, 15] }, "exit": { "width": 30, "height": 30, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 376, 377, 0, 378, 0, 378, 0, 412, 0, 375, 410, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 412, 0, 0, 72, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 376, 377, 0, 0, 344, 0, 0, 72, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 412, 0, 412, 0, 72, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 341, 376, 377, 0, 344, 0, 344, 0, 344, 0, 0, 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 478, 478, 478, 479, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 10, + "y": 18 + }, + { + "x": 20, + "y": 16 + } + ], "entrances": [ { "x": 0, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] } - ] + ], + "endCheckPoint": [20, 15, 15, 15] }, "rooms": [ { @@ -44,19 +73,67 @@ "height": 30, "weight": 2, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 411, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 648, 0, 0, 0, 0, 0, 137, 138, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 647, 0, 0, 478, 478, 478, 478, 478, 478, 479, 0, 0, 137, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 477, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 171, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 411, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 478, 478, 478, 478, 478, 478, 479, 0, 0, 137, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 0, 477, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 3, + "y": 18 + }, + { + "x": 26, + "y": 18 + } + ], "entrances": [ { "x": 0, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] }, { "x": 29, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] + } + ], + "sprites": [ + { + "type": "black_pudding", + "x": 1, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 12, + "y": 12, + "possibility": 1 + }, + { + "type": "Snake", + "x": 18, + "y": 15, + "possibility": 1 + }, + { + "type": "Snake", + "x": 14, + "y": 16, + "possibility": 1 + }, + { + "type": "Snake", + "x": 24, + "y": 17, + "possibility": 1 + }, + { + "type": "Snake", + "x": 6, + "y": 17, + "possibility": 1 } ] }, @@ -65,19 +142,79 @@ "height": 30, "weight": 2, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 70, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 104, 104, 104, 104, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 409, 410, 410, 410, 410, 411, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 69, 70, 70, 70, 70, 71, 0, 477, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 103, 104, 104, 104, 104, 105, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 171, 172, 172, 172, 172, 173, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 70, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 104, 104, 104, 104, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 409, 410, 410, 410, 410, 411, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 69, 70, 70, 70, 70, 71, 0, 477, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 103, 104, 104, 104, 104, 105, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 173, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 16, + "y": 18 + }, + { + "x": 28, + "y": 18 + } + ], "entrances": [ { "x": 0, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] }, { "x": 29, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] + } + ], + "sprites": [ + { + "type": "black_pudding", + "x": 1, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 5, + "y": 14, + "possibility": 1 + }, + { + "type": "Snake", + "x": 14, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 11, + "y": 12, + "possibility": 1 + }, + { + "type": "Snake", + "x": 18, + "y": 12, + "possibility": 1 + }, + { + "type": "Snake", + "x": 23, + "y": 15, + "possibility": 1 + }, + { + "type": "Snake", + "x": 16, + "y": 16, + "possibility": 1 + }, + { + "type": "Snake", + "x": 27, + "y": 16, + "possibility": 1 } ] }, @@ -86,20 +223,73 @@ "height": 30, "weight": 2, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 308, 308, 308, 308, 308, 308, 309, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 307, 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 0, 0, 0, 477, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 308, 308, 308, 308, 308, 308, 309, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 307, 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 478, 479, 0, 0, 477, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 0, 0, 0, 477, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 0, 0, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 12, + "y": 12 + }, + { + "x": 11, + "y": 16 + }, + { + "x": 25, + "y": 16 + } + ], "entrances": [ { "x": 0, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] }, { "x": 29, "y": 14, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] } + ], + "sprites": [ + { + "type": "black_pudding", + "x": 1, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 5, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 11, + "y": 12, + "possibility": 1 + }, + { + "type": "Snake", + "x": 12, + "y": 9, + "possibility": 1 + }, + { + "type": "Snake", + "x": 15, + "y": 15, + "possibility": 1 + }, + { + "type": "Snake", + "x": 25, + "y": 14, + "possibility": 1 + } + ] }, { @@ -107,19 +297,67 @@ "height": 30, "weight": 2, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 410, 410, 410, 410, 410, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 70, 70, 70, 70, 70, 71, 0, 0, 0, 649, 0, 0, 409, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 342, 342, 342, 342, 342, 342, 342, 70, 70, 410, 410, 410, 410, 410, 410, 70, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 342, 342, 342, 342, 342, 342, 342, 343, 0, 0, 0, 0, 0, 0, 0, 443, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 341, 342, 343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 138, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 477, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 444, 444, 444, 444, 444, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 409, 410, 410, 410, 410, 410, 410, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 70, 70, 70, 70, 70, 71, 0, 0, 0, 0, 0, 0, 409, 410, 411, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 342, 342, 342, 342, 342, 342, 342, 70, 70, 410, 410, 410, 410, 410, 410, 70, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 70, 342, 342, 342, 342, 342, 342, 342, 343, 0, 0, 0, 0, 0, 0, 0, 443, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 341, 342, 343, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 0, 0, 0, 0, 0, 0, 0, 0, 443, 444, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 478, 138, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 477, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 444, 444, 444, 444, 444, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 13, + "y": 11 + }, + { + "x": 19, + "y": 13 + } + ], "entrances": [ { "x": 0, "y": 16, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] }, { "x": 29, "y": 13, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] + } + ], + "sprites": [ + { + "type": "black_pudding", + "x": 1, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 9, + "y": 10, + "possibility": 1 + }, + { + "type": "black_pudding", + "x": 9, + "y": 5, + "possibility": 1 + }, + { + "type": "black_pudding", + "x": 15, + "y": 18, + "possibility": 1 + }, + { + "type": "black_pudding", + "x": 23, + "y": 16, + "possibility": 1 + }, + { + "type": "black_pudding", + "x": 27, + "y": 14, + "possibility": 1 } ] }, @@ -128,19 +366,63 @@ "height": 30, "weight": 2, "bottomLayer": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 338, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 335, 404, 371, 372, 407, 408, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 322, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 390, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 321, 390, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 355, 390, 493, 494, 495, 496, 497, 498, 499, 500, 501, 468, 503, 504, 471, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 521, 522, 523, 524, 389, 356, 527, 528, 529, 530, 531, 532, 533, 534, 535, 468, 537, 538, 471, 540, 541, 542, 543, 544, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 389, 390, 459, 460, 461, 462, 531, 464, 465, 466, 467, 468, 469, 470, 505, 472, 473, 474, 475, 476, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 321, 322, 323, 494, 495, 496, 531, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 515, 516, 517, 518, 519, 452, 453, 522, 523, 524, 355, 356, 357, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 549, 550, 551, 552, 553, 452, 385, 556, 557, 558, 389, 390, 391, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 481, 584, 585, 586, 587, 418, 419, 590, 591, 592, 423, 424, 425, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 481, 618, 619, 620, 621, 452, 487, 488, 489, 626, 457, 458, 459, 630, 631, 632, 565, 568, 635, 636, 637, 638, 639, 606, 641, 642, 643, 644, 645, 612, 481, 652, 653, 654, 655, 486, 487, 488, 489, 660, 491, 492, 493, 664, 665, 666, 565, 568, 606, 670, 671, 672, 568, 606, 675, 574, 677, 678, 679, 612, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 599, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 612, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 633, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 633, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680], - "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 308, 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 650, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 479, 0, 477, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 138, 0, 137, 138, 138, 138, 138, 138, 478, 478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 137, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 138, 138, 138, 173, 0, 171, 138, 138, 138, 138, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 376, 376, 376, 376, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 307, 308, 308, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 479, 0, 0, 477, 478, 478, 478, 478, 479, 0, 0, 0, 0, 0, 0, 307, 309, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 138, 138, 0, 0, 137, 138, 138, 138, 138, 138, 478, 478, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 478, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 0, 0, 0, 0, 0, 0, 0, 0, 477, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 478, 478, 478, 478, 478, 478, 478, 478, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 0, 0, 137, 138, 138, 138, 138, 138, 138, 138, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 138, 138, 173, 0, 0, 171, 138, 138, 138, 138, 172, 172, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "objectLayer": [ + { + "x": 25, + "y": 15 + } + ], "entrances": [ { "x": 0, "y": 17, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] }, { "x": 29, "y": 14, "width": 3, - "alt_tile": [477, 479] + "alt_tile": [0, 478] + } + ], + "sprites": [ + { + "type": "black_pudding", + "x": 1, + "y": 10, + "possibility": 1 + }, + { + "type": "Snake", + "x": 7, + "y": 13, + "possibility": 1 + }, + { + "type": "Snake", + "x": 13, + "y": 12, + "possibility": 1 + }, + { + "type": "Snake", + "x": 18, + "y": 14, + "possibility": 1 + }, + { + "type": "Snake", + "x": 13, + "y": 16, + "possibility": 1 + }, + { + "type": "Snake", + "x": 23, + "y": 13, + "possibility": 1 } ] } diff --git a/public/shattered_sword_assets/jsons/greatwall_template.json b/public/shattered_sword_assets/jsons/greatwall_template.json new file mode 100644 index 0000000..e0e12ce --- /dev/null +++ b/public/shattered_sword_assets/jsons/greatwall_template.json @@ -0,0 +1,275 @@ +{ + "columns":3, + "tileheight":16, + "tilewidth":16, + "tilecount":33, + "firstgid":1, + "imageheight":176, + "imagewidth":48, + "margin":0, + "spacing":0, + "name":"greatwall_tileset", + "image":"shattered_sword_assets/tilemaps/greatwall_tileset.png", + "background": 16, + "minroom": 10, + "entrance": { + "width": 30, + "height": 20, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 13, 15, 0, 0, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 5, 5, 17, 18, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], + "entrances": [ + { + "x": 29, + "y": 9, + "width": 3, + "alt_tile": [0, 5] + } + ], + "sprites": [ + { + "type": "player", + "x": 5, + "y": 11 + } + ] + + }, + "exit": { + "width": 33, + "height": 20, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 4, 0, 4, 0, 4, 0, 4, 4, 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 9, 0, 0, 4, 0, 0, 4, 0, 0, 4, 0, 0, 0, 7, 8, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 4, 0, 4, 0, 4, 0, 0, 4, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 21, 5, 19, 21, 5, 19, 21, 5, 0, 0, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 5, 22, 24, 5, 22, 24, 5, 22, 24, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 27, 5, 25, 27, 5, 25, 27, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + "objectLayer": [ + { + "x": 22, + "y": 12 + } + ], + "entrances": [ + { + "x": 0, + "y": 11, + "width": 3, + "alt_tile": [0, 5] + } + ] + }, + "rooms": [ + { + "width": 40, + "height": 20, + "weight": 2, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 29, 5, 5, 29, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 29, 5, 5, 5, 5, 5, 5, 5, 5, 29, 29, 30, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 11, 12, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 11, 12, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 0, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + "objectLayer": [ + { + "x": 9, + "y": 12 + }, + { + "x": 21, + "y": 12 + } + ], + "entrances": [ + { + "x": 39, + "y": 9, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 0, + "y": 10, + "width": 3, + "alt_tile": [0, 5] + } + ] + }, + { + "width": 30, + "height": 20, + "weight": 2, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 6, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 28, 29, 30, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 4, 5, 5, 5, 6, 0, 0, 28, 29, 29, 19, 20, 21, 29, 29, 29, 19, 20, 21, 29, 29, 29, 19, 20, 21, 29, 29, 30, 0, 0, 4, 5, 32, 32, 33, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 31, 32, 5, 5, 6, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 8, 5, 5, 5, 5, 0, 0, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 0, 0, 8, 5, 5, 5, 5, 0, 0, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 0, 0, 8, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 8, 5], + "entrances": [ + { + "x": 29, + "y": 10, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 0, + "y": 10, + "width": 3, + "alt_tile": [0, 5] + } + ] + }, + { + "width": 66, + "height": 30, + "weight": 2, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 31, 32, 33, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 31, 32, 33, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 4, 5, 5, 28, 29, 29, 29, 29, 30, 5, 5, 5, 28, 29, 29, 29, 29, 30, 5, 5, 6, 28, 29, 30, 0, 0, 0, 0, 0, 0, 28, 29, 30, 4, 5, 5, 28, 29, 29, 29, 29, 30, 5, 5, 5, 28, 29, 29, 29, 29, 30, 5, 5, 6, 28, 29, 30, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 19, 20, 21, 5, 5, 5, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 22, 23, 24, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + "objectLayer": [ + { + "x": 13, + "y": 17 + }, + { + "x": 49, + "y": 17 + }, + { + "x": 63, + "y": 17 + } + ], + "entrances": [ + { + "x": 65, + "y": 9, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 31, + "y": 19, + "width": 4, + "alt_tile": [5, 5] + }, + { + "x": 65, + "y": 15, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 0, + "y": 15, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 0, + "y": 9, + "width": 3, + "alt_tile": [0, 5] + } + ] + }, + { + "width": 30, + "height": 20, + "weight": 1, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 6, 4, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 6, 4, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 6, 4, 5, 5, 5, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 0, 0, 0, 0, 13, 14, 14, 14, 14, 15, 6, 4, 19, 20, 21, 19, 20, 21, 19, 20, 21, 19, 20, 21, 19, 20, 21, 19, 20, 21, 0, 0, 0, 0, 19, 20, 21, 19, 20, 21, 6, 4, 22, 23, 24, 22, 23, 24, 22, 23, 24, 22, 23, 24, 22, 23, 24, 22, 23, 24, 0, 0, 0, 0, 22, 23, 24, 22, 23, 24, 6, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8], + "objectLayer": [ + { + "x": 4, + "y": 5 + }, + { + "x": 3, + "y": 15 + }, + { + "x": 16, + "y": 15 + } + ], + "entrances": [ + { + "x": 19, + "y": 19, + "width": 4, + "alt_tile": [5, 5] + }, + { + "x": 19, + "y": 0, + "width": 4, + "alt_tile": [5, 5] + } + ] + }, + { + "width": 30, + "height": 30, + "weight": 1, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 1, 1, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 6, 4, 0, 0, 0, 5, 5, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 11, 12, 5, 11, 12, 5, 11, 12, 5, 11, 12, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 13, 14, 15, 0, 0, 0, 0, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5, 6, 0, 0, 0, 0, 4, 5, 6, 0, 0, 6, 4, 4, 5, 6, 0, 0, 0, 0, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 8, 9, 0, 0, 0, 0, 4, 5, 6, 0, 0, 6, 4, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 19, 20, 21, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 22, 23, 24, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 0, 6, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 6, 4, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 22, 23, 24, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, 5, 6, 0, 0, 0, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 6, 4, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8], + "objectLayer": [ + { + "x": 27, + "y": 4 + }, + { + "x": 18, + "y": 12 + }, + { + "x": 26, + "y": 18 + }, + { + "x": 16, + "y": 28 + } + ], + "entrances": [ + { + "x": 20, + "y": 29, + "width": 4, + "alt_tile": [5, 5] + }, + { + "x": 20, + "y": 0, + "width": 4, + "alt_tile": [5, 5] + } + ] + }, + { + "width": 30, + "height": 20, + "weight": 2, + "bottomLayer": [16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + "topLayer": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + "objectLayer": [ + { + "x": 17, + "y": 8 + }, + { + "x": 28, + "y": 17 + } + ], + "entrances": [ + { + "x": 29, + "y": 15, + "width": 3, + "alt_tile": [0, 5] + }, + { + "x": 13, + "y": 19, + "width": 4, + "alt_tile": [5, 5] + }, + { + "x": 0, + "y": 15, + "width": 3, + "alt_tile": [0, 5] + } + ] + } + ] + } \ No newline at end of file diff --git a/public/shattered_sword_assets/jsons/level1story.json b/public/shattered_sword_assets/jsons/level1story.json new file mode 100644 index 0000000..fd1ddbf --- /dev/null +++ b/public/shattered_sword_assets/jsons/level1story.json @@ -0,0 +1,102 @@ +{ + "texts": [ + { + "speaker": "", + "content": "Press A/LEFT to go LEFT and D/RIGHT to go right", + "actions": [ + { + "type": "loadSprite", + "key": "rightleft", + "path": "shattered_sword_assets/images/guide1.png", + "positon": [ + 300, + 150 + ], + "scale": [ + 2, + 2 + ] + } + ] + }, + { + "speaker": "", + "content": "Press Z or space to jump, double-click to double-jump", + "actions": [ + { + "type": "hideSprite", + "key": "rightleft" + }, + { + "type": "loadSprite", + "key": "jump", + "path": "shattered_sword_assets/images/guide2.png", + "positon": [ + 300, + 150 + ], + "scale": [ + 2, + 2 + ] + } + ] + }, + { + "speaker": "", + "content": "Press X or J to attack", + "actions": [ + { + "type": "hideSprite", + "key": "jump" + }, + { + "type": "loadSprite", + "key": "attack", + "path": "shattered_sword_assets/images/guide3.png", + "positon": [ + 300, + 150 + ], + "scale": [ + 2, + 2 + ] + } + ] + }, + { + "speaker": "", + "content": "Press C or K to dash", + "actions": [ + { + "type": "hideSprite", + "key": "attack" + }, + { + "type": "loadSprite", + "key": "dash", + "path": "shattered_sword_assets/images/guide4.png", + "positon": [ + 300, + 150 + ], + "scale": [ + 2, + 2 + ] + } + ] + }, + { + "speaker": "", + "content": "", + "actions": [ + { + "type": "hideSprite", + "key": "dash" + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/jsons/porcelain_template.json b/public/shattered_sword_assets/jsons/porcelain_template.json new file mode 100644 index 0000000..00252e3 --- /dev/null +++ b/public/shattered_sword_assets/jsons/porcelain_template.json @@ -0,0 +1,310 @@ +{ + "columns":5, + "tileheight":16, + "tilewidth":16, + "tilecount":15, + "firstgid":1, + "imageheight":48, + "imagewidth":80, + "margin":0, + "spacing":0, + "name":"porcelain_tileset", + "image":"shattered_sword_assets/tilemaps/porcelain_tileset.png", + "background": 4, + "minroom": 6, + "entrance": { + "width": 30, + "height": 16, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [0, 0, 0, 0, 0, 0, 13, 6, 3, 2, 13, 3, 6, 11, 2, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 8, 12, 1, 3, 13, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 12, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 3, 7, 2, 6, 3, 8, 12, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 13, 8, 3, 13, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 11, 2, 12, 0, 0, 0, 0, 13, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 6, 1, 11, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 3, 13, 12, 0, 0, 0, 0, 0, 0, 12, 3, 2, 8, 12, 8, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 8, 11, 12, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 0, 0, 0, 0, 13, 12, 7, 0, 0, 0, 0, 0, 0, 7, 1, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 13, 2, 0, 0, 0, 0, 0, 1, 7, 13, 3, 12, 13, 2, 11, 8, 12, 3, 6, 3, 2, 6, 7, 8, 1, 3, 12, 3, 2, 7, 12, 3, 8, 7, 3, 2, 6], + "objectLayer": [ + { + "x": 2, + "y": 14 + }, + { + "x": 24, + "y": 9 + } + ], + "entrances": [ + { + "x": 29, + "y": 12, + "width": 3, + "alt_tile": [11, 11] + } + ], + "sprites": [ + { + "type": "player", + "x": 5, + "y": 10 + } + ] + + }, + "exit": { + "width": 30, + "height": 20, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [8, 11, 6, 8, 0, 0, 0, 0, 1, 11, 7, 1, 11, 6, 12, 8, 2, 11, 6, 11, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 1, 7, 12, 2, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 2, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 11, 6, 3, 11, 2, 1, 3, 8, 11, 0, 0, 8, 6, 7, 2, 7, 2, 0, 8, 3, 2, 8, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 3, 8, 12, 2, 0, 0, 8, 11, 1, 3, 8, 6, 2, 0, 0, 0, 0, 11, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 8, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 11, 6, 2, 1, 11, 0, 0, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 13, 0, 11, 0, 6, 0, 7, 0, 11, 6, 2, 0, 0, 6, 11, 0, 0, 0, 0, 0, 7, 8, 11, 1, 3, 8, 0, 0, 7, 0, 0, 0, 1, 13, 7, 0, 11, 0, 0, 13, 0, 0, 0, 11, 6, 0, 0, 0, 0, 3, 13, 0, 0, 0, 0, 2, 0, 0, 13, 1, 11, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 1, 8, 0, 0, 0, 6, 7, 8, 13, 1, 11, 6, 2, 0, 0, 1, 0, 0, 0, 13, 0, 6, 0, 6, 0, 0, 7, 0, 0, 0, 12, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 3, 0, 7, 0, 11, 0, 11, 0, 0, 2, 0, 0, 0, 7, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 8, 11, 2, 8, 12, 11, 2, 12, 11, 8, 11, 1, 11, 6, 12, 8, 2, 6, 11, 7, 2, 6, 11, 12, 6, 11, 7, 6, 11, 6], + "objectLayer": [ + { + "x": 9, + "y": 13 + }, + { + "x": 14, + "y": 5 + } + ], + "entrances": [ + { + "x": 4, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + } + ] + }, + "rooms": [ + { + "width": 40, + "height": 20, + "weight": 2, + "bottomLayer": [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [13, 11, 6, 7, 6, 12, 12, 12, 12, 8, 13, 7, 8, 6, 3, 11, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 6, 13, 12, 3, 7, 2, 6, 7, 6, 3, 13, 6, 12, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 6, 12, 2, 6, 3, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 0, 0, 6, 2, 3, 1, 6, 12, 13, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 12, 6, 13, 3, 7, 1, 6, 13, 0, 0, 0, 12, 13, 0, 0, 0, 1, 13, 12, 6, 13, 1, 7, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 3, 6, 2, 13, 3, 7, 12, 0, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 7, 2, 6, 8, 2, 6, 7, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 6, 1, 7, 13, 8, 6, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 8, 3, 8, 13, 12, 6, 3, 2, 8, 3, 2, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 3, 12, 6, 2, 6, 3, 6, 2, 3, 6, 13, 6, 1, 6, 13, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 2, 7, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 2, 7, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 13, 1, 3, 8, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 3, 6, 12, 7, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 0, 0, 6, 8, 7, 12, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 7, 6, 2, 3, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 1, 12, 3, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 13, 7, 0, 0, 0, 0, 13, 12, 0, 0, 2, 3, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 13, 2, 8, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 6, 11, 13, 8, 11, 6, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 2, 3, 7, 6, 13, 8, 6, 13, 12, 6, 3, 7, 6, 3, 11, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 8, 6, 13, 12, 6, 3, 13, 6, 8, 12, 3, 13, 6, 8], + "objectLayer": [ + { + "x": 5, + "y": 13 + }, + { + "x": 17, + "y": 16 + }, + { + "x": 21, + "y": 7 + }, + { + "x": 26, + "y": 18 + }, + { + "x": 33, + "y": 5 + } + ], + "entrances": [ + { + "x": 39, + "y": 16, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 0, + "y": 16, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 5, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + } + ] + }, + { + "width": 20, + "height": 30, + "weight": 2, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [3, 6, 13, 2, 1, 12, 12, 12, 12, 8, 1, 7, 13, 6, 3, 12, 2, 3, 1, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 0, 0, 0, 3, 7, 6, 13, 2, 7, 13, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 2, 6, 1, 13, 6, 8, 3, 6, 1, 2, 0, 0, 0, 0, 6, 7, 3, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, 12, 8, 7, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 6, 3, 6, 13, 0, 0, 0, 6, 6, 11, 3, 8, 2, 6, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 2, 8, 12, 7, 13, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 7, 0, 0, 11, 3, 7, 6, 8, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 2, 6, 13, 12, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0, 0, 1, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 6, 8, 7, 13, 12, 8, 6, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 2, 13, 6, 2, 3, 6, 13, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7, 8, 6, 8, 11, 0, 0, 3, 7, 13, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 8, 6, 0, 0, 0, 0, 0, 6, 6, 3, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 12, 8, 3, 13, 3, 2, 6, 7, 6, 11, 6, 3, 8, 12, 12, 12, 12, 8, 11, 1, 3, 11, 6, 2], + "objectLayer": [ + { + "x": 2, + "y": 6 + }, + { + "x": 17, + "y": 6 + }, + { + "x": 14, + "y": 16 + }, + { + "x": 4, + "y": 28 + }, + { + "x": 17, + "y": 27 + } + ], + "entrances": [ + { + "x": 9, + "y": 29, + "width": 4, + "alt_tile": [11, 11] + }, + { + "x": 5, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + }, + { + "x": 0, + "y": 4, + "width": 3, + "alt_tile": [11, 11] + } + ] + }, + { + "width": 30, + "height": 30, + "weight": 2, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [3, 12, 6, 13, 6, 8, 12, 12, 12, 12, 3, 6, 3, 13, 7, 1, 3, 6, 12, 13, 6, 7, 8, 3, 6, 7, 6, 12, 13, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 6, 12, 2, 6, 8, 6, 13, 6, 1, 13, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 2, 3, 1, 12, 2, 7, 12, 3, 12, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 0, 0, 0, 1, 13, 6, 8, 13, 1, 2, 6, 13, 12, 6, 0, 0, 0, 0, 7, 6, 7, 2, 6, 7, 6, 3, 7, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 13, 6, 11, 3, 2, 3, 11, 6, 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 3, 2, 7, 12, 2, 6, 7, 6, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 7, 13, 1, 12, 0, 0, 6, 2, 6, 11, 6, 7, 13, 2, 3, 1, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 12, 6, 2, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 3, 6, 3, 6, 12, 8, 0, 0, 3, 6, 1, 3, 12, 6, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 0, 8, 12, 8, 2, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 6, 0, 0, 0, 0, 0, 6, 8, 2, 6, 8, 12, 11, 3, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0, 0, 0, 0, 2, 3, 12, 3, 2, 6, 12, 8, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 3, 7, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 1, 8, 7, 3, 13, 8, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 11, 7, 11, 13, 0, 0, 0, 0, 0, 0, 13, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7, 8, 13, 6, 3, 12, 7, 13, 8, 12, 0, 0, 13, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 13, 6, 3, 6, 8, 12, 7, 6, 3, 13, 6, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 3, 12, 8, 3, 6, 2, 3, 6, 13, 6, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 8, 3, 6, 12, 12, 12, 12, 6, 8, 2, 7, 6, 8, 13, 2, 8], + "objectLayer": [ + { + "x": 3, + "y": 25 + }, + { + "x": 20, + "y": 22 + }, + { + "x": 14, + "y": 14 + }, + { + "x": 25, + "y": 6 + } + ], + "entrances": [ + { + "x": 29, + "y": 26, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 17, + "y": 29, + "width": 4, + "alt_tile": [11, 11] + }, + { + "x": 6, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + } + ] + }, + { + "width": 30, + "height": 25, + "weight": 2, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [1, 3, 7, 12, 12, 12, 12, 6, 1, 11, 7, 1, 3, 8, 1, 13, 7, 1, 6, 12, 6, 1, 3, 6, 7, 1, 3, 2, 1, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 0, 3, 13, 11, 6, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 2, 6, 3, 12, 8, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 6, 3, 7, 1, 12, 8, 1, 8, 0, 0, 0, 0, 0, 0, 0, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 12, 7, 1, 11, 8, 1, 6, 3, 12, 0, 0, 0, 0, 0, 0, 0, 2, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 1, 8, 1, 3, 12, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2684354561, 3, 2, 7, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 3, 6, 1, 3, 8, 0, 0, 0, 0, 3, 7, 2684354561, 12, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 2, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 7, 8, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 3, 6, 0, 0, 0, 0, 0, 0, 0, 8, 6, 8, 3, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 8, 13, 2, 1, 13, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 12, 11, 1, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 8, 2, 3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 7, 13, 12, 1, 8, 12, 13, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 3, 11, 8, 2684354561, 1, 3, 2, 3, 2, 11, 8, 13, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2684354561, 2, 13, 7, 2684354561, 7, 3, 2684354561, 3, 12, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 12, 6, 3, 8, 6, 8, 6, 13, 6, 2, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 13, 8, 7, 6, 3, 13, 7, 11, 3, 8, 3, 6, 8, 7, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 1, 2, 6, 13, 3, 6, 3, 13, 1, 12, 8, 7, 2, 8, 1, 12, 7, 3, 1, 3, 8], + "objectLayer": [ + { + "x": 18, + "y": 5 + }, + { + "x": 27, + "y": 8 + }, + { + "x": 13, + "y": 13 + }, + { + "x": 11, + "y": 23 + } + ], + "entrances": [ + { + "x": 29, + "y": 21, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 0, + "y": 6, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 3, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + } + ] + }, + { + "width": 40, + "height": 30, + "weight": 2, + "bottomLayer": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "topLayer": [1, 7, 12, 6, 1, 8, 6, 7, 8, 2, 6, 8, 1, 12, 6, 7, 3, 13, 8, 6, 12, 12, 12, 12, 7, 13, 2, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 8, 3, 6, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 11, 3, 13, 1, 7, 12, 6, 1, 2, 8, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 12, 3, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 12, 6, 2, 6, 8, 11, 13, 7, 12, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 12, 1, 13, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 6, 8, 3, 1, 3, 13, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 11, 13, 3, 6, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 7, 11, 6, 12, 7, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 3, 12, 6, 7, 12, 13, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 11, 13, 3, 6, 1, 7, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 3, 12, 6, 7, 12, 13, 3, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 12, 1, 8, 6, 2, 13, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 3, 13, 1, 12, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 6, 12, 13, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2, 11, 2, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 1, 6, 2, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 12, 6, 7, 13, 1, 6, 13, 2, 6, 12, 6, 12, 0, 0, 0, 6, 12, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 13, 7, 6, 3, 7, 2, 6, 8, 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 6, 2, 3, 1, 13, 6, 1, 6, 3, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 13, 7, 3, 1, 6, 13, 2, 12, 7, 3, 8, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 6, 12, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 13, 8, 6, 1, 7, 13, 3, 12, 6, 3, 2, 6, 2, 8, 6, 1, 8, 1, 2, 3, 7, 2, 6, 13, 12, 3, 13], + "objectLayer": [ + { + "x": 3, + "y": 4 + }, + { + "x": 10, + "y": 7 + }, + { + "x": 25, + "y": 13 + }, + { + "x": 19, + "y": 22 + }, + { + "x": 23, + "y": 28 + } + ], + "entrances": [ + { + "x": 39, + "y": 26, + "width": 3, + "alt_tile": [11, 11] + }, + { + "x": 20, + "y": 0, + "width": 4, + "alt_tile": [11, 11] + }, + { + "x": 0, + "y": 22, + "width": 3, + "alt_tile": [11, 11] + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets2/jsons/sampleconfig.json b/public/shattered_sword_assets/jsons/sampleconfig.json similarity index 100% rename from public/shattered_sword_assets2/jsons/sampleconfig.json rename to public/shattered_sword_assets/jsons/sampleconfig.json diff --git a/public/shattered_sword_assets2/jsons/samplesave.json b/public/shattered_sword_assets/jsons/samplesave.json similarity index 100% rename from public/shattered_sword_assets2/jsons/samplesave.json rename to public/shattered_sword_assets/jsons/samplesave.json diff --git a/public/shattered_sword_assets2/jsons/samplestory.json b/public/shattered_sword_assets/jsons/samplestory.json similarity index 100% rename from public/shattered_sword_assets2/jsons/samplestory.json rename to public/shattered_sword_assets/jsons/samplestory.json diff --git a/public/shattered_sword_assets2/jsons/story.json b/public/shattered_sword_assets/jsons/story.json similarity index 72% rename from public/shattered_sword_assets2/jsons/story.json rename to public/shattered_sword_assets/jsons/story.json index 6d88ab3..d3eaec3 100644 --- a/public/shattered_sword_assets2/jsons/story.json +++ b/public/shattered_sword_assets/jsons/story.json @@ -1,33 +1,27 @@ { - "bgm": [ - { - "key": "test", - "path": "shattered_sword_assets/sounds/test.mp3" - } - ], "texts": [ { "speaker": "", - "content": "There's a the legendary royal greatsword that is the only weapon powerful enough to slay the monster", + "content": "There was the legendary royal greatsword that would grant great power to its wielder", "actions": [ { "type": "loadSprite", "key": "sword", "path": "shattered_sword_assets/images/story1.png", "positon": [ - 600, - 250 + 300, + 150 ], "scale": [ - 8, - 8 + 4, + 4 ] } ] }, { "speaker": "", - "content": "But the monster shatter it into 6 pieces", + "content": "But an evil monster shattered it into 6 pieces", "actions": [ { "type": "hideSprite", @@ -38,19 +32,19 @@ "key": "sword_shattered", "path": "shattered_sword_assets/images/story2.png", "positon": [ - 600, - 250 + 300, + 150 ], "scale": [ - 8, - 8 + 4, + 4 ] } ] }, { "speaker": "", - "content": "Hiro is the only prince from the kingdom", + "content": "Hiro is the only surviving prince from the kingdom destroyed by the monster", "actions": [ { "type": "hideSprite", @@ -61,12 +55,12 @@ "key": "hiro_appear", "path": "shattered_sword_assets/images/story3.png", "positon": [ - 630, - 300 + 300, + 150 ], "scale": [ - 7, - 7 + 4, + 4 ] } ] @@ -84,19 +78,19 @@ "key": "hiro_sword", "path": "shattered_sword_assets/images/story4.png", "positon": [ - 630, - 300 + 300, + 150 ], "scale": [ - 7, - 7 + 4, + 4 ] } ] }, { "speaker": "Hiro", - "content": "I should go on the journey to collect the pieces of the sword... and kill the monster!", + "content": "I must go on the journey to collect the pieces of the sword... and kill the monster!", "actions": [ { "type": "showSprite", @@ -115,14 +109,14 @@ { "type": "loadSprite", "key": "logo", - "path": "shattered_sword_assets/images/Logo.png", + "path": "shattered_sword_assets/images/logo.png", "positon": [ - 650, - 300 + 330, + 150 ], "scale": [ - 1, - 1 + 0.5, + 0.5 ] } ] diff --git a/public/shattered_sword_assets/sounds/bgm1.mp3 b/public/shattered_sword_assets/sounds/bgm1.mp3 new file mode 100644 index 0000000..be15dd6 Binary files /dev/null and b/public/shattered_sword_assets/sounds/bgm1.mp3 differ diff --git a/public/shattered_sword_assets/sounds/dash.wav b/public/shattered_sword_assets/sounds/dash.wav new file mode 100644 index 0000000..539f141 Binary files /dev/null and b/public/shattered_sword_assets/sounds/dash.wav differ diff --git a/public/shattered_sword_assets/sounds/die.wav b/public/shattered_sword_assets/sounds/die.wav new file mode 100644 index 0000000..fe7e8da Binary files /dev/null and b/public/shattered_sword_assets/sounds/die.wav differ diff --git a/public/shattered_sword_assets/sounds/hurt.wav b/public/shattered_sword_assets/sounds/hurt.wav new file mode 100644 index 0000000..fe2cb58 Binary files /dev/null and b/public/shattered_sword_assets/sounds/hurt.wav differ diff --git a/public/shattered_sword_assets/sounds/jump.wav b/public/shattered_sword_assets/sounds/jump.wav new file mode 100644 index 0000000..949997e Binary files /dev/null and b/public/shattered_sword_assets/sounds/jump.wav differ diff --git a/public/shattered_sword_assets/sounds/jump2.wav b/public/shattered_sword_assets/sounds/jump2.wav new file mode 100644 index 0000000..8212788 Binary files /dev/null and b/public/shattered_sword_assets/sounds/jump2.wav differ diff --git a/public/shattered_sword_assets/sounds/level_up.wav b/public/shattered_sword_assets/sounds/level_up.wav new file mode 100644 index 0000000..74f1f74 Binary files /dev/null and b/public/shattered_sword_assets/sounds/level_up.wav differ diff --git a/public/shattered_sword_assets/sounds/sword_ding.m4a b/public/shattered_sword_assets/sounds/sword_ding.m4a new file mode 100644 index 0000000..33aa0fb Binary files /dev/null and b/public/shattered_sword_assets/sounds/sword_ding.m4a differ diff --git a/public/shattered_sword_assets/sounds/sword_ding1.m4a b/public/shattered_sword_assets/sounds/sword_ding1.m4a new file mode 100644 index 0000000..9e7d1da Binary files /dev/null and b/public/shattered_sword_assets/sounds/sword_ding1.m4a differ diff --git a/public/shattered_sword_assets2/sprites/inventory.png b/public/shattered_sword_assets/sprites/inventory.png similarity index 100% rename from public/shattered_sword_assets2/sprites/inventory.png rename to public/shattered_sword_assets/sprites/inventory.png diff --git a/public/shattered_sword_assets2/sprites/knife.png b/public/shattered_sword_assets/sprites/knife.png similarity index 100% rename from public/shattered_sword_assets2/sprites/knife.png rename to public/shattered_sword_assets/sprites/knife.png diff --git a/public/shattered_sword_assets/spritesheets/Archer.json b/public/shattered_sword_assets/spritesheets/Archer.json new file mode 100644 index 0000000..14642c9 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/Archer.json @@ -0,0 +1,21 @@ +{ + "name" : "Archer", + "spriteSheetImage": "Archer.png", + "spriteWidth": 64, + "spriteHeight": 64, + "columns": 1, + "rows": 1, + "durationType": "time", + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 20 + } + ] + } + ] +} diff --git a/public/shattered_sword_assets/spritesheets/Archer.png b/public/shattered_sword_assets/spritesheets/Archer.png new file mode 100644 index 0000000..1b65bd5 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/Archer.png differ diff --git a/public/shattered_sword_assets/spritesheets/Bull.json b/public/shattered_sword_assets/spritesheets/Bull.json new file mode 100644 index 0000000..16a68f1 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/Bull.json @@ -0,0 +1,35 @@ +{ + "name" : "Bull", + "spriteSheetImage": "Bull.png", + "spriteWidth": 64, + "spriteHeight": 64, + "width": 256, + "height": 64, + "columns": 4, + "rows": 1, + "durationType": "time", + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 20 + }, + { + "index": 1, + "duration": 20 + }, + { + "index": 2, + "duration": 20 + }, + { + "index": 1, + "duration": 20 + } + ] + } + ] +} diff --git a/public/shattered_sword_assets/spritesheets/Bull.png b/public/shattered_sword_assets/spritesheets/Bull.png new file mode 100644 index 0000000..25bf4b0 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/Bull.png differ diff --git a/public/shattered_sword_assets2/spritesheets/Hiro.json b/public/shattered_sword_assets/spritesheets/Hiro.json similarity index 66% rename from public/shattered_sword_assets2/spritesheets/Hiro.json rename to public/shattered_sword_assets/spritesheets/Hiro.json index b7c4b4c..647f076 100644 --- a/public/shattered_sword_assets2/spritesheets/Hiro.json +++ b/public/shattered_sword_assets/spritesheets/Hiro.json @@ -3,7 +3,7 @@ "spriteSheetImage": "Hiro.png", "spriteWidth": 64, "spriteHeight": 64, - "columns": 7, + "columns": 8, "rows": 7, "durationType": "time", "animations": [ @@ -13,11 +13,11 @@ "frames": [ { "index": 0, - "duration": 150 + "duration": 10 }, { "index": 1, - "duration": 150 + "duration": 10 } ] }, @@ -27,35 +27,35 @@ "frames": [ { "index": 4, - "duration": 150 + "duration": 5 }, { "index": 5, - "duration": 150 + "duration": 5 }, { "index": 6, - "duration": 150 + "duration": 5 }, { "index": 7, - "duration": 150 + "duration": 5 }, { "index": 8, - "duration": 150 + "duration": 5 }, { "index": 9, - "duration": 150 + "duration": 5 }, { "index": 10, - "duration": 150 + "duration": 5 }, { "index": 11, - "duration": 150 + "duration": 5 } ] }, @@ -64,57 +64,65 @@ "repeat": true, "frames": [ { - "index": 0, - "duration": 150 + "index": 44, + "duration": 10 }, { - "index": 1, - "duration": 150 + "index": 45, + "duration": 10 } ] }, + { + "name": "JUMP2", + "repeat": false, + "frames": [ + { + "index": 30, + "duration": 5 + }, + { + "index": 31, + "duration": 5 + }, + { + "index": 32, + "duration": 10 + }, + { + "index": 31, + "duration": 5 + }, + { + "index": 30, + "duration": 5 + } + ] + }, { "name": "JUMP", "repeat": false, - "frames": [ - { - "index": 30, - "duration": 150 - }, - { - "index": 31, - "duration": 150 - }, - { - "index": 32, - "duration": 150 - } - ] - }, - { - "name": "JUMP_RIGHT", - "repeat": false, "frames": [ { "index": 20, - "duration": 150 + "duration": 10 }, { "index": 21, - "duration": 150 + "duration": 10 }, { "index": 22, - "duration": 150 + "duration": 10 }, { "index": 23, - "duration": 150 + "duration": 10 }, { "index": 24, - "duration": 150 + "duration": 10 } ] }, @@ -124,23 +132,23 @@ "frames": [ { "index": 25, - "duration": 150 + "duration": 10 }, { "index": 26, - "duration": 150 + "duration": 10 }, { "index": 27, - "duration": 150 + "duration": 10 }, { "index": 28, - "duration": 150 + "duration": 10 }, { "index": 29, - "duration": 150 + "duration": 10 } ] }, @@ -150,15 +158,15 @@ "frames": [ { "index": 33, - "duration": 250 + "duration": 10 }, { "index": 34, - "duration": 400 + "duration": 5 }, { "index": 35, - "duration": 250 + "duration": 10 } ] }, @@ -168,15 +176,15 @@ "frames": [ { "index": 33, - "duration": 150 + "duration": 10 }, { "index": 34, - "duration": 100 + "duration": 5 }, { "index": 35, - "duration": 150 + "duration": 10 } ] }, @@ -186,15 +194,15 @@ "frames": [ { "index": 36, - "duration": 150 + "duration": 10 }, { "index": 37, - "duration": 100 + "duration": 5 }, { "index": 38, - "duration": 150 + "duration": 10 } ] }, @@ -202,6 +210,10 @@ "name": "HURT", "repeat": false, "frames": [ + { + "index": 39, + "duration": 5 + }, { "index": 0, "duration": 5 @@ -266,19 +278,19 @@ "frames": [ { "index": 0, - "duration": 150 + "duration": 10 }, { "index": 40, - "duration": 100 + "duration": 5 }, { "index": 41, - "duration": 100 + "duration": 5 }, { "index": 42, - "duration": 150 + "duration": 10 } ] }, @@ -288,7 +300,41 @@ "frames": [ { "index": 43, - "duration": 150 + "duration": 10 + } + ] + }, + { + "name": "DASH", + "repeat": false, + "frames": [ + { + "index": 46, + "duration": 1 + }, + { + "index": 47, + "duration": 1 + }, + { + "index": 48, + "duration": 1 + }, + { + "index": 49, + "duration": 2 + }, + { + "index": 48, + "duration": 1 + }, + { + "index": 47, + "duration": 1 + }, + { + "index": 46, + "duration": 1 } ] } diff --git a/public/shattered_sword_assets/spritesheets/Hiro.png b/public/shattered_sword_assets/spritesheets/Hiro.png new file mode 100644 index 0000000..5406695 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/Hiro.png differ diff --git a/public/shattered_sword_assets/spritesheets/Snake.json b/public/shattered_sword_assets/spritesheets/Snake.json new file mode 100644 index 0000000..3ffd495 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/Snake.json @@ -0,0 +1,232 @@ +{ + "name" : "Snake", + "spriteSheetImage": "Snake.png", + "spriteWidth": 32, + "spriteHeight": 32, + "width": 160, + "height": 160, + "columns": 5, + "rows": 5, + "durationType": "time", + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 1, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 5 + }, + { + "index": 4, + "duration": 5 + }, + { + "index": 3, + "duration": 5 + }, + { + "index": 4, + "duration": 5 + }, + { + "index": 3, + "duration": 5 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 1, + "duration": 10 + } + ] + }, + { + "name": "WALK", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 1, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 5 + }, + { + "index": 4, + "duration": 5 + } + ] + }, + { + "name": "CHARGE", + "repeat": false, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 5, + "duration": 10 + }, + { + "index": 6, + "duration": 10 + }, + { + "index": 7, + "duration": 10 + }, + { + "index": 8, + "duration": 10 + }, + { + "index": 7, + "duration": 10 + } + ] + }, + { + "name": "ATTACK", + "repeat": false, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 9, + "duration": 5 + }, + { + "index": 10, + "duration": 5 + }, + { + "index": 11, + "duration": 5 + }, + { + "index": 12, + "duration": 5 + }, + { + "index": 13, + "duration": 10 + } + + ] + }, + { + "name": "DYING", + "repeat": false, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 14, + "duration": 5 + }, + { + "index": 15, + "duration": 5 + }, + { + "index": 16, + "duration": 5 + }, + { + "index": 17, + "duration": 10 + }, + { + "index": 18, + "duration": 10 + }, + { + "index": 19, + "duration": 10 + }, + { + "index": 20, + "duration": 10 + } + ] + }, + { + "name": "HURT", + "repeat": false, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 14, + "duration": 5 + }, + { + "index": 15, + "duration": 5 + }, + { + "index": 16, + "duration": 5 + }, + { + "index": 17, + "duration": 10 + }, + { + "index": 18, + "duration": 10 + }, + { + "index": 19, + "duration": 10 + }, + { + "index": 20, + "duration": 10 + } + ] + }, + { + "name": "DEAD", + "repeat": true, + "frames": [ + { + "index": 21, + "duration": 10 + } + ] + } + ] +} diff --git a/public/shattered_sword_assets/spritesheets/Snake.png b/public/shattered_sword_assets/spritesheets/Snake.png new file mode 100644 index 0000000..05b204d Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/Snake.png differ diff --git a/public/shattered_sword_assets/spritesheets/Tiger.json b/public/shattered_sword_assets/spritesheets/Tiger.json new file mode 100644 index 0000000..badf900 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/Tiger.json @@ -0,0 +1,110 @@ +{ + "name" : "Tiger", + "spriteSheetImage": "Tiger.png", + "spriteWidth": 64, + "spriteHeight": 64, + "columns": 3, + "rows": 3, + "durationType": "time", + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 10 + } + + ] + }, + { + "name": "WALK", + "repeat": true, + "frames": [ + { + "index": 1, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + } + ] + }, + { + "name": "WALK_RIGHT", + "repeat": true, + "frames": [ + { + "index": 1, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + } + ] + }, + { + "name": "WALK_LEFT", + "repeat": true, + "frames": [ + { + "index": 4, + "duration": 10 + }, + { + "index": 5, + "duration": 10 + }, + { + "index": 6, + "duration": 10 + }, + { + "index": 5, + "duration": 10 + } + ] + }, + { + "name": "CHARGE", + "repeat": false, + "frames": [ + { + "index": 7, + "duration": 20 + } + + ] + }, + { + "name": "ATTACK", + "repeat": false, + "frames": [ + { + "index": 8, + "duration": 20 + } + + ] + } + ] +} diff --git a/public/shattered_sword_assets/spritesheets/Tiger.png b/public/shattered_sword_assets/spritesheets/Tiger.png new file mode 100644 index 0000000..e14bd5b Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/Tiger.png differ diff --git a/public/shattered_sword_assets/spritesheets/black_pudding.json b/public/shattered_sword_assets/spritesheets/black_pudding.json new file mode 100644 index 0000000..9d7b7f1 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/black_pudding.json @@ -0,0 +1,892 @@ +{ + "name": "Black Pudding", + "spriteSheetImage": "black_pudding.png", + "spriteWidth": 128, + "spriteHeight": 128, + "columns": 30, + "rows": 10, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 4 + }, + { + "index": 1, + "duration": 4 + }, + { + "index": 2, + "duration": 4 + }, + { + "index": 3, + "duration": 4 + }, + { + "index": 4, + "duration": 4 + }, + { + "index": 5, + "duration": 4 + }, + { + "index": 6, + "duration": 4 + }, + { + "index": 7, + "duration": 4 + }, + { + "index": 8, + "duration": 4 + }, + { + "index": 9, + "duration": 4 + }, + { + "index": 10, + "duration": 4 + }, + { + "index": 11, + "duration": 4 + } + ] + }, + { + "name": "WALK", + "repeat": true, + "frames": [ + { + "index": 60, + "duration": 4 + }, + { + "index": 61, + "duration": 4 + }, + { + "index": 62, + "duration": 4 + }, + { + "index": 63, + "duration": 4 + }, + { + "index": 64, + "duration": 4 + }, + { + "index": 65, + "duration": 4 + }, + { + "index": 66, + "duration": 4 + }, + { + "index": 67, + "duration": 4 + }, + { + "index": 68, + "duration": 4 + }, + { + "index": 69, + "duration": 4 + } + ] + }, + { + "name": "ATTACK", + "repeat": true, + "frames": [ + { + "index": 120, + "duration": 4 + }, + { + "index": 121, + "duration": 4 + }, + { + "index": 122, + "duration": 4 + }, + { + "index": 123, + "duration": 4 + }, + { + "index": 124, + "duration": 4 + }, + { + "index": 125, + "duration": 4 + }, + { + "index": 126, + "duration": 4 + }, + { + "index": 127, + "duration": 4 + }, + { + "index": 128, + "duration": 4 + }, + { + "index": 129, + "duration": 4 + }, + { + "index": 130, + "duration": 4 + }, + { + "index": 131, + "duration": 4 + }, + { + "index": 132, + "duration": 4 + }, + { + "index": 133, + "duration": 4 + }, + { + "index": 134, + "duration": 4 + }, + { + "index": 135, + "duration": 4 + }, + { + "index": 136, + "duration": 4 + }, + { + "index": 137, + "duration": 4 + }, + { + "index": 138, + "duration": 4 + }, + { + "index": 139, + "duration": 4 + }, + { + "index": 140, + "duration": 4 + }, + { + "index": 141, + "duration": 4 + }, + { + "index": 142, + "duration": 4 + }, + { + "index": 143, + "duration": 4 + }, + { + "index": 144, + "duration": 4 + }, + { + "index": 145, + "duration": 4 + }, + { + "index": 146, + "duration": 4 + }, + { + "index": 147, + "duration": 4 + }, + { + "index": 148, + "duration": 4 + }, + { + "index": 149, + "duration": 4 + } + ] + }, + { + "name": "HURT", + "repeat": false, + "frames": [ + { + "index": 180, + "duration": 4 + }, + { + "index": 181, + "duration": 4 + }, + { + "index": 182, + "duration": 4 + }, + { + "index": 183, + "duration": 4 + }, + { + "index": 184, + "duration": 4 + }, + { + "index": 185, + "duration": 4 + }, + { + "index": 186, + "duration": 4 + }, + { + "index": 187, + "duration": 4 + }, + { + "index": 188, + "duration": 4 + }, + { + "index": 189, + "duration": 4 + }, + { + "index": 190, + "duration": 4 + }, + { + "index": 191, + "duration": 4 + }, + { + "index": 192, + "duration": 4 + }, + { + "index": 193, + "duration": 4 + }, + { + "index": 194, + "duration": 4 + } + ] + }, + { + "name": "Moving Left", + "repeat": true, + "frames": [ + { + "index": 30, + "duration": 4 + }, + { + "index": 31, + "duration": 4 + }, + { + "index": 32, + "duration": 4 + }, + { + "index": 33, + "duration": 4 + }, + { + "index": 34, + "duration": 4 + }, + { + "index": 35, + "duration": 4 + }, + { + "index": 36, + "duration": 4 + }, + { + "index": 37, + "duration": 4 + }, + { + "index": 38, + "duration": 4 + }, + { + "index": 39, + "duration": 4 + } + ] + }, + { + "name": "Moving Right", + "repeat": true, + "frames": [ + { + "index": 60, + "duration": 4 + }, + { + "index": 61, + "duration": 4 + }, + { + "index": 62, + "duration": 4 + }, + { + "index": 63, + "duration": 4 + }, + { + "index": 64, + "duration": 4 + }, + { + "index": 65, + "duration": 4 + }, + { + "index": 66, + "duration": 4 + }, + { + "index": 67, + "duration": 4 + }, + { + "index": 68, + "duration": 4 + }, + { + "index": 69, + "duration": 4 + } + ] + }, + { + "name": "Attack Left", + "repeat": true, + "frames": [ + { + "index": 90, + "duration": 4 + }, + { + "index": 91, + "duration": 4 + }, + { + "index": 92, + "duration": 4 + }, + { + "index": 93, + "duration": 4 + }, + { + "index": 94, + "duration": 4 + }, + { + "index": 95, + "duration": 4 + }, + { + "index": 96, + "duration": 4 + }, + { + "index": 97, + "duration": 4 + }, + { + "index": 98, + "duration": 4 + }, + { + "index": 99, + "duration": 4 + }, + { + "index": 100, + "duration": 4 + }, + { + "index": 101, + "duration": 4 + }, + { + "index": 102, + "duration": 4 + }, + { + "index": 103, + "duration": 4 + }, + { + "index": 104, + "duration": 4 + }, + { + "index": 105, + "duration": 4 + }, + { + "index": 106, + "duration": 4 + }, + { + "index": 107, + "duration": 4 + }, + { + "index": 108, + "duration": 4 + }, + { + "index": 109, + "duration": 4 + }, + { + "index": 110, + "duration": 4 + }, + { + "index": 111, + "duration": 4 + }, + { + "index": 112, + "duration": 4 + }, + { + "index": 113, + "duration": 4 + }, + { + "index": 114, + "duration": 4 + }, + { + "index": 115, + "duration": 4 + }, + { + "index": 116, + "duration": 4 + }, + { + "index": 117, + "duration": 4 + }, + { + "index": 118, + "duration": 4 + }, + { + "index": 119, + "duration": 4 + } + ] + }, + { + "name": "Attack Right", + "repeat": true, + "frames": [ + { + "index": 120, + "duration": 4 + }, + { + "index": 121, + "duration": 4 + }, + { + "index": 122, + "duration": 4 + }, + { + "index": 123, + "duration": 4 + }, + { + "index": 124, + "duration": 4 + }, + { + "index": 125, + "duration": 4 + }, + { + "index": 126, + "duration": 4 + }, + { + "index": 127, + "duration": 4 + }, + { + "index": 128, + "duration": 4 + }, + { + "index": 129, + "duration": 4 + }, + { + "index": 130, + "duration": 4 + }, + { + "index": 131, + "duration": 4 + }, + { + "index": 132, + "duration": 4 + }, + { + "index": 133, + "duration": 4 + }, + { + "index": 134, + "duration": 4 + }, + { + "index": 135, + "duration": 4 + }, + { + "index": 136, + "duration": 4 + }, + { + "index": 137, + "duration": 4 + }, + { + "index": 138, + "duration": 4 + }, + { + "index": 139, + "duration": 4 + }, + { + "index": 140, + "duration": 4 + }, + { + "index": 141, + "duration": 4 + }, + { + "index": 142, + "duration": 4 + }, + { + "index": 143, + "duration": 4 + }, + { + "index": 144, + "duration": 4 + }, + { + "index": 145, + "duration": 4 + }, + { + "index": 146, + "duration": 4 + }, + { + "index": 147, + "duration": 4 + }, + { + "index": 148, + "duration": 4 + }, + { + "index": 149, + "duration": 4 + } + ] + }, + { + "name": "Damaged Left", + "repeat": true, + "frames": [ + { + "index": 150, + "duration": 4 + }, + { + "index": 151, + "duration": 4 + }, + { + "index": 152, + "duration": 4 + }, + { + "index": 153, + "duration": 4 + }, + { + "index": 154, + "duration": 4 + }, + { + "index": 155, + "duration": 4 + }, + { + "index": 156, + "duration": 4 + }, + { + "index": 157, + "duration": 4 + }, + { + "index": 158, + "duration": 4 + }, + { + "index": 159, + "duration": 4 + }, + { + "index": 160, + "duration": 4 + }, + { + "index": 161, + "duration": 4 + }, + { + "index": 162, + "duration": 4 + }, + { + "index": 163, + "duration": 4 + }, + { + "index": 164, + "duration": 4 + } + ] + }, + { + "name": "Damaged Right", + "repeat": true, + "frames": [ + { + "index": 180, + "duration": 4 + }, + { + "index": 181, + "duration": 4 + }, + { + "index": 182, + "duration": 4 + }, + { + "index": 183, + "duration": 4 + }, + { + "index": 184, + "duration": 4 + }, + { + "index": 185, + "duration": 4 + }, + { + "index": 186, + "duration": 4 + }, + { + "index": 187, + "duration": 4 + }, + { + "index": 188, + "duration": 4 + }, + { + "index": 189, + "duration": 4 + }, + { + "index": 190, + "duration": 4 + }, + { + "index": 191, + "duration": 4 + }, + { + "index": 192, + "duration": 4 + }, + { + "index": 193, + "duration": 4 + }, + { + "index": 194, + "duration": 4 + } + ] + }, + { + "name": "DYING", + "repeat": false, + "frames": [ + { + "index": 210, + "duration": 4 + }, + { + "index": 211, + "duration": 4 + }, + { + "index": 212, + "duration": 4 + }, + { + "index": 213, + "duration": 4 + }, + { + "index": 214, + "duration": 4 + }, + { + "index": 215, + "duration": 4 + }, + { + "index": 216, + "duration": 4 + }, + { + "index": 217, + "duration": 4 + }, + { + "index": 218, + "duration": 4 + }, + { + "index": 219, + "duration": 4 + } + ] + }, + { + "name": "DEAD", + "repeat": false, + "frames": [ + { + "index": 240, + "duration": 100 + } + ] + }, + { + "name": "Dancing", + "repeat": true, + "frames": [ + { + "index": 270, + "duration": 4 + }, + { + "index": 271, + "duration": 4 + }, + { + "index": 272, + "duration": 4 + }, + { + "index": 273, + "duration": 4 + }, + { + "index": 272, + "duration": 4 + }, + { + "index": 271, + "duration": 4 + }, + { + "index": 270, + "duration": 4 + }, + { + "index": 274, + "duration": 4 + }, + { + "index": 275, + "duration": 4 + }, + { + "index": 276, + "duration": 4 + }, + { + "index": 275, + "duration": 4 + }, + { + "index": 274, + "duration": 4 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/black_pudding.png b/public/shattered_sword_assets/spritesheets/black_pudding.png new file mode 100644 index 0000000..2475c29 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/black_pudding.png differ diff --git a/public/shattered_sword_assets/spritesheets/carrion_crawler.json b/public/shattered_sword_assets/spritesheets/carrion_crawler.json new file mode 100644 index 0000000..970b069 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/carrion_crawler.json @@ -0,0 +1,482 @@ +{ + "name": "Carrion Crawler", + "spriteSheetImage": "carrion_crawler.png", + "spriteWidth": 128, + "spriteHeight": 32, + "columns": 20, + "rows": 10, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "animations": [ + { + "name": "WALK LEFT", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 5 + }, + { + "index": 1, + "duration": 5 + }, + { + "index": 2, + "duration": 5 + }, + { + "index": 3, + "duration": 5 + }, + { + "index": 4, + "duration": 5 + }, + { + "index": 5, + "duration": 5 + }, + { + "index": 6, + "duration": 5 + }, + { + "index": 7, + "duration": 5 + }, + { + "index": 8, + "duration": 5 + }, + { + "index": 9, + "duration": 5 + }, + { + "index": 10, + "duration": 5 + }, + { + "index": 11, + "duration": 5 + }, + { + "index": 12, + "duration": 5 + }, + { + "index": 13, + "duration": 5 + } + ] + }, + { + "name": "WALK RIGHT", + "repeat": true, + "frames": [ + { + "index": 33, + "duration": 5 + }, + { + "index": 32, + "duration": 5 + }, + { + "index": 31, + "duration": 5 + }, + { + "index": 30, + "duration": 5 + }, + { + "index": 29, + "duration": 5 + }, + { + "index": 28, + "duration": 5 + }, + { + "index": 27, + "duration": 5 + }, + { + "index": 26, + "duration": 5 + }, + { + "index": 25, + "duration": 5 + }, + { + "index": 24, + "duration": 5 + }, + { + "index": 23, + "duration": 5 + }, + { + "index": 22, + "duration": 5 + }, + { + "index": 21, + "duration": 5 + }, + { + "index": 20, + "duration": 5 + } + ] + }, + { + "name": "ATTACK LEFT", + "repeat": true, + "frames": [ + { + "index": 40, + "duration": 5 + }, + { + "index": 41, + "duration": 5 + }, + { + "index": 42, + "duration": 5 + }, + { + "index": 43, + "duration": 5 + }, + { + "index": 44, + "duration": 5 + }, + { + "index": 45, + "duration": 5 + }, + { + "index": 46, + "duration": 5 + }, + { + "index": 47, + "duration": 5 + }, + { + "index": 48, + "duration": 5 + }, + { + "index": 49, + "duration": 5 + }, + { + "index": 50, + "duration": 5 + }, + { + "index": 51, + "duration": 5 + } + ] + }, + { + "name": "ATTACK RIGHT", + "repeat": true, + "frames": [ + { + "index": 71, + "duration": 5 + }, + { + "index": 70, + "duration": 5 + }, + { + "index": 69, + "duration": 5 + }, + { + "index": 68, + "duration": 5 + }, + { + "index": 67, + "duration": 5 + }, + { + "index": 66, + "duration": 5 + }, + { + "index": 65, + "duration": 5 + }, + { + "index": 64, + "duration": 5 + }, + { + "index": 63, + "duration": 5 + }, + { + "index": 62, + "duration": 5 + }, + { + "index": 61, + "duration": 5 + }, + { + "index": 60, + "duration": 5 + } + ] + }, + { + "name": "DAMAGED LEFT", + "repeat": false, + "frames": [ + { + "index": 80, + "duration": 5 + }, + { + "index": 81, + "duration": 5 + }, + { + "index": 82, + "duration": 5 + }, + { + "index": 83, + "duration": 5 + }, + { + "index": 82, + "duration": 5 + }, + { + "index": 81, + "duration": 5 + }, + { + "index": 80, + "duration": 5 + } + ] + }, + { + "name": "DAMAGED RIGHT", + "repeat": false, + "frames": [ + { + "index": 103, + "duration": 5 + }, + { + "index": 102, + "duration": 5 + }, + { + "index": 101, + "duration": 5 + }, + { + "index": 100, + "duration": 5 + }, + { + "index": 101, + "duration": 5 + }, + { + "index": 102, + "duration": 5 + }, + { + "index": 103, + "duration": 5 + } + ] + }, + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 120, + "duration": 5 + }, + { + "index": 121, + "duration": 5 + }, + { + "index": 122, + "duration": 5 + }, + { + "index": 123, + "duration": 10 + }, + { + "index": 124, + "duration": 5 + }, + { + "index": 125, + "duration": 10 + }, + { + "index": 122, + "duration": 5 + }, + { + "index": 121, + "duration": 5 + }, + { + "index": 120, + "duration": 25 + } + ] + }, + { + "name": "DANCE", + "repeat": true, + "frames": [ + { + "index": 140, + "duration": 5 + }, + { + "index": 141, + "duration": 5 + }, + { + "index": 142, + "duration": 5 + }, + { + "index": 143, + "duration": 5 + }, + { + "index": 144, + "duration": 5 + }, + { + "index": 145, + "duration": 5 + } + ] + }, + { + "name": "DIE", + "repeat": false, + "frames": [ + { + "index": 160, + "duration": 5 + }, + { + "index": 161, + "duration": 5 + }, + { + "index": 162, + "duration": 5 + }, + { + "index": 163, + "duration": 5 + }, + { + "index": 164, + "duration": 5 + }, + { + "index": 165, + "duration": 5 + }, + { + "index": 166, + "duration": 5 + }, + { + "index": 167, + "duration": 5 + }, + { + "index": 168, + "duration": 5 + }, + { + "index": 169, + "duration": 5 + }, + { + "index": 170, + "duration": 5 + }, + { + "index": 171, + "duration": 5 + }, + { + "index": 172, + "duration": 5 + }, + { + "index": 173, + "duration": 5 + }, + { + "index": 174, + "duration": 5 + }, + { + "index": 175, + "duration": 5 + }, + { + "index": 176, + "duration": 5 + }, + { + "index": 177, + "duration": 5 + }, + { + "index": 178, + "duration": 5 + }, + { + "index": 179, + "duration": 5 + } + ] + }, + { + "name": "DEAD", + "repeat": true, + "frames": [ + { + "index": 180, + "duration": 5 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/carrion_crawler.png b/public/shattered_sword_assets/spritesheets/carrion_crawler.png new file mode 100644 index 0000000..82b7f0b Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/carrion_crawler.png differ diff --git a/public/shattered_sword_assets/spritesheets/flying_sword.json b/public/shattered_sword_assets/spritesheets/flying_sword.json new file mode 100644 index 0000000..ef2e7c9 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/flying_sword.json @@ -0,0 +1,353 @@ +{ + "name": "Flying Sword", + "spriteSheetImage": "flying_sword.png", + "spriteWidth": 128, + "spriteHeight": 128, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "columns": 9, + "rows": 11, + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 9, + "duration": 8 + }, + { + "index": 10, + "duration": 8 + }, + { + "index": 11, + "duration": 8 + }, + { + "index": 12, + "duration": 8 + }, + { + "index": 13, + "duration": 8 + }, + { + "index": 14, + "duration": 8 + } + ] + }, + { + "name": "SPAWN", + "repeat": false, + "frames": [ + { + "index": 0, + "duration": 12 + }, + { + "index": 1, + "duration": 6 + }, + { + "index": 2, + "duration": 6 + }, + { + "index": 3, + "duration": 6 + }, + { + "index": 4, + "duration": 6 + } + ] + }, + { + "name": "MOVE_RIGHT", + "repeat": true, + "frames": [ + { + "index": 18, + "duration": 8 + }, + { + "index": 19, + "duration": 8 + }, + { + "index": 20, + "duration": 8 + }, + { + "index": 21, + "duration": 8 + }, + { + "index": 22, + "duration": 8 + }, + { + "index": 23, + "duration": 8 + } + ] + }, + { + "name": "MOVE_LEFT", + "repeat": true, + "frames": [ + { + "index": 27, + "duration": 8 + }, + { + "index": 28, + "duration": 8 + }, + { + "index": 29, + "duration": 8 + }, + { + "index": 30, + "duration": 8 + }, + { + "index": 31, + "duration": 8 + }, + { + "index": 32, + "duration": 8 + } + ] + }, + { + "name": "ATTACK_RIGHT", + "repeat": false, + "frames": [ + { + "index": 36, + "duration": 6 + }, + { + "index": 38, + "duration": 6 + }, + { + "index": 39, + "duration": 6 + }, + { + "index": 40, + "duration": 6 + }, + { + "index": 41, + "duration": 6 + }, + { + "index": 42, + "duration": 6 + } + ] + }, + { + "name": "ATTACK_LEFT", + "repeat": false, + "frames": [ + { + "index": 45, + "duration": 6 + }, + { + "index": 47, + "duration": 6 + }, + { + "index": 48, + "duration": 6 + }, + { + "index": 49, + "duration": 6 + }, + { + "index": 50, + "duration": 6 + }, + { + "index": 51, + "duration": 6 + } + ] + }, + { + "name": "DANCE", + "repeat": true, + "frames": [ + { + "index": 54, + "duration": 8 + }, + { + "index": 55, + "duration": 8 + }, + { + "index": 56, + "duration": 8 + }, + { + "index": 57, + "duration": 8 + }, + { + "index": 58, + "duration": 8 + }, + { + "index": 59, + "duration": 8 + } + ] + }, + { + "name": "ATTACKED_RIGHT", + "repeat": false, + "frames": [ + { + "index": 63, + "duration": 6 + }, + { + "index": 64, + "duration": 4 + }, + { + "index": 65, + "duration": 4 + }, + { + "index": 66, + "duration": 8 + }, + { + "index": 67, + "duration": 8 + }, + { + "index": 68, + "duration": 8 + } + ] + }, + { + "name": "ATTACKED_LEFT", + "repeat": false, + "frames": [ + { + "index": 72, + "duration": 6 + }, + { + "index": 73, + "duration": 4 + }, + { + "index": 74, + "duration": 4 + }, + { + "index": 75, + "duration": 8 + }, + { + "index": 76, + "duration": 8 + }, + { + "index": 77, + "duration": 8 + } + ] + }, + { + "name": "DYING", + "repeat": true, + "frames": [ + { + "index": 81, + "duration": 4 + }, + { + "index": 82, + "duration": 8 + }, + { + "index": 83, + "duration": 8 + }, + { + "index": 84, + "duration": 8 + }, + { + "index": 85, + "duration": 8 + }, + { + "index": 86, + "duration": 8 + }, + { + "index": 87, + "duration": 8 + }, + { + "index": 88, + "duration": 8 + }, + { + "index": 89, + "duration": 4 + } + ] + }, + { + "name": "DEAD", + "frames": "90-95", + "repeat": false, + "frames": [ + { + "index": 90, + "duration": 8 + }, + { + "index": 91, + "duration": 8 + }, + { + "index": 92, + "duration": 8 + }, + { + "index": 93, + "duration": 8 + }, + { + "index": 94, + "duration": 8 + }, + { + "index": 95, + "duration": 12 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/flying_sword.png b/public/shattered_sword_assets/spritesheets/flying_sword.png new file mode 100644 index 0000000..09d18e4 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/flying_sword.png differ diff --git a/public/shattered_sword_assets/spritesheets/greater_seawolf.json b/public/shattered_sword_assets/spritesheets/greater_seawolf.json new file mode 100644 index 0000000..d3e0196 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/greater_seawolf.json @@ -0,0 +1,348 @@ +{ + "name": "Greater Seawolf", + "spriteSheetImage": "greater_seawolf.png", + "spriteWidth": 128, + "spriteHeight": 128, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "columns": 5, + "rows": 13, + "animations": [ + { + "name": "IDLE_RIGHT", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 1, + "duration": 11 + }, + { + "index": 2, + "duration": 12 + }, + { + "index": 3, + "duration": 13 + }, + { + "index": 4, + "duration": 8 + } + ] + }, + { + "name": "IDLE_LEFT", + "repeat": true, + "frames": [ + { + "index": 5, + "duration": 10 + }, + { + "index": 6, + "duration": 11 + }, + { + "index": 7, + "duration": 12 + }, + { + "index": 8, + "duration": 13 + }, + { + "index": 9, + "duration": 8 + } + ] + }, + { + "name": "DANCING_RIGHT", + "repeat": true, + "frames": [ + { + "index": 10, + "duration": 6 + }, + { + "index": 11, + "duration": 6 + }, + { + "index": 12, + "duration": 6 + }, + { + "index": 13, + "duration": 3 + }, + { + "index": 14, + "duration": 6 + } + ] + }, + { + "name": "DANCING_LEFT", + "repeat": true, + "frames": [ + { + "index": 15, + "duration": 6 + }, + { + "index": 16, + "duration": 6 + }, + { + "index": 17, + "duration": 6 + }, + { + "index": 18, + "duration": 3 + }, + { + "index": 19, + "duration": 6 + } + ] + }, + { + "name": "WALKING_RIGHT", + "repeat": true, + "frames": [ + { + "index": 20, + "duration": 4 + }, + { + "index": 21, + "duration": 6 + }, + { + "index": 22, + "duration": 6 + }, + { + "index": 23, + "duration": 6 + }, + { + "index": 24, + "duration": 4 + } + ] + }, + { + "name": "WALKING_LEFT", + "repeat": true, + "frames": [ + { + "index": 25, + "duration": 4 + }, + { + "index": 26, + "duration": 6 + }, + { + "index": 27, + "duration": 6 + }, + { + "index": 28, + "duration": 6 + }, + { + "index": 29, + "duration": 4 + } + ] + }, + { + "name": "DAMAGE_RIGHT", + "repeat": true, + "frames": [ + { + "index": 30, + "duration": 8 + }, + { + "index": 31, + "duration": 8 + }, + { + "index": 32, + "duration": 8 + }, + { + "index": 33, + "duration": 8 + }, + { + "index": 34, + "duration": 8 + } + ] + }, + { + "name": "DAMAGE_LEFT", + "repeat": true, + "frames": [ + { + "index": 35, + "duration": 8 + }, + { + "index": 36, + "duration": 8 + }, + { + "index": 37, + "duration": 8 + }, + { + "index": 38, + "duration": 8 + }, + { + "index": 39, + "duration": 8 + } + ] + }, + { + "name": "DYING_RIGHT", + "repeat": false, + "next": "DEAD_RIGHT", + "frames": [ + { + "index": 40, + "duration": 8 + }, + { + "index": 41, + "duration": 8 + }, + { + "index": 42, + "duration": 8 + }, + { + "index": 43, + "duration": 8 + }, + { + "index": 44, + "duration": 8 + } + ] + }, + { + "name": "DYING_LEFT", + "repeat": false, + "next": "DEAD_LEFT", + "frames": [ + { + "index": 45, + "duration": 8 + }, + { + "index": 46, + "duration": 8 + }, + { + "index": 47, + "duration": 8 + }, + { + "index": 48, + "duration": 8 + }, + { + "index": 49, + "duration": 8 + } + ] + }, + { + "name": "ATTACK_RIGHT", + "repeat": true, + "frames": [ + { + "index": 50, + "duration": 6 + }, + { + "index": 51, + "duration": 6 + }, + { + "index": 52, + "duration": 6 + }, + { + "index": 53, + "duration": 6 + }, + { + "index": 54, + "duration": 6 + } + ] + }, + { + "name": "ATTACK_LEFT", + "repeat": true, + "frames": [ + { + "index": 55, + "duration": 6 + }, + { + "index": 56, + "duration": 6 + }, + { + "index": 57, + "duration": 6 + }, + { + "index": 58, + "duration": 6 + }, + { + "index": 59, + "duration": 6 + } + ] + }, + { + "name": "DEAD_RIGHT", + "repeat": true, + "frames": [ + { + "index": 60, + "duration": 20 + } + ] + }, + { + "name": "DEAD_LEFT", + "repeat": true, + "frames": [ + { + "index": 61, + "duration": 20 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/greater_seawolf.png b/public/shattered_sword_assets/spritesheets/greater_seawolf.png new file mode 100644 index 0000000..3278ed6 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/greater_seawolf.png differ diff --git a/public/shattered_sword_assets/spritesheets/ogremoch.json b/public/shattered_sword_assets/spritesheets/ogremoch.json new file mode 100644 index 0000000..10436b5 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/ogremoch.json @@ -0,0 +1,271 @@ +{ + "name": "Ogremoch", + "spriteSheetImage": "ogremoch.png", + "spriteWidth": 128, + "spriteHeight": 128, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "columns": 7, + "rows": 10, + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 8 + }, + { + "index": 1, + "duration": 9 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 11 + }, + { + "index": 4, + "duration": 11 + }, + { + "index": 5, + "duration": 10 + }, + { + "index": 6, + "duration": 9 + } + ] + }, + { + "name": "Dancing", + "repeat": true, + "frames": [ + { + "index": 7, + "duration": 6 + }, + { + "index": 8, + "duration": 6 + }, + { + "index": 9, + "duration": 6 + }, + { + "index": 10, + "duration": 6 + }, + { + "index": 11, + "duration": 6 + } + ] + }, + { + "name": "DYING", + "repeat": false, + "next": "DEAD", + "frames": [ + { + "index": 14, + "duration": 6 + }, + { + "index": 15, + "duration": 6 + }, + { + "index": 16, + "duration": 6 + }, + { + "index": 17, + "duration": 6 + }, + { + "index": 18, + "duration": 6 + }, + { + "index": 19, + "duration": 6 + } + ] + }, + { + "name": "DEAD", + "repeat": true, + "frames": [ + { + "index": 21, + "duration": 6 + } + ] + }, + { + "name": "WALK_LEFT", + "repeat": true, + "frames": [ + { + "index": 28, + "duration": 6 + }, + { + "index": 29, + "duration": 6 + }, + { + "index": 30, + "duration": 6 + }, + { + "index": 31, + "duration": 6 + }, + { + "index": 32, + "duration": 6 + } + ] + }, + { + "name": "WALK_RIGHT", + "repeat": true, + "frames": [ + { + "index": 35, + "duration": 6 + }, + { + "index": 36, + "duration": 6 + }, + { + "index": 37, + "duration": 6 + }, + { + "index": 38, + "duration": 6 + }, + { + "index": 39, + "duration": 6 + } + ] + }, + { + "name": "DMG_LEFT", + "repeat": true, + "frames": [ + { + "index": 42, + "duration": 6 + }, + { + "index": 43, + "duration": 6 + }, + { + "index": 44, + "duration": 6 + }, + { + "index": 45, + "duration": 6 + }, + { + "index": 46, + "duration": 6 + } + ] + }, + { + "name": "DMG_RIGHT", + "repeat": true, + "frames": [ + { + "index": 49, + "duration": 6 + }, + { + "index": 50, + "duration": 6 + }, + { + "index": 51, + "duration": 6 + }, + { + "index": 52, + "duration": 6 + }, + { + "index": 53, + "duration": 6 + } + ] + }, + { + "name": "ATK_LEFT", + "repeat": true, + "frames": [ + { + "index": 56, + "duration": 6 + }, + { + "index": 57, + "duration": 6 + }, + { + "index": 58, + "duration": 6 + }, + { + "index": 59, + "duration": 6 + }, + { + "index": 60, + "duration": 6 + } + ] + }, + { + "name": "ATK_RIGHT", + "repeat": true, + "frames": [ + { + "index": 63, + "duration": 6 + }, + { + "index": 64, + "duration": 6 + }, + { + "index": 65, + "duration": 6 + }, + { + "index": 66, + "duration": 3 + }, + { + "index": 67, + "duration": 6 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/ogremoch.png b/public/shattered_sword_assets/spritesheets/ogremoch.png new file mode 100644 index 0000000..d609f3a Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/ogremoch.png differ diff --git a/public/shattered_sword_assets/spritesheets/remus_werewolf.json b/public/shattered_sword_assets/spritesheets/remus_werewolf.json new file mode 100644 index 0000000..807635b --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/remus_werewolf.json @@ -0,0 +1 @@ +{"name":"remus_werewolf","spriteSheetImage":"remus_werewolf.png","spriteWidth":204,"spriteHeight":183,"leftBuffer":0,"rightBuffer":0,"topBuffer":0,"bottomBuffer":0,"columns":8,"rows":5,"animations":[{"name":"WALK_RIGHT","repeat":true,"frames":[{"index":8,"duration":1},{"index":9,"duration":2},{"index":10,"duration":3},{"index":9,"duration":4},{"index":8,"duration":5}]},{"name":"WALK_LEFT","repeat":true,"frames":[{"index":13,"duration":1},{"index":12,"duration":2},{"index":11,"duration":3},{"index":12,"duration":4},{"index":13,"duration":5}]},{"name":"IDLE_RIGHT","repeat":true,"frames":[{"index":0,"duration":1},{"index":1,"duration":2}]},{"name":"IDLE_LEFT","repeat":true,"frames":[{"index":2,"duration":1},{"index":3,"duration":2}]},{"name":"DANCE","repeat":true,"frames":[{"index":24,"duration":1},{"index":25,"duration":2},{"index":27,"duration":2},{"index":26,"duration":2}]},{"name":"ATTACK_RIGHT","repeat":false,"next":"IDLE_RIGHT","frames":[{"index":16,"duration":2},{"index":17,"duration":2},{"index":18,"duration":2}]},{"name":"ATTACK_LEFT","repeat":false,"next":"IDLE_LEFT","frames":[{"index":21,"duration":2},{"index":20,"duration":2},{"index":19,"duration":2}]},{"name":"DYING","repeat":false,"next":"DEAD","frames":[{"index":32,"duration":2},{"index":33,"duration":2},{"index":34,"duration":2}]},{"name":"DEAD","repeat":true,"frames":[{"index":34,"duration":2}]}]} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/remus_werewolf.png b/public/shattered_sword_assets/spritesheets/remus_werewolf.png new file mode 100644 index 0000000..cc9ca34 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/remus_werewolf.png differ diff --git a/public/shattered_sword_assets2/spritesheets/slice.json b/public/shattered_sword_assets/spritesheets/slice.json similarity index 90% rename from public/shattered_sword_assets2/spritesheets/slice.json rename to public/shattered_sword_assets/spritesheets/slice.json index 4f68387..3862151 100644 --- a/public/shattered_sword_assets2/spritesheets/slice.json +++ b/public/shattered_sword_assets/spritesheets/slice.json @@ -1,6 +1,6 @@ { "name": "slice", - "spriteSheetImage": "slice.png", + "spriteSheetImage": "slice_black.png", "spriteWidth": 16, "spriteHeight": 16, "columns": 4, diff --git a/public/shattered_sword_assets/spritesheets/slice.png b/public/shattered_sword_assets/spritesheets/slice.png new file mode 100644 index 0000000..8c0e5ec Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/slice.png differ diff --git a/public/shattered_sword_assets/spritesheets/slice_black.png b/public/shattered_sword_assets/spritesheets/slice_black.png new file mode 100644 index 0000000..5e912d5 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/slice_black.png differ diff --git a/public/shattered_sword_assets/spritesheets/slice_red.png b/public/shattered_sword_assets/spritesheets/slice_red.png new file mode 100644 index 0000000..8683d79 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/slice_red.png differ diff --git a/public/shattered_sword_assets2/spritesheets/test_dummy.json b/public/shattered_sword_assets/spritesheets/test_dummy.json similarity index 100% rename from public/shattered_sword_assets2/spritesheets/test_dummy.json rename to public/shattered_sword_assets/spritesheets/test_dummy.json diff --git a/public/shattered_sword_assets2/spritesheets/test_dummy.png b/public/shattered_sword_assets/spritesheets/test_dummy.png similarity index 100% rename from public/shattered_sword_assets2/spritesheets/test_dummy.png rename to public/shattered_sword_assets/spritesheets/test_dummy.png diff --git a/public/shattered_sword_assets/spritesheets/xvart.json b/public/shattered_sword_assets/spritesheets/xvart.json new file mode 100644 index 0000000..1359be5 --- /dev/null +++ b/public/shattered_sword_assets/spritesheets/xvart.json @@ -0,0 +1,326 @@ +{ + "name": "Xvart", + "spriteSheetImage": "xvart.png", + "spriteWidth": 128, + "spriteHeight": 128, + "leftBuffer": 0, + "rightBuffer": 0, + "topBuffer": 0, + "bottomBuffer": 0, + "columns": 8, + "rows": 10, + "animations": [ + { + "name": "IDLE", + "repeat": true, + "frames": [ + { + "index": 0, + "duration": 10 + }, + { + "index": 1, + "duration": 10 + }, + { + "index": 2, + "duration": 10 + }, + { + "index": 3, + "duration": 10 + }, + { + "index": 4, + "duration": 10 + }, + { + "index": 5, + "duration": 10 + } + ] + }, + { + "name": "WALK RIGHT", + "repeat": true, + "frames": [ + { + "index": 8, + "duration": 6 + }, + { + "index": 9, + "duration": 6 + }, + { + "index": 10, + "duration": 6 + }, + { + "index": 11, + "duration": 6 + }, + { + "index": 12, + "duration": 6 + }, + { + "index": 13, + "duration": 6 + }, + { + "index": 14, + "duration": 6 + }, + { + "index": 15, + "duration": 6 + } + ] + }, + { + "name": "WALK LEFT", + "repeat": true, + "frames": [ + { + "index": 16, + "duration": 6 + }, + { + "index": 17, + "duration": 6 + }, + { + "index": 18, + "duration": 6 + }, + { + "index": 19, + "duration": 6 + }, + { + "index": 20, + "duration": 6 + }, + { + "index": 21, + "duration": 6 + }, + { + "index": 22, + "duration": 6 + }, + { + "index": 23, + "duration": 6 + } + ] + }, + { + "name": "ATTACK RIGHT", + "repeat": true, + "frames": [ + { + "index": 24, + "duration": 4 + }, + { + "index": 25, + "duration": 4 + }, + { + "index": 26, + "duration": 4 + }, + { + "index": 27, + "duration": 4 + }, + { + "index": 28, + "duration": 4 + }, + { + "index": 29, + "duration": 4 + } + ] + }, + { + "name": "ATTACK LEFT", + "repeat": true, + "frames": [ + { + "index": 32, + "duration": 4 + }, + { + "index": 33, + "duration": 4 + }, + { + "index": 34, + "duration": 4 + }, + { + "index": 35, + "duration": 4 + }, + { + "index": 36, + "duration": 4 + }, + { + "index": 37, + "duration": 4 + } + ] + }, + { + "name": "TAKING DAMAGE RIGHT", + "repeat": true, + "frames": [ + { + "index": 40, + "duration": 5 + }, + { + "index": 41, + "duration": 5 + }, + { + "index": 42, + "duration": 5 + }, + { + "index": 43, + "duration": 5 + }, + { + "index": 44, + "duration": 5 + }, + { + "index": 45, + "duration": 5 + } + ] + }, + { + "name": "TAKING DAMAGE LEFT", + "repeat": true, + "frames": [ + { + "index": 48, + "duration": 5 + }, + { + "index": 49, + "duration": 5 + }, + { + "index": 50, + "duration": 5 + }, + { + "index": 51, + "duration": 5 + }, + { + "index": 52, + "duration": 5 + }, + { + "index": 53, + "duration": 5 + } + ] + }, + { + "name": "DYING", + "repeat": true, + "frames": [ + { + "index": 56, + "duration": 5 + }, + { + "index": 57, + "duration": 5 + }, + { + "index": 58, + "duration": 5 + }, + { + "index": 59, + "duration": 5 + }, + { + "index": 60, + "duration": 5 + }, + { + "index": 61, + "duration": 5 + }, + { + "index": 62, + "duration": 5 + }, + { + "index": 63, + "duration": 5 + } + ] + }, + { + "name": "DEAD", + "repeat": true, + "frames": [ + { + "index": 64, + "duration": 20 + } + ] + }, + { + "name": "DANCING", + "repeat": true, + "frames": [ + { + "index": 72, + "duration": 5 + }, + { + "index": 73, + "duration": 5 + }, + { + "index": 74, + "duration": 5 + }, + { + "index": 75, + "duration": 5 + }, + { + "index": 76, + "duration": 5 + }, + { + "index": 77, + "duration": 5 + }, + { + "index": 78, + "duration": 5 + }, + { + "index": 79, + "duration": 5 + } + ] + } + ] +} \ No newline at end of file diff --git a/public/shattered_sword_assets/spritesheets/xvart.png b/public/shattered_sword_assets/spritesheets/xvart.png new file mode 100644 index 0000000..381dc35 Binary files /dev/null and b/public/shattered_sword_assets/spritesheets/xvart.png differ diff --git a/public/shattered_sword_assets2/tilemaps/Tutorial.json b/public/shattered_sword_assets/tilemaps/Tutorial.json similarity index 100% rename from public/shattered_sword_assets2/tilemaps/Tutorial.json rename to public/shattered_sword_assets/tilemaps/Tutorial.json diff --git a/public/shattered_sword_assets2/tilemaps/bamboo_forest.tsx b/public/shattered_sword_assets/tilemaps/bamboo_forest.tsx similarity index 100% rename from public/shattered_sword_assets2/tilemaps/bamboo_forest.tsx rename to public/shattered_sword_assets/tilemaps/bamboo_forest.tsx diff --git a/public/shattered_sword_assets2/tilemaps/forest1.json b/public/shattered_sword_assets/tilemaps/forest1.json similarity index 100% rename from public/shattered_sword_assets2/tilemaps/forest1.json rename to public/shattered_sword_assets/tilemaps/forest1.json diff --git a/public/shattered_sword_assets2/tilemaps/forest1.png b/public/shattered_sword_assets/tilemaps/forest1.png similarity index 100% rename from public/shattered_sword_assets2/tilemaps/forest1.png rename to public/shattered_sword_assets/tilemaps/forest1.png diff --git a/public/shattered_sword_assets2/tilemaps/forest_tileset.png b/public/shattered_sword_assets/tilemaps/forest_tileset.png similarity index 100% rename from public/shattered_sword_assets2/tilemaps/forest_tileset.png rename to public/shattered_sword_assets/tilemaps/forest_tileset.png diff --git a/public/shattered_sword_assets/tilemaps/greatwall_tileset.png b/public/shattered_sword_assets/tilemaps/greatwall_tileset.png new file mode 100644 index 0000000..23152ec Binary files /dev/null and b/public/shattered_sword_assets/tilemaps/greatwall_tileset.png differ diff --git a/public/shattered_sword_assets/tilemaps/porcelain_tileset.png b/public/shattered_sword_assets/tilemaps/porcelain_tileset.png new file mode 100644 index 0000000..43878bd Binary files /dev/null and b/public/shattered_sword_assets/tilemaps/porcelain_tileset.png differ diff --git a/public/shattered_sword_assets2/sounds/test.mp3 b/public/shattered_sword_assets2/sounds/test.mp3 deleted file mode 100644 index 695c58d..0000000 Binary files a/public/shattered_sword_assets2/sounds/test.mp3 and /dev/null differ diff --git a/public/shattered_sword_assets2/spritesheets/Hiro.png b/public/shattered_sword_assets2/spritesheets/Hiro.png deleted file mode 100644 index 7b20265..0000000 Binary files a/public/shattered_sword_assets2/spritesheets/Hiro.png and /dev/null differ diff --git a/public/shattered_sword_assets2/spritesheets/Hiro1.json b/public/shattered_sword_assets2/spritesheets/Hiro1.json deleted file mode 100644 index f593278..0000000 --- a/public/shattered_sword_assets2/spritesheets/Hiro1.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "Hiro", - "spriteSheetImage": "Hiro.png", - "spriteWidth": 32, - "spriteHeight": 32, - "columns": 1, - "rows": 1, - "durationType": "time", - "animations": [ - { - "name": "IDLE", - "frames": [ {"index": 0, "duration": 540} ] - }, - { - "name": "JUMP", - "frames":[ {"index": 0, "duration": 32}] - }, - { - "name": "WALK", - "frames": [ {"index": 0, "duration": 540} ] - }, - { - "name": "FALL", - "frames": [ {"index": 0, "duration": 540} ] - } - ] -} \ No newline at end of file diff --git a/public/shattered_sword_assets2/spritesheets/Hiro1.png b/public/shattered_sword_assets2/spritesheets/Hiro1.png deleted file mode 100644 index 729338f..0000000 Binary files a/public/shattered_sword_assets2/spritesheets/Hiro1.png and /dev/null differ diff --git a/public/shattered_sword_assets2/spritesheets/Snake.json b/public/shattered_sword_assets2/spritesheets/Snake.json deleted file mode 100644 index ebedb68..0000000 --- a/public/shattered_sword_assets2/spritesheets/Snake.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "name" : "Snake", - "spriteSheetImage": "snake.png", - "spriteWidth": 160, - "spriteHeight": 128, - "columns": 5, - "rows": 4, - "durationType": "time", - "animations": [ - { - "name": "IDLE", - "repeat": true, - "frames": [ - { - "index": 0, - "duration": 150 - }, - { - "index": 1, - "duration": 150 - }, - { - "index": 2, - "duration": 150 - }, - { - "index": 3, - "duration": 100 - }, - { - "index": 4, - "duration": 100 - }, - { - "index": 3, - "duration": 100 - }, - { - "index": 4, - "duration": 100 - }, - { - "index": 3, - "duration": 100 - }, - { - "index": 2, - "duration": 150 - }, - { - "index": 1, - "duration": 150 - } - ] - }, - { - "name": "ATTACK", - "repeat": true, - "frames": [ - { - "index": 0, - "duration": 150 - }, - { - "index": 5, - "duration": 100 - }, - { - "index": 6, - "duration": 100 - }, - { - "index": 7, - "duration": 100 - }, - { - "index": 8, - "duration": 100 - }, - { - "index": 9, - "duration": 100 - }, - { - "index": 10, - "duration": 100 - }, - { - "index": 11, - "duration": 150 - } - - ] - }, - { - "name": "DYING", - "repeat": false, - "frames": [ - { - "index": 0, - "duration": 150 - }, - { - "index": 12, - "duration": 100 - }, - { - "index": 13, - "duration": 100 - }, - { - "index": 14, - "duration": 100 - }, - { - "index": 15, - "duration": 150 - }, - { - "index": 16, - "duration": 150 - }, - { - "index": 17, - "duration": 150 - }, - { - "index": 18, - "duration": 150 - } - ] - }, - { - "name": "DEAD", - "repeat": true, - "frames": [ - { - "index": 18, - "duration": 150 - } - ] - } - ] -} diff --git a/public/shattered_sword_assets2/spritesheets/Snake.png b/public/shattered_sword_assets2/spritesheets/Snake.png deleted file mode 100644 index cd19808..0000000 Binary files a/public/shattered_sword_assets2/spritesheets/Snake.png and /dev/null differ diff --git a/public/shattered_sword_assets2/spritesheets/Tiger.json b/public/shattered_sword_assets2/spritesheets/Tiger.json deleted file mode 100644 index 8077233..0000000 --- a/public/shattered_sword_assets2/spritesheets/Tiger.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name" : "Tiger", - "spriteSheetImage": "tiger.png", - "spriteWidth": 192, - "spriteHeight": 192, - "columns": 3, - "rows": 3, - "durationType": "time", - "animations": [ - { - "name": "IDLE", - "repeat": true, - "frames": [ - { - "index": 0, - "duration": 150 - } - - ] - }, - { - "name": "WALK_RIGHT", - "repeat": true, - "frames": [ - { - "index": 1, - "duration": 150 - }, - { - "index": 2, - "duration": 150 - }, - { - "index": 3, - "duration": 150 - }, - { - "index": 4, - "duration": 150 - } - ] - }, - { - "name": "WALK_LEFT", - "repeat": true, - "frames": [ - { - "index": 5, - "duration": 150 - }, - { - "index": 6, - "duration": 150 - }, - { - "index": 7, - "duration": 150 - }, - { - "index": 8, - "duration": 150 - } - ] - } - ] -} diff --git a/public/shattered_sword_assets2/spritesheets/Tiger.png b/public/shattered_sword_assets2/spritesheets/Tiger.png deleted file mode 100644 index 4567024..0000000 Binary files a/public/shattered_sword_assets2/spritesheets/Tiger.png and /dev/null differ diff --git a/public/shattered_sword_assets2/spritesheets/slice.png b/public/shattered_sword_assets2/spritesheets/slice.png deleted file mode 100644 index 5308b53..0000000 Binary files a/public/shattered_sword_assets2/spritesheets/slice.png and /dev/null differ