mirror of
https://github.com/bvanroll/rpiRadio.git
synced 2025-08-30 12:32:47 +00:00
3156 lines
229 KiB
JavaScript
3156 lines
229 KiB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.MidiPlayer = f()}})(function(){var define,module,exports;return (function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){
|
|
'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
|
|
}
|
|
|
|
revLookup['-'.charCodeAt(0)] = 62
|
|
revLookup['_'.charCodeAt(0)] = 63
|
|
|
|
function placeHoldersCount (b64) {
|
|
var len = b64.length
|
|
if (len % 4 > 0) {
|
|
throw new Error('Invalid string. Length must be a multiple of 4')
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
|
|
}
|
|
|
|
function byteLength (b64) {
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
return (b64.length * 3 / 4) - placeHoldersCount(b64)
|
|
}
|
|
|
|
function toByteArray (b64) {
|
|
var i, l, tmp, placeHolders, arr
|
|
var len = b64.length
|
|
placeHolders = placeHoldersCount(b64)
|
|
|
|
arr = new Arr((len * 3 / 4) - placeHolders)
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? len - 4 : len
|
|
|
|
var L = 0
|
|
|
|
for (i = 0; i < l; 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[L++] = (tmp >> 16) & 0xFF
|
|
arr[L++] = (tmp >> 8) & 0xFF
|
|
arr[L++] = tmp & 0xFF
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
|
|
arr[L++] = tmp & 0xFF
|
|
} else if (placeHolders === 1) {
|
|
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
|
|
arr[L++] = (tmp >> 8) & 0xFF
|
|
arr[L++] = 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) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
|
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 output = ''
|
|
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]
|
|
output += lookup[tmp >> 2]
|
|
output += lookup[(tmp << 4) & 0x3F]
|
|
output += '=='
|
|
} else if (extraBytes === 2) {
|
|
tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
|
|
output += lookup[tmp >> 10]
|
|
output += lookup[(tmp >> 4) & 0x3F]
|
|
output += lookup[(tmp << 2) & 0x3F]
|
|
output += '='
|
|
}
|
|
|
|
parts.push(output)
|
|
|
|
return parts.join('')
|
|
}
|
|
|
|
},{}],2:[function(require,module,exports){
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <https://feross.org>
|
|
* @license MIT
|
|
*/
|
|
/* eslint-disable no-proto */
|
|
|
|
'use strict'
|
|
|
|
var base64 = require('base64-js')
|
|
var ieee754 = require('ieee754')
|
|
|
|
exports.Buffer = Buffer
|
|
exports.SlowBuffer = SlowBuffer
|
|
exports.INSPECT_MAX_BYTES = 50
|
|
|
|
var K_MAX_LENGTH = 0x7fffffff
|
|
exports.kMaxLength = K_MAX_LENGTH
|
|
|
|
/**
|
|
* If `Buffer.TYPED_ARRAY_SUPPORT`:
|
|
* === true Use Uint8Array implementation (fastest)
|
|
* === false Print warning and recommend using `buffer` v4.x which has an 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+.
|
|
*
|
|
* We report that the browser does not support typed arrays if the are not subclassable
|
|
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
|
|
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
|
|
* for __proto__ and has a buggy typed array implementation.
|
|
*/
|
|
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
|
|
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' &&
|
|
typeof console.error === 'function') {
|
|
console.error(
|
|
'This browser lacks typed array (Uint8Array) support which is required by ' +
|
|
'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'
|
|
)
|
|
}
|
|
|
|
function typedArraySupport () {
|
|
// Can typed array instances can be augmented?
|
|
try {
|
|
var arr = new Uint8Array(1)
|
|
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
|
|
return arr.foo() === 42
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function createBuffer (length) {
|
|
if (length > K_MAX_LENGTH) {
|
|
throw new RangeError('Invalid typed array length')
|
|
}
|
|
// Return an augmented `Uint8Array` instance
|
|
var buf = new Uint8Array(length)
|
|
buf.__proto__ = Buffer.prototype
|
|
return buf
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
// 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(arg)
|
|
}
|
|
return from(arg, encodingOrOffset, length)
|
|
}
|
|
|
|
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
|
|
if (typeof Symbol !== 'undefined' && Symbol.species &&
|
|
Buffer[Symbol.species] === Buffer) {
|
|
Object.defineProperty(Buffer, Symbol.species, {
|
|
value: null,
|
|
configurable: true,
|
|
enumerable: false,
|
|
writable: false
|
|
})
|
|
}
|
|
|
|
Buffer.poolSize = 8192 // not used by this implementation
|
|
|
|
function from (value, encodingOrOffset, length) {
|
|
if (typeof value === 'number') {
|
|
throw new TypeError('"value" argument must not be a number')
|
|
}
|
|
|
|
if (isArrayBuffer(value)) {
|
|
return fromArrayBuffer(value, encodingOrOffset, length)
|
|
}
|
|
|
|
if (typeof value === 'string') {
|
|
return fromString(value, encodingOrOffset)
|
|
}
|
|
|
|
return fromObject(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(value, encodingOrOffset, length)
|
|
}
|
|
|
|
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
|
|
// https://github.com/feross/buffer/pull/148
|
|
Buffer.prototype.__proto__ = Uint8Array.prototype
|
|
Buffer.__proto__ = Uint8Array
|
|
|
|
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 (size, fill, encoding) {
|
|
assertSize(size)
|
|
if (size <= 0) {
|
|
return createBuffer(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(size).fill(fill, encoding)
|
|
: createBuffer(size).fill(fill)
|
|
}
|
|
return createBuffer(size)
|
|
}
|
|
|
|
/**
|
|
* Creates a new filled Buffer instance.
|
|
* alloc(size[, fill[, encoding]])
|
|
**/
|
|
Buffer.alloc = function (size, fill, encoding) {
|
|
return alloc(size, fill, encoding)
|
|
}
|
|
|
|
function allocUnsafe (size) {
|
|
assertSize(size)
|
|
return createBuffer(size < 0 ? 0 : checked(size) | 0)
|
|
}
|
|
|
|
/**
|
|
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
|
|
* */
|
|
Buffer.allocUnsafe = function (size) {
|
|
return allocUnsafe(size)
|
|
}
|
|
/**
|
|
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
|
|
*/
|
|
Buffer.allocUnsafeSlow = function (size) {
|
|
return allocUnsafe(size)
|
|
}
|
|
|
|
function fromString (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
|
|
var buf = createBuffer(length)
|
|
|
|
var actual = buf.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')
|
|
buf = buf.slice(0, actual)
|
|
}
|
|
|
|
return buf
|
|
}
|
|
|
|
function fromArrayLike (array) {
|
|
var length = array.length < 0 ? 0 : checked(array.length) | 0
|
|
var buf = createBuffer(length)
|
|
for (var i = 0; i < length; i += 1) {
|
|
buf[i] = array[i] & 255
|
|
}
|
|
return buf
|
|
}
|
|
|
|
function fromArrayBuffer (array, byteOffset, length) {
|
|
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')
|
|
}
|
|
|
|
var buf
|
|
if (byteOffset === undefined && length === undefined) {
|
|
buf = new Uint8Array(array)
|
|
} else if (length === undefined) {
|
|
buf = new Uint8Array(array, byteOffset)
|
|
} else {
|
|
buf = new Uint8Array(array, byteOffset, length)
|
|
}
|
|
|
|
// Return an augmented `Uint8Array` instance
|
|
buf.__proto__ = Buffer.prototype
|
|
return buf
|
|
}
|
|
|
|
function fromObject (obj) {
|
|
if (Buffer.isBuffer(obj)) {
|
|
var len = checked(obj.length) | 0
|
|
var buf = createBuffer(len)
|
|
|
|
if (buf.length === 0) {
|
|
return buf
|
|
}
|
|
|
|
obj.copy(buf, 0, 0, len)
|
|
return buf
|
|
}
|
|
|
|
if (obj) {
|
|
if (isArrayBufferView(obj) || 'length' in obj) {
|
|
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) {
|
|
return createBuffer(0)
|
|
}
|
|
return fromArrayLike(obj)
|
|
}
|
|
|
|
if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
|
|
return fromArrayLike(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 < K_MAX_LENGTH` here because that fails when
|
|
// length is NaN (which is otherwise coerced to zero.)
|
|
if (length >= K_MAX_LENGTH) {
|
|
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
|
'size: 0x' + K_MAX_LENGTH.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 === true
|
|
}
|
|
|
|
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 (!Array.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 (isArrayBufferView(string) || isArrayBuffer(string)) {
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
|
|
// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
|
|
// reliably in a browserify context because there could be multiple different
|
|
// copies of the 'buffer' package in use. This method works even for Buffer
|
|
// instances that were created from another copy of the `buffer` package.
|
|
// See: https://github.com/feross/buffer/issues/154
|
|
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
|
|
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 ' + str + '>'
|
|
}
|
|
|
|
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 (numberIsNaN(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 (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 (numberIsNaN(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
|
|
}
|
|
} 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 = this.subarray(start, end)
|
|
// Return an augmented `Uint8Array` instance
|
|
newBuf.__proto__ = Buffer.prototype
|
|
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) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
return this[offset]
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return this[offset] | (this[offset + 1] << 8)
|
|
}
|
|
|
|
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return (this[offset] << 8) | this[offset + 1]
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
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) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, true, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, false, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, true, 52, 8)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
|
|
offset = offset >>> 0
|
|
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)
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
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)
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
this[offset + 3] = (value >>> 24)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset] = (value & 0xff)
|
|
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)
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
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 (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)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
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)
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
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)
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 3] = (value >>> 24)
|
|
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
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
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) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
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) {
|
|
value = +value
|
|
offset = offset >>> 0
|
|
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) {
|
|
// 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
|
|
: new Buffer(val, encoding)
|
|
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 = str.trim().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 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
|
|
}
|
|
|
|
// ArrayBuffers from another context (i.e. an iframe) do not pass the `instanceof` check
|
|
// but they should be treated as valid. See: https://github.com/feross/buffer/issues/166
|
|
function isArrayBuffer (obj) {
|
|
return obj instanceof ArrayBuffer ||
|
|
(obj != null && obj.constructor != null && obj.constructor.name === 'ArrayBuffer' &&
|
|
typeof obj.byteLength === 'number')
|
|
}
|
|
|
|
// Node 0.10 supports `ArrayBuffer` but lacks `ArrayBuffer.isView`
|
|
function isArrayBufferView (obj) {
|
|
return (typeof ArrayBuffer.isView === 'function') && ArrayBuffer.isView(obj)
|
|
}
|
|
|
|
function numberIsNaN (obj) {
|
|
return obj !== obj // eslint-disable-line no-self-compare
|
|
}
|
|
|
|
},{"base64-js":1,"ieee754":3}],3:[function(require,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
|
|
}
|
|
|
|
},{}],4:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
/**
|
|
* Constants used in player.
|
|
*/
|
|
var Constants = {
|
|
VERSION: '2.0.3',
|
|
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.
|
|
var allNotes = [['C'], ['C#', 'Db'], ['D'], ['D#', 'Eb'], ['E'], ['F'], ['F#', 'Gb'], ['G'], ['G#', 'Ab'], ['A'], ['A#', 'Bb'], ['B']];
|
|
var counter = 0;
|
|
|
|
// All available octaves.
|
|
|
|
var _loop = function _loop(i) {
|
|
allNotes.forEach(function (noteGroup) {
|
|
noteGroup.forEach(function (note) {
|
|
return Constants.NOTES[counter] = note + i;
|
|
});
|
|
counter++;
|
|
});
|
|
};
|
|
|
|
for (var i = -1; i <= 9; i++) {
|
|
_loop(i);
|
|
}
|
|
|
|
exports.Constants = Constants;
|
|
|
|
},{}],5:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
var Player = require("./player");
|
|
var Utils = require("./utils");
|
|
var Constants = require("./constants");
|
|
|
|
module.exports = {
|
|
Player: Player.Player,
|
|
Utils: Utils.Utils,
|
|
Constants: Constants.Constants
|
|
};
|
|
|
|
},{"./constants":4,"./player":6,"./utils":8}],6:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
var Utils = require("./utils").Utils;
|
|
var 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).
|
|
*/
|
|
|
|
var Player = function () {
|
|
function Player(eventHandler, buffer) {
|
|
_classCallCheck(this, Player);
|
|
|
|
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}
|
|
*/
|
|
|
|
|
|
_createClass(Player, [{
|
|
key: "loadFile",
|
|
value: function loadFile(path) {
|
|
var 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "loadArrayBuffer",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "loadDataUri",
|
|
value: function 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
|
|
var byteString = Utils.atob(dataUri.split(',')[1]);
|
|
|
|
// write the bytes of the string to an ArrayBuffer
|
|
var ia = new Uint8Array(byteString.length);
|
|
for (var 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.
|
|
*/
|
|
|
|
}, {
|
|
key: "getFilesize",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "fileLoaded",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "validate",
|
|
value: function validate() {
|
|
return Utils.bytesToLetters(this.buffer.subarray(0, 4)) === 'MThd';
|
|
}
|
|
|
|
/**
|
|
* Gets MIDI file format for loaded file.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "getFormat",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "getTracks",
|
|
value: function getTracks() {
|
|
this.tracks = [];
|
|
var trackOffset = 0;
|
|
while (trackOffset < this.buffer.length) {
|
|
if (Utils.bytesToLetters(this.buffer.subarray(trackOffset, trackOffset + 4)) == 'MTrk') {
|
|
var 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "enableTrack",
|
|
value: function enableTrack(trackNumber) {
|
|
this.tracks[trackNumber - 1].enable();
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Disables a track for playing.
|
|
* @param {number} - Track number
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "disableTrack",
|
|
value: function disableTrack(trackNumber) {
|
|
this.tracks[trackNumber - 1].disable();
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Gets quarter note division of loaded MIDI file.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "getDivision",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "playLoop",
|
|
value: function 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 {
|
|
var 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)
|
|
*/
|
|
|
|
}, {
|
|
key: "setTempo",
|
|
value: function setTempo(tempo) {
|
|
this.tempo = tempo;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Setter for startTime.
|
|
* @param {number} - UTC timestamp
|
|
*/
|
|
|
|
}, {
|
|
key: "setStartTime",
|
|
value: function setStartTime(startTime) {
|
|
this.startTime = startTime;
|
|
}
|
|
|
|
/**
|
|
* Start playing loaded MIDI file if not already playing.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "play",
|
|
value: function 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 = setInterval(this.playLoop.bind(this), this.sampleRate);
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Pauses playback if playing.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "pause",
|
|
value: function pause() {
|
|
clearInterval(this.setIntervalId);
|
|
this.setIntervalId = false;
|
|
this.startTick = this.tick;
|
|
this.startTime = 0;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Stops playback if playing.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "stop",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "skipToTick",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "skipToPercent",
|
|
value: function 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}
|
|
*/
|
|
|
|
}, {
|
|
key: "skipToSeconds",
|
|
value: function skipToSeconds(seconds) {
|
|
var songTime = this.getSongTime();
|
|
if (seconds < 0 || seconds > songTime) throw seconds + " seconds not within song time of " + songTime;
|
|
this.skipToPercent(seconds / songTime * 100);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Checks if player is playing
|
|
* @return {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "isPlaying",
|
|
value: function isPlaying() {
|
|
return this.setIntervalId > 0 || _typeof(this.setIntervalId) === 'object';
|
|
}
|
|
|
|
/**
|
|
* Plays the loaded MIDI file without regard for timing and saves events in this.events. Essentially used as a parser.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "dryRun",
|
|
value: function dryRun() {
|
|
// Reset tracks first
|
|
this.resetTracks();
|
|
while (!this.endOfFile()) {
|
|
this.playLoop(true);
|
|
}this.events = this.getEvents();
|
|
this.totalEvents = this.getTotalEvents();
|
|
this.totalTicks = this.getTotalTicks();
|
|
this.startTick = 0;
|
|
this.startTime = 0;
|
|
|
|
// Leave tracks in pristine condish
|
|
this.resetTracks();
|
|
|
|
//console.log('Song time: ' + this.getSongTime() + ' seconds / ' + this.totalTicks + ' ticks.');
|
|
|
|
this.triggerPlayerEvent('fileLoaded', this);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Resets play pointers for all tracks.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "resetTracks",
|
|
value: function resetTracks() {
|
|
this.tracks.forEach(function (track) {
|
|
return track.reset();
|
|
});
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Gets an array of events grouped by track.
|
|
* @return {array}
|
|
*/
|
|
|
|
}, {
|
|
key: "getEvents",
|
|
value: function getEvents() {
|
|
return this.tracks.map(function (track) {
|
|
return track.events;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Gets total number of ticks in the loaded MIDI file.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getTotalTicks",
|
|
value: function getTotalTicks() {
|
|
return Math.max.apply(null, this.tracks.map(function (track) {
|
|
return track.delta;
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Gets total number of events in the loaded MIDI file.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getTotalEvents",
|
|
value: function getTotalEvents() {
|
|
return this.tracks.reduce(function (a, b) {
|
|
return { events: { length: a.events.length + b.events.length } };
|
|
}, { events: { length: 0 } }).events.length;
|
|
}
|
|
|
|
/**
|
|
* Gets song duration in seconds.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getSongTime",
|
|
value: function getSongTime() {
|
|
return this.totalTicks / this.division / this.tempo * 60;
|
|
}
|
|
|
|
/**
|
|
* Gets remaining number of seconds in playback.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getSongTimeRemaining",
|
|
value: function getSongTimeRemaining() {
|
|
return Math.round((this.totalTicks - this.tick) / this.division / this.tempo * 60);
|
|
}
|
|
|
|
/**
|
|
* Gets remaining percent of playback.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getSongPercentRemaining",
|
|
value: function getSongPercentRemaining() {
|
|
return Math.round(this.getSongTimeRemaining() / this.getSongTime() * 100);
|
|
}
|
|
|
|
/**
|
|
* Number of bytes processed in the loaded MIDI file.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "bytesProcessed",
|
|
value: function bytesProcessed() {
|
|
// Currently assume header chunk is strictly 14 bytes
|
|
return 14 + this.tracks.length * 8 + this.tracks.reduce(function (a, b) {
|
|
return { pointer: a.pointer + b.pointer };
|
|
}, { pointer: 0 }).pointer;
|
|
}
|
|
|
|
/**
|
|
* Number of events played up to this point.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "eventsPlayed",
|
|
value: function eventsPlayed() {
|
|
return this.tracks.reduce(function (a, b) {
|
|
return { eventIndex: a.eventIndex + b.eventIndex };
|
|
}, { eventIndex: 0 }).eventIndex;
|
|
}
|
|
|
|
/**
|
|
* Determines if the player pointer has reached the end of the loaded MIDI file.
|
|
* Used in two ways:
|
|
* 1. If playing result is based on loaded JSON events.
|
|
* 2. If parsing (dryRun) it's based on the actual buffer length vs bytes processed.
|
|
* @return {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "endOfFile",
|
|
value: function endOfFile() {
|
|
if (this.isPlaying()) {
|
|
return this.eventsPlayed() == this.totalEvents;
|
|
}
|
|
|
|
return this.bytesProcessed() == this.buffer.length;
|
|
}
|
|
|
|
/**
|
|
* Gets the current tick number in playback.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getCurrentTick",
|
|
value: function getCurrentTick() {
|
|
return Math.round((new Date().getTime() - this.startTime) / 1000 * (this.division * (this.tempo / 60))) + this.startTick;
|
|
}
|
|
|
|
/**
|
|
* Sends MIDI event out to listener.
|
|
* @param {object}
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "emitEvent",
|
|
value: function emitEvent(event) {
|
|
this.triggerPlayerEvent('midiEvent', event);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Subscribes events to listeners
|
|
* @param {string} - Name of event to subscribe to.
|
|
* @param {function} - Callback to fire when event is broadcast.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "on",
|
|
value: function on(playerEvent, fn) {
|
|
if (!this.eventListeners.hasOwnProperty(playerEvent)) this.eventListeners[playerEvent] = [];
|
|
this.eventListeners[playerEvent].push(fn);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Broadcasts event to trigger subscribed callbacks.
|
|
* @param {string} - Name of event.
|
|
* @param {object} - Data to be passed to subscriber callback.
|
|
* @return {Player}
|
|
*/
|
|
|
|
}, {
|
|
key: "triggerPlayerEvent",
|
|
value: function triggerPlayerEvent(playerEvent, data) {
|
|
if (this.eventListeners.hasOwnProperty(playerEvent)) this.eventListeners[playerEvent].forEach(function (fn) {
|
|
return fn(data || {});
|
|
});
|
|
return this;
|
|
}
|
|
}]);
|
|
|
|
return Player;
|
|
}();
|
|
|
|
exports.Player = Player;
|
|
|
|
},{"./track":7,"./utils":8,"fs":"fs"}],7:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
var Constants = require("./constants").Constants;
|
|
var Utils = require("./utils").Utils;
|
|
|
|
/**
|
|
* Class representing a track. Contains methods for parsing events and keeping track of pointer.
|
|
*/
|
|
|
|
var Track = function () {
|
|
function Track(index, data) {
|
|
_classCallCheck(this, Track);
|
|
|
|
this.enabled = true;
|
|
this.eventIndex = 0;
|
|
this.pointer = 0;
|
|
this.lastTick = 0;
|
|
this.lastStatus = null;
|
|
this.index = index;
|
|
this.data = data;
|
|
this.delta = 0;
|
|
this.runningDelta = 0;
|
|
this.events = [];
|
|
}
|
|
|
|
/**
|
|
* Resets all stateful track informaion used during playback.
|
|
* @return {Track}
|
|
*/
|
|
|
|
|
|
_createClass(Track, [{
|
|
key: "reset",
|
|
value: function reset() {
|
|
this.enabled = true;
|
|
this.eventIndex = 0;
|
|
this.pointer = 0;
|
|
this.lastTick = 0;
|
|
this.lastStatus = null;
|
|
this.delta = 0;
|
|
this.runningDelta = 0;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets this track to be enabled during playback.
|
|
* @return {Track}
|
|
*/
|
|
|
|
}, {
|
|
key: "enable",
|
|
value: function enable() {
|
|
this.enabled = true;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets this track to be disabled during playback.
|
|
* @return {Track}
|
|
*/
|
|
|
|
}, {
|
|
key: "disable",
|
|
value: function disable() {
|
|
this.enabled = false;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the track event index to the nearest event to the given tick.
|
|
* @param {number} tick
|
|
* @return {Track}
|
|
*/
|
|
|
|
}, {
|
|
key: "setEventIndexByTick",
|
|
value: function setEventIndexByTick(tick) {
|
|
tick = tick || 0;
|
|
|
|
for (var i in this.events) {
|
|
if (this.events[i].tick >= tick) {
|
|
this.eventIndex = i;
|
|
return this;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets byte located at pointer position.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getCurrentByte",
|
|
value: function getCurrentByte() {
|
|
return this.data[this.pointer];
|
|
}
|
|
|
|
/**
|
|
* Gets count of delta bytes and current pointer position.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getDeltaByteCount",
|
|
value: function getDeltaByteCount() {
|
|
// Get byte count of delta VLV
|
|
// http://www.ccarh.org/courses/253/handout/vlv/
|
|
// If byte is greater or equal to 80h (128 decimal) then the next byte
|
|
// is also part of the VLV,
|
|
// else byte is the last byte in a VLV.
|
|
var currentByte = this.getCurrentByte();
|
|
var byteCount = 1;
|
|
|
|
while (currentByte >= 128) {
|
|
currentByte = this.data[this.pointer + byteCount];
|
|
byteCount++;
|
|
}
|
|
|
|
return byteCount;
|
|
}
|
|
|
|
/**
|
|
* Get delta value at current pointer position.
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: "getDelta",
|
|
value: function getDelta() {
|
|
return Utils.readVarInt(this.data.subarray(this.pointer, this.pointer + this.getDeltaByteCount()));
|
|
}
|
|
|
|
/**
|
|
* Handles event within a given track starting at specified index
|
|
* @param {number} currentTick
|
|
* @param {boolean} dryRun - If true events will be parsed and returned regardless of time.
|
|
*/
|
|
|
|
}, {
|
|
key: "handleEvent",
|
|
value: function handleEvent(currentTick, dryRun) {
|
|
dryRun = dryRun || false;
|
|
|
|
if (dryRun) {
|
|
var elapsedTicks = currentTick - this.lastTick;
|
|
var delta = this.getDelta();
|
|
var eventReady = elapsedTicks >= delta;
|
|
|
|
if (this.pointer < this.data.length && (dryRun || eventReady)) {
|
|
var _event = this.parseEvent();
|
|
if (this.enabled) return _event;
|
|
// Recursively call this function for each event ahead that has 0 delta time?
|
|
}
|
|
} else {
|
|
// Let's actually play the MIDI from the generated JSON events created by the dry run.
|
|
if (this.events[this.eventIndex] && this.events[this.eventIndex].tick <= currentTick) {
|
|
this.eventIndex++;
|
|
if (this.enabled) return this.events[this.eventIndex - 1];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get string data from event.
|
|
* @param {number} eventStartIndex
|
|
* @return {string}
|
|
*/
|
|
|
|
}, {
|
|
key: "getStringData",
|
|
value: function getStringData(eventStartIndex) {
|
|
var currentByte = this.pointer;
|
|
var byteCount = 1;
|
|
var length = Utils.readVarInt(this.data.subarray(eventStartIndex + 2, eventStartIndex + 2 + byteCount));
|
|
var stringLength = length;
|
|
|
|
return Utils.bytesToLetters(this.data.subarray(eventStartIndex + byteCount + 2, eventStartIndex + byteCount + length + 2));
|
|
}
|
|
|
|
/**
|
|
* Parses event into JSON and advances pointer for the track
|
|
* @return {object}
|
|
*/
|
|
|
|
}, {
|
|
key: "parseEvent",
|
|
value: function parseEvent() {
|
|
var eventStartIndex = this.pointer + this.getDeltaByteCount();
|
|
var eventJson = {};
|
|
var deltaByteCount = this.getDeltaByteCount();
|
|
eventJson.track = this.index + 1;
|
|
eventJson.delta = this.getDelta();
|
|
this.lastTick = this.lastTick + eventJson.delta;
|
|
this.runningDelta += eventJson.delta;
|
|
eventJson.tick = this.runningDelta;
|
|
eventJson.byteIndex = this.pointer;
|
|
|
|
//eventJson.raw = event;
|
|
if (this.data[eventStartIndex] == 0xff) {
|
|
// Meta Event
|
|
|
|
// If this is a meta event we should emit the data and immediately move to the next event
|
|
// otherwise if we let it run through the next cycle a slight delay will accumulate if multiple tracks
|
|
// are being played simultaneously
|
|
|
|
switch (this.data[eventStartIndex + 1]) {
|
|
case 0x00:
|
|
// Sequence Number
|
|
eventJson.name = 'Sequence Number';
|
|
break;
|
|
case 0x01:
|
|
// Text Event
|
|
eventJson.name = 'Text Event';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x02:
|
|
// Copyright Notice
|
|
eventJson.name = 'Copyright Notice';
|
|
break;
|
|
case 0x03:
|
|
// Sequence/Track Name
|
|
eventJson.name = 'Sequence/Track Name';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x04:
|
|
// Instrument Name
|
|
eventJson.name = 'Instrument Name';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x05:
|
|
// Lyric
|
|
eventJson.name = 'Lyric';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x06:
|
|
// Marker
|
|
eventJson.name = 'Marker';
|
|
break;
|
|
case 0x07:
|
|
// Cue Point
|
|
eventJson.name = 'Cue Point';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x09:
|
|
// Device Name
|
|
eventJson.name = 'Device Name';
|
|
eventJson.string = this.getStringData(eventStartIndex);
|
|
break;
|
|
case 0x20:
|
|
// MIDI Channel Prefix
|
|
eventJson.name = 'MIDI Channel Prefix';
|
|
break;
|
|
case 0x21:
|
|
// MIDI Port
|
|
eventJson.name = 'MIDI Port';
|
|
eventJson.data = Utils.bytesToNumber([this.data[eventStartIndex + 3]]);
|
|
break;
|
|
case 0x2F:
|
|
// End of Track
|
|
eventJson.name = 'End of Track';
|
|
break;
|
|
case 0x51:
|
|
// Set Tempo
|
|
eventJson.name = 'Set Tempo';
|
|
eventJson.data = Math.round(60000000 / Utils.bytesToNumber(this.data.subarray(eventStartIndex + 3, eventStartIndex + 6)));
|
|
this.tempo = eventJson.data;
|
|
break;
|
|
case 0x54:
|
|
// SMTPE Offset
|
|
eventJson.name = 'SMTPE Offset';
|
|
break;
|
|
case 0x58:
|
|
// Time Signature
|
|
// 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(eventJson.data[1], 2);
|
|
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;
|
|
}
|
|
|
|
var length = this.data[this.pointer + deltaByteCount + 2];
|
|
// Some meta events will have vlv that needs to be handled
|
|
|
|
this.pointer += deltaByteCount + 3 + length;
|
|
} else if (this.data[eventStartIndex] == 0xf0) {
|
|
// Sysex
|
|
eventJson.name = 'Sysex';
|
|
var length = this.data[this.pointer + deltaByteCount + 1];
|
|
this.pointer += deltaByteCount + 2 + length;
|
|
} else {
|
|
// Voice event
|
|
if (this.data[eventStartIndex] < 0x80) {
|
|
// Running status
|
|
eventJson.running = true;
|
|
eventJson.noteNumber = this.data[eventStartIndex];
|
|
eventJson.noteName = Constants.NOTES[this.data[eventStartIndex]];
|
|
eventJson.velocity = this.data[eventStartIndex + 1];
|
|
|
|
if (this.lastStatus <= 0x8f) {
|
|
eventJson.name = 'Note off';
|
|
eventJson.channel = this.lastStatus - 0x80 + 1;
|
|
} else if (this.lastStatus <= 0x9f) {
|
|
eventJson.name = 'Note on';
|
|
eventJson.channel = this.lastStatus - 0x90 + 1;
|
|
}
|
|
|
|
this.pointer += deltaByteCount + 2;
|
|
} else {
|
|
this.lastStatus = this.data[eventStartIndex];
|
|
|
|
if (this.data[eventStartIndex] <= 0x8f) {
|
|
// Note off
|
|
eventJson.name = 'Note off';
|
|
eventJson.channel = this.lastStatus - 0x80 + 1;
|
|
eventJson.noteNumber = this.data[eventStartIndex + 1];
|
|
eventJson.noteName = Constants.NOTES[this.data[eventStartIndex + 1]];
|
|
eventJson.velocity = Math.round(this.data[eventStartIndex + 2] / 127 * 100);
|
|
this.pointer += deltaByteCount + 3;
|
|
} else if (this.data[eventStartIndex] <= 0x9f) {
|
|
// Note on
|
|
eventJson.name = 'Note on';
|
|
eventJson.channel = this.lastStatus - 0x90 + 1;
|
|
eventJson.noteNumber = this.data[eventStartIndex + 1];
|
|
eventJson.noteName = Constants.NOTES[this.data[eventStartIndex + 1]];
|
|
eventJson.velocity = Math.round(this.data[eventStartIndex + 2] / 127 * 100);
|
|
this.pointer += deltaByteCount + 3;
|
|
} else if (this.data[eventStartIndex] <= 0xaf) {
|
|
// Polyphonic Key Pressure
|
|
eventJson.name = 'Polyphonic Key Pressure';
|
|
eventJson.channel = this.lastStatus - 0xa0 + 1;
|
|
eventJson.note = Constants.NOTES[this.data[eventStartIndex + 1]];
|
|
eventJson.pressure = event[2];
|
|
this.pointer += deltaByteCount + 3;
|
|
} else if (this.data[eventStartIndex] <= 0xbf) {
|
|
// Controller Change
|
|
eventJson.name = 'Controller Change';
|
|
eventJson.channel = this.lastStatus - 0xb0 + 1;
|
|
eventJson.number = this.data[eventStartIndex + 1];
|
|
eventJson.value = this.data[eventStartIndex + 2];
|
|
this.pointer += deltaByteCount + 3;
|
|
} else if (this.data[eventStartIndex] <= 0xcf) {
|
|
// Program Change
|
|
eventJson.name = 'Program Change';
|
|
eventJson.channel = this.lastStatus - 0xc0 + 1;
|
|
eventJson.value = this.data[eventStartIndex + 1];
|
|
this.pointer += deltaByteCount + 2;
|
|
} else if (this.data[eventStartIndex] <= 0xdf) {
|
|
// Channel Key Pressure
|
|
eventJson.name = 'Channel Key Pressure';
|
|
eventJson.channel = this.lastStatus - 0xd0 + 1;
|
|
this.pointer += deltaByteCount + 2;
|
|
} else if (this.data[eventStartIndex] <= 0xef) {
|
|
// Pitch Bend
|
|
eventJson.name = 'Pitch Bend';
|
|
eventJson.channel = this.lastStatus - 0xe0 + 1;
|
|
this.pointer += deltaByteCount + 3;
|
|
} else {
|
|
eventJson.name = 'Unknown. Pointer: ' + this.pointer.toString() + ' ' + eventStartIndex.toString() + ' ' + this.data.length;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.delta += eventJson.delta;
|
|
this.events.push(eventJson);
|
|
|
|
return eventJson;
|
|
}
|
|
|
|
/**
|
|
* Returns true if pointer has reached the end of the track.
|
|
* @param {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "endOfTrack",
|
|
value: function endOfTrack() {
|
|
if (this.data[this.pointer + 1] == 0xff && this.data[this.pointer + 2] == 0x2f && this.data[this.pointer + 3] == 0x00) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}]);
|
|
|
|
return Track;
|
|
}();
|
|
|
|
module.exports.Track = Track;
|
|
|
|
},{"./constants":4,"./utils":8}],8:[function(require,module,exports){
|
|
(function (Buffer){
|
|
'use strict';
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/**
|
|
* Contains misc static utility methods.
|
|
*/
|
|
var Utils = function () {
|
|
function Utils() {
|
|
_classCallCheck(this, Utils);
|
|
}
|
|
|
|
_createClass(Utils, null, [{
|
|
key: 'byteToHex',
|
|
|
|
|
|
/**
|
|
* Converts a single byte to a hex string.
|
|
* @param {number} byte
|
|
* @return {string}
|
|
*/
|
|
value: function byteToHex(byte) {
|
|
// Ensure hex string always has two chars
|
|
return ('0' + byte.toString(16)).slice(-2);
|
|
}
|
|
|
|
/**
|
|
* Converts an array of bytes to a hex string.
|
|
* @param {array} byteArray
|
|
* @return {string}
|
|
*/
|
|
|
|
}, {
|
|
key: 'bytesToHex',
|
|
value: function bytesToHex(byteArray) {
|
|
var hex = [];
|
|
byteArray.forEach(function (byte) {
|
|
return hex.push(Utils.byteToHex(byte));
|
|
});
|
|
return hex.join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a hex string to a number.
|
|
* @param {string} hexString
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: 'hexToNumber',
|
|
value: function hexToNumber(hexString) {
|
|
return parseInt(hexString, 16);
|
|
}
|
|
|
|
/**
|
|
* Converts an array of bytes to a number.
|
|
* @param {array} byteArray
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: 'bytesToNumber',
|
|
value: function bytesToNumber(byteArray) {
|
|
return Utils.hexToNumber(Utils.bytesToHex(byteArray));
|
|
}
|
|
|
|
/**
|
|
* Converts an array of bytes to letters.
|
|
* @param {array} byteArray
|
|
* @return {string}
|
|
*/
|
|
|
|
}, {
|
|
key: 'bytesToLetters',
|
|
value: function bytesToLetters(byteArray) {
|
|
var letters = [];
|
|
byteArray.forEach(function (byte) {
|
|
return letters.push(String.fromCharCode(byte));
|
|
});
|
|
return letters.join('');
|
|
}
|
|
|
|
/**
|
|
* Converts a decimal to it's binary representation.
|
|
* @param {number} dec
|
|
* @return {string}
|
|
*/
|
|
|
|
}, {
|
|
key: 'decToBinary',
|
|
value: function decToBinary(dec) {
|
|
return (dec >>> 0).toString(2);
|
|
}
|
|
|
|
/**
|
|
* Reads a variable length value.
|
|
* @param {array} byteArray
|
|
* @return {number}
|
|
*/
|
|
|
|
}, {
|
|
key: 'readVarInt',
|
|
value: function readVarInt(byteArray) {
|
|
var result = 0;
|
|
byteArray.forEach(function (number) {
|
|
var b = number;
|
|
if (b & 0x80) {
|
|
result += b & 0x7f;
|
|
result <<= 7;
|
|
} else {
|
|
/* b is the last byte */
|
|
result += b;
|
|
}
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Decodes base-64 encoded string
|
|
* @param {string} string
|
|
* @return {string}
|
|
*/
|
|
|
|
}, {
|
|
key: 'atob',
|
|
value: function (_atob) {
|
|
function atob(_x) {
|
|
return _atob.apply(this, arguments);
|
|
}
|
|
|
|
atob.toString = function () {
|
|
return _atob.toString();
|
|
};
|
|
|
|
return atob;
|
|
}(function (string) {
|
|
if (typeof atob === 'function') return atob(string);
|
|
return new Buffer(string, 'base64').toString('binary');
|
|
})
|
|
}]);
|
|
|
|
return Utils;
|
|
}();
|
|
|
|
exports.Utils = Utils;
|
|
|
|
}).call(this,require("buffer").Buffer)
|
|
|
|
},{"buffer":2}]},{},[5])(5)
|
|
});
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYmFzZTY0LWpzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzIiwic3JjL2NvbnN0YW50cy5qcyIsInNyYy9pbmRleC5qcyIsInNyYy9wbGF5ZXIuanMiLCJzcmMvdHJhY2suanMiLCJzcmMvdXRpbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcEZBOzs7QUFHQSxJQUFJLFlBQVk7QUFDZixVQUFTLE9BRE07QUFFZixRQUFPLEVBRlE7QUFHZixvQkFBbUIsQ0FBQyxHQUFELEVBQU0sR0FBTixFQUFXLElBQVgsRUFBaUIsSUFBakIsRUFBdUIsSUFBdkIsRUFBNkIsSUFBN0IsRUFBbUMsSUFBbkMsRUFBeUMsSUFBekMsRUFBK0MsSUFBL0MsRUFBcUQsS0FBckQsRUFBNEQsS0FBNUQsRUFBbUUsS0FBbkUsQ0FISjtBQUlmLG1CQUFrQixDQUFDLEdBQUQsRUFBTSxHQUFOLEVBQVcsR0FBWCxFQUFnQixHQUFoQixFQUFxQixHQUFyQixFQUEwQixHQUExQixFQUErQixJQUEvQixFQUFxQyxJQUFyQyxFQUEyQyxJQUEzQyxFQUFpRCxJQUFqRCxFQUF1RCxJQUF2RCxFQUE2RCxJQUE3RDtBQUpILENBQWhCOztBQU9BO0FBQ0EsSUFBSSxXQUFXLENBQUMsQ0FBQyxHQUFELENBQUQsRUFBUSxDQUFDLElBQUQsRUFBTSxJQUFOLENBQVIsRUFBcUIsQ0FBQyxHQUFELENBQXJCLEVBQTRCLENBQUMsSUFBRCxFQUFNLElBQU4sQ0FBNUIsRUFBeUMsQ0FBQyxHQUFELENBQXpDLEVBQStDLENBQUMsR0FBRCxDQUEvQyxFQUFzRCxDQUFDLElBQUQsRUFBTSxJQUFOLENBQXRELEVBQW1FLENBQUMsR0FBRCxDQUFuRSxFQUEwRSxDQUFDLElBQUQsRUFBTSxJQUFOLENBQTFFLEVBQXVGLENBQUMsR0FBRCxDQUF2RixFQUE4RixDQUFDLElBQUQsRUFBTSxJQUFOLENBQTlGLEVBQTJHLENBQUMsR0FBRCxDQUEzRyxDQUFmO0FBQ0EsSUFBSSxVQUFVLENBQWQ7O0FBRUE7OzJCQUNTLEM7QUFDUixVQUFTLE9BQVQsQ0FBaUIscUJBQWE7QUFDN0IsWUFBVSxPQUFWLENBQWtCO0FBQUEsVUFBUSxVQUFVLEtBQVYsQ0FBZ0IsT0FBaEIsSUFBMkIsT0FBTyxDQUExQztBQUFBLEdBQWxCO0FBQ0E7QUFDQSxFQUhEOzs7QUFERCxLQUFLLElBQUksSUFBSSxDQUFDLENBQWQsRUFBaUIsS0FBSyxDQUF0QixFQUF5QixHQUF6QixFQUE4QjtBQUFBLE9BQXJCLENBQXFCO0FBSzdCOztBQUVELFFBQVEsU0FBUixHQUFvQixTQUFwQjs7Ozs7QUN0QkEsSUFBTSxTQUFTLFFBQVEsVUFBUixDQUFmO0FBQ0EsSUFBTSxRQUFRLFFBQVEsU0FBUixDQUFkO0FBQ0EsSUFBTSxZQUFZLFFBQVEsYUFBUixDQUFsQjs7QUFFQSxPQUFPLE9BQVAsR0FBaUI7QUFDYixZQUFPLE9BQU8sTUFERDtBQUViLFdBQU0sTUFBTSxLQUZDO0FBR2IsZUFBVSxVQUFVO0FBSFAsQ0FBakI7Ozs7Ozs7Ozs7O0FDSkEsSUFBTSxRQUFRLFFBQVEsU0FBUixFQUFtQixLQUFqQztBQUNBLElBQU0sUUFBUSxRQUFRLFNBQVIsRUFBbUIsS0FBakM7O0FBRUE7QUFDQSxJQUFJLENBQUMsV0FBVyxTQUFYLENBQXFCLE9BQTFCLEVBQW1DO0FBQ2xDLFFBQU8sY0FBUCxDQUFzQixXQUFXLFNBQWpDLEVBQTRDLFNBQTVDLEVBQXVEO0FBQ3RELFNBQU8sTUFBTSxTQUFOLENBQWdCO0FBRCtCLEVBQXZEO0FBR0E7O0FBRUQ7Ozs7OztJQUtNLE07QUFDTCxpQkFBWSxZQUFaLEVBQTBCLE1BQTFCLEVBQWtDO0FBQUE7O0FBQ2pDLE9BQUssVUFBTCxHQUFrQixDQUFsQixDQURpQyxDQUNaO0FBQ3JCLE9BQUssU0FBTCxHQUFpQixDQUFqQjtBQUNBLE9BQUssTUFBTCxHQUFjLFVBQVUsSUFBeEI7QUFDQSxPQUFLLFFBQUw7QUFDQSxPQUFLLE1BQUw7QUFDQSxPQUFLLGFBQUwsR0FBcUIsS0FBckI7QUFDQSxPQUFLLE1BQUwsR0FBYyxFQUFkO0FBQ0EsT0FBSyxXQUFMLEdBQW1CLEVBQW5CO0FBQ0EsT0FBSyxZQUFMLEdBQW9CLEdBQXBCO0FBQ0EsT0FBSyxLQUFMLEdBQWEsSUFBYjtBQUNBLE9BQUssU0FBTCxHQUFpQixDQUFqQjtBQUNBLE9BQUssSUFBTCxHQUFZLENBQVo7QUFDQSxPQUFLLFFBQUwsR0FBZ0IsSUFBaEI7QUFDQSxPQUFLLE1BQUwsR0FBYyxLQUFkO0FBQ0EsT0FBSyxVQUFMLEdBQWtCLENBQWxCO0FBQ0EsT0FBSyxNQUFMLEdBQWMsRUFBZDtBQUNBLE9BQUssV0FBTCxHQUFtQixDQUFuQjtBQUNBLE9BQUssY0FBTCxHQUFzQixFQUF0Qjs7QUFFQSxNQUFJLE9BQU8sWUFBUCxLQUF5QixVQUE3QixFQUF5QyxLQUFLLEVBQUwsQ0FBUSxXQUFSLEVBQXFCLFlBQXJCO0FBQ3pDOztBQUVEOzs7Ozs7Ozs7MkJBS1MsSSxFQUFNO0FBQ2QsT0FBSSxLQUFLLFFBQVEsSUFBUixDQUFUO0FBQ0EsUUFBSyxNQUFMLEdBQWMsR0FBRyxZQUFILENBQWdCLElBQWhCLENBQWQ7QUFDQSxVQUFPLEtBQUssVUFBTCxFQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7O2tDQUtnQixXLEVBQWE7QUFDNUIsUUFBSyxNQUFMLEdBQWMsSUFBSSxVQUFKLENBQWUsV0FBZixDQUFkO0FBQ0EsVUFBTyxLQUFLLFVBQUwsRUFBUDtBQUNBOztBQUVEOzs7Ozs7Ozs4QkFLWSxPLEVBQVM7QUFDcEI7QUFDQTtBQUNBLE9BQUksYUFBYSxNQUFNLElBQU4sQ0FBVyxRQUFRLEtBQVIsQ0FBYyxHQUFkLEVBQW1CLENBQW5CLENBQVgsQ0FBakI7O0FBRUE7QUFDQSxPQUFJLEtBQUssSUFBSSxVQUFKLENBQWUsV0FBVyxNQUExQixDQUFUO0FBQ0EsUUFBSyxJQUFJLElBQUksQ0FBYixFQUFnQixJQUFJLFdBQVcsTUFBL0IsRUFBdUMsR0FBdkMsRUFBNEM7QUFDM0MsT0FBRyxDQUFILElBQVEsV0FBVyxVQUFYLENBQXNCLENBQXRCLENBQVI7QUFDQTs7QUFFRCxRQUFLLE1BQUwsR0FBYyxFQUFkO0FBQ0EsVUFBTyxLQUFLLFVBQUwsRUFBUDtBQUNBOztBQUVEOzs7Ozs7O2dDQUljO0FBQ2IsVUFBTyxLQUFLLE1BQUwsR0FBYyxLQUFLLE1BQUwsQ0FBWSxNQUExQixHQUFtQyxDQUExQztBQUNBOztBQUVEOzs7Ozs7OzsrQkFLYTtBQUNaLE9BQUksQ0FBQyxLQUFLLFFBQUwsRUFBTCxFQUFzQixNQUFNLDJDQUFOO0FBQ3RCLFVBQU8sS0FBSyxRQUFMLENBQWMsS0FBSyxZQUFuQixFQUFpQyxXQUFqQyxHQUErQyxTQUEvQyxHQUEyRCxTQUEzRCxHQUF1RSxNQUF2RSxFQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7NkJBSVc7QUFDVixVQUFPLE1BQU0sY0FBTixDQUFxQixLQUFLLE1BQUwsQ0FBWSxRQUFaLENBQXFCLENBQXJCLEVBQXdCLENBQXhCLENBQXJCLE1BQXFELE1BQTVEO0FBQ0E7O0FBRUQ7Ozs7Ozs7OEJBSVk7QUFDWDs7Ozs7Ozs7OztBQVVBLFFBQUssTUFBTCxHQUFjLE1BQU0sYUFBTixDQUFvQixLQUFLLE1BQUwsQ0FBWSxRQUFaLENBQXFCLENBQXJCLEVBQXdCLEVBQXhCLENBQXBCLENBQWQ7QUFDQSxVQUFPLElBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs4QkFJWTtBQUNYLFFBQUssTUFBTCxHQUFjLEVBQWQ7QUFDQSxPQUFJLGNBQWMsQ0FBbEI7QUFDQSxVQUFPLGNBQWMsS0FBSyxNQUFMLENBQVksTUFBakMsRUFBeUM7QUFDeEMsUUFBSSxNQUFNLGNBQU4sQ0FBcUIsS0FBSyxNQUFMLENBQVksUUFBWixDQUFxQixXQUFyQixFQUFrQyxjQUFjLENBQWhELENBQXJCLEtBQTRFLE1BQWhGLEVBQXdGO0FBQ3ZGLFNBQUksY0FBYyxNQUFNLGFBQU4sQ0FBb0IsS0FBSyxNQUFMLENBQVksUUFBWixDQUFxQixjQUFjLENBQW5DLEVBQXNDLGNBQWMsQ0FBcEQsQ0FBcEIsQ0FBbEI7QUFDQSxVQUFLLE1BQUwsQ0FBWSxJQUFaLENBQWlCLElBQUksS0FBSixDQUFVLEtBQUssTUFBTCxDQUFZLE1BQXRCLEVBQThCLEtBQUssTUFBTCxDQUFZLFFBQVosQ0FBcUIsY0FBYyxDQUFuQyxFQUFzQyxjQUFjLENBQWQsR0FBa0IsV0FBeEQsQ0FBOUIsQ0FBakI7QUFDQTs7QUFFRCxtQkFBZSxNQUFNLGFBQU4sQ0FBb0IsS0FBSyxNQUFMLENBQVksUUFBWixDQUFxQixjQUFjLENBQW5DLEVBQXNDLGNBQWMsQ0FBcEQsQ0FBcEIsSUFBOEUsQ0FBN0Y7QUFDQTtBQUNELFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7Ozs4QkFLWSxXLEVBQWE7QUFDeEIsUUFBSyxNQUFMLENBQVksY0FBYyxDQUExQixFQUE2QixNQUE3QjtBQUNBLFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7OzsrQkFLYSxXLEVBQWE7QUFDekIsUUFBSyxNQUFMLENBQVksY0FBYyxDQUExQixFQUE2QixPQUE3QjtBQUNBLFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7O2dDQUljO0FBQ2IsUUFBSyxRQUFMLEdBQWdCLE1BQU0sYUFBTixDQUFvQixLQUFLLE1BQUwsQ0FBWSxRQUFaLENBQXFCLEVBQXJCLEVBQXlCLEVBQXpCLENBQXBCLENBQWhCO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzJCQUtTLE0sRUFBUTtBQUNoQixPQUFJLENBQUMsS0FBSyxNQUFWLEVBQWtCO0FBQ2pCLFNBQUssTUFBTCxHQUFjLElBQWQ7QUFDQSxTQUFLLElBQUwsR0FBWSxLQUFLLGNBQUwsRUFBWjs7QUFFQSxTQUFLLE1BQUwsQ0FBWSxPQUFaLENBQW9CLFVBQVMsS0FBVCxFQUFnQjtBQUNuQztBQUNBLFNBQUksQ0FBQyxNQUFELElBQVcsS0FBSyxTQUFMLEVBQWYsRUFBaUM7QUFDaEM7QUFDQSxXQUFLLGtCQUFMLENBQXdCLFdBQXhCO0FBQ0EsV0FBSyxJQUFMO0FBQ0EsTUFKRCxNQUlPO0FBQ04sVUFBSSxRQUFRLE1BQU0sV0FBTixDQUFrQixLQUFLLElBQXZCLEVBQTZCLE1BQTdCLENBQVo7O0FBRUEsVUFBSSxVQUFVLEtBQWQsRUFBcUI7QUFDcEIsV0FBSSxNQUFNLGNBQU4sQ0FBcUIsTUFBckIsS0FBZ0MsTUFBTSxJQUFOLEtBQWUsV0FBbkQsRUFBZ0U7QUFDL0Q7QUFDQSxhQUFLLFFBQUwsQ0FBYyxNQUFNLElBQXBCO0FBQ0E7QUFDRCxXQUFJLE1BQU0sY0FBTixDQUFxQixNQUFyQixLQUFnQyxNQUFNLElBQU4sS0FBZSxnQkFBbkQsRUFBcUU7QUFDcEUsWUFBSSxDQUFDLEtBQUssV0FBTCxDQUFpQixRQUFqQixDQUEwQixNQUFNLEtBQWhDLENBQUwsRUFBNkM7QUFDNUMsY0FBSyxXQUFMLENBQWlCLElBQWpCLENBQXNCLE1BQU0sS0FBNUI7QUFDQTtBQUNEO0FBQ0QsT0FWRCxNQVVPLElBQUksS0FBSixFQUFXLEtBQUssU0FBTCxDQUFlLEtBQWY7QUFDbEI7QUFFRCxLQXRCRCxFQXNCRyxJQXRCSDs7QUF3QkEsUUFBSSxDQUFDLE1BQUwsRUFBYSxLQUFLLGtCQUFMLENBQXdCLFNBQXhCLEVBQW1DLEVBQUMsTUFBTSxLQUFLLElBQVosRUFBbkM7QUFDYixTQUFLLE1BQUwsR0FBYyxLQUFkO0FBQ0E7QUFDRDs7QUFFRDs7Ozs7OzsyQkFJUyxLLEVBQU87QUFDZixRQUFLLEtBQUwsR0FBYSxLQUFiO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7K0JBSWEsUyxFQUFXO0FBQ3ZCLFFBQUssU0FBTCxHQUFpQixTQUFqQjtBQUNBOztBQUVEOzs7Ozs7O3lCQUlPO0FBQ04sT0FBSSxLQUFLLFNBQUwsRUFBSixFQUFzQixNQUFNLG9CQUFOOztBQUV0QjtBQUNBLE9BQUksQ0FBQyxLQUFLLFNBQVYsRUFBcUIsS0FBSyxTQUFMLEdBQWtCLElBQUksSUFBSixFQUFELENBQWEsT0FBYixFQUFqQjs7QUFFckI7QUFDQTtBQUNBLFFBQUssYUFBTCxHQUFxQixZQUFZLEtBQUssUUFBTCxDQUFjLElBQWQsQ0FBbUIsSUFBbkIsQ0FBWixFQUFzQyxLQUFLLFVBQTNDLENBQXJCOztBQUVBLFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7OzBCQUlRO0FBQ1AsaUJBQWMsS0FBSyxhQUFuQjtBQUNBLFFBQUssYUFBTCxHQUFxQixLQUFyQjtBQUNBLFFBQUssU0FBTCxHQUFpQixLQUFLLElBQXRCO0FBQ0EsUUFBSyxTQUFMLEdBQWlCLENBQWpCO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7eUJBSU87QUFDTixpQkFBYyxLQUFLLGFBQW5CO0FBQ0EsUUFBSyxhQUFMLEdBQXFCLEtBQXJCO0FBQ0EsUUFBSyxTQUFMLEdBQWlCLENBQWpCO0FBQ0EsUUFBSyxTQUFMLEdBQWlCLENBQWpCO0FBQ0EsUUFBSyxXQUFMO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzZCQUtXLEksRUFBTTtBQUNoQixRQUFLLElBQUw7QUFDQSxRQUFLLFNBQUwsR0FBaUIsSUFBakI7O0FBRUE7QUFDQSxRQUFLLE1BQUwsQ0FBWSxPQUFaLENBQW9CLFVBQVMsS0FBVCxFQUFnQjtBQUNuQyxVQUFNLG1CQUFOLENBQTBCLElBQTFCO0FBQ0EsSUFGRDtBQUdBLFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7OztnQ0FLYyxPLEVBQVM7QUFDdEIsT0FBSSxVQUFVLENBQVYsSUFBZSxVQUFVLEdBQTdCLEVBQWtDLE1BQU0sMkNBQU47QUFDbEMsUUFBSyxVQUFMLENBQWdCLEtBQUssS0FBTCxDQUFXLFVBQVUsR0FBVixHQUFnQixLQUFLLFVBQWhDLENBQWhCO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7O2dDQUtjLE8sRUFBUztBQUN0QixPQUFJLFdBQVcsS0FBSyxXQUFMLEVBQWY7QUFDQSxPQUFJLFVBQVUsQ0FBVixJQUFlLFVBQVUsUUFBN0IsRUFBdUMsTUFBTSxVQUFVLG1DQUFWLEdBQWdELFFBQXREO0FBQ3ZDLFFBQUssYUFBTCxDQUFtQixVQUFVLFFBQVYsR0FBcUIsR0FBeEM7QUFDQSxVQUFPLElBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs4QkFJWTtBQUNYLFVBQU8sS0FBSyxhQUFMLEdBQXFCLENBQXJCLElBQTBCLFFBQU8sS0FBSyxhQUFaLE1BQThCLFFBQS9EO0FBQ0E7O0FBRUQ7Ozs7Ozs7MkJBSVM7QUFDUjtBQUNBLFFBQUssV0FBTDtBQUNBLFVBQU8sQ0FBQyxLQUFLLFNBQUwsRUFBUjtBQUEwQixTQUFLLFFBQUwsQ0FBYyxJQUFkO0FBQTFCLElBQ0EsS0FBSyxNQUFMLEdBQWMsS0FBSyxTQUFMLEVBQWQ7QUFDQSxRQUFLLFdBQUwsR0FBbUIsS0FBSyxjQUFMLEVBQW5CO0FBQ0EsUUFBSyxVQUFMLEdBQWtCLEtBQUssYUFBTCxFQUFsQjtBQUNBLFFBQUssU0FBTCxHQUFpQixDQUFqQjtBQUNBLFFBQUssU0FBTCxHQUFpQixDQUFqQjs7QUFFQTtBQUNBLFFBQUssV0FBTDs7QUFFQTs7QUFFQSxRQUFLLGtCQUFMLENBQXdCLFlBQXhCLEVBQXNDLElBQXRDO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7Z0NBSWM7QUFDYixRQUFLLE1BQUwsQ0FBWSxPQUFaLENBQW9CO0FBQUEsV0FBUyxNQUFNLEtBQU4sRUFBVDtBQUFBLElBQXBCO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OEJBSVk7QUFDWCxVQUFPLEtBQUssTUFBTCxDQUFZLEdBQVosQ0FBZ0I7QUFBQSxXQUFTLE1BQU0sTUFBZjtBQUFBLElBQWhCLENBQVA7QUFDQTs7QUFFRDs7Ozs7OztrQ0FJZ0I7QUFDZixVQUFPLEtBQUssR0FBTCxDQUFTLEtBQVQsQ0FBZSxJQUFmLEVBQXFCLEtBQUssTUFBTCxDQUFZLEdBQVosQ0FBZ0I7QUFBQSxXQUFTLE1BQU0sS0FBZjtBQUFBLElBQWhCLENBQXJCLENBQVA7QUFDQTs7QUFFRDs7Ozs7OzttQ0FJaUI7QUFDaEIsVUFBTyxLQUFLLE1BQUwsQ0FBWSxNQUFaLENBQW1CLFVBQUMsQ0FBRCxFQUFJLENBQUosRUFBVTtBQUFDLFdBQU8sRUFBQyxRQUFRLEVBQUMsUUFBUSxFQUFFLE1BQUYsQ0FBUyxNQUFULEdBQWtCLEVBQUUsTUFBRixDQUFTLE1BQXBDLEVBQVQsRUFBUDtBQUE2RCxJQUEzRixFQUE2RixFQUFDLFFBQVEsRUFBQyxRQUFRLENBQVQsRUFBVCxFQUE3RixFQUFvSCxNQUFwSCxDQUEySCxNQUFsSTtBQUNBOztBQUVEOzs7Ozs7O2dDQUljO0FBQ2IsVUFBTyxLQUFLLFVBQUwsR0FBa0IsS0FBSyxRQUF2QixHQUFrQyxLQUFLLEtBQXZDLEdBQStDLEVBQXREO0FBQ0E7O0FBRUQ7Ozs7Ozs7eUNBSXVCO0FBQ3RCLFVBQU8sS0FBSyxLQUFMLENBQVcsQ0FBQyxLQUFLLFVBQUwsR0FBa0IsS0FBSyxJQUF4QixJQUFnQyxLQUFLLFFBQXJDLEdBQWdELEtBQUssS0FBckQsR0FBNkQsRUFBeEUsQ0FBUDtBQUNBOztBQUVEOzs7Ozs7OzRDQUkwQjtBQUN6QixVQUFPLEtBQUssS0FBTCxDQUFXLEtBQUssb0JBQUwsS0FBOEIsS0FBSyxXQUFMLEVBQTlCLEdBQW1ELEdBQTlELENBQVA7QUFDQTs7QUFFRDs7Ozs7OzttQ0FJaUI7QUFDaEI7QUFDQSxVQUFPLEtBQUssS0FBSyxNQUFMLENBQVksTUFBWixHQUFxQixDQUExQixHQUE4QixLQUFLLE1BQUwsQ0FBWSxNQUFaLENBQW1CLFVBQUMsQ0FBRCxFQUFJLENBQUosRUFBVTtBQUFDLFdBQU8sRUFBQyxTQUFTLEVBQUUsT0FBRixHQUFZLEVBQUUsT0FBeEIsRUFBUDtBQUF3QyxJQUF0RSxFQUF3RSxFQUFDLFNBQVMsQ0FBVixFQUF4RSxFQUFzRixPQUEzSDtBQUNBOztBQUVEOzs7Ozs7O2lDQUllO0FBQ2QsVUFBTyxLQUFLLE1BQUwsQ0FBWSxNQUFaLENBQW1CLFVBQUMsQ0FBRCxFQUFJLENBQUosRUFBVTtBQUFDLFdBQU8sRUFBQyxZQUFZLEVBQUUsVUFBRixHQUFlLEVBQUUsVUFBOUIsRUFBUDtBQUFpRCxJQUEvRSxFQUFpRixFQUFDLFlBQVksQ0FBYixFQUFqRixFQUFrRyxVQUF6RztBQUNBOztBQUVEOzs7Ozs7Ozs7OzhCQU9ZO0FBQ1gsT0FBSSxLQUFLLFNBQUwsRUFBSixFQUFzQjtBQUNyQixXQUFPLEtBQUssWUFBTCxNQUF1QixLQUFLLFdBQW5DO0FBQ0E7O0FBRUQsVUFBTyxLQUFLLGNBQUwsTUFBeUIsS0FBSyxNQUFMLENBQVksTUFBNUM7QUFDQTs7QUFFRDs7Ozs7OzttQ0FJaUI7QUFDaEIsVUFBTyxLQUFLLEtBQUwsQ0FBVyxDQUFFLElBQUksSUFBSixFQUFELENBQWEsT0FBYixLQUF5QixLQUFLLFNBQS9CLElBQTRDLElBQTVDLElBQW9ELEtBQUssUUFBTCxJQUFpQixLQUFLLEtBQUwsR0FBYSxFQUE5QixDQUFwRCxDQUFYLElBQXFHLEtBQUssU0FBakg7QUFDQTs7QUFFRDs7Ozs7Ozs7NEJBS1UsSyxFQUFPO0FBQ2hCLFFBQUssa0JBQUwsQ0FBd0IsV0FBeEIsRUFBcUMsS0FBckM7QUFDQSxVQUFPLElBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs7O3FCQU1HLFcsRUFBYSxFLEVBQUk7QUFDbkIsT0FBSSxDQUFDLEtBQUssY0FBTCxDQUFvQixjQUFwQixDQUFtQyxXQUFuQyxDQUFMLEVBQXNELEtBQUssY0FBTCxDQUFvQixXQUFwQixJQUFtQyxFQUFuQztBQUN0RCxRQUFLLGNBQUwsQ0FBb0IsV0FBcEIsRUFBaUMsSUFBakMsQ0FBc0MsRUFBdEM7QUFDQSxVQUFPLElBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs7O3FDQU1tQixXLEVBQWEsSSxFQUFNO0FBQ3JDLE9BQUksS0FBSyxjQUFMLENBQW9CLGNBQXBCLENBQW1DLFdBQW5DLENBQUosRUFBcUQsS0FBSyxjQUFMLENBQW9CLFdBQXBCLEVBQWlDLE9BQWpDLENBQXlDO0FBQUEsV0FBTSxHQUFHLFFBQVEsRUFBWCxDQUFOO0FBQUEsSUFBekM7QUFDckQsVUFBTyxJQUFQO0FBQ0E7Ozs7OztBQUlGLFFBQVEsTUFBUixHQUFpQixNQUFqQjs7Ozs7Ozs7O0FDeGRBLElBQU0sWUFBWSxRQUFRLGFBQVIsRUFBdUIsU0FBekM7QUFDQSxJQUFNLFFBQVEsUUFBUSxTQUFSLEVBQW1CLEtBQWpDOztBQUVBOzs7O0lBR00sSztBQUNMLGdCQUFZLEtBQVosRUFBbUIsSUFBbkIsRUFBeUI7QUFBQTs7QUFDeEIsT0FBSyxPQUFMLEdBQWUsSUFBZjtBQUNBLE9BQUssVUFBTCxHQUFrQixDQUFsQjtBQUNBLE9BQUssT0FBTCxHQUFlLENBQWY7QUFDQSxPQUFLLFFBQUwsR0FBZ0IsQ0FBaEI7QUFDQSxPQUFLLFVBQUwsR0FBa0IsSUFBbEI7QUFDQSxPQUFLLEtBQUwsR0FBYSxLQUFiO0FBQ0EsT0FBSyxJQUFMLEdBQVksSUFBWjtBQUNBLE9BQUssS0FBTCxHQUFhLENBQWI7QUFDQSxPQUFLLFlBQUwsR0FBb0IsQ0FBcEI7QUFDQSxPQUFLLE1BQUwsR0FBYyxFQUFkO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzBCQUlRO0FBQ1AsUUFBSyxPQUFMLEdBQWUsSUFBZjtBQUNBLFFBQUssVUFBTCxHQUFrQixDQUFsQjtBQUNBLFFBQUssT0FBTCxHQUFlLENBQWY7QUFDQSxRQUFLLFFBQUwsR0FBZ0IsQ0FBaEI7QUFDQSxRQUFLLFVBQUwsR0FBa0IsSUFBbEI7QUFDQSxRQUFLLEtBQUwsR0FBYSxDQUFiO0FBQ0EsUUFBSyxZQUFMLEdBQW9CLENBQXBCO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7MkJBSVM7QUFDUixRQUFLLE9BQUwsR0FBZSxJQUFmO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7NEJBSVU7QUFDVCxRQUFLLE9BQUwsR0FBZSxLQUFmO0FBQ0EsVUFBTyxJQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7O3NDQUtvQixJLEVBQU07QUFDekIsVUFBTyxRQUFRLENBQWY7O0FBRUEsUUFBSyxJQUFJLENBQVQsSUFBYyxLQUFLLE1BQW5CLEVBQTJCO0FBQzFCLFFBQUksS0FBSyxNQUFMLENBQVksQ0FBWixFQUFlLElBQWYsSUFBdUIsSUFBM0IsRUFBaUM7QUFDaEMsVUFBSyxVQUFMLEdBQWtCLENBQWxCO0FBQ0EsWUFBTyxJQUFQO0FBQ0E7QUFDRDtBQUNEOztBQUVEOzs7Ozs7O21DQUlpQjtBQUNoQixVQUFPLEtBQUssSUFBTCxDQUFVLEtBQUssT0FBZixDQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7c0NBSW9CO0FBQ25CO0FBQ0E7QUFDQTtBQUNHO0FBQ0E7QUFDQSxPQUFJLGNBQWMsS0FBSyxjQUFMLEVBQWxCO0FBQ0EsT0FBSSxZQUFZLENBQWhCOztBQUVILFVBQU8sZUFBZSxHQUF0QixFQUEyQjtBQUMxQixrQkFBYyxLQUFLLElBQUwsQ0FBVSxLQUFLLE9BQUwsR0FBZSxTQUF6QixDQUFkO0FBQ0E7QUFDQTs7QUFFRCxVQUFPLFNBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs2QkFJVztBQUNWLFVBQU8sTUFBTSxVQUFOLENBQWlCLEtBQUssSUFBTCxDQUFVLFFBQVYsQ0FBbUIsS0FBSyxPQUF4QixFQUFpQyxLQUFLLE9BQUwsR0FBZSxLQUFLLGlCQUFMLEVBQWhELENBQWpCLENBQVA7QUFDQTs7QUFFRDs7Ozs7Ozs7OEJBS1ksVyxFQUFhLE0sRUFBUTtBQUNoQyxZQUFTLFVBQVUsS0FBbkI7O0FBRUEsT0FBSSxNQUFKLEVBQVk7QUFDWCxRQUFJLGVBQWUsY0FBYyxLQUFLLFFBQXRDO0FBQ0EsUUFBSSxRQUFRLEtBQUssUUFBTCxFQUFaO0FBQ0EsUUFBSSxhQUFhLGdCQUFnQixLQUFqQzs7QUFFQSxRQUFJLEtBQUssT0FBTCxHQUFlLEtBQUssSUFBTCxDQUFVLE1BQXpCLEtBQW9DLFVBQVUsVUFBOUMsQ0FBSixFQUErRDtBQUM5RCxTQUFJLFNBQVEsS0FBSyxVQUFMLEVBQVo7QUFDQSxTQUFJLEtBQUssT0FBVCxFQUFrQixPQUFPLE1BQVA7QUFDbEI7QUFDQTtBQUVELElBWEQsTUFXTztBQUNOO0FBQ0EsUUFBSSxLQUFLLE1BQUwsQ0FBWSxLQUFLLFVBQWpCLEtBQWdDLEtBQUssTUFBTCxDQUFZLEtBQUssVUFBakIsRUFBNkIsSUFBN0IsSUFBcUMsV0FBekUsRUFBc0Y7QUFDckYsVUFBSyxVQUFMO0FBQ0EsU0FBSSxLQUFLLE9BQVQsRUFBa0IsT0FBTyxLQUFLLE1BQUwsQ0FBWSxLQUFLLFVBQUwsR0FBa0IsQ0FBOUIsQ0FBUDtBQUNsQjtBQUNEOztBQUVELFVBQU8sSUFBUDtBQUNBOztBQUVEOzs7Ozs7OztnQ0FLYyxlLEVBQWlCO0FBQzlCLE9BQUksY0FBYyxLQUFLLE9BQXZCO0FBQ0EsT0FBSSxZQUFZLENBQWhCO0FBQ0EsT0FBSSxTQUFTLE1BQU0sVUFBTixDQUFpQixLQUFLLElBQUwsQ0FBVSxRQUFWLENBQW1CLGtCQUFrQixDQUFyQyxFQUF3QyxrQkFBa0IsQ0FBbEIsR0FBc0IsU0FBOUQsQ0FBakIsQ0FBYjtBQUNBLE9BQUksZUFBZSxNQUFuQjs7QUFFQSxVQUFPLE1BQU0sY0FBTixDQUFxQixLQUFLLElBQUwsQ0FBVSxRQUFWLENBQW1CLGtCQUFrQixTQUFsQixHQUE4QixDQUFqRCxFQUFvRCxrQkFBa0IsU0FBbEIsR0FBOEIsTUFBOUIsR0FBdUMsQ0FBM0YsQ0FBckIsQ0FBUDtBQUNBOztBQUVEOzs7Ozs7OytCQUlhO0FBQ1osT0FBSSxrQkFBa0IsS0FBSyxPQUFMLEdBQWUsS0FBSyxpQkFBTCxFQUFyQztBQUNBLE9BQUksWUFBWSxFQUFoQjtBQUNBLE9BQUksaUJBQWlCLEtBQUssaUJBQUwsRUFBckI7QUFDQSxhQUFVLEtBQVYsR0FBa0IsS0FBSyxLQUFMLEdBQWEsQ0FBL0I7QUFDQSxhQUFVLEtBQVYsR0FBa0IsS0FBSyxRQUFMLEVBQWxCO0FBQ0EsUUFBSyxRQUFMLEdBQWdCLEtBQUssUUFBTCxHQUFnQixVQUFVLEtBQTFDO0FBQ0EsUUFBSyxZQUFMLElBQXFCLFVBQVUsS0FBL0I7QUFDQSxhQUFVLElBQVYsR0FBaUIsS0FBSyxZQUF0QjtBQUNBLGFBQVUsU0FBVixHQUFzQixLQUFLLE9BQTNCOztBQUVBO0FBQ0EsT0FBSSxLQUFLLElBQUwsQ0FBVSxlQUFWLEtBQThCLElBQWxDLEVBQXdDO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxZQUFPLEtBQUssSUFBTCxDQUFVLGtCQUFrQixDQUE1QixDQUFQO0FBQ0MsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLGlCQUFqQjtBQUNBO0FBQ0QsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLFlBQWpCO0FBQ0EsZ0JBQVUsTUFBVixHQUFtQixLQUFLLGFBQUwsQ0FBbUIsZUFBbkIsQ0FBbkI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQixrQkFBakI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQixxQkFBakI7QUFDQSxnQkFBVSxNQUFWLEdBQW1CLEtBQUssYUFBTCxDQUFtQixlQUFuQixDQUFuQjtBQUNBO0FBQ0QsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLGlCQUFqQjtBQUNBLGdCQUFVLE1BQVYsR0FBbUIsS0FBSyxhQUFMLENBQW1CLGVBQW5CLENBQW5CO0FBQ0E7QUFDRCxVQUFLLElBQUw7QUFBVztBQUNWLGdCQUFVLElBQVYsR0FBaUIsT0FBakI7QUFDQSxnQkFBVSxNQUFWLEdBQW1CLEtBQUssYUFBTCxDQUFtQixlQUFuQixDQUFuQjtBQUNBO0FBQ0QsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLFFBQWpCO0FBQ0E7QUFDRCxVQUFLLElBQUw7QUFBVztBQUNWLGdCQUFVLElBQVYsR0FBaUIsV0FBakI7QUFDQSxnQkFBVSxNQUFWLEdBQW1CLEtBQUssYUFBTCxDQUFtQixlQUFuQixDQUFuQjtBQUNBO0FBQ0QsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLGFBQWpCO0FBQ0EsZ0JBQVUsTUFBVixHQUFtQixLQUFLLGFBQUwsQ0FBbUIsZUFBbkIsQ0FBbkI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQixxQkFBakI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQixXQUFqQjtBQUNBLGdCQUFVLElBQVYsR0FBaUIsTUFBTSxhQUFOLENBQW9CLENBQUMsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQUQsQ0FBcEIsQ0FBakI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQixjQUFqQjtBQUNBO0FBQ0QsVUFBSyxJQUFMO0FBQVc7QUFDVixnQkFBVSxJQUFWLEdBQWlCLFdBQWpCO0FBQ0EsZ0JBQVUsSUFBVixHQUFpQixLQUFLLEtBQUwsQ0FBVyxXQUFXLE1BQU0sYUFBTixDQUFvQixLQUFLLElBQUwsQ0FBVSxRQUFWLENBQW1CLGtCQUFrQixDQUFyQyxFQUF3QyxrQkFBa0IsQ0FBMUQsQ0FBcEIsQ0FBdEIsQ0FBakI7QUFDQSxXQUFLLEtBQUwsR0FBYSxVQUFVLElBQXZCO0FBQ0E7QUFDRCxVQUFLLElBQUw7QUFBVztBQUNWLGdCQUFVLElBQVYsR0FBaUIsY0FBakI7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1Y7QUFDQSxnQkFBVSxJQUFWLEdBQWlCLGdCQUFqQjtBQUNBLGdCQUFVLElBQVYsR0FBaUIsS0FBSyxJQUFMLENBQVUsUUFBVixDQUFtQixrQkFBa0IsQ0FBckMsRUFBd0Msa0JBQWtCLENBQTFELENBQWpCO0FBQ0EsZ0JBQVUsYUFBVixHQUEwQixLQUFLLFVBQVUsSUFBVixDQUFlLENBQWYsQ0FBTCxHQUF5QixHQUF6QixHQUErQixLQUFLLEdBQUwsQ0FBUyxVQUFVLElBQVYsQ0FBZSxDQUFmLENBQVQsRUFBNEIsQ0FBNUIsQ0FBekQ7QUFDQTtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1Y7QUFDQSxnQkFBVSxJQUFWLEdBQWlCLGVBQWpCO0FBQ0EsZ0JBQVUsSUFBVixHQUFpQixLQUFLLElBQUwsQ0FBVSxRQUFWLENBQW1CLGtCQUFrQixDQUFyQyxFQUF3QyxrQkFBa0IsQ0FBMUQsQ0FBakI7O0FBRUEsVUFBSSxVQUFVLElBQVYsQ0FBZSxDQUFmLEtBQXFCLENBQXpCLEVBQTRCO0FBQzNCLGlCQUFVLFlBQVYsR0FBeUIsVUFBVSxnQkFBVixDQUEyQixVQUFVLElBQVYsQ0FBZSxDQUFmLENBQTNCLENBQXpCO0FBRUEsT0FIRCxNQUdPLElBQUksVUFBVSxJQUFWLENBQWUsQ0FBZixJQUFvQixDQUF4QixFQUEyQjtBQUNqQyxpQkFBVSxZQUFWLEdBQXlCLFVBQVUsaUJBQVYsQ0FBNEIsS0FBSyxHQUFMLENBQVMsVUFBVSxJQUFWLENBQWUsQ0FBZixDQUFULENBQTVCLENBQXpCO0FBQ0E7O0FBRUQsVUFBSSxVQUFVLElBQVYsQ0FBZSxDQUFmLEtBQXFCLENBQXpCLEVBQTRCO0FBQzNCLGlCQUFVLFlBQVYsSUFBMEIsUUFBMUI7QUFFQSxPQUhELE1BR08sSUFBSSxVQUFVLElBQVYsQ0FBZSxDQUFmLEtBQXFCLENBQXpCLEVBQTRCO0FBQ2xDLGlCQUFVLFlBQVYsSUFBMEIsUUFBMUI7QUFDQTs7QUFFRDtBQUNELFVBQUssSUFBTDtBQUFXO0FBQ1YsZ0JBQVUsSUFBVixHQUFpQiwrQkFBakI7QUFDQTtBQUNEO0FBQ0MsZ0JBQVUsSUFBVixHQUFpQixjQUFjLEtBQUssSUFBTCxDQUFVLGtCQUFrQixDQUE1QixFQUErQixRQUEvQixDQUF3QyxFQUF4QyxDQUEvQjtBQUNBO0FBbkZGOztBQXNGQSxRQUFJLFNBQVMsS0FBSyxJQUFMLENBQVUsS0FBSyxPQUFMLEdBQWUsY0FBZixHQUFnQyxDQUExQyxDQUFiO0FBQ0E7O0FBRUEsU0FBSyxPQUFMLElBQWdCLGlCQUFpQixDQUFqQixHQUFxQixNQUFyQztBQUVBLElBbEdELE1Ba0dPLElBQUcsS0FBSyxJQUFMLENBQVUsZUFBVixLQUE4QixJQUFqQyxFQUF1QztBQUM3QztBQUNBLGNBQVUsSUFBVixHQUFpQixPQUFqQjtBQUNBLFFBQUksU0FBUyxLQUFLLElBQUwsQ0FBVSxLQUFLLE9BQUwsR0FBZSxjQUFmLEdBQWdDLENBQTFDLENBQWI7QUFDQSxTQUFLLE9BQUwsSUFBZ0IsaUJBQWlCLENBQWpCLEdBQXFCLE1BQXJDO0FBRUEsSUFOTSxNQU1BO0FBQ047QUFDQSxRQUFJLEtBQUssSUFBTCxDQUFVLGVBQVYsSUFBNkIsSUFBakMsRUFBdUM7QUFDdEM7QUFDQSxlQUFVLE9BQVYsR0FBb0IsSUFBcEI7QUFDQSxlQUFVLFVBQVYsR0FBdUIsS0FBSyxJQUFMLENBQVUsZUFBVixDQUF2QjtBQUNBLGVBQVUsUUFBVixHQUFxQixVQUFVLEtBQVYsQ0FBZ0IsS0FBSyxJQUFMLENBQVUsZUFBVixDQUFoQixDQUFyQjtBQUNBLGVBQVUsUUFBVixHQUFxQixLQUFLLElBQUwsQ0FBVSxrQkFBa0IsQ0FBNUIsQ0FBckI7O0FBRUEsU0FBSSxLQUFLLFVBQUwsSUFBbUIsSUFBdkIsRUFBNkI7QUFDNUIsZ0JBQVUsSUFBVixHQUFpQixVQUFqQjtBQUNBLGdCQUFVLE9BQVYsR0FBb0IsS0FBSyxVQUFMLEdBQWtCLElBQWxCLEdBQXlCLENBQTdDO0FBRUEsTUFKRCxNQUlPLElBQUksS0FBSyxVQUFMLElBQW1CLElBQXZCLEVBQTZCO0FBQ25DLGdCQUFVLElBQVYsR0FBaUIsU0FBakI7QUFDQSxnQkFBVSxPQUFWLEdBQW9CLEtBQUssVUFBTCxHQUFrQixJQUFsQixHQUF5QixDQUE3QztBQUNBOztBQUVELFVBQUssT0FBTCxJQUFnQixpQkFBaUIsQ0FBakM7QUFFQSxLQWxCRCxNQWtCTztBQUNOLFVBQUssVUFBTCxHQUFrQixLQUFLLElBQUwsQ0FBVSxlQUFWLENBQWxCOztBQUVBLFNBQUksS0FBSyxJQUFMLENBQVUsZUFBVixLQUE4QixJQUFsQyxFQUF3QztBQUN2QztBQUNBLGdCQUFVLElBQVYsR0FBaUIsVUFBakI7QUFDQSxnQkFBVSxPQUFWLEdBQW9CLEtBQUssVUFBTCxHQUFrQixJQUFsQixHQUF5QixDQUE3QztBQUNBLGdCQUFVLFVBQVYsR0FBdUIsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQXZCO0FBQ0EsZ0JBQVUsUUFBVixHQUFxQixVQUFVLEtBQVYsQ0FBZ0IsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQWhCLENBQXJCO0FBQ0EsZ0JBQVUsUUFBVixHQUFxQixLQUFLLEtBQUwsQ0FBVyxLQUFLLElBQUwsQ0FBVSxrQkFBa0IsQ0FBNUIsSUFBaUMsR0FBakMsR0FBdUMsR0FBbEQsQ0FBckI7QUFDQSxXQUFLLE9BQUwsSUFBZ0IsaUJBQWlCLENBQWpDO0FBRUEsTUFURCxNQVNPLElBQUksS0FBSyxJQUFMLENBQVUsZUFBVixLQUE4QixJQUFsQyxFQUF3QztBQUM5QztBQUNBLGdCQUFVLElBQVYsR0FBaUIsU0FBakI7QUFDQSxnQkFBVSxPQUFWLEdBQW9CLEtBQUssVUFBTCxHQUFrQixJQUFsQixHQUF5QixDQUE3QztBQUNBLGdCQUFVLFVBQVYsR0FBdUIsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQXZCO0FBQ0EsZ0JBQVUsUUFBVixHQUFxQixVQUFVLEtBQVYsQ0FBZ0IsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQWhCLENBQXJCO0FBQ0EsZ0JBQVUsUUFBVixHQUFxQixLQUFLLEtBQUwsQ0FBVyxLQUFLLElBQUwsQ0FBVSxrQkFBa0IsQ0FBNUIsSUFBaUMsR0FBakMsR0FBdUMsR0FBbEQsQ0FBckI7QUFDQSxXQUFLLE9BQUwsSUFBZ0IsaUJBQWlCLENBQWpDO0FBRUEsTUFUTSxNQVNBLElBQUksS0FBSyxJQUFMLENBQVUsZUFBVixLQUE4QixJQUFsQyxFQUF3QztBQUM5QztBQUNBLGdCQUFVLElBQVYsR0FBaUIseUJBQWpCO0FBQ0EsZ0JBQVUsT0FBVixHQUFvQixLQUFLLFVBQUwsR0FBa0IsSUFBbEIsR0FBeUIsQ0FBN0M7QUFDQSxnQkFBVSxJQUFWLEdBQWlCLFVBQVUsS0FBVixDQUFnQixLQUFLLElBQUwsQ0FBVSxrQkFBa0IsQ0FBNUIsQ0FBaEIsQ0FBakI7QUFDQSxnQkFBVSxRQUFWLEdBQXFCLE1BQU0sQ0FBTixDQUFyQjtBQUNBLFdBQUssT0FBTCxJQUFnQixpQkFBaUIsQ0FBakM7QUFFQSxNQVJNLE1BUUEsSUFBSSxLQUFLLElBQUwsQ0FBVSxlQUFWLEtBQThCLElBQWxDLEVBQXdDO0FBQzlDO0FBQ0EsZ0JBQVUsSUFBVixHQUFpQixtQkFBakI7QUFDQSxnQkFBVSxPQUFWLEdBQW9CLEtBQUssVUFBTCxHQUFrQixJQUFsQixHQUF5QixDQUE3QztBQUNBLGdCQUFVLE1BQVYsR0FBbUIsS0FBSyxJQUFMLENBQVUsa0JBQWtCLENBQTVCLENBQW5CO0FBQ0EsZ0JBQVUsS0FBVixHQUFrQixLQUFLLElBQUwsQ0FBVSxrQkFBa0IsQ0FBNUIsQ0FBbEI7QUFDQSxXQUFLLE9BQUwsSUFBZ0IsaUJBQWlCLENBQWpDO0FBRUEsTUFSTSxNQVFBLElBQUksS0FBSyxJQUFMLENBQVUsZUFBVixLQUE4QixJQUFsQyxFQUF3QztBQUM5QztBQUNBLGdCQUFVLElBQVYsR0FBaUIsZ0JBQWpCO0FBQ0EsZ0JBQVUsT0FBVixHQUFvQixLQUFLLFVBQUwsR0FBa0IsSUFBbEIsR0FBeUIsQ0FBN0M7QUFDQSxnQkFBVSxLQUFWLEdBQWtCLEtBQUssSUFBTCxDQUFVLGtCQUFrQixDQUE1QixDQUFsQjtBQUNBLFdBQUssT0FBTCxJQUFnQixpQkFBaUIsQ0FBakM7QUFFQSxNQVBNLE1BT0EsSUFBSSxLQUFLLElBQUwsQ0FBVSxlQUFWLEtBQThCLElBQWxDLEVBQXdDO0FBQzlDO0FBQ0EsZ0JBQVUsSUFBVixHQUFpQixzQkFBakI7QUFDQSxnQkFBVSxPQUFWLEdBQW9CLEtBQUssVUFBTCxHQUFrQixJQUFsQixHQUF5QixDQUE3QztBQUNBLFdBQUssT0FBTCxJQUFnQixpQkFBaUIsQ0FBakM7QUFFQSxNQU5NLE1BTUEsSUFBSSxLQUFLLElBQUwsQ0FBVSxlQUFWLEtBQThCLElBQWxDLEVBQXdDO0FBQzlDO0FBQ0EsZ0JBQVUsSUFBVixHQUFpQixZQUFqQjtBQUNBLGdCQUFVLE9BQVYsR0FBb0IsS0FBSyxVQUFMLEdBQWtCLElBQWxCLEdBQXlCLENBQTdDO0FBQ0EsV0FBSyxPQUFMLElBQWdCLGlCQUFpQixDQUFqQztBQUVBLE1BTk0sTUFNQTtBQUNOLGdCQUFVLElBQVYsR0FBaUIsd0JBQXdCLEtBQUssT0FBTCxDQUFhLFFBQWIsRUFBeEIsR0FBa0QsR0FBbEQsR0FBeUQsZ0JBQWdCLFFBQWhCLEVBQXpELEdBQXNGLEdBQXRGLEdBQTRGLEtBQUssSUFBTCxDQUFVLE1BQXZIO0FBQ0E7QUFDRDtBQUNEOztBQUVELFFBQUssS0FBTCxJQUFjLFVBQVUsS0FBeEI7QUFDQSxRQUFLLE1BQUwsQ0FBWSxJQUFaLENBQWlCLFNBQWpCOztBQUVBLFVBQU8sU0FBUDtBQUNBOztBQUVEOzs7Ozs7OytCQUlhO0FBQ1osT0FBSSxLQUFLLElBQUwsQ0FBVSxLQUFLLE9BQUwsR0FBZSxDQUF6QixLQUErQixJQUEvQixJQUF1QyxLQUFLLElBQUwsQ0FBVSxLQUFLLE9BQUwsR0FBZSxDQUF6QixLQUErQixJQUF0RSxJQUE4RSxLQUFLLElBQUwsQ0FBVSxLQUFLLE9BQUwsR0FBZSxDQUF6QixLQUErQixJQUFqSCxFQUF1SDtBQUN0SCxXQUFPLElBQVA7QUFDQTs7QUFFRCxVQUFPLEtBQVA7QUFDQTs7Ozs7O0FBR0YsT0FBTyxPQUFQLENBQWUsS0FBZixHQUF1QixLQUF2Qjs7Ozs7Ozs7OztBQ25YQTs7O0lBR00sSzs7Ozs7Ozs7O0FBRUw7Ozs7OzRCQUtpQixJLEVBQU07QUFDdEI7QUFDQSxVQUFPLENBQUMsTUFBTSxLQUFLLFFBQUwsQ0FBYyxFQUFkLENBQVAsRUFBMEIsS0FBMUIsQ0FBZ0MsQ0FBQyxDQUFqQyxDQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzZCQUtrQixTLEVBQVc7QUFDNUIsT0FBSSxNQUFNLEVBQVY7QUFDQSxhQUFVLE9BQVYsQ0FBa0I7QUFBQSxXQUFRLElBQUksSUFBSixDQUFTLE1BQU0sU0FBTixDQUFnQixJQUFoQixDQUFULENBQVI7QUFBQSxJQUFsQjtBQUNBLFVBQU8sSUFBSSxJQUFKLENBQVMsRUFBVCxDQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzhCQUttQixTLEVBQVc7QUFDN0IsVUFBTyxTQUFTLFNBQVQsRUFBb0IsRUFBcEIsQ0FBUDtBQUNBOztBQUVEOzs7Ozs7OztnQ0FLcUIsUyxFQUFXO0FBQy9CLFVBQU8sTUFBTSxXQUFOLENBQWtCLE1BQU0sVUFBTixDQUFpQixTQUFqQixDQUFsQixDQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7O2lDQUtzQixTLEVBQVc7QUFDaEMsT0FBSSxVQUFVLEVBQWQ7QUFDQSxhQUFVLE9BQVYsQ0FBa0I7QUFBQSxXQUFRLFFBQVEsSUFBUixDQUFhLE9BQU8sWUFBUCxDQUFvQixJQUFwQixDQUFiLENBQVI7QUFBQSxJQUFsQjtBQUNBLFVBQU8sUUFBUSxJQUFSLENBQWEsRUFBYixDQUFQO0FBQ0E7O0FBRUQ7Ozs7Ozs7OzhCQUttQixHLEVBQUs7QUFDcEIsVUFBTyxDQUFDLFFBQVEsQ0FBVCxFQUFZLFFBQVosQ0FBcUIsQ0FBckIsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs2QkFLa0IsUyxFQUFXO0FBQzVCLE9BQUksU0FBUyxDQUFiO0FBQ0EsYUFBVSxPQUFWLENBQWtCLGtCQUFVO0FBQzNCLFFBQUksSUFBSSxNQUFSO0FBQ0EsUUFBSSxJQUFJLElBQVIsRUFBYztBQUNiLGVBQVcsSUFBSSxJQUFmO0FBQ0EsZ0JBQVcsQ0FBWDtBQUNBLEtBSEQsTUFHTztBQUNOO0FBQ0EsZUFBVSxDQUFWO0FBQ0E7QUFDRCxJQVREOztBQVdBLFVBQU8sTUFBUDtBQUNBOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Y0FLWSxNLEVBQVE7QUFDbkIsT0FBSSxPQUFPLElBQVAsS0FBZ0IsVUFBcEIsRUFBZ0MsT0FBTyxLQUFLLE1BQUwsQ0FBUDtBQUNoQyxVQUFPLElBQUksTUFBSixDQUFXLE1BQVgsRUFBbUIsUUFBbkIsRUFBNkIsUUFBN0IsQ0FBc0MsUUFBdEMsQ0FBUDtBQUNBLEc7Ozs7OztBQUdGLFFBQVEsS0FBUixHQUFnQixLQUFoQiIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9cmV0dXJuIGV9KSgpIiwiJ3VzZSBzdHJpY3QnXG5cbmV4cG9ydHMuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcbmV4cG9ydHMudG9CeXRlQXJyYXkgPSB0b0J5dGVBcnJheVxuZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gZnJvbUJ5dGVBcnJheVxuXG52YXIgbG9va3VwID0gW11cbnZhciByZXZMb29rdXAgPSBbXVxudmFyIEFyciA9IHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJyA/IFVpbnQ4QXJyYXkgOiBBcnJheVxuXG52YXIgY29kZSA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJ1xuZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNvZGUubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgbG9va3VwW2ldID0gY29kZVtpXVxuICByZXZMb29rdXBbY29kZS5jaGFyQ29kZUF0KGkpXSA9IGlcbn1cblxucmV2TG9va3VwWyctJy5jaGFyQ29kZUF0KDApXSA9IDYyXG5yZXZMb29rdXBbJ18nLmNoYXJDb2RlQXQoMCldID0gNjNcblxuZnVuY3Rpb24gcGxhY2VIb2xkZXJzQ291bnQgKGI2NCkge1xuICB2YXIgbGVuID0gYjY0Lmxlbmd0aFxuICBpZiAobGVuICUgNCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuICB9XG5cbiAgLy8gdGhlIG51bWJlciBvZiBlcXVhbCBzaWducyAocGxhY2UgaG9sZGVycylcbiAgLy8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuICAvLyByZXByZXNlbnQgb25lIGJ5dGVcbiAgLy8gaWYgdGhlcmUgaXMgb25seSBvbmUsIHRoZW4gdGhlIHRocmVlIGNoYXJhY3RlcnMgYmVmb3JlIGl0IHJlcHJlc2VudCAyIGJ5dGVzXG4gIC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2VcbiAgcmV0dXJuIGI2NFtsZW4gLSAyXSA9PT0gJz0nID8gMiA6IGI2NFtsZW4gLSAxXSA9PT0gJz0nID8gMSA6IDBcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoYjY0KSB7XG4gIC8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuICByZXR1cm4gKGI2NC5sZW5ndGggKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNDb3VudChiNjQpXG59XG5cbmZ1bmN0aW9uIHRvQnl0ZUFycmF5IChiNjQpIHtcbiAgdmFyIGksIGwsIHRtcCwgcGxhY2VIb2xkZXJzLCBhcnJcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcbiAgcGxhY2VIb2xkZXJzID0gcGxhY2VIb2xkZXJzQ291bnQoYjY0KVxuXG4gIGFyciA9IG5ldyBBcnIoKGxlbiAqIDMgLyA0KSAtIHBsYWNlSG9sZGVycylcblxuICAvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG4gIGwgPSBwbGFjZUhvbGRlcnMgPiAwID8gbGVuIC0gNCA6IGxlblxuXG4gIHZhciBMID0gMFxuXG4gIGZvciAoaSA9IDA7IGkgPCBsOyBpICs9IDQpIHtcbiAgICB0bXAgPSAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxOCkgfCAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgMTIpIHwgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildIDw8IDYpIHwgcmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAzKV1cbiAgICBhcnJbTCsrXSA9ICh0bXAgPj4gMTYpICYgMHhGRlxuICAgIGFycltMKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbTCsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIGlmIChwbGFjZUhvbGRlcnMgPT09IDIpIHtcbiAgICB0bXAgPSAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAyKSB8IChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA+PiA0KVxuICAgIGFycltMKytdID0gdG1wICYgMHhGRlxuICB9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuICAgIHRtcCA9IChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDEwKSB8IChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCA0KSB8IChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKVxuICAgIGFycltMKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbTCsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBhcnJcbn1cblxuZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcbiAgcmV0dXJuIGxvb2t1cFtudW0gPj4gMTggJiAweDNGXSArIGxvb2t1cFtudW0gPj4gMTIgJiAweDNGXSArIGxvb2t1cFtudW0gPj4gNiAmIDB4M0ZdICsgbG9va3VwW251bSAmIDB4M0ZdXG59XG5cbmZ1bmN0aW9uIGVuY29kZUNodW5rICh1aW50OCwgc3RhcnQsIGVuZCkge1xuICB2YXIgdG1wXG4gIHZhciBvdXRwdXQgPSBbXVxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gMykge1xuICAgIHRtcCA9ICh1aW50OFtpXSA8PCAxNikgKyAodWludDhbaSArIDFdIDw8IDgpICsgKHVpbnQ4W2kgKyAyXSlcbiAgICBvdXRwdXQucHVzaCh0cmlwbGV0VG9CYXNlNjQodG1wKSlcbiAgfVxuICByZXR1cm4gb3V0cHV0LmpvaW4oJycpXG59XG5cbmZ1bmN0aW9uIGZyb21CeXRlQXJyYXkgKHVpbnQ4KSB7XG4gIHZhciB0bXBcbiAgdmFyIGxlbiA9IHVpbnQ4Lmxlbmd0aFxuICB2YXIgZXh0cmFCeXRlcyA9IGxlbiAlIDMgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcbiAgdmFyIG91dHB1dCA9ICcnXG4gIHZhciBwYXJ0cyA9IFtdXG4gIHZhciBtYXhDaHVua0xlbmd0aCA9IDE2MzgzIC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xuXG4gIC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcbiAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xuICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsodWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKSkpXG4gIH1cblxuICAvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG4gIGlmIChleHRyYUJ5dGVzID09PSAxKSB7XG4gICAgdG1wID0gdWludDhbbGVuIC0gMV1cbiAgICBvdXRwdXQgKz0gbG9va3VwW3RtcCA+PiAyXVxuICAgIG91dHB1dCArPSBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdXG4gICAgb3V0cHV0ICs9ICc9PSdcbiAgfSBlbHNlIGlmIChleHRyYUJ5dGVzID09PSAyKSB7XG4gICAgdG1wID0gKHVpbnQ4W2xlbiAtIDJdIDw8IDgpICsgKHVpbnQ4W2xlbiAtIDFdKVxuICAgIG91dHB1dCArPSBsb29rdXBbdG1wID4+IDEwXVxuICAgIG91dHB1dCArPSBsb29rdXBbKHRtcCA+PiA0KSAmIDB4M0ZdXG4gICAgb3V0cHV0ICs9IGxvb2t1cFsodG1wIDw8IDIpICYgMHgzRl1cbiAgICBvdXRwdXQgKz0gJz0nXG4gIH1cblxuICBwYXJ0cy5wdXNoKG91dHB1dClcblxuICByZXR1cm4gcGFydHMuam9pbignJylcbn1cbiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cblxuJ3VzZSBzdHJpY3QnXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuXG52YXIgS19NQVhfTEVOR1RIID0gMHg3ZmZmZmZmZlxuZXhwb3J0cy5rTWF4TGVuZ3RoID0gS19NQVhfTEVOR1RIXG5cbi8qKlxuICogSWYgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYDpcbiAqICAgPT09IHRydWUgICAgVXNlIFVpbnQ4QXJyYXkgaW1wbGVtZW50YXRpb24gKGZhc3Rlc3QpXG4gKiAgID09PSBmYWxzZSAgIFByaW50IHdhcm5pbmcgYW5kIHJlY29tbWVuZCB1c2luZyBgYnVmZmVyYCB2NC54IHdoaWNoIGhhcyBhbiBPYmplY3RcbiAqICAgICAgICAgICAgICAgaW1wbGVtZW50YXRpb24gKG1vc3QgY29tcGF0aWJsZSwgZXZlbiBJRTYpXG4gKlxuICogQnJvd3NlcnMgdGhhdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBhcmUgSUUgMTArLCBGaXJlZm94IDQrLCBDaHJvbWUgNyssIFNhZmFyaSA1LjErLFxuICogT3BlcmEgMTEuNissIGlPUyA0LjIrLlxuICpcbiAqIFdlIHJlcG9ydCB0aGF0IHRoZSBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGlmIHRoZSBhcmUgbm90IHN1YmNsYXNzYWJsZVxuICogdXNpbmcgX19wcm90b19fLiBGaXJlZm94IDQtMjkgbGFja3Mgc3VwcG9ydCBmb3IgYWRkaW5nIG5ldyBwcm9wZXJ0aWVzIHRvIGBVaW50OEFycmF5YFxuICogKFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njk1NDM4KS4gSUUgMTAgbGFja3Mgc3VwcG9ydFxuICogZm9yIF9fcHJvdG9fXyBhbmQgaGFzIGEgYnVnZ3kgdHlwZWQgYXJyYXkgaW1wbGVtZW50YXRpb24uXG4gKi9cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gdHlwZWRBcnJheVN1cHBvcnQoKVxuXG5pZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUICYmIHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHR5cGVvZiBjb25zb2xlLmVycm9yID09PSAnZnVuY3Rpb24nKSB7XG4gIGNvbnNvbGUuZXJyb3IoXG4gICAgJ1RoaXMgYnJvd3NlciBsYWNrcyB0eXBlZCBhcnJheSAoVWludDhBcnJheSkgc3VwcG9ydCB3aGljaCBpcyByZXF1aXJlZCBieSAnICtcbiAgICAnYGJ1ZmZlcmAgdjUueC4gVXNlIGBidWZmZXJgIHY0LnggaWYgeW91IHJlcXVpcmUgb2xkIGJyb3dzZXIgc3VwcG9ydC4nXG4gIClcbn1cblxuZnVuY3Rpb24gdHlwZWRBcnJheVN1cHBvcnQgKCkge1xuICAvLyBDYW4gdHlwZWQgYXJyYXkgaW5zdGFuY2VzIGNhbiBiZSBhdWdtZW50ZWQ/XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgYXJyLl9fcHJvdG9fXyA9IHtfX3Byb3RvX186IFVpbnQ4QXJyYXkucHJvdG90eXBlLCBmb286IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH19XG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDJcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAobGVuZ3RoKSB7XG4gIGlmIChsZW5ndGggPiBLX01BWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW52YWxpZCB0eXBlZCBhcnJheSBsZW5ndGgnKVxuICB9XG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIHZhciBidWYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpXG4gIGJ1Zi5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIHJldHVybiBidWZcbn1cblxuLyoqXG4gKiBUaGUgQnVmZmVyIGNvbnN0cnVjdG9yIHJldHVybnMgaW5zdGFuY2VzIG9mIGBVaW50OEFycmF5YCB0aGF0IGhhdmUgdGhlaXJcbiAqIHByb3RvdHlwZSBjaGFuZ2VkIHRvIGBCdWZmZXIucHJvdG90eXBlYC4gRnVydGhlcm1vcmUsIGBCdWZmZXJgIGlzIGEgc3ViY2xhc3Mgb2ZcbiAqIGBVaW50OEFycmF5YCwgc28gdGhlIHJldHVybmVkIGluc3RhbmNlcyB3aWxsIGhhdmUgYWxsIHRoZSBub2RlIGBCdWZmZXJgIG1ldGhvZHNcbiAqIGFuZCB0aGUgYFVpbnQ4QXJyYXlgIG1ldGhvZHMuIFNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0XG4gKiByZXR1cm5zIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIFRoZSBgVWludDhBcnJheWAgcHJvdG90eXBlIHJlbWFpbnMgdW5tb2RpZmllZC5cbiAqL1xuXG5mdW5jdGlvbiBCdWZmZXIgKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAodHlwZW9mIGVuY29kaW5nT3JPZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdJZiBlbmNvZGluZyBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZydcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIGFsbG9jVW5zYWZlKGFyZylcbiAgfVxuICByZXR1cm4gZnJvbShhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuLy8gRml4IHN1YmFycmF5KCkgaW4gRVMyMDE2LiBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL3B1bGwvOTdcbmlmICh0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wuc3BlY2llcyAmJlxuICAgIEJ1ZmZlcltTeW1ib2wuc3BlY2llc10gPT09IEJ1ZmZlcikge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLCBTeW1ib2wuc3BlY2llcywge1xuICAgIHZhbHVlOiBudWxsLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICB3cml0YWJsZTogZmFsc2VcbiAgfSlcbn1cblxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbmZ1bmN0aW9uIGZyb20gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgYSBudW1iZXInKVxuICB9XG5cbiAgaWYgKGlzQXJyYXlCdWZmZXIodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldClcbiAgfVxuXG4gIHJldHVybiBmcm9tT2JqZWN0KHZhbHVlKVxufVxuXG4vKipcbiAqIEZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHRvIEJ1ZmZlcihhcmcsIGVuY29kaW5nKSBidXQgdGhyb3dzIGEgVHlwZUVycm9yXG4gKiBpZiB2YWx1ZSBpcyBhIG51bWJlci5cbiAqIEJ1ZmZlci5mcm9tKHN0clssIGVuY29kaW5nXSlcbiAqIEJ1ZmZlci5mcm9tKGFycmF5KVxuICogQnVmZmVyLmZyb20oYnVmZmVyKVxuICogQnVmZmVyLmZyb20oYXJyYXlCdWZmZXJbLCBieXRlT2Zmc2V0WywgbGVuZ3RoXV0pXG4gKiovXG5CdWZmZXIuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBmcm9tKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbi8vIE5vdGU6IENoYW5nZSBwcm90b3R5cGUgKmFmdGVyKiBCdWZmZXIuZnJvbSBpcyBkZWZpbmVkIHRvIHdvcmthcm91bmQgQ2hyb21lIGJ1Zzpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL3B1bGwvMTQ4XG5CdWZmZXIucHJvdG90eXBlLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXkucHJvdG90eXBlXG5CdWZmZXIuX19wcm90b19fID0gVWludDhBcnJheVxuXG5mdW5jdGlvbiBhc3NlcnRTaXplIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IGJlIGEgbnVtYmVyJylcbiAgfSBlbHNlIGlmIChzaXplIDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBuZWdhdGl2ZScpXG4gIH1cbn1cblxuZnVuY3Rpb24gYWxsb2MgKHNpemUsIGZpbGwsIGVuY29kaW5nKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgaWYgKHNpemUgPD0gMCkge1xuICAgIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbiAgfVxuICBpZiAoZmlsbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gT25seSBwYXkgYXR0ZW50aW9uIHRvIGVuY29kaW5nIGlmIGl0J3MgYSBzdHJpbmcuIFRoaXNcbiAgICAvLyBwcmV2ZW50cyBhY2NpZGVudGFsbHkgc2VuZGluZyBpbiBhIG51bWJlciB0aGF0IHdvdWxkXG4gICAgLy8gYmUgaW50ZXJwcmV0dGVkIGFzIGEgc3RhcnQgb2Zmc2V0LlxuICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICA/IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgICAgOiBjcmVhdGVCdWZmZXIoc2l6ZSkuZmlsbChmaWxsKVxuICB9XG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKiBhbGxvYyhzaXplWywgZmlsbFssIGVuY29kaW5nXV0pXG4gKiovXG5CdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGFsbG9jKHNpemUsIGZpbGwsIGVuY29kaW5nKVxufVxuXG5mdW5jdGlvbiBhbGxvY1Vuc2FmZSAoc2l6ZSkge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG59XG5cbi8qKlxuICogRXF1aXZhbGVudCB0byBCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqICovXG5CdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cbi8qKlxuICogRXF1aXZhbGVudCB0byBTbG93QnVmZmVyKG51bSksIGJ5IGRlZmF1bHQgY3JlYXRlcyBhIG5vbi16ZXJvLWZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICB9XG5cbiAgaWYgKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImVuY29kaW5nXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZyBlbmNvZGluZycpXG4gIH1cblxuICB2YXIgbGVuZ3RoID0gYnl0ZUxlbmd0aChzdHJpbmcsIGVuY29kaW5nKSB8IDBcbiAgdmFyIGJ1ZiA9IGNyZWF0ZUJ1ZmZlcihsZW5ndGgpXG5cbiAgdmFyIGFjdHVhbCA9IGJ1Zi53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuXG4gIGlmIChhY3R1YWwgIT09IGxlbmd0aCkge1xuICAgIC8vIFdyaXRpbmcgYSBoZXggc3RyaW5nLCBmb3IgZXhhbXBsZSwgdGhhdCBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnMgd2lsbFxuICAgIC8vIGNhdXNlIGV2ZXJ5dGhpbmcgYWZ0ZXIgdGhlIGZpcnN0IGludmFsaWQgY2hhcmFjdGVyIHRvIGJlIGlnbm9yZWQuIChlLmcuXG4gICAgLy8gJ2FieHhjZCcgd2lsbCBiZSB0cmVhdGVkIGFzICdhYicpXG4gICAgYnVmID0gYnVmLnNsaWNlKDAsIGFjdHVhbClcbiAgfVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5TGlrZSAoYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIGJ1ZltpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIgKGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwIHx8IGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0KSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1xcJ29mZnNldFxcJyBpcyBvdXQgb2YgYm91bmRzJylcbiAgfVxuXG4gIGlmIChhcnJheS5ieXRlTGVuZ3RoIDwgYnl0ZU9mZnNldCArIChsZW5ndGggfHwgMCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnbGVuZ3RoXFwnIGlzIG91dCBvZiBib3VuZHMnKVxuICB9XG5cbiAgdmFyIGJ1ZlxuICBpZiAoYnl0ZU9mZnNldCA9PT0gdW5kZWZpbmVkICYmIGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYnVmID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXkpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSwgYnl0ZU9mZnNldClcbiAgfSBlbHNlIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSwgYnl0ZU9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2VcbiAgYnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0IChvYmopIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmopKSB7XG4gICAgdmFyIGxlbiA9IGNoZWNrZWQob2JqLmxlbmd0aCkgfCAwXG4gICAgdmFyIGJ1ZiA9IGNyZWF0ZUJ1ZmZlcihsZW4pXG5cbiAgICBpZiAoYnVmLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJ1ZlxuICAgIH1cblxuICAgIG9iai5jb3B5KGJ1ZiwgMCwgMCwgbGVuKVxuICAgIHJldHVybiBidWZcbiAgfVxuXG4gIGlmIChvYmopIHtcbiAgICBpZiAoaXNBcnJheUJ1ZmZlclZpZXcob2JqKSB8fCAnbGVuZ3RoJyBpbiBvYmopIHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gJ251bWJlcicgfHwgbnVtYmVySXNOYU4ob2JqLmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcigwKVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZyb21BcnJheUxpa2Uob2JqKVxuICAgIH1cblxuICAgIGlmIChvYmoudHlwZSA9PT0gJ0J1ZmZlcicgJiYgQXJyYXkuaXNBcnJheShvYmouZGF0YSkpIHtcbiAgICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKG9iai5kYXRhKVxuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCBvciBhcnJheS1saWtlIG9iamVjdC4nKVxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwgS19NQVhfTEVOR1RIYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IEtfTUFYX0xFTkdUSCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBLX01BWF9MRU5HVEgudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlciAobGVuZ3RoKSB7XG4gIGlmICgrbGVuZ3RoICE9IGxlbmd0aCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGVxZXFlcVxuICAgIGxlbmd0aCA9IDBcbiAgfVxuICByZXR1cm4gQnVmZmVyLmFsbG9jKCtsZW5ndGgpXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiBiICE9IG51bGwgJiYgYi5faXNCdWZmZXIgPT09IHRydWVcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGEpIHx8ICFCdWZmZXIuaXNCdWZmZXIoYikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudHMgbXVzdCBiZSBCdWZmZXJzJylcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIHZhciB4ID0gYS5sZW5ndGhcbiAgdmFyIHkgPSBiLmxlbmd0aFxuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBNYXRoLm1pbih4LCB5KTsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHtcbiAgICAgIHggPSBhW2ldXG4gICAgICB5ID0gYltpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnbGF0aW4xJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIUFycmF5LmlzQXJyYXkobGlzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmZmVyID0gQnVmZmVyLmFsbG9jVW5zYWZlKGxlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYnVmID0gbGlzdFtpXVxuICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gICAgfVxuICAgIGJ1Zi5jb3B5KGJ1ZmZlciwgcG9zKVxuICAgIHBvcyArPSBidWYubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZmZlclxufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIoc3RyaW5nKSkge1xuICAgIHJldHVybiBzdHJpbmcubGVuZ3RoXG4gIH1cbiAgaWYgKGlzQXJyYXlCdWZmZXJWaWV3KHN0cmluZykgfHwgaXNBcnJheUJ1ZmZlcihzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5ieXRlTGVuZ3RoXG4gIH1cbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgc3RyaW5nID0gJycgKyBzdHJpbmdcbiAgfVxuXG4gIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChsZW4gPT09IDApIHJldHVybiAwXG5cbiAgLy8gVXNlIGEgZm9yIGxvb3AgdG8gYXZvaWQgcmVjdXJzaW9uXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxlblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gbGVuICogMlxuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGxlbiA+Pj4gMVxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoIC8vIGFzc3VtZSB1dGY4XG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcblxuZnVuY3Rpb24gc2xvd1RvU3RyaW5nIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIC8vIE5vIG5lZWQgdG8gdmVyaWZ5IHRoYXQgXCJ0aGlzLmxlbmd0aCA8PSBNQVhfVUlOVDMyXCIgc2luY2UgaXQncyBhIHJlYWQtb25seVxuICAvLyBwcm9wZXJ0eSBvZiBhIHR5cGVkIGFycmF5LlxuXG4gIC8vIFRoaXMgYmVoYXZlcyBuZWl0aGVyIGxpa2UgU3RyaW5nIG5vciBVaW50OEFycmF5IGluIHRoYXQgd2Ugc2V0IHN0YXJ0L2VuZFxuICAvLyB0byB0aGVpciB1cHBlci9sb3dlciBib3VuZHMgaWYgdGhlIHZhbHVlIHBhc3NlZCBpcyBvdXQgb2YgcmFuZ2UuXG4gIC8vIHVuZGVmaW5lZCBpcyBoYW5kbGVkIHNwZWNpYWxseSBhcyBwZXIgRUNNQS0yNjIgNnRoIEVkaXRpb24sXG4gIC8vIFNlY3Rpb24gMTMuMy4zLjcgUnVudGltZSBTZW1hbnRpY3M6IEtleWVkQmluZGluZ0luaXRpYWxpemF0aW9uLlxuICBpZiAoc3RhcnQgPT09IHVuZGVmaW5lZCB8fCBzdGFydCA8IDApIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICAvLyBSZXR1cm4gZWFybHkgaWYgc3RhcnQgPiB0aGlzLmxlbmd0aC4gRG9uZSBoZXJlIHRvIHByZXZlbnQgcG90ZW50aWFsIHVpbnQzMlxuICAvLyBjb2VyY2lvbiBmYWlsIGJlbG93LlxuICBpZiAoc3RhcnQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgfVxuXG4gIGlmIChlbmQgPD0gMCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgLy8gRm9yY2UgY29lcnNpb24gdG8gdWludDMyLiBUaGlzIHdpbGwgYWxzbyBjb2VyY2UgZmFsc2V5L05hTiB2YWx1ZXMgdG8gMC5cbiAgZW5kID4+Pj0gMFxuICBzdGFydCA+Pj49IDBcblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsYXRpbjFTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHV0ZjE2bGVTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuLy8gVGhpcyBwcm9wZXJ0eSBpcyB1c2VkIGJ5IGBCdWZmZXIuaXNCdWZmZXJgIChhbmQgdGhlIGBpcy1idWZmZXJgIG5wbSBwYWNrYWdlKVxuLy8gdG8gZGV0ZWN0IGEgQnVmZmVyIGluc3RhbmNlLiBJdCdzIG5vdCBwb3NzaWJsZSB0byB1c2UgYGluc3RhbmNlb2YgQnVmZmVyYFxuLy8gcmVsaWFibHkgaW4gYSBicm93c2VyaWZ5IGNvbnRleHQgYmVjYXVzZSB0aGVyZSBjb3VsZCBiZSBtdWx0aXBsZSBkaWZmZXJlbnRcbi8vIGNvcGllcyBvZiB0aGUgJ2J1ZmZlcicgcGFja2FnZSBpbiB1c2UuIFRoaXMgbWV0aG9kIHdvcmtzIGV2ZW4gZm9yIEJ1ZmZlclxuLy8gaW5zdGFuY2VzIHRoYXQgd2VyZSBjcmVhdGVkIGZyb20gYW5vdGhlciBjb3B5IG9mIHRoZSBgYnVmZmVyYCBwYWNrYWdlLlxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9pc3N1ZXMvMTU0XG5CdWZmZXIucHJvdG90eXBlLl9pc0J1ZmZlciA9IHRydWVcblxuZnVuY3Rpb24gc3dhcCAoYiwgbiwgbSkge1xuICB2YXIgaSA9IGJbbl1cbiAgYltuXSA9IGJbbV1cbiAgYlttXSA9IGlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMTYgPSBmdW5jdGlvbiBzd2FwMTYgKCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbiAlIDIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDE2LWJpdHMnKVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDIpIHtcbiAgICBzd2FwKHRoaXMsIGksIGkgKyAxKVxuICB9XG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc3dhcDMyID0gZnVuY3Rpb24gc3dhcDMyICgpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA0ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzMi1iaXRzJylcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA0KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgMylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgMilcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXA2NCA9IGZ1bmN0aW9uIHN3YXA2NCAoKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgOCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0cycpXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gOCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDcpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDYpXG4gICAgc3dhcCh0aGlzLCBpICsgMiwgaSArIDUpXG4gICAgc3dhcCh0aGlzLCBpICsgMywgaSArIDQpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW5ndGggPT09IDApIHJldHVybiAnJ1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCAwLCBsZW5ndGgpXG4gIHJldHVybiBzbG93VG9TdHJpbmcuYXBwbHkodGhpcywgYXJndW1lbnRzKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIGVxdWFscyAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYikgPT09IDBcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gIHZhciBzdHIgPSAnJ1xuICB2YXIgbWF4ID0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFU1xuICBpZiAodGhpcy5sZW5ndGggPiAwKSB7XG4gICAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5tYXRjaCgvLnsyfS9nKS5qb2luKCcgJylcbiAgICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIH1cbiAgcmV0dXJuICc8QnVmZmVyICcgKyBzdHIgKyAnPidcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAodGFyZ2V0LCBzdGFydCwgZW5kLCB0aGlzU3RhcnQsIHRoaXNFbmQpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGFyZ2V0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICB9XG5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmQgPSB0YXJnZXQgPyB0YXJnZXQubGVuZ3RoIDogMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNTdGFydCA9IDBcbiAgfVxuICBpZiAodGhpc0VuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpc0VuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoc3RhcnQgPCAwIHx8IGVuZCA+IHRhcmdldC5sZW5ndGggfHwgdGhpc1N0YXJ0IDwgMCB8fCB0aGlzRW5kID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb3V0IG9mIHJhbmdlIGluZGV4JylcbiAgfVxuXG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCAmJiBzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCkge1xuICAgIHJldHVybiAtMVxuICB9XG4gIGlmIChzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMVxuICB9XG5cbiAgc3RhcnQgPj4+PSAwXG4gIGVuZCA+Pj49IDBcbiAgdGhpc1N0YXJ0ID4+Pj0gMFxuICB0aGlzRW5kID4+Pj0gMFxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQpIHJldHVybiAwXG5cbiAgdmFyIHggPSB0aGlzRW5kIC0gdGhpc1N0YXJ0XG4gIHZhciB5ID0gZW5kIC0gc3RhcnRcbiAgdmFyIGxlbiA9IE1hdGgubWluKHgsIHkpXG5cbiAgdmFyIHRoaXNDb3B5ID0gdGhpcy5zbGljZSh0aGlzU3RhcnQsIHRoaXNFbmQpXG4gIHZhciB0YXJnZXRDb3B5ID0gdGFyZ2V0LnNsaWNlKHN0YXJ0LCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgIGlmICh0aGlzQ29weVtpXSAhPT0gdGFyZ2V0Q29weVtpXSkge1xuICAgICAgeCA9IHRoaXNDb3B5W2ldXG4gICAgICB5ID0gdGFyZ2V0Q29weVtpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbi8vIEZpbmRzIGVpdGhlciB0aGUgZmlyc3QgaW5kZXggb2YgYHZhbGAgaW4gYGJ1ZmZlcmAgYXQgb2Zmc2V0ID49IGBieXRlT2Zmc2V0YCxcbi8vIE9SIHRoZSBsYXN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA8PSBgYnl0ZU9mZnNldGAuXG4vL1xuLy8gQXJndW1lbnRzOlxuLy8gLSBidWZmZXIgLSBhIEJ1ZmZlciB0byBzZWFyY2hcbi8vIC0gdmFsIC0gYSBzdHJpbmcsIEJ1ZmZlciwgb3IgbnVtYmVyXG4vLyAtIGJ5dGVPZmZzZXQgLSBhbiBpbmRleCBpbnRvIGBidWZmZXJgOyB3aWxsIGJlIGNsYW1wZWQgdG8gYW4gaW50MzJcbi8vIC0gZW5jb2RpbmcgLSBhbiBvcHRpb25hbCBlbmNvZGluZywgcmVsZXZhbnQgaXMgdmFsIGlzIGEgc3RyaW5nXG4vLyAtIGRpciAtIHRydWUgZm9yIGluZGV4T2YsIGZhbHNlIGZvciBsYXN0SW5kZXhPZlxuZnVuY3Rpb24gYmlkaXJlY3Rpb25hbEluZGV4T2YgKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIC8vIEVtcHR5IGJ1ZmZlciBtZWFucyBubyBtYXRjaFxuICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xXG5cbiAgLy8gTm9ybWFsaXplIGJ5dGVPZmZzZXRcbiAgaWYgKHR5cGVvZiBieXRlT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gYnl0ZU9mZnNldFxuICAgIGJ5dGVPZmZzZXQgPSAwXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA+IDB4N2ZmZmZmZmYpIHtcbiAgICBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAtMHg4MDAwMDAwMCkge1xuICAgIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICB9XG4gIGJ5dGVPZmZzZXQgPSArYnl0ZU9mZnNldCAgLy8gQ29lcmNlIHRvIE51bWJlci5cbiAgaWYgKG51bWJlcklzTmFOKGJ5dGVPZmZzZXQpKSB7XG4gICAgLy8gYnl0ZU9mZnNldDogaXQgaXQncyB1bmRlZmluZWQsIG51bGwsIE5hTiwgXCJmb29cIiwgZXRjLCBzZWFyY2ggd2hvbGUgYnVmZmVyXG4gICAgYnl0ZU9mZnNldCA9IGRpciA/IDAgOiAoYnVmZmVyLmxlbmd0aCAtIDEpXG4gIH1cblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldDogbmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoICsgYnl0ZU9mZnNldFxuICBpZiAoYnl0ZU9mZnNldCA+PSBidWZmZXIubGVuZ3RoKSB7XG4gICAgaWYgKGRpcikgcmV0dXJuIC0xXG4gICAgZWxzZSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCAtIDFcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgMCkge1xuICAgIGlmIChkaXIpIGJ5dGVPZmZzZXQgPSAwXG4gICAgZWxzZSByZXR1cm4gLTFcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSB2YWxcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsID0gQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgfVxuXG4gIC8vIEZpbmFsbHksIHNlYXJjaCBlaXRoZXIgaW5kZXhPZiAoaWYgZGlyIGlzIHRydWUpIG9yIGxhc3RJbmRleE9mXG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIC8vIFNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nL2J1ZmZlciBhbHdheXMgZmFpbHNcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAweEZGIC8vIFNlYXJjaCBmb3IgYSBieXRlIHZhbHVlIFswLTI1NV1cbiAgICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgWyB2YWwgXSwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcilcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlcicpXG59XG5cbmZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpIHtcbiAgdmFyIGluZGV4U2l6ZSA9IDFcbiAgdmFyIGFyckxlbmd0aCA9IGFyci5sZW5ndGhcbiAgdmFyIHZhbExlbmd0aCA9IHZhbC5sZW5ndGhcblxuICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgaWYgKGVuY29kaW5nID09PSAndWNzMicgfHwgZW5jb2RpbmcgPT09ICd1Y3MtMicgfHxcbiAgICAgICAgZW5jb2RpbmcgPT09ICd1dGYxNmxlJyB8fCBlbmNvZGluZyA9PT0gJ3V0Zi0xNmxlJykge1xuICAgICAgaWYgKGFyci5sZW5ndGggPCAyIHx8IHZhbC5sZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgICAgaW5kZXhTaXplID0gMlxuICAgICAgYXJyTGVuZ3RoIC89IDJcbiAgICAgIHZhbExlbmd0aCAvPSAyXG4gICAgICBieXRlT2Zmc2V0IC89IDJcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZWFkIChidWYsIGkpIHtcbiAgICBpZiAoaW5kZXhTaXplID09PSAxKSB7XG4gICAgICByZXR1cm4gYnVmW2ldXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBidWYucmVhZFVJbnQxNkJFKGkgKiBpbmRleFNpemUpXG4gICAgfVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGRpcikge1xuICAgIHZhciBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKGkgPSBieXRlT2Zmc2V0OyBpIDwgYXJyTGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChyZWFkKGFyciwgaSkgPT09IHJlYWQodmFsLCBmb3VuZEluZGV4ID09PSAtMSA/IDAgOiBpIC0gZm91bmRJbmRleCkpIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggPT09IC0xKSBmb3VuZEluZGV4ID0gaVxuICAgICAgICBpZiAoaSAtIGZvdW5kSW5kZXggKyAxID09PSB2YWxMZW5ndGgpIHJldHVybiBmb3VuZEluZGV4ICogaW5kZXhTaXplXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm91bmRJbmRleCAhPT0gLTEpIGkgLT0gaSAtIGZvdW5kSW5kZXhcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChieXRlT2Zmc2V0ICsgdmFsTGVuZ3RoID4gYXJyTGVuZ3RoKSBieXRlT2Zmc2V0ID0gYXJyTGVuZ3RoIC0gdmFsTGVuZ3RoXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciBmb3VuZCA9IHRydWVcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmFsTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKHJlYWQoYXJyLCBpICsgaikgIT09IHJlYWQodmFsLCBqKSkge1xuICAgICAgICAgIGZvdW5kID0gZmFsc2VcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZm91bmQpIHJldHVybiBpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIC0xXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gdGhpcy5pbmRleE9mKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpICE9PSAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCB0cnVlKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGJpZGlyZWN0aW9uYWxJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGZhbHNlKVxufVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIC8vIG11c3QgYmUgYW4gZXZlbiBudW1iZXIgb2YgZGlnaXRzXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChzdHJMZW4gJSAyICE9PSAwKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGlmIChudW1iZXJJc05hTihwYXJzZWQpKSByZXR1cm4gaVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gbGF0aW4xV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCA+Pj4gMFxuICAgICAgaWYgKGVuY29kaW5nID09PSB1bmRlZmluZWQpIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ0J1ZmZlci53cml0ZShzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXRbLCBsZW5ndGhdKSBpcyBubyBsb25nZXIgc3VwcG9ydGVkJ1xuICAgIClcbiAgfVxuXG4gIHZhciByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxhdGluMVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgdmFyIHJlcyA9IFtdXG5cbiAgdmFyIGkgPSBzdGFydFxuICB3aGlsZSAoaSA8IGVuZCkge1xuICAgIHZhciBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICB2YXIgY29kZVBvaW50ID0gbnVsbFxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpID8gNFxuICAgICAgOiAoZmlyc3RCeXRlID4gMHhERikgPyAzXG4gICAgICA6IChmaXJzdEJ5dGUgPiAweEJGKSA/IDJcbiAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgdmFyIHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxudmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICB2YXIgbGVuID0gY29kZVBvaW50cy5sZW5ndGhcbiAgaWYgKGxlbiA8PSBNQVhfQVJHVU1FTlRTX0xFTkdUSCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY29kZVBvaW50cykgLy8gYXZvaWQgZXh0cmEgc2xpY2UoKVxuICB9XG5cbiAgLy8gRGVjb2RlIGluIGNodW5rcyB0byBhdm9pZCBcImNhbGwgc3RhY2sgc2l6ZSBleGNlZWRlZFwiLlxuICB2YXIgcmVzID0gJydcbiAgdmFyIGkgPSAwXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXG4gICAgICBTdHJpbmcsXG4gICAgICBjb2RlUG9pbnRzLnNsaWNlKGksIGkgKz0gTUFYX0FSR1VNRU5UU19MRU5HVEgpXG4gICAgKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0gJiAweDdGKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gbGF0aW4xU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIChieXRlc1tpICsgMV0gKiAyNTYpKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWYgPSB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpXG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIG5ld0J1Zi5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIHJldHVybiBuZXdCdWZcbn1cblxuLypcbiAqIE5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgYnVmZmVyIGlzbid0IHRyeWluZyB0byB3cml0ZSBvdXQgb2YgYm91bmRzLlxuICovXG5mdW5jdGlvbiBjaGVja09mZnNldCAob2Zmc2V0LCBleHQsIGxlbmd0aCkge1xuICBpZiAoKG9mZnNldCAlIDEpICE9PSAwIHx8IG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdvZmZzZXQgaXMgbm90IHVpbnQnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gbGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgdmFyIG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIHJlYWRJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkUgPSBmdW5jdGlvbiByZWFkSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoXG4gIHZhciBtdWwgPSAxXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0taV1cbiAgd2hpbGUgKGkgPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1pXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiByZWFkSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgaWYgKCEodGhpc1tvZmZzZXRdICYgMHg4MCkpIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdExFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiByZWFkRmxvYXRCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiByZWFkRG91YmxlTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiByZWFkRG91YmxlQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgNTIsIDgpXG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJidWZmZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFID0gZnVuY3Rpb24gd3JpdGVVSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIG1heEJ5dGVzID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpIC0gMVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG1heEJ5dGVzLCAwKVxuICB9XG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoIC0gMVxuICB2YXIgbXVsID0gMVxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVVSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4ZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgKDggKiBieXRlTGVuZ3RoKSAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICBpZiAodmFsdWUgPCAwICYmIHN1YiA9PT0gMCAmJiB0aGlzW29mZnNldCArIGkgLSAxXSAhPT0gMCkge1xuICAgICAgc3ViID0gMVxuICAgIH1cbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiB3cml0ZUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBsaW1pdCA9IE1hdGgucG93KDIsICg4ICogYnl0ZUxlbmd0aCkgLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpICsgMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweDdmLCAtMHg4MClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuZnVuY3Rpb24gd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDgsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG4gIHJldHVybiBvZmZzZXQgKyA4XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUJFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gY29weSAodGFyZ2V0LCB0YXJnZXRTdGFydCwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0U3RhcnQgPj0gdGFyZ2V0Lmxlbmd0aCkgdGFyZ2V0U3RhcnQgPSB0YXJnZXQubGVuZ3RoXG4gIGlmICghdGFyZ2V0U3RhcnQpIHRhcmdldFN0YXJ0ID0gMFxuICBpZiAoZW5kID4gMCAmJiBlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVybiAwXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldFN0YXJ0IDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgfVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlU3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChlbmQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCA8IGVuZCAtIHN0YXJ0KSB7XG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0ICsgc3RhcnRcbiAgfVxuXG4gIHZhciBsZW4gPSBlbmQgLSBzdGFydFxuICB2YXIgaVxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgc3RhcnQgPCB0YXJnZXRTdGFydCAmJiB0YXJnZXRTdGFydCA8IGVuZCkge1xuICAgIC8vIGRlc2NlbmRpbmcgY29weSBmcm9tIGVuZFxuICAgIGZvciAoaSA9IGxlbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIGlmIChsZW4gPCAxMDAwKSB7XG4gICAgLy8gYXNjZW5kaW5nIGNvcHkgZnJvbSBzdGFydFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwoXG4gICAgICB0YXJnZXQsXG4gICAgICB0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksXG4gICAgICB0YXJnZXRTdGFydFxuICAgIClcbiAgfVxuXG4gIHJldHVybiBsZW5cbn1cblxuLy8gVXNhZ2U6XG4vLyAgICBidWZmZXIuZmlsbChudW1iZXJbLCBvZmZzZXRbLCBlbmRdXSlcbi8vICAgIGJ1ZmZlci5maWxsKGJ1ZmZlclssIG9mZnNldFssIGVuZF1dKVxuLy8gICAgYnVmZmVyLmZpbGwoc3RyaW5nWywgb2Zmc2V0WywgZW5kXV1bLCBlbmNvZGluZ10pXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiBmaWxsICh2YWwsIHN0YXJ0LCBlbmQsIGVuY29kaW5nKSB7XG4gIC8vIEhhbmRsZSBzdHJpbmcgY2FzZXM6XG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIGlmICh0eXBlb2Ygc3RhcnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IHN0YXJ0XG4gICAgICBzdGFydCA9IDBcbiAgICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZW5kID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBlbmRcbiAgICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gICAgfVxuICAgIGlmICh2YWwubGVuZ3RoID09PSAxKSB7XG4gICAgICB2YXIgY29kZSA9IHZhbC5jaGFyQ29kZUF0KDApXG4gICAgICBpZiAoY29kZSA8IDI1Nikge1xuICAgICAgICB2YWwgPSBjb2RlXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChlbmNvZGluZyAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuY29kaW5nIG11c3QgYmUgYSBzdHJpbmcnKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnc3RyaW5nJyAmJiAhQnVmZmVyLmlzRW5jb2RpbmcoZW5jb2RpbmcpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMjU1XG4gIH1cblxuICAvLyBJbnZhbGlkIHJhbmdlcyBhcmUgbm90IHNldCB0byBhIGRlZmF1bHQsIHNvIGNhbiByYW5nZSBjaGVjayBlYXJseS5cbiAgaWYgKHN0YXJ0IDwgMCB8fCB0aGlzLmxlbmd0aCA8IHN0YXJ0IHx8IHRoaXMubGVuZ3RoIDwgZW5kKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghdmFsKSB2YWwgPSAwXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgdGhpc1tpXSA9IHZhbFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogbmV3IEJ1ZmZlcih2YWwsIGVuY29kaW5nKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBmb3IgKGkgPSAwOyBpIDwgZW5kIC0gc3RhcnQ7ICsraSkge1xuICAgICAgdGhpc1tpICsgc3RhcnRdID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbnZhciBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXisvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHN0cmlwcyBvdXQgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgXFxuIGFuZCBcXHQgZnJvbSB0aGUgc3RyaW5nLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgc3RyID0gc3RyLnRyaW0oKS5yZXBsYWNlKElOVkFMSURfQkFTRTY0X1JFLCAnJylcbiAgLy8gTm9kZSBjb252ZXJ0cyBzdHJpbmdzIHdpdGggbGVuZ3RoIDwgMiB0byAnJ1xuICBpZiAoc3RyLmxlbmd0aCA8IDIpIHJldHVybiAnJ1xuICAvLyBOb2RlIGFsbG93cyBmb3Igbm9uLXBhZGRlZCBiYXNlNjQgc3RyaW5ncyAobWlzc2luZyB0cmFpbGluZyA9PT0pLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgd2hpbGUgKHN0ci5sZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgc3RyID0gc3RyICsgJz0nXG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgdmFyIGNvZGVQb2ludFxuICB2YXIgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcbiAgdmFyIGJ5dGVzID0gW11cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICghbGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuICAgICAgICBpZiAoY29kZVBvaW50ID4gMHhEQkZGKSB7XG4gICAgICAgICAgLy8gdW5leHBlY3RlZCB0cmFpbFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgIC8vIHVucGFpcmVkIGxlYWRcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgY29kZVBvaW50ID0gKGxlYWRTdXJyb2dhdGUgLSAweEQ4MDAgPDwgMTAgfCBjb2RlUG9pbnQgLSAweERDMDApICsgMHgxMDAwMFxuICAgIH0gZWxzZSBpZiAobGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgLy8gdmFsaWQgYm1wIGNoYXIsIGJ1dCBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgfVxuXG4gICAgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcblxuICAgIC8vIGVuY29kZSB1dGY4XG4gICAgaWYgKGNvZGVQb2ludCA8IDB4ODApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMSkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChjb2RlUG9pbnQpXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDgwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2IHwgMHhDMCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyB8IDB4RTAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDQpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDEyIHwgMHhGMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4QyAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2RlIHBvaW50JylcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnl0ZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0ciwgdW5pdHMpIHtcbiAgdmFyIGMsIGhpLCBsb1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcblxuICAgIGMgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGhpID0gYyA+PiA4XG4gICAgbG8gPSBjICUgMjU2XG4gICAgYnl0ZUFycmF5LnB1c2gobG8pXG4gICAgYnl0ZUFycmF5LnB1c2goaGkpXG4gIH1cblxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMgKHN0cikge1xuICByZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KGJhc2U2NGNsZWFuKHN0cikpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKSBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbi8vIEFycmF5QnVmZmVycyBmcm9tIGFub3RoZXIgY29udGV4dCAoaS5lLiBhbiBpZnJhbWUpIGRvIG5vdCBwYXNzIHRoZSBgaW5zdGFuY2VvZmAgY2hlY2tcbi8vIGJ1dCB0aGV5IHNob3VsZCBiZSB0cmVhdGVkIGFzIHZhbGlkLiBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8xNjZcbmZ1bmN0aW9uIGlzQXJyYXlCdWZmZXIgKG9iaikge1xuICByZXR1cm4gb2JqIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcbiAgICAob2JqICE9IG51bGwgJiYgb2JqLmNvbnN0cnVjdG9yICE9IG51bGwgJiYgb2JqLmNvbnN0cnVjdG9yLm5hbWUgPT09ICdBcnJheUJ1ZmZlcicgJiZcbiAgICAgIHR5cGVvZiBvYmouYnl0ZUxlbmd0aCA9PT0gJ251bWJlcicpXG59XG5cbi8vIE5vZGUgMC4xMCBzdXBwb3J0cyBgQXJyYXlCdWZmZXJgIGJ1dCBsYWNrcyBgQXJyYXlCdWZmZXIuaXNWaWV3YFxuZnVuY3Rpb24gaXNBcnJheUJ1ZmZlclZpZXcgKG9iaikge1xuICByZXR1cm4gKHR5cGVvZiBBcnJheUJ1ZmZlci5pc1ZpZXcgPT09ICdmdW5jdGlvbicpICYmIEFycmF5QnVmZmVyLmlzVmlldyhvYmopXG59XG5cbmZ1bmN0aW9uIG51bWJlcklzTmFOIChvYmopIHtcbiAgcmV0dXJuIG9iaiAhPT0gb2JqIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tc2VsZi1jb21wYXJlXG59XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbVxuICB2YXIgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSBlICogMjU2ICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhc1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSlcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pXG4gICAgZSA9IGUgLSBlQmlhc1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pXG59XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGNcbiAgdmFyIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsIi8qKlxuICogQ29uc3RhbnRzIHVzZWQgaW4gcGxheWVyLlxuICovXG52YXIgQ29uc3RhbnRzID0ge1xuXHRWRVJTSU9OOiAnMi4wLjMnLFxuXHROT1RFUzogW10sXG5cdENJUkNMRV9PRl9GT1VSVEhTOiBbJ0MnLCAnRicsICdCYicsICdFYicsICdBYicsICdEYicsICdHYicsICdDYicsICdGYicsICdCYmInLCAnRWJiJywgJ0FiYiddLFxuXHRDSVJDTEVfT0ZfRklGVEhTOiBbJ0MnLCAnRycsICdEJywgJ0EnLCAnRScsICdCJywgJ0YjJywgJ0MjJywgJ0cjJywgJ0QjJywgJ0EjJywgJ0UjJ11cbn07XG5cbi8vIEJ1aWxkcyBub3RlcyBvYmplY3QgZm9yIHJlZmVyZW5jZSBhZ2FpbnN0IGJpbmFyeSB2YWx1ZXMuXG52YXIgYWxsTm90ZXMgPSBbWydDJ10sIFsnQyMnLCdEYiddLCBbJ0QnXSwgWydEIycsJ0ViJ10sIFsnRSddLFsnRiddLCBbJ0YjJywnR2InXSwgWydHJ10sIFsnRyMnLCdBYiddLCBbJ0EnXSwgWydBIycsJ0JiJ10sIFsnQiddXTtcbnZhciBjb3VudGVyID0gMDtcblxuLy8gQWxsIGF2YWlsYWJsZSBvY3RhdmVzLlxuZm9yIChsZXQgaSA9IC0xOyBpIDw9IDk7IGkrKykge1xuXHRhbGxOb3Rlcy5mb3JFYWNoKG5vdGVHcm91cCA9PiB7XG5cdFx0bm90ZUdyb3VwLmZvckVhY2gobm90ZSA9PiBDb25zdGFudHMuTk9URVNbY291bnRlcl0gPSBub3RlICsgaSk7XG5cdFx0Y291bnRlciArKztcblx0fSk7XG59XG5cbmV4cG9ydHMuQ29uc3RhbnRzID0gQ29uc3RhbnRzOyIsImNvbnN0IFBsYXllciA9IHJlcXVpcmUoXCIuL3BsYXllclwiKTtcbmNvbnN0IFV0aWxzID0gcmVxdWlyZShcIi4vdXRpbHNcIik7XG5jb25zdCBDb25zdGFudHMgPSByZXF1aXJlKFwiLi9jb25zdGFudHNcIik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFBsYXllcjpQbGF5ZXIuUGxheWVyLFxuICAgIFV0aWxzOlV0aWxzLlV0aWxzLFxuICAgIENvbnN0YW50czpDb25zdGFudHMuQ29uc3RhbnRzXG59IiwiY29uc3QgVXRpbHMgPSByZXF1aXJlKFwiLi91dGlsc1wiKS5VdGlscztcbmNvbnN0IFRyYWNrID0gcmVxdWlyZShcIi4vdHJhY2tcIikuVHJhY2s7XG5cbi8vIFBvbHlmaWxsIFVpbnQ4QXJyYXkuZm9yRWFjaDogRG9lc24ndCBleGlzdCBvbiBTYWZhcmkgPDEwXG5pZiAoIVVpbnQ4QXJyYXkucHJvdG90eXBlLmZvckVhY2gpIHtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KFVpbnQ4QXJyYXkucHJvdG90eXBlLCAnZm9yRWFjaCcsIHtcblx0XHR2YWx1ZTogQXJyYXkucHJvdG90eXBlLmZvckVhY2hcblx0fSk7XG59XG5cbi8qKlxuICogTWFpbiBwbGF5ZXIgY2xhc3MuICBDb250YWlucyBtZXRob2RzIHRvIGxvYWQgZmlsZXMsIHN0YXJ0LCBzdG9wLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gLSBDYWxsYmFjayB0byBmaXJlIGZvciBlYWNoIE1JREkgZXZlbnQuICBDYW4gYWxzbyBiZSBhZGRlZCB3aXRoIG9uKCdtaWRpRXZlbnQnLCBmbilcbiAqIEBwYXJhbSB7YXJyYXl9IC0gQXJyYXkgYnVmZmVyIG9mIE1JREkgZmlsZSAob3B0aW9uYWwpLlxuICovXG5jbGFzcyBQbGF5ZXIge1xuXHRjb25zdHJ1Y3RvcihldmVudEhhbmRsZXIsIGJ1ZmZlcikge1xuXHRcdHRoaXMuc2FtcGxlUmF0ZSA9IDU7IC8vIG1pbGxpc2Vjb25kc1xuXHRcdHRoaXMuc3RhcnRUaW1lID0gMDtcblx0XHR0aGlzLmJ1ZmZlciA9IGJ1ZmZlciB8fCBudWxsO1xuXHRcdHRoaXMuZGl2aXNpb247XG5cdFx0dGhpcy5mb3JtYXQ7XG5cdFx0dGhpcy5zZXRJbnRlcnZhbElkID0gZmFsc2U7XG5cdFx0dGhpcy50cmFja3MgPSBbXTtcblx0XHR0aGlzLmluc3RydW1lbnRzID0gW107XG5cdFx0dGhpcy5kZWZhdWx0VGVtcG8gPSAxMjA7XG5cdFx0dGhpcy50ZW1wbyA9IG51bGw7XG5cdFx0dGhpcy5zdGFydFRpY2sgPSAwO1xuXHRcdHRoaXMudGljayA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IG51bGw7XG5cdFx0dGhpcy5pbkxvb3AgPSBmYWxzZTtcblx0XHR0aGlzLnRvdGFsVGlja3MgPSAwO1xuXHRcdHRoaXMuZXZlbnRzID0gW107XG5cdFx0dGhpcy50b3RhbEV2ZW50cyA9IDA7XG5cdFx0dGhpcy5ldmVudExpc3RlbmVycyA9IHt9O1xuXG5cdFx0aWYgKHR5cGVvZihldmVudEhhbmRsZXIpID09PSAnZnVuY3Rpb24nKSB0aGlzLm9uKCdtaWRpRXZlbnQnLCBldmVudEhhbmRsZXIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIExvYWQgYSBmaWxlIGludG8gdGhlIHBsYXllciAoTm9kZS5qcyBvbmx5KS5cblx0ICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBQYXRoIG9mIGZpbGUuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWRGaWxlKHBhdGgpIHtcblx0XHR2YXIgZnMgPSByZXF1aXJlKCdmcycpO1xuXHRcdHRoaXMuYnVmZmVyID0gZnMucmVhZEZpbGVTeW5jKHBhdGgpO1xuXHRcdHJldHVybiB0aGlzLmZpbGVMb2FkZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBMb2FkIGFuIGFycmF5IGJ1ZmZlciBpbnRvIHRoZSBwbGF5ZXIuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGFycmF5QnVmZmVyIC0gQXJyYXkgYnVmZmVyIG9mIGZpbGUgdG8gYmUgbG9hZGVkLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRsb2FkQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIpIHtcblx0XHR0aGlzLmJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKTtcblx0XHRyZXR1cm4gdGhpcy5maWxlTG9hZGVkKCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCBhIGRhdGEgVVJJIGludG8gdGhlIHBsYXllci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGRhdGFVcmkgLSBEYXRhIFVSSSB0byBiZSBsb2FkZWQuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGxvYWREYXRhVXJpKGRhdGFVcmkpIHtcblx0XHQvLyBjb252ZXJ0IGJhc2U2NCB0byByYXcgYmluYXJ5IGRhdGEgaGVsZCBpbiBhIHN0cmluZy5cblx0XHQvLyBkb2Vzbid0IGhhbmRsZSBVUkxFbmNvZGVkIERhdGFVUklzIC0gc2VlIFNPIGFuc3dlciAjNjg1MDI3NiBmb3IgY29kZSB0aGF0IGRvZXMgdGhpc1xuXHRcdHZhciBieXRlU3RyaW5nID0gVXRpbHMuYXRvYihkYXRhVXJpLnNwbGl0KCcsJylbMV0pO1xuXG5cdFx0Ly8gd3JpdGUgdGhlIGJ5dGVzIG9mIHRoZSBzdHJpbmcgdG8gYW4gQXJyYXlCdWZmZXJcblx0XHR2YXIgaWEgPSBuZXcgVWludDhBcnJheShieXRlU3RyaW5nLmxlbmd0aCk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBieXRlU3RyaW5nLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRpYVtpXSA9IGJ5dGVTdHJpbmcuY2hhckNvZGVBdChpKTtcblx0XHR9XG5cblx0XHR0aGlzLmJ1ZmZlciA9IGlhO1xuXHRcdHJldHVybiB0aGlzLmZpbGVMb2FkZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgZmlsZXNpemUgb2YgbG9hZGVkIGZpbGUgaW4gbnVtYmVyIG9mIGJ5dGVzLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9IC0gVGhlIGZpbGVzaXplLlxuXHQgKi9cblx0Z2V0RmlsZXNpemUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuYnVmZmVyID8gdGhpcy5idWZmZXIubGVuZ3RoIDogMDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIGRlZmF1bHQgdGVtcG8sIHBhcnNlcyBmaWxlIGZvciBuZWNlc3NhcnkgaW5mb3JtYXRpb24sIGFuZCBkb2VzIGEgZHJ5IHJ1biB0byBjYWxjdWxhdGUgdG90YWwgbGVuZ3RoLlxuXHQgKiBQb3B1bGF0ZXMgdGhpcy5ldmVudHMgJiB0aGlzLnRvdGFsVGlja3MuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGZpbGVMb2FkZWQoKSB7XG5cdFx0aWYgKCF0aGlzLnZhbGlkYXRlKCkpIHRocm93ICdJbnZhbGlkIE1JREkgZmlsZTsgc2hvdWxkIHN0YXJ0IHdpdGggTVRoZCc7XG5cdFx0cmV0dXJuIHRoaXMuc2V0VGVtcG8odGhpcy5kZWZhdWx0VGVtcG8pLmdldERpdmlzaW9uKCkuZ2V0Rm9ybWF0KCkuZ2V0VHJhY2tzKCkuZHJ5UnVuKCk7XG5cdH1cblxuXHQvKipcblx0ICogVmFsaWRhdGVzIGZpbGUgdXNpbmcgc2ltcGxlIG1lYW5zIC0gZmlyc3QgZm91ciBieXRlcyBzaG91bGQgPT0gTVRoZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdHZhbGlkYXRlKCkge1xuXHRcdHJldHVybiBVdGlscy5ieXRlc1RvTGV0dGVycyh0aGlzLmJ1ZmZlci5zdWJhcnJheSgwLCA0KSkgPT09ICdNVGhkJztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIE1JREkgZmlsZSBmb3JtYXQgZm9yIGxvYWRlZCBmaWxlLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRnZXRGb3JtYXQoKSB7XG5cdFx0Lypcblx0XHRNSURJIGZpbGVzIGNvbWUgaW4gMyB2YXJpYXRpb25zOlxuXHRcdEZvcm1hdCAwIHdoaWNoIGNvbnRhaW4gYSBzaW5nbGUgdHJhY2tcblx0XHRGb3JtYXQgMSB3aGljaCBjb250YWluIG9uZSBvciBtb3JlIHNpbXVsdGFuZW91cyB0cmFja3Ncblx0XHQoaWUgYWxsIHRyYWNrcyBhcmUgdG8gYmUgcGxheWVkIHNpbXVsdGFuZW91c2x5KS5cblx0XHRGb3JtYXQgMiB3aGljaCBjb250YWluIG9uZSBvciBtb3JlIGluZGVwZW5kYW50IHRyYWNrc1xuXHRcdChpZSBlYWNoIHRyYWNrIGlzIHRvIGJlIHBsYXllZCBpbmRlcGVuZGFudGx5IG9mIHRoZSBvdGhlcnMpLlxuXHRcdHJldHVybiBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuYnVmZmVyLnN1YmFycmF5KDgsIDEwKSk7XG5cdFx0Ki9cblxuXHRcdHRoaXMuZm9ybWF0ID0gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmJ1ZmZlci5zdWJhcnJheSg4LCAxMCkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnNlcyBvdXQgdHJhY2tzLCBwbGFjZXMgdGhlbSBpbiB0aGlzLnRyYWNrcyBhbmQgaW5pdGlhbGl6ZXMgdGhpcy5wb2ludGVyc1xuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRnZXRUcmFja3MoKSB7XG5cdFx0dGhpcy50cmFja3MgPSBbXTtcblx0XHRsZXQgdHJhY2tPZmZzZXQgPSAwO1xuXHRcdHdoaWxlICh0cmFja09mZnNldCA8IHRoaXMuYnVmZmVyLmxlbmd0aCkge1xuXHRcdFx0aWYgKFV0aWxzLmJ5dGVzVG9MZXR0ZXJzKHRoaXMuYnVmZmVyLnN1YmFycmF5KHRyYWNrT2Zmc2V0LCB0cmFja09mZnNldCArIDQpKSA9PSAnTVRyaycpIHtcblx0XHRcdFx0bGV0IHRyYWNrTGVuZ3RoID0gVXRpbHMuYnl0ZXNUb051bWJlcih0aGlzLmJ1ZmZlci5zdWJhcnJheSh0cmFja09mZnNldCArIDQsIHRyYWNrT2Zmc2V0ICsgOCkpO1xuXHRcdFx0XHR0aGlzLnRyYWNrcy5wdXNoKG5ldyBUcmFjayh0aGlzLnRyYWNrcy5sZW5ndGgsIHRoaXMuYnVmZmVyLnN1YmFycmF5KHRyYWNrT2Zmc2V0ICsgOCwgdHJhY2tPZmZzZXQgKyA4ICsgdHJhY2tMZW5ndGgpKSk7XG5cdFx0XHR9XG5cblx0XHRcdHRyYWNrT2Zmc2V0ICs9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkodHJhY2tPZmZzZXQgKyA0LCB0cmFja09mZnNldCArIDgpKSArIDg7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEVuYWJsZXMgYSB0cmFjayBmb3IgcGxheWluZy5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHRyYWNrTnVtYmVyIC0gVHJhY2sgbnVtYmVyXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGVuYWJsZVRyYWNrKHRyYWNrTnVtYmVyKSB7XG5cdFx0dGhpcy50cmFja3NbdHJhY2tOdW1iZXIgLSAxXS5lbmFibGUoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNhYmxlcyBhIHRyYWNrIGZvciBwbGF5aW5nLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUcmFjayBudW1iZXJcblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0ZGlzYWJsZVRyYWNrKHRyYWNrTnVtYmVyKSB7XG5cdFx0dGhpcy50cmFja3NbdHJhY2tOdW1iZXIgLSAxXS5kaXNhYmxlKCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBxdWFydGVyIG5vdGUgZGl2aXNpb24gb2YgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0Z2V0RGl2aXNpb24oKSB7XG5cdFx0dGhpcy5kaXZpc2lvbiA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIodGhpcy5idWZmZXIuc3ViYXJyYXkoMTIsIDE0KSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIG1haW4gcGxheSBsb29wLlxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IC0gSW5kaWNhdGVzIHdoZXRoZXIgb3Igbm90IHRoaXMgaXMgYmVpbmcgY2FsbGVkIHNpbXBseSBmb3IgcGFyc2luZyBwdXJwb3Nlcy4gIERpc3JlZ2FyZHMgdGltaW5nIGlmIHNvLlxuXHQgKiBAcmV0dXJuIHt1bmRlZmluZWR9XG5cdCAqL1xuXHRwbGF5TG9vcChkcnlSdW4pIHtcblx0XHRpZiAoIXRoaXMuaW5Mb29wKSB7XG5cdFx0XHR0aGlzLmluTG9vcCA9IHRydWU7XG5cdFx0XHR0aGlzLnRpY2sgPSB0aGlzLmdldEN1cnJlbnRUaWNrKCk7XG5cblx0XHRcdHRoaXMudHJhY2tzLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcblx0XHRcdFx0Ly8gSGFuZGxlIG5leHQgZXZlbnRcblx0XHRcdFx0aWYgKCFkcnlSdW4gJiYgdGhpcy5lbmRPZkZpbGUoKSkge1xuXHRcdFx0XHRcdC8vY29uc29sZS5sb2coJ2VuZCBvZiBmaWxlJylcblx0XHRcdFx0XHR0aGlzLnRyaWdnZXJQbGF5ZXJFdmVudCgnZW5kT2ZGaWxlJyk7XG5cdFx0XHRcdFx0dGhpcy5zdG9wKCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bGV0IGV2ZW50ID0gdHJhY2suaGFuZGxlRXZlbnQodGhpcy50aWNrLCBkcnlSdW4pO1xuXG5cdFx0XHRcdFx0aWYgKGRyeVJ1biAmJiBldmVudCkge1xuXHRcdFx0XHRcdFx0aWYgKGV2ZW50Lmhhc093blByb3BlcnR5KCduYW1lJykgJiYgZXZlbnQubmFtZSA9PT0gJ1NldCBUZW1wbycpIHtcblx0XHRcdFx0XHRcdFx0Ly8gR3JhYiB0ZW1wbyBpZiBhdmFpbGFibGUuXG5cdFx0XHRcdFx0XHRcdHRoaXMuc2V0VGVtcG8oZXZlbnQuZGF0YSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoZXZlbnQuaGFzT3duUHJvcGVydHkoJ25hbWUnKSAmJiBldmVudC5uYW1lID09PSAnUHJvZ3JhbSBDaGFuZ2UnKSB7XG5cdFx0XHRcdFx0XHRcdGlmICghdGhpcy5pbnN0cnVtZW50cy5pbmNsdWRlcyhldmVudC52YWx1ZSkpIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmluc3RydW1lbnRzLnB1c2goZXZlbnQudmFsdWUpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChldmVudCkgdGhpcy5lbWl0RXZlbnQoZXZlbnQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdH0sIHRoaXMpO1xuXG5cdFx0XHRpZiAoIWRyeVJ1bikgdGhpcy50cmlnZ2VyUGxheWVyRXZlbnQoJ3BsYXlpbmcnLCB7dGljazogdGhpcy50aWNrfSk7XG5cdFx0XHR0aGlzLmluTG9vcCA9IGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTZXR0ZXIgZm9yIHRlbXBvLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUZW1wbyBpbiBicG0gKGRlZmF1bHRzIHRvIDEyMClcblx0ICovXG5cdHNldFRlbXBvKHRlbXBvKSB7XG5cdFx0dGhpcy50ZW1wbyA9IHRlbXBvO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHRlciBmb3Igc3RhcnRUaW1lLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBVVEMgdGltZXN0YW1wXG5cdCAqL1xuXHRzZXRTdGFydFRpbWUoc3RhcnRUaW1lKSB7XG5cdFx0dGhpcy5zdGFydFRpbWUgPSBzdGFydFRpbWU7XG5cdH1cblxuXHQvKipcblx0ICogU3RhcnQgcGxheWluZyBsb2FkZWQgTUlESSBmaWxlIGlmIG5vdCBhbHJlYWR5IHBsYXlpbmcuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHBsYXkoKSB7XG5cdFx0aWYgKHRoaXMuaXNQbGF5aW5nKCkpIHRocm93ICdBbHJlYWR5IHBsYXlpbmcuLi4nO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZVxuXHRcdGlmICghdGhpcy5zdGFydFRpbWUpIHRoaXMuc3RhcnRUaW1lID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcblxuXHRcdC8vIFN0YXJ0IHBsYXkgbG9vcFxuXHRcdC8vd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnBsYXlMb29wLmJpbmQodGhpcykpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IHNldEludGVydmFsKHRoaXMucGxheUxvb3AuYmluZCh0aGlzKSwgdGhpcy5zYW1wbGVSYXRlKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhdXNlcyBwbGF5YmFjayBpZiBwbGF5aW5nLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHRwYXVzZSgpIHtcblx0XHRjbGVhckludGVydmFsKHRoaXMuc2V0SW50ZXJ2YWxJZCk7XG5cdFx0dGhpcy5zZXRJbnRlcnZhbElkID0gZmFsc2U7XG5cdFx0dGhpcy5zdGFydFRpY2sgPSB0aGlzLnRpY2s7XG5cdFx0dGhpcy5zdGFydFRpbWUgPSAwO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN0b3BzIHBsYXliYWNrIGlmIHBsYXlpbmcuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHN0b3AoKSB7XG5cdFx0Y2xlYXJJbnRlcnZhbCh0aGlzLnNldEludGVydmFsSWQpO1xuXHRcdHRoaXMuc2V0SW50ZXJ2YWxJZCA9IGZhbHNlO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gMDtcblx0XHR0aGlzLnN0YXJ0VGltZSA9IDA7XG5cdFx0dGhpcy5yZXNldFRyYWNrcygpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNraXBzIHBsYXllciBwb2ludGVyIHRvIHNwZWNpZmllZCB0aWNrLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBUaWNrIHRvIHNraXAgdG8uXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1RpY2sodGljaykge1xuXHRcdHRoaXMuc3RvcCgpO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gdGljaztcblxuXHRcdC8vIE5lZWQgdG8gc2V0IHRyYWNrIGV2ZW50IGluZGV4ZXMgdG8gdGhlIG5lYXJlc3QgcG9zc2libGUgZXZlbnQgdG8gdGhlIHNwZWNpZmllZCB0aWNrLlxuXHRcdHRoaXMudHJhY2tzLmZvckVhY2goZnVuY3Rpb24odHJhY2spIHtcblx0XHRcdHRyYWNrLnNldEV2ZW50SW5kZXhCeVRpY2sodGljayk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2tpcHMgcGxheWVyIHBvaW50ZXIgdG8gc3BlY2lmaWVkIHBlcmNlbnRhZ2UuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSAtIFBlcmNlbnQgdmFsdWUgaW4gaW50ZWdlciBmb3JtYXQuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1BlcmNlbnQocGVyY2VudCkge1xuXHRcdGlmIChwZXJjZW50IDwgMCB8fCBwZXJjZW50ID4gMTAwKSB0aHJvdyBcIlBlcmNlbnQgbXVzdCBiZSBudW1iZXIgYmV0d2VlbiAxIGFuZCAxMDAuXCI7XG5cdFx0dGhpcy5za2lwVG9UaWNrKE1hdGgucm91bmQocGVyY2VudCAvIDEwMCAqIHRoaXMudG90YWxUaWNrcykpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNraXBzIHBsYXllciBwb2ludGVyIHRvIHNwZWNpZmllZCBzZWNvbmRzLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gLSBTZWNvbmRzIHRvIHNraXAgdG8uXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdHNraXBUb1NlY29uZHMoc2Vjb25kcykge1xuXHRcdHZhciBzb25nVGltZSA9IHRoaXMuZ2V0U29uZ1RpbWUoKTtcblx0XHRpZiAoc2Vjb25kcyA8IDAgfHwgc2Vjb25kcyA+IHNvbmdUaW1lKSB0aHJvdyBzZWNvbmRzICsgXCIgc2Vjb25kcyBub3Qgd2l0aGluIHNvbmcgdGltZSBvZiBcIiArIHNvbmdUaW1lO1xuXHRcdHRoaXMuc2tpcFRvUGVyY2VudChzZWNvbmRzIC8gc29uZ1RpbWUgKiAxMDApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrcyBpZiBwbGF5ZXIgaXMgcGxheWluZ1xuXHQgKiBAcmV0dXJuIHtib29sZWFufVxuXHQgKi9cblx0aXNQbGF5aW5nKCkge1xuXHRcdHJldHVybiB0aGlzLnNldEludGVydmFsSWQgPiAwIHx8IHR5cGVvZiB0aGlzLnNldEludGVydmFsSWQgPT09ICdvYmplY3QnO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBsYXlzIHRoZSBsb2FkZWQgTUlESSBmaWxlIHdpdGhvdXQgcmVnYXJkIGZvciB0aW1pbmcgYW5kIHNhdmVzIGV2ZW50cyBpbiB0aGlzLmV2ZW50cy4gIEVzc2VudGlhbGx5IHVzZWQgYXMgYSBwYXJzZXIuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGRyeVJ1bigpIHtcblx0XHQvLyBSZXNldCB0cmFja3MgZmlyc3Rcblx0XHR0aGlzLnJlc2V0VHJhY2tzKCk7XG5cdFx0d2hpbGUgKCF0aGlzLmVuZE9mRmlsZSgpKSB0aGlzLnBsYXlMb29wKHRydWUpO1xuXHRcdHRoaXMuZXZlbnRzID0gdGhpcy5nZXRFdmVudHMoKTtcblx0XHR0aGlzLnRvdGFsRXZlbnRzID0gdGhpcy5nZXRUb3RhbEV2ZW50cygpO1xuXHRcdHRoaXMudG90YWxUaWNrcyA9IHRoaXMuZ2V0VG90YWxUaWNrcygpO1xuXHRcdHRoaXMuc3RhcnRUaWNrID0gMDtcblx0XHR0aGlzLnN0YXJ0VGltZSA9IDA7XG5cblx0XHQvLyBMZWF2ZSB0cmFja3MgaW4gcHJpc3RpbmUgY29uZGlzaFxuXHRcdHRoaXMucmVzZXRUcmFja3MoKTtcblxuXHRcdC8vY29uc29sZS5sb2coJ1NvbmcgdGltZTogJyArIHRoaXMuZ2V0U29uZ1RpbWUoKSArICcgc2Vjb25kcyAvICcgKyB0aGlzLnRvdGFsVGlja3MgKyAnIHRpY2tzLicpO1xuXG5cdFx0dGhpcy50cmlnZ2VyUGxheWVyRXZlbnQoJ2ZpbGVMb2FkZWQnLCB0aGlzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNldHMgcGxheSBwb2ludGVycyBmb3IgYWxsIHRyYWNrcy5cblx0ICogQHJldHVybiB7UGxheWVyfVxuXHQgKi9cblx0cmVzZXRUcmFja3MoKSB7XG5cdFx0dGhpcy50cmFja3MuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5yZXNldCgpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIGFuIGFycmF5IG9mIGV2ZW50cyBncm91cGVkIGJ5IHRyYWNrLlxuXHQgKiBAcmV0dXJuIHthcnJheX1cblx0ICovXG5cdGdldEV2ZW50cygpIHtcblx0XHRyZXR1cm4gdGhpcy50cmFja3MubWFwKHRyYWNrID0+IHRyYWNrLmV2ZW50cyk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyB0b3RhbCBudW1iZXIgb2YgdGlja3MgaW4gdGhlIGxvYWRlZCBNSURJIGZpbGUuXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdGdldFRvdGFsVGlja3MoKSB7XG5cdFx0cmV0dXJuIE1hdGgubWF4LmFwcGx5KG51bGwsIHRoaXMudHJhY2tzLm1hcCh0cmFjayA9PiB0cmFjay5kZWx0YSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdG90YWwgbnVtYmVyIG9mIGV2ZW50cyBpbiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0VG90YWxFdmVudHMoKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJhY2tzLnJlZHVjZSgoYSwgYikgPT4ge3JldHVybiB7ZXZlbnRzOiB7bGVuZ3RoOiBhLmV2ZW50cy5sZW5ndGggKyBiLmV2ZW50cy5sZW5ndGh9fX0sIHtldmVudHM6IHtsZW5ndGg6IDB9fSkuZXZlbnRzLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHNvbmcgZHVyYXRpb24gaW4gc2Vjb25kcy5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1RpbWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMudG90YWxUaWNrcyAvIHRoaXMuZGl2aXNpb24gLyB0aGlzLnRlbXBvICogNjA7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgbnVtYmVyIG9mIHNlY29uZHMgaW4gcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge251bWJlcn1cblx0ICovXG5cdGdldFNvbmdUaW1lUmVtYWluaW5nKCkge1xuXHRcdHJldHVybiBNYXRoLnJvdW5kKCh0aGlzLnRvdGFsVGlja3MgLSB0aGlzLnRpY2spIC8gdGhpcy5kaXZpc2lvbiAvIHRoaXMudGVtcG8gKiA2MCk7XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyByZW1haW5pbmcgcGVyY2VudCBvZiBwbGF5YmFjay5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0U29uZ1BlcmNlbnRSZW1haW5pbmcoKSB7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQodGhpcy5nZXRTb25nVGltZVJlbWFpbmluZygpIC8gdGhpcy5nZXRTb25nVGltZSgpICogMTAwKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOdW1iZXIgb2YgYnl0ZXMgcHJvY2Vzc2VkIGluIHRoZSBsb2FkZWQgTUlESSBmaWxlLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRieXRlc1Byb2Nlc3NlZCgpIHtcblx0XHQvLyBDdXJyZW50bHkgYXNzdW1lIGhlYWRlciBjaHVuayBpcyBzdHJpY3RseSAxNCBieXRlc1xuXHRcdHJldHVybiAxNCArIHRoaXMudHJhY2tzLmxlbmd0aCAqIDggKyB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHtyZXR1cm4ge3BvaW50ZXI6IGEucG9pbnRlciArIGIucG9pbnRlcn19LCB7cG9pbnRlcjogMH0pLnBvaW50ZXI7XG5cdH1cblxuXHQvKipcblx0ICogTnVtYmVyIG9mIGV2ZW50cyBwbGF5ZWQgdXAgdG8gdGhpcyBwb2ludC5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0ZXZlbnRzUGxheWVkKCkge1xuXHRcdHJldHVybiB0aGlzLnRyYWNrcy5yZWR1Y2UoKGEsIGIpID0+IHtyZXR1cm4ge2V2ZW50SW5kZXg6IGEuZXZlbnRJbmRleCArIGIuZXZlbnRJbmRleH19LCB7ZXZlbnRJbmRleDogMH0pLmV2ZW50SW5kZXg7XG5cdH1cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgcGxheWVyIHBvaW50ZXIgaGFzIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgbG9hZGVkIE1JREkgZmlsZS5cblx0ICogVXNlZCBpbiB0d28gd2F5czpcblx0ICogMS4gSWYgcGxheWluZyByZXN1bHQgaXMgYmFzZWQgb24gbG9hZGVkIEpTT04gZXZlbnRzLlxuXHQgKiAyLiBJZiBwYXJzaW5nIChkcnlSdW4pIGl0J3MgYmFzZWQgb24gdGhlIGFjdHVhbCBidWZmZXIgbGVuZ3RoIHZzIGJ5dGVzIHByb2Nlc3NlZC5cblx0ICogQHJldHVybiB7Ym9vbGVhbn1cblx0ICovXG5cdGVuZE9mRmlsZSgpIHtcblx0XHRpZiAodGhpcy5pc1BsYXlpbmcoKSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZXZlbnRzUGxheWVkKCkgPT0gdGhpcy50b3RhbEV2ZW50cztcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5ieXRlc1Byb2Nlc3NlZCgpID09IHRoaXMuYnVmZmVyLmxlbmd0aDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSBjdXJyZW50IHRpY2sgbnVtYmVyIGluIHBsYXliYWNrLlxuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRnZXRDdXJyZW50VGljaygpIHtcblx0XHRyZXR1cm4gTWF0aC5yb3VuZCgoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHRoaXMuc3RhcnRUaW1lKSAvIDEwMDAgKiAodGhpcy5kaXZpc2lvbiAqICh0aGlzLnRlbXBvIC8gNjApKSkgKyB0aGlzLnN0YXJ0VGljaztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZW5kcyBNSURJIGV2ZW50IG91dCB0byBsaXN0ZW5lci5cblx0ICogQHBhcmFtIHtvYmplY3R9XG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdGVtaXRFdmVudChldmVudCkge1xuXHRcdHRoaXMudHJpZ2dlclBsYXllckV2ZW50KCdtaWRpRXZlbnQnLCBldmVudCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU3Vic2NyaWJlcyBldmVudHMgdG8gbGlzdGVuZXJzXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSAtIE5hbWUgb2YgZXZlbnQgdG8gc3Vic2NyaWJlIHRvLlxuXHQgKiBAcGFyYW0ge2Z1bmN0aW9ufSAtIENhbGxiYWNrIHRvIGZpcmUgd2hlbiBldmVudCBpcyBicm9hZGNhc3QuXG5cdCAqIEByZXR1cm4ge1BsYXllcn1cblx0ICovXG5cdG9uKHBsYXllckV2ZW50LCBmbikge1xuXHRcdGlmICghdGhpcy5ldmVudExpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShwbGF5ZXJFdmVudCkpIHRoaXMuZXZlbnRMaXN0ZW5lcnNbcGxheWVyRXZlbnRdID0gW107XG5cdFx0dGhpcy5ldmVudExpc3RlbmVyc1twbGF5ZXJFdmVudF0ucHVzaChmbik7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogQnJvYWRjYXN0cyBldmVudCB0byB0cmlnZ2VyIHN1YnNjcmliZWQgY2FsbGJhY2tzLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gLSBOYW1lIG9mIGV2ZW50LlxuXHQgKiBAcGFyYW0ge29iamVjdH0gLSBEYXRhIHRvIGJlIHBhc3NlZCB0byBzdWJzY3JpYmVyIGNhbGxiYWNrLlxuXHQgKiBAcmV0dXJuIHtQbGF5ZXJ9XG5cdCAqL1xuXHR0cmlnZ2VyUGxheWVyRXZlbnQocGxheWVyRXZlbnQsIGRhdGEpIHtcblx0XHRpZiAodGhpcy5ldmVudExpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShwbGF5ZXJFdmVudCkpIHRoaXMuZXZlbnRMaXN0ZW5lcnNbcGxheWVyRXZlbnRdLmZvckVhY2goZm4gPT4gZm4oZGF0YSB8fCB7fSkpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cbn1cblxuZXhwb3J0cy5QbGF5ZXIgPSBQbGF5ZXI7XG4iLCJjb25zdCBDb25zdGFudHMgPSByZXF1aXJlKFwiLi9jb25zdGFudHNcIikuQ29uc3RhbnRzO1xuY29uc3QgVXRpbHMgPSByZXF1aXJlKFwiLi91dGlsc1wiKS5VdGlscztcblxuLyoqXG4gKiBDbGFzcyByZXByZXNlbnRpbmcgYSB0cmFjay4gIENvbnRhaW5zIG1ldGhvZHMgZm9yIHBhcnNpbmcgZXZlbnRzIGFuZCBrZWVwaW5nIHRyYWNrIG9mIHBvaW50ZXIuXG4gKi9cbmNsYXNzIFRyYWNrXHR7XG5cdGNvbnN0cnVjdG9yKGluZGV4LCBkYXRhKSB7XG5cdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblx0XHR0aGlzLmV2ZW50SW5kZXggPSAwO1xuXHRcdHRoaXMucG9pbnRlciA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IDA7XG5cdFx0dGhpcy5sYXN0U3RhdHVzID0gbnVsbDtcblx0XHR0aGlzLmluZGV4ID0gaW5kZXg7XG5cdFx0dGhpcy5kYXRhID0gZGF0YTtcblx0XHR0aGlzLmRlbHRhID0gMDtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSA9IDA7XG5cdFx0dGhpcy5ldmVudHMgPSBbXTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXNldHMgYWxsIHN0YXRlZnVsIHRyYWNrIGluZm9ybWFpb24gdXNlZCBkdXJpbmcgcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge1RyYWNrfVxuXHQgKi9cblx0cmVzZXQoKSB7XG5cdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblx0XHR0aGlzLmV2ZW50SW5kZXggPSAwO1xuXHRcdHRoaXMucG9pbnRlciA9IDA7XG5cdFx0dGhpcy5sYXN0VGljayA9IDA7XG5cdFx0dGhpcy5sYXN0U3RhdHVzID0gbnVsbDtcblx0XHR0aGlzLmRlbHRhID0gMDtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSA9IDA7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxuXHQvKipcblx0ICogU2V0cyB0aGlzIHRyYWNrIHRvIGJlIGVuYWJsZWQgZHVyaW5nIHBsYXliYWNrLlxuXHQgKiBAcmV0dXJuIHtUcmFja31cblx0ICovXG5cdGVuYWJsZSgpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgdGhpcyB0cmFjayB0byBiZSBkaXNhYmxlZCBkdXJpbmcgcGxheWJhY2suXG5cdCAqIEByZXR1cm4ge1RyYWNrfVxuXHQgKi9cblx0ZGlzYWJsZSgpIHtcblx0XHR0aGlzLmVuYWJsZWQgPSBmYWxzZTtcblx0XHRyZXR1cm4gdGhpcztcblx0fVxuXG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0cmFjayBldmVudCBpbmRleCB0byB0aGUgbmVhcmVzdCBldmVudCB0byB0aGUgZ2l2ZW4gdGljay5cblx0ICogQHBhcmFtIHtudW1iZXJ9IHRpY2tcblx0ICogQHJldHVybiB7VHJhY2t9XG5cdCAqL1xuXHRzZXRFdmVudEluZGV4QnlUaWNrKHRpY2spIHtcblx0XHR0aWNrID0gdGljayB8fCAwO1xuXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLmV2ZW50cykge1xuXHRcdFx0aWYgKHRoaXMuZXZlbnRzW2ldLnRpY2sgPj0gdGljaykge1xuXHRcdFx0XHR0aGlzLmV2ZW50SW5kZXggPSBpO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogR2V0cyBieXRlIGxvY2F0ZWQgYXQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0Q3VycmVudEJ5dGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuZGF0YVt0aGlzLnBvaW50ZXJdO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgY291bnQgb2YgZGVsdGEgYnl0ZXMgYW5kIGN1cnJlbnQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0RGVsdGFCeXRlQ291bnQoKSB7XG5cdFx0Ly8gR2V0IGJ5dGUgY291bnQgb2YgZGVsdGEgVkxWXG5cdFx0Ly8gaHR0cDovL3d3dy5jY2FyaC5vcmcvY291cnNlcy8yNTMvaGFuZG91dC92bHYvXG5cdFx0Ly8gSWYgYnl0ZSBpcyBncmVhdGVyIG9yIGVxdWFsIHRvIDgwaCAoMTI4IGRlY2ltYWwpIHRoZW4gdGhlIG5leHQgYnl0ZVxuXHQgICAgLy8gaXMgYWxzbyBwYXJ0IG9mIHRoZSBWTFYsXG5cdCAgIFx0Ly8gZWxzZSBieXRlIGlzIHRoZSBsYXN0IGJ5dGUgaW4gYSBWTFYuXG5cdCAgIFx0dmFyIGN1cnJlbnRCeXRlID0gdGhpcy5nZXRDdXJyZW50Qnl0ZSgpO1xuXHQgICBcdHZhciBieXRlQ291bnQgPSAxO1xuXG5cdFx0d2hpbGUgKGN1cnJlbnRCeXRlID49IDEyOCkge1xuXHRcdFx0Y3VycmVudEJ5dGUgPSB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgYnl0ZUNvdW50XTtcblx0XHRcdGJ5dGVDb3VudCsrO1xuXHRcdH1cblxuXHRcdHJldHVybiBieXRlQ291bnQ7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IGRlbHRhIHZhbHVlIGF0IGN1cnJlbnQgcG9pbnRlciBwb3NpdGlvbi5cblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0Z2V0RGVsdGEoKSB7XG5cdFx0cmV0dXJuIFV0aWxzLnJlYWRWYXJJbnQodGhpcy5kYXRhLnN1YmFycmF5KHRoaXMucG9pbnRlciwgdGhpcy5wb2ludGVyICsgdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpKSk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlcyBldmVudCB3aXRoaW4gYSBnaXZlbiB0cmFjayBzdGFydGluZyBhdCBzcGVjaWZpZWQgaW5kZXhcblx0ICogQHBhcmFtIHtudW1iZXJ9IGN1cnJlbnRUaWNrXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gZHJ5UnVuIC0gSWYgdHJ1ZSBldmVudHMgd2lsbCBiZSBwYXJzZWQgYW5kIHJldHVybmVkIHJlZ2FyZGxlc3Mgb2YgdGltZS5cblx0ICovXG5cdGhhbmRsZUV2ZW50KGN1cnJlbnRUaWNrLCBkcnlSdW4pIHtcblx0XHRkcnlSdW4gPSBkcnlSdW4gfHwgZmFsc2U7XG5cblx0XHRpZiAoZHJ5UnVuKSB7XG5cdFx0XHR2YXIgZWxhcHNlZFRpY2tzID0gY3VycmVudFRpY2sgLSB0aGlzLmxhc3RUaWNrO1xuXHRcdFx0dmFyIGRlbHRhID0gdGhpcy5nZXREZWx0YSgpO1xuXHRcdFx0dmFyIGV2ZW50UmVhZHkgPSBlbGFwc2VkVGlja3MgPj0gZGVsdGE7XG5cblx0XHRcdGlmICh0aGlzLnBvaW50ZXIgPCB0aGlzLmRhdGEubGVuZ3RoICYmIChkcnlSdW4gfHwgZXZlbnRSZWFkeSkpIHtcblx0XHRcdFx0bGV0IGV2ZW50ID0gdGhpcy5wYXJzZUV2ZW50KCk7XG5cdFx0XHRcdGlmICh0aGlzLmVuYWJsZWQpIHJldHVybiBldmVudDtcblx0XHRcdFx0Ly8gUmVjdXJzaXZlbHkgY2FsbCB0aGlzIGZ1bmN0aW9uIGZvciBlYWNoIGV2ZW50IGFoZWFkIHRoYXQgaGFzIDAgZGVsdGEgdGltZT9cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBMZXQncyBhY3R1YWxseSBwbGF5IHRoZSBNSURJIGZyb20gdGhlIGdlbmVyYXRlZCBKU09OIGV2ZW50cyBjcmVhdGVkIGJ5IHRoZSBkcnkgcnVuLlxuXHRcdFx0aWYgKHRoaXMuZXZlbnRzW3RoaXMuZXZlbnRJbmRleF0gJiYgdGhpcy5ldmVudHNbdGhpcy5ldmVudEluZGV4XS50aWNrIDw9IGN1cnJlbnRUaWNrKSB7XG5cdFx0XHRcdHRoaXMuZXZlbnRJbmRleCsrO1xuXHRcdFx0XHRpZiAodGhpcy5lbmFibGVkKSByZXR1cm4gdGhpcy5ldmVudHNbdGhpcy5ldmVudEluZGV4IC0gMV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHN0cmluZyBkYXRhIGZyb20gZXZlbnQuXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBldmVudFN0YXJ0SW5kZXhcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0Z2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpIHtcblx0XHR2YXIgY3VycmVudEJ5dGUgPSB0aGlzLnBvaW50ZXI7XG5cdFx0dmFyIGJ5dGVDb3VudCA9IDE7XG5cdFx0dmFyIGxlbmd0aCA9IFV0aWxzLnJlYWRWYXJJbnQodGhpcy5kYXRhLnN1YmFycmF5KGV2ZW50U3RhcnRJbmRleCArIDIsIGV2ZW50U3RhcnRJbmRleCArIDIgKyBieXRlQ291bnQpKTtcblx0XHR2YXIgc3RyaW5nTGVuZ3RoID0gbGVuZ3RoO1xuXG5cdFx0cmV0dXJuIFV0aWxzLmJ5dGVzVG9MZXR0ZXJzKHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyAyLCBldmVudFN0YXJ0SW5kZXggKyBieXRlQ291bnQgKyBsZW5ndGggKyAyKSk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2VzIGV2ZW50IGludG8gSlNPTiBhbmQgYWR2YW5jZXMgcG9pbnRlciBmb3IgdGhlIHRyYWNrXG5cdCAqIEByZXR1cm4ge29iamVjdH1cblx0ICovXG5cdHBhcnNlRXZlbnQoKSB7XG5cdFx0dmFyIGV2ZW50U3RhcnRJbmRleCA9IHRoaXMucG9pbnRlciArIHRoaXMuZ2V0RGVsdGFCeXRlQ291bnQoKTtcblx0XHR2YXIgZXZlbnRKc29uID0ge307XG5cdFx0dmFyIGRlbHRhQnl0ZUNvdW50ID0gdGhpcy5nZXREZWx0YUJ5dGVDb3VudCgpO1xuXHRcdGV2ZW50SnNvbi50cmFjayA9IHRoaXMuaW5kZXggKyAxO1xuXHRcdGV2ZW50SnNvbi5kZWx0YSA9IHRoaXMuZ2V0RGVsdGEoKTtcblx0XHR0aGlzLmxhc3RUaWNrID0gdGhpcy5sYXN0VGljayArIGV2ZW50SnNvbi5kZWx0YTtcblx0XHR0aGlzLnJ1bm5pbmdEZWx0YSArPSBldmVudEpzb24uZGVsdGE7XG5cdFx0ZXZlbnRKc29uLnRpY2sgPSB0aGlzLnJ1bm5pbmdEZWx0YTtcblx0XHRldmVudEpzb24uYnl0ZUluZGV4ID0gdGhpcy5wb2ludGVyO1xuXG5cdFx0Ly9ldmVudEpzb24ucmF3ID0gZXZlbnQ7XG5cdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdID09IDB4ZmYpIHtcblx0XHRcdC8vIE1ldGEgRXZlbnRcblxuXHRcdFx0Ly8gSWYgdGhpcyBpcyBhIG1ldGEgZXZlbnQgd2Ugc2hvdWxkIGVtaXQgdGhlIGRhdGEgYW5kIGltbWVkaWF0ZWx5IG1vdmUgdG8gdGhlIG5leHQgZXZlbnRcblx0XHRcdC8vIG90aGVyd2lzZSBpZiB3ZSBsZXQgaXQgcnVuIHRocm91Z2ggdGhlIG5leHQgY3ljbGUgYSBzbGlnaHQgZGVsYXkgd2lsbCBhY2N1bXVsYXRlIGlmIG11bHRpcGxlIHRyYWNrc1xuXHRcdFx0Ly8gYXJlIGJlaW5nIHBsYXllZCBzaW11bHRhbmVvdXNseVxuXG5cdFx0XHRzd2l0Y2godGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdKSB7XG5cdFx0XHRcdGNhc2UgMHgwMDogLy8gU2VxdWVuY2UgTnVtYmVyXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2VxdWVuY2UgTnVtYmVyJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDAxOiAvLyBUZXh0IEV2ZW50XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVGV4dCBFdmVudCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDI6IC8vIENvcHlyaWdodCBOb3RpY2Vcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdDb3B5cmlnaHQgTm90aWNlJztcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDAzOiAvLyBTZXF1ZW5jZS9UcmFjayBOYW1lXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2VxdWVuY2UvVHJhY2sgTmFtZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDQ6IC8vIEluc3RydW1lbnQgTmFtZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0luc3RydW1lbnQgTmFtZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDU6IC8vIEx5cmljXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTHlyaWMnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDA2OiAvLyBNYXJrZXJcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdNYXJrZXInO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDc6IC8vIEN1ZSBQb2ludFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0N1ZSBQb2ludCc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnN0cmluZyA9IHRoaXMuZ2V0U3RyaW5nRGF0YShldmVudFN0YXJ0SW5kZXgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MDk6IC8vIERldmljZSBOYW1lXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnRGV2aWNlIE5hbWUnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5zdHJpbmcgPSB0aGlzLmdldFN0cmluZ0RhdGEoZXZlbnRTdGFydEluZGV4KTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDIwOiAvLyBNSURJIENoYW5uZWwgUHJlZml4XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTUlESSBDaGFubmVsIFByZWZpeCc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHgyMTogLy8gTUlESSBQb3J0XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTUlESSBQb3J0Jztcblx0XHRcdFx0XHRldmVudEpzb24uZGF0YSA9IFV0aWxzLmJ5dGVzVG9OdW1iZXIoW3RoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAzXV0pO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4MkY6IC8vIEVuZCBvZiBUcmFja1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0VuZCBvZiBUcmFjayc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg1MTogLy8gU2V0IFRlbXBvXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU2V0IFRlbXBvJztcblx0XHRcdFx0XHRldmVudEpzb24uZGF0YSA9IE1hdGgucm91bmQoNjAwMDAwMDAgLyBVdGlscy5ieXRlc1RvTnVtYmVyKHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyAzLCBldmVudFN0YXJ0SW5kZXggKyA2KSkpO1xuXHRcdFx0XHRcdHRoaXMudGVtcG8gPSBldmVudEpzb24uZGF0YTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDU0OiAvLyBTTVRQRSBPZmZzZXRcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdTTVRQRSBPZmZzZXQnO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIDB4NTg6IC8vIFRpbWUgU2lnbmF0dXJlXG5cdFx0XHRcdFx0Ly8gRkYgNTggMDQgbm4gZGQgY2MgYmJcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdUaW1lIFNpZ25hdHVyZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmRhdGEgPSB0aGlzLmRhdGEuc3ViYXJyYXkoZXZlbnRTdGFydEluZGV4ICsgMywgZXZlbnRTdGFydEluZGV4ICsgNyk7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnRpbWVTaWduYXR1cmUgPSBcIlwiICsgZXZlbnRKc29uLmRhdGFbMF0gKyBcIi9cIiArIE1hdGgucG93KGV2ZW50SnNvbi5kYXRhWzFdLCAyKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAweDU5OiAvLyBLZXkgU2lnbmF0dXJlXG5cdFx0XHRcdFx0Ly8gRkYgNTkgMDIgc2YgbWlcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdLZXkgU2lnbmF0dXJlJztcblx0XHRcdFx0XHRldmVudEpzb24uZGF0YSA9IHRoaXMuZGF0YS5zdWJhcnJheShldmVudFN0YXJ0SW5kZXggKyAzLCBldmVudFN0YXJ0SW5kZXggKyA1KTtcblxuXHRcdFx0XHRcdGlmIChldmVudEpzb24uZGF0YVswXSA+PSAwKSB7XG5cdFx0XHRcdFx0XHRldmVudEpzb24ua2V5U2lnbmF0dXJlID0gQ29uc3RhbnRzLkNJUkNMRV9PRl9GSUZUSFNbZXZlbnRKc29uLmRhdGFbMF1dO1xuXG5cdFx0XHRcdFx0fSBlbHNlIGlmIChldmVudEpzb24uZGF0YVswXSA8IDApIHtcblx0XHRcdFx0XHRcdGV2ZW50SnNvbi5rZXlTaWduYXR1cmUgPSBDb25zdGFudHMuQ0lSQ0xFX09GX0ZPVVJUSFNbTWF0aC5hYnMoZXZlbnRKc29uLmRhdGFbMF0pXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZXZlbnRKc29uLmRhdGFbMV0gPT0gMCkge1xuXHRcdFx0XHRcdFx0ZXZlbnRKc29uLmtleVNpZ25hdHVyZSArPSBcIiBNYWpvclwiO1xuXG5cdFx0XHRcdFx0fSBlbHNlIGlmIChldmVudEpzb24uZGF0YVsxXSA9PSAxKSB7XG5cdFx0XHRcdFx0XHRldmVudEpzb24ua2V5U2lnbmF0dXJlICs9IFwiIE1pbm9yXCI7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgMHg3RjogLy8gU2VxdWVuY2VyLVNwZWNpZmljIE1ldGEtZXZlbnRcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdTZXF1ZW5jZXItU3BlY2lmaWMgTWV0YS1ldmVudCc7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnVW5rbm93bjogJyArIHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXS50b1N0cmluZygxNik7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBsZW5ndGggPSB0aGlzLmRhdGFbdGhpcy5wb2ludGVyICsgZGVsdGFCeXRlQ291bnQgKyAyXTtcblx0XHRcdC8vIFNvbWUgbWV0YSBldmVudHMgd2lsbCBoYXZlIHZsdiB0aGF0IG5lZWRzIHRvIGJlIGhhbmRsZWRcblxuXHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMyArIGxlbmd0aDtcblxuXHRcdH0gZWxzZSBpZih0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XSA9PSAweGYwKSB7XG5cdFx0XHQvLyBTeXNleFxuXHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnU3lzZXgnO1xuXHRcdFx0dmFyIGxlbmd0aCA9IHRoaXMuZGF0YVt0aGlzLnBvaW50ZXIgKyBkZWx0YUJ5dGVDb3VudCArIDFdO1xuXHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMiArIGxlbmd0aDtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBWb2ljZSBldmVudFxuXHRcdFx0aWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDwgMHg4MCkge1xuXHRcdFx0XHQvLyBSdW5uaW5nIHN0YXR1c1xuXHRcdFx0XHRldmVudEpzb24ucnVubmluZyA9IHRydWU7XG5cdFx0XHRcdGV2ZW50SnNvbi5ub3RlTnVtYmVyID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleF07XG5cdFx0XHRcdGV2ZW50SnNvbi5ub3RlTmFtZSA9IENvbnN0YW50cy5OT1RFU1t0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XV07XG5cdFx0XHRcdGV2ZW50SnNvbi52ZWxvY2l0eSA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblxuXHRcdFx0XHRpZiAodGhpcy5sYXN0U3RhdHVzIDw9IDB4OGYpIHtcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9mZic7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweDgwICsgMTtcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMubGFzdFN0YXR1cyA8PSAweDlmKSB7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTm90ZSBvbic7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweDkwICsgMTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMucG9pbnRlciArPSBkZWx0YUJ5dGVDb3VudCArIDI7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMubGFzdFN0YXR1cyA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdO1xuXG5cdFx0XHRcdGlmICh0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XSA8PSAweDhmKSB7XG5cdFx0XHRcdFx0Ly8gTm90ZSBvZmZcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdOb3RlIG9mZic7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweDgwICsgMTtcblx0XHRcdFx0XHRldmVudEpzb24ubm90ZU51bWJlciA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHRldmVudEpzb24ubm90ZU5hbWUgPSBDb25zdGFudHMuTk9URVNbdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdXTtcblx0XHRcdFx0XHRldmVudEpzb24udmVsb2NpdHkgPSBNYXRoLnJvdW5kKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAyXSAvIDEyNyAqIDEwMCk7XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4OWYpIHtcblx0XHRcdFx0XHQvLyBOb3RlIG9uXG5cdFx0XHRcdFx0ZXZlbnRKc29uLm5hbWUgPSAnTm90ZSBvbic7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweDkwICsgMTtcblx0XHRcdFx0XHRldmVudEpzb24ubm90ZU51bWJlciA9IHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXTtcblx0XHRcdFx0XHRldmVudEpzb24ubm90ZU5hbWUgPSBDb25zdGFudHMuTk9URVNbdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDFdXTtcblx0XHRcdFx0XHRldmVudEpzb24udmVsb2NpdHkgPSBNYXRoLnJvdW5kKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAyXSAvIDEyNyAqIDEwMCk7XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4YWYpIHtcblx0XHRcdFx0XHQvLyBQb2x5cGhvbmljIEtleSBQcmVzc3VyZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1BvbHlwaG9uaWMgS2V5IFByZXNzdXJlJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4YTAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5ub3RlID0gQ29uc3RhbnRzLk5PVEVTW3RoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXggKyAxXV07XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnByZXNzdXJlID0gZXZlbnRbMl07XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4YmYpIHtcblx0XHRcdFx0XHQvLyBDb250cm9sbGVyIENoYW5nZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0NvbnRyb2xsZXIgQ2hhbmdlJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4YjAgKyAxO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5udW1iZXIgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV07XG5cdFx0XHRcdFx0ZXZlbnRKc29uLnZhbHVlID0gdGhpcy5kYXRhW2V2ZW50U3RhcnRJbmRleCArIDJdO1xuXHRcdFx0XHRcdHRoaXMucG9pbnRlciArPSBkZWx0YUJ5dGVDb3VudCArIDM7XG5cblx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XSA8PSAweGNmKSB7XG5cdFx0XHRcdFx0Ly8gUHJvZ3JhbSBDaGFuZ2Vcblx0XHRcdFx0XHRldmVudEpzb24ubmFtZSA9ICdQcm9ncmFtIENoYW5nZSc7XG5cdFx0XHRcdFx0ZXZlbnRKc29uLmNoYW5uZWwgPSB0aGlzLmxhc3RTdGF0dXMgLSAweGMwICsgMTtcblx0XHRcdFx0XHRldmVudEpzb24udmFsdWUgPSB0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4ICsgMV07XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMjtcblxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuZGF0YVtldmVudFN0YXJ0SW5kZXhdIDw9IDB4ZGYpIHtcblx0XHRcdFx0XHQvLyBDaGFubmVsIEtleSBQcmVzc3VyZVxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ0NoYW5uZWwgS2V5IFByZXNzdXJlJztcblx0XHRcdFx0XHRldmVudEpzb24uY2hhbm5lbCA9IHRoaXMubGFzdFN0YXR1cyAtIDB4ZDAgKyAxO1xuXHRcdFx0XHRcdHRoaXMucG9pbnRlciArPSBkZWx0YUJ5dGVDb3VudCArIDI7XG5cblx0XHRcdFx0fSBlbHNlIGlmICh0aGlzLmRhdGFbZXZlbnRTdGFydEluZGV4XSA8PSAweGVmKSB7XG5cdFx0XHRcdFx0Ly8gUGl0Y2ggQmVuZFxuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1BpdGNoIEJlbmQnO1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5jaGFubmVsID0gdGhpcy5sYXN0U3RhdHVzIC0gMHhlMCArIDE7XG5cdFx0XHRcdFx0dGhpcy5wb2ludGVyICs9IGRlbHRhQnl0ZUNvdW50ICsgMztcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGV2ZW50SnNvbi5uYW1lID0gJ1Vua25vd24uICBQb2ludGVyOiAnICsgdGhpcy5wb2ludGVyLnRvU3RyaW5nKCkgKyAnICcgICsgZXZlbnRTdGFydEluZGV4LnRvU3RyaW5nKCkgKyAnICcgKyB0aGlzLmRhdGEubGVuZ3RoO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5kZWx0YSArPSBldmVudEpzb24uZGVsdGE7XG5cdFx0dGhpcy5ldmVudHMucHVzaChldmVudEpzb24pO1xuXG5cdFx0cmV0dXJuIGV2ZW50SnNvbjtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRydWUgaWYgcG9pbnRlciBoYXMgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSB0cmFjay5cblx0ICogQHBhcmFtIHtib29sZWFufVxuXHQgKi9cblx0ZW5kT2ZUcmFjaygpIHtcblx0XHRpZiAodGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDFdID09IDB4ZmYgJiYgdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDJdID09IDB4MmYgJiYgdGhpcy5kYXRhW3RoaXMucG9pbnRlciArIDNdID09IDB4MDApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxufVxuXG5tb2R1bGUuZXhwb3J0cy5UcmFjayA9IFRyYWNrOyIsIi8qKlxuICogQ29udGFpbnMgbWlzYyBzdGF0aWMgdXRpbGl0eSBtZXRob2RzLlxuICovXG5jbGFzcyBVdGlscyB7XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgc2luZ2xlIGJ5dGUgdG8gYSBoZXggc3RyaW5nLlxuXHQgKiBAcGFyYW0ge251bWJlcn0gYnl0ZVxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgYnl0ZVRvSGV4KGJ5dGUpIHtcblx0XHQvLyBFbnN1cmUgaGV4IHN0cmluZyBhbHdheXMgaGFzIHR3byBjaGFyc1xuXHRcdHJldHVybiAoJzAnICsgYnl0ZS50b1N0cmluZygxNikpLnNsaWNlKC0yKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBieXRlcyB0byBhIGhleCBzdHJpbmcuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IGJ5dGVBcnJheVxuXHQgKiBAcmV0dXJuIHtzdHJpbmd9XG5cdCAqL1xuXHRzdGF0aWMgYnl0ZXNUb0hleChieXRlQXJyYXkpIHtcblx0XHR2YXIgaGV4ID0gW107XG5cdFx0Ynl0ZUFycmF5LmZvckVhY2goYnl0ZSA9PiBoZXgucHVzaChVdGlscy5ieXRlVG9IZXgoYnl0ZSkpKTtcblx0XHRyZXR1cm4gaGV4LmpvaW4oJycpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgaGV4IHN0cmluZyB0byBhIG51bWJlci5cblx0ICogQHBhcmFtIHtzdHJpbmd9IGhleFN0cmluZ1xuXHQgKiBAcmV0dXJuIHtudW1iZXJ9XG5cdCAqL1xuXHRzdGF0aWMgaGV4VG9OdW1iZXIoaGV4U3RyaW5nKSB7XG5cdFx0cmV0dXJuIHBhcnNlSW50KGhleFN0cmluZywgMTYpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGFuIGFycmF5IG9mIGJ5dGVzIHRvIGEgbnVtYmVyLlxuXHQgKiBAcGFyYW0ge2FycmF5fSBieXRlQXJyYXlcblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0c3RhdGljIGJ5dGVzVG9OdW1iZXIoYnl0ZUFycmF5KSB7XG5cdFx0cmV0dXJuIFV0aWxzLmhleFRvTnVtYmVyKFV0aWxzLmJ5dGVzVG9IZXgoYnl0ZUFycmF5KSk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYW4gYXJyYXkgb2YgYnl0ZXMgdG8gbGV0dGVycy5cblx0ICogQHBhcmFtIHthcnJheX0gYnl0ZUFycmF5XG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBieXRlc1RvTGV0dGVycyhieXRlQXJyYXkpIHtcblx0XHR2YXIgbGV0dGVycyA9IFtdO1xuXHRcdGJ5dGVBcnJheS5mb3JFYWNoKGJ5dGUgPT4gbGV0dGVycy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZSkpKTtcblx0XHRyZXR1cm4gbGV0dGVycy5qb2luKCcnKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIGRlY2ltYWwgdG8gaXQncyBiaW5hcnkgcmVwcmVzZW50YXRpb24uXG5cdCAqIEBwYXJhbSB7bnVtYmVyfSBkZWNcblx0ICogQHJldHVybiB7c3RyaW5nfVxuXHQgKi9cblx0c3RhdGljIGRlY1RvQmluYXJ5KGRlYykge1xuICAgIFx0cmV0dXJuIChkZWMgPj4+IDApLnRvU3RyaW5nKDIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlYWRzIGEgdmFyaWFibGUgbGVuZ3RoIHZhbHVlLlxuXHQgKiBAcGFyYW0ge2FycmF5fSBieXRlQXJyYXlcblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0c3RhdGljIHJlYWRWYXJJbnQoYnl0ZUFycmF5KSB7XG5cdFx0dmFyIHJlc3VsdCA9IDA7XG5cdFx0Ynl0ZUFycmF5LmZvckVhY2gobnVtYmVyID0+IHtcblx0XHRcdHZhciBiID0gbnVtYmVyO1xuXHRcdFx0aWYgKGIgJiAweDgwKSB7XG5cdFx0XHRcdHJlc3VsdCArPSAoYiAmIDB4N2YpO1xuXHRcdFx0XHRyZXN1bHQgPDw9IDc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvKiBiIGlzIHRoZSBsYXN0IGJ5dGUgKi9cblx0XHRcdFx0cmVzdWx0ICs9IGI7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0LyoqXG5cdCAqIERlY29kZXMgYmFzZS02NCBlbmNvZGVkIHN0cmluZ1xuXHQgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nXG5cdCAqIEByZXR1cm4ge3N0cmluZ31cblx0ICovXG5cdHN0YXRpYyBhdG9iKHN0cmluZykge1xuXHRcdGlmICh0eXBlb2YgYXRvYiA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGF0b2Ioc3RyaW5nKTtcblx0XHRyZXR1cm4gbmV3IEJ1ZmZlcihzdHJpbmcsICdiYXNlNjQnKS50b1N0cmluZygnYmluYXJ5Jyk7XG5cdH1cbn1cblxuZXhwb3J0cy5VdGlscyA9IFV0aWxzOyJdfQ==
|