(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.MidiPlayer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 100) throw "Percent must be number between 1 and 100."; this.skipToTick(Math.round(percent / 100 * this.totalTicks)); return this; } /** * Skips player pointer to specified seconds. * @param {number} - Seconds to skip to. * @return {Player} */ }, { key: "skipToSeconds", value: function skipToSeconds(seconds) { var songTime = this.getSongTime(); if (seconds < 0 || seconds > songTime) throw seconds + " seconds not within song time of " + songTime; this.skipToPercent(seconds / songTime * 100); return this; } /** * Checks if player is playing * @return {boolean} */ }, { key: "isPlaying", value: function isPlaying() { return this.setIntervalId > 0 || _typeof(this.setIntervalId) === 'object'; } /** * Plays the loaded MIDI file without regard for timing and saves events in this.events. Essentially used as a parser. * @return {Player} */ }, { key: "dryRun", value: function dryRun() { // Reset tracks first this.resetTracks(); while (!this.endOfFile()) { this.playLoop(true); }this.events = this.getEvents(); this.totalEvents = this.getTotalEvents(); this.totalTicks = this.getTotalTicks(); this.startTick = 0; this.startTime = 0; // Leave tracks in pristine condish this.resetTracks(); //console.log('Song time: ' + this.getSongTime() + ' seconds / ' + this.totalTicks + ' ticks.'); this.triggerPlayerEvent('fileLoaded', this); return this; } /** * Resets play pointers for all tracks. * @return {Player} */ }, { key: "resetTracks", value: function resetTracks() { this.tracks.forEach(function (track) { return track.reset(); }); return this; } /** * Gets an array of events grouped by track. * @return {array} */ }, { key: "getEvents", value: function getEvents() { return this.tracks.map(function (track) { return track.events; }); } /** * Gets total number of ticks in the loaded MIDI file. * @return {number} */ }, { key: "getTotalTicks", value: function getTotalTicks() { return Math.max.apply(null, this.tracks.map(function (track) { return track.delta; })); } /** * Gets total number of events in the loaded MIDI file. * @return {number} */ }, { key: "getTotalEvents", value: function getTotalEvents() { return this.tracks.reduce(function (a, b) { return { events: { length: a.events.length + b.events.length } }; }, { events: { length: 0 } }).events.length; } /** * Gets song duration in seconds. * @return {number} */ }, { key: "getSongTime", value: function getSongTime() { return this.totalTicks / this.division / this.tempo * 60; } /** * Gets remaining number of seconds in playback. * @return {number} */ }, { key: "getSongTimeRemaining", value: function getSongTimeRemaining() { return Math.round((this.totalTicks - this.tick) / this.division / this.tempo * 60); } /** * Gets remaining percent of playback. * @return {number} */ }, { key: "getSongPercentRemaining", value: function getSongPercentRemaining() { return Math.round(this.getSongTimeRemaining() / this.getSongTime() * 100); } /** * Number of bytes processed in the loaded MIDI file. * @return {number} */ }, { key: "bytesProcessed", value: function bytesProcessed() { // Currently assume header chunk is strictly 14 bytes return 14 + this.tracks.length * 8 + this.tracks.reduce(function (a, b) { return { pointer: a.pointer + b.pointer }; }, { pointer: 0 }).pointer; } /** * Number of events played up to this point. * @return {number} */ }, { key: "eventsPlayed", value: function eventsPlayed() { return this.tracks.reduce(function (a, b) { return { eventIndex: a.eventIndex + b.eventIndex }; }, { eventIndex: 0 }).eventIndex; } /** * Determines if the player pointer has reached the end of the loaded MIDI file. * Used in two ways: * 1. If playing result is based on loaded JSON events. * 2. If parsing (dryRun) it's based on the actual buffer length vs bytes processed. * @return {boolean} */ }, { key: "endOfFile", value: function endOfFile() { if (this.isPlaying()) { return this.eventsPlayed() == this.totalEvents; } return this.bytesProcessed() == this.buffer.length; } /** * Gets the current tick number in playback. * @return {number} */ }, { key: "getCurrentTick", value: function getCurrentTick() { return Math.round((new Date().getTime() - this.startTime) / 1000 * (this.division * (this.tempo / 60))) + this.startTick; } /** * Sends MIDI event out to listener. * @param {object} * @return {Player} */ }, { key: "emitEvent", value: function emitEvent(event) { this.triggerPlayerEvent('midiEvent', event); return this; } /** * Subscribes events to listeners * @param {string} - Name of event to subscribe to. * @param {function} - Callback to fire when event is broadcast. * @return {Player} */ }, { key: "on", value: function on(playerEvent, fn) { if (!this.eventListeners.hasOwnProperty(playerEvent)) this.eventListeners[playerEvent] = []; this.eventListeners[playerEvent].push(fn); return this; } /** * Broadcasts event to trigger subscribed callbacks. * @param {string} - Name of event. * @param {object} - Data to be passed to subscriber callback. * @return {Player} */ }, { key: "triggerPlayerEvent", value: function triggerPlayerEvent(playerEvent, data) { if (this.eventListeners.hasOwnProperty(playerEvent)) this.eventListeners[playerEvent].forEach(function (fn) { return fn(data || {}); }); return this; } }]); return Player; }(); exports.Player = Player; },{"./track":4,"./utils":5,"fs":undefined}],4:[function(require,module,exports){ "use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Constants = require("./constants").Constants; var Utils = require("./utils").Utils; /** * Class representing a track. Contains methods for parsing events and keeping track of pointer. */ var Track = function () { function Track(index, data) { _classCallCheck(this, Track); this.enabled = true; this.eventIndex = 0; this.pointer = 0; this.lastTick = 0; this.lastStatus = null; this.index = index; this.data = data; this.delta = 0; this.runningDelta = 0; this.events = []; } /** * Resets all stateful track informaion used during playback. * @return {Track} */ _createClass(Track, [{ key: "reset", value: function reset() { this.enabled = true; this.eventIndex = 0; this.pointer = 0; this.lastTick = 0; this.lastStatus = null; this.delta = 0; this.runningDelta = 0; return this; } /** * Sets this track to be enabled during playback. * @return {Track} */ }, { key: "enable", value: function enable() { this.enabled = true; return this; } /** * Sets this track to be disabled during playback. * @return {Track} */ }, { key: "disable", value: function disable() { this.enabled = false; return this; } /** * Sets the track event index to the nearest event to the given tick. * @param {number} tick * @return {Track} */ }, { key: "setEventIndexByTick", value: function setEventIndexByTick(tick) { tick = tick || 0; for (var i in this.events) { if (this.events[i].tick >= tick) { this.eventIndex = i; return this; } } } /** * Gets byte located at pointer position. * @return {number} */ }, { key: "getCurrentByte", value: function getCurrentByte() { return this.data[this.pointer]; } /** * Gets count of delta bytes and current pointer position. * @return {number} */ }, { key: "getDeltaByteCount", value: function getDeltaByteCount() { // Get byte count of delta VLV // http://www.ccarh.org/courses/253/handout/vlv/ // If byte is greater or equal to 80h (128 decimal) then the next byte // is also part of the VLV, // else byte is the last byte in a VLV. var currentByte = this.getCurrentByte(); var byteCount = 1; while (currentByte >= 128) { currentByte = this.data[this.pointer + byteCount]; byteCount++; } return byteCount; } /** * Get delta value at current pointer position. * @return {number} */ }, { key: "getDelta", value: function getDelta() { return Utils.readVarInt(this.data.subarray(this.pointer, this.pointer + this.getDeltaByteCount())); } /** * Handles event within a given track starting at specified index * @param {number} currentTick * @param {boolean} dryRun - If true events will be parsed and returned regardless of time. */ }, { key: "handleEvent", value: function handleEvent(currentTick, dryRun) { dryRun = dryRun || false; if (dryRun) { var elapsedTicks = currentTick - this.lastTick; var delta = this.getDelta(); var eventReady = elapsedTicks >= delta; if (this.pointer < this.data.length && (dryRun || eventReady)) { var _event = this.parseEvent(); if (this.enabled) return _event; // Recursively call this function for each event ahead that has 0 delta time? } } else { // Let's actually play the MIDI from the generated JSON events created by the dry run. if (this.events[this.eventIndex] && this.events[this.eventIndex].tick <= currentTick) { this.eventIndex++; if (this.enabled) return this.events[this.eventIndex - 1]; } } return null; } /** * Get string data from event. * @param {number} eventStartIndex * @return {string} */ }, { key: "getStringData", value: function getStringData(eventStartIndex) { var currentByte = this.pointer; var byteCount = 1; var length = Utils.readVarInt(this.data.subarray(eventStartIndex + 2, eventStartIndex + 2 + byteCount)); var stringLength = length; return Utils.bytesToLetters(this.data.subarray(eventStartIndex + byteCount + 2, eventStartIndex + byteCount + length + 2)); } /** * Parses event into JSON and advances pointer for the track * @return {object} */ }, { key: "parseEvent", value: function parseEvent() { var eventStartIndex = this.pointer + this.getDeltaByteCount(); var eventJson = {}; var deltaByteCount = this.getDeltaByteCount(); eventJson.track = this.index + 1; eventJson.delta = this.getDelta(); this.lastTick = this.lastTick + eventJson.delta; this.runningDelta += eventJson.delta; eventJson.tick = this.runningDelta; eventJson.byteIndex = this.pointer; //eventJson.raw = event; if (this.data[eventStartIndex] == 0xff) { // Meta Event // If this is a meta event we should emit the data and immediately move to the next event // otherwise if we let it run through the next cycle a slight delay will accumulate if multiple tracks // are being played simultaneously switch (this.data[eventStartIndex + 1]) { case 0x00: // Sequence Number eventJson.name = 'Sequence Number'; break; case 0x01: // Text Event eventJson.name = 'Text Event'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x02: // Copyright Notice eventJson.name = 'Copyright Notice'; break; case 0x03: // Sequence/Track Name eventJson.name = 'Sequence/Track Name'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x04: // Instrument Name eventJson.name = 'Instrument Name'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x05: // Lyric eventJson.name = 'Lyric'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x06: // Marker eventJson.name = 'Marker'; break; case 0x07: // Cue Point eventJson.name = 'Cue Point'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x09: // Device Name eventJson.name = 'Device Name'; eventJson.string = this.getStringData(eventStartIndex); break; case 0x20: // MIDI Channel Prefix eventJson.name = 'MIDI Channel Prefix'; break; case 0x21: // MIDI Port eventJson.name = 'MIDI Port'; eventJson.data = Utils.bytesToNumber([this.data[eventStartIndex + 3]]); break; case 0x2F: // End of Track eventJson.name = 'End of Track'; break; case 0x51: // Set Tempo eventJson.name = 'Set Tempo'; eventJson.data = Math.round(60000000 / Utils.bytesToNumber(this.data.subarray(eventStartIndex + 3, eventStartIndex + 6))); this.tempo = eventJson.data; break; case 0x54: // SMTPE Offset eventJson.name = 'SMTPE Offset'; break; case 0x58: // Time Signature eventJson.name = 'Time Signature'; break; case 0x59: // Key Signature eventJson.name = 'Key Signature'; break; case 0x7F: // Sequencer-Specific Meta-event eventJson.name = 'Sequencer-Specific Meta-event'; break; default: eventJson.name = 'Unknown: ' + this.data[eventStartIndex + 1].toString(16); break; } var length = this.data[this.pointer + deltaByteCount + 2]; // Some meta events will have vlv that needs to be handled this.pointer += deltaByteCount + 3 + length; } else if (this.data[eventStartIndex] == 0xf0) { // Sysex eventJson.name = 'Sysex'; var length = this.data[this.pointer + deltaByteCount + 1]; this.pointer += deltaByteCount + 2 + length; } else { // Voice event if (this.data[eventStartIndex] < 0x80) { // Running status eventJson.running = true; eventJson.noteNumber = this.data[eventStartIndex]; eventJson.noteName = Constants.NOTES[this.data[eventStartIndex]]; eventJson.velocity = this.data[eventStartIndex + 1]; if (this.lastStatus <= 0x8f) { eventJson.name = 'Note off'; eventJson.channel = this.lastStatus - 0x80 + 1; } else if (this.lastStatus <= 0x9f) { eventJson.name = 'Note on'; eventJson.channel = this.lastStatus - 0x90 + 1; } this.pointer += deltaByteCount + 2; } else { this.lastStatus = this.data[eventStartIndex]; if (this.data[eventStartIndex] <= 0x8f) { // Note off eventJson.name = 'Note off'; eventJson.channel = this.lastStatus - 0x80 + 1; eventJson.noteNumber = this.data[eventStartIndex + 1]; eventJson.noteName = Constants.NOTES[this.data[eventStartIndex + 1]]; eventJson.velocity = Math.round(this.data[eventStartIndex + 2] / 127 * 100); this.pointer += deltaByteCount + 3; } else if (this.data[eventStartIndex] <= 0x9f) { // Note on eventJson.name = 'Note on'; eventJson.channel = this.lastStatus - 0x90 + 1; eventJson.noteNumber = this.data[eventStartIndex + 1]; eventJson.noteName = Constants.NOTES[this.data[eventStartIndex + 1]]; eventJson.velocity = Math.round(this.data[eventStartIndex + 2] / 127 * 100); this.pointer += deltaByteCount + 3; } else if (this.data[eventStartIndex] <= 0xaf) { // Polyphonic Key Pressure eventJson.name = 'Polyphonic Key Pressure'; eventJson.channel = this.lastStatus - 0xa0 + 1; eventJson.note = Constants.NOTES[this.data[eventStartIndex + 1]]; eventJson.pressure = event[2]; this.pointer += deltaByteCount + 3; } else if (this.data[eventStartIndex] <= 0xbf) { // Controller Change eventJson.name = 'Controller Change'; eventJson.channel = this.lastStatus - 0xb0 + 1; eventJson.number = this.data[eventStartIndex + 1]; eventJson.value = this.data[eventStartIndex + 2]; this.pointer += deltaByteCount + 3; } else if (this.data[eventStartIndex] <= 0xcf) { // Program Change eventJson.name = 'Program Change'; eventJson.channel = this.lastStatus - 0xc0 + 1; eventJson.value = this.data[eventStartIndex + 1]; this.pointer += deltaByteCount + 2; } else if (this.data[eventStartIndex] <= 0xdf) { // Channel Key Pressure eventJson.name = 'Channel Key Pressure'; eventJson.channel = this.lastStatus - 0xd0 + 1; this.pointer += deltaByteCount + 2; } else if (this.data[eventStartIndex] <= 0xef) { // Pitch Bend eventJson.name = 'Pitch Bend'; eventJson.channel = this.lastStatus - 0xe0 + 1; this.pointer += deltaByteCount + 3; } else { eventJson.name = 'Unknown. Pointer: ' + this.pointer.toString() + ' ' + eventStartIndex.toString() + ' ' + this.data.length; } } } this.delta += eventJson.delta; this.events.push(eventJson); return eventJson; } /** * Returns true if pointer has reached the end of the track. * @param {boolean} */ }, { key: "endOfTrack", value: function endOfTrack() { if (this.data[this.pointer + 1] == 0xff && this.data[this.pointer + 2] == 0x2f && this.data[this.pointer + 3] == 0x00) { return true; } return false; } }]); return Track; }(); module.exports.Track = Track; },{"./constants":1,"./utils":5}],5:[function(require,module,exports){ (function (Buffer){ 'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Contains misc static utility methods. */ var Utils = function () { function Utils() { _classCallCheck(this, Utils); } _createClass(Utils, null, [{ key: 'byteToHex', /** * Converts a single byte to a hex string. * @param {number} byte * @return {string} */ value: function byteToHex(byte) { // Ensure hex string always has two chars return ('0' + byte.toString(16)).slice(-2); } /** * Converts an array of bytes to a hex string. * @param {array} byteArray * @return {string} */ }, { key: 'bytesToHex', value: function bytesToHex(byteArray) { var hex = []; byteArray.forEach(function (byte) { return hex.push(Utils.byteToHex(byte)); }); return hex.join(''); } /** * Converts a hex string to a number. * @param {string} hexString * @return {number} */ }, { key: 'hexToNumber', value: function hexToNumber(hexString) { return parseInt(hexString, 16); } /** * Converts an array of bytes to a number. * @param {array} byteArray * @return {number} */ }, { key: 'bytesToNumber', value: function bytesToNumber(byteArray) { return Utils.hexToNumber(Utils.bytesToHex(byteArray)); } /** * Converts an array of bytes to letters. * @param {array} byteArray * @return {string} */ }, { key: 'bytesToLetters', value: function bytesToLetters(byteArray) { var letters = []; byteArray.forEach(function (byte) { return letters.push(String.fromCharCode(byte)); }); return letters.join(''); } /** * Converts a decimal to it's binary representation. * @param {number} dec * @return {string} */ }, { key: 'decToBinary', value: function decToBinary(dec) { return (dec >>> 0).toString(2); } /** * Reads a variable length value. * @param {array} byteArray * @return {number} */ }, { key: 'readVarInt', value: function readVarInt(byteArray) { var result = 0; byteArray.forEach(function (number) { var b = number; if (b & 0x80) { result += b & 0x7f; result <<= 7; } else { /* b is the last byte */ result += b; } }); return result; } /** * Decodes base-64 encoded string * @param {string} string * @return {string} */ }, { key: 'atob', value: function (_atob) { function atob(_x) { return _atob.apply(this, arguments); } atob.toString = function () { return _atob.toString(); }; return atob; }(function (string) { if (typeof atob === 'function') return atob(string); return new Buffer(string, 'base64').toString('binary'); }) }]); return Utils; }(); exports.Utils = Utils; }).call(this,require("buffer").Buffer) },{"buffer":undefined}]},{},[2])(2) }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmNcXGNvbnN0YW50cy5qcyIsInNyY1xcaW5kZXguanMiLCJzcmNcXHBsYXllci5qcyIsInNyY1xcdHJhY2suanMiLCJzcmNcXHNyY1xcdXRpbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztBQ0FBOzs7QUFHQSxJQUFJLFlBQVk7QUFDZixVQUFTLE9BRE07QUFFZixRQUFPO0FBRlEsQ0FBaEI7O0FBS0EsQ0FBQyxZQUFXO0FBQ1g7QUFDQSxLQUFJLFdBQVcsQ0FBQyxDQUFDLEdBQUQsQ0FBRCxFQUFRLENBQUMsSUFBRCxFQUFNLElBQU4sQ0FBUixFQUFxQixDQUFDLEdBQUQsQ0FBckIsRUFBNEIsQ0FBQyxJQUFELEVBQU0sSUFBTixDQUE1QixFQUF5QyxDQUFDLEdBQUQsQ0FBekMsRUFBK0MsQ0FBQyxHQUFELENBQS9DLEVBQXNELENBQUMsSUFBRCxFQUFNLElBQU4sQ0FBdEQsRUFBbUUsQ0FBQyxHQUFELENBQW5FLEVBQTBFLENBQUMsSUFBRCxFQUFNLElBQU4sQ0FBMUUsRUFBdUYsQ0FBQyxHQUFELENBQXZGLEVBQThGLENBQUMsSUFBRCxFQUFNLElBQU4sQ0FBOUYsRUFBMkcsQ0FBQyxHQUFELENBQTNHLENBQWY7QUFDQSxLQUFJLFVBQVUsQ0FBZDs7QUFFQTs7QUFMVyw0QkFNRixDQU5FO0FBT1YsV0FBUyxPQUFULENBQWlCLHFCQUFhO0FBQzdCLGFBQVUsT0FBVixDQUFrQjtBQUFBLFdBQVEsVUFBVSxLQUFWLENBQWdCLE9BQWhCLElBQTJCLE9BQU8sQ0FBMUM7QUFBQSxJQUFsQjtBQUNBO0FBQ0EsR0FIRDtBQVBVOztBQU1YLE1BQUssSUFBSSxJQUFJLENBQUMsQ0FBZCxFQUFpQixLQUFLLENBQXRCLEVBQXlCLEdBQXpCLEVBQThCO0FBQUEsUUFBckIsQ0FBcUI7QUFLN0I7QUFDRCxDQVpEOztBQWNBLFFBQVEsU0FBUixHQUFvQixTQUFwQjs7Ozs7QUN0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QUFxQixDQUFyQixDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7OzZCQUtrQixTLEVBQVc7QUFDNUIsT0FBSSxTQUFTLENBQWI7QUFDQSxhQUFVLE9BQVYsQ0FBa0Isa0JBQVU7QUFDM0IsUUFBSSxJQUFJLE1BQVI7QUFDQSxRQUFJLElBQUksSUFBUixFQUFjO0FBQ2IsZUFBVyxJQUFJLElBQWY7QUFDQSxnQkFBVyxDQUFYO0FBQ0EsS0FIRCxNQUdPO0FBQ047QUFDQSxlQUFVLENBQVY7QUFDQTtBQUNELElBVEQ7O0FBV0EsVUFBTyxNQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OztjQUtZLE0sRUFBUTtBQUNuQixPQUFJLE9BQU8sSUFBUCxLQUFnQixVQUFwQixFQUFnQyxPQUFPLEtBQUssTUFBTCxDQUFQO0FBQ2hDLFVBQU8sSUFBSSxNQUFKLENBQVcsTUFBWCxFQUFtQixRQUFuQixFQUE2QixRQUE3QixDQUFzQyxRQUF0QyxDQUFQO0FBQ0EsRzs7Ozs7O0FBR0YsUUFBUSxLQUFSLEdBQWdCLEtBQWhCIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIi8qKlxuICogQ29uc3RhbnRzIHVzZWQgaW4gcGxheWVyLlxuICovXG52YXIgQ29uc3RhbnRzID0ge1xuXHRWRVJTSU9OOiAnMi4wLjEnLFxuXHROT1RFUzogW11cbn07XG5cbihmdW5jdGlvbigpIHtcblx0Ly8gQnVpbGRzIG5vdGVzIG9iamVjdCBmb3IgcmVmZXJlbmNlIGFnYWluc3QgYmluYXJ5IHZhbHVlcy5cblx0dmFyIGFsbE5vdGVzID0gW1snQyddLCBbJ0MjJywnRGInXSwgWydEJ10sIFsnRCMnLCdFYiddLCBbJ0UnXSxbJ0YnXSwgWydGIycsJ0diJ10sIFsnRyddLCBbJ0cjJywnQWInXSwgWydBJ10sIFsnQSMnLCdCYiddLCBbJ0InXV07XG5cdHZhciBjb3VudGVyID0gMDtcblxuXHQvLyBBbGwgYXZhaWxhYmxlIG9jdGF2ZXMuXG5cdGZvciAobGV0IGkgPSAtMTsgaSA8PSA5OyBpKyspIHtcblx0XHRhbGxOb3Rlcy5mb3JFYWNoKG5vdGVHcm91cCA9PiB7XG5cdFx0XHRub3RlR3JvdXAuZm9yRWFjaChub3RlID0+IENvbnN0YW50cy5OT1RFU1tjb3VudGVyXSA9IG5vdGUgKyBpKTtcblx0XHRcdGNvdW50ZXIgKys7XG5cdFx0fSk7XG5cdH1cbn0pKCk7XG5cbmV4cG9ydHMuQ29uc3RhbnRzID0gQ29uc3RhbnRzOyIsImNvbnN0IFBsYXllciA9IHJlcXVpcmUoXCIuL3BsYXllclwiKTtcbmNvbnN0IFV0aWxzID0gcmVxdWlyZShcIi4vdXRpbHNcIik7XG5jb25zdCBDb25zdGFudHMgPSByZXF1aXJlKFwiLi9jb25zdGFudHNcIik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFBsYXllcjpQbGF5ZXIuUGxheWVyLFxuICAgIFV0aWxzOlV0aWxzLlV0aWxzLFxuICAgIENvbnN0YW50czpDb25zdGFudHMuQ29uc3RhbnRzXG59IiwiY29uc3QgVXRpbHMgPSByZXF1aXJlKFwiLi91dGlsc1wiKS5VdGlscztcbmNvbnN0IFRyYWNrID0gcmVxdWlyZShcIi4vdHJhY2tcIikuVHJhY2s7XG5cbi8vIFBvbHlmaWxsIFVpbnQ4QXJyYXkuZm9yRWFjaDogRG9lc24ndCBleGlzdCBvbiBTYWZhcmkgPDEwXG5pZiAoIVVpbnQ4QXJyYXkucHJvdG90eXBlLmZvckVhY2gpIHtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KFVpbnQ4QXJyYXkucHJvdG90eXBlLCAnZm9yRWFjaCcsIHtcblx0XHR2YWx1ZTogQXJyYXkucHJvdG90eXBlLmZvckVhY2hcblx0fSk7XG59XG5cbi8qKlxuICogTWFpbiBwbGF5ZXIgY2xhc3MuICBDb250YWlucyBtZXRob2RzIHRvIGxvYWQgZmlsZXMsIHN0YXJ0LCBzdG9wLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gLSBDYWxsYmFjayB0byBmaXJlIGZvciBlYWNoIE1JREkgZXZlbnQuICBDYW4gYWxzbyBiZSBhZGRlZCB3aXRoIG9uKCdtaWRpRXZlbnQnLCBmbilcbiAqIEBwYXJhbSB7YXJyYXl9IC0gQXJyYXkgYnVmZmVyIG9mIE1JREkgZmlsZSAob3B0aW9uYWwpLlxuICovXG5jbGFzcyBQbGF5ZXIge1xuXHRjb25zdHJ1Y3RvcihldmVudEhhbmRsZXIsIGJ1ZmZlcikge1xuXHRcdHRoaXMuc2FtcGxlUmF0ZSA9IDU7IC8vIG1pbGxpc2Vjb25kc1xuXHRcdHRoaXMuc3RhcnRUaW1lID0gMDtcblx0XHR0aGlzLmJ1ZmZlciA9IGJ1ZmZlciB8fCBudWxsO1xuXHRcdHRoaXMuZGl2aXNpb247XG5cdFx0dGhpcy5mb3JtYXQ7XG5cdFx0dGhpcy5zZXRJbnRlcnZhbElkID0gZmFsc2U7XG5cdFx0dGhpcy50cmFja3MgPSBbXTtcblx0XHR0aGlzLmluc3RydW1lbnRzID0gW107XG5cdFx0dGhpcy5kZWZhdWx0VGVtcG8gPSAxMjA7XG5cdFx0dGhpcy50ZW1wbyA9IG51bGw7XG5cdFx0dGhpcy5zdGFydFRpY2sgPSAwO1xuXHRcdHRoaXMudGljayA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IG51bGw7XG5cdFx0dGhpcy5pbkxvb3AgPSBmYWxzZTtcblx0XHR0aGlzLnRvdGFsVGlja3MgPSAwO1xuXHRcdHRoaXMuZXZlbnRzID0gW107XG5cdFx0dGhpcy50b3RhbEV2ZW50cyA9IDA7XG5cdFx0dGhpcy5ldmVudExpc3RlbmVycyA9IHt9O1xuXG5cdFx0aWYgKHR5cGVvZihldmVudEhhbmRsZXIpID09PSAnZnVuY3Rpb24nKSB0aGlzLm9uKCdtaWRpRXZlbnQnLCBldmVudEhhbmRsZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvYWQgYSBmaWxlIGludG8gdGhlIHBsYXllciAoTm9kZS5qcyBvbmx5KS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBQYXRoIG9mIGZpbGUuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWRGaWxlKHBhdGgpIHtcblx0XHR2YXIgZnMgPSByZXF1aXJlKCdmcycpO1xuXHRcdHRoaXMuYnVmZmVyID0gZnMucmVhZEZpbGVTeW5jKHBhdGgpO1xuXHRcdHJldHVybiB0aGlzLmZpbGVMb2FkZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMb2FkIGFuIGFycmF5IGJ1ZmZlciBpbnRvIHRoZSBwbGF5ZXIuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGFycmF5QnVmZmVyIC0gQXJyYXkgYnVmZmVyIG9mIGZpbGUgdG8gYmUgbG9hZGVkLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRsb2FkQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIpIHtcblx0XHR0aGlzLmJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKTtcblx0XHRyZXR1cm4gdGhpcy5maWxlTG9hZGVkKCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCBhIGRhdGEgVVJJIGludG8gdGhlIHBsYXllci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGRhdGFVcmkgLSBEYXRhIFVSSSB0byBiZSBsb2FkZWQuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWREYXRhVXJpKGRhdGFVcmkpIHtcblx0XHQvLyBjb252ZXJ0IGJhc2U2NCB0byByYXcgYmluYXJ5IGRhdGEgaGVsZCBpbiBhIHN0cmluZy5cblx0XHQvLyBkb2Vzbid0IGhhbmRsZSBVUkxFbmNvZGVkIERhdGFVUklzIC0gc2VlIFNPIGFuc3dlciAjNjg1MDI3NiBmb3IgY29kZSB0aGF0IGRvZXMgdGhpc1xuXHRcdHZhciBieXRlU3RyaW5nID0gVXRpbHMuYXRvYihkYXRhVXJpLnNwbGl0KCcsJylbMV0pO1xuXG5cdFx0Ly8gd3JpdGUgdGhlIGJ5dGVzIG9mIHRoZSBzdHJpbmcgdG8gYW4gQXJyYXlCdWZmZXJcblx0XHR2YXIgaWEgPSBuZXcgVWludDhBcnJheShieXRlU3RyaW5nLmxlbmd0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBieXRlU3RyaW5nLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpYVtpXSA9IGJ5dGVTdHJpbmcuY2hhckNvZGVBdChpKTtcblx0XHR9XG5cblx0XHR0aGlzLmJ1ZmZlciA9IGlhO1xuXHRcdHJldHVybiB0aGlzLmZpbGVMb2FkZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgZmlsZXNpemUgb2YgbG9hZGVkIGZpbGUgaW4gbnVtYmVyIG9mIGJ5dGVzLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9IC0gVGhlIGZpbGVzaXplLlxuXHQgKi9cblx0Z2V0RmlsZXNpemUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYnVmZmVyID8gdGhpcy5idWZmZXIubGVuZ3RoIDogMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGRlZmF1bHQgdGVtcG8sIHBhcnNlcyBmaWxlIGZvciBuZWNlc3NhcnkgaW5mb3JtYXRpb24sIGFuZCBkb2VzIGEgZHJ5IHJ1biB0byBjYWxjdWxhdGUgdG90YWwgbGVuZ3RoLlxuXHQgKiBQb3B1bGF0ZXMgdGhpcy5ldmVudHMgJiB0aGlzLnRvdGFsVGlja3MuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGZpbGVMb2FkZWQoKSB7XG5cdFx0aWYgKCF0aGlzLnZhbGlkYXRlKCkpIHRocm93ICdJbnZhbGlkIE1JREkgZmlsZTsgc2hvdWxkIHN0YXJ0IHdpdGggTVRoZCc7XG5cdFx0cmV0dXJuIHRoaXMuc2V0VGVtcG8odGhpcy5kZWZhdWx0VGVtcG8pLmdldERpdmlzaW9uKCkuZ2V0Rm9ybWF0KCkuZ2V0VHJhY2tzKCkuZHJ5UnVuKCk7XG5cdH1cblxuXHQvKipcblx0ICogVmFsaWRhdGVzIGZpbGUgdXNpbmcgc2ltcGxlIG1lYW5zIC0gZmlyc3QgZm91ciBieXRlcyBzaG91bGQgPT0gTVRoZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHZhbGlkYXRlKCkge1xuXHRcdHJldHVybiBVdGlscy5ieXRlc1RvTGV0dGVycyh0aGlzLmJ1ZmZlci5zdWJhcnJheSgwLCA0KSkgPT09ICdNVGhkJztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIE1JREkgZmlsZSBmb3JtYXQgZm9yIGxvYWRlZCBmaWxlLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRnZXRGb3JtYXQoKSB7XG5cdFx0Lypcblx0XHRNSURJIGZpbGVzIGNvbWUgaW4gMyB2YXJpYXRpb25zOlxuXHRcdEZvcm1hdCAwIHdoaWNoIGNvbnRhaW4gYSBzaW5nbGUgdHJhY2tcblx0XHRGb3JtYXQgMSB3aGljaCBjb250YWluIG9uZSBvciBtb3JlIHNpbXVsdGFuZW91cyB0cmFja3Ncblx0XHQoaWUgYWxsIHRyYWNrcyBhcmUgdG8gYmUgcGxheWVkIHNpbXVsdGFuZW91c2x5KS5cblx0XHRGb3JtYXQgMiB3aGljaCBjb250YWluIG9uZSBvciBtb3JlIGluZGVwZW5kYW50IHRyYWNrc1xuXHRcdChpZSBlYWNoIHRyYWNrIGlzIHRvIGJlIHBsYXllZCBpbmRlcGVuZGFudGx5IG9mIHRoZSBvdGhlcnMpLlxuXHRcdHJldHVybiBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuYnVmZmVyLnN1YmFycmF5KDgsIDEwKSk7XG5cdFx0Ki9cblxuXHRcdHRoaXMuZm9ybWF0ID0gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmJ1ZmZlci5zdWJhcnJheSg4LCAxMCkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnNlcyBvdXQgdHJhY2tzLCBwbGFjZXMgdGhlbSBpbiB0aGlzLnRyYWNrcyBhbmQgaW5pdGlhbGl6ZXMgdGhpcy5wb2ludGVyc1xuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRnZXRUcmFja3MoKSB7XG5cdFx0dGhpcy50cmFja3MgPSBbXTtcblx0XHRsZXQgdHJhY2tPZmZzZXQgPSAwO1xuXHRcdHdoaWxlICh0cmFja09mZnNldCA8IHRoaXMuYnVmZmVyLmxlbmd0aCkge1xuXHRcdFx0aWYgKFV0aWxzLmJ5dGVzVG9MZXR0ZXJzKHRoaXMuYnVmZmVyLnN1YmFycmF5KHRyYWNrT2Zmc2V0LCB0cmFja09mZnNldCArIDQpKSA9PSAnTVRyaycpIHtcblx0XHRcdFx0bGV0IHRyYWNrTGVuZ3RoID0gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmJ1ZmZlci5zdWJhcnJheSh0cmFja09mZnNldCArIDQsIHRyYWNrT2Zmc2V0ICsgOCkpO1xuXHRcdFx0XHR0aGlzLnRyYWNrcy5wdXNoKG5ldyBUcmFjayh0aGlzLnRyYWNrcy5sZW5ndGgsIHRoaXMuYnVmZmVyLnN1YmFycmF5KHRyYWNrT2Zmc2V0ICsgOCwgdHJhY2tPZmZzZXQgKyA4ICsgdHJhY2tMZW5ndGgpKSk7XG5cdFx0XHR9XG5cblx0XHRcdHRyYWNrT2Zmc2V0ICs9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkodHJhY2tPZmZzZXQgKyA0LCB0cmFja09mZnNldCArIDgpKSArIDg7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVuYWJsZXMgYSB0cmFjayBmb3IgcGxheWluZy5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHRyYWNrTnVtYmVyIC0gVHJhY2sgbnVtYmVyXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGVuYWJsZVRyYWNrKHRyYWNrTnVtYmVyKSB7XG5cdFx0dGhpcy50cmFja3NbdHJhY2tOdW1iZXIgLSAxXS5lbmFibGUoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNhYmxlcyBhIHRyYWNrIGZvciBwbGF5aW5nLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUcmFjayBudW1iZXJcblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0ZGlzYWJsZVRyYWNrKHRyYWNrTnVtYmVyKSB7XG5cdFx0dGhpcy50cmFja3NbdHJhY2tOdW1iZXIgLSAxXS5kaXNhYmxlKCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBxdWFydGVyIG5vdGUgZGl2aXNpb24gb2YgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0Z2V0RGl2aXNpb24oKSB7XG5cdFx0dGhpcy5kaXZpc2lvbiA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkoMTIsIDE0KSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIG1haW4gcGxheSBsb29wLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IC0gSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoaXMgaXMgYmVpbmcgY2FsbGVkIHNpbXBseSBmb3IgcGFyc2luZyBwdXJwb3Nlcy4gIERpc3JlZ2FyZHMgdGltaW5nIGlmIHNvLlxuXHQgKiBAcmV0dXJuIHt1bmRlZmluZWR9XG5cdCAqL1xuXHRwbGF5TG9vcChkcnlSdW4pIHtcblx0XHRpZiAoIXRoaXMuaW5Mb29wKSB7XG5cdFx0XHR0aGlzLmluTG9vcCA9IHRydWU7XG5cdFx0XHR0aGlzLnRpY2sgPSB0aGlzLmdldEN1cnJlbnRUaWNrKCk7XG5cblx0XHRcdHRoaXMudHJhY2tzLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcblx0XHRcdFx0Ly8gSGFuZGxlIG5leHQgZXZlbnRcblx0XHRcdFx0aWYgKCFkcnlSdW4gJiYgdGhpcy5lbmRPZkZpbGUoKSkge1xuXHRcdFx0XHRcdC8vY29uc29sZS5sb2coJ2VuZCBvZiBmaWxlJylcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXJQbGF5ZXJFdmVudCgnZW5kT2ZGaWxlJyk7XG5cdFx0XHRcdFx0dGhpcy5zdG9wKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bGV0IGV2ZW50ID0gdHJhY2suaGFuZGxlRXZlbnQodGhpcy50aWNrLCBkcnlSdW4pO1xuXG5cdFx0XHRcdFx0aWYgKGRyeVJ1biAmJiBldmVudCkge1xuXHRcdFx0XHRcdFx0aWYgKGV2ZW50Lmhhc093blByb3BlcnR5KCduYW1lJykgJiYgZXZlbnQubmFtZSA9PT0gJ1NldCBUZW1wbycpIHtcblx0XHRcdFx0XHRcdFx0Ly8gR3JhYiB0ZW1wbyBpZiBhdmFpbGFibGUuXG5cdFx0XHRcdFx0XHRcdHRoaXMuc2V0VGVtcG8oZXZlbnQuZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoZXZlbnQuaGFzT3duUHJvcGVydHkoJ25hbWUnKSAmJiBldmVudC5uYW1lID09PSAnUHJvZ3JhbSBDaGFuZ2UnKSB7XG5cdFx0XHRcdFx0XHRcdGlmICghdGhpcy5pbnN0cnVtZW50cy5pbmNsdWRlcyhldmVudC52YWx1ZSkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmluc3RydW1lbnRzLnB1c2goZXZlbnQudmFsdWUpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChldmVudCkgdGhpcy5lbWl0RXZlbnQoZXZlbnQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0sIHRoaXMpO1xuXG5cdFx0XHRpZiAoIWRyeVJ1bikgdGhpcy50cmlnZ2VyUGxheWVyRXZlbnQoJ3BsYXlpbmcnLCB7dGljazogdGhpcy50aWNrfSk7XG5cdFx0XHR0aGlzLmluTG9vcCA9IGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXR0ZXIgZm9yIHRlbXBvLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUZW1wbyBpbiBicG0gKGRlZmF1bHRzIHRvIDEyMClcblx0ICovXG5cdHNldFRlbXBvKHRlbXBvKSB7XG5cdFx0dGhpcy50ZW1wbyA9IHRlbXBvO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHRlciBmb3Igc3RhcnRUaW1lLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBVVEMgdGltZXN0YW1wXG5cdCAqL1xuXHRzZXRTdGFydFRpbWUoc3RhcnRUaW1lKSB7XG5cdFx0dGhpcy5zdGFydFRpbWUgPSBzdGFydFRpbWU7XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnQgcGxheWluZyBsb2FkZWQgTUlESSBmaWxlIGlmIG5vdCBhbHJlYWR5IHBsYXlpbmcuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHBsYXkoKSB7XG5cdFx0aWYgKHRoaXMuaXNQbGF5aW5nKCkpIHRocm93ICdBbHJlYWR5IHBsYXlpbmcuLi4nO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZVxuXHRcdGlmICghdGhpcy5zdGFydFRpbWUpIHRoaXMuc3RhcnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuXHRcdC8vIFN0YXJ0IHBsYXkgbG9vcFxuXHRcdC8vd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnBsYXlMb29wLmJpbmQodGhpcykpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IHNldEludGVydmFsKHRoaXMucGxheUxvb3AuYmluZCh0aGlzKSwgdGhpcy5zYW1wbGVSYXRlKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhdXNlcyBwbGF5YmFjayBpZiBwbGF5aW5nLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRwYXVzZSgpIHtcblx0XHRjbGVhckludGVydmFsKHRoaXMuc2V0SW50ZXJ2YWxJZCk7XG5cdFx0dGhpcy5zZXRJbnRlcnZhbElkID0gZmFsc2U7XG5cdFx0dGhpcy5zdGFydFRpY2sgPSB0aGlzLnRpY2s7XG5cdFx0dGhpcy5zdGFydFRpbWUgPSAwO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0b3BzIHBsYXliYWNrIGlmIHBsYXlpbmcuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHN0b3AoKSB7XG5cdFx0Y2xlYXJJbnRlcnZhbCh0aGlzLnNldEludGVydmFsSWQpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IGZhbHNlO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gMDtcblx0XHR0aGlzLnN0YXJ0VGltZSA9IDA7XG5cdFx0dGhpcy5yZXNldFRyYWNrcygpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNraXBzIHBsYXllciBwb2ludGVyIHRvIHNwZWNpZmllZCB0aWNrLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUaWNrIHRvIHNraXAgdG8uXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1RpY2sodGljaykge1xuXHRcdHRoaXMuc3RvcCgpO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gdGljaztcblxuXHRcdC8vIE5lZWQgdG8gc2V0IHRyYWNrIGV2ZW50IGluZGV4ZXMgdG8gdGhlIG5lYXJlc3QgcG9zc2libGUgZXZlbnQgdG8gdGhlIHNwZWNpZmllZCB0aWNrLlxuXHRcdHRoaXMudHJhY2tzLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcblx0XHRcdHRyYWNrLnNldEV2ZW50SW5kZXhCeVRpY2sodGljayk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2tpcHMgcGxheWVyIHBvaW50ZXIgdG8gc3BlY2lmaWVkIHBlcmNlbnRhZ2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSAtIFBlcmNlbnQgdmFsdWUgaW4gaW50ZWdlciBmb3JtYXQuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1BlcmNlbnQocGVyY2VudCkge1xuXHRcdGlmIChwZXJjZW50IDwgMCB8fCBwZXJjZW50ID4gMTAwKSB0aHJvdyBcIlBlcmNlbnQgbXVzdCBiZSBudW1iZXIgYmV0d2VlbiAxIGFuZCAxMDAuXCI7XG5cdFx0dGhpcy5za2lwVG9UaWNrKE1hdGgucm91bmQocGVyY2VudCAvIDEwMCAqIHRoaXMudG90YWxUaWNrcykpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNraXBzIHBsYXllciBwb2ludGVyIHRvIHNwZWNpZmllZCBzZWNvbmRzLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBTZWNvbmRzIHRvIHNraXAgdG8uXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1NlY29uZHMoc2Vjb25kcykge1xuXHRcdHZhciBzb25nVGltZSA9IHRoaXMuZ2V0U29uZ1RpbWUoKTtcblx0XHRpZiAoc2Vjb25kcyA8IDAgfHwgc2Vjb25kcyA+IHNvbmdUaW1lKSB0aHJvdyBzZWNvbmRzICsgXCIgc2Vjb25kcyBub3Qgd2l0aGluIHNvbmcgdGltZSBvZiBcIiArIHNvbmdUaW1lO1xuXHRcdHRoaXMuc2tpcFRvUGVyY2VudChzZWNvbmRzIC8gc29uZ1RpbWUgKiAxMDApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBwbGF5ZXIgaXMgcGxheWluZ1xuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0aXNQbGF5aW5nKCkge1xuXHRcdHJldHVybiB0aGlzLnNldEludGVydmFsSWQgPiAwIHx8IHR5cGVvZiB0aGlzLnNldEludGVydmFsSWQgPT09ICdvYmplY3QnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBsYXlzIHRoZSBsb2FkZWQgTUlESSBmaWxlIHdpdGhvdXQgcmVnYXJkIGZvciB0aW1pbmcgYW5kIHNhdmVzIGV2ZW50cyBpbiB0aGlzLmV2ZW50cy4gIEVzc2VudGlhbGx5IHVzZWQgYXMgYSBwYXJzZXIuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGRyeVJ1bigpIHtcblx0XHQvLyBSZXNldCB0cmFja3MgZmlyc3Rcblx0XHR0aGlzLnJlc2V0VHJhY2tzKCk7XG5cdFx0d2hpbGUgKCF0aGlzLmVuZE9mRmlsZSgpKSB0aGlzLnBsYXlMb29wKHRydWUpO1xuXHRcdHRoaXMuZXZlbnRzID0gdGhpcy5nZXRFdmVudHMoKTtcblx0XHR0aGlzLnRvdGFsRXZlbnRzID0gdGhpcy5nZXRUb3RhbEV2ZW50cygpO1xuXHRcdHRoaXMudG90YWxUaWNrcyA9IHRoaXMuZ2V0VG90YWxUaWNrcygpO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gMDtcblx0XHR0aGlzLnN0YXJ0VGltZSA9IDA7XG5cblx0XHQvLyBMZWF2ZSB0cmFja3MgaW4gcHJpc3RpbmUgY29uZGlzaFxuXHRcdHRoaXMucmVzZXRUcmFja3MoKTtcblxuXHRcdC8vY29uc29sZS5sb2coJ1NvbmcgdGltZTogJyArIHRoaXMuZ2V0U29uZ1RpbWUoKSArICcgc2Vjb25kcyAvICcgKyB0aGlzLnRvdGFsVGlja3MgKyAnIHRpY2tzLicpO1xuXG5cdFx0dGhpcy50cmlnZ2VyUGxheWVyRXZlbnQoJ2ZpbGVMb2FkZWQnLCB0aGlzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNldHMgcGxheSBwb2ludGVycyBmb3IgYWxsIHRyYWNrcy5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0cmVzZXRUcmFja3MoKSB7XG5cdFx0dGhpcy50cmFja3MuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5yZXNldCgpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFuIGFycmF5IG9mIGV2ZW50cyBncm91cGVkIGJ5IHRyYWNrLlxuXHQgKiBAcmV0dXJuIHthcnJheX1cblx0ICovXG5cdGdldEV2ZW50cygpIHtcblx0XHRyZXR1cm4gdGhpcy50cmFja3MubWFwKHRyYWNrID0+IHRyYWNrLmV2ZW50cyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0b3RhbCBudW1iZXIgb2YgdGlja3MgaW4gdGhlIGxvYWRlZCBNSURJIGZpbGUuXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdGdldFRvdGFsVGlja3MoKSB7XG5cdFx0cmV0dXJuIE1hdGgubWF4LmFwcGx5KG51bGwsIHRoaXMudHJhY2tzLm1hcCh0cmFjayA9PiB0cmFjay5kZWx0YSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdG90YWwgbnVtYmVyIG9mIGV2ZW50cyBpbiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0VG90YWxFdmVudHMoKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJhY2tzLnJlZHVjZSgoYSwgYikgPT4ge3JldHVybiB7ZXZlbnRzOiB7bGVuZ3RoOiBhLmV2ZW50cy5sZW5ndGggKyBiLmV2ZW50cy5sZW5ndGh9fX0sIHtldmVudHM6IHtsZW5ndGg6IDB9fSkuZXZlbnRzLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHNvbmcgZHVyYXRpb24gaW4gc2Vjb25kcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1RpbWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudG90YWxUaWNrcyAvIHRoaXMuZGl2aXNpb24gLyB0aGlzLnRlbXBvICogNjA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgbnVtYmVyIG9mIHNlY29uZHMgaW4gcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdGdldFNvbmdUaW1lUmVtYWluaW5nKCkge1xuXHRcdHJldHVybiBNYXRoLnJvdW5kKCh0aGlzLnRvdGFsVGlja3MgLSB0aGlzLnRpY2spIC8gdGhpcy5kaXZpc2lvbiAvIHRoaXMudGVtcG8gKiA2MCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgcGVyY2VudCBvZiBwbGF5YmFjay5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1BlcmNlbnRSZW1haW5pbmcoKSB7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQodGhpcy5nZXRTb25nVGltZVJlbWFpbmluZygpIC8gdGhpcy5nZXRTb25nVGltZSgpICogMTAwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOdW1iZXIgb2YgYnl0ZXMgcHJvY2Vzc2VkIGluIHRoZSBsb2FkZWQgTUlESSBmaWxlLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRieXRlc1Byb2Nlc3NlZCgpIHtcblx0XHQvLyBDdXJyZW50bHkgYXNzdW1lIGhlYWRlciBjaHVuayBpcyBzdHJpY3RseSAxNCBieXRlc1xuXHRcdHJldHVybiAxNCArIHRoaXMudHJhY2tzLmxlbmd0aCAqIDggKyB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHtyZXR1cm4ge3BvaW50ZXI6IGEucG9pbnRlciArIGIucG9pbnRlcn19LCB7cG9pbnRlcjogMH0pLnBvaW50ZXI7XG5cdH1cblxuXHQvKipcblx0ICogTnVtYmVyIG9mIGV2ZW50cyBwbGF5ZWQgdXAgdG8gdGhpcyBwb2ludC5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0ZXZlbnRzUGxheWVkKCkge1xuXHRcdHJldHVybiB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHtyZXR1cm4ge2V2ZW50SW5kZXg6IGEuZXZlbnRJbmRleCArIGIuZXZlbnRJbmRleH19LCB7ZXZlbnRJbmRleDogMH0pLmV2ZW50SW5kZXg7XG5cdH1cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgcGxheWVyIHBvaW50ZXIgaGFzIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogVXNlZCBpbiB0d28gd2F5czpcblx0ICogMS4gSWYgcGxheWluZyByZXN1bHQgaXMgYmFzZWQgb24gbG9hZGVkIEpTT04gZXZlbnRzLlxuXHQgKiAyLiBJZiBwYXJzaW5nIChkcnlSdW4pIGl0J3MgYmFzZWQgb24gdGhlIGFjdHVhbCBidWZmZXIgbGVuZ3RoIHZzIGJ5dGVzIHByb2Nlc3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGVuZE9mRmlsZSgpIHtcblx0XHRpZiAodGhpcy5pc1BsYXlpbmcoKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZXZlbnRzUGxheWVkKCkgPT0gdGhpcy50b3RhbEV2ZW50cztcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5ieXRlc1Byb2Nlc3NlZCgpID09IHRoaXMuYnVmZmVyLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjdXJyZW50IHRpY2sgbnVtYmVyIGluIHBsYXliYWNrLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXRDdXJyZW50VGljaygpIHtcblx0XHRyZXR1cm4gTWF0aC5yb3VuZCgoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHRoaXMuc3RhcnRUaW1lKSAvIDEwMDAgKiAodGhpcy5kaXZpc2lvbiAqICh0aGlzLnRlbXBvIC8gNjApKSkgKyB0aGlzLnN0YXJ0VGljaztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZW5kcyBNSURJIGV2ZW50IG91dCB0byBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtvYmplY3R9XG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGVtaXRFdmVudChldmVudCkge1xuXHRcdHRoaXMudHJpZ2dlclBsYXllckV2ZW50KCdtaWRpRXZlbnQnLCBldmVudCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU3Vic2NyaWJlcyBldmVudHMgdG8gbGlzdGVuZXJzXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSAtIE5hbWUgb2YgZXZlbnQgdG8gc3Vic2NyaWJlIHRvLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9ufSAtIENhbGxiYWNrIHRvIGZpcmUgd2hlbiBldmVudCBpcyBicm9hZGNhc3QuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdG9uKHBsYXllckV2ZW50LCBmbikge1xuXHRcdGlmICghdGhpcy5ldmVudExpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShwbGF5ZXJFdmVudCkpIHRoaXMuZXZlbnRMaXN0ZW5lcnNbcGxheWVyRXZlbnRdID0gW107XG5cdFx0dGhpcy5ldmVudExpc3RlbmVyc1twbGF5ZXJFdmVudF0ucHVzaChmbik7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQnJvYWRjYXN0cyBldmVudCB0byB0cmlnZ2VyIHN1YnNjcmliZWQgY2FsbGJhY2tzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gLSBOYW1lIG9mIGV2ZW50LlxuXHQgKiBAcGFyYW0ge29iamVjdH0gLSBEYXRhIHRvIGJlIHBhc3NlZCB0byBzdWJzY3JpYmVyIGNhbGxiYWNrLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHR0cmlnZ2VyUGxheWVyRXZlbnQocGxheWVyRXZlbnQsIGRhdGEpIHtcblx0XHRpZiAodGhpcy5ldmVudExpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShwbGF5ZXJFdmVudCkpIHRoaXMuZXZlbnRMaXN0ZW5lcnNbcGxheWVyRXZlbnRdLmZvckVhY2goZm4gPT4gZm4oZGF0YSB8fCB7fSkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cbn1cblxuZXhwb3J0cy5QbGF5ZXIgPSBQbGF5ZXI7XG4iLCJjb25zdCBDb25zdGFudHMgPSByZXF1aXJlKFwiLi9jb25zdGFudHNcIikuQ29uc3RhbnRzO1xuY29uc3QgVXRpbHMgPSByZXF1aXJlKFwiLi91dGlsc1wiKS5VdGlscztcblxuLyoqXG4gKiBDbGFzcyByZXByZXNlbnRpbmcgYSB0cmFjay4gIENvbnRhaW5zIG1ldGhvZHMgZm9yIHBhcnNpbmcgZXZlbnRzIGFuZCBrZWVwaW5nIHRyYWNrIG9mIHBvaW50ZXIuXG4gKi9cbmNsYXNzIFRyYWNrXHR7XG5cdGNvbnN0cnVjdG9yKGluZGV4LCBkYXRhKSB7XG5cdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblx0XHR0aGlzLmV2ZW50SW5kZXggPSAwO1xuXHRcdHRoaXMucG9pbnRlciA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IDA7XG5cdFx0dGhpcy5sYXN0U3RhdHVzID0gbnVsbDtcblx0XHR0aGlzLmluZGV4ID0gaW5kZXg7XG5cdFx0dGhpcy5kYXRhID0gZGF0YTtcblx0XHR0aGlzLmRlbHRhID0gMDtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSA9IDA7XG5cdFx0dGhpcy5ldmVudHMgPSBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNldHMgYWxsIHN0YXRlZnVsIHRyYWNrIGluZm9ybWFpb24gdXNlZCBkdXJpbmcgcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge1RyYWNrfVxuXHQgKi9cblx0cmVzZXQoKSB7XG5cdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblx0XHR0aGlzLmV2ZW50SW5kZXggPSAwO1xuXHRcdHRoaXMucG9pbnRlciA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IDA7XG5cdFx0dGhpcy5sYXN0U3RhdHVzID0gbnVsbDtcblx0XHR0aGlzLmRlbHRhID0gMDtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSA9IDA7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGlzIHRyYWNrIHRvIGJlIGVuYWJsZWQgZHVyaW5nIHBsYXliYWNrLlxuXHQgKiBAcmV0dXJuIHtUcmFja31cblx0ICovXG5cdGVuYWJsZSgpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhpcyB0cmFjayB0byBiZSBkaXNhYmxlZCBkdXJpbmcgcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge1RyYWNrfVxuXHQgKi9cblx0ZGlzYWJsZSgpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSBmYWxzZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0cmFjayBldmVudCBpbmRleCB0byB0aGUgbmVhcmVzdCBldmVudCB0byB0aGUgZ2l2ZW4gdGljay5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHRpY2tcblx0ICogQHJldHVybiB7VHJhY2t9XG5cdCAqL1xuXHRzZXRFdmVudEluZGV4QnlUaWNrKHRpY2spIHtcblx0XHR0aWNrID0gdGljayB8fCAwO1xuXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLmV2ZW50cykge1xuXHRcdFx0aWYgKHRoaXMuZXZlbnRzW2ldLnRpY2sgPj0gdGljaykge1xuXHRcdFx0XHR0aGlzLmV2ZW50SW5kZXggPSBpO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBieXRlIGxvY2F0ZWQgYXQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0Q3VycmVudEJ5dGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGF0YVt0aGlzLnBvaW50ZXJdO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgY291bnQgb2YgZGVsdGEgYnl0ZXMgYW5kIGN1cnJlbnQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0RGVsdGFCeXRlQ291bnQoKSB7XG5cdFx0Ly8gR2V0IGJ5dGUgY291bnQgb2YgZGVsdGEgVkxWXG5cdFx0Ly8gaHR0cDovL3d3dy5jY2FyaC5vcmcvY291cnNlcy8yNTMvaGFuZG91dC92bHYvXG5cdFx0Ly8gSWYgYnl0ZSBpcyBncmVhdGVyIG9yIGVxdWFsIHRvIDgwaCAoMTI4IGRlY2ltYWwpIHRoZW4gdGhlIG5leHQgYnl0ZVxuXHQgICAgLy8gaXMgYWxzbyBwYXJ0IG9mIHRoZSBWTFYsXG5cdCAgIFx0Ly8gZWxzZSBieXRlIGlzIHRoZSBsYXN0IGJ5dGUgaW4gYSBWTFYuXG5cdCAgIFx0dmFyIGN1cnJlbnRCeXRlID0gdGhpcy5nZXRDdXJyZW50Qnl0ZSgpO1xuXHQgICBcdHZhciBieXRlQ291bnQgPSAxO1xuXG5cdFx0d2hpbGUgKGN1cnJlbnRCeXRlID49IDEyOCkge1xuXHRcdFx0Y3VycmVudEJ5dGUgPSB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgYnl0ZUNvdW50XTtcblx0XHRcdGJ5dGVDb3VudCsrO1xuXHRcdH1cblxuXHRcdHJldHVybiBieXRlQ291bnQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGRlbHRhIHZhbHVlIGF0IGN1cnJlbnQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0RGVsdGEoKSB7XG5cdFx0cmV0dXJuIFV0aWxzLnJlYWRWYXJJbnQodGhpcy5kYXRhLnN1YmFycmF5KHRoaXMucG9pbnRlciwgdGhpcy5wb2ludGVyICsgdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpKSk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBldmVudCB3aXRoaW4gYSBnaXZlbiB0cmFjayBzdGFydGluZyBhdCBzcGVjaWZpZWQgaW5kZXhcblx0ICogQHBhcmFtIHtudW1iZXJ9IGN1cnJlbnRUaWNrXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZHJ5UnVuIC0gSWYgdHJ1ZSBldmVudHMgd2lsbCBiZSBwYXJzZWQgYW5kIHJldHVybmVkIHJlZ2FyZGxlc3Mgb2YgdGltZS5cblx0ICovXG5cdGhhbmRsZUV2ZW50KGN1cnJlbnRUaWNrLCBkcnlSdW4pIHtcblx0XHRkcnlSdW4gPSBkcnlSdW4gfHwgZmFsc2U7XG5cblx0XHRpZiAoZHJ5UnVuKSB7XG5cdFx0XHR2YXIgZWxhcHNlZFRpY2tzID0gY3VycmVudFRpY2sgLSB0aGlzLmxhc3RUaWNrO1xuXHRcdFx0dmFyIGRlbHRhID0gdGhpcy5nZXREZWx0YSgpO1xuXHRcdFx0dmFyIGV2ZW50UmVhZHkgPSBlbGFwc2VkVGlja3MgPj0gZGVsdGE7XG5cblx0XHRcdGlmICh0aGlzLnBvaW50ZXIgPCB0aGlzLmRhdGEubGVuZ3RoICYmIChkcnlSdW4gfHwgZXZlbnRSZWFkeSkpIHtcblx0XHRcdFx0bGV0IGV2ZW50ID0gdGhpcy5wYXJzZUV2ZW50KCk7XG5cdFx0XHRcdGlmICh0aGlzLmVuYWJsZWQpIHJldHVybiBldmVudDtcblx0XHRcdFx0Ly8gUmVjdXJzaXZlbHkgY2FsbCB0aGlzIGZ1bmN0aW9uIGZvciBlYWNoIGV2ZW50IGFoZWFkIHRoYXQgaGFzIDAgZGVsdGEgdGltZT9cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBMZXQncyBhY3R1YWxseSBwbGF5IHRoZSBNSURJIGZyb20gdGhlIGdlbmVyYXRlZCBKU09OIGV2ZW50cyBjcmVhdGVkIGJ5IHRoZSBkcnkgcnVuLlxuXHRcdFx0aWYgKHRoaXMuZXZlbnRzW3RoaXMuZXZlbnRJbmRleF0gJiYgdGhpcy5ldmVudHNbdGhpcy5ldmVudEluZGV4XS50aWNrIDw9IGN1cnJlbnRUaWNrKSB7XG5cdFx0XHRcdHRoaXMuZXZlbnRJbmRleCsrO1xuXHRcdFx0XHRpZiAodGhpcy5lbmFibGVkKSByZXR1cm4gdGhpcy5ldmVudHNbdGhpcy5ldmVudEluZGV4IC0gMV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHN0cmluZyBkYXRhIGZyb20gZXZlbnQuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBldmVudFN0YXJ0SW5kZXhcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpIHtcblx0XHR2YXIgY3VycmVudEJ5dGUgPSB0aGlzLnBvaW50ZXI7XG5cdFx0dmFyIGJ5dGVDb3VudCA9IDE7XG5cdFx0dmFyIGxlbmd0aCA9IFV0aWxzLnJlYWRWYXJJbnQodGhpcy5kYXRhLnN1YmFycmF5KGV2ZW50U3RhcnRJbmRleCArIDIsIGV2ZW50U3RhcnRJbmRleCArIDIgKyBieXRlQ291bnQpKTtcblx0XHR2YXIgc3RyaW5nTGVuZ3RoID0gbGVuZ3RoO1xuXG5cdFx0cmV0dXJuIFV0aWxzLmJ5dGVzVG9MZXR0ZXJzKHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyAyLCBldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyBsZW5ndGggKyAyKSk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIGV2ZW50IGludG8gSlNPTiBhbmQgYWR2YW5jZXMgcG9pbnRlciBmb3IgdGhlIHRyYWNrXG5cdCAqIEByZXR1cm4ge29iamVjdH1cblx0ICovXG5cdHBhcnNlRXZlbnQoKSB7XG5cdFx0dmFyIGV2ZW50U3RhcnRJbmRleCA9IHRoaXMucG9pbnRlciArIHRoaXMuZ2V0RGVsdGFCeXRlQ291bnQoKTtcblx0XHR2YXIgZXZlbnRKc29uID0ge307XG5cdFx0dmFyIGRlbHRhQnl0ZUNvdW50ID0gdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpO1xuXHRcdGV2ZW50SnNvbi50cmFjayA9IHRoaXMuaW5kZXggKyAxO1xuXHRcdGV2ZW50SnNvbi5kZWx0YSA9IHRoaXMuZ2V0RGVsdGEoKTtcblx0XHR0aGlzLmxhc3RUaWNrID0gdGhpcy5sYXN0VGljayArIGV2ZW50SnNvbi5kZWx0YTtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSArPSBldmVudEpzb24uZGVsdGE7XG5cdFx0ZXZlbnRKc29uLnRpY2sgPSB0aGlzLnJ1bm5pbmdEZWx0YTtcblx0XHRldmVudEpzb24uYnl0ZUluZGV4ID0gdGhpcy5wb2ludGVyO1xuXG5cdFx0Ly9ldmVudEpzb24ucmF3ID0gZXZlbnQ7XG5cdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdID09IDB4ZmYpIHtcblx0XHRcdC8vIE1ldGEgRXZlbnRcblxuXHRcdFx0Ly8gSWYgdGhpcyBpcyBhIG1ldGEgZXZlbnQgd2Ugc2hvdWxkIGVtaXQgdGhlIGRhdGEgYW5kIGltbWVkaWF0ZWx5IG1vdmUgdG8gdGhlIG5leHQgZXZlbnRcblx0XHRcdC8vIG90aGVyd2lzZSBpZiB3ZSBsZXQgaXQgcnVuIHRocm91Z2ggdGhlIG5leHQgY3ljbGUgYSBzbGlnaHQgZGVsYXkgd2lsbCBhY2N1bXVsYXRlIGlmIG11bHRpcGxlIHRyYWNrc1xuXHRcdFx0Ly8gYXJlIGJlaW5nIHBsYXllZCBzaW11bHRhbmVvdXNseVxuXG5cdFx0XHRzd2l0Y2godGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdKSB7XG5cdFx0XHRcdGNhc2UgMHgwMDogLy8gU2VxdWVuY2UgTnVtYmVyXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2VxdWVuY2UgTnVtYmVyJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDAxOiAvLyBUZXh0IEV2ZW50XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVGV4dCBFdmVudCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDI6IC8vIENvcHlyaWdodCBOb3RpY2Vcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdDb3B5cmlnaHQgTm90aWNlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDAzOiAvLyBTZXF1ZW5jZS9UcmFjayBOYW1lXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2VxdWVuY2UvVHJhY2sgTmFtZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDQ6IC8vIEluc3RydW1lbnQgTmFtZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0luc3RydW1lbnQgTmFtZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDU6IC8vIEx5cmljXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTHlyaWMnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA2OiAvLyBNYXJrZXJcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdNYXJrZXInO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDc6IC8vIEN1ZSBQb2ludFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0N1ZSBQb2ludCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDk6IC8vIERldmljZSBOYW1lXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnRGV2aWNlIE5hbWUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDIwOiAvLyBNSURJIENoYW5uZWwgUHJlZml4XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTUlESSBDaGFubmVsIFByZWZpeCc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgyMTogLy8gTUlESSBQb3J0XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTUlESSBQb3J0Jztcblx0XHRcdFx0XHRldmVudEpzb24uZGF0YSA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIoW3RoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAzXV0pO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MkY6IC8vIEVuZCBvZiBUcmFja1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0VuZCBvZiBUcmFjayc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg1MTogLy8gU2V0IFRlbXBvXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2V0IFRlbXBvJztcblx0XHRcdFx0XHRldmVudEpzb24uZGF0YSA9IE1hdGgucm91bmQoNjAwMDAwMDAgLyBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyAzLCBldmVudFN0YXJ0SW5kZXggKyA2KSkpO1xuXHRcdFx0XHRcdHRoaXMudGVtcG8gPSBldmVudEpzb24uZGF0YTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDU0OiAvLyBTTVRQRSBPZmZzZXRcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdTTVRQRSBPZmZzZXQnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4NTg6IC8vIFRpbWUgU2lnbmF0dXJlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVGltZSBTaWduYXR1cmUnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4NTk6IC8vIEtleSBTaWduYXR1cmVcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdLZXkgU2lnbmF0dXJlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDdGOiAvLyBTZXF1ZW5jZXItU3BlY2lmaWMgTWV0YS1ldmVudFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1NlcXVlbmNlci1TcGVjaWZpYyBNZXRhLWV2ZW50Jztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdVbmtub3duOiAnICsgdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdLnRvU3RyaW5nKDE2KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0dmFyIGxlbmd0aCA9IHRoaXMuZGF0YVt0aGlzLnBvaW50ZXIgKyBkZWx0YUJ5dGVDb3VudCArIDJdO1xuXHRcdFx0Ly8gU29tZSBtZXRhIGV2ZW50cyB3aWxsIGhhdmUgdmx2IHRoYXQgbmVlZHMgdG8gYmUgaGFuZGxlZFxuXG5cdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzICsgbGVuZ3RoO1xuXG5cdFx0fSBlbHNlIGlmKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdID09IDB4ZjApIHtcblx0XHRcdC8vIFN5c2V4XG5cdFx0XHRldmVudEpzb24ubmFtZSA9ICdTeXNleCc7XG5cdFx0XHR2YXIgbGVuZ3RoID0gdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIGRlbHRhQnl0ZUNvdW50ICsgMV07XG5cdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAyICsgbGVuZ3RoO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFZvaWNlIGV2ZW50XG5cdFx0XHRpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPCAweDgwKSB7XG5cdFx0XHRcdC8vIFJ1bm5pbmcgc3RhdHVzXG5cdFx0XHRcdGV2ZW50SnNvbi5ydW5uaW5nID0gdHJ1ZTtcblx0XHRcdFx0ZXZlbnRKc29uLm5vdGVOdW1iZXIgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XTtcblx0XHRcdFx0ZXZlbnRKc29uLm5vdGVOYW1lID0gQ29uc3RhbnRzLk5PVEVTW3RoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdXTtcblx0XHRcdFx0ZXZlbnRKc29uLnZlbG9jaXR5ID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXG5cdFx0XHRcdGlmICh0aGlzLmxhc3RTdGF0dXMgPD0gMHg4Zikge1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ05vdGUgb2ZmJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4ODAgKyAxO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5sYXN0U3RhdHVzIDw9IDB4OWYpIHtcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9uJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4OTAgKyAxO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMjtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5sYXN0U3RhdHVzID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF07XG5cblx0XHRcdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4OGYpIHtcblx0XHRcdFx0XHQvLyBOb3RlIG9mZlxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ05vdGUgb2ZmJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4ODAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTnVtYmVyID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTmFtZSA9IENvbnN0YW50cy5OT1RFU1t0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV1dO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52ZWxvY2l0eSA9IE1hdGgucm91bmQodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDJdIC8gMTI3ICogMTAwKTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHg5Zikge1xuXHRcdFx0XHRcdC8vIE5vdGUgb25cblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9uJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4OTAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTnVtYmVyID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTmFtZSA9IENvbnN0YW50cy5OT1RFU1t0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV1dO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52ZWxvY2l0eSA9IE1hdGgucm91bmQodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDJdIC8gMTI3ICogMTAwKTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhhZikge1xuXHRcdFx0XHRcdC8vIFBvbHlwaG9uaWMgS2V5IFByZXNzdXJlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnUG9seXBob25pYyBLZXkgUHJlc3N1cmUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhhMCArIDE7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5vdGUgPSBDb25zdGFudHMuTk9URVNbdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdXTtcblx0XHRcdFx0XHRldmVudEpzb24ucHJlc3N1cmUgPSBldmVudFsyXTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhiZikge1xuXHRcdFx0XHRcdC8vIENvbnRyb2xsZXIgQ2hhbmdlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnQ29udHJvbGxlciBDaGFuZ2UnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhiMCArIDE7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm51bWJlciA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHRldmVudEpzb24udmFsdWUgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMl07XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4Y2YpIHtcblx0XHRcdFx0XHQvLyBQcm9ncmFtIENoYW5nZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1Byb2dyYW0gQ2hhbmdlJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4YzAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52YWx1ZSA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAyO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhkZikge1xuXHRcdFx0XHRcdC8vIENoYW5uZWwgS2V5IFByZXNzdXJlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnQ2hhbm5lbCBLZXkgUHJlc3N1cmUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhkMCArIDE7XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMjtcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4ZWYpIHtcblx0XHRcdFx0XHQvLyBQaXRjaCBCZW5kXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnUGl0Y2ggQmVuZCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweGUwICsgMTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVW5rbm93bi4gIFBvaW50ZXI6ICcgKyB0aGlzLnBvaW50ZXIudG9TdHJpbmcoKSArICcgJyAgKyBldmVudFN0YXJ0SW5kZXgudG9TdHJpbmcoKSArICcgJyArIHRoaXMuZGF0YS5sZW5ndGg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLmRlbHRhICs9IGV2ZW50SnNvbi5kZWx0YTtcblx0XHR0aGlzLmV2ZW50cy5wdXNoKGV2ZW50SnNvbik7XG5cblx0XHRyZXR1cm4gZXZlbnRKc29uO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdHJ1ZSBpZiBwb2ludGVyIGhhcyByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIHRyYWNrLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59XG5cdCAqL1xuXHRlbmRPZlRyYWNrKCkge1xuXHRcdGlmICh0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgMV0gPT0gMHhmZiAmJiB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgMl0gPT0gMHgyZiAmJiB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgM10gPT0gMHgwMCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzLlRyYWNrID0gVHJhY2s7IiwiLyoqXG4gKiBDb250YWlucyBtaXNjIHN0YXRpYyB1dGlsaXR5IG1ldGhvZHMuXG4gKi9cbmNsYXNzIFV0aWxzIHtcblxuXHQvKipcblx0ICogQ29udmVydHMgYSBzaW5nbGUgYnl0ZSB0byBhIGhleCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBieXRlXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBieXRlVG9IZXgoYnl0ZSkge1xuXHRcdC8vIEVuc3VyZSBoZXggc3RyaW5nIGFsd2F5cyBoYXMgdHdvIGNoYXJzXG5cdFx0cmV0dXJuICgnMCcgKyBieXRlLnRvU3RyaW5nKDE2KSkuc2xpY2UoLTIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGFuIGFycmF5IG9mIGJ5dGVzIHRvIGEgaGV4IHN0cmluZy5cblx0ICogQHBhcmFtIHthcnJheX0gYnl0ZUFycmF5XG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBieXRlc1RvSGV4KGJ5dGVBcnJheSkge1xuXHRcdHZhciBoZXggPSBbXTtcblx0XHRieXRlQXJyYXkuZm9yRWFjaChieXRlID0+IGhleC5wdXNoKFV0aWxzLmJ5dGVUb0hleChieXRlKSkpO1xuXHRcdHJldHVybiBoZXguam9pbignJyk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBoZXggc3RyaW5nIHRvIGEgbnVtYmVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaGV4U3RyaW5nXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdHN0YXRpYyBoZXhUb051bWJlcihoZXhTdHJpbmcpIHtcblx0XHRyZXR1cm4gcGFyc2VJbnQoaGV4U3RyaW5nLCAxNik7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYW4gYXJyYXkgb2YgYnl0ZXMgdG8gYSBudW1iZXIuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRzdGF0aWMgYnl0ZXNUb051bWJlcihieXRlQXJyYXkpIHtcblx0XHRyZXR1cm4gVXRpbHMuaGV4VG9OdW1iZXIoVXRpbHMuYnl0ZXNUb0hleChieXRlQXJyYXkpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBieXRlcyB0byBsZXR0ZXJzLlxuXHQgKiBAcGFyYW0ge2FycmF5fSBieXRlQXJyYXlcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIGJ5dGVzVG9MZXR0ZXJzKGJ5dGVBcnJheSkge1xuXHRcdHZhciBsZXR0ZXJzID0gW107XG5cdFx0Ynl0ZUFycmF5LmZvckVhY2goYnl0ZSA9PiBsZXR0ZXJzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShieXRlKSkpO1xuXHRcdHJldHVybiBsZXR0ZXJzLmpvaW4oJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgZGVjaW1hbCB0byBpdCdzIGJpbmFyeSByZXByZXNlbnRhdGlvbi5cblx0ICogQHBhcmFtIHtudW1iZXJ9IGRlY1xuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgZGVjVG9CaW5hcnkoZGVjKSB7XG4gICAgXHRyZXR1cm4gKGRlYyA+Pj4gMCkudG9TdHJpbmcoMik7XG5cdH1cblxuXHQvKipcblx0ICogUmVhZHMgYSB2YXJpYWJsZSBsZW5ndGggdmFsdWUuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRzdGF0aWMgcmVhZFZhckludChieXRlQXJyYXkpIHtcblx0XHR2YXIgcmVzdWx0ID0gMDtcblx0XHRieXRlQXJyYXkuZm9yRWFjaChudW1iZXIgPT4ge1xuXHRcdFx0dmFyIGIgPSBudW1iZXI7XG5cdFx0XHRpZiAoYiAmIDB4ODApIHtcblx0XHRcdFx0cmVzdWx0ICs9IChiICYgMHg3Zik7XG5cdFx0XHRcdHJlc3VsdCA8PD0gNztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8qIGIgaXMgdGhlIGxhc3QgYnl0ZSAqL1xuXHRcdFx0XHRyZXN1bHQgKz0gYjtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHQvKipcblx0ICogRGVjb2RlcyBiYXNlLTY0IGVuY29kZWQgc3RyaW5nXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIGF0b2Ioc3RyaW5nKSB7XG5cdFx0aWYgKHR5cGVvZiBhdG9iID09PSAnZnVuY3Rpb24nKSByZXR1cm4gYXRvYihzdHJpbmcpO1xuXHRcdHJldHVybiBuZXcgQnVmZmVyKHN0cmluZywgJ2Jhc2U2NCcpLnRvU3RyaW5nKCdiaW5hcnknKTtcblx0fVxufVxuXG5leHBvcnRzLlV0aWxzID0gVXRpbHM7Il19