diff --git a/dist/jclic-es6.js b/dist/jclic-es6.js new file mode 100644 index 00000000..c6e269d2 --- /dev/null +++ b/dist/jclic-es6.js @@ -0,0 +1,65546 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/JClic.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js": +/*!***************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/arrayWithHoles.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +module.exports = _arrayWithHoles; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/arrayWithoutHoles.js": +/*!******************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/arrayWithoutHoles.js ***! + \******************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { + arr2[i] = arr[i]; + } + + return arr2; + } +} + +module.exports = _arrayWithoutHoles; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js": +/*!**********************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/assertThisInitialized.js ***! + \**********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +module.exports = _assertThisInitialized; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/classCallCheck.js": +/*!***************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/classCallCheck.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +module.exports = _classCallCheck; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/createClass.js": +/*!************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/createClass.js ***! + \************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +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); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +module.exports = _createClass; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/defineProperty.js": +/*!***************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/defineProperty.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +module.exports = _defineProperty; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js": +/*!***************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/getPrototypeOf.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _getPrototypeOf(o) { + module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +module.exports = _getPrototypeOf; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/inherits.js": +/*!*********************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/inherits.js ***! + \*********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var setPrototypeOf = __webpack_require__(/*! ./setPrototypeOf */ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js"); + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) setPrototypeOf(subClass, superClass); +} + +module.exports = _inherits; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/iterableToArray.js": +/*!****************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/iterableToArray.js ***! + \****************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); +} + +module.exports = _iterableToArray; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js": +/*!*********************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js ***! + \*********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _iterableToArrayLimit(arr, i) { + if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { + return; + } + + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +module.exports = _iterableToArrayLimit; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/nonIterableRest.js": +/*!****************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/nonIterableRest.js ***! + \****************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance"); +} + +module.exports = _nonIterableRest; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/nonIterableSpread.js": +/*!******************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/nonIterableSpread.js ***! + \******************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); +} + +module.exports = _nonIterableSpread; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/objectSpread.js": +/*!*************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/objectSpread.js ***! + \*************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var defineProperty = __webpack_require__(/*! ./defineProperty */ "./node_modules/@babel/runtime/helpers/defineProperty.js"); + +function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? Object(arguments[i]) : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + defineProperty(target, key, source[key]); + }); + } + + return target; +} + +module.exports = _objectSpread; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js": +/*!**************************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var _typeof = __webpack_require__(/*! ../helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js"); + +var assertThisInitialized = __webpack_require__(/*! ./assertThisInitialized */ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js"); + +function _possibleConstructorReturn(self, call) { + if (call && (_typeof(call) === "object" || typeof call === "function")) { + return call; + } + + return assertThisInitialized(self); +} + +module.exports = _possibleConstructorReturn; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/setPrototypeOf.js": +/*!***************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/setPrototypeOf.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _setPrototypeOf(o, p) { + module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +module.exports = _setPrototypeOf; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/slicedToArray.js": +/*!**************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/slicedToArray.js ***! + \**************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayWithHoles = __webpack_require__(/*! ./arrayWithHoles */ "./node_modules/@babel/runtime/helpers/arrayWithHoles.js"); + +var iterableToArrayLimit = __webpack_require__(/*! ./iterableToArrayLimit */ "./node_modules/@babel/runtime/helpers/iterableToArrayLimit.js"); + +var nonIterableRest = __webpack_require__(/*! ./nonIterableRest */ "./node_modules/@babel/runtime/helpers/nonIterableRest.js"); + +function _slicedToArray(arr, i) { + return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest(); +} + +module.exports = _slicedToArray; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/toConsumableArray.js": +/*!******************************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/toConsumableArray.js ***! + \******************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayWithoutHoles = __webpack_require__(/*! ./arrayWithoutHoles */ "./node_modules/@babel/runtime/helpers/arrayWithoutHoles.js"); + +var iterableToArray = __webpack_require__(/*! ./iterableToArray */ "./node_modules/@babel/runtime/helpers/iterableToArray.js"); + +var nonIterableSpread = __webpack_require__(/*! ./nonIterableSpread */ "./node_modules/@babel/runtime/helpers/nonIterableSpread.js"); + +function _toConsumableArray(arr) { + return arrayWithoutHoles(arr) || iterableToArray(arr) || nonIterableSpread(); +} + +module.exports = _toConsumableArray; + +/***/ }), + +/***/ "./node_modules/@babel/runtime/helpers/typeof.js": +/*!*******************************************************!*\ + !*** ./node_modules/@babel/runtime/helpers/typeof.js ***! + \*******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + module.exports = _typeof = function _typeof(obj) { + return typeof obj; + }; + } else { + module.exports = _typeof = function _typeof(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); +} + +module.exports = _typeof; + +/***/ }), + +/***/ "./node_modules/@francesc/basic-midi-player-js/module/midiplayer.js": +/*!**************************************************************************!*\ + !*** ./node_modules/@francesc/basic-midi-player-js/module/midiplayer.js ***! + \**************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var require;var require;(function(f){if(true){module.exports=f()}else { var g; }})(function(){var define,module,exports;return (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 require(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= end) { + value = end + } + + return value +} + +module.exports = ADSR + +},{}],2:[function(require,module,exports){ +'use strict' + +// DECODE UTILITIES +function b64ToUint6(nChr) { + return nChr > 64 && nChr < 91 ? nChr - 65 + : nChr > 96 && nChr < 123 ? nChr - 71 + : nChr > 47 && nChr < 58 ? nChr + 4 + : nChr === 43 ? 62 + : nChr === 47 ? 63 + : 0 +} + +// Decode Base64 to Uint8Array +// --------------------------- +function decode(sBase64, nBlocksSize) { + const sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, '') + const nInLen = sB64Enc.length + const nOutLen = nBlocksSize + ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize + : nInLen * 3 + 1 >> 2 + const taBytes = new Uint8Array(nOutLen) + + for (let nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { + nMod4 = nInIdx & 3 + nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4 + if (nMod4 === 3 || nInLen - nInIdx === 1) { + for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++ , nOutIdx++) { + taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255 + } + nUint24 = 0 + } + } + return taBytes +} + +module.exports = { decode } + +},{}],3:[function(require,module,exports){ +/* global XMLHttpRequest */ +'use strict' + +/** + * Given a url and a return type, returns a promise to the content of the url + * Basically it wraps a XMLHttpRequest into a Promise + * + * @param {String} url + * @param {String} type - can be 'text' or 'arraybuffer' + * @return {Promise} + */ +module.exports = function (url, type) { + return new Promise(function (done, reject) { + const req = new XMLHttpRequest() + if (type) + req.responseType = type + + req.open('GET', url) + req.onload = function () { + if (req.status === 200) + done(req.response) + reject(Error(req.statusText)) + } + req.onerror = () => reject(Error('Network Error')) + req.send() + }) +} + +},{}],4:[function(require,module,exports){ +'use strict' + +const base64 = require('./base64') +const fetch = require('./fetch') + +// Given a regex, return a function that test if against a string +function fromRegex(r) { + return function (o) { return typeof o === 'string' && r.test(o) } +} +// Try to apply a prefix to a name +function prefix(pre, name) { + return typeof pre === 'string' ? pre + name + : typeof pre === 'function' ? pre(name) + : name +} + +/** + * Load one or more audio files + * + * + * Possible option keys: + * + * - __from__ {Function|String}: a function or string to convert from file names to urls. + * If is a string it will be prefixed to the name: + * `load(ac, 'snare.mp3', { from: 'http://audio.net/samples/' })` + * If it's a function it receives the file name and should return the url as string. + * - __only__ {Array} - when loading objects, if provided, only the given keys + * will be included in the decoded object: + * `load(ac, 'piano.json', { only: ['C2', 'D2'] })` + * + * @param {AudioContext} ac - the audio context + * @param {Object} source - the object to be loaded + * @param {Object} options - (Optional) the load options for that object + * @param {Object} defaultValue - (Optional) the default value to return as + * in a promise if not valid loader found + */ +function load(ac, source, options, defVal) { + const loader = + // Basic audio loading + isArrayBuffer(source) ? loadArrayBuffer + : isAudioFileName(source) ? loadAudioFile + : isPromise(source) ? loadPromise + // Compound objects + : isArray(source) ? loadArrayData + : isObject(source) ? loadObjectData + : isJsonFileName(source) ? loadJsonFile + // Base64 encoded audio + : isBase64Audio(source) ? loadBase64Audio + : isJsFileName(source) ? loadMidiJSFile + : null + + const opts = options || {} + return loader ? loader(ac, source, opts) + : defVal ? Promise.resolve(defVal) + : Promise.reject(`Source not valid (${source})`) +} +load.fetch = fetch + +// BASIC AUDIO LOADING +// =================== + +// Load (decode) an array buffer +function isArrayBuffer(o) { return o instanceof ArrayBuffer } + +function loadArrayBuffer(ac, array, _options) { + return new Promise(function (done, reject) { + ac.decodeAudioData(array, + function (buffer) { done(buffer) }, + function () { reject(`Can't decode audio data (${array.slice(0, 30)}...)`) } + ) + }) +} + +// Load an audio filename +const isAudioFileName = fromRegex(/\.(mp3|wav|ogg)(\?.*)?$/i) + +function loadAudioFile(ac, name, options) { + const url = prefix(options.from, name) + return load(ac, load.fetch(url, 'arraybuffer'), options) +} + +// Load the result of a promise +function isPromise(o) { return o && typeof o.then === 'function' } + +function loadPromise(ac, promise, options) { + return promise.then(function (value) { + return load(ac, value, options) + }) +} + +// COMPOUND OBJECTS +// ================ + +// Try to load all the items of an array +const isArray = Array.isArray + +function loadArrayData(ac, array, options) { + return Promise.all(array.map(data => load(ac, data, options, data))) +} + +// Try to load all the values of a key/value object +function isObject(o) { return o && typeof o === 'object' } + +function loadObjectData(ac, obj, options) { + const dest = {} + const promises = Object.keys(obj).map(function (key) { + if (options.only && options.only.indexOf(key) === -1) + return null + const value = obj[key] + return load(ac, value, options, value) + .then(audio => { + dest[key] = audio + }) + }) + return Promise.all(promises) + .then(() => dest) +} + +// Load the content of a JSON file +const isJsonFileName = fromRegex(/\.json(\?.*)?$/i) + +function loadJsonFile(ac, name, options) { + const url = prefix(options.from, name) + return load(ac, load.fetch(url, 'text').then(JSON.parse), options) +} + +// BASE64 ENCODED FORMATS +// ====================== + +// Load strings with Base64 encoded audio +const isBase64Audio = fromRegex(/^data:audio/) + +function loadBase64Audio(ac, source, options) { + const i = source.indexOf(',') + return load(ac, base64.decode(source.slice(i + 1)).buffer, options) +} + +// Load .js files with MidiJS soundfont prerendered audio +const isJsFileName = fromRegex(/\.js(\?.*)?$/i) + +function loadMidiJSFile(ac, name, options) { + const url = prefix(options.from, name) + return load(ac, load.fetch(url, 'text').then(midiJsToJson), options) +} + +// convert a MIDI.js javascript soundfont file to json +function midiJsToJson(data) { + let begin = data.indexOf('MIDI.Soundfont.') + if (begin < 0) + throw Error('Invalid MIDI.js Soundfont format') + begin = data.indexOf('=', begin) + 2 + const end = data.lastIndexOf(',') + return JSON.parse(data.slice(begin, end) + '}') +} + +module.exports = { load } + +},{"./base64":2,"./fetch":3}],5:[function(require,module,exports){ +/** + * Constants used in player. + */ +const Constants = { + VERSION: '2.0.4', + NOTES: [], + CIRCLE_OF_FOURTHS: ['C', 'F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb', 'Cb', 'Fb', 'Bbb', 'Ebb', 'Abb'], + CIRCLE_OF_FIFTHS: ['C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#', 'G#', 'D#', 'A#', 'E#'] +}; + +// Builds notes object for reference against binary values. +const allNotes = [['C'], ['C#', 'Db'], ['D'], ['D#', 'Eb'], ['E'], ['F'], ['F#', 'Gb'], ['G'], ['G#', 'Ab'], ['A'], ['A#', 'Bb'], ['B']]; +let counter = 0; + +// All available octaves. +for (let i = -1; i <= 9; i++) { + allNotes.forEach(noteGroup => { + noteGroup.forEach(note => Constants.NOTES[counter] = note + i); + counter++; + }); +} + +module.exports.Constants = Constants; + +},{}],6:[function(require,module,exports){ +const Player = require('./player'); +const Soundfont = require('./soundfont-player/index'); +//const AcousticGrandPiano = require('./soundfonts/acoustic_grand_piano-mp3'); + +module.exports = { + Player: Player.Player, + Soundfont: Soundfont.Soundfont, + //AcousticGrandPiano +} + + +},{"./player":8,"./soundfont-player/index":14}],7:[function(require,module,exports){ +'use strict' + +// util +const fillStr = (s, num) => Array(num + 1).join(s) +const isNum = x => typeof x === 'number' +const isStr = x => typeof x === 'string' +const isDef = x => typeof x !== 'undefined' +const midiToFreq = (midi, tuning) => Math.pow(2, (midi - 69) / 12) * (tuning || 440) + +const REGEX = /^([a-gA-G])(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)\s*$/ +/** + * A regex for matching note strings in scientific notation. + * + * @name regex + * @function + * @return {RegExp} the regexp used to parse the note name + * + * The note string should have the form `letter[accidentals][octave][element]` + * where: + * + * - letter: (Required) is a letter from A to G either upper or lower case + * - accidentals: (Optional) can be one or more `b` (flats), `#` (sharps) or `x` (double sharps). + * They can NOT be mixed. + * - octave: (Optional) a positive or negative integer + * - element: (Optional) additionally anything after the duration is considered to + * be the element name (for example: 'C2 dorian') + * + * The executed regex contains (by array index): + * + * - 0: the complete string + * - 1: the note letter + * - 2: the optional accidentals + * - 3: the optional octave + * - 4: the rest of the string (trimmed) + * + * @example + * var parser = require('note-parser') + * parser.regex.exec('c#4') + * // => ['c#4', 'c', '#', '4', ''] + * parser.regex.exec('c#4 major') + * // => ['c#4major', 'c', '#', '4', 'major'] + * parser.regex().exec('CMaj7') + * // => ['CMaj7', 'C', '', '', 'Maj7'] + */ +function regex() { return REGEX }; + +const SEMITONES = [0, 2, 4, 5, 7, 9, 11] +/** + * Parse a note name in scientific notation an return it's components, + * and some numeric properties including midi number and frequency. + * + * @name parse + * @function + * @param {String} note - the note string to be parsed + * @param {Boolean} isTonic - true the strings it's supposed to contain a note number + * and some category (for example an scale: 'C# major'). It's false by default, + * but when true, en extra tonicOf property is returned with the category ('major') + * @param {Float} tunning - The frequency of A4 note to calculate frequencies. + * By default it 440. + * @return {Object} the parsed note name or null if not a valid note + * + * The parsed note name object will ALWAYS contains: + * - letter: the uppercase letter of the note + * - acc: the accidentals of the note (only sharps or flats) + * - pc: the pitch class (letter + acc) + * - step: s a numeric representation of the letter. It's an integer from 0 to 6 + * where 0 = C, 1 = D ... 6 = B + * - alt: a numeric representation of the accidentals. 0 means no alteration, + * positive numbers are for sharps and negative for flats + * - chroma: a numeric representation of the pitch class. It's like midi for + * pitch classes. 0 = C, 1 = C#, 2 = D ... 11 = B. Can be used to find enharmonics + * since, for example, chroma of 'Cb' and 'B' are both 11 + * + * If the note has octave, the parser object will contain: + * - oct: the octave number (as integer) + * - midi: the midi number + * - freq: the frequency (using tuning parameter as base) + * + * If the parameter `isTonic` is set to true, the parsed object will contain: + * - tonicOf: the rest of the string that follows note name (left and right trimmed) + * + * @example + * var parse = require('note-parser').parse + * parse('Cb4') + * // => { letter: 'C', acc: 'b', pc: 'Cb', step: 0, alt: -1, chroma: -1, + * oct: 4, midi: 59, freq: 246.94165062806206 } + * // if no octave, no midi, no freq + * parse('fx') + * // => { letter: 'F', acc: '##', pc: 'F##', step: 3, alt: 2, chroma: 7 }) + */ +function parse(str, isTonic, tuning) { + if (typeof str !== 'string') + return null + const m = REGEX.exec(str) + if (!m || (!isTonic && m[4])) + return null + + const p = { letter: m[1].toUpperCase(), acc: m[2].replace(/x/g, '##') } + p.pc = p.letter + p.acc + p.step = (p.letter.charCodeAt(0) + 3) % 7 + p.alt = p.acc[0] === 'b' ? -p.acc.length : p.acc.length + const pos = SEMITONES[p.step] + p.alt + p.chroma = pos < 0 ? 12 + pos : pos % 12 + if (m[3]) { // has octave + p.oct = +m[3] + p.midi = pos + 12 * (p.oct + 1) + p.freq = midiToFreq(p.midi, tuning) + } + if (isTonic) + p.tonicOf = m[4] + return p +} + +const LETTERS = 'CDEFGAB' +const accStr = n => !isNum(n) ? '' : n < 0 ? fillStr('b', -n) : fillStr('#', n) +const octStr = n => !isNum(n) ? '' : '' + n + +/** + * Create a string from a parsed object or `step, alteration, octave` parameters + * @param {Object} obj - the parsed data object + * @return {String} a note string or null if not valid parameters + * @since 1.2 + * @example + * parser.build(parser.parse('cb2')) // => 'Cb2' + * + * @example + * // it accepts (step, alteration, octave) parameters: + * parser.build(3) // => 'F' + * parser.build(3, -1) // => 'Fb' + * parser.build(3, -1, 4) // => 'Fb4' + */ +function build(s, a, o) { + if (s === null || typeof s === 'undefined') + return null + if (s.step) + return build(s.step, s.alt, s.oct) + if (s < 0 || s > 6) + return null + return LETTERS.charAt(s) + accStr(a) + octStr(o) +} + +/** + * Get midi of a note + * + * @name midi + * @function + * @param {String|Integer} note - the note name or midi number + * @return {Integer} the midi number of the note or null if not a valid note + * or the note does NOT contains octave + * @example + * var parser = require('note-parser') + * parser.midi('A4') // => 69 + * parser.midi('A') // => null + * @example + * // midi numbers are bypassed (even as strings) + * parser.midi(60) // => 60 + * parser.midi('60') // => 60 + */ +function midi(note) { + if ((isNum(note) || isStr(note)) && note >= 0 && note < 128) + return +note + const p = parse(note) + return p && isDef(p.midi) ? p.midi : null +} + +/** + * Get freq of a note in hertzs (in a well tempered 440Hz A4) + * + * @name freq + * @function + * @param {String} note - the note name or note midi number + * @param {String} tuning - (Optional) the A4 frequency (440 by default) + * @return {Float} the freq of the number if hertzs or null if not valid note + * @example + * var parser = require('note-parser') + * parser.freq('A4') // => 440 + * parser.freq('A') // => null + * @example + * // can change tuning (440 by default) + * parser.freq('A4', 444) // => 444 + * parser.freq('A3', 444) // => 222 + * @example + * // it accepts midi numbers (as numbers and as strings) + * parser.freq(69) // => 440 + * parser.freq('69', 442) // => 442 + */ +function freq(note, tuning) { + const m = midi(note) + return m === null ? null : midiToFreq(m, tuning) +} + +const letter = src => (parse(src) || {}).letter +const acc = src => (parse(src) || {}).acc +const pc = src => (parse(src) || {}).pc +const step = src => (parse(src) || {}).step +const alt = src => (parse(src) || {}).alt +const chroma = src => (parse(src) || {}).chroma +const oct = src => (parse(src) || {}).oct + +module.exports = { + regex, + parse, + build, + midi, + freq, + letter, + acc, + pc, + step, + alt, + chroma, + oct, +} + +},{}],8:[function(require,module,exports){ +const Utils = require('./utils').Utils; +const Track = require('./track').Track; + +// Polyfill Uint8Array.forEach: Doesn't exist on Safari <10 +if (!Uint8Array.prototype.forEach) { + Object.defineProperty(Uint8Array.prototype, 'forEach', { + value: Array.prototype.forEach + }); +} + +/** + * Main player class. Contains methods to load files, start, stop. + * @param {function} - Callback to fire for each MIDI event. Can also be added with on('midiEvent', fn) + * @param {array} - Array buffer of MIDI file (optional). + */ +class Player { + constructor(eventHandler, buffer) { + this.sampleRate = 5; // milliseconds + this.startTime = 0; + this.buffer = buffer || null; + this.division; + this.format; + this.setIntervalId = false; + this.tracks = []; + this.instruments = []; + this.defaultTempo = 120; + this.tempo = null; + this.startTick = 0; + this.tick = 0; + this.lastTick = null; + this.inLoop = false; + this.totalTicks = 0; + this.events = []; + this.totalEvents = 0; + this.eventListeners = {}; + + if (typeof (eventHandler) === 'function') this.on('midiEvent', eventHandler); + } + + /** + * Load a file into the player (Node.js only). + * @param {string} path - Path of file. + * @return {Player} + */ + loadFile(path) { + const fs = require('fs'); + this.buffer = fs.readFileSync(path); + return this.fileLoaded(); + } + + /** + * Load an array buffer into the player. + * @param {array} arrayBuffer - Array buffer of file to be loaded. + * @return {Player} + */ + loadArrayBuffer(arrayBuffer) { + this.buffer = new Uint8Array(arrayBuffer); + return this.fileLoaded(); + } + + /** + * Load a data URI into the player. + * @param {string} dataUri - Data URI to be loaded. + * @return {Player} + */ + loadDataUri(dataUri) { + // convert base64 to raw binary data held in a string. + // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this + const byteString = window.atob(dataUri.split(',')[1]); + + // write the bytes of the string to an ArrayBuffer + const ia = new Uint8Array(byteString.length); + for (let i = 0; i < byteString.length; i++) + ia[i] = byteString.charCodeAt(i); + + this.buffer = ia; + return this.fileLoaded(); + } + + /** + * Get filesize of loaded file in number of bytes. + * @return {number} - The filesize. + */ + getFilesize() { + return this.buffer ? this.buffer.length : 0; + } + + /** + * Sets default tempo, parses file for necessary information, and does a dry run to calculate total length. + * Populates this.events & this.totalTicks. + * @return {Player} + */ + fileLoaded() { + if (!this.validate()) throw 'Invalid MIDI file; should start with MThd'; + return this.setTempo(this.defaultTempo).getDivision().getFormat().getTracks().dryRun(); + } + + /** + * Validates file using simple means - first four bytes should == MThd. + * @return {boolean} + */ + validate() { + return Utils.bytesToLetters(this.buffer.subarray(0, 4)) === 'MThd'; + } + + /** + * Gets MIDI file format for loaded file. + * @return {Player} + */ + getFormat() { + /* + MIDI files come in 3 variations: + Format 0 which contain a single track + Format 1 which contain one or more simultaneous tracks + (ie all tracks are to be played simultaneously). + Format 2 which contain one or more independant tracks + (ie each track is to be played independantly of the others). + return Utils.bytesToNumber(this.buffer.subarray(8, 10)); + */ + + this.format = Utils.bytesToNumber(this.buffer.subarray(8, 10)); + return this; + } + + /** + * Parses out tracks, places them in this.tracks and initializes this.pointers + * @return {Player} + */ + getTracks() { + this.tracks = []; + let trackOffset = 0; + while (trackOffset < this.buffer.length) { + if (Utils.bytesToLetters(this.buffer.subarray(trackOffset, trackOffset + 4)) == 'MTrk') { + let trackLength = Utils.bytesToNumber(this.buffer.subarray(trackOffset + 4, trackOffset + 8)); + this.tracks.push(new Track(this.tracks.length, this.buffer.subarray(trackOffset + 8, trackOffset + 8 + trackLength))); + } + + trackOffset += Utils.bytesToNumber(this.buffer.subarray(trackOffset + 4, trackOffset + 8)) + 8; + } + return this; + } + + /** + * Enables a track for playing. + * @param {number} trackNumber - Track number + * @return {Player} + */ + enableTrack(trackNumber) { + this.tracks[trackNumber - 1].enable(); + return this; + } + + /** + * Disables a track for playing. + * @param {number} - Track number + * @return {Player} + */ + disableTrack(trackNumber) { + this.tracks[trackNumber - 1].disable(); + return this; + } + + /** + * Gets quarter note division of loaded MIDI file. + * @return {Player} + */ + getDivision() { + this.division = Utils.bytesToNumber(this.buffer.subarray(12, 14)); + return this; + } + + /** + * The main play loop. + * @param {boolean} - Indicates whether or not this is being called simply for parsing purposes. Disregards timing if so. + * @return {undefined} + */ + playLoop(dryRun) { + if (!this.inLoop) { + this.inLoop = true; + this.tick = this.getCurrentTick(); + + this.tracks.forEach(function (track) { + // Handle next event + if (!dryRun && this.endOfFile()) { + //console.log('end of file') + this.triggerPlayerEvent('endOfFile'); + this.stop(); + } else { + let event = track.handleEvent(this.tick, dryRun); + + if (dryRun && event) { + if (event.hasOwnProperty('name') && event.name === 'Set Tempo') { + // Grab tempo if available. + this.setTempo(event.data); + } + if (event.hasOwnProperty('name') && event.name === 'Program Change') { + if (!this.instruments.includes(event.value)) { + this.instruments.push(event.value); + } + } + } else if (event) this.emitEvent(event); + } + + }, this); + + if (!dryRun) this.triggerPlayerEvent('playing', { tick: this.tick }); + this.inLoop = false; + } + } + + /** + * Setter for tempo. + * @param {number} - Tempo in bpm (defaults to 120) + */ + setTempo(tempo) { + this.tempo = tempo; + return this; + } + + /** + * Setter for startTime. + * @param {number} - UTC timestamp + */ + setStartTime(startTime) { + this.startTime = startTime; + } + + /** + * Start playing loaded MIDI file if not already playing. + * @return {Player} + */ + play() { + if (this.isPlaying()) + throw 'Already playing...'; + + // Initialize + if (!this.startTime) + this.startTime = (new Date()).getTime(); + + // Start play loop + //window.requestAnimationFrame(this.playLoop.bind(this)); + this.setIntervalId = window.setInterval(this.playLoop.bind(this), this.sampleRate); + + return this; + } + + /** + * Pauses playback if playing. + * @return {Player} + */ + pause() { + clearInterval(this.setIntervalId); + this.setIntervalId = false; + this.startTick = this.tick; + this.startTime = 0; + return this; + } + + /** + * Stops playback if playing. + * @return {Player} + */ + stop() { + clearInterval(this.setIntervalId); + this.setIntervalId = false; + this.startTick = 0; + this.startTime = 0; + this.resetTracks(); + return this; + } + + /** + * Skips player pointer to specified tick. + * @param {number} - Tick to skip to. + * @return {Player} + */ + skipToTick(tick) { + this.stop(); + this.startTick = tick; + + // Need to set track event indexes to the nearest possible event to the specified tick. + this.tracks.forEach(function (track) { + track.setEventIndexByTick(tick); + }); + return this; + } + + /** + * Skips player pointer to specified percentage. + * @param {number} - Percent value in integer format. + * @return {Player} + */ + skipToPercent(percent) { + if (percent < 0 || percent > 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} + */ + skipToSeconds(seconds) { + const 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} + */ + 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} + */ + 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} + */ + resetTracks() { + this.tracks.forEach(track => track.reset()); + return this; + } + + /** + * Gets an array of events grouped by track. + * @return {array} + */ + getEvents() { + return this.tracks.map(track => track.events); + } + + /** + * Gets total number of ticks in the loaded MIDI file. + * @return {number} + */ + getTotalTicks() { + return Math.max.apply(null, this.tracks.map(track => track.delta)); + } + + /** + * Gets total number of events in the loaded MIDI file. + * @return {number} + */ + getTotalEvents() { + return this.tracks.reduce( + (a, b) => { return { events: { length: a.events.length + b.events.length } } }, + { events: { length: 0 } } + ).events.length; + } + + /** + * Gets song duration in seconds. + * @return {number} + */ + getSongTime() { + return this.totalTicks / this.division / this.tempo * 60; + } + + /** + * Gets remaining number of seconds in playback. + * @return {number} + */ + getSongTimeRemaining() { + return Math.round((this.totalTicks - this.tick) / this.division / this.tempo * 60); + } + + /** + * Gets remaining percent of playback. + * @return {number} + */ + getSongPercentRemaining() { + return Math.round(this.getSongTimeRemaining() / this.getSongTime() * 100); + } + + /** + * Number of bytes processed in the loaded MIDI file. + * @return {number} + */ + bytesProcessed() { + // Currently assume header chunk is strictly 14 bytes + return 14 + this.tracks.length * 8 + this.tracks.reduce((a, b) => { return { pointer: a.pointer + b.pointer } }, { pointer: 0 }).pointer; + } + + /** + * Number of events played up to this point. + * @return {number} + */ + eventsPlayed() { + return this.tracks.reduce((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} + */ + endOfFile() { + if (this.isPlaying()) + return this.eventsPlayed() == this.totalEvents; + + return this.bytesProcessed() == this.buffer.length; + } + + /** + * Gets the current tick number in playback. + * @return {number} + */ + 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} + */ + 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} + */ + 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} + */ + triggerPlayerEvent(playerEvent, data) { + if (this.eventListeners.hasOwnProperty(playerEvent)) + this.eventListeners[playerEvent].forEach(fn => fn(data || {})); + return this; + } + +} + +module.exports = { Player } + +},{"./track":15,"./utils":16,"fs":undefined}],9:[function(require,module,exports){ + +module.exports = function (player) { + /** + * Adds a listener of an event + * @chainable + * @param {String} event - the event name + * @param {Function} callback - the event handler + * @return {SamplePlayer} the player + * @example + * player.on('start', function(time, note) { + * console.log(time, note) + * }) + */ + player.on = function (event, cb) { + if (arguments.length === 1 && typeof event === 'function') return player.on('event', event) + var prop = 'on' + event + var old = player[prop] + player[prop] = old ? chain(old, cb) : cb + return player + } + return player +} + +function chain (fn1, fn2) { + return function (a, b, c, d) { fn1(a, b, c, d); fn2(a, b, c, d) } +} + +},{}],10:[function(require,module,exports){ +'use strict' + +const player = require('./player') +const events = require('./events') +const notes = require('./notes') +const scheduler = require('./scheduler') +//const midi = require('./midi') + +function SamplePlayer(ac, source, options) { + //return midi(scheduler(notes(events(player(ac, source, options))))) + return scheduler(notes(events(player(ac, source, options)))) +} + +module.exports = { SamplePlayer } + +},{"./events":9,"./notes":11,"./player":12,"./scheduler":13}],11:[function(require,module,exports){ +'use strict' + +var note = require('../note-parser/index') +var isMidi = function (n) { return n !== null && n !== [] && n >= 0 && n < 129 } +var toMidi = function (n) { return isMidi(n) ? +n : note.midi(n) } + +// Adds note name to midi conversion +module.exports = function (player) { + if (player.buffers) { + var map = player.opts.map + var toKey = typeof map === 'function' ? map : toMidi + var mapper = function (name) { + return name ? toKey(name) || name : null + } + + player.buffers = mapBuffers(player.buffers, mapper) + var start = player.start + player.start = function (name, when, options) { + var key = mapper(name) + var dec = key % 1 + if (dec) { + key = Math.floor(key) + options = Object.assign(options || {}, { cents: Math.floor(dec * 100) }) + } + return start(key, when, options) + } + } + return player +} + +function mapBuffers(buffers, toKey) { + return Object.keys(buffers).reduce(function (mapped, name) { + mapped[toKey(name)] = buffers[name] + return mapped + }, {}) +} + +},{"../note-parser/index":7}],12:[function(require,module,exports){ +/* global AudioBuffer */ +'use strict' + +const ADSR = require('../adsr/index') + +const EMPTY = {} +const DEFAULTS = { + gain: 1, + attack: 0.01, + decay: 0.1, + sustain: 0.9, + release: 0.3, + loop: false, + cents: 0, + loopStart: 0, + loopEnd: 0 +} + +/** + * Create a sample player. + * + * @param {AudioContext} ac - the audio context + * @param {ArrayBuffer|Object} source + * @param {Onject} options - (Optional) an options object + * @return {player} the player + * @example + * const SamplePlayer = require('sample-player') + * const ac = new AudioContext() + * const snare = SamplePlayer(ac, ) + * snare.play() + */ +function SamplePlayer(ac, source, options) { + let connected = false + let nextId = 0 + let tracked = {} + const out = ac.createGain() + out.gain.value = 1 + + const opts = Object.assign({}, DEFAULTS, options) + + /** + * @namespace + */ + const player = { context: ac, out, opts } + if (source instanceof AudioBuffer) + player.buffer = source + else + player.buffers = source + + /** + * Start a sample buffer. + * + * The returned object has a function `stop(when)` to stop the sound. + * + * @param {String} name - the name of the buffer. If the source of the + * SamplePlayer is one sample buffer, this parameter is not required + * @param {Float} when - (Optional) when to start (current time if by default) + * @param {Object} options - additional sample playing options + * @return {AudioNode} an audio node with a `stop` function + * @example + * var sample = player(ac, ).connect(ac.destination) + * sample.start() + * sample.start(5, { gain: 0.7 }) // name not required since is only one AudioBuffer + * @example + * var drums = player(ac, { snare: , kick: , ... }).connect(ac.destination) + * drums.start('snare') + * drums.start('snare', 0, { gain: 0.3 }) + */ + player.start = function (name, when, options) { + // if only one buffer, reorder arguments + if (player.buffer && name !== null) + return player.start(null, name, when) + + var buffer = name ? player.buffers[name] : player.buffer + if (!buffer) { + console.warn(`Buffer ${name} not found.`) + return + } else if (!connected) { + console.warn('SamplePlayer not connected to any node.') + return + } + + const opts = options || EMPTY + when = Math.max(ac.currentTime, when || 0) + player.emit('start', when, name, opts) + var node = createNode(name, buffer, opts) + node.id = track(name, node) + node.env.start(when) + node.source.start(when) + player.emit('started', when, node.id, node) + if (opts.duration) + node.stop(when + opts.duration) + return node + } + + // NOTE: start will be override so we can't copy the function reference + // this is obviously not a good design, so this code will be gone soon. + /** + * An alias for `player.start` + * @see player.start + * @since 0.3.0 + */ + player.play = function (name, when, options) { + return player.start(name, when, options) + } + + /** + * Stop some or all samples + * + * @param {Float} when - (Optional) an absolute time in seconds (or currentTime + * if not specified) + * @param {Array} nodes - (Optional) an array of nodes or nodes ids to stop + * @return {Array} an array of ids of the stoped samples + * + * @example + * var longSound = player(ac, ).connect(ac.destination) + * longSound.start(ac.currentTime) + * longSound.start(ac.currentTime + 1) + * longSound.start(ac.currentTime + 2) + * longSound.stop(ac.currentTime + 3) // stop the three sounds + */ + player.stop = function (when, ids) { + ids = ids || Object.keys(tracked) + return ids.map(function (id) { + const node = tracked[id] + if (!node) return null + node.stop(when) + return node.id + }) + } + /** + * Connect the player to a destination node + * + * @param {AudioNode} destination - the destination node + * @return {AudioPlayer} the player + * @chainable + * @example + * var sample = player(ac, ).connect(ac.destination) + */ + player.connect = function (dest) { + connected = true + out.connect(dest) + return player + } + + player.emit = function (event, when, obj, opts) { + if (player.onevent) player.onevent(event, when, obj, opts) + const fn = player['on' + event] + if (fn) fn(when, obj, opts) + } + + return player + + // =============== PRIVATE FUNCTIONS ============== // + + function track(name, node) { + node.id = nextId++ + tracked[node.id] = node + node.source.onended = function () { + const now = ac.currentTime + node.source.disconnect() + node.env.disconnect() + node.disconnect() + player.emit('ended', now, node.id, node) + } + return node.id + } + + function createNode(name, buffer, options) { + const node = ac.createGain() + node.gain.value = 0 // the envelope will control the gain + node.connect(out) + + node.env = envelope(ac, options, opts) + node.env.connect(node.gain) + + node.source = ac.createBufferSource() + node.source.buffer = buffer + node.source.connect(node) + node.source.loop = options.loop || opts.loop + node.source.playbackRate.value = centsToRate(options.cents || opts.cents) + node.source.loopStart = options.loopStart || opts.loopStart + node.source.loopEnd = options.loopEnd || opts.loopEnd + node.stop = function (when) { + const time = when || ac.currentTime + player.emit('stop', time, name) + const stopAt = node.env.stop(time) + node.source.stop(stopAt) + } + return node + } +} + +function isNum(x) { return typeof x === 'number' } + +const PARAMS = ['attack', 'decay', 'sustain', 'release'] + +function envelope(ac, options, opts) { + const env = ADSR(ac) + const adsr = options.adsr || opts.adsr + PARAMS.forEach(function (name, i) { + if (adsr) env[name] = adsr[i] + else env[name] = options[name] || opts[name] + }) + env.value.value = isNum(options.gain) ? options.gain + : isNum(opts.gain) ? opts.gain : 1 + return env +} + +/* + * Get playback rate for a given pitch change (in cents) + * Basic [math](http://www.birdsoft.demon.co.uk/music/samplert.htm): + * f2 = f1 * 2^( C / 1200 ) + */ +function centsToRate(cents) { return cents ? Math.pow(2, cents / 1200) : 1 } + +module.exports = SamplePlayer + +},{"../adsr/index":1}],13:[function(require,module,exports){ +'use strict' + +var isArr = Array.isArray +var isObj = function (o) { return o && typeof o === 'object' } +var OPTS = {} + +module.exports = function (player) { + /** + * Schedule a list of events to be played at specific time. + * + * It supports three formats of events for the events list: + * + * - An array with [time, note] + * - An array with [time, object] + * - An object with { time: ?, [name|note|midi|key]: ? } + * + * @param {Float} time - an absolute time to start (or AudioContext's + * currentTime if provided number is 0) + * @param {Array} events - the events list. + * @return {Array} an array of ids + * + * @example + * // Event format: [time, note] + * var piano = player(ac, ...).connect(ac.destination) + * piano.schedule(0, [ [0, 'C2'], [0.5, 'C3'], [1, 'C4'] ]) + * + * @example + * // Event format: an object { time: ?, name: ? } + * var drums = player(ac, ...).connect(ac.destination) + * drums.schedule(0, [ + * { name: 'kick', time: 0 }, + * { name: 'snare', time: 0.5 }, + * { name: 'kick', time: 1 }, + * { name: 'snare', time: 1.5 } + * ]) + */ + player.schedule = function (time, events) { + var now = player.context.currentTime + var when = time < now ? now : time + player.emit('schedule', when, events) + var t, o, note, opts + return events.map(function (event) { + if (!event) return null + else if (isArr(event)) { + t = event[0]; o = event[1] + } else { + t = event.time; o = event + } + + if (isObj(o)) { + note = o.name || o.key || o.note || o.midi || null + opts = o + } else { + note = o + opts = OPTS + } + + return player.start(note, when + (t || 0), opts) + }) + } + return player +} + +},{}],14:[function(require,module,exports){ +'use strict' + +const load = require('../audio-loader/index').load +const player = require('../sample-player/index').SamplePlayer + +/** + * Load a soundfont instrument. It returns a promise that resolves to a + * instrument object. + * + * The instrument object returned by the promise has the following properties: + * + * - name: the instrument name + * - play: A function to play notes from the buffer with the signature + * `play(note, time, duration, options)` + * + * + * The valid options are: + * + * - `format`: the soundfont format. 'mp3' by default. Can be 'ogg' + * - `soundfont`: the soundfont name. 'MusyngKite' by default. Can be 'FluidR3_GM' + * - `nameToUrl` : a function to convert from instrument names to URL + * - `destination`: by default Soundfont uses the `audioContext.destination` but you can override it. + * - `gain`: the gain of the player (1 by default) + * - `notes`: an array of the notes to decode. It can be an array of strings + * with note names or an array of numbers with midi note numbers. This is a + * performance option: since decoding mp3 is a cpu intensive process, you can limit + * limit the number of notes you want and reduce the time to load the instrument. + * + * @param {AudioContext} ac - the audio context + * @param {String} name - the instrument name. For example: 'acoustic_grand_piano' + * @param {Object} options - (Optional) the same options as Soundfont.loadBuffers + * @return {Promise} + * + * @example + * var Soundfont = require('sounfont-player') + * Soundfont.instrument('marimba').then(function (marimba) { + * marimba.play('C4') + * }) + */ +function instrument(ac, source, options = {}) { + if (arguments.length === 1) + return function (n, o) { return instrument(ac, n, o) } + + let instName = '', instUrl = ''; + if (typeof source === 'string') { + instName = source + const isUrl = options.isSoundfontURL || isSoundfontURL + const toUrl = options.nameToUrl || nameToUrl + instUrl = isUrl(source) ? source : toUrl(source, options.soundfont, options.format) + source = instUrl + } + + return load(ac, source, { only: options.only || options.notes }) + .then(buffers => { + const p = player(ac, buffers, options).connect(options.destination ? options.destination : ac.destination) + p.url = instUrl + p.name = instName + return p + }) +} + +function isSoundfontURL(name) { + return /\.js(\?.*)?$/i.test(name) +} + +/** + * Given an instrument name returns a URL to to the Benjamin Gleitzman's + * package of [pre-rendered sound fonts](https://github.com/gleitz/midi-js-soundfonts) + * + * @param {String} name - instrument name + * @param {String} soundfont - (Optional) the soundfont name. One of 'FluidR3_GM' + * or 'MusyngKite' ('MusyngKite' by default) + * @param {String} format - (Optional) Can be 'mp3' or 'ogg' (mp3 by default) + * @returns {String} the Soundfont file url + * @example + * var Soundfont = require('soundfont-player') + * Soundfont.nameToUrl('marimba', 'mp3') + */ +function nameToUrl(name, sf, format) { + format = format === 'ogg' ? format : 'mp3' + sf = sf === 'FluidR3_GM' ? sf : 'MusyngKite' + return 'https://gleitz.github.io/midi-js-soundfonts/' + sf + '/' + name + '-' + format + '.js' +} + +const Soundfont = { + instrument, + nameToUrl, +} + +module.exports = { Soundfont } + +},{"../audio-loader/index":4,"../sample-player/index":10}],15:[function(require,module,exports){ +const Constants = require('./constants').Constants; +const Utils = require('./utils').Utils; + +/** + * Class representing a track. Contains methods for parsing events and keeping track of pointer. + */ +class Track { + constructor(index, data) { + 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} + */ + 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} + */ + enable() { + this.enabled = true; + return this; + } + + /** + * Sets this track to be disabled during playback. + * @return {Track} + */ + disable() { + this.enabled = false; + return this; + } + + /** + * Sets the track event index to the nearest event to the given tick. + * @param {number} tick + * @return {Track} + */ + setEventIndexByTick(tick) { + tick = tick || 0; + + for (let i in this.events) { + if (this.events[i].tick >= tick) { + this.eventIndex = i; + return this; + } + } + } + + /** + * Gets byte located at pointer position. + * @return {number} + */ + getCurrentByte() { + return this.data[this.pointer]; + } + + /** + * Gets count of delta bytes and current pointer position. + * @return {number} + */ + 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. + let currentByte = this.getCurrentByte(); + let byteCount = 1; + + while (currentByte >= 128) { + currentByte = this.data[this.pointer + byteCount]; + byteCount++; + } + + return byteCount; + } + + /** + * Get delta value at current pointer position. + * @return {number} + */ + 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. + */ + handleEvent(currentTick, dryRun) { + dryRun = dryRun || false; + + if (dryRun) { + const elapsedTicks = currentTick - this.lastTick; + const delta = this.getDelta(); + const eventReady = elapsedTicks >= delta; + + if (this.pointer < this.data.length && (dryRun || eventReady)) { + const 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} + */ + getStringData(eventStartIndex) { + //const currentByte = this.pointer; + const byteCount = 1; + const length = Utils.readVarInt(this.data.subarray(eventStartIndex + 2, eventStartIndex + 2 + byteCount)); + //const 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} + */ + parseEvent() { + const eventStartIndex = this.pointer + this.getDeltaByteCount(); + const eventJson = {}; + const 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 + // FF 58 04 nn dd cc bb + eventJson.name = 'Time Signature'; + eventJson.data = this.data.subarray(eventStartIndex + 3, eventStartIndex + 7); + eventJson.timeSignature = "" + eventJson.data[0] + "/" + Math.pow(2, eventJson.data[1]); + break; + case 0x59: // Key Signature + // FF 59 02 sf mi + eventJson.name = 'Key Signature'; + eventJson.data = this.data.subarray(eventStartIndex + 3, eventStartIndex + 5); + + if (eventJson.data[0] >= 0) { + eventJson.keySignature = Constants.CIRCLE_OF_FIFTHS[eventJson.data[0]]; + + } else if (eventJson.data[0] < 0) { + eventJson.keySignature = Constants.CIRCLE_OF_FOURTHS[Math.abs(eventJson.data[0])]; + } + + if (eventJson.data[1] == 0) { + eventJson.keySignature += ' Major'; + + } else if (eventJson.data[1] == 1) { + eventJson.keySignature += ' Minor'; + } + + 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; + } + + const 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'; + const 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} + */ + endOfTrack() { + if (this.data[this.pointer + 1] == 0xff && this.data[this.pointer + 2] == 0x2f && this.data[this.pointer + 3] == 0x00) + return true; + + return false; + } +} + +module.exports = { Track } + +},{"./constants":5,"./utils":16}],16:[function(require,module,exports){ +/** + * Contains misc static utility methods. + */ +class Utils { + + /** + * Converts a single byte to a hex string. + * @param {number} byte + * @return {string} + */ + static 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} + */ + static bytesToHex(byteArray) { + const hex = []; + byteArray.forEach(byte => hex.push(Utils.byteToHex(byte))); + return hex.join(''); + } + + /** + * Converts a hex string to a number. + * @param {string} hexString + * @return {number} + */ + static hexToNumber(hexString) { + return parseInt(hexString, 16); + } + + /** + * Converts an array of bytes to a number. + * @param {array} byteArray + * @return {number} + */ + static bytesToNumber(byteArray) { + return Utils.hexToNumber(Utils.bytesToHex(byteArray)); + } + + /** + * Converts an array of bytes to letters. + * @param {array} byteArray + * @return {string} + */ + static bytesToLetters(byteArray) { + const letters = []; + byteArray.forEach(byte => letters.push(String.fromCharCode(byte))); + return letters.join(''); + } + + /** + * Converts a decimal to it's binary representation. + * @param {number} dec + * @return {string} + */ + static decToBinary(dec) { + return (dec >>> 0).toString(2); + } + + /** + * Reads a variable length value. + * @param {array} byteArray + * @return {number} + */ + static readVarInt(byteArray) { + let result = 0; + byteArray.forEach(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} + */ + /* Only for NodeJS! + static atob(string) { + if (typeof atob === 'function') return atob(string); + return new Buffer(string, 'base64').toString('binary'); + } + */ +} + +module.exports = { Utils } +},{}]},{},[6])(6) +}); + +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvYWRzci9pbmRleC5qcyIsInNyYy9hdWRpby1sb2FkZXIvYmFzZTY0LmpzIiwic3JjL2F1ZGlvLWxvYWRlci9mZXRjaC5qcyIsInNyYy9hdWRpby1sb2FkZXIvaW5kZXguanMiLCJzcmMvY29uc3RhbnRzLmpzIiwic3JjL2luZGV4LmpzIiwic3JjL25vdGUtcGFyc2VyL2luZGV4LmpzIiwic3JjL3BsYXllci5qcyIsInNyYy9zYW1wbGUtcGxheWVyL2V2ZW50cy5qcyIsInNyYy9zYW1wbGUtcGxheWVyL2luZGV4LmpzIiwic3JjL3NhbXBsZS1wbGF5ZXIvbm90ZXMuanMiLCJzcmMvc2FtcGxlLXBsYXllci9wbGF5ZXIuanMiLCJzcmMvc2FtcGxlLXBsYXllci9zY2hlZHVsZXIuanMiLCJzcmMvc291bmRmb250LXBsYXllci9pbmRleC5qcyIsInNyYy90cmFjay5qcyIsInNyYy91dGlscy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoZUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDek5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIlxuZnVuY3Rpb24gQURTUihhdWRpb0NvbnRleHQpIHtcbiAgY29uc3Qgbm9kZSA9IGF1ZGlvQ29udGV4dC5jcmVhdGVHYWluKClcblxuICBjb25zdCB2b2x0YWdlID0gbm9kZS5fdm9sdGFnZSA9IGdldFZvbHRhZ2UoYXVkaW9Db250ZXh0KVxuICBjb25zdCB2YWx1ZSA9IHNjYWxlKHZvbHRhZ2UpXG4gIGNvbnN0IHN0YXJ0VmFsdWUgPSBzY2FsZSh2b2x0YWdlKVxuICBjb25zdCBlbmRWYWx1ZSA9IHNjYWxlKHZvbHRhZ2UpXG5cbiAgbm9kZS5fc3RhcnRBbW91bnQgPSBzY2FsZShzdGFydFZhbHVlKVxuICBub2RlLl9lbmRBbW91bnQgPSBzY2FsZShlbmRWYWx1ZSlcblxuICBub2RlLl9tdWx0aXBsaWVyID0gc2NhbGUodmFsdWUpXG4gIG5vZGUuX211bHRpcGxpZXIuY29ubmVjdChub2RlKVxuICBub2RlLl9zdGFydEFtb3VudC5jb25uZWN0KG5vZGUpXG4gIG5vZGUuX2VuZEFtb3VudC5jb25uZWN0KG5vZGUpXG5cbiAgbm9kZS52YWx1ZSA9IHZhbHVlLmdhaW5cbiAgbm9kZS5zdGFydFZhbHVlID0gc3RhcnRWYWx1ZS5nYWluXG4gIG5vZGUuZW5kVmFsdWUgPSBlbmRWYWx1ZS5nYWluXG5cbiAgbm9kZS5zdGFydFZhbHVlLnZhbHVlID0gMFxuICBub2RlLmVuZFZhbHVlLnZhbHVlID0gMFxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKVxuICByZXR1cm4gbm9kZVxufVxuXG5jb25zdCBwcm9wcyA9IHtcblxuICBhdHRhY2s6IHsgdmFsdWU6IDAsIHdyaXRhYmxlOiB0cnVlIH0sXG4gIGRlY2F5OiB7IHZhbHVlOiAwLCB3cml0YWJsZTogdHJ1ZSB9LFxuICBzdXN0YWluOiB7IHZhbHVlOiAxLCB3cml0YWJsZTogdHJ1ZSB9LFxuICByZWxlYXNlOiB7IHZhbHVlOiAwLCB3cml0YWJsZTogdHJ1ZSB9LFxuXG4gIGdldFJlbGVhc2VEdXJhdGlvbjoge1xuICAgIHZhbHVlOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWxlYXNlXG4gICAgfVxuICB9LFxuXG4gIHN0YXJ0OiB7XG4gICAgdmFsdWU6IGZ1bmN0aW9uIChhdCkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5fbXVsdGlwbGllci5nYWluXG4gICAgICBjb25zdCBzdGFydEFtb3VudCA9IHRoaXMuX3N0YXJ0QW1vdW50LmdhaW5cbiAgICAgIGNvbnN0IGVuZEFtb3VudCA9IHRoaXMuX2VuZEFtb3VudC5nYWluXG5cbiAgICAgIHRoaXMuX3ZvbHRhZ2Uuc3RhcnQoYXQpXG4gICAgICB0aGlzLl9kZWNheUZyb20gPSB0aGlzLl9kZWNheUZyb20gPSBhdCArIHRoaXMuYXR0YWNrXG4gICAgICB0aGlzLl9zdGFydGVkQXQgPSBhdFxuXG4gICAgICBjb25zdCBzdXN0YWluID0gdGhpcy5zdXN0YWluXG5cbiAgICAgIHRhcmdldC5jYW5jZWxTY2hlZHVsZWRWYWx1ZXMoYXQpXG4gICAgICBzdGFydEFtb3VudC5jYW5jZWxTY2hlZHVsZWRWYWx1ZXMoYXQpXG4gICAgICBlbmRBbW91bnQuY2FuY2VsU2NoZWR1bGVkVmFsdWVzKGF0KVxuXG4gICAgICBlbmRBbW91bnQuc2V0VmFsdWVBdFRpbWUoMCwgYXQpXG5cbiAgICAgIGlmICh0aGlzLmF0dGFjaykge1xuICAgICAgICB0YXJnZXQuc2V0VmFsdWVBdFRpbWUoMCwgYXQpXG4gICAgICAgIHRhcmdldC5saW5lYXJSYW1wVG9WYWx1ZUF0VGltZSgxLCBhdCArIHRoaXMuYXR0YWNrKVxuXG4gICAgICAgIHN0YXJ0QW1vdW50LnNldFZhbHVlQXRUaW1lKDEsIGF0KVxuICAgICAgICBzdGFydEFtb3VudC5saW5lYXJSYW1wVG9WYWx1ZUF0VGltZSgwLCBhdCArIHRoaXMuYXR0YWNrKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGFyZ2V0LnNldFZhbHVlQXRUaW1lKDEsIGF0KVxuICAgICAgICBzdGFydEFtb3VudC5zZXRWYWx1ZUF0VGltZSgwLCBhdClcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZGVjYXkpIHtcbiAgICAgICAgdGFyZ2V0LnNldFRhcmdldEF0VGltZShzdXN0YWluLCB0aGlzLl9kZWNheUZyb20sIGdldFRpbWVDb25zdGFudCh0aGlzLmRlY2F5KSlcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgc3RvcDoge1xuICAgIHZhbHVlOiBmdW5jdGlvbiAoYXQsIGlzVGFyZ2V0KSB7XG4gICAgICBpZiAoaXNUYXJnZXQpIHtcbiAgICAgICAgYXQgPSBhdCAtIHRoaXMucmVsZWFzZVxuICAgICAgfVxuXG4gICAgICBjb25zdCBlbmRUaW1lID0gYXQgKyB0aGlzLnJlbGVhc2VcbiAgICAgIGlmICh0aGlzLnJlbGVhc2UpIHtcblxuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLl9tdWx0aXBsaWVyLmdhaW5cbiAgICAgICAgY29uc3Qgc3RhcnRBbW91bnQgPSB0aGlzLl9zdGFydEFtb3VudC5nYWluXG4gICAgICAgIGNvbnN0IGVuZEFtb3VudCA9IHRoaXMuX2VuZEFtb3VudC5nYWluXG5cbiAgICAgICAgdGFyZ2V0LmNhbmNlbFNjaGVkdWxlZFZhbHVlcyhhdClcbiAgICAgICAgc3RhcnRBbW91bnQuY2FuY2VsU2NoZWR1bGVkVmFsdWVzKGF0KVxuICAgICAgICBlbmRBbW91bnQuY2FuY2VsU2NoZWR1bGVkVmFsdWVzKGF0KVxuXG4gICAgICAgIGNvbnN0IGV4cEZhbGxvZmYgPSBnZXRUaW1lQ29uc3RhbnQodGhpcy5yZWxlYXNlKVxuXG4gICAgICAgIC8vIHRydW5jYXRlIGF0dGFjayAocmVxdWlyZWQgYXMgbGluZWFyUmFtcCBpcyByZW1vdmVkIGJ5IGNhbmNlbFNjaGVkdWxlZFZhbHVlcylcbiAgICAgICAgaWYgKHRoaXMuYXR0YWNrICYmIGF0IDwgdGhpcy5fZGVjYXlGcm9tKSB7XG4gICAgICAgICAgY29uc3QgdmFsdWVBdFRpbWUgPSBnZXRWYWx1ZSgwLCAxLCB0aGlzLl9zdGFydGVkQXQsIHRoaXMuX2RlY2F5RnJvbSwgYXQpXG4gICAgICAgICAgdGFyZ2V0LmxpbmVhclJhbXBUb1ZhbHVlQXRUaW1lKHZhbHVlQXRUaW1lLCBhdClcbiAgICAgICAgICBzdGFydEFtb3VudC5saW5lYXJSYW1wVG9WYWx1ZUF0VGltZSgxIC0gdmFsdWVBdFRpbWUsIGF0KVxuICAgICAgICAgIHN0YXJ0QW1vdW50LnNldFRhcmdldEF0VGltZSgwLCBhdCwgZXhwRmFsbG9mZilcbiAgICAgICAgfVxuXG4gICAgICAgIGVuZEFtb3VudC5zZXRUYXJnZXRBdFRpbWUoMSwgYXQsIGV4cEZhbGxvZmYpXG4gICAgICAgIHRhcmdldC5zZXRUYXJnZXRBdFRpbWUoMCwgYXQsIGV4cEZhbGxvZmYpXG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3ZvbHRhZ2Uuc3RvcChlbmRUaW1lKVxuICAgICAgcmV0dXJuIGVuZFRpbWVcbiAgICB9XG4gIH0sXG5cbiAgb25lbmRlZDoge1xuICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZvbHRhZ2Uub25lbmRlZFxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgIHRoaXMuX3ZvbHRhZ2Uub25lbmRlZCA9IHZhbHVlXG4gICAgfVxuICB9XG5cbn1cblxuY29uc3QgZmxhdCA9IG5ldyBGbG9hdDMyQXJyYXkoWzEsIDFdKVxuZnVuY3Rpb24gZ2V0Vm9sdGFnZShjb250ZXh0KSB7XG4gIGNvbnN0IHZvbHRhZ2UgPSBjb250ZXh0LmNyZWF0ZUJ1ZmZlclNvdXJjZSgpXG4gIGNvbnN0IGJ1ZmZlciA9IGNvbnRleHQuY3JlYXRlQnVmZmVyKDEsIDIsIGNvbnRleHQuc2FtcGxlUmF0ZSlcbiAgYnVmZmVyLmdldENoYW5uZWxEYXRhKDApLnNldChmbGF0KVxuICB2b2x0YWdlLmJ1ZmZlciA9IGJ1ZmZlclxuICB2b2x0YWdlLmxvb3AgPSB0cnVlXG4gIHJldHVybiB2b2x0YWdlXG59XG5cbmZ1bmN0aW9uIHNjYWxlKG5vZGUpIHtcbiAgY29uc3QgZ2FpbiA9IG5vZGUuY29udGV4dC5jcmVhdGVHYWluKClcbiAgbm9kZS5jb25uZWN0KGdhaW4pXG4gIHJldHVybiBnYWluXG59XG5cbmZ1bmN0aW9uIGdldFRpbWVDb25zdGFudCh0aW1lKSB7XG4gIHJldHVybiBNYXRoLmxvZyh0aW1lICsgMSkgLyBNYXRoLmxvZygxMDApXG59XG5cbmZ1bmN0aW9uIGdldFZhbHVlKHN0YXJ0LCBlbmQsIGZyb21UaW1lLCB0b1RpbWUsIGF0KSB7XG4gIGNvbnN0IGRpZmZlcmVuY2UgPSBlbmQgLSBzdGFydFxuICBjb25zdCB0aW1lID0gdG9UaW1lIC0gZnJvbVRpbWVcbiAgY29uc3QgdHJ1bmNhdGVUaW1lID0gYXQgLSBmcm9tVGltZVxuICBjb25zdCBwaGFzZSA9IHRydW5jYXRlVGltZSAvIHRpbWVcbiAgbGV0IHZhbHVlID0gc3RhcnQgKyBwaGFzZSAqIGRpZmZlcmVuY2VcblxuICBpZiAodmFsdWUgPD0gc3RhcnQpIHtcbiAgICB2YWx1ZSA9IHN0YXJ0XG4gIH1cbiAgaWYgKHZhbHVlID49IGVuZCkge1xuICAgIHZhbHVlID0gZW5kXG4gIH1cblxuICByZXR1cm4gdmFsdWVcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBBRFNSXG4iLCIndXNlIHN0cmljdCdcblxuLy8gREVDT0RFIFVUSUxJVElFU1xuZnVuY3Rpb24gYjY0VG9VaW50NihuQ2hyKSB7XG4gIHJldHVybiBuQ2hyID4gNjQgJiYgbkNociA8IDkxID8gbkNociAtIDY1XG4gICAgOiBuQ2hyID4gOTYgJiYgbkNociA8IDEyMyA/IG5DaHIgLSA3MVxuICAgICAgOiBuQ2hyID4gNDcgJiYgbkNociA8IDU4ID8gbkNociArIDRcbiAgICAgICAgOiBuQ2hyID09PSA0MyA/IDYyXG4gICAgICAgICAgOiBuQ2hyID09PSA0NyA/IDYzXG4gICAgICAgICAgICA6IDBcbn1cblxuLy8gRGVjb2RlIEJhc2U2NCB0byBVaW50OEFycmF5XG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIGRlY29kZShzQmFzZTY0LCBuQmxvY2tzU2l6ZSkge1xuICBjb25zdCBzQjY0RW5jID0gc0Jhc2U2NC5yZXBsYWNlKC9bXkEtWmEtejAtOVxcK1xcL10vZywgJycpXG4gIGNvbnN0IG5JbkxlbiA9IHNCNjRFbmMubGVuZ3RoXG4gIGNvbnN0IG5PdXRMZW4gPSBuQmxvY2tzU2l6ZVxuICAgID8gTWF0aC5jZWlsKChuSW5MZW4gKiAzICsgMSA+PiAyKSAvIG5CbG9ja3NTaXplKSAqIG5CbG9ja3NTaXplXG4gICAgOiBuSW5MZW4gKiAzICsgMSA+PiAyXG4gIGNvbnN0IHRhQnl0ZXMgPSBuZXcgVWludDhBcnJheShuT3V0TGVuKVxuXG4gIGZvciAobGV0IG5Nb2QzLCBuTW9kNCwgblVpbnQyNCA9IDAsIG5PdXRJZHggPSAwLCBuSW5JZHggPSAwOyBuSW5JZHggPCBuSW5MZW47IG5JbklkeCsrKSB7XG4gICAgbk1vZDQgPSBuSW5JZHggJiAzXG4gICAgblVpbnQyNCB8PSBiNjRUb1VpbnQ2KHNCNjRFbmMuY2hhckNvZGVBdChuSW5JZHgpKSA8PCAxOCAtIDYgKiBuTW9kNFxuICAgIGlmIChuTW9kNCA9PT0gMyB8fCBuSW5MZW4gLSBuSW5JZHggPT09IDEpIHtcbiAgICAgIGZvciAobk1vZDMgPSAwOyBuTW9kMyA8IDMgJiYgbk91dElkeCA8IG5PdXRMZW47IG5Nb2QzKysgLCBuT3V0SWR4KyspIHtcbiAgICAgICAgdGFCeXRlc1tuT3V0SWR4XSA9IG5VaW50MjQgPj4+ICgxNiA+Pj4gbk1vZDMgJiAyNCkgJiAyNTVcbiAgICAgIH1cbiAgICAgIG5VaW50MjQgPSAwXG4gICAgfVxuICB9XG4gIHJldHVybiB0YUJ5dGVzXG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBkZWNvZGUgfVxuIiwiLyogZ2xvYmFsIFhNTEh0dHBSZXF1ZXN0ICovXG4ndXNlIHN0cmljdCdcblxuLyoqXG4gKiBHaXZlbiBhIHVybCBhbmQgYSByZXR1cm4gdHlwZSwgcmV0dXJucyBhIHByb21pc2UgdG8gdGhlIGNvbnRlbnQgb2YgdGhlIHVybFxuICogQmFzaWNhbGx5IGl0IHdyYXBzIGEgWE1MSHR0cFJlcXVlc3QgaW50byBhIFByb21pc2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZSAtIGNhbiBiZSAndGV4dCcgb3IgJ2FycmF5YnVmZmVyJ1xuICogQHJldHVybiB7UHJvbWlzZX1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodXJsLCB0eXBlKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoZG9uZSwgcmVqZWN0KSB7XG4gICAgY29uc3QgcmVxID0gbmV3IFhNTEh0dHBSZXF1ZXN0KClcbiAgICBpZiAodHlwZSlcbiAgICAgIHJlcS5yZXNwb25zZVR5cGUgPSB0eXBlXG5cbiAgICByZXEub3BlbignR0VUJywgdXJsKVxuICAgIHJlcS5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAocmVxLnN0YXR1cyA9PT0gMjAwKVxuICAgICAgICBkb25lKHJlcS5yZXNwb25zZSlcbiAgICAgIHJlamVjdChFcnJvcihyZXEuc3RhdHVzVGV4dCkpXG4gICAgfVxuICAgIHJlcS5vbmVycm9yID0gKCkgPT4gcmVqZWN0KEVycm9yKCdOZXR3b3JrIEVycm9yJykpXG4gICAgcmVxLnNlbmQoKVxuICB9KVxufVxuIiwiJ3VzZSBzdHJpY3QnXG5cbmNvbnN0IGJhc2U2NCA9IHJlcXVpcmUoJy4vYmFzZTY0JylcbmNvbnN0IGZldGNoID0gcmVxdWlyZSgnLi9mZXRjaCcpXG5cbi8vIEdpdmVuIGEgcmVnZXgsIHJldHVybiBhIGZ1bmN0aW9uIHRoYXQgdGVzdCBpZiBhZ2FpbnN0IGEgc3RyaW5nXG5mdW5jdGlvbiBmcm9tUmVnZXgocikge1xuICByZXR1cm4gZnVuY3Rpb24gKG8pIHsgcmV0dXJuIHR5cGVvZiBvID09PSAnc3RyaW5nJyAmJiByLnRlc3QobykgfVxufVxuLy8gVHJ5IHRvIGFwcGx5IGEgcHJlZml4IHRvIGEgbmFtZVxuZnVuY3Rpb24gcHJlZml4KHByZSwgbmFtZSkge1xuICByZXR1cm4gdHlwZW9mIHByZSA9PT0gJ3N0cmluZycgPyBwcmUgKyBuYW1lXG4gICAgOiB0eXBlb2YgcHJlID09PSAnZnVuY3Rpb24nID8gcHJlKG5hbWUpXG4gICAgICA6IG5hbWVcbn1cblxuLyoqXG4gKiBMb2FkIG9uZSBvciBtb3JlIGF1ZGlvIGZpbGVzXG4gKlxuICpcbiAqIFBvc3NpYmxlIG9wdGlvbiBrZXlzOlxuICpcbiAqIC0gX19mcm9tX18ge0Z1bmN0aW9ufFN0cmluZ306IGEgZnVuY3Rpb24gb3Igc3RyaW5nIHRvIGNvbnZlcnQgZnJvbSBmaWxlIG5hbWVzIHRvIHVybHMuXG4gKiBJZiBpcyBhIHN0cmluZyBpdCB3aWxsIGJlIHByZWZpeGVkIHRvIHRoZSBuYW1lOlxuICogYGxvYWQoYWMsICdzbmFyZS5tcDMnLCB7IGZyb206ICdodHRwOi8vYXVkaW8ubmV0L3NhbXBsZXMvJyB9KWBcbiAqIElmIGl0J3MgYSBmdW5jdGlvbiBpdCByZWNlaXZlcyB0aGUgZmlsZSBuYW1lIGFuZCBzaG91bGQgcmV0dXJuIHRoZSB1cmwgYXMgc3RyaW5nLlxuICogLSBfX29ubHlfXyB7QXJyYXl9IC0gd2hlbiBsb2FkaW5nIG9iamVjdHMsIGlmIHByb3ZpZGVkLCBvbmx5IHRoZSBnaXZlbiBrZXlzXG4gKiB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBkZWNvZGVkIG9iamVjdDpcbiAqIGBsb2FkKGFjLCAncGlhbm8uanNvbicsIHsgb25seTogWydDMicsICdEMiddIH0pYFxuICpcbiAqIEBwYXJhbSB7QXVkaW9Db250ZXh0fSBhYyAtIHRoZSBhdWRpbyBjb250ZXh0XG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIC0gdGhlIG9iamVjdCB0byBiZSBsb2FkZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gKE9wdGlvbmFsKSB0aGUgbG9hZCBvcHRpb25zIGZvciB0aGF0IG9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IGRlZmF1bHRWYWx1ZSAtIChPcHRpb25hbCkgdGhlIGRlZmF1bHQgdmFsdWUgdG8gcmV0dXJuIGFzXG4gKiBpbiBhIHByb21pc2UgaWYgbm90IHZhbGlkIGxvYWRlciBmb3VuZFxuICovXG5mdW5jdGlvbiBsb2FkKGFjLCBzb3VyY2UsIG9wdGlvbnMsIGRlZlZhbCkge1xuICBjb25zdCBsb2FkZXIgPVxuICAgIC8vIEJhc2ljIGF1ZGlvIGxvYWRpbmdcbiAgICBpc0FycmF5QnVmZmVyKHNvdXJjZSkgPyBsb2FkQXJyYXlCdWZmZXJcbiAgICAgIDogaXNBdWRpb0ZpbGVOYW1lKHNvdXJjZSkgPyBsb2FkQXVkaW9GaWxlXG4gICAgICAgIDogaXNQcm9taXNlKHNvdXJjZSkgPyBsb2FkUHJvbWlzZVxuICAgICAgICAgIC8vIENvbXBvdW5kIG9iamVjdHNcbiAgICAgICAgICA6IGlzQXJyYXkoc291cmNlKSA/IGxvYWRBcnJheURhdGFcbiAgICAgICAgICAgIDogaXNPYmplY3Qoc291cmNlKSA/IGxvYWRPYmplY3REYXRhXG4gICAgICAgICAgICAgIDogaXNKc29uRmlsZU5hbWUoc291cmNlKSA/IGxvYWRKc29uRmlsZVxuICAgICAgICAgICAgICAgIC8vIEJhc2U2NCBlbmNvZGVkIGF1ZGlvXG4gICAgICAgICAgICAgICAgOiBpc0Jhc2U2NEF1ZGlvKHNvdXJjZSkgPyBsb2FkQmFzZTY0QXVkaW9cbiAgICAgICAgICAgICAgICAgIDogaXNKc0ZpbGVOYW1lKHNvdXJjZSkgPyBsb2FkTWlkaUpTRmlsZVxuICAgICAgICAgICAgICAgICAgICA6IG51bGxcblxuICBjb25zdCBvcHRzID0gb3B0aW9ucyB8fCB7fVxuICByZXR1cm4gbG9hZGVyID8gbG9hZGVyKGFjLCBzb3VyY2UsIG9wdHMpXG4gICAgOiBkZWZWYWwgPyBQcm9taXNlLnJlc29sdmUoZGVmVmFsKVxuICAgICAgOiBQcm9taXNlLnJlamVjdChgU291cmNlIG5vdCB2YWxpZCAoJHtzb3VyY2V9KWApXG59XG5sb2FkLmZldGNoID0gZmV0Y2hcblxuLy8gQkFTSUMgQVVESU8gTE9BRElOR1xuLy8gPT09PT09PT09PT09PT09PT09PVxuXG4vLyBMb2FkIChkZWNvZGUpIGFuIGFycmF5IGJ1ZmZlclxuZnVuY3Rpb24gaXNBcnJheUJ1ZmZlcihvKSB7IHJldHVybiBvIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfVxuXG5mdW5jdGlvbiBsb2FkQXJyYXlCdWZmZXIoYWMsIGFycmF5LCBfb3B0aW9ucykge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGRvbmUsIHJlamVjdCkge1xuICAgIGFjLmRlY29kZUF1ZGlvRGF0YShhcnJheSxcbiAgICAgIGZ1bmN0aW9uIChidWZmZXIpIHsgZG9uZShidWZmZXIpIH0sXG4gICAgICBmdW5jdGlvbiAoKSB7IHJlamVjdChgQ2FuJ3QgZGVjb2RlIGF1ZGlvIGRhdGEgKCR7YXJyYXkuc2xpY2UoMCwgMzApfS4uLilgKSB9XG4gICAgKVxuICB9KVxufVxuXG4vLyBMb2FkIGFuIGF1ZGlvIGZpbGVuYW1lXG5jb25zdCBpc0F1ZGlvRmlsZU5hbWUgPSBmcm9tUmVnZXgoL1xcLihtcDN8d2F2fG9nZykoXFw/LiopPyQvaSlcblxuZnVuY3Rpb24gbG9hZEF1ZGlvRmlsZShhYywgbmFtZSwgb3B0aW9ucykge1xuICBjb25zdCB1cmwgPSBwcmVmaXgob3B0aW9ucy5mcm9tLCBuYW1lKVxuICByZXR1cm4gbG9hZChhYywgbG9hZC5mZXRjaCh1cmwsICdhcnJheWJ1ZmZlcicpLCBvcHRpb25zKVxufVxuXG4vLyBMb2FkIHRoZSByZXN1bHQgb2YgYSBwcm9taXNlXG5mdW5jdGlvbiBpc1Byb21pc2UobykgeyByZXR1cm4gbyAmJiB0eXBlb2Ygby50aGVuID09PSAnZnVuY3Rpb24nIH1cblxuZnVuY3Rpb24gbG9hZFByb21pc2UoYWMsIHByb21pc2UsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHByb21pc2UudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gbG9hZChhYywgdmFsdWUsIG9wdGlvbnMpXG4gIH0pXG59XG5cbi8vIENPTVBPVU5EIE9CSkVDVFNcbi8vID09PT09PT09PT09PT09PT1cblxuLy8gVHJ5IHRvIGxvYWQgYWxsIHRoZSBpdGVtcyBvZiBhbiBhcnJheVxuY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXlcblxuZnVuY3Rpb24gbG9hZEFycmF5RGF0YShhYywgYXJyYXksIG9wdGlvbnMpIHtcbiAgcmV0dXJuIFByb21pc2UuYWxsKGFycmF5Lm1hcChkYXRhID0+IGxvYWQoYWMsIGRhdGEsIG9wdGlvbnMsIGRhdGEpKSlcbn1cblxuLy8gVHJ5IHRvIGxvYWQgYWxsIHRoZSB2YWx1ZXMgb2YgYSBrZXkvdmFsdWUgb2JqZWN0XG5mdW5jdGlvbiBpc09iamVjdChvKSB7IHJldHVybiBvICYmIHR5cGVvZiBvID09PSAnb2JqZWN0JyB9XG5cbmZ1bmN0aW9uIGxvYWRPYmplY3REYXRhKGFjLCBvYmosIG9wdGlvbnMpIHtcbiAgY29uc3QgZGVzdCA9IHt9XG4gIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LmtleXMob2JqKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgIGlmIChvcHRpb25zLm9ubHkgJiYgb3B0aW9ucy5vbmx5LmluZGV4T2Yoa2V5KSA9PT0gLTEpXG4gICAgICByZXR1cm4gbnVsbFxuICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV1cbiAgICByZXR1cm4gbG9hZChhYywgdmFsdWUsIG9wdGlvbnMsIHZhbHVlKVxuICAgICAgLnRoZW4oYXVkaW8gPT4ge1xuICAgICAgICBkZXN0W2tleV0gPSBhdWRpb1xuICAgICAgfSlcbiAgfSlcbiAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKVxuICAgIC50aGVuKCgpID0+IGRlc3QpXG59XG5cbi8vIExvYWQgdGhlIGNvbnRlbnQgb2YgYSBKU09OIGZpbGVcbmNvbnN0IGlzSnNvbkZpbGVOYW1lID0gZnJvbVJlZ2V4KC9cXC5qc29uKFxcPy4qKT8kL2kpXG5cbmZ1bmN0aW9uIGxvYWRKc29uRmlsZShhYywgbmFtZSwgb3B0aW9ucykge1xuICBjb25zdCB1cmwgPSBwcmVmaXgob3B0aW9ucy5mcm9tLCBuYW1lKVxuICByZXR1cm4gbG9hZChhYywgbG9hZC5mZXRjaCh1cmwsICd0ZXh0JykudGhlbihKU09OLnBhcnNlKSwgb3B0aW9ucylcbn1cblxuLy8gQkFTRTY0IEVOQ09ERUQgRk9STUFUU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PVxuXG4vLyBMb2FkIHN0cmluZ3Mgd2l0aCBCYXNlNjQgZW5jb2RlZCBhdWRpb1xuY29uc3QgaXNCYXNlNjRBdWRpbyA9IGZyb21SZWdleCgvXmRhdGE6YXVkaW8vKVxuXG5mdW5jdGlvbiBsb2FkQmFzZTY0QXVkaW8oYWMsIHNvdXJjZSwgb3B0aW9ucykge1xuICBjb25zdCBpID0gc291cmNlLmluZGV4T2YoJywnKVxuICByZXR1cm4gbG9hZChhYywgYmFzZTY0LmRlY29kZShzb3VyY2Uuc2xpY2UoaSArIDEpKS5idWZmZXIsIG9wdGlvbnMpXG59XG5cbi8vIExvYWQgLmpzIGZpbGVzIHdpdGggTWlkaUpTIHNvdW5kZm9udCBwcmVyZW5kZXJlZCBhdWRpb1xuY29uc3QgaXNKc0ZpbGVOYW1lID0gZnJvbVJlZ2V4KC9cXC5qcyhcXD8uKik/JC9pKVxuXG5mdW5jdGlvbiBsb2FkTWlkaUpTRmlsZShhYywgbmFtZSwgb3B0aW9ucykge1xuICBjb25zdCB1cmwgPSBwcmVmaXgob3B0aW9ucy5mcm9tLCBuYW1lKVxuICByZXR1cm4gbG9hZChhYywgbG9hZC5mZXRjaCh1cmwsICd0ZXh0JykudGhlbihtaWRpSnNUb0pzb24pLCBvcHRpb25zKVxufVxuXG4vLyBjb252ZXJ0IGEgTUlESS5qcyBqYXZhc2NyaXB0IHNvdW5kZm9udCBmaWxlIHRvIGpzb25cbmZ1bmN0aW9uIG1pZGlKc1RvSnNvbihkYXRhKSB7XG4gIGxldCBiZWdpbiA9IGRhdGEuaW5kZXhPZignTUlESS5Tb3VuZGZvbnQuJylcbiAgaWYgKGJlZ2luIDwgMClcbiAgICB0aHJvdyBFcnJvcignSW52YWxpZCBNSURJLmpzIFNvdW5kZm9udCBmb3JtYXQnKVxuICBiZWdpbiA9IGRhdGEuaW5kZXhPZignPScsIGJlZ2luKSArIDJcbiAgY29uc3QgZW5kID0gZGF0YS5sYXN0SW5kZXhPZignLCcpXG4gIHJldHVybiBKU09OLnBhcnNlKGRhdGEuc2xpY2UoYmVnaW4sIGVuZCkgKyAnfScpXG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBsb2FkIH1cbiIsIi8qKlxuICogQ29uc3RhbnRzIHVzZWQgaW4gcGxheWVyLlxuICovXG5jb25zdCBDb25zdGFudHMgPSB7XG5cdFZFUlNJT046ICcyLjAuNCcsXG5cdE5PVEVTOiBbXSxcblx0Q0lSQ0xFX09GX0ZPVVJUSFM6IFsnQycsICdGJywgJ0JiJywgJ0ViJywgJ0FiJywgJ0RiJywgJ0diJywgJ0NiJywgJ0ZiJywgJ0JiYicsICdFYmInLCAnQWJiJ10sXG5cdENJUkNMRV9PRl9GSUZUSFM6IFsnQycsICdHJywgJ0QnLCAnQScsICdFJywgJ0InLCAnRiMnLCAnQyMnLCAnRyMnLCAnRCMnLCAnQSMnLCAnRSMnXVxufTtcblxuLy8gQnVpbGRzIG5vdGVzIG9iamVjdCBmb3IgcmVmZXJlbmNlIGFnYWluc3QgYmluYXJ5IHZhbHVlcy5cbmNvbnN0IGFsbE5vdGVzID0gW1snQyddLCBbJ0MjJywgJ0RiJ10sIFsnRCddLCBbJ0QjJywgJ0ViJ10sIFsnRSddLCBbJ0YnXSwgWydGIycsICdHYiddLCBbJ0cnXSwgWydHIycsICdBYiddLCBbJ0EnXSwgWydBIycsICdCYiddLCBbJ0InXV07XG5sZXQgY291bnRlciA9IDA7XG5cbi8vIEFsbCBhdmFpbGFibGUgb2N0YXZlcy5cbmZvciAobGV0IGkgPSAtMTsgaSA8PSA5OyBpKyspIHtcblx0YWxsTm90ZXMuZm9yRWFjaChub3RlR3JvdXAgPT4ge1xuXHRcdG5vdGVHcm91cC5mb3JFYWNoKG5vdGUgPT4gQ29uc3RhbnRzLk5PVEVTW2NvdW50ZXJdID0gbm90ZSArIGkpO1xuXHRcdGNvdW50ZXIrKztcblx0fSk7XG59XG5cbm1vZHVsZS5leHBvcnRzLkNvbnN0YW50cyA9IENvbnN0YW50cztcbiIsImNvbnN0IFBsYXllciA9IHJlcXVpcmUoJy4vcGxheWVyJyk7XG5jb25zdCBTb3VuZGZvbnQgPSByZXF1aXJlKCcuL3NvdW5kZm9udC1wbGF5ZXIvaW5kZXgnKTtcbi8vY29uc3QgQWNvdXN0aWNHcmFuZFBpYW5vID0gcmVxdWlyZSgnLi9zb3VuZGZvbnRzL2Fjb3VzdGljX2dyYW5kX3BpYW5vLW1wMycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBQbGF5ZXI6IFBsYXllci5QbGF5ZXIsXG4gICAgU291bmRmb250OiBTb3VuZGZvbnQuU291bmRmb250LFxuICAgIC8vQWNvdXN0aWNHcmFuZFBpYW5vXG59XG5cbiIsIid1c2Ugc3RyaWN0J1xuXG4vLyB1dGlsXG5jb25zdCBmaWxsU3RyID0gKHMsIG51bSkgPT4gQXJyYXkobnVtICsgMSkuam9pbihzKVxuY29uc3QgaXNOdW0gPSB4ID0+IHR5cGVvZiB4ID09PSAnbnVtYmVyJ1xuY29uc3QgaXNTdHIgPSB4ID0+IHR5cGVvZiB4ID09PSAnc3RyaW5nJ1xuY29uc3QgaXNEZWYgPSB4ID0+IHR5cGVvZiB4ICE9PSAndW5kZWZpbmVkJ1xuY29uc3QgbWlkaVRvRnJlcSA9IChtaWRpLCB0dW5pbmcpID0+IE1hdGgucG93KDIsIChtaWRpIC0gNjkpIC8gMTIpICogKHR1bmluZyB8fCA0NDApXG5cbmNvbnN0IFJFR0VYID0gL14oW2EtZ0EtR10pKCN7MSx9fGJ7MSx9fHh7MSx9fCkoLT9cXGQqKVxccyooLiopXFxzKiQvXG4vKipcbiAqIEEgcmVnZXggZm9yIG1hdGNoaW5nIG5vdGUgc3RyaW5ncyBpbiBzY2llbnRpZmljIG5vdGF0aW9uLlxuICpcbiAqIEBuYW1lIHJlZ2V4XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm4ge1JlZ0V4cH0gdGhlIHJlZ2V4cCB1c2VkIHRvIHBhcnNlIHRoZSBub3RlIG5hbWVcbiAqXG4gKiBUaGUgbm90ZSBzdHJpbmcgc2hvdWxkIGhhdmUgdGhlIGZvcm0gYGxldHRlclthY2NpZGVudGFsc11bb2N0YXZlXVtlbGVtZW50XWBcbiAqIHdoZXJlOlxuICpcbiAqIC0gbGV0dGVyOiAoUmVxdWlyZWQpIGlzIGEgbGV0dGVyIGZyb20gQSB0byBHIGVpdGhlciB1cHBlciBvciBsb3dlciBjYXNlXG4gKiAtIGFjY2lkZW50YWxzOiAoT3B0aW9uYWwpIGNhbiBiZSBvbmUgb3IgbW9yZSBgYmAgKGZsYXRzKSwgYCNgIChzaGFycHMpIG9yIGB4YCAoZG91YmxlIHNoYXJwcykuXG4gKiBUaGV5IGNhbiBOT1QgYmUgbWl4ZWQuXG4gKiAtIG9jdGF2ZTogKE9wdGlvbmFsKSBhIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIGludGVnZXJcbiAqIC0gZWxlbWVudDogKE9wdGlvbmFsKSBhZGRpdGlvbmFsbHkgYW55dGhpbmcgYWZ0ZXIgdGhlIGR1cmF0aW9uIGlzIGNvbnNpZGVyZWQgdG9cbiAqIGJlIHRoZSBlbGVtZW50IG5hbWUgKGZvciBleGFtcGxlOiAnQzIgZG9yaWFuJylcbiAqXG4gKiBUaGUgZXhlY3V0ZWQgcmVnZXggY29udGFpbnMgKGJ5IGFycmF5IGluZGV4KTpcbiAqXG4gKiAtIDA6IHRoZSBjb21wbGV0ZSBzdHJpbmdcbiAqIC0gMTogdGhlIG5vdGUgbGV0dGVyXG4gKiAtIDI6IHRoZSBvcHRpb25hbCBhY2NpZGVudGFsc1xuICogLSAzOiB0aGUgb3B0aW9uYWwgb2N0YXZlXG4gKiAtIDQ6IHRoZSByZXN0IG9mIHRoZSBzdHJpbmcgKHRyaW1tZWQpXG4gKlxuICogQGV4YW1wbGVcbiAqIHZhciBwYXJzZXIgPSByZXF1aXJlKCdub3RlLXBhcnNlcicpXG4gKiBwYXJzZXIucmVnZXguZXhlYygnYyM0JylcbiAqIC8vID0+IFsnYyM0JywgJ2MnLCAnIycsICc0JywgJyddXG4gKiBwYXJzZXIucmVnZXguZXhlYygnYyM0IG1ham9yJylcbiAqIC8vID0+IFsnYyM0bWFqb3InLCAnYycsICcjJywgJzQnLCAnbWFqb3InXVxuICogcGFyc2VyLnJlZ2V4KCkuZXhlYygnQ01hajcnKVxuICogLy8gPT4gWydDTWFqNycsICdDJywgJycsICcnLCAnTWFqNyddXG4gKi9cbmZ1bmN0aW9uIHJlZ2V4KCkgeyByZXR1cm4gUkVHRVggfTtcblxuY29uc3QgU0VNSVRPTkVTID0gWzAsIDIsIDQsIDUsIDcsIDksIDExXVxuLyoqXG4gKiBQYXJzZSBhIG5vdGUgbmFtZSBpbiBzY2llbnRpZmljIG5vdGF0aW9uIGFuIHJldHVybiBpdCdzIGNvbXBvbmVudHMsXG4gKiBhbmQgc29tZSBudW1lcmljIHByb3BlcnRpZXMgaW5jbHVkaW5nIG1pZGkgbnVtYmVyIGFuZCBmcmVxdWVuY3kuXG4gKlxuICogQG5hbWUgcGFyc2VcbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtTdHJpbmd9IG5vdGUgLSB0aGUgbm90ZSBzdHJpbmcgdG8gYmUgcGFyc2VkXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGlzVG9uaWMgLSB0cnVlIHRoZSBzdHJpbmdzIGl0J3Mgc3VwcG9zZWQgdG8gY29udGFpbiBhIG5vdGUgbnVtYmVyXG4gKiBhbmQgc29tZSBjYXRlZ29yeSAoZm9yIGV4YW1wbGUgYW4gc2NhbGU6ICdDIyBtYWpvcicpLiBJdCdzIGZhbHNlIGJ5IGRlZmF1bHQsXG4gKiBidXQgd2hlbiB0cnVlLCBlbiBleHRyYSB0b25pY09mIHByb3BlcnR5IGlzIHJldHVybmVkIHdpdGggdGhlIGNhdGVnb3J5ICgnbWFqb3InKVxuICogQHBhcmFtIHtGbG9hdH0gdHVubmluZyAtIFRoZSBmcmVxdWVuY3kgb2YgQTQgbm90ZSB0byBjYWxjdWxhdGUgZnJlcXVlbmNpZXMuXG4gKiBCeSBkZWZhdWx0IGl0IDQ0MC5cbiAqIEByZXR1cm4ge09iamVjdH0gdGhlIHBhcnNlZCBub3RlIG5hbWUgb3IgbnVsbCBpZiBub3QgYSB2YWxpZCBub3RlXG4gKlxuICogVGhlIHBhcnNlZCBub3RlIG5hbWUgb2JqZWN0IHdpbGwgQUxXQVlTIGNvbnRhaW5zOlxuICogLSBsZXR0ZXI6IHRoZSB1cHBlcmNhc2UgbGV0dGVyIG9mIHRoZSBub3RlXG4gKiAtIGFjYzogdGhlIGFjY2lkZW50YWxzIG9mIHRoZSBub3RlIChvbmx5IHNoYXJwcyBvciBmbGF0cylcbiAqIC0gcGM6IHRoZSBwaXRjaCBjbGFzcyAobGV0dGVyICsgYWNjKVxuICogLSBzdGVwOiBzIGEgbnVtZXJpYyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbGV0dGVyLiBJdCdzIGFuIGludGVnZXIgZnJvbSAwIHRvIDZcbiAqIHdoZXJlIDAgPSBDLCAxID0gRCAuLi4gNiA9IEJcbiAqIC0gYWx0OiBhIG51bWVyaWMgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFjY2lkZW50YWxzLiAwIG1lYW5zIG5vIGFsdGVyYXRpb24sXG4gKiBwb3NpdGl2ZSBudW1iZXJzIGFyZSBmb3Igc2hhcnBzIGFuZCBuZWdhdGl2ZSBmb3IgZmxhdHNcbiAqIC0gY2hyb21hOiBhIG51bWVyaWMgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBpdGNoIGNsYXNzLiBJdCdzIGxpa2UgbWlkaSBmb3JcbiAqIHBpdGNoIGNsYXNzZXMuIDAgPSBDLCAxID0gQyMsIDIgPSBEIC4uLiAxMSA9IEIuIENhbiBiZSB1c2VkIHRvIGZpbmQgZW5oYXJtb25pY3NcbiAqIHNpbmNlLCBmb3IgZXhhbXBsZSwgY2hyb21hIG9mICdDYicgYW5kICdCJyBhcmUgYm90aCAxMVxuICpcbiAqIElmIHRoZSBub3RlIGhhcyBvY3RhdmUsIHRoZSBwYXJzZXIgb2JqZWN0IHdpbGwgY29udGFpbjpcbiAqIC0gb2N0OiB0aGUgb2N0YXZlIG51bWJlciAoYXMgaW50ZWdlcilcbiAqIC0gbWlkaTogdGhlIG1pZGkgbnVtYmVyXG4gKiAtIGZyZXE6IHRoZSBmcmVxdWVuY3kgKHVzaW5nIHR1bmluZyBwYXJhbWV0ZXIgYXMgYmFzZSlcbiAqXG4gKiBJZiB0aGUgcGFyYW1ldGVyIGBpc1RvbmljYCBpcyBzZXQgdG8gdHJ1ZSwgdGhlIHBhcnNlZCBvYmplY3Qgd2lsbCBjb250YWluOlxuICogLSB0b25pY09mOiB0aGUgcmVzdCBvZiB0aGUgc3RyaW5nIHRoYXQgZm9sbG93cyBub3RlIG5hbWUgKGxlZnQgYW5kIHJpZ2h0IHRyaW1tZWQpXG4gKlxuICogQGV4YW1wbGVcbiAqIHZhciBwYXJzZSA9IHJlcXVpcmUoJ25vdGUtcGFyc2VyJykucGFyc2VcbiAqIHBhcnNlKCdDYjQnKVxuICogLy8gPT4geyBsZXR0ZXI6ICdDJywgYWNjOiAnYicsIHBjOiAnQ2InLCBzdGVwOiAwLCBhbHQ6IC0xLCBjaHJvbWE6IC0xLFxuICogICAgICAgICBvY3Q6IDQsIG1pZGk6IDU5LCBmcmVxOiAyNDYuOTQxNjUwNjI4MDYyMDYgfVxuICogLy8gaWYgbm8gb2N0YXZlLCBubyBtaWRpLCBubyBmcmVxXG4gKiBwYXJzZSgnZngnKVxuICogLy8gPT4geyBsZXR0ZXI6ICdGJywgYWNjOiAnIyMnLCBwYzogJ0YjIycsIHN0ZXA6IDMsIGFsdDogMiwgY2hyb21hOiA3IH0pXG4gKi9cbmZ1bmN0aW9uIHBhcnNlKHN0ciwgaXNUb25pYywgdHVuaW5nKSB7XG4gIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJylcbiAgICByZXR1cm4gbnVsbFxuICBjb25zdCBtID0gUkVHRVguZXhlYyhzdHIpXG4gIGlmICghbSB8fCAoIWlzVG9uaWMgJiYgbVs0XSkpXG4gICAgcmV0dXJuIG51bGxcblxuICBjb25zdCBwID0geyBsZXR0ZXI6IG1bMV0udG9VcHBlckNhc2UoKSwgYWNjOiBtWzJdLnJlcGxhY2UoL3gvZywgJyMjJykgfVxuICBwLnBjID0gcC5sZXR0ZXIgKyBwLmFjY1xuICBwLnN0ZXAgPSAocC5sZXR0ZXIuY2hhckNvZGVBdCgwKSArIDMpICUgN1xuICBwLmFsdCA9IHAuYWNjWzBdID09PSAnYicgPyAtcC5hY2MubGVuZ3RoIDogcC5hY2MubGVuZ3RoXG4gIGNvbnN0IHBvcyA9IFNFTUlUT05FU1twLnN0ZXBdICsgcC5hbHRcbiAgcC5jaHJvbWEgPSBwb3MgPCAwID8gMTIgKyBwb3MgOiBwb3MgJSAxMlxuICBpZiAobVszXSkgeyAvLyBoYXMgb2N0YXZlXG4gICAgcC5vY3QgPSArbVszXVxuICAgIHAubWlkaSA9IHBvcyArIDEyICogKHAub2N0ICsgMSlcbiAgICBwLmZyZXEgPSBtaWRpVG9GcmVxKHAubWlkaSwgdHVuaW5nKVxuICB9XG4gIGlmIChpc1RvbmljKVxuICAgIHAudG9uaWNPZiA9IG1bNF1cbiAgcmV0dXJuIHBcbn1cblxuY29uc3QgTEVUVEVSUyA9ICdDREVGR0FCJ1xuY29uc3QgYWNjU3RyID0gbiA9PiAhaXNOdW0obikgPyAnJyA6IG4gPCAwID8gZmlsbFN0cignYicsIC1uKSA6IGZpbGxTdHIoJyMnLCBuKVxuY29uc3Qgb2N0U3RyID0gbiA9PiAhaXNOdW0obikgPyAnJyA6ICcnICsgblxuXG4vKipcbiAqIENyZWF0ZSBhIHN0cmluZyBmcm9tIGEgcGFyc2VkIG9iamVjdCBvciBgc3RlcCwgYWx0ZXJhdGlvbiwgb2N0YXZlYCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqIC0gdGhlIHBhcnNlZCBkYXRhIG9iamVjdFxuICogQHJldHVybiB7U3RyaW5nfSBhIG5vdGUgc3RyaW5nIG9yIG51bGwgaWYgbm90IHZhbGlkIHBhcmFtZXRlcnNcbiAqIEBzaW5jZSAxLjJcbiAqIEBleGFtcGxlXG4gKiBwYXJzZXIuYnVpbGQocGFyc2VyLnBhcnNlKCdjYjInKSkgLy8gPT4gJ0NiMidcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gaXQgYWNjZXB0cyAoc3RlcCwgYWx0ZXJhdGlvbiwgb2N0YXZlKSBwYXJhbWV0ZXJzOlxuICogcGFyc2VyLmJ1aWxkKDMpIC8vID0+ICdGJ1xuICogcGFyc2VyLmJ1aWxkKDMsIC0xKSAvLyA9PiAnRmInXG4gKiBwYXJzZXIuYnVpbGQoMywgLTEsIDQpIC8vID0+ICdGYjQnXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkKHMsIGEsIG8pIHtcbiAgaWYgKHMgPT09IG51bGwgfHwgdHlwZW9mIHMgPT09ICd1bmRlZmluZWQnKVxuICAgIHJldHVybiBudWxsXG4gIGlmIChzLnN0ZXApXG4gICAgcmV0dXJuIGJ1aWxkKHMuc3RlcCwgcy5hbHQsIHMub2N0KVxuICBpZiAocyA8IDAgfHwgcyA+IDYpXG4gICAgcmV0dXJuIG51bGxcbiAgcmV0dXJuIExFVFRFUlMuY2hhckF0KHMpICsgYWNjU3RyKGEpICsgb2N0U3RyKG8pXG59XG5cbi8qKlxuICogR2V0IG1pZGkgb2YgYSBub3RlXG4gKlxuICogQG5hbWUgbWlkaVxuICogQGZ1bmN0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ3xJbnRlZ2VyfSBub3RlIC0gdGhlIG5vdGUgbmFtZSBvciBtaWRpIG51bWJlclxuICogQHJldHVybiB7SW50ZWdlcn0gdGhlIG1pZGkgbnVtYmVyIG9mIHRoZSBub3RlIG9yIG51bGwgaWYgbm90IGEgdmFsaWQgbm90ZVxuICogb3IgdGhlIG5vdGUgZG9lcyBOT1QgY29udGFpbnMgb2N0YXZlXG4gKiBAZXhhbXBsZVxuICogdmFyIHBhcnNlciA9IHJlcXVpcmUoJ25vdGUtcGFyc2VyJylcbiAqIHBhcnNlci5taWRpKCdBNCcpIC8vID0+IDY5XG4gKiBwYXJzZXIubWlkaSgnQScpIC8vID0+IG51bGxcbiAqIEBleGFtcGxlXG4gKiAvLyBtaWRpIG51bWJlcnMgYXJlIGJ5cGFzc2VkIChldmVuIGFzIHN0cmluZ3MpXG4gKiBwYXJzZXIubWlkaSg2MCkgLy8gPT4gNjBcbiAqIHBhcnNlci5taWRpKCc2MCcpIC8vID0+IDYwXG4gKi9cbmZ1bmN0aW9uIG1pZGkobm90ZSkge1xuICBpZiAoKGlzTnVtKG5vdGUpIHx8IGlzU3RyKG5vdGUpKSAmJiBub3RlID49IDAgJiYgbm90ZSA8IDEyOClcbiAgICByZXR1cm4gK25vdGVcbiAgY29uc3QgcCA9IHBhcnNlKG5vdGUpXG4gIHJldHVybiBwICYmIGlzRGVmKHAubWlkaSkgPyBwLm1pZGkgOiBudWxsXG59XG5cbi8qKlxuICogR2V0IGZyZXEgb2YgYSBub3RlIGluIGhlcnR6cyAoaW4gYSB3ZWxsIHRlbXBlcmVkIDQ0MEh6IEE0KVxuICpcbiAqIEBuYW1lIGZyZXFcbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtTdHJpbmd9IG5vdGUgLSB0aGUgbm90ZSBuYW1lIG9yIG5vdGUgbWlkaSBudW1iZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSB0dW5pbmcgLSAoT3B0aW9uYWwpIHRoZSBBNCBmcmVxdWVuY3kgKDQ0MCBieSBkZWZhdWx0KVxuICogQHJldHVybiB7RmxvYXR9IHRoZSBmcmVxIG9mIHRoZSBudW1iZXIgaWYgaGVydHpzIG9yIG51bGwgaWYgbm90IHZhbGlkIG5vdGVcbiAqIEBleGFtcGxlXG4gKiB2YXIgcGFyc2VyID0gcmVxdWlyZSgnbm90ZS1wYXJzZXInKVxuICogcGFyc2VyLmZyZXEoJ0E0JykgLy8gPT4gNDQwXG4gKiBwYXJzZXIuZnJlcSgnQScpIC8vID0+IG51bGxcbiAqIEBleGFtcGxlXG4gKiAvLyBjYW4gY2hhbmdlIHR1bmluZyAoNDQwIGJ5IGRlZmF1bHQpXG4gKiBwYXJzZXIuZnJlcSgnQTQnLCA0NDQpIC8vID0+IDQ0NFxuICogcGFyc2VyLmZyZXEoJ0EzJywgNDQ0KSAvLyA9PiAyMjJcbiAqIEBleGFtcGxlXG4gKiAvLyBpdCBhY2NlcHRzIG1pZGkgbnVtYmVycyAoYXMgbnVtYmVycyBhbmQgYXMgc3RyaW5ncylcbiAqIHBhcnNlci5mcmVxKDY5KSAvLyA9PiA0NDBcbiAqIHBhcnNlci5mcmVxKCc2OScsIDQ0MikgLy8gPT4gNDQyXG4gKi9cbmZ1bmN0aW9uIGZyZXEobm90ZSwgdHVuaW5nKSB7XG4gIGNvbnN0IG0gPSBtaWRpKG5vdGUpXG4gIHJldHVybiBtID09PSBudWxsID8gbnVsbCA6IG1pZGlUb0ZyZXEobSwgdHVuaW5nKVxufVxuXG5jb25zdCBsZXR0ZXIgPSBzcmMgPT4gKHBhcnNlKHNyYykgfHwge30pLmxldHRlclxuY29uc3QgYWNjID0gc3JjID0+IChwYXJzZShzcmMpIHx8IHt9KS5hY2NcbmNvbnN0IHBjID0gc3JjID0+IChwYXJzZShzcmMpIHx8IHt9KS5wY1xuY29uc3Qgc3RlcCA9IHNyYyA9PiAocGFyc2Uoc3JjKSB8fCB7fSkuc3RlcFxuY29uc3QgYWx0ID0gc3JjID0+IChwYXJzZShzcmMpIHx8IHt9KS5hbHRcbmNvbnN0IGNocm9tYSA9IHNyYyA9PiAocGFyc2Uoc3JjKSB8fCB7fSkuY2hyb21hXG5jb25zdCBvY3QgPSBzcmMgPT4gKHBhcnNlKHNyYykgfHwge30pLm9jdFxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcmVnZXgsXG4gIHBhcnNlLFxuICBidWlsZCxcbiAgbWlkaSxcbiAgZnJlcSxcbiAgbGV0dGVyLFxuICBhY2MsXG4gIHBjLFxuICBzdGVwLFxuICBhbHQsXG4gIGNocm9tYSxcbiAgb2N0LFxufVxuIiwiY29uc3QgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJykuVXRpbHM7XG5jb25zdCBUcmFjayA9IHJlcXVpcmUoJy4vdHJhY2snKS5UcmFjaztcblxuLy8gUG9seWZpbGwgVWludDhBcnJheS5mb3JFYWNoOiBEb2Vzbid0IGV4aXN0IG9uIFNhZmFyaSA8MTBcbmlmICghVWludDhBcnJheS5wcm90b3R5cGUuZm9yRWFjaCkge1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoVWludDhBcnJheS5wcm90b3R5cGUsICdmb3JFYWNoJywge1xuXHRcdHZhbHVlOiBBcnJheS5wcm90b3R5cGUuZm9yRWFjaFxuXHR9KTtcbn1cblxuLyoqXG4gKiBNYWluIHBsYXllciBjbGFzcy4gIENvbnRhaW5zIG1ldGhvZHMgdG8gbG9hZCBmaWxlcywgc3RhcnQsIHN0b3AuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSAtIENhbGxiYWNrIHRvIGZpcmUgZm9yIGVhY2ggTUlESSBldmVudC4gIENhbiBhbHNvIGJlIGFkZGVkIHdpdGggb24oJ21pZGlFdmVudCcsIGZuKVxuICogQHBhcmFtIHthcnJheX0gLSBBcnJheSBidWZmZXIgb2YgTUlESSBmaWxlIChvcHRpb25hbCkuXG4gKi9cbmNsYXNzIFBsYXllciB7XG5cdGNvbnN0cnVjdG9yKGV2ZW50SGFuZGxlciwgYnVmZmVyKSB7XG5cdFx0dGhpcy5zYW1wbGVSYXRlID0gNTsgLy8gbWlsbGlzZWNvbmRzXG5cdFx0dGhpcy5zdGFydFRpbWUgPSAwO1xuXHRcdHRoaXMuYnVmZmVyID0gYnVmZmVyIHx8IG51bGw7XG5cdFx0dGhpcy5kaXZpc2lvbjtcblx0XHR0aGlzLmZvcm1hdDtcblx0XHR0aGlzLnNldEludGVydmFsSWQgPSBmYWxzZTtcblx0XHR0aGlzLnRyYWNrcyA9IFtdO1xuXHRcdHRoaXMuaW5zdHJ1bWVudHMgPSBbXTtcblx0XHR0aGlzLmRlZmF1bHRUZW1wbyA9IDEyMDtcblx0XHR0aGlzLnRlbXBvID0gbnVsbDtcblx0XHR0aGlzLnN0YXJ0VGljayA9IDA7XG5cdFx0dGhpcy50aWNrID0gMDtcblx0XHR0aGlzLmxhc3RUaWNrID0gbnVsbDtcblx0XHR0aGlzLmluTG9vcCA9IGZhbHNlO1xuXHRcdHRoaXMudG90YWxUaWNrcyA9IDA7XG5cdFx0dGhpcy5ldmVudHMgPSBbXTtcblx0XHR0aGlzLnRvdGFsRXZlbnRzID0gMDtcblx0XHR0aGlzLmV2ZW50TGlzdGVuZXJzID0ge307XG5cblx0XHRpZiAodHlwZW9mIChldmVudEhhbmRsZXIpID09PSAnZnVuY3Rpb24nKSB0aGlzLm9uKCdtaWRpRXZlbnQnLCBldmVudEhhbmRsZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvYWQgYSBmaWxlIGludG8gdGhlIHBsYXllciAoTm9kZS5qcyBvbmx5KS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBQYXRoIG9mIGZpbGUuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWRGaWxlKHBhdGgpIHtcblx0XHRjb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJyk7XG5cdFx0dGhpcy5idWZmZXIgPSBmcy5yZWFkRmlsZVN5bmMocGF0aCk7XG5cdFx0cmV0dXJuIHRoaXMuZmlsZUxvYWRlZCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvYWQgYW4gYXJyYXkgYnVmZmVyIGludG8gdGhlIHBsYXllci5cblx0ICogQHBhcmFtIHthcnJheX0gYXJyYXlCdWZmZXIgLSBBcnJheSBidWZmZXIgb2YgZmlsZSB0byBiZSBsb2FkZWQuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWRBcnJheUJ1ZmZlcihhcnJheUJ1ZmZlcikge1xuXHRcdHRoaXMuYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpO1xuXHRcdHJldHVybiB0aGlzLmZpbGVMb2FkZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMb2FkIGEgZGF0YSBVUkkgaW50byB0aGUgcGxheWVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZGF0YVVyaSAtIERhdGEgVVJJIHRvIGJlIGxvYWRlZC5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0bG9hZERhdGFVcmkoZGF0YVVyaSkge1xuXHRcdC8vIGNvbnZlcnQgYmFzZTY0IHRvIHJhdyBiaW5hcnkgZGF0YSBoZWxkIGluIGEgc3RyaW5nLlxuXHRcdC8vIGRvZXNuJ3QgaGFuZGxlIFVSTEVuY29kZWQgRGF0YVVSSXMgLSBzZWUgU08gYW5zd2VyICM2ODUwMjc2IGZvciBjb2RlIHRoYXQgZG9lcyB0aGlzXG5cdFx0Y29uc3QgYnl0ZVN0cmluZyA9IHdpbmRvdy5hdG9iKGRhdGFVcmkuc3BsaXQoJywnKVsxXSk7XG5cblx0XHQvLyB3cml0ZSB0aGUgYnl0ZXMgb2YgdGhlIHN0cmluZyB0byBhbiBBcnJheUJ1ZmZlclxuXHRcdGNvbnN0IGlhID0gbmV3IFVpbnQ4QXJyYXkoYnl0ZVN0cmluZy5sZW5ndGgpO1xuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZVN0cmluZy5sZW5ndGg7IGkrKylcblx0XHRcdGlhW2ldID0gYnl0ZVN0cmluZy5jaGFyQ29kZUF0KGkpO1xuXG5cdFx0dGhpcy5idWZmZXIgPSBpYTtcblx0XHRyZXR1cm4gdGhpcy5maWxlTG9hZGVkKCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGZpbGVzaXplIG9mIGxvYWRlZCBmaWxlIGluIG51bWJlciBvZiBieXRlcy5cblx0ICogQHJldHVybiB7bnVtYmVyfSAtIFRoZSBmaWxlc2l6ZS5cblx0ICovXG5cdGdldEZpbGVzaXplKCkge1xuXHRcdHJldHVybiB0aGlzLmJ1ZmZlciA/IHRoaXMuYnVmZmVyLmxlbmd0aCA6IDA7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyBkZWZhdWx0IHRlbXBvLCBwYXJzZXMgZmlsZSBmb3IgbmVjZXNzYXJ5IGluZm9ybWF0aW9uLCBhbmQgZG9lcyBhIGRyeSBydW4gdG8gY2FsY3VsYXRlIHRvdGFsIGxlbmd0aC5cblx0ICogUG9wdWxhdGVzIHRoaXMuZXZlbnRzICYgdGhpcy50b3RhbFRpY2tzLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRmaWxlTG9hZGVkKCkge1xuXHRcdGlmICghdGhpcy52YWxpZGF0ZSgpKSB0aHJvdyAnSW52YWxpZCBNSURJIGZpbGU7IHNob3VsZCBzdGFydCB3aXRoIE1UaGQnO1xuXHRcdHJldHVybiB0aGlzLnNldFRlbXBvKHRoaXMuZGVmYXVsdFRlbXBvKS5nZXREaXZpc2lvbigpLmdldEZvcm1hdCgpLmdldFRyYWNrcygpLmRyeVJ1bigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFZhbGlkYXRlcyBmaWxlIHVzaW5nIHNpbXBsZSBtZWFucyAtIGZpcnN0IGZvdXIgYnl0ZXMgc2hvdWxkID09IE1UaGQuXG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59XG5cdCAqL1xuXHR2YWxpZGF0ZSgpIHtcblx0XHRyZXR1cm4gVXRpbHMuYnl0ZXNUb0xldHRlcnModGhpcy5idWZmZXIuc3ViYXJyYXkoMCwgNCkpID09PSAnTVRoZCc7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBNSURJIGZpbGUgZm9ybWF0IGZvciBsb2FkZWQgZmlsZS5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0Z2V0Rm9ybWF0KCkge1xuXHRcdC8qXG5cdFx0TUlESSBmaWxlcyBjb21lIGluIDMgdmFyaWF0aW9uczpcblx0XHRGb3JtYXQgMCB3aGljaCBjb250YWluIGEgc2luZ2xlIHRyYWNrXG5cdFx0Rm9ybWF0IDEgd2hpY2ggY29udGFpbiBvbmUgb3IgbW9yZSBzaW11bHRhbmVvdXMgdHJhY2tzXG5cdFx0KGllIGFsbCB0cmFja3MgYXJlIHRvIGJlIHBsYXllZCBzaW11bHRhbmVvdXNseSkuXG5cdFx0Rm9ybWF0IDIgd2hpY2ggY29udGFpbiBvbmUgb3IgbW9yZSBpbmRlcGVuZGFudCB0cmFja3Ncblx0XHQoaWUgZWFjaCB0cmFjayBpcyB0byBiZSBwbGF5ZWQgaW5kZXBlbmRhbnRseSBvZiB0aGUgb3RoZXJzKS5cblx0XHRyZXR1cm4gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmJ1ZmZlci5zdWJhcnJheSg4LCAxMCkpO1xuXHRcdCovXG5cblx0XHR0aGlzLmZvcm1hdCA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkoOCwgMTApKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJzZXMgb3V0IHRyYWNrcywgcGxhY2VzIHRoZW0gaW4gdGhpcy50cmFja3MgYW5kIGluaXRpYWxpemVzIHRoaXMucG9pbnRlcnNcblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0Z2V0VHJhY2tzKCkge1xuXHRcdHRoaXMudHJhY2tzID0gW107XG5cdFx0bGV0IHRyYWNrT2Zmc2V0ID0gMDtcblx0XHR3aGlsZSAodHJhY2tPZmZzZXQgPCB0aGlzLmJ1ZmZlci5sZW5ndGgpIHtcblx0XHRcdGlmIChVdGlscy5ieXRlc1RvTGV0dGVycyh0aGlzLmJ1ZmZlci5zdWJhcnJheSh0cmFja09mZnNldCwgdHJhY2tPZmZzZXQgKyA0KSkgPT0gJ01UcmsnKSB7XG5cdFx0XHRcdGxldCB0cmFja0xlbmd0aCA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkodHJhY2tPZmZzZXQgKyA0LCB0cmFja09mZnNldCArIDgpKTtcblx0XHRcdFx0dGhpcy50cmFja3MucHVzaChuZXcgVHJhY2sodGhpcy50cmFja3MubGVuZ3RoLCB0aGlzLmJ1ZmZlci5zdWJhcnJheSh0cmFja09mZnNldCArIDgsIHRyYWNrT2Zmc2V0ICsgOCArIHRyYWNrTGVuZ3RoKSkpO1xuXHRcdFx0fVxuXG5cdFx0XHR0cmFja09mZnNldCArPSBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuYnVmZmVyLnN1YmFycmF5KHRyYWNrT2Zmc2V0ICsgNCwgdHJhY2tPZmZzZXQgKyA4KSkgKyA4O1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBFbmFibGVzIGEgdHJhY2sgZm9yIHBsYXlpbmcuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSB0cmFja051bWJlciAtIFRyYWNrIG51bWJlclxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRlbmFibGVUcmFjayh0cmFja051bWJlcikge1xuXHRcdHRoaXMudHJhY2tzW3RyYWNrTnVtYmVyIC0gMV0uZW5hYmxlKCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogRGlzYWJsZXMgYSB0cmFjayBmb3IgcGxheWluZy5cblx0ICogQHBhcmFtIHtudW1iZXJ9IC0gVHJhY2sgbnVtYmVyXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGRpc2FibGVUcmFjayh0cmFja051bWJlcikge1xuXHRcdHRoaXMudHJhY2tzW3RyYWNrTnVtYmVyIC0gMV0uZGlzYWJsZSgpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgcXVhcnRlciBub3RlIGRpdmlzaW9uIG9mIGxvYWRlZCBNSURJIGZpbGUuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGdldERpdmlzaW9uKCkge1xuXHRcdHRoaXMuZGl2aXNpb24gPSBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuYnVmZmVyLnN1YmFycmF5KDEyLCAxNCkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFRoZSBtYWluIHBsYXkgbG9vcC5cblx0ICogQHBhcmFtIHtib29sZWFufSAtIEluZGljYXRlcyB3aGV0aGVyIG9yIG5vdCB0aGlzIGlzIGJlaW5nIGNhbGxlZCBzaW1wbHkgZm9yIHBhcnNpbmcgcHVycG9zZXMuICBEaXNyZWdhcmRzIHRpbWluZyBpZiBzby5cblx0ICogQHJldHVybiB7dW5kZWZpbmVkfVxuXHQgKi9cblx0cGxheUxvb3AoZHJ5UnVuKSB7XG5cdFx0aWYgKCF0aGlzLmluTG9vcCkge1xuXHRcdFx0dGhpcy5pbkxvb3AgPSB0cnVlO1xuXHRcdFx0dGhpcy50aWNrID0gdGhpcy5nZXRDdXJyZW50VGljaygpO1xuXG5cdFx0XHR0aGlzLnRyYWNrcy5mb3JFYWNoKGZ1bmN0aW9uICh0cmFjaykge1xuXHRcdFx0XHQvLyBIYW5kbGUgbmV4dCBldmVudFxuXHRcdFx0XHRpZiAoIWRyeVJ1biAmJiB0aGlzLmVuZE9mRmlsZSgpKSB7XG5cdFx0XHRcdFx0Ly9jb25zb2xlLmxvZygnZW5kIG9mIGZpbGUnKVxuXHRcdFx0XHRcdHRoaXMudHJpZ2dlclBsYXllckV2ZW50KCdlbmRPZkZpbGUnKTtcblx0XHRcdFx0XHR0aGlzLnN0b3AoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsZXQgZXZlbnQgPSB0cmFjay5oYW5kbGVFdmVudCh0aGlzLnRpY2ssIGRyeVJ1bik7XG5cblx0XHRcdFx0XHRpZiAoZHJ5UnVuICYmIGV2ZW50KSB7XG5cdFx0XHRcdFx0XHRpZiAoZXZlbnQuaGFzT3duUHJvcGVydHkoJ25hbWUnKSAmJiBldmVudC5uYW1lID09PSAnU2V0IFRlbXBvJykge1xuXHRcdFx0XHRcdFx0XHQvLyBHcmFiIHRlbXBvIGlmIGF2YWlsYWJsZS5cblx0XHRcdFx0XHRcdFx0dGhpcy5zZXRUZW1wbyhldmVudC5kYXRhKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChldmVudC5oYXNPd25Qcm9wZXJ0eSgnbmFtZScpICYmIGV2ZW50Lm5hbWUgPT09ICdQcm9ncmFtIENoYW5nZScpIHtcblx0XHRcdFx0XHRcdFx0aWYgKCF0aGlzLmluc3RydW1lbnRzLmluY2x1ZGVzKGV2ZW50LnZhbHVlKSkge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuaW5zdHJ1bWVudHMucHVzaChldmVudC52YWx1ZSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2UgaWYgKGV2ZW50KSB0aGlzLmVtaXRFdmVudChldmVudCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0fSwgdGhpcyk7XG5cblx0XHRcdGlmICghZHJ5UnVuKSB0aGlzLnRyaWdnZXJQbGF5ZXJFdmVudCgncGxheWluZycsIHsgdGljazogdGhpcy50aWNrIH0pO1xuXHRcdFx0dGhpcy5pbkxvb3AgPSBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogU2V0dGVyIGZvciB0ZW1wby5cblx0ICogQHBhcmFtIHtudW1iZXJ9IC0gVGVtcG8gaW4gYnBtIChkZWZhdWx0cyB0byAxMjApXG5cdCAqL1xuXHRzZXRUZW1wbyh0ZW1wbykge1xuXHRcdHRoaXMudGVtcG8gPSB0ZW1wbztcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXR0ZXIgZm9yIHN0YXJ0VGltZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IC0gVVRDIHRpbWVzdGFtcFxuXHQgKi9cblx0c2V0U3RhcnRUaW1lKHN0YXJ0VGltZSkge1xuXHRcdHRoaXMuc3RhcnRUaW1lID0gc3RhcnRUaW1lO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0YXJ0IHBsYXlpbmcgbG9hZGVkIE1JREkgZmlsZSBpZiBub3QgYWxyZWFkeSBwbGF5aW5nLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRwbGF5KCkge1xuXHRcdGlmICh0aGlzLmlzUGxheWluZygpKVxuXHRcdFx0dGhyb3cgJ0FscmVhZHkgcGxheWluZy4uLic7XG5cblx0XHQvLyBJbml0aWFsaXplXG5cdFx0aWYgKCF0aGlzLnN0YXJ0VGltZSlcblx0XHRcdHRoaXMuc3RhcnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuXHRcdC8vIFN0YXJ0IHBsYXkgbG9vcFxuXHRcdC8vd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnBsYXlMb29wLmJpbmQodGhpcykpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IHdpbmRvdy5zZXRJbnRlcnZhbCh0aGlzLnBsYXlMb29wLmJpbmQodGhpcyksIHRoaXMuc2FtcGxlUmF0ZSk7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXVzZXMgcGxheWJhY2sgaWYgcGxheWluZy5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0cGF1c2UoKSB7XG5cdFx0Y2xlYXJJbnRlcnZhbCh0aGlzLnNldEludGVydmFsSWQpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IGZhbHNlO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gdGhpcy50aWNrO1xuXHRcdHRoaXMuc3RhcnRUaW1lID0gMDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTdG9wcyBwbGF5YmFjayBpZiBwbGF5aW5nLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRzdG9wKCkge1xuXHRcdGNsZWFySW50ZXJ2YWwodGhpcy5zZXRJbnRlcnZhbElkKTtcblx0XHR0aGlzLnNldEludGVydmFsSWQgPSBmYWxzZTtcblx0XHR0aGlzLnN0YXJ0VGljayA9IDA7XG5cdFx0dGhpcy5zdGFydFRpbWUgPSAwO1xuXHRcdHRoaXMucmVzZXRUcmFja3MoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTa2lwcyBwbGF5ZXIgcG9pbnRlciB0byBzcGVjaWZpZWQgdGljay5cblx0ICogQHBhcmFtIHtudW1iZXJ9IC0gVGljayB0byBza2lwIHRvLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRza2lwVG9UaWNrKHRpY2spIHtcblx0XHR0aGlzLnN0b3AoKTtcblx0XHR0aGlzLnN0YXJ0VGljayA9IHRpY2s7XG5cblx0XHQvLyBOZWVkIHRvIHNldCB0cmFjayBldmVudCBpbmRleGVzIHRvIHRoZSBuZWFyZXN0IHBvc3NpYmxlIGV2ZW50IHRvIHRoZSBzcGVjaWZpZWQgdGljay5cblx0XHR0aGlzLnRyYWNrcy5mb3JFYWNoKGZ1bmN0aW9uICh0cmFjaykge1xuXHRcdFx0dHJhY2suc2V0RXZlbnRJbmRleEJ5VGljayh0aWNrKTtcblx0XHR9KTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTa2lwcyBwbGF5ZXIgcG9pbnRlciB0byBzcGVjaWZpZWQgcGVyY2VudGFnZS5cblx0ICogQHBhcmFtIHtudW1iZXJ9IC0gUGVyY2VudCB2YWx1ZSBpbiBpbnRlZ2VyIGZvcm1hdC5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0c2tpcFRvUGVyY2VudChwZXJjZW50KSB7XG5cdFx0aWYgKHBlcmNlbnQgPCAwIHx8IHBlcmNlbnQgPiAxMDApIHRocm93ICdQZXJjZW50IG11c3QgYmUgbnVtYmVyIGJldHdlZW4gMSBhbmQgMTAwLic7XG5cdFx0dGhpcy5za2lwVG9UaWNrKE1hdGgucm91bmQocGVyY2VudCAvIDEwMCAqIHRoaXMudG90YWxUaWNrcykpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNraXBzIHBsYXllciBwb2ludGVyIHRvIHNwZWNpZmllZCBzZWNvbmRzLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBTZWNvbmRzIHRvIHNraXAgdG8uXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1NlY29uZHMoc2Vjb25kcykge1xuXHRcdGNvbnN0IHNvbmdUaW1lID0gdGhpcy5nZXRTb25nVGltZSgpO1xuXHRcdGlmIChzZWNvbmRzIDwgMCB8fCBzZWNvbmRzID4gc29uZ1RpbWUpXG5cdFx0XHR0aHJvdyBgJHtzZWNvbmRzfSBzZWNvbmRzIG5vdCB3aXRoaW4gc29uZyB0aW1lIG9mICR7c29uZ1RpbWV9YDtcblx0XHR0aGlzLnNraXBUb1BlcmNlbnQoc2Vjb25kcyAvIHNvbmdUaW1lICogMTAwKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVja3MgaWYgcGxheWVyIGlzIHBsYXlpbmdcblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGlzUGxheWluZygpIHtcblx0XHRyZXR1cm4gdGhpcy5zZXRJbnRlcnZhbElkID4gMCB8fCB0eXBlb2YgdGhpcy5zZXRJbnRlcnZhbElkID09PSAnb2JqZWN0Jztcblx0fVxuXG5cdC8qKlxuXHQgKiBQbGF5cyB0aGUgbG9hZGVkIE1JREkgZmlsZSB3aXRob3V0IHJlZ2FyZCBmb3IgdGltaW5nIGFuZCBzYXZlcyBldmVudHMgaW4gdGhpcy5ldmVudHMuICBFc3NlbnRpYWxseSB1c2VkIGFzIGEgcGFyc2VyLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRkcnlSdW4oKSB7XG5cdFx0Ly8gUmVzZXQgdHJhY2tzIGZpcnN0XG5cdFx0dGhpcy5yZXNldFRyYWNrcygpO1xuXHRcdHdoaWxlICghdGhpcy5lbmRPZkZpbGUoKSlcblx0XHRcdHRoaXMucGxheUxvb3AodHJ1ZSk7XG5cdFx0dGhpcy5ldmVudHMgPSB0aGlzLmdldEV2ZW50cygpO1xuXHRcdHRoaXMudG90YWxFdmVudHMgPSB0aGlzLmdldFRvdGFsRXZlbnRzKCk7XG5cdFx0dGhpcy50b3RhbFRpY2tzID0gdGhpcy5nZXRUb3RhbFRpY2tzKCk7XG5cdFx0dGhpcy5zdGFydFRpY2sgPSAwO1xuXHRcdHRoaXMuc3RhcnRUaW1lID0gMDtcblxuXHRcdC8vIExlYXZlIHRyYWNrcyBpbiBwcmlzdGluZSBjb25kaXNoXG5cdFx0dGhpcy5yZXNldFRyYWNrcygpO1xuXG5cdFx0Ly9jb25zb2xlLmxvZygnU29uZyB0aW1lOiAnICsgdGhpcy5nZXRTb25nVGltZSgpICsgJyBzZWNvbmRzIC8gJyArIHRoaXMudG90YWxUaWNrcyArICcgdGlja3MuJyk7XG5cblx0XHR0aGlzLnRyaWdnZXJQbGF5ZXJFdmVudCgnZmlsZUxvYWRlZCcsIHRoaXMpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc2V0cyBwbGF5IHBvaW50ZXJzIGZvciBhbGwgdHJhY2tzLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRyZXNldFRyYWNrcygpIHtcblx0XHR0aGlzLnRyYWNrcy5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLnJlc2V0KCkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYW4gYXJyYXkgb2YgZXZlbnRzIGdyb3VwZWQgYnkgdHJhY2suXG5cdCAqIEByZXR1cm4ge2FycmF5fVxuXHQgKi9cblx0Z2V0RXZlbnRzKCkge1xuXHRcdHJldHVybiB0aGlzLnRyYWNrcy5tYXAodHJhY2sgPT4gdHJhY2suZXZlbnRzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRvdGFsIG51bWJlciBvZiB0aWNrcyBpbiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0VG90YWxUaWNrcygpIHtcblx0XHRyZXR1cm4gTWF0aC5tYXguYXBwbHkobnVsbCwgdGhpcy50cmFja3MubWFwKHRyYWNrID0+IHRyYWNrLmRlbHRhKSk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0b3RhbCBudW1iZXIgb2YgZXZlbnRzIGluIHRoZSBsb2FkZWQgTUlESSBmaWxlLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXRUb3RhbEV2ZW50cygpIHtcblx0XHRyZXR1cm4gdGhpcy50cmFja3MucmVkdWNlKFxuXHRcdFx0KGEsIGIpID0+IHsgcmV0dXJuIHsgZXZlbnRzOiB7IGxlbmd0aDogYS5ldmVudHMubGVuZ3RoICsgYi5ldmVudHMubGVuZ3RoIH0gfSB9LFxuXHRcdFx0eyBldmVudHM6IHsgbGVuZ3RoOiAwIH0gfVxuXHRcdCkuZXZlbnRzLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHNvbmcgZHVyYXRpb24gaW4gc2Vjb25kcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1RpbWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudG90YWxUaWNrcyAvIHRoaXMuZGl2aXNpb24gLyB0aGlzLnRlbXBvICogNjA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgbnVtYmVyIG9mIHNlY29uZHMgaW4gcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdGdldFNvbmdUaW1lUmVtYWluaW5nKCkge1xuXHRcdHJldHVybiBNYXRoLnJvdW5kKCh0aGlzLnRvdGFsVGlja3MgLSB0aGlzLnRpY2spIC8gdGhpcy5kaXZpc2lvbiAvIHRoaXMudGVtcG8gKiA2MCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgcGVyY2VudCBvZiBwbGF5YmFjay5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1BlcmNlbnRSZW1haW5pbmcoKSB7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQodGhpcy5nZXRTb25nVGltZVJlbWFpbmluZygpIC8gdGhpcy5nZXRTb25nVGltZSgpICogMTAwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOdW1iZXIgb2YgYnl0ZXMgcHJvY2Vzc2VkIGluIHRoZSBsb2FkZWQgTUlESSBmaWxlLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRieXRlc1Byb2Nlc3NlZCgpIHtcblx0XHQvLyBDdXJyZW50bHkgYXNzdW1lIGhlYWRlciBjaHVuayBpcyBzdHJpY3RseSAxNCBieXRlc1xuXHRcdHJldHVybiAxNCArIHRoaXMudHJhY2tzLmxlbmd0aCAqIDggKyB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHsgcmV0dXJuIHsgcG9pbnRlcjogYS5wb2ludGVyICsgYi5wb2ludGVyIH0gfSwgeyBwb2ludGVyOiAwIH0pLnBvaW50ZXI7XG5cdH1cblxuXHQvKipcblx0ICogTnVtYmVyIG9mIGV2ZW50cyBwbGF5ZWQgdXAgdG8gdGhpcyBwb2ludC5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0ZXZlbnRzUGxheWVkKCkge1xuXHRcdHJldHVybiB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHsgcmV0dXJuIHsgZXZlbnRJbmRleDogYS5ldmVudEluZGV4ICsgYi5ldmVudEluZGV4IH0gfSwgeyBldmVudEluZGV4OiAwIH0pLmV2ZW50SW5kZXg7XG5cdH1cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgcGxheWVyIHBvaW50ZXIgaGFzIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogVXNlZCBpbiB0d28gd2F5czpcblx0ICogMS4gSWYgcGxheWluZyByZXN1bHQgaXMgYmFzZWQgb24gbG9hZGVkIEpTT04gZXZlbnRzLlxuXHQgKiAyLiBJZiBwYXJzaW5nIChkcnlSdW4pIGl0J3MgYmFzZWQgb24gdGhlIGFjdHVhbCBidWZmZXIgbGVuZ3RoIHZzIGJ5dGVzIHByb2Nlc3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGVuZE9mRmlsZSgpIHtcblx0XHRpZiAodGhpcy5pc1BsYXlpbmcoKSlcblx0XHRcdHJldHVybiB0aGlzLmV2ZW50c1BsYXllZCgpID09IHRoaXMudG90YWxFdmVudHM7XG5cblx0XHRyZXR1cm4gdGhpcy5ieXRlc1Byb2Nlc3NlZCgpID09IHRoaXMuYnVmZmVyLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjdXJyZW50IHRpY2sgbnVtYmVyIGluIHBsYXliYWNrLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXRDdXJyZW50VGljaygpIHtcblx0XHRyZXR1cm4gTWF0aC5yb3VuZCgoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHRoaXMuc3RhcnRUaW1lKSAvIDEwMDAgKiAodGhpcy5kaXZpc2lvbiAqICh0aGlzLnRlbXBvIC8gNjApKSkgKyB0aGlzLnN0YXJ0VGljaztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZW5kcyBNSURJIGV2ZW50IG91dCB0byBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtvYmplY3R9XG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGVtaXRFdmVudChldmVudCkge1xuXHRcdHRoaXMudHJpZ2dlclBsYXllckV2ZW50KCdtaWRpRXZlbnQnLCBldmVudCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU3Vic2NyaWJlcyBldmVudHMgdG8gbGlzdGVuZXJzXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSAtIE5hbWUgb2YgZXZlbnQgdG8gc3Vic2NyaWJlIHRvLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9ufSAtIENhbGxiYWNrIHRvIGZpcmUgd2hlbiBldmVudCBpcyBicm9hZGNhc3QuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdG9uKHBsYXllckV2ZW50LCBmbikge1xuXHRcdGlmICghdGhpcy5ldmVudExpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShwbGF5ZXJFdmVudCkpXG5cdFx0XHR0aGlzLmV2ZW50TGlzdGVuZXJzW3BsYXllckV2ZW50XSA9IFtdO1xuXHRcdHRoaXMuZXZlbnRMaXN0ZW5lcnNbcGxheWVyRXZlbnRdLnB1c2goZm4pO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEJyb2FkY2FzdHMgZXZlbnQgdG8gdHJpZ2dlciBzdWJzY3JpYmVkIGNhbGxiYWNrcy5cblx0ICogQHBhcmFtIHtzdHJpbmd9IC0gTmFtZSBvZiBldmVudC5cblx0ICogQHBhcmFtIHtvYmplY3R9IC0gRGF0YSB0byBiZSBwYXNzZWQgdG8gc3Vic2NyaWJlciBjYWxsYmFjay5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0dHJpZ2dlclBsYXllckV2ZW50KHBsYXllckV2ZW50LCBkYXRhKSB7XG5cdFx0aWYgKHRoaXMuZXZlbnRMaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkocGxheWVyRXZlbnQpKVxuXHRcdFx0dGhpcy5ldmVudExpc3RlbmVyc1twbGF5ZXJFdmVudF0uZm9yRWFjaChmbiA9PiBmbihkYXRhIHx8IHt9KSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHsgUGxheWVyIH1cbiIsIlxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocGxheWVyKSB7XG4gIC8qKlxuICAgKiBBZGRzIGEgbGlzdGVuZXIgb2YgYW4gZXZlbnRcbiAgICogQGNoYWluYWJsZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnQgLSB0aGUgZXZlbnQgbmFtZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIHRoZSBldmVudCBoYW5kbGVyXG4gICAqIEByZXR1cm4ge1NhbXBsZVBsYXllcn0gdGhlIHBsYXllclxuICAgKiBAZXhhbXBsZVxuICAgKiBwbGF5ZXIub24oJ3N0YXJ0JywgZnVuY3Rpb24odGltZSwgbm90ZSkge1xuICAgKiAgIGNvbnNvbGUubG9nKHRpbWUsIG5vdGUpXG4gICAqIH0pXG4gICAqL1xuICBwbGF5ZXIub24gPSBmdW5jdGlvbiAoZXZlbnQsIGNiKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGV2ZW50ID09PSAnZnVuY3Rpb24nKSByZXR1cm4gcGxheWVyLm9uKCdldmVudCcsIGV2ZW50KVxuICAgIHZhciBwcm9wID0gJ29uJyArIGV2ZW50XG4gICAgdmFyIG9sZCA9IHBsYXllcltwcm9wXVxuICAgIHBsYXllcltwcm9wXSA9IG9sZCA/IGNoYWluKG9sZCwgY2IpIDogY2JcbiAgICByZXR1cm4gcGxheWVyXG4gIH1cbiAgcmV0dXJuIHBsYXllclxufVxuXG5mdW5jdGlvbiBjaGFpbiAoZm4xLCBmbjIpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChhLCBiLCBjLCBkKSB7IGZuMShhLCBiLCBjLCBkKTsgZm4yKGEsIGIsIGMsIGQpIH1cbn1cbiIsIid1c2Ugc3RyaWN0J1xuXG5jb25zdCBwbGF5ZXIgPSByZXF1aXJlKCcuL3BsYXllcicpXG5jb25zdCBldmVudHMgPSByZXF1aXJlKCcuL2V2ZW50cycpXG5jb25zdCBub3RlcyA9IHJlcXVpcmUoJy4vbm90ZXMnKVxuY29uc3Qgc2NoZWR1bGVyID0gcmVxdWlyZSgnLi9zY2hlZHVsZXInKVxuLy9jb25zdCBtaWRpID0gcmVxdWlyZSgnLi9taWRpJylcblxuZnVuY3Rpb24gU2FtcGxlUGxheWVyKGFjLCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgLy9yZXR1cm4gbWlkaShzY2hlZHVsZXIobm90ZXMoZXZlbnRzKHBsYXllcihhYywgc291cmNlLCBvcHRpb25zKSkpKSlcbiAgcmV0dXJuIHNjaGVkdWxlcihub3RlcyhldmVudHMocGxheWVyKGFjLCBzb3VyY2UsIG9wdGlvbnMpKSkpXG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBTYW1wbGVQbGF5ZXIgfVxuIiwiJ3VzZSBzdHJpY3QnXG5cbnZhciBub3RlID0gcmVxdWlyZSgnLi4vbm90ZS1wYXJzZXIvaW5kZXgnKVxudmFyIGlzTWlkaSA9IGZ1bmN0aW9uIChuKSB7IHJldHVybiBuICE9PSBudWxsICYmIG4gIT09IFtdICYmIG4gPj0gMCAmJiBuIDwgMTI5IH1cbnZhciB0b01pZGkgPSBmdW5jdGlvbiAobikgeyByZXR1cm4gaXNNaWRpKG4pID8gK24gOiBub3RlLm1pZGkobikgfVxuXG4vLyBBZGRzIG5vdGUgbmFtZSB0byBtaWRpIGNvbnZlcnNpb25cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHBsYXllcikge1xuICBpZiAocGxheWVyLmJ1ZmZlcnMpIHtcbiAgICB2YXIgbWFwID0gcGxheWVyLm9wdHMubWFwXG4gICAgdmFyIHRvS2V5ID0gdHlwZW9mIG1hcCA9PT0gJ2Z1bmN0aW9uJyA/IG1hcCA6IHRvTWlkaVxuICAgIHZhciBtYXBwZXIgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgcmV0dXJuIG5hbWUgPyB0b0tleShuYW1lKSB8fCBuYW1lIDogbnVsbFxuICAgIH1cblxuICAgIHBsYXllci5idWZmZXJzID0gbWFwQnVmZmVycyhwbGF5ZXIuYnVmZmVycywgbWFwcGVyKVxuICAgIHZhciBzdGFydCA9IHBsYXllci5zdGFydFxuICAgIHBsYXllci5zdGFydCA9IGZ1bmN0aW9uIChuYW1lLCB3aGVuLCBvcHRpb25zKSB7XG4gICAgICB2YXIga2V5ID0gbWFwcGVyKG5hbWUpXG4gICAgICB2YXIgZGVjID0ga2V5ICUgMVxuICAgICAgaWYgKGRlYykge1xuICAgICAgICBrZXkgPSBNYXRoLmZsb29yKGtleSlcbiAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucyB8fCB7fSwgeyBjZW50czogTWF0aC5mbG9vcihkZWMgKiAxMDApIH0pXG4gICAgICB9XG4gICAgICByZXR1cm4gc3RhcnQoa2V5LCB3aGVuLCBvcHRpb25zKVxuICAgIH1cbiAgfVxuICByZXR1cm4gcGxheWVyXG59XG5cbmZ1bmN0aW9uIG1hcEJ1ZmZlcnMoYnVmZmVycywgdG9LZXkpIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKGJ1ZmZlcnMpLnJlZHVjZShmdW5jdGlvbiAobWFwcGVkLCBuYW1lKSB7XG4gICAgbWFwcGVkW3RvS2V5KG5hbWUpXSA9IGJ1ZmZlcnNbbmFtZV1cbiAgICByZXR1cm4gbWFwcGVkXG4gIH0sIHt9KVxufVxuIiwiLyogZ2xvYmFsIEF1ZGlvQnVmZmVyICovXG4ndXNlIHN0cmljdCdcblxuY29uc3QgQURTUiA9IHJlcXVpcmUoJy4uL2Fkc3IvaW5kZXgnKVxuXG5jb25zdCBFTVBUWSA9IHt9XG5jb25zdCBERUZBVUxUUyA9IHtcbiAgZ2FpbjogMSxcbiAgYXR0YWNrOiAwLjAxLFxuICBkZWNheTogMC4xLFxuICBzdXN0YWluOiAwLjksXG4gIHJlbGVhc2U6IDAuMyxcbiAgbG9vcDogZmFsc2UsXG4gIGNlbnRzOiAwLFxuICBsb29wU3RhcnQ6IDAsXG4gIGxvb3BFbmQ6IDBcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBzYW1wbGUgcGxheWVyLlxuICpcbiAqIEBwYXJhbSB7QXVkaW9Db250ZXh0fSBhYyAtIHRoZSBhdWRpbyBjb250ZXh0XG4gKiBAcGFyYW0ge0FycmF5QnVmZmVyfE9iamVjdDxTdHJpbmcsQXJyYXlCdWZmZXI+fSBzb3VyY2VcbiAqIEBwYXJhbSB7T25qZWN0fSBvcHRpb25zIC0gKE9wdGlvbmFsKSBhbiBvcHRpb25zIG9iamVjdFxuICogQHJldHVybiB7cGxheWVyfSB0aGUgcGxheWVyXG4gKiBAZXhhbXBsZVxuICogY29uc3QgU2FtcGxlUGxheWVyID0gcmVxdWlyZSgnc2FtcGxlLXBsYXllcicpXG4gKiBjb25zdCBhYyA9IG5ldyBBdWRpb0NvbnRleHQoKVxuICogY29uc3Qgc25hcmUgPSBTYW1wbGVQbGF5ZXIoYWMsIDxBdWRpb0J1ZmZlcj4pXG4gKiBzbmFyZS5wbGF5KClcbiAqL1xuZnVuY3Rpb24gU2FtcGxlUGxheWVyKGFjLCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgbGV0IGNvbm5lY3RlZCA9IGZhbHNlXG4gIGxldCBuZXh0SWQgPSAwXG4gIGxldCB0cmFja2VkID0ge31cbiAgY29uc3Qgb3V0ID0gYWMuY3JlYXRlR2FpbigpXG4gIG91dC5nYWluLnZhbHVlID0gMVxuXG4gIGNvbnN0IG9wdHMgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUUywgb3B0aW9ucylcblxuICAvKipcbiAgICogQG5hbWVzcGFjZVxuICAgKi9cbiAgY29uc3QgcGxheWVyID0geyBjb250ZXh0OiBhYywgb3V0LCBvcHRzIH1cbiAgaWYgKHNvdXJjZSBpbnN0YW5jZW9mIEF1ZGlvQnVmZmVyKVxuICAgIHBsYXllci5idWZmZXIgPSBzb3VyY2VcbiAgZWxzZVxuICAgIHBsYXllci5idWZmZXJzID0gc291cmNlXG5cbiAgLyoqXG4gICAqIFN0YXJ0IGEgc2FtcGxlIGJ1ZmZlci5cbiAgICpcbiAgICogVGhlIHJldHVybmVkIG9iamVjdCBoYXMgYSBmdW5jdGlvbiBgc3RvcCh3aGVuKWAgdG8gc3RvcCB0aGUgc291bmQuXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gdGhlIG5hbWUgb2YgdGhlIGJ1ZmZlci4gSWYgdGhlIHNvdXJjZSBvZiB0aGVcbiAgICogU2FtcGxlUGxheWVyIGlzIG9uZSBzYW1wbGUgYnVmZmVyLCB0aGlzIHBhcmFtZXRlciBpcyBub3QgcmVxdWlyZWRcbiAgICogQHBhcmFtIHtGbG9hdH0gd2hlbiAtIChPcHRpb25hbCkgd2hlbiB0byBzdGFydCAoY3VycmVudCB0aW1lIGlmIGJ5IGRlZmF1bHQpXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gYWRkaXRpb25hbCBzYW1wbGUgcGxheWluZyBvcHRpb25zXG4gICAqIEByZXR1cm4ge0F1ZGlvTm9kZX0gYW4gYXVkaW8gbm9kZSB3aXRoIGEgYHN0b3BgIGZ1bmN0aW9uXG4gICAqIEBleGFtcGxlXG4gICAqIHZhciBzYW1wbGUgPSBwbGF5ZXIoYWMsIDxBdWRpb0J1ZmZlcj4pLmNvbm5lY3QoYWMuZGVzdGluYXRpb24pXG4gICAqIHNhbXBsZS5zdGFydCgpXG4gICAqIHNhbXBsZS5zdGFydCg1LCB7IGdhaW46IDAuNyB9KSAvLyBuYW1lIG5vdCByZXF1aXJlZCBzaW5jZSBpcyBvbmx5IG9uZSBBdWRpb0J1ZmZlclxuICAgKiBAZXhhbXBsZVxuICAgKiB2YXIgZHJ1bXMgPSBwbGF5ZXIoYWMsIHsgc25hcmU6IDxBdWRpb0J1ZmZlcj4sIGtpY2s6IDxBdWRpb0J1ZmZlcj4sIC4uLiB9KS5jb25uZWN0KGFjLmRlc3RpbmF0aW9uKVxuICAgKiBkcnVtcy5zdGFydCgnc25hcmUnKVxuICAgKiBkcnVtcy5zdGFydCgnc25hcmUnLCAwLCB7IGdhaW46IDAuMyB9KVxuICAgKi9cbiAgcGxheWVyLnN0YXJ0ID0gZnVuY3Rpb24gKG5hbWUsIHdoZW4sIG9wdGlvbnMpIHtcbiAgICAvLyBpZiBvbmx5IG9uZSBidWZmZXIsIHJlb3JkZXIgYXJndW1lbnRzXG4gICAgaWYgKHBsYXllci5idWZmZXIgJiYgbmFtZSAhPT0gbnVsbClcbiAgICAgIHJldHVybiBwbGF5ZXIuc3RhcnQobnVsbCwgbmFtZSwgd2hlbilcblxuICAgIHZhciBidWZmZXIgPSBuYW1lID8gcGxheWVyLmJ1ZmZlcnNbbmFtZV0gOiBwbGF5ZXIuYnVmZmVyXG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgIGNvbnNvbGUud2FybihgQnVmZmVyICR7bmFtZX0gbm90IGZvdW5kLmApXG4gICAgICByZXR1cm5cbiAgICB9IGVsc2UgaWYgKCFjb25uZWN0ZWQpIHtcbiAgICAgIGNvbnNvbGUud2FybignU2FtcGxlUGxheWVyIG5vdCBjb25uZWN0ZWQgdG8gYW55IG5vZGUuJylcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IG9wdHMgPSBvcHRpb25zIHx8IEVNUFRZXG4gICAgd2hlbiA9IE1hdGgubWF4KGFjLmN1cnJlbnRUaW1lLCB3aGVuIHx8IDApXG4gICAgcGxheWVyLmVtaXQoJ3N0YXJ0Jywgd2hlbiwgbmFtZSwgb3B0cylcbiAgICB2YXIgbm9kZSA9IGNyZWF0ZU5vZGUobmFtZSwgYnVmZmVyLCBvcHRzKVxuICAgIG5vZGUuaWQgPSB0cmFjayhuYW1lLCBub2RlKVxuICAgIG5vZGUuZW52LnN0YXJ0KHdoZW4pXG4gICAgbm9kZS5zb3VyY2Uuc3RhcnQod2hlbilcbiAgICBwbGF5ZXIuZW1pdCgnc3RhcnRlZCcsIHdoZW4sIG5vZGUuaWQsIG5vZGUpXG4gICAgaWYgKG9wdHMuZHVyYXRpb24pXG4gICAgICBub2RlLnN0b3Aod2hlbiArIG9wdHMuZHVyYXRpb24pXG4gICAgcmV0dXJuIG5vZGVcbiAgfVxuXG4gIC8vIE5PVEU6IHN0YXJ0IHdpbGwgYmUgb3ZlcnJpZGUgc28gd2UgY2FuJ3QgY29weSB0aGUgZnVuY3Rpb24gcmVmZXJlbmNlXG4gIC8vIHRoaXMgaXMgb2J2aW91c2x5IG5vdCBhIGdvb2QgZGVzaWduLCBzbyB0aGlzIGNvZGUgd2lsbCBiZSBnb25lIHNvb24uXG4gIC8qKlxuICAgKiBBbiBhbGlhcyBmb3IgYHBsYXllci5zdGFydGBcbiAgICogQHNlZSBwbGF5ZXIuc3RhcnRcbiAgICogQHNpbmNlIDAuMy4wXG4gICAqL1xuICBwbGF5ZXIucGxheSA9IGZ1bmN0aW9uIChuYW1lLCB3aGVuLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIHBsYXllci5zdGFydChuYW1lLCB3aGVuLCBvcHRpb25zKVxuICB9XG5cbiAgLyoqXG4gICAqIFN0b3Agc29tZSBvciBhbGwgc2FtcGxlc1xuICAgKlxuICAgKiBAcGFyYW0ge0Zsb2F0fSB3aGVuIC0gKE9wdGlvbmFsKSBhbiBhYnNvbHV0ZSB0aW1lIGluIHNlY29uZHMgKG9yIGN1cnJlbnRUaW1lXG4gICAqIGlmIG5vdCBzcGVjaWZpZWQpXG4gICAqIEBwYXJhbSB7QXJyYXl9IG5vZGVzIC0gKE9wdGlvbmFsKSBhbiBhcnJheSBvZiBub2RlcyBvciBub2RlcyBpZHMgdG8gc3RvcFxuICAgKiBAcmV0dXJuIHtBcnJheX0gYW4gYXJyYXkgb2YgaWRzIG9mIHRoZSBzdG9wZWQgc2FtcGxlc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiB2YXIgbG9uZ1NvdW5kID0gcGxheWVyKGFjLCA8QXVkaW9CdWZmZXI+KS5jb25uZWN0KGFjLmRlc3RpbmF0aW9uKVxuICAgKiBsb25nU291bmQuc3RhcnQoYWMuY3VycmVudFRpbWUpXG4gICAqIGxvbmdTb3VuZC5zdGFydChhYy5jdXJyZW50VGltZSArIDEpXG4gICAqIGxvbmdTb3VuZC5zdGFydChhYy5jdXJyZW50VGltZSArIDIpXG4gICAqIGxvbmdTb3VuZC5zdG9wKGFjLmN1cnJlbnRUaW1lICsgMykgLy8gc3RvcCB0aGUgdGhyZWUgc291bmRzXG4gICAqL1xuICBwbGF5ZXIuc3RvcCA9IGZ1bmN0aW9uICh3aGVuLCBpZHMpIHtcbiAgICBpZHMgPSBpZHMgfHwgT2JqZWN0LmtleXModHJhY2tlZClcbiAgICByZXR1cm4gaWRzLm1hcChmdW5jdGlvbiAoaWQpIHtcbiAgICAgIGNvbnN0IG5vZGUgPSB0cmFja2VkW2lkXVxuICAgICAgaWYgKCFub2RlKSByZXR1cm4gbnVsbFxuICAgICAgbm9kZS5zdG9wKHdoZW4pXG4gICAgICByZXR1cm4gbm9kZS5pZFxuICAgIH0pXG4gIH1cbiAgLyoqXG4gICAqIENvbm5lY3QgdGhlIHBsYXllciB0byBhIGRlc3RpbmF0aW9uIG5vZGVcbiAgICpcbiAgICogQHBhcmFtIHtBdWRpb05vZGV9IGRlc3RpbmF0aW9uIC0gdGhlIGRlc3RpbmF0aW9uIG5vZGVcbiAgICogQHJldHVybiB7QXVkaW9QbGF5ZXJ9IHRoZSBwbGF5ZXJcbiAgICogQGNoYWluYWJsZVxuICAgKiBAZXhhbXBsZVxuICAgKiB2YXIgc2FtcGxlID0gcGxheWVyKGFjLCA8QXVkaW9CdWZmZXI+KS5jb25uZWN0KGFjLmRlc3RpbmF0aW9uKVxuICAgKi9cbiAgcGxheWVyLmNvbm5lY3QgPSBmdW5jdGlvbiAoZGVzdCkge1xuICAgIGNvbm5lY3RlZCA9IHRydWVcbiAgICBvdXQuY29ubmVjdChkZXN0KVxuICAgIHJldHVybiBwbGF5ZXJcbiAgfVxuXG4gIHBsYXllci5lbWl0ID0gZnVuY3Rpb24gKGV2ZW50LCB3aGVuLCBvYmosIG9wdHMpIHtcbiAgICBpZiAocGxheWVyLm9uZXZlbnQpIHBsYXllci5vbmV2ZW50KGV2ZW50LCB3aGVuLCBvYmosIG9wdHMpXG4gICAgY29uc3QgZm4gPSBwbGF5ZXJbJ29uJyArIGV2ZW50XVxuICAgIGlmIChmbikgZm4od2hlbiwgb2JqLCBvcHRzKVxuICB9XG5cbiAgcmV0dXJuIHBsYXllclxuXG4gIC8vID09PT09PT09PT09PT09PSBQUklWQVRFIEZVTkNUSU9OUyA9PT09PT09PT09PT09PSAvL1xuXG4gIGZ1bmN0aW9uIHRyYWNrKG5hbWUsIG5vZGUpIHtcbiAgICBub2RlLmlkID0gbmV4dElkKytcbiAgICB0cmFja2VkW25vZGUuaWRdID0gbm9kZVxuICAgIG5vZGUuc291cmNlLm9uZW5kZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub3cgPSBhYy5jdXJyZW50VGltZVxuICAgICAgbm9kZS5zb3VyY2UuZGlzY29ubmVjdCgpXG4gICAgICBub2RlLmVudi5kaXNjb25uZWN0KClcbiAgICAgIG5vZGUuZGlzY29ubmVjdCgpXG4gICAgICBwbGF5ZXIuZW1pdCgnZW5kZWQnLCBub3csIG5vZGUuaWQsIG5vZGUpXG4gICAgfVxuICAgIHJldHVybiBub2RlLmlkXG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVOb2RlKG5hbWUsIGJ1ZmZlciwgb3B0aW9ucykge1xuICAgIGNvbnN0IG5vZGUgPSBhYy5jcmVhdGVHYWluKClcbiAgICBub2RlLmdhaW4udmFsdWUgPSAwIC8vIHRoZSBlbnZlbG9wZSB3aWxsIGNvbnRyb2wgdGhlIGdhaW5cbiAgICBub2RlLmNvbm5lY3Qob3V0KVxuXG4gICAgbm9kZS5lbnYgPSBlbnZlbG9wZShhYywgb3B0aW9ucywgb3B0cylcbiAgICBub2RlLmVudi5jb25uZWN0KG5vZGUuZ2FpbilcblxuICAgIG5vZGUuc291cmNlID0gYWMuY3JlYXRlQnVmZmVyU291cmNlKClcbiAgICBub2RlLnNvdXJjZS5idWZmZXIgPSBidWZmZXJcbiAgICBub2RlLnNvdXJjZS5jb25uZWN0KG5vZGUpXG4gICAgbm9kZS5zb3VyY2UubG9vcCA9IG9wdGlvbnMubG9vcCB8fCBvcHRzLmxvb3BcbiAgICBub2RlLnNvdXJjZS5wbGF5YmFja1JhdGUudmFsdWUgPSBjZW50c1RvUmF0ZShvcHRpb25zLmNlbnRzIHx8IG9wdHMuY2VudHMpXG4gICAgbm9kZS5zb3VyY2UubG9vcFN0YXJ0ID0gb3B0aW9ucy5sb29wU3RhcnQgfHwgb3B0cy5sb29wU3RhcnRcbiAgICBub2RlLnNvdXJjZS5sb29wRW5kID0gb3B0aW9ucy5sb29wRW5kIHx8IG9wdHMubG9vcEVuZFxuICAgIG5vZGUuc3RvcCA9IGZ1bmN0aW9uICh3aGVuKSB7XG4gICAgICBjb25zdCB0aW1lID0gd2hlbiB8fCBhYy5jdXJyZW50VGltZVxuICAgICAgcGxheWVyLmVtaXQoJ3N0b3AnLCB0aW1lLCBuYW1lKVxuICAgICAgY29uc3Qgc3RvcEF0ID0gbm9kZS5lbnYuc3RvcCh0aW1lKVxuICAgICAgbm9kZS5zb3VyY2Uuc3RvcChzdG9wQXQpXG4gICAgfVxuICAgIHJldHVybiBub2RlXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNOdW0oeCkgeyByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInIH1cblxuY29uc3QgUEFSQU1TID0gWydhdHRhY2snLCAnZGVjYXknLCAnc3VzdGFpbicsICdyZWxlYXNlJ11cblxuZnVuY3Rpb24gZW52ZWxvcGUoYWMsIG9wdGlvbnMsIG9wdHMpIHtcbiAgY29uc3QgZW52ID0gQURTUihhYylcbiAgY29uc3QgYWRzciA9IG9wdGlvbnMuYWRzciB8fCBvcHRzLmFkc3JcbiAgUEFSQU1TLmZvckVhY2goZnVuY3Rpb24gKG5hbWUsIGkpIHtcbiAgICBpZiAoYWRzcikgZW52W25hbWVdID0gYWRzcltpXVxuICAgIGVsc2UgZW52W25hbWVdID0gb3B0aW9uc1tuYW1lXSB8fCBvcHRzW25hbWVdXG4gIH0pXG4gIGVudi52YWx1ZS52YWx1ZSA9IGlzTnVtKG9wdGlvbnMuZ2FpbikgPyBvcHRpb25zLmdhaW5cbiAgICA6IGlzTnVtKG9wdHMuZ2FpbikgPyBvcHRzLmdhaW4gOiAxXG4gIHJldHVybiBlbnZcbn1cblxuLypcbiAqIEdldCBwbGF5YmFjayByYXRlIGZvciBhIGdpdmVuIHBpdGNoIGNoYW5nZSAoaW4gY2VudHMpXG4gKiBCYXNpYyBbbWF0aF0oaHR0cDovL3d3dy5iaXJkc29mdC5kZW1vbi5jby51ay9tdXNpYy9zYW1wbGVydC5odG0pOlxuICogZjIgPSBmMSAqIDJeKCBDIC8gMTIwMCApXG4gKi9cbmZ1bmN0aW9uIGNlbnRzVG9SYXRlKGNlbnRzKSB7IHJldHVybiBjZW50cyA/IE1hdGgucG93KDIsIGNlbnRzIC8gMTIwMCkgOiAxIH1cblxubW9kdWxlLmV4cG9ydHMgPSBTYW1wbGVQbGF5ZXJcbiIsIid1c2Ugc3RyaWN0J1xuXG52YXIgaXNBcnIgPSBBcnJheS5pc0FycmF5XG52YXIgaXNPYmogPSBmdW5jdGlvbiAobykgeyByZXR1cm4gbyAmJiB0eXBlb2YgbyA9PT0gJ29iamVjdCcgfVxudmFyIE9QVFMgPSB7fVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwbGF5ZXIpIHtcbiAgLyoqXG4gICAqIFNjaGVkdWxlIGEgbGlzdCBvZiBldmVudHMgdG8gYmUgcGxheWVkIGF0IHNwZWNpZmljIHRpbWUuXG4gICAqXG4gICAqIEl0IHN1cHBvcnRzIHRocmVlIGZvcm1hdHMgb2YgZXZlbnRzIGZvciB0aGUgZXZlbnRzIGxpc3Q6XG4gICAqXG4gICAqIC0gQW4gYXJyYXkgd2l0aCBbdGltZSwgbm90ZV1cbiAgICogLSBBbiBhcnJheSB3aXRoIFt0aW1lLCBvYmplY3RdXG4gICAqIC0gQW4gb2JqZWN0IHdpdGggeyB0aW1lOiA/LCBbbmFtZXxub3RlfG1pZGl8a2V5XTogPyB9XG4gICAqXG4gICAqIEBwYXJhbSB7RmxvYXR9IHRpbWUgLSBhbiBhYnNvbHV0ZSB0aW1lIHRvIHN0YXJ0IChvciBBdWRpb0NvbnRleHQnc1xuICAgKiBjdXJyZW50VGltZSBpZiBwcm92aWRlZCBudW1iZXIgaXMgMClcbiAgICogQHBhcmFtIHtBcnJheX0gZXZlbnRzIC0gdGhlIGV2ZW50cyBsaXN0LlxuICAgKiBAcmV0dXJuIHtBcnJheX0gYW4gYXJyYXkgb2YgaWRzXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIEV2ZW50IGZvcm1hdDogW3RpbWUsIG5vdGVdXG4gICAqIHZhciBwaWFubyA9IHBsYXllcihhYywgLi4uKS5jb25uZWN0KGFjLmRlc3RpbmF0aW9uKVxuICAgKiBwaWFuby5zY2hlZHVsZSgwLCBbIFswLCAnQzInXSwgWzAuNSwgJ0MzJ10sIFsxLCAnQzQnXSBdKVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBFdmVudCBmb3JtYXQ6IGFuIG9iamVjdCB7IHRpbWU6ID8sIG5hbWU6ID8gfVxuICAgKiB2YXIgZHJ1bXMgPSBwbGF5ZXIoYWMsIC4uLikuY29ubmVjdChhYy5kZXN0aW5hdGlvbilcbiAgICogZHJ1bXMuc2NoZWR1bGUoMCwgW1xuICAgKiAgIHsgbmFtZTogJ2tpY2snLCB0aW1lOiAwIH0sXG4gICAqICAgeyBuYW1lOiAnc25hcmUnLCB0aW1lOiAwLjUgfSxcbiAgICogICB7IG5hbWU6ICdraWNrJywgdGltZTogMSB9LFxuICAgKiAgIHsgbmFtZTogJ3NuYXJlJywgdGltZTogMS41IH1cbiAgICogXSlcbiAgICovXG4gIHBsYXllci5zY2hlZHVsZSA9IGZ1bmN0aW9uICh0aW1lLCBldmVudHMpIHtcbiAgICB2YXIgbm93ID0gcGxheWVyLmNvbnRleHQuY3VycmVudFRpbWVcbiAgICB2YXIgd2hlbiA9IHRpbWUgPCBub3cgPyBub3cgOiB0aW1lXG4gICAgcGxheWVyLmVtaXQoJ3NjaGVkdWxlJywgd2hlbiwgZXZlbnRzKVxuICAgIHZhciB0LCBvLCBub3RlLCBvcHRzXG4gICAgcmV0dXJuIGV2ZW50cy5tYXAoZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBpZiAoIWV2ZW50KSByZXR1cm4gbnVsbFxuICAgICAgZWxzZSBpZiAoaXNBcnIoZXZlbnQpKSB7XG4gICAgICAgIHQgPSBldmVudFswXTsgbyA9IGV2ZW50WzFdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ID0gZXZlbnQudGltZTsgbyA9IGV2ZW50XG4gICAgICB9XG5cbiAgICAgIGlmIChpc09iaihvKSkge1xuICAgICAgICBub3RlID0gby5uYW1lIHx8IG8ua2V5IHx8IG8ubm90ZSB8fCBvLm1pZGkgfHwgbnVsbFxuICAgICAgICBvcHRzID0gb1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm90ZSA9IG9cbiAgICAgICAgb3B0cyA9IE9QVFNcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHBsYXllci5zdGFydChub3RlLCB3aGVuICsgKHQgfHwgMCksIG9wdHMpXG4gICAgfSlcbiAgfVxuICByZXR1cm4gcGxheWVyXG59XG4iLCIndXNlIHN0cmljdCdcblxuY29uc3QgbG9hZCA9IHJlcXVpcmUoJy4uL2F1ZGlvLWxvYWRlci9pbmRleCcpLmxvYWRcbmNvbnN0IHBsYXllciA9IHJlcXVpcmUoJy4uL3NhbXBsZS1wbGF5ZXIvaW5kZXgnKS5TYW1wbGVQbGF5ZXJcblxuLyoqXG4gKiBMb2FkIGEgc291bmRmb250IGluc3RydW1lbnQuIEl0IHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYVxuICogaW5zdHJ1bWVudCBvYmplY3QuXG4gKlxuICogVGhlIGluc3RydW1lbnQgb2JqZWN0IHJldHVybmVkIGJ5IHRoZSBwcm9taXNlIGhhcyB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XG4gKlxuICogLSBuYW1lOiB0aGUgaW5zdHJ1bWVudCBuYW1lXG4gKiAtIHBsYXk6IEEgZnVuY3Rpb24gdG8gcGxheSBub3RlcyBmcm9tIHRoZSBidWZmZXIgd2l0aCB0aGUgc2lnbmF0dXJlXG4gKiBgcGxheShub3RlLCB0aW1lLCBkdXJhdGlvbiwgb3B0aW9ucylgXG4gKlxuICpcbiAqIFRoZSB2YWxpZCBvcHRpb25zIGFyZTpcbiAqXG4gKiAtIGBmb3JtYXRgOiB0aGUgc291bmRmb250IGZvcm1hdC4gJ21wMycgYnkgZGVmYXVsdC4gQ2FuIGJlICdvZ2cnXG4gKiAtIGBzb3VuZGZvbnRgOiB0aGUgc291bmRmb250IG5hbWUuICdNdXN5bmdLaXRlJyBieSBkZWZhdWx0LiBDYW4gYmUgJ0ZsdWlkUjNfR00nXG4gKiAtIGBuYW1lVG9VcmxgIDxGdW5jdGlvbj46IGEgZnVuY3Rpb24gdG8gY29udmVydCBmcm9tIGluc3RydW1lbnQgbmFtZXMgdG8gVVJMXG4gKiAtIGBkZXN0aW5hdGlvbmA6IGJ5IGRlZmF1bHQgU291bmRmb250IHVzZXMgdGhlIGBhdWRpb0NvbnRleHQuZGVzdGluYXRpb25gIGJ1dCB5b3UgY2FuIG92ZXJyaWRlIGl0LlxuICogLSBgZ2FpbmA6IHRoZSBnYWluIG9mIHRoZSBwbGF5ZXIgKDEgYnkgZGVmYXVsdClcbiAqIC0gYG5vdGVzYDogYW4gYXJyYXkgb2YgdGhlIG5vdGVzIHRvIGRlY29kZS4gSXQgY2FuIGJlIGFuIGFycmF5IG9mIHN0cmluZ3NcbiAqIHdpdGggbm90ZSBuYW1lcyBvciBhbiBhcnJheSBvZiBudW1iZXJzIHdpdGggbWlkaSBub3RlIG51bWJlcnMuIFRoaXMgaXMgYVxuICogcGVyZm9ybWFuY2Ugb3B0aW9uOiBzaW5jZSBkZWNvZGluZyBtcDMgaXMgYSBjcHUgaW50ZW5zaXZlIHByb2Nlc3MsIHlvdSBjYW4gbGltaXRcbiAqIGxpbWl0IHRoZSBudW1iZXIgb2Ygbm90ZXMgeW91IHdhbnQgYW5kIHJlZHVjZSB0aGUgdGltZSB0byBsb2FkIHRoZSBpbnN0cnVtZW50LlxuICpcbiAqIEBwYXJhbSB7QXVkaW9Db250ZXh0fSBhYyAtIHRoZSBhdWRpbyBjb250ZXh0XG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSAtIHRoZSBpbnN0cnVtZW50IG5hbWUuIEZvciBleGFtcGxlOiAnYWNvdXN0aWNfZ3JhbmRfcGlhbm8nXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIChPcHRpb25hbCkgdGhlIHNhbWUgb3B0aW9ucyBhcyBTb3VuZGZvbnQubG9hZEJ1ZmZlcnNcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKlxuICogQGV4YW1wbGVcbiAqIHZhciBTb3VuZGZvbnQgPSByZXF1aXJlKCdzb3VuZm9udC1wbGF5ZXInKVxuICogU291bmRmb250Lmluc3RydW1lbnQoJ21hcmltYmEnKS50aGVuKGZ1bmN0aW9uIChtYXJpbWJhKSB7XG4gKiAgIG1hcmltYmEucGxheSgnQzQnKVxuICogfSlcbiAqL1xuZnVuY3Rpb24gaW5zdHJ1bWVudChhYywgc291cmNlLCBvcHRpb25zID0ge30pIHtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChuLCBvKSB7IHJldHVybiBpbnN0cnVtZW50KGFjLCBuLCBvKSB9XG5cbiAgbGV0IGluc3ROYW1lID0gJycsIGluc3RVcmwgPSAnJztcbiAgaWYgKHR5cGVvZiBzb3VyY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgaW5zdE5hbWUgPSBzb3VyY2VcbiAgICBjb25zdCBpc1VybCA9IG9wdGlvbnMuaXNTb3VuZGZvbnRVUkwgfHwgaXNTb3VuZGZvbnRVUkxcbiAgICBjb25zdCB0b1VybCA9IG9wdGlvbnMubmFtZVRvVXJsIHx8IG5hbWVUb1VybFxuICAgIGluc3RVcmwgPSBpc1VybChzb3VyY2UpID8gc291cmNlIDogdG9Vcmwoc291cmNlLCBvcHRpb25zLnNvdW5kZm9udCwgb3B0aW9ucy5mb3JtYXQpXG4gICAgc291cmNlID0gaW5zdFVybFxuICB9XG5cbiAgcmV0dXJuIGxvYWQoYWMsIHNvdXJjZSwgeyBvbmx5OiBvcHRpb25zLm9ubHkgfHwgb3B0aW9ucy5ub3RlcyB9KVxuICAgIC50aGVuKGJ1ZmZlcnMgPT4ge1xuICAgICAgY29uc3QgcCA9IHBsYXllcihhYywgYnVmZmVycywgb3B0aW9ucykuY29ubmVjdChvcHRpb25zLmRlc3RpbmF0aW9uID8gb3B0aW9ucy5kZXN0aW5hdGlvbiA6IGFjLmRlc3RpbmF0aW9uKVxuICAgICAgcC51cmwgPSBpbnN0VXJsXG4gICAgICBwLm5hbWUgPSBpbnN0TmFtZVxuICAgICAgcmV0dXJuIHBcbiAgICB9KVxufVxuXG5mdW5jdGlvbiBpc1NvdW5kZm9udFVSTChuYW1lKSB7XG4gIHJldHVybiAvXFwuanMoXFw/LiopPyQvaS50ZXN0KG5hbWUpXG59XG5cbi8qKlxuICogR2l2ZW4gYW4gaW5zdHJ1bWVudCBuYW1lIHJldHVybnMgYSBVUkwgdG8gdG8gdGhlIEJlbmphbWluIEdsZWl0em1hbidzXG4gKiBwYWNrYWdlIG9mIFtwcmUtcmVuZGVyZWQgc291bmQgZm9udHNdKGh0dHBzOi8vZ2l0aHViLmNvbS9nbGVpdHovbWlkaS1qcy1zb3VuZGZvbnRzKVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIC0gaW5zdHJ1bWVudCBuYW1lXG4gKiBAcGFyYW0ge1N0cmluZ30gc291bmRmb250IC0gKE9wdGlvbmFsKSB0aGUgc291bmRmb250IG5hbWUuIE9uZSBvZiAnRmx1aWRSM19HTSdcbiAqIG9yICdNdXN5bmdLaXRlJyAoJ011c3luZ0tpdGUnIGJ5IGRlZmF1bHQpXG4gKiBAcGFyYW0ge1N0cmluZ30gZm9ybWF0IC0gKE9wdGlvbmFsKSBDYW4gYmUgJ21wMycgb3IgJ29nZycgKG1wMyBieSBkZWZhdWx0KVxuICogQHJldHVybnMge1N0cmluZ30gdGhlIFNvdW5kZm9udCBmaWxlIHVybFxuICogQGV4YW1wbGVcbiAqIHZhciBTb3VuZGZvbnQgPSByZXF1aXJlKCdzb3VuZGZvbnQtcGxheWVyJylcbiAqIFNvdW5kZm9udC5uYW1lVG9VcmwoJ21hcmltYmEnLCAnbXAzJylcbiAqL1xuZnVuY3Rpb24gbmFtZVRvVXJsKG5hbWUsIHNmLCBmb3JtYXQpIHtcbiAgZm9ybWF0ID0gZm9ybWF0ID09PSAnb2dnJyA/IGZvcm1hdCA6ICdtcDMnXG4gIHNmID0gc2YgPT09ICdGbHVpZFIzX0dNJyA/IHNmIDogJ011c3luZ0tpdGUnXG4gIHJldHVybiAnaHR0cHM6Ly9nbGVpdHouZ2l0aHViLmlvL21pZGktanMtc291bmRmb250cy8nICsgc2YgKyAnLycgKyBuYW1lICsgJy0nICsgZm9ybWF0ICsgJy5qcydcbn1cblxuY29uc3QgU291bmRmb250ID0ge1xuICBpbnN0cnVtZW50LFxuICBuYW1lVG9VcmwsXG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBTb3VuZGZvbnQgfVxuIiwiY29uc3QgQ29uc3RhbnRzID0gcmVxdWlyZSgnLi9jb25zdGFudHMnKS5Db25zdGFudHM7XG5jb25zdCBVdGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKS5VdGlscztcblxuLyoqXG4gKiBDbGFzcyByZXByZXNlbnRpbmcgYSB0cmFjay4gIENvbnRhaW5zIG1ldGhvZHMgZm9yIHBhcnNpbmcgZXZlbnRzIGFuZCBrZWVwaW5nIHRyYWNrIG9mIHBvaW50ZXIuXG4gKi9cbmNsYXNzIFRyYWNrIHtcblx0Y29uc3RydWN0b3IoaW5kZXgsIGRhdGEpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXHRcdHRoaXMuZXZlbnRJbmRleCA9IDA7XG5cdFx0dGhpcy5wb2ludGVyID0gMDtcblx0XHR0aGlzLmxhc3RUaWNrID0gMDtcblx0XHR0aGlzLmxhc3RTdGF0dXMgPSBudWxsO1xuXHRcdHRoaXMuaW5kZXggPSBpbmRleDtcblx0XHR0aGlzLmRhdGEgPSBkYXRhO1xuXHRcdHRoaXMuZGVsdGEgPSAwO1xuXHRcdHRoaXMucnVubmluZ0RlbHRhID0gMDtcblx0XHR0aGlzLmV2ZW50cyA9IFtdO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlc2V0cyBhbGwgc3RhdGVmdWwgdHJhY2sgaW5mb3JtYWlvbiB1c2VkIGR1cmluZyBwbGF5YmFjay5cblx0ICogQHJldHVybiB7VHJhY2t9XG5cdCAqL1xuXHRyZXNldCgpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXHRcdHRoaXMuZXZlbnRJbmRleCA9IDA7XG5cdFx0dGhpcy5wb2ludGVyID0gMDtcblx0XHR0aGlzLmxhc3RUaWNrID0gMDtcblx0XHR0aGlzLmxhc3RTdGF0dXMgPSBudWxsO1xuXHRcdHRoaXMuZGVsdGEgPSAwO1xuXHRcdHRoaXMucnVubmluZ0RlbHRhID0gMDtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoaXMgdHJhY2sgdG8gYmUgZW5hYmxlZCBkdXJpbmcgcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge1RyYWNrfVxuXHQgKi9cblx0ZW5hYmxlKCkge1xuXHRcdHRoaXMuZW5hYmxlZCA9IHRydWU7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGlzIHRyYWNrIHRvIGJlIGRpc2FibGVkIGR1cmluZyBwbGF5YmFjay5cblx0ICogQHJldHVybiB7VHJhY2t9XG5cdCAqL1xuXHRkaXNhYmxlKCkge1xuXHRcdHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhlIHRyYWNrIGV2ZW50IGluZGV4IHRvIHRoZSBuZWFyZXN0IGV2ZW50IHRvIHRoZSBnaXZlbiB0aWNrLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gdGlja1xuXHQgKiBAcmV0dXJuIHtUcmFja31cblx0ICovXG5cdHNldEV2ZW50SW5kZXhCeVRpY2sodGljaykge1xuXHRcdHRpY2sgPSB0aWNrIHx8IDA7XG5cblx0XHRmb3IgKGxldCBpIGluIHRoaXMuZXZlbnRzKSB7XG5cdFx0XHRpZiAodGhpcy5ldmVudHNbaV0udGljayA+PSB0aWNrKSB7XG5cdFx0XHRcdHRoaXMuZXZlbnRJbmRleCA9IGk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGJ5dGUgbG9jYXRlZCBhdCBwb2ludGVyIHBvc2l0aW9uLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXRDdXJyZW50Qnl0ZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5kYXRhW3RoaXMucG9pbnRlcl07XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBjb3VudCBvZiBkZWx0YSBieXRlcyBhbmQgY3VycmVudCBwb2ludGVyIHBvc2l0aW9uLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXREZWx0YUJ5dGVDb3VudCgpIHtcblx0XHQvLyBHZXQgYnl0ZSBjb3VudCBvZiBkZWx0YSBWTFZcblx0XHQvLyBodHRwOi8vd3d3LmNjYXJoLm9yZy9jb3Vyc2VzLzI1My9oYW5kb3V0L3Zsdi9cblx0XHQvLyBJZiBieXRlIGlzIGdyZWF0ZXIgb3IgZXF1YWwgdG8gODBoICgxMjggZGVjaW1hbCkgdGhlbiB0aGUgbmV4dCBieXRlXG5cdFx0Ly8gaXMgYWxzbyBwYXJ0IG9mIHRoZSBWTFYsXG5cdFx0Ly8gZWxzZSBieXRlIGlzIHRoZSBsYXN0IGJ5dGUgaW4gYSBWTFYuXG5cdFx0bGV0IGN1cnJlbnRCeXRlID0gdGhpcy5nZXRDdXJyZW50Qnl0ZSgpO1xuXHRcdGxldCBieXRlQ291bnQgPSAxO1xuXG5cdFx0d2hpbGUgKGN1cnJlbnRCeXRlID49IDEyOCkge1xuXHRcdFx0Y3VycmVudEJ5dGUgPSB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgYnl0ZUNvdW50XTtcblx0XHRcdGJ5dGVDb3VudCsrO1xuXHRcdH1cblxuXHRcdHJldHVybiBieXRlQ291bnQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGRlbHRhIHZhbHVlIGF0IGN1cnJlbnQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0RGVsdGEoKSB7XG5cdFx0cmV0dXJuIFV0aWxzLnJlYWRWYXJJbnQodGhpcy5kYXRhLnN1YmFycmF5KHRoaXMucG9pbnRlciwgdGhpcy5wb2ludGVyICsgdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpKSk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBldmVudCB3aXRoaW4gYSBnaXZlbiB0cmFjayBzdGFydGluZyBhdCBzcGVjaWZpZWQgaW5kZXhcblx0ICogQHBhcmFtIHtudW1iZXJ9IGN1cnJlbnRUaWNrXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZHJ5UnVuIC0gSWYgdHJ1ZSBldmVudHMgd2lsbCBiZSBwYXJzZWQgYW5kIHJldHVybmVkIHJlZ2FyZGxlc3Mgb2YgdGltZS5cblx0ICovXG5cdGhhbmRsZUV2ZW50KGN1cnJlbnRUaWNrLCBkcnlSdW4pIHtcblx0XHRkcnlSdW4gPSBkcnlSdW4gfHwgZmFsc2U7XG5cblx0XHRpZiAoZHJ5UnVuKSB7XG5cdFx0XHRjb25zdCBlbGFwc2VkVGlja3MgPSBjdXJyZW50VGljayAtIHRoaXMubGFzdFRpY2s7XG5cdFx0XHRjb25zdCBkZWx0YSA9IHRoaXMuZ2V0RGVsdGEoKTtcblx0XHRcdGNvbnN0IGV2ZW50UmVhZHkgPSBlbGFwc2VkVGlja3MgPj0gZGVsdGE7XG5cblx0XHRcdGlmICh0aGlzLnBvaW50ZXIgPCB0aGlzLmRhdGEubGVuZ3RoICYmIChkcnlSdW4gfHwgZXZlbnRSZWFkeSkpIHtcblx0XHRcdFx0Y29uc3QgZXZlbnQgPSB0aGlzLnBhcnNlRXZlbnQoKTtcblx0XHRcdFx0aWYgKHRoaXMuZW5hYmxlZClcblx0XHRcdFx0XHRyZXR1cm4gZXZlbnQ7XG5cdFx0XHRcdC8vIFJlY3Vyc2l2ZWx5IGNhbGwgdGhpcyBmdW5jdGlvbiBmb3IgZWFjaCBldmVudCBhaGVhZCB0aGF0IGhhcyAwIGRlbHRhIHRpbWU/XG5cdFx0XHR9XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gTGV0J3MgYWN0dWFsbHkgcGxheSB0aGUgTUlESSBmcm9tIHRoZSBnZW5lcmF0ZWQgSlNPTiBldmVudHMgY3JlYXRlZCBieSB0aGUgZHJ5IHJ1bi5cblx0XHRcdGlmICh0aGlzLmV2ZW50c1t0aGlzLmV2ZW50SW5kZXhdICYmIHRoaXMuZXZlbnRzW3RoaXMuZXZlbnRJbmRleF0udGljayA8PSBjdXJyZW50VGljaykge1xuXHRcdFx0XHR0aGlzLmV2ZW50SW5kZXgrKztcblx0XHRcdFx0aWYgKHRoaXMuZW5hYmxlZClcblx0XHRcdFx0XHRyZXR1cm4gdGhpcy5ldmVudHNbdGhpcy5ldmVudEluZGV4IC0gMV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHN0cmluZyBkYXRhIGZyb20gZXZlbnQuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBldmVudFN0YXJ0SW5kZXhcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpIHtcblx0XHQvL2NvbnN0IGN1cnJlbnRCeXRlID0gdGhpcy5wb2ludGVyO1xuXHRcdGNvbnN0IGJ5dGVDb3VudCA9IDE7XG5cdFx0Y29uc3QgbGVuZ3RoID0gVXRpbHMucmVhZFZhckludCh0aGlzLmRhdGEuc3ViYXJyYXkoZXZlbnRTdGFydEluZGV4ICsgMiwgZXZlbnRTdGFydEluZGV4ICsgMiArIGJ5dGVDb3VudCkpO1xuXHRcdC8vY29uc3Qgc3RyaW5nTGVuZ3RoID0gbGVuZ3RoO1xuXG5cdFx0cmV0dXJuIFV0aWxzLmJ5dGVzVG9MZXR0ZXJzKHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyAyLCBldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyBsZW5ndGggKyAyKSk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIGV2ZW50IGludG8gSlNPTiBhbmQgYWR2YW5jZXMgcG9pbnRlciBmb3IgdGhlIHRyYWNrXG5cdCAqIEByZXR1cm4ge29iamVjdH1cblx0ICovXG5cdHBhcnNlRXZlbnQoKSB7XG5cdFx0Y29uc3QgZXZlbnRTdGFydEluZGV4ID0gdGhpcy5wb2ludGVyICsgdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpO1xuXHRcdGNvbnN0IGV2ZW50SnNvbiA9IHt9O1xuXHRcdGNvbnN0IGRlbHRhQnl0ZUNvdW50ID0gdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpO1xuXHRcdGV2ZW50SnNvbi50cmFjayA9IHRoaXMuaW5kZXggKyAxO1xuXHRcdGV2ZW50SnNvbi5kZWx0YSA9IHRoaXMuZ2V0RGVsdGEoKTtcblx0XHR0aGlzLmxhc3RUaWNrID0gdGhpcy5sYXN0VGljayArIGV2ZW50SnNvbi5kZWx0YTtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSArPSBldmVudEpzb24uZGVsdGE7XG5cdFx0ZXZlbnRKc29uLnRpY2sgPSB0aGlzLnJ1bm5pbmdEZWx0YTtcblx0XHRldmVudEpzb24uYnl0ZUluZGV4ID0gdGhpcy5wb2ludGVyO1xuXG5cdFx0Ly9ldmVudEpzb24ucmF3ID0gZXZlbnQ7XG5cdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdID09IDB4ZmYpIHtcblx0XHRcdC8vIE1ldGEgRXZlbnRcblxuXHRcdFx0Ly8gSWYgdGhpcyBpcyBhIG1ldGEgZXZlbnQgd2Ugc2hvdWxkIGVtaXQgdGhlIGRhdGEgYW5kIGltbWVkaWF0ZWx5IG1vdmUgdG8gdGhlIG5leHQgZXZlbnRcblx0XHRcdC8vIG90aGVyd2lzZSBpZiB3ZSBsZXQgaXQgcnVuIHRocm91Z2ggdGhlIG5leHQgY3ljbGUgYSBzbGlnaHQgZGVsYXkgd2lsbCBhY2N1bXVsYXRlIGlmIG11bHRpcGxlIHRyYWNrc1xuXHRcdFx0Ly8gYXJlIGJlaW5nIHBsYXllZCBzaW11bHRhbmVvdXNseVxuXG5cdFx0XHRzd2l0Y2ggKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXSkge1xuXHRcdFx0XHRjYXNlIDB4MDA6IC8vIFNlcXVlbmNlIE51bWJlclxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1NlcXVlbmNlIE51bWJlcic7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgwMTogLy8gVGV4dCBFdmVudFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1RleHQgRXZlbnQnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDAyOiAvLyBDb3B5cmlnaHQgTm90aWNlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnQ29weXJpZ2h0IE5vdGljZSc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgwMzogLy8gU2VxdWVuY2UvVHJhY2sgTmFtZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1NlcXVlbmNlL1RyYWNrIE5hbWUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA0OiAvLyBJbnN0cnVtZW50IE5hbWVcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdJbnN0cnVtZW50IE5hbWUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA1OiAvLyBMeXJpY1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0x5cmljJztcblx0XHRcdFx0XHRldmVudEpzb24uc3RyaW5nID0gdGhpcy5nZXRTdHJpbmdEYXRhKGV2ZW50U3RhcnRJbmRleCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgwNjogLy8gTWFya2VyXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTWFya2VyJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA3OiAvLyBDdWUgUG9pbnRcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdDdWUgUG9pbnQnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA5OiAvLyBEZXZpY2UgTmFtZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0RldmljZSBOYW1lJztcblx0XHRcdFx0XHRldmVudEpzb24uc3RyaW5nID0gdGhpcy5nZXRTdHJpbmdEYXRhKGV2ZW50U3RhcnRJbmRleCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgyMDogLy8gTUlESSBDaGFubmVsIFByZWZpeFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ01JREkgQ2hhbm5lbCBQcmVmaXgnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MjE6IC8vIE1JREkgUG9ydFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ01JREkgUG9ydCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmRhdGEgPSBVdGlscy5ieXRlc1RvTnVtYmVyKFt0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgM11dKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDJGOiAvLyBFbmQgb2YgVHJhY2tcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdFbmQgb2YgVHJhY2snO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4NTE6IC8vIFNldCBUZW1wb1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1NldCBUZW1wbyc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmRhdGEgPSBNYXRoLnJvdW5kKDYwMDAwMDAwIC8gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmRhdGEuc3ViYXJyYXkoZXZlbnRTdGFydEluZGV4ICsgMywgZXZlbnRTdGFydEluZGV4ICsgNikpKTtcblx0XHRcdFx0XHR0aGlzLnRlbXBvID0gZXZlbnRKc29uLmRhdGE7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg1NDogLy8gU01UUEUgT2Zmc2V0XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU01UUEUgT2Zmc2V0Jztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDU4OiAvLyBUaW1lIFNpZ25hdHVyZVxuXHRcdFx0XHRcdC8vIEZGIDU4IDA0IG5uIGRkIGNjIGJiXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVGltZSBTaWduYXR1cmUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5kYXRhID0gdGhpcy5kYXRhLnN1YmFycmF5KGV2ZW50U3RhcnRJbmRleCArIDMsIGV2ZW50U3RhcnRJbmRleCArIDcpO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi50aW1lU2lnbmF0dXJlID0gXCJcIiArIGV2ZW50SnNvbi5kYXRhWzBdICsgXCIvXCIgKyBNYXRoLnBvdygyLCBldmVudEpzb24uZGF0YVsxXSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg1OTogLy8gS2V5IFNpZ25hdHVyZVxuXHRcdFx0XHRcdC8vIEZGIDU5IDAyIHNmIG1pXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnS2V5IFNpZ25hdHVyZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmRhdGEgPSB0aGlzLmRhdGEuc3ViYXJyYXkoZXZlbnRTdGFydEluZGV4ICsgMywgZXZlbnRTdGFydEluZGV4ICsgNSk7XG5cblx0XHRcdFx0XHRpZiAoZXZlbnRKc29uLmRhdGFbMF0gPj0gMCkge1xuXHRcdFx0XHRcdFx0ZXZlbnRKc29uLmtleVNpZ25hdHVyZSA9IENvbnN0YW50cy5DSVJDTEVfT0ZfRklGVEhTW2V2ZW50SnNvbi5kYXRhWzBdXTtcblxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZXZlbnRKc29uLmRhdGFbMF0gPCAwKSB7XG5cdFx0XHRcdFx0XHRldmVudEpzb24ua2V5U2lnbmF0dXJlID0gQ29uc3RhbnRzLkNJUkNMRV9PRl9GT1VSVEhTW01hdGguYWJzKGV2ZW50SnNvbi5kYXRhWzBdKV07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKGV2ZW50SnNvbi5kYXRhWzFdID09IDApIHtcblx0XHRcdFx0XHRcdGV2ZW50SnNvbi5rZXlTaWduYXR1cmUgKz0gJyBNYWpvcic7XG5cblx0XHRcdFx0XHR9IGVsc2UgaWYgKGV2ZW50SnNvbi5kYXRhWzFdID09IDEpIHtcblx0XHRcdFx0XHRcdGV2ZW50SnNvbi5rZXlTaWduYXR1cmUgKz0gJyBNaW5vcic7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg3RjogLy8gU2VxdWVuY2VyLVNwZWNpZmljIE1ldGEtZXZlbnRcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdTZXF1ZW5jZXItU3BlY2lmaWMgTWV0YS1ldmVudCc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSBgVW5rbm93bjogJHt0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV0udG9TdHJpbmcoMTYpfWA7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGxlbmd0aCA9IHRoaXMuZGF0YVt0aGlzLnBvaW50ZXIgKyBkZWx0YUJ5dGVDb3VudCArIDJdO1xuXHRcdFx0Ly8gU29tZSBtZXRhIGV2ZW50cyB3aWxsIGhhdmUgdmx2IHRoYXQgbmVlZHMgdG8gYmUgaGFuZGxlZFxuXG5cdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzICsgbGVuZ3RoO1xuXG5cdFx0fSBlbHNlIGlmICh0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XSA9PSAweGYwKSB7XG5cdFx0XHQvLyBTeXNleFxuXHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU3lzZXgnO1xuXHRcdFx0Y29uc3QgbGVuZ3RoID0gdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIGRlbHRhQnl0ZUNvdW50ICsgMV07XG5cdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAyICsgbGVuZ3RoO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFZvaWNlIGV2ZW50XG5cdFx0XHRpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPCAweDgwKSB7XG5cdFx0XHRcdC8vIFJ1bm5pbmcgc3RhdHVzXG5cdFx0XHRcdGV2ZW50SnNvbi5ydW5uaW5nID0gdHJ1ZTtcblx0XHRcdFx0ZXZlbnRKc29uLm5vdGVOdW1iZXIgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XTtcblx0XHRcdFx0ZXZlbnRKc29uLm5vdGVOYW1lID0gQ29uc3RhbnRzLk5PVEVTW3RoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdXTtcblx0XHRcdFx0ZXZlbnRKc29uLnZlbG9jaXR5ID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXG5cdFx0XHRcdGlmICh0aGlzLmxhc3RTdGF0dXMgPD0gMHg4Zikge1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ05vdGUgb2ZmJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4ODAgKyAxO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5sYXN0U3RhdHVzIDw9IDB4OWYpIHtcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9uJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4OTAgKyAxO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMjtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5sYXN0U3RhdHVzID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF07XG5cblx0XHRcdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4OGYpIHtcblx0XHRcdFx0XHQvLyBOb3RlIG9mZlxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ05vdGUgb2ZmJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4ODAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTnVtYmVyID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTmFtZSA9IENvbnN0YW50cy5OT1RFU1t0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV1dO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52ZWxvY2l0eSA9IE1hdGgucm91bmQodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDJdIC8gMTI3ICogMTAwKTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHg5Zikge1xuXHRcdFx0XHRcdC8vIE5vdGUgb25cblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9uJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4OTAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTnVtYmVyID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlTmFtZSA9IENvbnN0YW50cy5OT1RFU1t0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV1dO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52ZWxvY2l0eSA9IE1hdGgucm91bmQodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDJdIC8gMTI3ICogMTAwKTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhhZikge1xuXHRcdFx0XHRcdC8vIFBvbHlwaG9uaWMgS2V5IFByZXNzdXJlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnUG9seXBob25pYyBLZXkgUHJlc3N1cmUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhhMCArIDE7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5vdGUgPSBDb25zdGFudHMuTk9URVNbdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdXTtcblx0XHRcdFx0XHRldmVudEpzb24ucHJlc3N1cmUgPSBldmVudFsyXTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhiZikge1xuXHRcdFx0XHRcdC8vIENvbnRyb2xsZXIgQ2hhbmdlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnQ29udHJvbGxlciBDaGFuZ2UnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhiMCArIDE7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm51bWJlciA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHRldmVudEpzb24udmFsdWUgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMl07XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4Y2YpIHtcblx0XHRcdFx0XHQvLyBQcm9ncmFtIENoYW5nZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1Byb2dyYW0gQ2hhbmdlJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4YzAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi52YWx1ZSA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAyO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF0gPD0gMHhkZikge1xuXHRcdFx0XHRcdC8vIENoYW5uZWwgS2V5IFByZXNzdXJlXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnQ2hhbm5lbCBLZXkgUHJlc3N1cmUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhkMCArIDE7XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMjtcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4ZWYpIHtcblx0XHRcdFx0XHQvLyBQaXRjaCBCZW5kXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnUGl0Y2ggQmVuZCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweGUwICsgMTtcblx0XHRcdFx0XHR0aGlzLnBvaW50ZXIgKz0gZGVsdGFCeXRlQ291bnQgKyAzO1xuXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSBgVW5rbm93bi4gIFBvaW50ZXI6ICR7dGhpcy5wb2ludGVyLnRvU3RyaW5nKCl9ICR7ZXZlbnRTdGFydEluZGV4LnRvU3RyaW5nKCl9ICR7dGhpcy5kYXRhLmxlbmd0aH1gO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5kZWx0YSArPSBldmVudEpzb24uZGVsdGE7XG5cdFx0dGhpcy5ldmVudHMucHVzaChldmVudEpzb24pO1xuXG5cdFx0cmV0dXJuIGV2ZW50SnNvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgcG9pbnRlciBoYXMgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSB0cmFjay5cblx0ICogQHBhcmFtIHtib29sZWFufVxuXHQgKi9cblx0ZW5kT2ZUcmFjaygpIHtcblx0XHRpZiAodGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDFdID09IDB4ZmYgJiYgdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDJdID09IDB4MmYgJiYgdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDNdID09IDB4MDApXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHsgVHJhY2sgfVxuIiwiLyoqXG4gKiBDb250YWlucyBtaXNjIHN0YXRpYyB1dGlsaXR5IG1ldGhvZHMuXG4gKi9cbmNsYXNzIFV0aWxzIHtcblxuXHQvKipcblx0ICogQ29udmVydHMgYSBzaW5nbGUgYnl0ZSB0byBhIGhleCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBieXRlXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBieXRlVG9IZXgoYnl0ZSkge1xuXHRcdC8vIEVuc3VyZSBoZXggc3RyaW5nIGFsd2F5cyBoYXMgdHdvIGNoYXJzXG5cdFx0cmV0dXJuIGAwJHtieXRlLnRvU3RyaW5nKDE2KX1gLnNsaWNlKC0yKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBieXRlcyB0byBhIGhleCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgYnl0ZXNUb0hleChieXRlQXJyYXkpIHtcblx0XHRjb25zdCBoZXggPSBbXTtcblx0XHRieXRlQXJyYXkuZm9yRWFjaChieXRlID0+IGhleC5wdXNoKFV0aWxzLmJ5dGVUb0hleChieXRlKSkpO1xuXHRcdHJldHVybiBoZXguam9pbignJyk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBoZXggc3RyaW5nIHRvIGEgbnVtYmVyLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gaGV4U3RyaW5nXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdHN0YXRpYyBoZXhUb051bWJlcihoZXhTdHJpbmcpIHtcblx0XHRyZXR1cm4gcGFyc2VJbnQoaGV4U3RyaW5nLCAxNik7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYW4gYXJyYXkgb2YgYnl0ZXMgdG8gYSBudW1iZXIuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRzdGF0aWMgYnl0ZXNUb051bWJlcihieXRlQXJyYXkpIHtcblx0XHRyZXR1cm4gVXRpbHMuaGV4VG9OdW1iZXIoVXRpbHMuYnl0ZXNUb0hleChieXRlQXJyYXkpKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBieXRlcyB0byBsZXR0ZXJzLlxuXHQgKiBAcGFyYW0ge2FycmF5fSBieXRlQXJyYXlcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIGJ5dGVzVG9MZXR0ZXJzKGJ5dGVBcnJheSkge1xuXHRcdGNvbnN0IGxldHRlcnMgPSBbXTtcblx0XHRieXRlQXJyYXkuZm9yRWFjaChieXRlID0+IGxldHRlcnMucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGUpKSk7XG5cdFx0cmV0dXJuIGxldHRlcnMuam9pbignJyk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBkZWNpbWFsIHRvIGl0J3MgYmluYXJ5IHJlcHJlc2VudGF0aW9uLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gZGVjXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBkZWNUb0JpbmFyeShkZWMpIHtcblx0XHRyZXR1cm4gKGRlYyA+Pj4gMCkudG9TdHJpbmcoMik7XG5cdH1cblxuXHQvKipcblx0ICogUmVhZHMgYSB2YXJpYWJsZSBsZW5ndGggdmFsdWUuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRzdGF0aWMgcmVhZFZhckludChieXRlQXJyYXkpIHtcblx0XHRsZXQgcmVzdWx0ID0gMDtcblx0XHRieXRlQXJyYXkuZm9yRWFjaChudW1iZXIgPT4ge1xuXHRcdFx0dmFyIGIgPSBudW1iZXI7XG5cdFx0XHRpZiAoYiAmIDB4ODApIHtcblx0XHRcdFx0cmVzdWx0ICs9IChiICYgMHg3Zik7XG5cdFx0XHRcdHJlc3VsdCA8PD0gNztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8qIGIgaXMgdGhlIGxhc3QgYnl0ZSAqL1xuXHRcdFx0XHRyZXN1bHQgKz0gYjtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHQvKipcblx0ICogRGVjb2RlcyBiYXNlLTY0IGVuY29kZWQgc3RyaW5nXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0LyogT25seSBmb3IgTm9kZUpTIVxuXHRzdGF0aWMgYXRvYihzdHJpbmcpIHtcblx0XHRpZiAodHlwZW9mIGF0b2IgPT09ICdmdW5jdGlvbicpIHJldHVybiBhdG9iKHN0cmluZyk7XG5cdFx0cmV0dXJuIG5ldyBCdWZmZXIoc3RyaW5nLCAnYmFzZTY0JykudG9TdHJpbmcoJ2JpbmFyeScpO1xuXHR9XG5cdCovXG59XG5cbm1vZHVsZS5leHBvcnRzID0geyBVdGlscyB9Il19 + + +/***/ }), + +/***/ "./node_modules/base64-js/index.js": +/*!*****************************************!*\ + !*** ./node_modules/base64-js/index.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + + +/***/ }), + +/***/ "./node_modules/buffer/index.js": +/*!**************************************!*\ + !*** ./node_modules/buffer/index.js ***! + \**************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + + + +var base64 = __webpack_require__(/*! base64-js */ "./node_modules/base64-js/index.js") +var ieee754 = __webpack_require__(/*! ieee754 */ "./node_modules/ieee754/index.js") +var isArray = __webpack_require__(/*! isarray */ "./node_modules/isarray/index.js") + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + +/* + * Export kMaxLength after typed array support is determined. + */ +exports.kMaxLength = kMaxLength() + +function typedArraySupport () { + try { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +} + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +function createBuffer (that, length) { + if (kMaxLength() < length) { + throw new RangeError('Invalid typed array length') + } + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = new Uint8Array(length) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + if (that === null) { + that = new Buffer(length) + } + that.length = length + } + + return that +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { + return new Buffer(arg, encodingOrOffset, length) + } + + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(this, arg) + } + return from(this, arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +// TODO: Legacy, not needed anymore. Remove in next major version. +Buffer._augment = function (arr) { + arr.__proto__ = Buffer.prototype + return arr +} + +function from (that, value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + return fromArrayBuffer(that, value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(that, value, encodingOrOffset) + } + + return fromObject(that, value) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(null, value, encodingOrOffset, length) +} + +if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array + if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true + }) + } +} + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } +} + +function alloc (that, size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(that, size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(that, size).fill(fill, encoding) + : createBuffer(that, size).fill(fill) + } + return createBuffer(that, size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(null, size, fill, encoding) +} + +function allocUnsafe (that, size) { + assertSize(size) + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < size; ++i) { + that[i] = 0 + } + } + return that +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(null, size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(null, size) +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0 + that = createBuffer(that, length) + + var actual = that.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + that = that.slice(0, actual) + } + + return that +} + +function fromArrayLike (that, array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + that = createBuffer(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array, byteOffset, length) { + array.byteLength // this throws if `array` is not a valid ArrayBuffer + + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + if (byteOffset === undefined && length === undefined) { + array = new Uint8Array(array) + } else if (length === undefined) { + array = new Uint8Array(array, byteOffset) + } else { + array = new Uint8Array(array, byteOffset, length) + } + + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = array + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that = fromArrayLike(that, array) + } + return that +} + +function fromObject (that, obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + that = createBuffer(that, len) + + if (that.length === 0) { + return that + } + + obj.copy(that, 0, 0, len) + return that + } + + if (obj) { + if ((typeof ArrayBuffer !== 'undefined' && + obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (typeof obj.length !== 'number' || isnan(obj.length)) { + return createBuffer(that, 0) + } + return fromArrayLike(that, obj) + } + + if (obj.type === 'Buffer' && isArray(obj.data)) { + return fromArrayLike(that, obj.data) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') +} + +function checked (length) { + // Note: cannot use `length < kMaxLength()` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && + (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string + } + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect +// Buffer instances. +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!Buffer.isBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (isNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (Buffer.TYPED_ARRAY_SUPPORT && + typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = this.subarray(start, end) + newBuf.__proto__ = Buffer.prototype + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; ++i) { + newBuf[i] = this[i + start] + } + } + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = (value & 0xff) + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if (code < 256) { + val = code + } + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : utf8ToBytes(new Buffer(val, encoding).toString()) + var len = bytes.length + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +function isnan (val) { + return val !== val // eslint-disable-line no-self-compare +} + +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"))) + +/***/ }), + +/***/ "./node_modules/clipboard-js/clipboard.js": +/*!************************************************!*\ + !*** ./node_modules/clipboard-js/clipboard.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(setImmediate) {// Import support https://stackoverflow.com/questions/13673346/supporting-both-commonjs-and-amd +(function(name, definition) { + if (true) { module.exports = definition(); } + else {} +}("clipboard", function() { + if (typeof document === 'undefined' || !document.addEventListener) { + return null; + } + + var clipboard = {}; + + clipboard.copy = (function() { + var _intercept = false; + var _data = null; // Map from data type (e.g. "text/html") to value. + var _bogusSelection = false; + + function cleanup() { + _intercept = false; + _data = null; + if (_bogusSelection) { + window.getSelection().removeAllRanges(); + } + _bogusSelection = false; + } + + document.addEventListener("copy", function(e) { + if (_intercept) { + for (var key in _data) { + e.clipboardData.setData(key, _data[key]); + } + e.preventDefault(); + } + }); + + // Workaround for Safari: https://bugs.webkit.org/show_bug.cgi?id=156529 + function bogusSelect() { + var sel = document.getSelection(); + // If "nothing" is selected... + if (!document.queryCommandEnabled("copy") && sel.isCollapsed) { + // ... temporarily select the entire body. + // + // We select the entire body because: + // - it's guaranteed to exist, + // - it works (unlike, say, document.head, or phantom element that is + // not inserted into the DOM), + // - it doesn't seem to flicker (due to the synchronous copy event), and + // - it avoids modifying the DOM (can trigger mutation observers). + // + // Because we can't do proper feature detection (we already checked + // document.queryCommandEnabled("copy") , which actually gives a false + // negative for Blink when nothing is selected) and UA sniffing is not + // reliable (a lot of UA strings contain "Safari"), this will also + // happen for some browsers other than Safari. :-() + var range = document.createRange(); + range.selectNodeContents(document.body); + sel.removeAllRanges(); + sel.addRange(range); + _bogusSelection = true; + } + }; + + return function(data) { + return new Promise(function(resolve, reject) { + _intercept = true; + if (typeof data === "string") { + _data = {"text/plain": data}; + } else if (data instanceof Node) { + _data = {"text/html": new XMLSerializer().serializeToString(data)}; + } else if (data instanceof Object){ + _data = data; + } else { + reject("Invalid data type. Must be string, DOM node, or an object mapping MIME types to strings.") + } + + function triggerCopy(tryBogusSelect) { + try { + if (document.execCommand("copy")) { + // document.execCommand is synchronous: http://www.w3.org/TR/2015/WD-clipboard-apis-20150421/#integration-with-rich-text-editing-apis + // So we can call resolve() back here. + cleanup(); + resolve(); + } + else { + if (!tryBogusSelect) { + bogusSelect(); + triggerCopy(true); + } else { + cleanup(); + throw new Error("Unable to copy. Perhaps it's not available in your browser?"); + } + } + } catch (e) { + cleanup(); + reject(e); + } + } + triggerCopy(false); + + }); + }; + })(); + + clipboard.paste = (function() { + var _intercept = false; + var _resolve; + var _dataType; + + document.addEventListener("paste", function(e) { + if (_intercept) { + _intercept = false; + e.preventDefault(); + var resolve = _resolve; + _resolve = null; + resolve(e.clipboardData.getData(_dataType)); + } + }); + + return function(dataType) { + return new Promise(function(resolve, reject) { + _intercept = true; + _resolve = resolve; + _dataType = dataType || "text/plain"; + try { + if (!document.execCommand("paste")) { + _intercept = false; + reject(new Error("Unable to paste. Pasting only works in Internet Explorer at the moment.")); + } + } catch (e) { + _intercept = false; + reject(new Error(e)); + } + }); + }; + })(); + + // Handle IE behaviour. + if (typeof ClipboardEvent === "undefined" && + typeof window.clipboardData !== "undefined" && + typeof window.clipboardData.setData !== "undefined") { + + /*! promise-polyfill 2.0.1 */ + (function(a){function b(a,b){return function(){a.apply(b,arguments)}}function c(a){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof a)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],i(a,b(e,this),b(f,this))}function d(a){var b=this;return null===this._state?void this._deferreds.push(a):void j(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(e){return void a.reject(e)}a.resolve(d)})}function e(a){try{if(a===this)throw new TypeError("A promise cannot be resolved with itself.");if(a&&("object"==typeof a||"function"==typeof a)){var c=a.then;if("function"==typeof c)return void i(b(c,a),b(e,this),b(f,this))}this._state=!0,this._value=a,g.call(this)}catch(d){f.call(this,d)}}function f(a){this._state=!1,this._value=a,g.call(this)}function g(){for(var a=0,b=this._deferreds.length;b>a;a++)d.call(this,this._deferreds[a]);this._deferreds=null}function h(a,b,c,d){this.onFulfilled="function"==typeof a?a:null,this.onRejected="function"==typeof b?b:null,this.resolve=c,this.reject=d}function i(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(e){if(d)return;d=!0,c(e)}}var j=c.immediateFn||"function"==typeof setImmediate&&setImmediate||function(a){setTimeout(a,1)},k=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};c.prototype["catch"]=function(a){return this.then(null,a)},c.prototype.then=function(a,b){var e=this;return new c(function(c,f){d.call(e,new h(a,b,c,f))})},c.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&k(arguments[0])?arguments[0]:arguments);return new c(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(i){c(i)}}if(0===a.length)return b([]);for(var e=a.length,f=0;fd;d++)a[d].then(b,c)})}, true&&module.exports?module.exports=c:a.Promise||(a.Promise=c)})(this); + + clipboard.copy = function(data) { + return new Promise(function(resolve, reject) { + // IE supports string and URL types: https://msdn.microsoft.com/en-us/library/ms536744(v=vs.85).aspx + // We only support the string type for now. + if (typeof data !== "string" && !("text/plain" in data)) { + throw new Error("You must provide a text/plain type."); + } + + var strData = (typeof data === "string" ? data : data["text/plain"]); + var copySucceeded = window.clipboardData.setData("Text", strData); + if (copySucceeded) { + resolve(); + } else { + reject(new Error("Copying was rejected.")); + } + }); + }; + + clipboard.paste = function() { + return new Promise(function(resolve, reject) { + var strData = window.clipboardData.getData("Text"); + if (strData) { + resolve(strData); + } else { + // The user rejected the paste request. + reject(new Error("Pasting was rejected.")); + } + }); + }; + } + + return clipboard; +})); + +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../timers-browserify/main.js */ "./node_modules/timers-browserify/main.js").setImmediate)) + +/***/ }), + +/***/ "./node_modules/core-util-is/lib/util.js": +/*!***********************************************!*\ + !*** ./node_modules/core-util-is/lib/util.js ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(Buffer) {// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../buffer/index.js */ "./node_modules/buffer/index.js").Buffer)) + +/***/ }), + +/***/ "./node_modules/events/events.js": +/*!***************************************!*\ + !*** ./node_modules/events/events.js ***! + \***************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var R = typeof Reflect === 'object' ? Reflect : null +var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + +var ReflectOwnKeys +if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys +} else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; +} else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; +} + +function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); +} + +var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; +} + +function EventEmitter() { + EventEmitter.init.call(this); +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._eventsCount = 0; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +function checkListener(listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } +} + +Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } +}); + +EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +}; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; +}; + +function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); +}; + +EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + checkListener(listener); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + checkListener(listener); + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; +}; + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + + +/***/ }), + +/***/ "./node_modules/i18next/dist/cjs/i18next.js": +/*!**************************************************!*\ + !*** ./node_modules/i18next/dist/cjs/i18next.js ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var _typeof = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js")); +var _objectSpread = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/objectSpread */ "./node_modules/@babel/runtime/helpers/objectSpread.js")); +var _classCallCheck = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js")); +var _createClass = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js")); +var _possibleConstructorReturn = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/possibleConstructorReturn */ "./node_modules/@babel/runtime/helpers/possibleConstructorReturn.js")); +var _getPrototypeOf = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/getPrototypeOf */ "./node_modules/@babel/runtime/helpers/getPrototypeOf.js")); +var _assertThisInitialized = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/assertThisInitialized */ "./node_modules/@babel/runtime/helpers/assertThisInitialized.js")); +var _inherits = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/inherits */ "./node_modules/@babel/runtime/helpers/inherits.js")); +var _toConsumableArray = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/toConsumableArray */ "./node_modules/@babel/runtime/helpers/toConsumableArray.js")); +var _slicedToArray = _interopDefault(__webpack_require__(/*! @babel/runtime/helpers/slicedToArray */ "./node_modules/@babel/runtime/helpers/slicedToArray.js")); + +var consoleLogger = { + type: 'logger', + log: function log(args) { + this.output('log', args); + }, + warn: function warn(args) { + this.output('warn', args); + }, + error: function error(args) { + this.output('error', args); + }, + output: function output(type, args) { + var _console; + + /* eslint no-console: 0 */ + if (console && console[type]) (_console = console)[type].apply(_console, _toConsumableArray(args)); + } +}; + +var Logger = +/*#__PURE__*/ +function () { + function Logger(concreteLogger) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, Logger); + + this.init(concreteLogger, options); + } + + _createClass(Logger, [{ + key: "init", + value: function init(concreteLogger) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.prefix = options.prefix || 'i18next:'; + this.logger = concreteLogger || consoleLogger; + this.options = options; + this.debug = options.debug; + } + }, { + key: "setDebug", + value: function setDebug(bool) { + this.debug = bool; + } + }, { + key: "log", + value: function log() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return this.forward(args, 'log', '', true); + } + }, { + key: "warn", + value: function warn() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + return this.forward(args, 'warn', '', true); + } + }, { + key: "error", + value: function error() { + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } + + return this.forward(args, 'error', ''); + } + }, { + key: "deprecate", + value: function deprecate() { + for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + + return this.forward(args, 'warn', 'WARNING DEPRECATED: ', true); + } + }, { + key: "forward", + value: function forward(args, lvl, prefix, debugOnly) { + if (debugOnly && !this.debug) return null; + if (typeof args[0] === 'string') args[0] = "".concat(prefix).concat(this.prefix, " ").concat(args[0]); + return this.logger[lvl](args); + } + }, { + key: "create", + value: function create(moduleName) { + return new Logger(this.logger, _objectSpread({}, { + prefix: "".concat(this.prefix, ":").concat(moduleName, ":") + }, this.options)); + } + }]); + + return Logger; +}(); + +var baseLogger = new Logger(); + +var EventEmitter = +/*#__PURE__*/ +function () { + function EventEmitter() { + _classCallCheck(this, EventEmitter); + + this.observers = {}; + } + + _createClass(EventEmitter, [{ + key: "on", + value: function on(events, listener) { + var _this = this; + + events.split(' ').forEach(function (event) { + _this.observers[event] = _this.observers[event] || []; + + _this.observers[event].push(listener); + }); + return this; + } + }, { + key: "off", + value: function off(event, listener) { + if (!this.observers[event]) return; + + if (!listener) { + delete this.observers[event]; + return; + } + + this.observers[event] = this.observers[event].filter(function (l) { + return l !== listener; + }); + } + }, { + key: "emit", + value: function emit(event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + if (this.observers[event]) { + var cloned = [].concat(this.observers[event]); + cloned.forEach(function (observer) { + observer.apply(void 0, args); + }); + } + + if (this.observers['*']) { + var _cloned = [].concat(this.observers['*']); + + _cloned.forEach(function (observer) { + observer.apply(observer, [event].concat(args)); + }); + } + } + }]); + + return EventEmitter; +}(); + +// http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/ +function defer() { + var res; + var rej; + var promise = new Promise(function (resolve, reject) { + res = resolve; + rej = reject; + }); + promise.resolve = res; + promise.reject = rej; + return promise; +} +function makeString(object) { + if (object == null) return ''; + /* eslint prefer-template: 0 */ + + return '' + object; +} +function copy(a, s, t) { + a.forEach(function (m) { + if (s[m]) t[m] = s[m]; + }); +} + +function getLastOfPath(object, path, Empty) { + function cleanKey(key) { + return key && key.indexOf('###') > -1 ? key.replace(/###/g, '.') : key; + } + + function canNotTraverseDeeper() { + return !object || typeof object === 'string'; + } + + var stack = typeof path !== 'string' ? [].concat(path) : path.split('.'); + + while (stack.length > 1) { + if (canNotTraverseDeeper()) return {}; + var key = cleanKey(stack.shift()); + if (!object[key] && Empty) object[key] = new Empty(); + object = object[key]; + } + + if (canNotTraverseDeeper()) return {}; + return { + obj: object, + k: cleanKey(stack.shift()) + }; +} + +function setPath(object, path, newValue) { + var _getLastOfPath = getLastOfPath(object, path, Object), + obj = _getLastOfPath.obj, + k = _getLastOfPath.k; + + obj[k] = newValue; +} +function pushPath(object, path, newValue, concat) { + var _getLastOfPath2 = getLastOfPath(object, path, Object), + obj = _getLastOfPath2.obj, + k = _getLastOfPath2.k; + + obj[k] = obj[k] || []; + if (concat) obj[k] = obj[k].concat(newValue); + if (!concat) obj[k].push(newValue); +} +function getPath(object, path) { + var _getLastOfPath3 = getLastOfPath(object, path), + obj = _getLastOfPath3.obj, + k = _getLastOfPath3.k; + + if (!obj) return undefined; + return obj[k]; +} +function getPathWithDefaults(data, defaultData, key) { + var value = getPath(data, key); + + if (value !== undefined) { + return value; + } // Fallback to default values + + + return getPath(defaultData, key); +} +function deepExtend(target, source, overwrite) { + /* eslint no-restricted-syntax: 0 */ + for (var prop in source) { + if (prop in target) { + // If we reached a leaf string in target or source then replace with source or skip depending on the 'overwrite' switch + if (typeof target[prop] === 'string' || target[prop] instanceof String || typeof source[prop] === 'string' || source[prop] instanceof String) { + if (overwrite) target[prop] = source[prop]; + } else { + deepExtend(target[prop], source[prop], overwrite); + } + } else { + target[prop] = source[prop]; + } + } + + return target; +} +function regexEscape(str) { + /* eslint no-useless-escape: 0 */ + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); +} +/* eslint-disable */ + +var _entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' +}; +/* eslint-enable */ + +function escape(data) { + if (typeof data === 'string') { + return data.replace(/[&<>"'\/]/g, function (s) { + return _entityMap[s]; + }); + } + + return data; +} + +var ResourceStore = +/*#__PURE__*/ +function (_EventEmitter) { + _inherits(ResourceStore, _EventEmitter); + + function ResourceStore(data) { + var _this; + + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + ns: ['translation'], + defaultNS: 'translation' + }; + + _classCallCheck(this, ResourceStore); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(ResourceStore).call(this)); + EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) + + _this.data = data || {}; + _this.options = options; + + if (_this.options.keySeparator === undefined) { + _this.options.keySeparator = '.'; + } + + return _this; + } + + _createClass(ResourceStore, [{ + key: "addNamespaces", + value: function addNamespaces(ns) { + if (this.options.ns.indexOf(ns) < 0) { + this.options.ns.push(ns); + } + } + }, { + key: "removeNamespaces", + value: function removeNamespaces(ns) { + var index = this.options.ns.indexOf(ns); + + if (index > -1) { + this.options.ns.splice(index, 1); + } + } + }, { + key: "getResource", + value: function getResource(lng, ns, key) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + var keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator; + var path = [lng, ns]; + if (key && typeof key !== 'string') path = path.concat(key); + if (key && typeof key === 'string') path = path.concat(keySeparator ? key.split(keySeparator) : key); + + if (lng.indexOf('.') > -1) { + path = lng.split('.'); + } + + return getPath(this.data, path); + } + }, { + key: "addResource", + value: function addResource(lng, ns, key, value) { + var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : { + silent: false + }; + var keySeparator = this.options.keySeparator; + if (keySeparator === undefined) keySeparator = '.'; + var path = [lng, ns]; + if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key); + + if (lng.indexOf('.') > -1) { + path = lng.split('.'); + value = ns; + ns = path[1]; + } + + this.addNamespaces(ns); + setPath(this.data, path, value); + if (!options.silent) this.emit('added', lng, ns, key, value); + } + }, { + key: "addResources", + value: function addResources(lng, ns, resources) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { + silent: false + }; + + /* eslint no-restricted-syntax: 0 */ + for (var m in resources) { + if (typeof resources[m] === 'string' || Object.prototype.toString.apply(resources[m]) === '[object Array]') this.addResource(lng, ns, m, resources[m], { + silent: true + }); + } + + if (!options.silent) this.emit('added', lng, ns, resources); + } + }, { + key: "addResourceBundle", + value: function addResourceBundle(lng, ns, resources, deep, overwrite) { + var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : { + silent: false + }; + var path = [lng, ns]; + + if (lng.indexOf('.') > -1) { + path = lng.split('.'); + deep = resources; + resources = ns; + ns = path[1]; + } + + this.addNamespaces(ns); + var pack = getPath(this.data, path) || {}; + + if (deep) { + deepExtend(pack, resources, overwrite); + } else { + pack = _objectSpread({}, pack, resources); + } + + setPath(this.data, path, pack); + if (!options.silent) this.emit('added', lng, ns, resources); + } + }, { + key: "removeResourceBundle", + value: function removeResourceBundle(lng, ns) { + if (this.hasResourceBundle(lng, ns)) { + delete this.data[lng][ns]; + } + + this.removeNamespaces(ns); + this.emit('removed', lng, ns); + } + }, { + key: "hasResourceBundle", + value: function hasResourceBundle(lng, ns) { + return this.getResource(lng, ns) !== undefined; + } + }, { + key: "getResourceBundle", + value: function getResourceBundle(lng, ns) { + if (!ns) ns = this.options.defaultNS; // COMPATIBILITY: remove extend in v2.1.0 + + if (this.options.compatibilityAPI === 'v1') return _objectSpread({}, {}, this.getResource(lng, ns)); + return this.getResource(lng, ns); + } + }, { + key: "getDataByLanguage", + value: function getDataByLanguage(lng) { + return this.data[lng]; + } + }, { + key: "toJSON", + value: function toJSON() { + return this.data; + } + }]); + + return ResourceStore; +}(EventEmitter); + +var postProcessor = { + processors: {}, + addPostProcessor: function addPostProcessor(module) { + this.processors[module.name] = module; + }, + handle: function handle(processors, value, key, options, translator) { + var _this = this; + + processors.forEach(function (processor) { + if (_this.processors[processor]) value = _this.processors[processor].process(value, key, options, translator); + }); + return value; + } +}; + +var checkedLoadedFor = {}; + +var Translator = +/*#__PURE__*/ +function (_EventEmitter) { + _inherits(Translator, _EventEmitter); + + function Translator(services) { + var _this; + + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, Translator); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Translator).call(this)); + EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) + + copy(['resourceStore', 'languageUtils', 'pluralResolver', 'interpolator', 'backendConnector', 'i18nFormat', 'utils'], services, _assertThisInitialized(_this)); + _this.options = options; + + if (_this.options.keySeparator === undefined) { + _this.options.keySeparator = '.'; + } + + _this.logger = baseLogger.create('translator'); + return _this; + } + + _createClass(Translator, [{ + key: "changeLanguage", + value: function changeLanguage(lng) { + if (lng) this.language = lng; + } + }, { + key: "exists", + value: function exists(key) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + interpolation: {} + }; + var resolved = this.resolve(key, options); + return resolved && resolved.res !== undefined; + } + }, { + key: "extractFromKey", + value: function extractFromKey(key, options) { + var nsSeparator = options.nsSeparator || this.options.nsSeparator; + if (nsSeparator === undefined) nsSeparator = ':'; + var keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator; + var namespaces = options.ns || this.options.defaultNS; + + if (nsSeparator && key.indexOf(nsSeparator) > -1) { + var parts = key.split(nsSeparator); + if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.indexOf(parts[0]) > -1) namespaces = parts.shift(); + key = parts.join(keySeparator); + } + + if (typeof namespaces === 'string') namespaces = [namespaces]; + return { + key: key, + namespaces: namespaces + }; + } + }, { + key: "translate", + value: function translate(keys, options) { + var _this2 = this; + + if (_typeof(options) !== 'object' && this.options.overloadTranslationOptionHandler) { + /* eslint prefer-rest-params: 0 */ + options = this.options.overloadTranslationOptionHandler(arguments); + } + + if (!options) options = {}; // non valid keys handling + + if (keys === undefined || keys === null + /* || keys === ''*/ + ) return ''; + if (!Array.isArray(keys)) keys = [String(keys)]; // separators + + var keySeparator = options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator; // get namespace(s) + + var _this$extractFromKey = this.extractFromKey(keys[keys.length - 1], options), + key = _this$extractFromKey.key, + namespaces = _this$extractFromKey.namespaces; + + var namespace = namespaces[namespaces.length - 1]; // return key on CIMode + + var lng = options.lng || this.language; + var appendNamespaceToCIMode = options.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode; + + if (lng && lng.toLowerCase() === 'cimode') { + if (appendNamespaceToCIMode) { + var nsSeparator = options.nsSeparator || this.options.nsSeparator; + return namespace + nsSeparator + key; + } + + return key; + } // resolve from store + + + var resolved = this.resolve(keys, options); + var res = resolved && resolved.res; + var resUsedKey = resolved && resolved.usedKey || key; + var resExactUsedKey = resolved && resolved.exactUsedKey || key; + var resType = Object.prototype.toString.apply(res); + var noObject = ['[object Number]', '[object Function]', '[object RegExp]']; + var joinArrays = options.joinArrays !== undefined ? options.joinArrays : this.options.joinArrays; // object + + var handleAsObjectInI18nFormat = !this.i18nFormat || this.i18nFormat.handleAsObject; + var handleAsObject = typeof res !== 'string' && typeof res !== 'boolean' && typeof res !== 'number'; + + if (handleAsObjectInI18nFormat && res && handleAsObject && noObject.indexOf(resType) < 0 && !(typeof joinArrays === 'string' && resType === '[object Array]')) { + if (!options.returnObjects && !this.options.returnObjects) { + this.logger.warn('accessing an object - but returnObjects options is not enabled!'); + return this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, res, options) : "key '".concat(key, " (").concat(this.language, ")' returned an object instead of string."); + } // if we got a separator we loop over children - else we just return object as is + // as having it set to false means no hierarchy so no lookup for nested values + + + if (keySeparator) { + var resTypeIsArray = resType === '[object Array]'; + var copy$$1 = resTypeIsArray ? [] : {}; // apply child translation on a copy + + /* eslint no-restricted-syntax: 0 */ + + var newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey; + + for (var m in res) { + if (Object.prototype.hasOwnProperty.call(res, m)) { + var deepKey = "".concat(newKeyToUse).concat(keySeparator).concat(m); + copy$$1[m] = this.translate(deepKey, _objectSpread({}, options, { + joinArrays: false, + ns: namespaces + })); + if (copy$$1[m] === deepKey) copy$$1[m] = res[m]; // if nothing found use orginal value as fallback + } + } + + res = copy$$1; + } + } else if (handleAsObjectInI18nFormat && typeof joinArrays === 'string' && resType === '[object Array]') { + // array special treatment + res = res.join(joinArrays); + if (res) res = this.extendTranslation(res, keys, options); + } else { + // string, empty or null + var usedDefault = false; + var usedKey = false; // fallback value + + if (!this.isValidLookup(res) && options.defaultValue !== undefined) { + usedDefault = true; + + if (options.count !== undefined) { + var suffix = this.pluralResolver.getSuffix(lng, options.count); + res = options["defaultValue".concat(suffix)]; + } + + if (!res) res = options.defaultValue; + } + + if (!this.isValidLookup(res)) { + usedKey = true; + res = key; + } // save missing + + + var updateMissing = options.defaultValue && options.defaultValue !== res && this.options.updateMissing; + + if (usedKey || usedDefault || updateMissing) { + this.logger.log(updateMissing ? 'updateKey' : 'missingKey', lng, namespace, key, updateMissing ? options.defaultValue : res); + var lngs = []; + var fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, options.lng || this.language); + + if (this.options.saveMissingTo === 'fallback' && fallbackLngs && fallbackLngs[0]) { + for (var i = 0; i < fallbackLngs.length; i++) { + lngs.push(fallbackLngs[i]); + } + } else if (this.options.saveMissingTo === 'all') { + lngs = this.languageUtils.toResolveHierarchy(options.lng || this.language); + } else { + lngs.push(options.lng || this.language); + } + + var send = function send(l, k) { + if (_this2.options.missingKeyHandler) { + _this2.options.missingKeyHandler(l, namespace, k, updateMissing ? options.defaultValue : res, updateMissing, options); + } else if (_this2.backendConnector && _this2.backendConnector.saveMissing) { + _this2.backendConnector.saveMissing(l, namespace, k, updateMissing ? options.defaultValue : res, updateMissing, options); + } + + _this2.emit('missingKey', l, namespace, k, res); + }; + + if (this.options.saveMissing) { + var needsPluralHandling = options.count !== undefined && typeof options.count !== 'string'; + + if (this.options.saveMissingPlurals && needsPluralHandling) { + lngs.forEach(function (l) { + var plurals = _this2.pluralResolver.getPluralFormsOfKey(l, key); + + plurals.forEach(function (p) { + return send([l], p); + }); + }); + } else { + send(lngs, key); + } + } + } // extend + + + res = this.extendTranslation(res, keys, options, resolved); // append namespace if still key + + if (usedKey && res === key && this.options.appendNamespaceToMissingKey) res = "".concat(namespace, ":").concat(key); // parseMissingKeyHandler + + if (usedKey && this.options.parseMissingKeyHandler) res = this.options.parseMissingKeyHandler(res); + } // return + + + return res; + } + }, { + key: "extendTranslation", + value: function extendTranslation(res, key, options, resolved) { + var _this3 = this; + + if (this.i18nFormat && this.i18nFormat.parse) { + res = this.i18nFormat.parse(res, options, resolved.usedLng, resolved.usedNS, resolved.usedKey, { + resolved: resolved + }); + } else if (!options.skipInterpolation) { + // i18next.parsing + if (options.interpolation) this.interpolator.init(_objectSpread({}, options, { + interpolation: _objectSpread({}, this.options.interpolation, options.interpolation) + })); // interpolate + + var data = options.replace && typeof options.replace !== 'string' ? options.replace : options; + if (this.options.interpolation.defaultVariables) data = _objectSpread({}, this.options.interpolation.defaultVariables, data); + res = this.interpolator.interpolate(res, data, options.lng || this.language, options); // nesting + + if (options.nest !== false) res = this.interpolator.nest(res, function () { + return _this3.translate.apply(_this3, arguments); + }, options); + if (options.interpolation) this.interpolator.reset(); + } // post process + + + var postProcess = options.postProcess || this.options.postProcess; + var postProcessorNames = typeof postProcess === 'string' ? [postProcess] : postProcess; + + if (res !== undefined && res !== null && postProcessorNames && postProcessorNames.length && options.applyPostProcessor !== false) { + res = postProcessor.handle(postProcessorNames, res, key, this.options && this.options.postProcessPassResolved ? _objectSpread({ + i18nResolved: resolved + }, options) : options, this); + } + + return res; + } + }, { + key: "resolve", + value: function resolve(keys) { + var _this4 = this; + + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var found; + var usedKey; // plain key + + var exactUsedKey; // key with context / plural + + var usedLng; + var usedNS; + if (typeof keys === 'string') keys = [keys]; // forEach possible key + + keys.forEach(function (k) { + if (_this4.isValidLookup(found)) return; + + var extracted = _this4.extractFromKey(k, options); + + var key = extracted.key; + usedKey = key; + var namespaces = extracted.namespaces; + if (_this4.options.fallbackNS) namespaces = namespaces.concat(_this4.options.fallbackNS); + var needsPluralHandling = options.count !== undefined && typeof options.count !== 'string'; + var needsContextHandling = options.context !== undefined && typeof options.context === 'string' && options.context !== ''; + var codes = options.lngs ? options.lngs : _this4.languageUtils.toResolveHierarchy(options.lng || _this4.language, options.fallbackLng); + namespaces.forEach(function (ns) { + if (_this4.isValidLookup(found)) return; + usedNS = ns; + + if (!checkedLoadedFor["".concat(codes[0], "-").concat(ns)] && _this4.utils && _this4.utils.hasLoadedNamespace && !_this4.utils.hasLoadedNamespace(usedNS)) { + checkedLoadedFor["".concat(codes[0], "-").concat(ns)] = true; + + _this4.logger.warn("key \"".concat(usedKey, "\" for namespace \"").concat(usedNS, "\" for languages \"").concat(codes.join(', '), "\" won't get resolved as namespace was not yet loaded"), 'This means something IS WRONG in your application setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!'); + } + + codes.forEach(function (code) { + if (_this4.isValidLookup(found)) return; + usedLng = code; + var finalKey = key; + var finalKeys = [finalKey]; + + if (_this4.i18nFormat && _this4.i18nFormat.addLookupKeys) { + _this4.i18nFormat.addLookupKeys(finalKeys, key, code, ns, options); + } else { + var pluralSuffix; + if (needsPluralHandling) pluralSuffix = _this4.pluralResolver.getSuffix(code, options.count); // fallback for plural if context not found + + if (needsPluralHandling && needsContextHandling) finalKeys.push(finalKey + pluralSuffix); // get key for context if needed + + if (needsContextHandling) finalKeys.push(finalKey += "".concat(_this4.options.contextSeparator).concat(options.context)); // get key for plural if needed + + if (needsPluralHandling) finalKeys.push(finalKey += pluralSuffix); + } // iterate over finalKeys starting with most specific pluralkey (-> contextkey only) -> singularkey only + + + var possibleKey; + /* eslint no-cond-assign: 0 */ + + while (possibleKey = finalKeys.pop()) { + if (!_this4.isValidLookup(found)) { + exactUsedKey = possibleKey; + found = _this4.getResource(code, ns, possibleKey, options); + } + } + }); + }); + }); + return { + res: found, + usedKey: usedKey, + exactUsedKey: exactUsedKey, + usedLng: usedLng, + usedNS: usedNS + }; + } + }, { + key: "isValidLookup", + value: function isValidLookup(res) { + return res !== undefined && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === ''); + } + }, { + key: "getResource", + value: function getResource(code, ns, key) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + if (this.i18nFormat && this.i18nFormat.getResource) return this.i18nFormat.getResource(code, ns, key, options); + return this.resourceStore.getResource(code, ns, key, options); + } + }]); + + return Translator; +}(EventEmitter); + +function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +var LanguageUtil = +/*#__PURE__*/ +function () { + function LanguageUtil(options) { + _classCallCheck(this, LanguageUtil); + + this.options = options; + this.whitelist = this.options.whitelist || false; + this.logger = baseLogger.create('languageUtils'); + } + + _createClass(LanguageUtil, [{ + key: "getScriptPartFromCode", + value: function getScriptPartFromCode(code) { + if (!code || code.indexOf('-') < 0) return null; + var p = code.split('-'); + if (p.length === 2) return null; + p.pop(); + return this.formatLanguageCode(p.join('-')); + } + }, { + key: "getLanguagePartFromCode", + value: function getLanguagePartFromCode(code) { + if (!code || code.indexOf('-') < 0) return code; + var p = code.split('-'); + return this.formatLanguageCode(p[0]); + } + }, { + key: "formatLanguageCode", + value: function formatLanguageCode(code) { + // http://www.iana.org/assignments/language-tags/language-tags.xhtml + if (typeof code === 'string' && code.indexOf('-') > -1) { + var specialCases = ['hans', 'hant', 'latn', 'cyrl', 'cans', 'mong', 'arab']; + var p = code.split('-'); + + if (this.options.lowerCaseLng) { + p = p.map(function (part) { + return part.toLowerCase(); + }); + } else if (p.length === 2) { + p[0] = p[0].toLowerCase(); + p[1] = p[1].toUpperCase(); + if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase()); + } else if (p.length === 3) { + p[0] = p[0].toLowerCase(); // if lenght 2 guess it's a country + + if (p[1].length === 2) p[1] = p[1].toUpperCase(); + if (p[0] !== 'sgn' && p[2].length === 2) p[2] = p[2].toUpperCase(); + if (specialCases.indexOf(p[1].toLowerCase()) > -1) p[1] = capitalize(p[1].toLowerCase()); + if (specialCases.indexOf(p[2].toLowerCase()) > -1) p[2] = capitalize(p[2].toLowerCase()); + } + + return p.join('-'); + } + + return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code; + } + }, { + key: "isWhitelisted", + value: function isWhitelisted(code) { + if (this.options.load === 'languageOnly' || this.options.nonExplicitWhitelist) { + code = this.getLanguagePartFromCode(code); + } + + return !this.whitelist || !this.whitelist.length || this.whitelist.indexOf(code) > -1; + } + }, { + key: "getFallbackCodes", + value: function getFallbackCodes(fallbacks, code) { + if (!fallbacks) return []; + if (typeof fallbacks === 'string') fallbacks = [fallbacks]; + if (Object.prototype.toString.apply(fallbacks) === '[object Array]') return fallbacks; + if (!code) return fallbacks["default"] || []; // asume we have an object defining fallbacks + + var found = fallbacks[code]; + if (!found) found = fallbacks[this.getScriptPartFromCode(code)]; + if (!found) found = fallbacks[this.formatLanguageCode(code)]; + if (!found) found = fallbacks["default"]; + return found || []; + } + }, { + key: "toResolveHierarchy", + value: function toResolveHierarchy(code, fallbackCode) { + var _this = this; + + var fallbackCodes = this.getFallbackCodes(fallbackCode || this.options.fallbackLng || [], code); + var codes = []; + + var addCode = function addCode(c) { + if (!c) return; + + if (_this.isWhitelisted(c)) { + codes.push(c); + } else { + _this.logger.warn("rejecting non-whitelisted language code: ".concat(c)); + } + }; + + if (typeof code === 'string' && code.indexOf('-') > -1) { + if (this.options.load !== 'languageOnly') addCode(this.formatLanguageCode(code)); + if (this.options.load !== 'languageOnly' && this.options.load !== 'currentOnly') addCode(this.getScriptPartFromCode(code)); + if (this.options.load !== 'currentOnly') addCode(this.getLanguagePartFromCode(code)); + } else if (typeof code === 'string') { + addCode(this.formatLanguageCode(code)); + } + + fallbackCodes.forEach(function (fc) { + if (codes.indexOf(fc) < 0) addCode(_this.formatLanguageCode(fc)); + }); + return codes; + } + }]); + + return LanguageUtil; +}(); + +/* eslint-disable */ + +var sets = [{ + lngs: ['ach', 'ak', 'am', 'arn', 'br', 'fil', 'gun', 'ln', 'mfe', 'mg', 'mi', 'oc', 'pt', 'pt-BR', 'tg', 'ti', 'tr', 'uz', 'wa'], + nr: [1, 2], + fc: 1 +}, { + lngs: ['af', 'an', 'ast', 'az', 'bg', 'bn', 'ca', 'da', 'de', 'dev', 'el', 'en', 'eo', 'es', 'et', 'eu', 'fi', 'fo', 'fur', 'fy', 'gl', 'gu', 'ha', 'hi', 'hu', 'hy', 'ia', 'it', 'kn', 'ku', 'lb', 'mai', 'ml', 'mn', 'mr', 'nah', 'nap', 'nb', 'ne', 'nl', 'nn', 'no', 'nso', 'pa', 'pap', 'pms', 'ps', 'pt-PT', 'rm', 'sco', 'se', 'si', 'so', 'son', 'sq', 'sv', 'sw', 'ta', 'te', 'tk', 'ur', 'yo'], + nr: [1, 2], + fc: 2 +}, { + lngs: ['ay', 'bo', 'cgg', 'fa', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky', 'lo', 'ms', 'sah', 'su', 'th', 'tt', 'ug', 'vi', 'wo', 'zh'], + nr: [1], + fc: 3 +}, { + lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'], + nr: [1, 2, 5], + fc: 4 +}, { + lngs: ['ar'], + nr: [0, 1, 2, 3, 11, 100], + fc: 5 +}, { + lngs: ['cs', 'sk'], + nr: [1, 2, 5], + fc: 6 +}, { + lngs: ['csb', 'pl'], + nr: [1, 2, 5], + fc: 7 +}, { + lngs: ['cy'], + nr: [1, 2, 3, 8], + fc: 8 +}, { + lngs: ['fr'], + nr: [1, 2], + fc: 9 +}, { + lngs: ['ga'], + nr: [1, 2, 3, 7, 11], + fc: 10 +}, { + lngs: ['gd'], + nr: [1, 2, 3, 20], + fc: 11 +}, { + lngs: ['is'], + nr: [1, 2], + fc: 12 +}, { + lngs: ['jv'], + nr: [0, 1], + fc: 13 +}, { + lngs: ['kw'], + nr: [1, 2, 3, 4], + fc: 14 +}, { + lngs: ['lt'], + nr: [1, 2, 10], + fc: 15 +}, { + lngs: ['lv'], + nr: [1, 2, 0], + fc: 16 +}, { + lngs: ['mk'], + nr: [1, 2], + fc: 17 +}, { + lngs: ['mnk'], + nr: [0, 1, 2], + fc: 18 +}, { + lngs: ['mt'], + nr: [1, 2, 11, 20], + fc: 19 +}, { + lngs: ['or'], + nr: [2, 1], + fc: 2 +}, { + lngs: ['ro'], + nr: [1, 2, 20], + fc: 20 +}, { + lngs: ['sl'], + nr: [5, 1, 2, 3], + fc: 21 +}, { + lngs: ['he'], + nr: [1, 2, 20, 21], + fc: 22 +}]; +var _rulesPluralsTypes = { + 1: function _(n) { + return Number(n > 1); + }, + 2: function _(n) { + return Number(n != 1); + }, + 3: function _(n) { + return 0; + }, + 4: function _(n) { + return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); + }, + 5: function _(n) { + return Number(n === 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5); + }, + 6: function _(n) { + return Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2); + }, + 7: function _(n) { + return Number(n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); + }, + 8: function _(n) { + return Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3); + }, + 9: function _(n) { + return Number(n >= 2); + }, + 10: function _(n) { + return Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4); + }, + 11: function _(n) { + return Number(n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3); + }, + 12: function _(n) { + return Number(n % 10 != 1 || n % 100 == 11); + }, + 13: function _(n) { + return Number(n !== 0); + }, + 14: function _(n) { + return Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3); + }, + 15: function _(n) { + return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); + }, + 16: function _(n) { + return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2); + }, + 17: function _(n) { + return Number(n == 1 || n % 10 == 1 ? 0 : 1); + }, + 18: function _(n) { + return Number(n == 0 ? 0 : n == 1 ? 1 : 2); + }, + 19: function _(n) { + return Number(n == 1 ? 0 : n === 0 || n % 100 > 1 && n % 100 < 11 ? 1 : n % 100 > 10 && n % 100 < 20 ? 2 : 3); + }, + 20: function _(n) { + return Number(n == 1 ? 0 : n === 0 || n % 100 > 0 && n % 100 < 20 ? 1 : 2); + }, + 21: function _(n) { + return Number(n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0); + }, + 22: function _(n) { + return Number(n === 1 ? 0 : n === 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3); + } +}; +/* eslint-enable */ + +function createRules() { + var rules = {}; + sets.forEach(function (set) { + set.lngs.forEach(function (l) { + rules[l] = { + numbers: set.nr, + plurals: _rulesPluralsTypes[set.fc] + }; + }); + }); + return rules; +} + +var PluralResolver = +/*#__PURE__*/ +function () { + function PluralResolver(languageUtils) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, PluralResolver); + + this.languageUtils = languageUtils; + this.options = options; + this.logger = baseLogger.create('pluralResolver'); + this.rules = createRules(); + } + + _createClass(PluralResolver, [{ + key: "addRule", + value: function addRule(lng, obj) { + this.rules[lng] = obj; + } + }, { + key: "getRule", + value: function getRule(code) { + return this.rules[code] || this.rules[this.languageUtils.getLanguagePartFromCode(code)]; + } + }, { + key: "needsPlural", + value: function needsPlural(code) { + var rule = this.getRule(code); + return rule && rule.numbers.length > 1; + } + }, { + key: "getPluralFormsOfKey", + value: function getPluralFormsOfKey(code, key) { + var _this = this; + + var ret = []; + var rule = this.getRule(code); + if (!rule) return ret; + rule.numbers.forEach(function (n) { + var suffix = _this.getSuffix(code, n); + + ret.push("".concat(key).concat(suffix)); + }); + return ret; + } + }, { + key: "getSuffix", + value: function getSuffix(code, count) { + var _this2 = this; + + var rule = this.getRule(code); + + if (rule) { + // if (rule.numbers.length === 1) return ''; // only singular + var idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count)); + var suffix = rule.numbers[idx]; // special treatment for lngs only having singular and plural + + if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) { + if (suffix === 2) { + suffix = 'plural'; + } else if (suffix === 1) { + suffix = ''; + } + } + + var returnSuffix = function returnSuffix() { + return _this2.options.prepend && suffix.toString() ? _this2.options.prepend + suffix.toString() : suffix.toString(); + }; // COMPATIBILITY JSON + // v1 + + + if (this.options.compatibilityJSON === 'v1') { + if (suffix === 1) return ''; + if (typeof suffix === 'number') return "_plural_".concat(suffix.toString()); + return returnSuffix(); + } else if ( + /* v2 */ + this.options.compatibilityJSON === 'v2') { + return returnSuffix(); + } else if ( + /* v3 - gettext index */ + this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) { + return returnSuffix(); + } + + return this.options.prepend && idx.toString() ? this.options.prepend + idx.toString() : idx.toString(); + } + + this.logger.warn("no plural rule found for: ".concat(code)); + return ''; + } + }]); + + return PluralResolver; +}(); + +var Interpolator = +/*#__PURE__*/ +function () { + function Interpolator() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Interpolator); + + this.logger = baseLogger.create('interpolator'); + this.options = options; + + this.format = options.interpolation && options.interpolation.format || function (value) { + return value; + }; + + this.init(options); + } + /* eslint no-param-reassign: 0 */ + + + _createClass(Interpolator, [{ + key: "init", + value: function init() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + if (!options.interpolation) options.interpolation = { + escapeValue: true + }; + var iOpts = options.interpolation; + this.escape = iOpts.escape !== undefined ? iOpts.escape : escape; + this.escapeValue = iOpts.escapeValue !== undefined ? iOpts.escapeValue : true; + this.useRawValueToEscape = iOpts.useRawValueToEscape !== undefined ? iOpts.useRawValueToEscape : false; + this.prefix = iOpts.prefix ? regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{'; + this.suffix = iOpts.suffix ? regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}'; + this.formatSeparator = iOpts.formatSeparator ? iOpts.formatSeparator : iOpts.formatSeparator || ','; + this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-'; + this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || ''; + this.nestingPrefix = iOpts.nestingPrefix ? regexEscape(iOpts.nestingPrefix) : iOpts.nestingPrefixEscaped || regexEscape('$t('); + this.nestingSuffix = iOpts.nestingSuffix ? regexEscape(iOpts.nestingSuffix) : iOpts.nestingSuffixEscaped || regexEscape(')'); + this.maxReplaces = iOpts.maxReplaces ? iOpts.maxReplaces : 1000; + this.alwaysFormat = iOpts.alwaysFormat !== undefined ? iOpts.alwaysFormat : false; // the regexp + + this.resetRegExp(); + } + }, { + key: "reset", + value: function reset() { + if (this.options) this.init(this.options); + } + }, { + key: "resetRegExp", + value: function resetRegExp() { + // the regexp + var regexpStr = "".concat(this.prefix, "(.+?)").concat(this.suffix); + this.regexp = new RegExp(regexpStr, 'g'); + var regexpUnescapeStr = "".concat(this.prefix).concat(this.unescapePrefix, "(.+?)").concat(this.unescapeSuffix).concat(this.suffix); + this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g'); + var nestingRegexpStr = "".concat(this.nestingPrefix, "(.+?)").concat(this.nestingSuffix); + this.nestingRegexp = new RegExp(nestingRegexpStr, 'g'); + } + }, { + key: "interpolate", + value: function interpolate(str, data, lng, options) { + var _this = this; + + var match; + var value; + var replaces; + var defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {}; + + function regexSafe(val) { + return val.replace(/\$/g, '$$$$'); + } + + var handleFormat = function handleFormat(key) { + if (key.indexOf(_this.formatSeparator) < 0) { + var path = getPathWithDefaults(data, defaultData, key); + return _this.alwaysFormat ? _this.format(path, undefined, lng) : path; + } + + var p = key.split(_this.formatSeparator); + var k = p.shift().trim(); + var f = p.join(_this.formatSeparator).trim(); + return _this.format(getPathWithDefaults(data, defaultData, k), f, lng, options); + }; + + this.resetRegExp(); + var missingInterpolationHandler = options && options.missingInterpolationHandler || this.options.missingInterpolationHandler; + replaces = 0; // unescape if has unescapePrefix/Suffix + + /* eslint no-cond-assign: 0 */ + + while (match = this.regexpUnescape.exec(str)) { + value = handleFormat(match[1].trim()); + + if (value === undefined) { + if (typeof missingInterpolationHandler === 'function') { + var temp = missingInterpolationHandler(str, match, options); + value = typeof temp === 'string' ? temp : ''; + } else { + this.logger.warn("missed to pass in variable ".concat(match[1], " for interpolating ").concat(str)); + value = ''; + } + } else if (typeof value !== 'string' && !this.useRawValueToEscape) { + value = makeString(value); + } + + str = str.replace(match[0], regexSafe(value)); + this.regexpUnescape.lastIndex = 0; + replaces++; + + if (replaces >= this.maxReplaces) { + break; + } + } + + replaces = 0; // regular escape on demand + + while (match = this.regexp.exec(str)) { + value = handleFormat(match[1].trim()); + + if (value === undefined) { + if (typeof missingInterpolationHandler === 'function') { + var _temp = missingInterpolationHandler(str, match, options); + + value = typeof _temp === 'string' ? _temp : ''; + } else { + this.logger.warn("missed to pass in variable ".concat(match[1], " for interpolating ").concat(str)); + value = ''; + } + } else if (typeof value !== 'string' && !this.useRawValueToEscape) { + value = makeString(value); + } + + value = this.escapeValue ? regexSafe(this.escape(value)) : regexSafe(value); + str = str.replace(match[0], value); + this.regexp.lastIndex = 0; + replaces++; + + if (replaces >= this.maxReplaces) { + break; + } + } + + return str; + } + }, { + key: "nest", + value: function nest(str, fc) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var match; + var value; + + var clonedOptions = _objectSpread({}, options); + + clonedOptions.applyPostProcessor = false; // avoid post processing on nested lookup + + delete clonedOptions.defaultValue; // assert we do not get a endless loop on interpolating defaultValue again and again + // if value is something like "myKey": "lorem $(anotherKey, { "count": {{aValueInOptions}} })" + + function handleHasOptions(key, inheritedOptions) { + if (key.indexOf(',') < 0) return key; + var p = key.split(','); + key = p.shift(); + var optionsString = p.join(','); + optionsString = this.interpolate(optionsString, clonedOptions); + optionsString = optionsString.replace(/'/g, '"'); + + try { + clonedOptions = JSON.parse(optionsString); + if (inheritedOptions) clonedOptions = _objectSpread({}, inheritedOptions, clonedOptions); + } catch (e) { + this.logger.error("failed parsing options string in nesting for key ".concat(key), e); + } // assert we do not get a endless loop on interpolating defaultValue again and again + + + delete clonedOptions.defaultValue; + return key; + } // regular escape on demand + + + while (match = this.nestingRegexp.exec(str)) { + value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions); // is only the nesting key (key1 = '$(key2)') return the value without stringify + + if (value && match[0] === str && typeof value !== 'string') return value; // no string to include or empty + + if (typeof value !== 'string') value = makeString(value); + + if (!value) { + this.logger.warn("missed to resolve ".concat(match[1], " for nesting ").concat(str)); + value = ''; + } // Nested keys should not be escaped by default #854 + // value = this.escapeValue ? regexSafe(utils.escape(value)) : regexSafe(value); + + + str = str.replace(match[0], value); + this.regexp.lastIndex = 0; + } + + return str; + } + }]); + + return Interpolator; +}(); + +function remove(arr, what) { + var found = arr.indexOf(what); + + while (found !== -1) { + arr.splice(found, 1); + found = arr.indexOf(what); + } +} + +var Connector = +/*#__PURE__*/ +function (_EventEmitter) { + _inherits(Connector, _EventEmitter); + + function Connector(backend, store, services) { + var _this; + + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + _classCallCheck(this, Connector); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Connector).call(this)); + EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) + + _this.backend = backend; + _this.store = store; + _this.services = services; + _this.languageUtils = services.languageUtils; + _this.options = options; + _this.logger = baseLogger.create('backendConnector'); + _this.state = {}; + _this.queue = []; + + if (_this.backend && _this.backend.init) { + _this.backend.init(services, options.backend, options); + } + + return _this; + } + + _createClass(Connector, [{ + key: "queueLoad", + value: function queueLoad(languages, namespaces, options, callback) { + var _this2 = this; + + // find what needs to be loaded + var toLoad = []; + var pending = []; + var toLoadLanguages = []; + var toLoadNamespaces = []; + languages.forEach(function (lng) { + var hasAllNamespaces = true; + namespaces.forEach(function (ns) { + var name = "".concat(lng, "|").concat(ns); + + if (!options.reload && _this2.store.hasResourceBundle(lng, ns)) { + _this2.state[name] = 2; // loaded + } else if (_this2.state[name] < 0) ; else if (_this2.state[name] === 1) { + if (pending.indexOf(name) < 0) pending.push(name); + } else { + _this2.state[name] = 1; // pending + + hasAllNamespaces = false; + if (pending.indexOf(name) < 0) pending.push(name); + if (toLoad.indexOf(name) < 0) toLoad.push(name); + if (toLoadNamespaces.indexOf(ns) < 0) toLoadNamespaces.push(ns); + } + }); + if (!hasAllNamespaces) toLoadLanguages.push(lng); + }); + + if (toLoad.length || pending.length) { + this.queue.push({ + pending: pending, + loaded: {}, + errors: [], + callback: callback + }); + } + + return { + toLoad: toLoad, + pending: pending, + toLoadLanguages: toLoadLanguages, + toLoadNamespaces: toLoadNamespaces + }; + } + }, { + key: "loaded", + value: function loaded(name, err, data) { + var _name$split = name.split('|'), + _name$split2 = _slicedToArray(_name$split, 2), + lng = _name$split2[0], + ns = _name$split2[1]; + + if (err) this.emit('failedLoading', lng, ns, err); + + if (data) { + this.store.addResourceBundle(lng, ns, data); + } // set loaded + + + this.state[name] = err ? -1 : 2; // consolidated loading done in this run - only emit once for a loaded namespace + + var loaded = {}; // callback if ready + + this.queue.forEach(function (q) { + pushPath(q.loaded, [lng], ns); + remove(q.pending, name); + if (err) q.errors.push(err); + + if (q.pending.length === 0 && !q.done) { + // only do once per loaded -> this.emit('loaded', q.loaded); + Object.keys(q.loaded).forEach(function (l) { + if (!loaded[l]) loaded[l] = []; + + if (q.loaded[l].length) { + q.loaded[l].forEach(function (ns) { + if (loaded[l].indexOf(ns) < 0) loaded[l].push(ns); + }); + } + }); + /* eslint no-param-reassign: 0 */ + + q.done = true; + + if (q.errors.length) { + q.callback(q.errors); + } else { + q.callback(); + } + } + }); // emit consolidated loaded event + + this.emit('loaded', loaded); // remove done load requests + + this.queue = this.queue.filter(function (q) { + return !q.done; + }); + } + }, { + key: "read", + value: function read(lng, ns, fcName) { + var _this3 = this; + + var tried = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + var wait = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 250; + var callback = arguments.length > 5 ? arguments[5] : undefined; + if (!lng.length) return callback(null, {}); // noting to load + + return this.backend[fcName](lng, ns, function (err, data) { + if (err && data + /* = retryFlag */ + && tried < 5) { + setTimeout(function () { + _this3.read.call(_this3, lng, ns, fcName, tried + 1, wait * 2, callback); + }, wait); + return; + } + + callback(err, data); + }); + } + /* eslint consistent-return: 0 */ + + }, { + key: "prepareLoading", + value: function prepareLoading(languages, namespaces) { + var _this4 = this; + + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var callback = arguments.length > 3 ? arguments[3] : undefined; + + if (!this.backend) { + this.logger.warn('No backend was added via i18next.use. Will not load resources.'); + return callback && callback(); + } + + if (typeof languages === 'string') languages = this.languageUtils.toResolveHierarchy(languages); + if (typeof namespaces === 'string') namespaces = [namespaces]; + var toLoad = this.queueLoad(languages, namespaces, options, callback); + + if (!toLoad.toLoad.length) { + if (!toLoad.pending.length) callback(); // nothing to load and no pendings...callback now + + return null; // pendings will trigger callback + } + + toLoad.toLoad.forEach(function (name) { + _this4.loadOne(name); + }); + } + }, { + key: "load", + value: function load(languages, namespaces, callback) { + this.prepareLoading(languages, namespaces, {}, callback); + } + }, { + key: "reload", + value: function reload(languages, namespaces, callback) { + this.prepareLoading(languages, namespaces, { + reload: true + }, callback); + } + }, { + key: "loadOne", + value: function loadOne(name) { + var _this5 = this; + + var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + + var _name$split3 = name.split('|'), + _name$split4 = _slicedToArray(_name$split3, 2), + lng = _name$split4[0], + ns = _name$split4[1]; + + this.read(lng, ns, 'read', undefined, undefined, function (err, data) { + if (err) _this5.logger.warn("".concat(prefix, "loading namespace ").concat(ns, " for language ").concat(lng, " failed"), err); + if (!err && data) _this5.logger.log("".concat(prefix, "loaded namespace ").concat(ns, " for language ").concat(lng), data); + + _this5.loaded(name, err, data); + }); + } + }, { + key: "saveMissing", + value: function saveMissing(languages, namespace, key, fallbackValue, isUpdate) { + var options = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; + + if (this.services.utils && this.services.utils.hasLoadedNamespace && !this.services.utils.hasLoadedNamespace(namespace)) { + this.logger.warn("did not save key \"".concat(key, "\" for namespace \"").concat(namespace, "\" as the namespace was not yet loaded"), 'This means something IS WRONG in your application setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!'); + return; + } // ignore non valid keys + + + if (key === undefined || key === null || key === '') return; + + if (this.backend && this.backend.create) { + this.backend.create(languages, namespace, key, fallbackValue, null + /* unused callback */ + , _objectSpread({}, options, { + isUpdate: isUpdate + })); + } // write to store to avoid resending + + + if (!languages || !languages[0]) return; + this.store.addResource(languages[0], namespace, key, fallbackValue); + } + }]); + + return Connector; +}(EventEmitter); + +function get() { + return { + debug: false, + initImmediate: true, + ns: ['translation'], + defaultNS: ['translation'], + fallbackLng: ['dev'], + fallbackNS: false, + // string or array of namespaces + whitelist: false, + // array with whitelisted languages + nonExplicitWhitelist: false, + load: 'all', + // | currentOnly | languageOnly + preload: false, + // array with preload languages + simplifyPluralSuffix: true, + keySeparator: '.', + nsSeparator: ':', + pluralSeparator: '_', + contextSeparator: '_', + partialBundledLanguages: false, + // allow bundling certain languages that are not remotely fetched + saveMissing: false, + // enable to send missing values + updateMissing: false, + // enable to update default values if different from translated value (only useful on initial development, or when keeping code as source of truth) + saveMissingTo: 'fallback', + // 'current' || 'all' + saveMissingPlurals: true, + // will save all forms not only singular key + missingKeyHandler: false, + // function(lng, ns, key, fallbackValue) -> override if prefer on handling + missingInterpolationHandler: false, + // function(str, match) + postProcess: false, + // string or array of postProcessor names + postProcessPassResolved: false, + // pass resolved object into 'options.i18nResolved' for postprocessor + returnNull: true, + // allows null value as valid translation + returnEmptyString: true, + // allows empty string value as valid translation + returnObjects: false, + joinArrays: false, + // or string to join array + returnedObjectHandler: false, + // function(key, value, options) triggered if key returns object but returnObjects is set to false + parseMissingKeyHandler: false, + // function(key) parsed a key that was not found in t() before returning + appendNamespaceToMissingKey: false, + appendNamespaceToCIMode: false, + overloadTranslationOptionHandler: function handle(args) { + var ret = {}; + if (_typeof(args[1]) === 'object') ret = args[1]; + if (typeof args[1] === 'string') ret.defaultValue = args[1]; + if (typeof args[2] === 'string') ret.tDescription = args[2]; + + if (_typeof(args[2]) === 'object' || _typeof(args[3]) === 'object') { + var options = args[3] || args[2]; + Object.keys(options).forEach(function (key) { + ret[key] = options[key]; + }); + } + + return ret; + }, + interpolation: { + escapeValue: true, + format: function format(value, _format, lng, options) { + return value; + }, + prefix: '{{', + suffix: '}}', + formatSeparator: ',', + // prefixEscaped: '{{', + // suffixEscaped: '}}', + // unescapeSuffix: '', + unescapePrefix: '-', + nestingPrefix: '$t(', + nestingSuffix: ')', + // nestingPrefixEscaped: '$t(', + // nestingSuffixEscaped: ')', + // defaultVariables: undefined // object that can have values to interpolate on - extends passed in interpolation data + maxReplaces: 1000 // max replaces to prevent endless loop + + } + }; +} +/* eslint no-param-reassign: 0 */ + +function transformOptions(options) { + // create namespace object if namespace is passed in as string + if (typeof options.ns === 'string') options.ns = [options.ns]; + if (typeof options.fallbackLng === 'string') options.fallbackLng = [options.fallbackLng]; + if (typeof options.fallbackNS === 'string') options.fallbackNS = [options.fallbackNS]; // extend whitelist with cimode + + if (options.whitelist && options.whitelist.indexOf('cimode') < 0) { + options.whitelist = options.whitelist.concat(['cimode']); + } + + return options; +} + +function noop() {} + +var I18n = +/*#__PURE__*/ +function (_EventEmitter) { + _inherits(I18n, _EventEmitter); + + function I18n() { + var _this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments.length > 1 ? arguments[1] : undefined; + + _classCallCheck(this, I18n); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(I18n).call(this)); + EventEmitter.call(_assertThisInitialized(_this)); // <=IE10 fix (unable to call parent constructor) + + _this.options = transformOptions(options); + _this.services = {}; + _this.logger = baseLogger; + _this.modules = { + external: [] + }; + + if (callback && !_this.isInitialized && !options.isClone) { + // https://github.com/i18next/i18next/issues/879 + if (!_this.options.initImmediate) { + _this.init(options, callback); + + return _possibleConstructorReturn(_this, _assertThisInitialized(_this)); + } + + setTimeout(function () { + _this.init(options, callback); + }, 0); + } + + return _this; + } + + _createClass(I18n, [{ + key: "init", + value: function init() { + var _this2 = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments.length > 1 ? arguments[1] : undefined; + + if (typeof options === 'function') { + callback = options; + options = {}; + } + + this.options = _objectSpread({}, get(), this.options, transformOptions(options)); + this.format = this.options.interpolation.format; + if (!callback) callback = noop; + + function createClassOnDemand(ClassOrObject) { + if (!ClassOrObject) return null; + if (typeof ClassOrObject === 'function') return new ClassOrObject(); + return ClassOrObject; + } // init services + + + if (!this.options.isClone) { + if (this.modules.logger) { + baseLogger.init(createClassOnDemand(this.modules.logger), this.options); + } else { + baseLogger.init(null, this.options); + } + + var lu = new LanguageUtil(this.options); + this.store = new ResourceStore(this.options.resources, this.options); + var s = this.services; + s.logger = baseLogger; + s.resourceStore = this.store; + s.languageUtils = lu; + s.pluralResolver = new PluralResolver(lu, { + prepend: this.options.pluralSeparator, + compatibilityJSON: this.options.compatibilityJSON, + simplifyPluralSuffix: this.options.simplifyPluralSuffix + }); + s.interpolator = new Interpolator(this.options); + s.utils = { + hasLoadedNamespace: this.hasLoadedNamespace.bind(this) + }; + s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options); // pipe events from backendConnector + + s.backendConnector.on('*', function (event) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + _this2.emit.apply(_this2, [event].concat(args)); + }); + + if (this.modules.languageDetector) { + s.languageDetector = createClassOnDemand(this.modules.languageDetector); + s.languageDetector.init(s, this.options.detection, this.options); + } + + if (this.modules.i18nFormat) { + s.i18nFormat = createClassOnDemand(this.modules.i18nFormat); + if (s.i18nFormat.init) s.i18nFormat.init(this); + } + + this.translator = new Translator(this.services, this.options); // pipe events from translator + + this.translator.on('*', function (event) { + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + + _this2.emit.apply(_this2, [event].concat(args)); + }); + this.modules.external.forEach(function (m) { + if (m.init) m.init(_this2); + }); + } + + if (!this.modules.languageDetector && !this.options.lng) { + this.logger.warn('init: no languageDetector is used and no lng is defined'); + } // append api + + + var storeApi = ['getResource', 'addResource', 'addResources', 'addResourceBundle', 'removeResourceBundle', 'hasResourceBundle', 'getResourceBundle', 'getDataByLanguage']; + storeApi.forEach(function (fcName) { + _this2[fcName] = function () { + var _this2$store; + + return (_this2$store = _this2.store)[fcName].apply(_this2$store, arguments); + }; + }); + var deferred = defer(); + + var load = function load() { + _this2.changeLanguage(_this2.options.lng, function (err, t) { + _this2.isInitialized = true; + + _this2.logger.log('initialized', _this2.options); + + _this2.emit('initialized', _this2.options); + + deferred.resolve(t); // not rejecting on err (as err is only a loading translation failed warning) + + callback(err, t); + }); + }; + + if (this.options.resources || !this.options.initImmediate) { + load(); + } else { + setTimeout(load, 0); + } + + return deferred; + } + /* eslint consistent-return: 0 */ + + }, { + key: "loadResources", + value: function loadResources(language) { + var _this3 = this; + + var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + var usedCallback = callback; + var usedLng = typeof language === 'string' ? language : this.language; + if (typeof language === 'function') usedCallback = language; + + if (!this.options.resources || this.options.partialBundledLanguages) { + if (usedLng && usedLng.toLowerCase() === 'cimode') return usedCallback(); // avoid loading resources for cimode + + var toLoad = []; + + var append = function append(lng) { + if (!lng) return; + + var lngs = _this3.services.languageUtils.toResolveHierarchy(lng); + + lngs.forEach(function (l) { + if (toLoad.indexOf(l) < 0) toLoad.push(l); + }); + }; + + if (!usedLng) { + // at least load fallbacks in this case + var fallbacks = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng); + fallbacks.forEach(function (l) { + return append(l); + }); + } else { + append(usedLng); + } + + if (this.options.preload) { + this.options.preload.forEach(function (l) { + return append(l); + }); + } + + this.services.backendConnector.load(toLoad, this.options.ns, usedCallback); + } else { + usedCallback(null); + } + } + }, { + key: "reloadResources", + value: function reloadResources(lngs, ns, callback) { + var deferred = defer(); + if (!lngs) lngs = this.languages; + if (!ns) ns = this.options.ns; + if (!callback) callback = noop; + this.services.backendConnector.reload(lngs, ns, function (err) { + deferred.resolve(); // not rejecting on err (as err is only a loading translation failed warning) + + callback(err); + }); + return deferred; + } + }, { + key: "use", + value: function use(module) { + if (module.type === 'backend') { + this.modules.backend = module; + } + + if (module.type === 'logger' || module.log && module.warn && module.error) { + this.modules.logger = module; + } + + if (module.type === 'languageDetector') { + this.modules.languageDetector = module; + } + + if (module.type === 'i18nFormat') { + this.modules.i18nFormat = module; + } + + if (module.type === 'postProcessor') { + postProcessor.addPostProcessor(module); + } + + if (module.type === '3rdParty') { + this.modules.external.push(module); + } + + return this; + } + }, { + key: "changeLanguage", + value: function changeLanguage(lng, callback) { + var _this4 = this; + + this.isLanguageChangingTo = lng; + var deferred = defer(); + this.emit('languageChanging', lng); + + var done = function done(err, l) { + if (l) { + _this4.language = l; + _this4.languages = _this4.services.languageUtils.toResolveHierarchy(l); + + _this4.translator.changeLanguage(l); + + _this4.isLanguageChangingTo = undefined; + + _this4.emit('languageChanged', l); + + _this4.logger.log('languageChanged', l); + } else { + _this4.isLanguageChangingTo = undefined; + } + + deferred.resolve(function () { + return _this4.t.apply(_this4, arguments); + }); + if (callback) callback(err, function () { + return _this4.t.apply(_this4, arguments); + }); + }; + + var setLng = function setLng(l) { + if (l) { + if (!_this4.language) { + _this4.language = l; + _this4.languages = _this4.services.languageUtils.toResolveHierarchy(l); + } + + if (!_this4.translator.language) _this4.translator.changeLanguage(l); + if (_this4.services.languageDetector) _this4.services.languageDetector.cacheUserLanguage(l); + } + + _this4.loadResources(l, function (err) { + done(err, l); + }); + }; + + if (!lng && this.services.languageDetector && !this.services.languageDetector.async) { + setLng(this.services.languageDetector.detect()); + } else if (!lng && this.services.languageDetector && this.services.languageDetector.async) { + this.services.languageDetector.detect(setLng); + } else { + setLng(lng); + } + + return deferred; + } + }, { + key: "getFixedT", + value: function getFixedT(lng, ns) { + var _this5 = this; + + var fixedT = function fixedT(key, opts) { + var options; + + if (_typeof(opts) !== 'object') { + for (var _len3 = arguments.length, rest = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) { + rest[_key3 - 2] = arguments[_key3]; + } + + options = _this5.options.overloadTranslationOptionHandler([key, opts].concat(rest)); + } else { + options = _objectSpread({}, opts); + } + + options.lng = options.lng || fixedT.lng; + options.lngs = options.lngs || fixedT.lngs; + options.ns = options.ns || fixedT.ns; + return _this5.t(key, options); + }; + + if (typeof lng === 'string') { + fixedT.lng = lng; + } else { + fixedT.lngs = lng; + } + + fixedT.ns = ns; + return fixedT; + } + }, { + key: "t", + value: function t() { + var _this$translator; + + return this.translator && (_this$translator = this.translator).translate.apply(_this$translator, arguments); + } + }, { + key: "exists", + value: function exists() { + var _this$translator2; + + return this.translator && (_this$translator2 = this.translator).exists.apply(_this$translator2, arguments); + } + }, { + key: "setDefaultNamespace", + value: function setDefaultNamespace(ns) { + this.options.defaultNS = ns; + } + }, { + key: "hasLoadedNamespace", + value: function hasLoadedNamespace(ns) { + var _this6 = this; + + if (!this.isInitialized) { + this.logger.warn('hasLoadedNamespace: i18next was not initialized', this.languages); + return false; + } + + if (!this.languages || !this.languages.length) { + this.logger.warn('hasLoadedNamespace: i18n.languages were undefined or empty', this.languages); + return false; + } + + var lng = this.languages[0]; + var fallbackLng = this.options ? this.options.fallbackLng : false; + var lastLng = this.languages[this.languages.length - 1]; // we're in cimode so this shall pass + + if (lng.toLowerCase() === 'cimode') return true; + + var loadNotPending = function loadNotPending(l, n) { + var loadState = _this6.services.backendConnector.state["".concat(l, "|").concat(n)]; + + return loadState === -1 || loadState === 2; + }; // loaded -> SUCCESS + + + if (this.hasResourceBundle(lng, ns)) return true; // were not loading at all -> SEMI SUCCESS + + if (!this.services.backendConnector.backend) return true; // failed loading ns - but at least fallback is not pending -> SEMI SUCCESS + + if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true; + return false; + } + }, { + key: "loadNamespaces", + value: function loadNamespaces(ns, callback) { + var _this7 = this; + + var deferred = defer(); + + if (!this.options.ns) { + callback && callback(); + return Promise.resolve(); + } + + if (typeof ns === 'string') ns = [ns]; + ns.forEach(function (n) { + if (_this7.options.ns.indexOf(n) < 0) _this7.options.ns.push(n); + }); + this.loadResources(function (err) { + deferred.resolve(); + if (callback) callback(err); + }); + return deferred; + } + }, { + key: "loadLanguages", + value: function loadLanguages(lngs, callback) { + var deferred = defer(); + if (typeof lngs === 'string') lngs = [lngs]; + var preloaded = this.options.preload || []; + var newLngs = lngs.filter(function (lng) { + return preloaded.indexOf(lng) < 0; + }); // Exit early if all given languages are already preloaded + + if (!newLngs.length) { + if (callback) callback(); + return Promise.resolve(); + } + + this.options.preload = preloaded.concat(newLngs); + this.loadResources(function (err) { + deferred.resolve(); + if (callback) callback(err); + }); + return deferred; + } + }, { + key: "dir", + value: function dir(lng) { + if (!lng) lng = this.languages && this.languages.length > 0 ? this.languages[0] : this.language; + if (!lng) return 'rtl'; + var rtlLngs = ['ar', 'shu', 'sqr', 'ssh', 'xaa', 'yhd', 'yud', 'aao', 'abh', 'abv', 'acm', 'acq', 'acw', 'acx', 'acy', 'adf', 'ads', 'aeb', 'aec', 'afb', 'ajp', 'apc', 'apd', 'arb', 'arq', 'ars', 'ary', 'arz', 'auz', 'avl', 'ayh', 'ayl', 'ayn', 'ayp', 'bbz', 'pga', 'he', 'iw', 'ps', 'pbt', 'pbu', 'pst', 'prp', 'prd', 'ur', 'ydd', 'yds', 'yih', 'ji', 'yi', 'hbo', 'men', 'xmn', 'fa', 'jpr', 'peo', 'pes', 'prs', 'dv', 'sam']; + return rtlLngs.indexOf(this.services.languageUtils.getLanguagePartFromCode(lng)) >= 0 ? 'rtl' : 'ltr'; + } + /* eslint class-methods-use-this: 0 */ + + }, { + key: "createInstance", + value: function createInstance() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments.length > 1 ? arguments[1] : undefined; + return new I18n(options, callback); + } + }, { + key: "cloneInstance", + value: function cloneInstance() { + var _this8 = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop; + + var mergedOptions = _objectSpread({}, this.options, options, { + isClone: true + }); + + var clone = new I18n(mergedOptions); + var membersToCopy = ['store', 'services', 'language']; + membersToCopy.forEach(function (m) { + clone[m] = _this8[m]; + }); + clone.translator = new Translator(clone.services, clone.options); + clone.translator.on('*', function (event) { + for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { + args[_key4 - 1] = arguments[_key4]; + } + + clone.emit.apply(clone, [event].concat(args)); + }); + clone.init(mergedOptions, callback); + clone.translator.options = clone.options; // sync options + + return clone; + } + }]); + + return I18n; +}(EventEmitter); + +var i18next = new I18n(); + +module.exports = i18next; + + +/***/ }), + +/***/ "./node_modules/ieee754/index.js": +/*!***************************************!*\ + !*** ./node_modules/ieee754/index.js ***! + \***************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + + +/***/ }), + +/***/ "./node_modules/immediate/lib/browser.js": +/*!***********************************************!*\ + !*** ./node_modules/immediate/lib/browser.js ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) { +var Mutation = global.MutationObserver || global.WebKitMutationObserver; + +var scheduleDrain; + +{ + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + scheduleDrain = function () { + element.data = (called = ++called % 2); + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + + // Create a