Skip to content

Instantly share code, notes, and snippets.

@EvanCarroll
Created January 5, 2015 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EvanCarroll/073ff45151a397dabb57 to your computer and use it in GitHub Desktop.
Save EvanCarroll/073ff45151a397dabb57 to your computer and use it in GitHub Desktop.
(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})({1:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('is-array')
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192 // not used by this implementation
var kMaxLength = 0x3fffffff
var rootParent = {}
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* Note:
*
* - Implementation must support adding new properties to `Uint8Array` instances.
* Firefox 4-29 lacked support, fixed in Firefox 30+.
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
*
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
*
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
* incorrect length in some situations.
*
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
* get the Object implementation, which is slower but will work correctly.
*/
Buffer.TYPED_ARRAY_SUPPORT = (function () {
try {
var buf = new ArrayBuffer(0)
var arr = new Uint8Array(buf)
arr.foo = function () { return 42 }
return 42 === arr.foo() && // typed array instances can be augmented
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) {
return false
}
})()
/**
* Class: Buffer
* =============
*
* The Buffer constructor returns instances of `Uint8Array` that are augmented
* with function properties for all the node `Buffer` API functions. We use
* `Uint8Array` so that square bracket notation works as expected -- it returns
* a single octet.
*
* By augmenting the instances, we can avoid modifying the `Uint8Array`
* prototype.
*/
function Buffer (subject, encoding, noZero) {
if (!(this instanceof Buffer))
return new Buffer(subject, encoding, noZero)
var type = typeof subject
// Find the length
var length
if (type === 'number')
length = subject > 0 ? subject >>> 0 : 0
else if (type === 'string') {
length = Buffer.byteLength(subject, encoding)
} else if (type === 'object' && subject !== null) { // assume object is array-like
if (subject.type === 'Buffer' && isArray(subject.data))
subject = subject.data
length = +subject.length > 0 ? Math.floor(+subject.length) : 0
} else
throw new TypeError('must start with number, buffer, array or string')
if (length > kMaxLength)
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength.toString(16) + ' bytes')
var buf
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Preferred: Return an augmented `Uint8Array` instance for best performance
buf = Buffer._augment(new Uint8Array(length))
} else {
// Fallback: Return THIS instance of Buffer (created by `new`)
buf = this
buf.length = length
buf._isBuffer = true
}
var i
if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') {
// Speed optimization -- use set if we're copying from a typed array
buf._set(subject)
} else if (isArrayish(subject)) {
// Treat array-ish objects as a byte array
if (Buffer.isBuffer(subject)) {
for (i = 0; i < length; i++)
buf[i] = subject.readUInt8(i)
} else {
for (i = 0; i < length; i++)
buf[i] = ((subject[i] % 256) + 256) % 256
}
} else if (type === 'string') {
buf.write(subject, 0, encoding)
} else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) {
for (i = 0; i < length; i++) {
buf[i] = 0
}
}
if (length > 0 && length <= Buffer.poolSize)
buf.parent = rootParent
return buf
}
function SlowBuffer(subject, encoding, noZero) {
if (!(this instanceof SlowBuffer))
return new SlowBuffer(subject, encoding, noZero)
var buf = new Buffer(subject, encoding, noZero)
delete buf.parent
return buf
}
Buffer.isBuffer = function (b) {
return !!(b != null && b._isBuffer)
}
Buffer.compare = function (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b))
throw new TypeError('Arguments must be Buffers')
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
if (i !== len) {
x = a[i]
y = b[i]
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'binary':
case 'base64':
case 'raw':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function (list, totalLength) {
if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])')
if (list.length === 0) {
return new Buffer(0)
} else if (list.length === 1) {
return list[0]
}
var i
if (totalLength === undefined) {
totalLength = 0
for (i = 0; i < list.length; i++) {
totalLength += list[i].length
}
}
var buf = new Buffer(totalLength)
var pos = 0
for (i = 0; i < list.length; i++) {
var item = list[i]
item.copy(buf, pos)
pos += item.length
}
return buf
}
Buffer.byteLength = function (str, encoding) {
var ret
str = str + ''
switch (encoding || 'utf8') {
case 'ascii':
case 'binary':
case 'raw':
ret = str.length
break
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
ret = str.length * 2
break
case 'hex':
ret = str.length >>> 1
break
case 'utf8':
case 'utf-8':
ret = utf8ToBytes(str).length
break
case 'base64':
ret = base64ToBytes(str).length
break
default:
ret = str.length
}
return ret
}
// pre-set for values that may exist in the future
Buffer.prototype.length = undefined
Buffer.prototype.parent = undefined
// toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function (encoding, start, end) {
var loweredCase = false
start = start >>> 0
end = end === undefined || end === Infinity ? this.length : end >>> 0
if (!encoding) encoding = 'utf8'
if (start < 0) start = 0
if (end > this.length) end = this.length
if (end <= start) return ''
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 'binary':
return binarySlice(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
}
}
}
Buffer.prototype.equals = function (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function () {
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 (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
return Buffer.compare(this, b)
}
// `get` will be removed in Node 0.13+
Buffer.prototype.get = function (offset) {
console.log('.get() is deprecated. Access using array indexes instead.')
return this.readUInt8(offset)
}
// `set` will be removed in Node 0.13+
Buffer.prototype.set = function (v, offset) {
console.log('.set() is deprecated. Access using array indexes instead.')
return this.writeUInt8(v, offset)
}
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 Error('Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; i++) {
var byte = parseInt(string.substr(i * 2, 2), 16)
if (isNaN(byte)) throw new Error('Invalid hex string')
buf[offset + i] = byte
}
return i
}
function utf8Write (buf, string, offset, length) {
var charsWritten = blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
return charsWritten
}
function asciiWrite (buf, string, offset, length) {
var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
return charsWritten
}
function binaryWrite (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
return charsWritten
}
function utf16leWrite (buf, string, offset, length) {
var charsWritten = blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length, 2)
return charsWritten
}
Buffer.prototype.write = function (string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length
length = undefined
}
} else { // legacy
var swap = encoding
encoding = offset
offset = length
length = swap
}
offset = Number(offset) || 0
if (length < 0 || offset < 0 || offset > this.length)
throw new RangeError('attempt to write outside buffer bounds');
var remaining = this.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
encoding = String(encoding || 'utf8').toLowerCase()
var ret
switch (encoding) {
case 'hex':
ret = hexWrite(this, string, offset, length)
break
case 'utf8':
case 'utf-8':
ret = utf8Write(this, string, offset, length)
break
case 'ascii':
ret = asciiWrite(this, string, offset, length)
break
case 'binary':
ret = binaryWrite(this, string, offset, length)
break
case 'base64':
ret = base64Write(this, string, offset, length)
break
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
ret = utf16leWrite(this, string, offset, length)
break
default:
throw new TypeError('Unknown encoding: ' + encoding)
}
return ret
}
Buffer.prototype.toJSON = function () {
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) {
var res = ''
var tmp = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++) {
if (buf[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
tmp = ''
} else {
tmp += '%' + buf[i].toString(16)
}
}
return res + decodeUtf8Char(tmp)
}
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 binarySlice (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 (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len;
if (start < 0)
start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0)
end = 0
} else if (end > len) {
end = len
}
if (end < start)
end = start
var newBuf
if (Buffer.TYPED_ARRAY_SUPPORT) {
newBuf = Buffer._augment(this.subarray(start, end))
} else {
var sliceLen = end - start
newBuf = new Buffer(sliceLen, undefined, true)
for (var i = 0; i < sliceLen; i++) {
newBuf[i] = this[i + start]
}
}
if (newBuf.length)
newBuf.parent = this.parent || this
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 (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 (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 (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[offset + 2] << 8) |
this[offset + 3])
}
Buffer.prototype.readIntLE = function (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 (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 (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 1, this.length)
if (!(this[offset] & 0x80))
return (this[offset])
return ((0xff - this[offset] + 1) * -1)
}
Buffer.prototype.readInt16LE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 2, this.length)
var val = this[offset] | (this[offset + 1] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt16BE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 2, this.length)
var val = this[offset + 1] | (this[offset] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt32LE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return (this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16) |
(this[offset + 3] << 24)
}
Buffer.prototype.readInt32BE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return (this[offset] << 24) |
(this[offset + 1] << 16) |
(this[offset + 2] << 8) |
(this[offset + 3])
}
Buffer.prototype.readFloatLE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, true, 23, 4)
}
Buffer.prototype.readFloatBE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, false, 23, 4)
}
Buffer.prototype.readDoubleLE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, true, 52, 8)
}
Buffer.prototype.readDoubleBE = function (offset, noAssert) {
if (!noAssert)
checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, false, 52, 8)
}
function checkInt (buf, value, offset, ext, max, min) {
if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
if (value > max || value < min) throw new RangeError('value is out of bounds')
if (offset + ext > buf.length) throw new RangeError('index out of range')
}
Buffer.prototype.writeUIntLE = function (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert)
checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
var mul = 1
var i = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100))
this[offset + i] = (value / mul) >>> 0 & 0xFF
return offset + byteLength
}
Buffer.prototype.writeUIntBE = function (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
byteLength = byteLength >>> 0
if (!noAssert)
checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
var i = byteLength - 1
var mul = 1
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100))
this[offset + i] = (value / mul) >>> 0 & 0xFF
return offset + byteLength
}
Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 1, 0xff, 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
this[offset] = value
return offset + 1
}
function objectWriteUInt16 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
(littleEndian ? i : 1 - i) * 8
}
}
Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
} else objectWriteUInt16(this, value, offset, true)
return offset + 2
}
Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = value
} else objectWriteUInt16(this, value, offset, false)
return offset + 2
}
function objectWriteUInt32 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffffffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
}
}
Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset + 3] = (value >>> 24)
this[offset + 2] = (value >>> 16)
this[offset + 1] = (value >>> 8)
this[offset] = value
} else objectWriteUInt32(this, value, offset, true)
return offset + 4
}
Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = value
} else objectWriteUInt32(this, value, offset, false)
return offset + 4
}
Buffer.prototype.writeIntLE = function (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
checkInt(this,
value,
offset,
byteLength,
Math.pow(2, 8 * byteLength - 1) - 1,
-Math.pow(2, 8 * byteLength - 1))
}
var i = 0
var mul = 1
var sub = value < 0 ? 1 : 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100))
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
return offset + byteLength
}
Buffer.prototype.writeIntBE = function (value, offset, byteLength, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert) {
checkInt(this,
value,
offset,
byteLength,
Math.pow(2, 8 * byteLength - 1) - 1,
-Math.pow(2, 8 * byteLength - 1))
}
var i = byteLength - 1
var mul = 1
var sub = value < 0 ? 1 : 0
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100))
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
return offset + byteLength
}
Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 1, 0x7f, -0x80)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
if (value < 0) value = 0xff + value + 1
this[offset] = value
return offset + 1
}
Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
} else objectWriteUInt16(this, value, offset, true)
return offset + 2
}
Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = value
} else objectWriteUInt16(this, value, offset, false)
return offset + 2
}
Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = value
this[offset + 1] = (value >>> 8)
this[offset + 2] = (value >>> 16)
this[offset + 3] = (value >>> 24)
} else objectWriteUInt32(this, value, offset, true)
return offset + 4
}
Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
value = +value
offset = offset >>> 0
if (!noAssert)
checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (value < 0) value = 0xffffffff + value + 1
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = value
} else objectWriteUInt32(this, value, offset, false)
return offset + 4
}
function checkIEEE754 (buf, value, offset, ext, max, min) {
if (value > max || value < min) throw new RangeError('value is out of bounds')
if (offset + ext > buf.length) throw new RangeError('index out of range')
if (offset < 0) throw new RangeError('index out of range')
}
function writeFloat (buf, value, offset, littleEndian, noAssert) {
if (!noAssert)
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
ieee754.write(buf, value, offset, littleEndian, 23, 4)
return offset + 4
}
Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
return writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
return writeFloat(this, value, offset, false, noAssert)
}
function writeDouble (buf, value, offset, littleEndian, noAssert) {
if (!noAssert)
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
ieee754.write(buf, value, offset, littleEndian, 52, 8)
return offset + 8
}
Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
return writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
return writeDouble(this, value, offset, false, noAssert)
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function (target, target_start, start, end) {
var source = this
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (target_start >= target.length) target_start = target.length
if (!target_start) target_start = 0
if (end > 0 && end < start) end = start
// Copy 0 bytes; we're done
if (end === start) return 0
if (target.length === 0 || source.length === 0) return 0
// Fatal error conditions
if (target_start < 0)
throw new RangeError('targetStart out of bounds')
if (start < 0 || start >= source.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 - target_start < end - start)
end = target.length - target_start + start
var len = end - start
if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < len; i++) {
target[i + target_start] = this[i + start]
}
} else {
target._set(this.subarray(start, start + len), target_start)
}
return len
}
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function (value, start, end) {
if (!value) value = 0
if (!start) start = 0
if (!end) end = this.length
if (end < start) throw new RangeError('end < start')
// Fill 0 bytes; we're done
if (end === start) return
if (this.length === 0) return
if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
var i
if (typeof value === 'number') {
for (i = start; i < end; i++) {
this[i] = value
}
} else {
var bytes = utf8ToBytes(value.toString())
var len = bytes.length
for (i = start; i < end; i++) {
this[i] = bytes[i % len]
}
}
return this
}
/**
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
* Added in Node 0.12. Only available in browsers that support ArrayBuffer.
*/
Buffer.prototype.toArrayBuffer = function () {
if (typeof Uint8Array !== 'undefined') {
if (Buffer.TYPED_ARRAY_SUPPORT) {
return (new Buffer(this)).buffer
} else {
var buf = new Uint8Array(this.length)
for (var i = 0, len = buf.length; i < len; i += 1) {
buf[i] = this[i]
}
return buf.buffer
}
} else {
throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
}
}
// HELPER FUNCTIONS
// ================
var BP = Buffer.prototype
/**
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
*/
Buffer._augment = function (arr) {
arr.constructor = Buffer
arr._isBuffer = true
// save reference to original Uint8Array get/set methods before overwriting
arr._get = arr.get
arr._set = arr.set
// deprecated, will be removed in node 0.13+
arr.get = BP.get
arr.set = BP.set
arr.write = BP.write
arr.toString = BP.toString
arr.toLocaleString = BP.toString
arr.toJSON = BP.toJSON
arr.equals = BP.equals
arr.compare = BP.compare
arr.copy = BP.copy
arr.slice = BP.slice
arr.readUIntLE = BP.readUIntLE
arr.readUIntBE = BP.readUIntBE
arr.readUInt8 = BP.readUInt8
arr.readUInt16LE = BP.readUInt16LE
arr.readUInt16BE = BP.readUInt16BE
arr.readUInt32LE = BP.readUInt32LE
arr.readUInt32BE = BP.readUInt32BE
arr.readIntLE = BP.readIntLE
arr.readIntBE = BP.readIntBE
arr.readInt8 = BP.readInt8
arr.readInt16LE = BP.readInt16LE
arr.readInt16BE = BP.readInt16BE
arr.readInt32LE = BP.readInt32LE
arr.readInt32BE = BP.readInt32BE
arr.readFloatLE = BP.readFloatLE
arr.readFloatBE = BP.readFloatBE
arr.readDoubleLE = BP.readDoubleLE
arr.readDoubleBE = BP.readDoubleBE
arr.writeUInt8 = BP.writeUInt8
arr.writeUIntLE = BP.writeUIntLE
arr.writeUIntBE = BP.writeUIntBE
arr.writeUInt16LE = BP.writeUInt16LE
arr.writeUInt16BE = BP.writeUInt16BE
arr.writeUInt32LE = BP.writeUInt32LE
arr.writeUInt32BE = BP.writeUInt32BE
arr.writeIntLE = BP.writeIntLE
arr.writeIntBE = BP.writeIntBE
arr.writeInt8 = BP.writeInt8
arr.writeInt16LE = BP.writeInt16LE
arr.writeInt16BE = BP.writeInt16BE
arr.writeInt32LE = BP.writeInt32LE
arr.writeInt32BE = BP.writeInt32BE
arr.writeFloatLE = BP.writeFloatLE
arr.writeFloatBE = BP.writeFloatBE
arr.writeDoubleLE = BP.writeDoubleLE
arr.writeDoubleBE = BP.writeDoubleBE
arr.fill = BP.fill
arr.inspect = BP.inspect
arr.toArrayBuffer = BP.toArrayBuffer
return arr
}
var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g
function base64clean (str) {
// Node strips out invalid characters like \n and \t from the string, base64-js does not
str = stringtrim(str).replace(INVALID_BASE64_RE, '')
// Node converts strings with length < 2 to ''
if (str.length < 2) return ''
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
while (str.length % 4 !== 0) {
str = str + '='
}
return str
}
function stringtrim (str) {
if (str.trim) return str.trim()
return str.replace(/^\s+|\s+$/g, '')
}
function isArrayish (subject) {
return isArray(subject) || Buffer.isBuffer(subject) ||
subject && typeof subject === 'object' &&
typeof subject.length === 'number'
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}
function utf8ToBytes(string, units) {
var codePoint, length = string.length
var leadSurrogate = null
units = units || Infinity
var bytes = []
var i = 0
for (; i<length; i++) {
codePoint = string.charCodeAt(i)
// is surrogate component
if (codePoint > 0xD7FF && codePoint < 0xE000) {
// last char was a lead
if (leadSurrogate) {
// 2 leads in a row
if (codePoint < 0xDC00) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = codePoint
continue
}
// valid surrogate pair
else {
codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
leadSurrogate = null
}
}
// no lead yet
else {
// unexpected trail
if (codePoint > 0xDBFF) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
}
// unpaired lead
else if (i + 1 === length) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
}
// valid lead
else {
leadSurrogate = codePoint
continue
}
}
}
// valid bmp char, but last char was a lead
else if (leadSurrogate) {
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 < 0x200000) {
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, unitSize) {
if (unitSize) length -= length % unitSize;
for (var i = 0; i < length; i++) {
if ((i + offset >= dst.length) || (i >= src.length))
break
dst[i + offset] = src[i]
}
return i
}
function decodeUtf8Char (str) {
try {
return decodeURIComponent(str)
} catch (err) {
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
}
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/browserify/node_modules/buffer/index.js","/node_modules/browserify/node_modules/buffer")
},{"_process":5,"base64-js":2,"buffer":1,"ieee754":3,"is-array":4}],2:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS ||
code === PLUS_URL_SAFE)
return 62 // '+'
if (code === SLASH ||
code === SLASH_URL_SAFE)
return 63 // '/'
if (code < NUMBER)
return -1 //no match
if (code < NUMBER + 10)
return code - NUMBER + 26 + 26
if (code < UPPER + 26)
return code - UPPER
if (code < LOWER + 26)
return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
if (b64.length % 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
var len = b64.length
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
var L = 0
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
return arr
}
function uint8ToBase64 (uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
}
return output
}
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/browserify/node_modules/buffer/node_modules/base64-js/lib/b64.js","/node_modules/browserify/node_modules/buffer/node_modules/base64-js/lib")
},{"_process":5,"buffer":1}],3:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
exports.read = function(buffer, offset, isLE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isLE ? (nBytes - 1) : 0,
d = isLE ? -1 : 1,
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,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isLE ? 0 : (nBytes - 1),
d = isLE ? 1 : -1,
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;
};
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/browserify/node_modules/buffer/node_modules/ieee754/index.js","/node_modules/browserify/node_modules/buffer/node_modules/ieee754")
},{"_process":5,"buffer":1}],4:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
/**
* isArray
*/
var isArray = Array.isArray;
/**
* toString
*/
var str = Object.prototype.toString;
/**
* Whether or not the given `val`
* is an array.
*
* example:
*
* isArray([]);
* // > true
* isArray(arguments);
* // > false
* isArray('');
* // > false
*
* @param {mixed} val
* @return {bool}
*/
module.exports = isArray || function (val) {
return !! val && '[object Array]' == str.call(val);
};
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/browserify/node_modules/buffer/node_modules/is-array/index.js","/node_modules/browserify/node_modules/buffer/node_modules/is-array")
},{"_process":5,"buffer":1}],5:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canMutationObserver = typeof window !== 'undefined'
&& window.MutationObserver;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
var queue = [];
if (canMutationObserver) {
var hiddenDiv = document.createElement("div");
var observer = new MutationObserver(function () {
var queueList = queue.slice();
queue.length = 0;
queueList.forEach(function (fn) {
fn();
});
});
observer.observe(hiddenDiv, { attributes: true });
return function nextTick(fn) {
if (!queue.length) {
hiddenDiv.setAttribute('yes', 'no');
}
queue.push(fn);
};
}
if (canPost) {
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/node_modules/browserify/node_modules/process/browser.js","/node_modules/browserify/node_modules/process")
},{"_process":5,"buffer":1}],6:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
/* Prototype JavaScript framework, version 1.7.2
* (c) 2005-2010 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.7.2',
Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
return {
IE: !!window.attachEvent && !isOpera,
Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
MobileSafari: /Apple.*Mobile/.test(ua)
}
})(),
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: (function() {
var constructor = window.Element || window.HTMLElement;
return !!(constructor && constructor.prototype);
})(),
SpecificElementExtensions: (function() {
if (typeof window.HTMLDivElement !== 'undefined')
return true;
var div = document.createElement('div'),
form = document.createElement('form'),
isSupported = false;
if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
isSupported = true;
}
div = form = null;
return isSupported;
})()
},
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script\\s*>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
/* Based on Alex Arnell's inheritance implementation. */
var Class = (function() {
var IS_DONTENUM_BUGGY = (function(){
for (var p in { toString: 1 }) {
if (p === 'toString') return false;
}
return true;
})();
function subclass() {};
function create() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
function klass() {
this.initialize.apply(this, arguments);
}
Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];
if (parent) {
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0, length = properties.length; i < length; i++)
klass.addMethods(properties[i]);
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
return klass;
}
function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype,
properties = Object.keys(source);
if (IS_DONTENUM_BUGGY) {
if (source.toString != Object.prototype.toString)
properties.push("toString");
if (source.valueOf != Object.prototype.valueOf)
properties.push("valueOf");
}
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames()[0] == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments); };
})(property).wrap(method);
value.valueOf = (function(method) {
return function() { return method.valueOf.call(method); };
})(method);
value.toString = (function(method) {
return function() { return method.toString.call(method); };
})(method);
}
this.prototype[property] = value;
}
return this;
}
return {
create: create,
Methods: {
addMethods: addMethods
}
};
})();
(function() {
var _toString = Object.prototype.toString,
_hasOwnProperty = Object.prototype.hasOwnProperty,
NULL_TYPE = 'Null',
UNDEFINED_TYPE = 'Undefined',
BOOLEAN_TYPE = 'Boolean',
NUMBER_TYPE = 'Number',
STRING_TYPE = 'String',
OBJECT_TYPE = 'Object',
FUNCTION_CLASS = '[object Function]',
BOOLEAN_CLASS = '[object Boolean]',
NUMBER_CLASS = '[object Number]',
STRING_CLASS = '[object String]',
ARRAY_CLASS = '[object Array]',
DATE_CLASS = '[object Date]',
NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
typeof JSON.stringify === 'function' &&
JSON.stringify(0) === '0' &&
typeof JSON.stringify(Prototype.K) === 'undefined';
var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',
'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];
var IS_DONTENUM_BUGGY = (function(){
for (var p in { toString: 1 }) {
if (p === 'toString') return false;
}
return true;
})();
function Type(o) {
switch(o) {
case null: return NULL_TYPE;
case (void 0): return UNDEFINED_TYPE;
}
var type = typeof o;
switch(type) {
case 'boolean': return BOOLEAN_TYPE;
case 'number': return NUMBER_TYPE;
case 'string': return STRING_TYPE;
}
return OBJECT_TYPE;
}
function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
function inspect(object) {
try {
if (isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
}
function toJSON(value) {
return Str('', { '': value }, []);
}
function Str(key, holder, stack) {
var value = holder[key];
if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
var _class = _toString.call(value);
switch (_class) {
case NUMBER_CLASS:
case BOOLEAN_CLASS:
case STRING_CLASS:
value = value.valueOf();
}
switch (value) {
case null: return 'null';
case true: return 'true';
case false: return 'false';
}
var type = typeof value;
switch (type) {
case 'string':
return value.inspect(true);
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'object':
for (var i = 0, length = stack.length; i < length; i++) {
if (stack[i] === value) {
throw new TypeError("Cyclic reference to '" + value + "' in object");
}
}
stack.push(value);
var partial = [];
if (_class === ARRAY_CLASS) {
for (var i = 0, length = value.length; i < length; i++) {
var str = Str(i, value, stack);
partial.push(typeof str === 'undefined' ? 'null' : str);
}
partial = '[' + partial.join(',') + ']';
} else {
var keys = Object.keys(value);
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i], str = Str(key, value, stack);
if (typeof str !== "undefined") {
partial.push(key.inspect(true)+ ':' + str);
}
}
partial = '{' + partial.join(',') + '}';
}
stack.pop();
return partial;
}
}
function stringify(object) {
return JSON.stringify(object);
}
function toQueryString(object) {
return $H(object).toQueryString();
}
function toHTML(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
}
function keys(object) {
if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
var results = [];
for (var property in object) {
if (_hasOwnProperty.call(object, property))
results.push(property);
}
if (IS_DONTENUM_BUGGY) {
for (var i = 0; property = DONT_ENUMS[i]; i++) {
if (_hasOwnProperty.call(object, property))
results.push(property);
}
}
return results;
}
function values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}
function clone(object) {
return extend({ }, object);
}
function isElement(object) {
return !!(object && object.nodeType == 1);
}
function isArray(object) {
return _toString.call(object) === ARRAY_CLASS;
}
var hasNativeIsArray = (typeof Array.isArray == 'function')
&& Array.isArray([]) && !Array.isArray({});
if (hasNativeIsArray) {
isArray = Array.isArray;
}
function isHash(object) {
return object instanceof Hash;
}
function isFunction(object) {
return _toString.call(object) === FUNCTION_CLASS;
}
function isString(object) {
return _toString.call(object) === STRING_CLASS;
}
function isNumber(object) {
return _toString.call(object) === NUMBER_CLASS;
}
function isDate(object) {
return _toString.call(object) === DATE_CLASS;
}
function isUndefined(object) {
return typeof object === "undefined";
}
extend(Object, {
extend: extend,
inspect: inspect,
toJSON: NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,
toQueryString: toQueryString,
toHTML: toHTML,
keys: Object.keys || keys,
values: values,
clone: clone,
isElement: isElement,
isArray: isArray,
isHash: isHash,
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
isDate: isDate,
isUndefined: isUndefined
});
})();
Object.extend(Function.prototype, (function() {
var slice = Array.prototype.slice;
function update(array, args) {
var arrayLength = array.length, length = args.length;
while (length--) array[arrayLength + length] = args[length];
return array;
}
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
}
function bind(context) {
if (arguments.length < 2 && Object.isUndefined(arguments[0]))
return this;
if (!Object.isFunction(this))
throw new TypeError("The object is not callable.");
var nop = function() {};
var __method = this, args = slice.call(arguments, 1);
var bound = function() {
var a = merge(args, arguments);
var c = this instanceof bound ? this : context;
return __method.apply(c, a);
};
nop.prototype = this.prototype;
bound.prototype = new nop();
return bound;
}
function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1);
return function(event) {
var a = update([event || window.event], args);
return __method.apply(context, a);
}
}
function curry() {
if (!arguments.length) return this;
var __method = this, args = slice.call(arguments, 0);
return function() {
var a = merge(args, arguments);
return __method.apply(this, a);
}
}
function delay(timeout) {
var __method = this, args = slice.call(arguments, 1);
timeout = timeout * 1000;
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
}
function defer() {
var args = update([0.01], arguments);
return this.delay.apply(this, args);
}
function wrap(wrapper) {
var __method = this;
return function() {
var a = update([__method.bind(this)], arguments);
return wrapper.apply(this, a);
}
}
function methodize() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
var a = update([this], arguments);
return __method.apply(null, a);
};
}
var extensions = {
argumentNames: argumentNames,
bindAsEventListener: bindAsEventListener,
curry: curry,
delay: delay,
defer: defer,
wrap: wrap,
methodize: methodize
};
if (!Function.prototype.bind)
extensions.bind = bind;
return extensions;
})());
(function(proto) {
function toISOString() {
return this.getUTCFullYear() + '-' +
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
this.getUTCDate().toPaddedString(2) + 'T' +
this.getUTCHours().toPaddedString(2) + ':' +
this.getUTCMinutes().toPaddedString(2) + ':' +
this.getUTCSeconds().toPaddedString(2) + 'Z';
}
function toJSON() {
return this.toISOString();
}
if (!proto.toISOString) proto.toISOString = toISOString;
if (!proto.toJSON) proto.toJSON = toJSON;
})(Date.prototype);
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.execute();
this.currentlyExecuting = false;
} catch(e) {
this.currentlyExecuting = false;
throw e;
}
}
}
});
Object.extend(String, {
interpret: function(value) {
return value == null ? '' : String(value);
},
specialChar: {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
});
Object.extend(String.prototype, (function() {
var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&
typeof JSON.parse === 'function' &&
JSON.parse('{"test": true}').test;
function prepareReplacement(replacement) {
if (Object.isFunction(replacement)) return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
}
function isNonEmptyRegExp(regexp) {
return regexp.source && regexp.source !== '(?:)';
}
function gsub(pattern, replacement) {
var result = '', source = this, match;
replacement = prepareReplacement(replacement);
if (Object.isString(pattern))
pattern = RegExp.escape(pattern);
if (!(pattern.length || isNonEmptyRegExp(pattern))) {
replacement = replacement('');
return replacement + source.split('').join(replacement) + replacement;
}
while (source.length > 0) {
match = source.match(pattern)
if (match && match[0].length > 0) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
}
function sub(pattern, replacement, count) {
replacement = prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
}
function scan(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
}
function truncate(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
}
function strip() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
}
function stripTags() {
return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
}
function stripScripts() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
}
function extractScripts() {
var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),
matchOne = new RegExp(Prototype.ScriptFragment, 'im');
return (this.match(matchAll) || []).map(function(scriptTag) {
return (scriptTag.match(matchOne) || ['', ''])[1];
});
}
function evalScripts() {
return this.extractScripts().map(function(script) { return eval(script); });
}
function escapeHTML() {
return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
function unescapeHTML() {
return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
}
function toQueryParams(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };
return match[1].split(separator || '&').inject({ }, function(hash, pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift()),
value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) {
value = value.gsub('+', ' ');
value = decodeURIComponent(value);
}
if (key in hash) {
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
hash[key].push(value);
}
else hash[key] = value;
}
return hash;
});
}
function toArray() {
return this.split('');
}
function succ() {
return this.slice(0, this.length - 1) +
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
}
function times(count) {
return count < 1 ? '' : new Array(count + 1).join(this);
}
function camelize() {
return this.replace(/-+(.)?/g, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
function capitalize() {
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}
function underscore() {
return this.replace(/::/g, '/')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
.replace(/([a-z\d])([A-Z])/g, '$1_$2')
.replace(/-/g, '_')
.toLowerCase();
}
function dasherize() {
return this.replace(/_/g, '-');
}
function inspect(useDoubleQuotes) {
var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) {
if (character in String.specialChar) {
return String.specialChar[character];
}
return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
});
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
return "'" + escapedString.replace(/'/g, '\\\'') + "'";
}
function unfilterJSON(filter) {
return this.replace(filter || Prototype.JSONFilter, '$1');
}
function isJSON() {
var str = this;
if (str.blank()) return false;
str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
return (/^[\],:{}\s]*$/).test(str);
}
function evalJSON(sanitize) {
var json = this.unfilterJSON(),
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
if (cx.test(json)) {
json = json.replace(cx, function (a) {
return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');
} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
}
function parseJSON() {
var json = this.unfilterJSON();
return JSON.parse(json);
}
function include(pattern) {
return this.indexOf(pattern) > -1;
}
function startsWith(pattern, position) {
position = Object.isNumber(position) ? position : 0;
return this.lastIndexOf(pattern, position) === position;
}
function endsWith(pattern, position) {
pattern = String(pattern);
position = Object.isNumber(position) ? position : this.length;
if (position < 0) position = 0;
if (position > this.length) position = this.length;
var d = position - pattern.length;
return d >= 0 && this.indexOf(pattern, d) === d;
}
function empty() {
return this == '';
}
function blank() {
return /^\s*$/.test(this);
}
function interpolate(object, pattern) {
return new Template(this, pattern).evaluate(object);
}
return {
gsub: gsub,
sub: sub,
scan: scan,
truncate: truncate,
strip: String.prototype.trim || strip,
stripTags: stripTags,
stripScripts: stripScripts,
extractScripts: extractScripts,
evalScripts: evalScripts,
escapeHTML: escapeHTML,
unescapeHTML: unescapeHTML,
toQueryParams: toQueryParams,
parseQuery: toQueryParams,
toArray: toArray,
succ: succ,
times: times,
camelize: camelize,
capitalize: capitalize,
underscore: underscore,
dasherize: dasherize,
inspect: inspect,
unfilterJSON: unfilterJSON,
isJSON: isJSON,
evalJSON: NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,
include: include,
startsWith: String.prototype.startsWith || startsWith,
endsWith: String.prototype.endsWith || endsWith,
empty: empty,
blank: blank,
interpolate: interpolate
};
})());
var Template = Class.create({
initialize: function(template, pattern) {
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
},
evaluate: function(object) {
if (object && Object.isFunction(object.toTemplateReplacements))
object = object.toTemplateReplacements();
return this.template.gsub(this.pattern, function(match) {
if (object == null) return (match[1] + '');
var before = match[1] || '';
if (before == '\\') return match[2];
var ctx = object, expr = match[3],
pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
match = pattern.exec(expr);
if (match == null) return before;
while (match != null) {
var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
ctx = ctx[comp];
if (null == ctx || '' == match[3]) break;
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
match = pattern.exec(expr);
}
return before + String.interpret(ctx);
});
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
var $break = { };
var Enumerable = (function() {
function each(iterator, context) {
try {
this._each(iterator, context);
} catch (e) {
if (e != $break) throw e;
}
return this;
}
function eachSlice(number, iterator, context) {
var index = -number, slices = [], array = this.toArray();
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
}
function all(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index, this);
if (!result) throw $break;
}, this);
return result;
}
function any(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
if (result = !!iterator.call(context, value, index, this))
throw $break;
}, this);
return result;
}
function collect(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index, this));
}, this);
return results;
}
function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index, this)) {
result = value;
throw $break;
}
}, this);
return result;
}
function findAll(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index, this))
results.push(value);
}, this);
return results;
}
function grep(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
filter = new RegExp(RegExp.escape(filter));
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, value, index, this));
}, this);
return results;
}
function include(object) {
if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)
return true;
var found = false;
this.each(function(value) {
if (value == object) {
found = true;
throw $break;
}
});
return found;
}
function inGroupsOf(number, fillWith) {
fillWith = Object.isUndefined(fillWith) ? null : fillWith;
return this.eachSlice(number, function(slice) {
while(slice.length < number) slice.push(fillWith);
return slice;
});
}
function inject(memo, iterator, context) {
this.each(function(value, index) {
memo = iterator.call(context, memo, value, index, this);
}, this);
return memo;
}
function invoke(method) {
var args = $A(arguments).slice(1);
return this.map(function(value) {
return value[method].apply(value, args);
});
}
function max(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index, this);
if (result == null || value >= result)
result = value;
}, this);
return result;
}
function min(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index, this);
if (result == null || value < result)
result = value;
}, this);
return result;
}
function partition(iterator, context) {
iterator = iterator || Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
(iterator.call(context, value, index, this) ?
trues : falses).push(value);
}, this);
return [trues, falses];
}
function pluck(property) {
var results = [];
this.each(function(value) {
results.push(value[property]);
});
return results;
}
function reject(iterator, context) {
var results = [];
this.each(function(value, index) {
if (!iterator.call(context, value, index, this))
results.push(value);
}, this);
return results;
}
function sortBy(iterator, context) {
return this.map(function(value, index) {
return {
value: value,
criteria: iterator.call(context, value, index, this)
};
}, this).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
}
function toArray() {
return this.map();
}
function zip() {
var iterator = Prototype.K, args = $A(arguments);
if (Object.isFunction(args.last()))
iterator = args.pop();
var collections = [this].concat(args).map($A);
return this.map(function(value, index) {
return iterator(collections.pluck(index));
});
}
function size() {
return this.toArray().length;
}
function inspect() {
return '#<Enumerable:' + this.toArray().inspect() + '>';
}
return {
each: each,
eachSlice: eachSlice,
all: all,
every: all,
any: any,
some: any,
collect: collect,
map: collect,
detect: detect,
findAll: findAll,
select: findAll,
filter: findAll,
grep: grep,
include: include,
member: include,
inGroupsOf: inGroupsOf,
inject: inject,
invoke: invoke,
max: max,
min: min,
partition: partition,
pluck: pluck,
reject: reject,
sortBy: sortBy,
toArray: toArray,
entries: toArray,
zip: zip,
size: size,
inspect: inspect,
find: detect
};
})();
function $A(iterable) {
if (!iterable) return [];
if ('toArray' in Object(iterable)) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
function $w(string) {
if (!Object.isString(string)) return [];
string = string.strip();
return string ? string.split(/\s+/) : [];
}
Array.from = $A;
(function() {
var arrayProto = Array.prototype,
slice = arrayProto.slice,
_each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
function each(iterator, context) {
for (var i = 0, length = this.length >>> 0; i < length; i++) {
if (i in this) iterator.call(context, this[i], i, this);
}
}
if (!_each) _each = each;
function clear() {
this.length = 0;
return this;
}
function first() {
return this[0];
}
function last() {
return this[this.length - 1];
}
function compact() {
return this.select(function(value) {
return value != null;
});
}
function flatten() {
return this.inject([], function(array, value) {
if (Object.isArray(value))
return array.concat(value.flatten());
array.push(value);
return array;
});
}
function without() {
var values = slice.call(arguments, 0);
return this.select(function(value) {
return !values.include(value);
});
}
function reverse(inline) {
return (inline === false ? this.toArray() : this)._reverse();
}
function uniq(sorted) {
return this.inject([], function(array, value, index) {
if (0 == index || (sorted ? array.last() != value : !array.include(value)))
array.push(value);
return array;
});
}
function intersect(array) {
return this.uniq().findAll(function(item) {
return array.indexOf(item) !== -1;
});
}
function clone() {
return slice.call(this, 0);
}
function size() {
return this.length;
}
function inspect() {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
function indexOf(item, i) {
if (this == null) throw new TypeError();
var array = Object(this), length = array.length >>> 0;
if (length === 0) return -1;
i = Number(i);
if (isNaN(i)) {
i = 0;
} else if (i !== 0 && isFinite(i)) {
i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
}
if (i > length) return -1;
var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);
for (; k < length; k++)
if (k in array && array[k] === item) return k;
return -1;
}
function lastIndexOf(item, i) {
if (this == null) throw new TypeError();
var array = Object(this), length = array.length >>> 0;
if (length === 0) return -1;
if (!Object.isUndefined(i)) {
i = Number(i);
if (isNaN(i)) {
i = 0;
} else if (i !== 0 && isFinite(i)) {
i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));
}
} else {
i = length;
}
var k = i >= 0 ? Math.min(i, length - 1) :
length - Math.abs(i);
for (; k >= 0; k--)
if (k in array && array[k] === item) return k;
return -1;
}
function concat(_) {
var array = [], items = slice.call(arguments, 0), item, n = 0;
items.unshift(this);
for (var i = 0, length = items.length; i < length; i++) {
item = items[i];
if (Object.isArray(item) && !('callee' in item)) {
for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {
if (j in item) array[n] = item[j];
n++;
}
} else {
array[n++] = item;
}
}
array.length = n;
return array;
}
function wrapNative(method) {
return function() {
if (arguments.length === 0) {
return method.call(this, Prototype.K);
} else if (arguments[0] === undefined) {
var args = slice.call(arguments, 1);
args.unshift(Prototype.K);
return method.apply(this, args);
} else {
return method.apply(this, arguments);
}
};
}
function map(iterator) {
if (this == null) throw new TypeError();
iterator = iterator || Prototype.K;
var object = Object(this);
var results = [], context = arguments[1], n = 0;
for (var i = 0, length = object.length >>> 0; i < length; i++) {
if (i in object) {
results[n] = iterator.call(context, object[i], i, object);
}
n++;
}
results.length = n;
return results;
}
if (arrayProto.map) {
map = wrapNative(Array.prototype.map);
}
function filter(iterator) {
if (this == null || !Object.isFunction(iterator))
throw new TypeError();
var object = Object(this);
var results = [], context = arguments[1], value;
for (var i = 0, length = object.length >>> 0; i < length; i++) {
if (i in object) {
value = object[i];
if (iterator.call(context, value, i, object)) {
results.push(value);
}
}
}
return results;
}
if (arrayProto.filter) {
filter = Array.prototype.filter;
}
function some(iterator) {
if (this == null) throw new TypeError();
iterator = iterator || Prototype.K;
var context = arguments[1];
var object = Object(this);
for (var i = 0, length = object.length >>> 0; i < length; i++) {
if (i in object && iterator.call(context, object[i], i, object)) {
return true;
}
}
return false;
}
if (arrayProto.some) {
var some = wrapNative(Array.prototype.some);
}
function every(iterator) {
if (this == null) throw new TypeError();
iterator = iterator || Prototype.K;
var context = arguments[1];
var object = Object(this);
for (var i = 0, length = object.length >>> 0; i < length; i++) {
if (i in object && !iterator.call(context, object[i], i, object)) {
return false;
}
}
return true;
}
if (arrayProto.every) {
var every = wrapNative(Array.prototype.every);
}
var _reduce = arrayProto.reduce;
function inject(memo, iterator) {
iterator = iterator || Prototype.K;
var context = arguments[2];
return _reduce.call(this, iterator.bind(context), memo);
}
if (!arrayProto.reduce) {
var inject = Enumerable.inject;
}
Object.extend(arrayProto, Enumerable);
if (!arrayProto._reverse)
arrayProto._reverse = arrayProto.reverse;
Object.extend(arrayProto, {
_each: _each,
map: map,
collect: map,
select: filter,
filter: filter,
findAll: filter,
some: some,
any: some,
every: every,
all: every,
inject: inject,
clear: clear,
first: first,
last: last,
compact: compact,
flatten: flatten,
without: without,
reverse: reverse,
uniq: uniq,
intersect: intersect,
clone: clone,
toArray: clone,
size: size,
inspect: inspect
});
var CONCAT_ARGUMENTS_BUGGY = (function() {
return [].concat(arguments)[0][0] !== 1;
})(1,2);
if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object) {
return new Hash(object);
};
var Hash = Class.create(Enumerable, (function() {
function initialize(object) {
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
}
function _each(iterator, context) {
var i = 0;
for (var key in this._object) {
var value = this._object[key], pair = [key, value];
pair.key = key;
pair.value = value;
iterator.call(context, pair, i);
i++;
}
}
function set(key, value) {
return this._object[key] = value;
}
function get(key) {
if (this._object[key] !== Object.prototype[key])
return this._object[key];
}
function unset(key) {
var value = this._object[key];
delete this._object[key];
return value;
}
function toObject() {
return Object.clone(this._object);
}
function keys() {
return this.pluck('key');
}
function values() {
return this.pluck('value');
}
function index(value) {
var match = this.detect(function(pair) {
return pair.value === value;
});
return match && match.key;
}
function merge(object) {
return this.clone().update(object);
}
function update(object) {
return new Hash(object).inject(this, function(result, pair) {
result.set(pair.key, pair.value);
return result;
});
}
function toQueryPair(key, value) {
if (Object.isUndefined(value)) return key;
value = String.interpret(value);
value = value.gsub(/(\r)?\n/, '\r\n');
value = encodeURIComponent(value);
value = value.gsub(/%20/, '+');
return key + '=' + value;
}
function toQueryString() {
return this.inject([], function(results, pair) {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
if (Object.isArray(values)) {
var queryValues = [];
for (var i = 0, len = values.length, value; i < len; i++) {
value = values[i];
queryValues.push(toQueryPair(key, value));
}
return results.concat(queryValues);
}
} else results.push(toQueryPair(key, values));
return results;
}).join('&');
}
function inspect() {
return '#<Hash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
}
function clone() {
return new Hash(this);
}
return {
initialize: initialize,
_each: _each,
set: set,
get: get,
unset: unset,
toObject: toObject,
toTemplateReplacements: toObject,
keys: keys,
values: values,
index: index,
merge: merge,
update: update,
toQueryString: toQueryString,
inspect: inspect,
toJSON: toObject,
clone: clone
};
})());
Hash.from = $H;
Object.extend(Number.prototype, (function() {
function toColorPart() {
return this.toPaddedString(2, 16);
}
function succ() {
return this + 1;
}
function times(iterator, context) {
$R(0, this, true).each(iterator, context);
return this;
}
function toPaddedString(length, radix) {
var string = this.toString(radix || 10);
return '0'.times(length - string.length) + string;
}
function abs() {
return Math.abs(this);
}
function round() {
return Math.round(this);
}
function ceil() {
return Math.ceil(this);
}
function floor() {
return Math.floor(this);
}
return {
toColorPart: toColorPart,
succ: succ,
times: times,
toPaddedString: toPaddedString,
abs: abs,
round: round,
ceil: ceil,
floor: floor
};
})());
function $R(start, end, exclusive) {
return new ObjectRange(start, end, exclusive);
}
var ObjectRange = Class.create(Enumerable, (function() {
function initialize(start, end, exclusive) {
this.start = start;
this.end = end;
this.exclusive = exclusive;
}
function _each(iterator, context) {
var value = this.start, i;
for (i = 0; this.include(value); i++) {
iterator.call(context, value, i);
value = value.succ();
}
}
function include(value) {
if (value < this.start)
return false;
if (this.exclusive)
return value < this.end;
return value <= this.end;
}
return {
initialize: initialize,
_each: _each,
include: include
};
})());
var Abstract = { };
var Try = {
these: function() {
var returnValue;
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) { }
}
return returnValue;
}
};
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},
activeRequestCount: 0
};
Ajax.Responders = {
responders: [],
_each: function(iterator, context) {
this.responders._each(iterator, context);
},
register: function(responder) {
if (!this.include(responder))
this.responders.push(responder);
},
unregister: function(responder) {
this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
if (Object.isFunction(responder[callback])) {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) { }
}
});
}
};
Object.extend(Ajax.Responders, Enumerable);
Ajax.Responders.register({
onCreate: function() { Ajax.activeRequestCount++ },
onComplete: function() { Ajax.activeRequestCount-- }
});
Ajax.Base = Class.create({
initialize: function(options) {
this.options = {
method: 'post',
asynchronous: true,
contentType: 'application/x-www-form-urlencoded',
encoding: 'UTF-8',
parameters: '',
evalJSON: true,
evalJS: true
};
Object.extend(this.options, options || { });
this.options.method = this.options.method.toLowerCase();
if (Object.isHash(this.options.parameters))
this.options.parameters = this.options.parameters.toObject();
}
});
Ajax.Request = Class.create(Ajax.Base, {
_complete: false,
initialize: function($super, url, options) {
$super(options);
this.transport = Ajax.getTransport();
this.request(url);
},
request: function(url) {
this.url = url;
this.method = this.options.method;
var params = Object.isString(this.options.parameters) ?
this.options.parameters :
Object.toQueryString(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
params += (params ? '&' : '') + "_method=" + this.method;
this.method = 'post';
}
if (params && this.method === 'get') {
this.url += (this.url.include('?') ? '&' : '?') + params;
}
this.parameters = params.toQueryParams();
try {
var response = new Ajax.Response(this);
if (this.options.onCreate) this.options.onCreate(response);
Ajax.Responders.dispatch('onCreate', this, response);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
this.transport.send(this.body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
}
catch (e) {
this.dispatchException(e);
}
},
onStateChange: function() {
var readyState = this.transport.readyState;
if (readyState > 1 && !((readyState == 4) && this._complete))
this.respondToReadyState(this.transport.readyState);
},
setRequestHeaders: function() {
var headers = {
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};
if (this.method == 'post') {
headers['Content-type'] = this.options.contentType +
(this.options.encoding ? '; charset=' + this.options.encoding : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (Object.isFunction(extras.push))
for (var i = 0, length = extras.length; i < length; i += 2)
headers[extras[i]] = extras[i+1];
else
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
}
for (var name in headers)
if (headers[name] != null)
this.transport.setRequestHeader(name, headers[name]);
},
success: function() {
var status = this.getStatus();
return !status || (status >= 200 && status < 300) || status == 304;
},
getStatus: function() {
try {
if (this.transport.status === 1223) return 204;
return this.transport.status || 0;
} catch (e) { return 0 }
},
respondToReadyState: function(readyState) {
var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
if (state == 'Complete') {
try {
this._complete = true;
(this.options['on' + response.status]
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
|| (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
try {
(this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
} catch (e) {
this.dispatchException(e);
}
if (state == 'Complete') {
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
isSameOrigin: function() {
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
protocol: location.protocol,
domain: document.domain,
port: location.port ? ':' + location.port : ''
}));
},
getHeader: function(name) {
try {
return this.transport.getResponseHeader(name) || null;
} catch (e) { return null; }
},
evalResponse: function() {
try {
return eval((this.transport.responseText || '').unfilterJSON());
} catch (e) {
this.dispatchException(e);
}
},
dispatchException: function(exception) {
(this.options.onException || Prototype.emptyFunction)(this, exception);
Ajax.Responders.dispatch('onException', this, exception);
}
});
Ajax.Request.Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Response = Class.create({
initialize: function(request){
this.request = request;
var transport = this.transport = request.transport,
readyState = this.readyState = transport.readyState;
if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
this.status = this.getStatus();
this.statusText = this.getStatusText();
this.responseText = String.interpret(transport.responseText);
this.headerJSON = this._getHeaderJSON();
}
if (readyState == 4) {
var xml = transport.responseXML;
this.responseXML = Object.isUndefined(xml) ? null : xml;
this.responseJSON = this._getResponseJSON();
}
},
status: 0,
statusText: '',
getStatus: Ajax.Request.prototype.getStatus,
getStatusText: function() {
try {
return this.transport.statusText || '';
} catch (e) { return '' }
},
getHeader: Ajax.Request.prototype.getHeader,
getAllHeaders: function() {
try {
return this.getAllResponseHeaders();
} catch (e) { return null }
},
getResponseHeader: function(name) {
return this.transport.getResponseHeader(name);
},
getAllResponseHeaders: function() {
return this.transport.getAllResponseHeaders();
},
_getHeaderJSON: function() {
var json = this.getHeader('X-JSON');
if (!json) return null;
try {
json = decodeURIComponent(escape(json));
} catch(e) {
}
try {
return json.evalJSON(this.request.options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
},
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON || (options.evalJSON != 'force' &&
!(this.getHeader('Content-type') || '').include('application/json')) ||
this.responseText.blank())
return null;
try {
return this.responseText.evalJSON(options.sanitizeJSON ||
!this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
}
});
Ajax.Updater = Class.create(Ajax.Request, {
initialize: function($super, container, url, options) {
this.container = {
success: (container.success || container),
failure: (container.failure || (container.success ? null : container))
};
options = Object.clone(options);
var onComplete = options.onComplete;
options.onComplete = (function(response, json) {
this.updateContent(response.responseText);
if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);
$super(url, options);
},
updateContent: function(responseText) {
var receiver = this.container[this.success() ? 'success' : 'failure'],
options = this.options;
if (!options.evalScripts) responseText = responseText.stripScripts();
if (receiver = $(receiver)) {
if (options.insertion) {
if (Object.isString(options.insertion)) {
var insertion = { }; insertion[options.insertion] = responseText;
receiver.insert(insertion);
}
else options.insertion(receiver, responseText);
}
else receiver.update(responseText);
}
}
});
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
initialize: function($super, container, url, options) {
$super(options);
this.onComplete = this.options.onComplete;
this.frequency = (this.options.frequency || 2);
this.decay = (this.options.decay || 1);
this.updater = { };
this.container = container;
this.url = url;
this.start();
},
start: function() {
this.options.onComplete = this.updateComplete.bind(this);
this.onTimerEvent();
},
stop: function() {
this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
updateComplete: function(response) {
if (this.options.decay) {
this.decay = (response.responseText == this.lastText ?
this.decay * this.options.decay : 1);
this.lastText = response.responseText;
}
this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},
onTimerEvent: function() {
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
(function(GLOBAL) {
var UNDEFINED;
var SLICE = Array.prototype.slice;
var DIV = document.createElement('div');
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
GLOBAL.$ = $;
if (!GLOBAL.Node) GLOBAL.Node = {};
if (!GLOBAL.Node.ELEMENT_NODE) {
Object.extend(GLOBAL.Node, {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
});
}
var ELEMENT_CACHE = {};
function shouldUseCreationCache(tagName, attributes) {
if (tagName === 'select') return false;
if ('type' in attributes) return false;
return true;
}
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
try {
var el = document.createElement('<input name="x">');
return el.tagName.toLowerCase() === 'input' && el.name === 'x';
}
catch(err) {
return false;
}
})();
var oldElement = GLOBAL.Element;
function Element(tagName, attributes) {
attributes = attributes || {};
tagName = tagName.toLowerCase();
if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
return Element.writeAttribute(document.createElement(tagName), attributes);
}
if (!ELEMENT_CACHE[tagName])
ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));
var node = shouldUseCreationCache(tagName, attributes) ?
ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);
return Element.writeAttribute(node, attributes);
}
GLOBAL.Element = Element;
Object.extend(GLOBAL.Element, oldElement || {});
if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;
Element.Methods = { ByTag: {}, Simulated: {} };
var methods = {};
var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };
function inspect(element) {
element = $(element);
var result = '<' + element.tagName.toLowerCase();
var attribute, value;
for (var property in INSPECT_ATTRIBUTES) {
attribute = INSPECT_ATTRIBUTES[property];
value = (element[property] || '').toString();
if (value) result += ' ' + attribute + '=' + value.inspect(true);
}
return result + '>';
}
methods.inspect = inspect;
function visible(element) {
return $(element).style.display !== 'none';
}
function toggle(element, bool) {
element = $(element);
if (Object.isUndefined(bool))
bool = !Element.visible(element);
Element[bool ? 'show' : 'hide'](element);
return element;
}
function hide(element) {
element = $(element);
element.style.display = 'none';
return element;
}
function show(element) {
element = $(element);
element.style.display = '';
return element;
}
Object.extend(methods, {
visible: visible,
toggle: toggle,
hide: hide,
show: show
});
function remove(element) {
element = $(element);
element.parentNode.removeChild(element);
return element;
}
var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
var el = document.createElement("select"),
isBuggy = true;
el.innerHTML = "<option value=\"test\">test</option>";
if (el.options && el.options[0]) {
isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
}
el = null;
return isBuggy;
})();
var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
try {
var el = document.createElement("table");
if (el && el.tBodies) {
el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
var isBuggy = typeof el.tBodies[0] == "undefined";
el = null;
return isBuggy;
}
} catch (e) {
return true;
}
})();
var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
try {
var el = document.createElement('div');
el.innerHTML = "<link />";
var isBuggy = (el.childNodes.length === 0);
el = null;
return isBuggy;
} catch(e) {
return true;
}
})();
var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
isBuggy = false;
try {
s.appendChild(document.createTextNode(""));
isBuggy = !s.firstChild ||
s.firstChild && s.firstChild.nodeType !== 3;
} catch (e) {
isBuggy = true;
}
s = null;
return isBuggy;
})();
function update(element, content) {
element = $(element);
var descendants = element.getElementsByTagName('*'),
i = descendants.length;
while (i--) purgeElement(descendants[i]);
if (content && content.toElement)
content = content.toElement();
if (Object.isElement(content))
return element.update().insert(content);
content = Object.toHTML(content);
var tagName = element.tagName.toUpperCase();
if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {
element.text = content;
return element;
}
if (ANY_INNERHTML_BUGGY) {
if (tagName in INSERTION_TRANSLATIONS.tags) {
while (element.firstChild)
element.removeChild(element.firstChild);
var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());
for (var i = 0, node; node = nodes[i]; i++)
element.appendChild(node);
} else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
while (element.firstChild)
element.removeChild(element.firstChild);
var nodes = getContentFromAnonymousElement(tagName,
content.stripScripts(), true);
for (var i = 0, node; node = nodes[i]; i++)
element.appendChild(node);
} else {
element.innerHTML = content.stripScripts();
}
} else {
element.innerHTML = content.stripScripts();
}
content.evalScripts.bind(content).defer();
return element;
}
function replace(element, content) {
element = $(element);
if (content && content.toElement) {
content = content.toElement();
} else if (!Object.isElement(content)) {
content = Object.toHTML(content);
var range = element.ownerDocument.createRange();
range.selectNode(element);
content.evalScripts.bind(content).defer();
content = range.createContextualFragment(content.stripScripts());
}
element.parentNode.replaceChild(content, element);
return element;
}
var INSERTION_TRANSLATIONS = {
before: function(element, node) {
element.parentNode.insertBefore(node, element);
},
top: function(element, node) {
element.insertBefore(node, element.firstChild);
},
bottom: function(element, node) {
element.appendChild(node);
},
after: function(element, node) {
element.parentNode.insertBefore(node, element.nextSibling);
},
tags: {
TABLE: ['<table>', '</table>', 1],
TBODY: ['<table><tbody>', '</tbody></table>', 2],
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
SELECT: ['<select>', '</select>', 1]
}
};
var tags = INSERTION_TRANSLATIONS.tags;
Object.extend(tags, {
THEAD: tags.TBODY,
TFOOT: tags.TBODY,
TH: tags.TD
});
function replace_IE(element, content) {
element = $(element);
if (content && content.toElement)
content = content.toElement();
if (Object.isElement(content)) {
element.parentNode.replaceChild(content, element);
return element;
}
content = Object.toHTML(content);
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
if (tagName in INSERTION_TRANSLATIONS.tags) {
var nextSibling = Element.next(element);
var fragments = getContentFromAnonymousElement(
tagName, content.stripScripts());
parent.removeChild(element);
var iterator;
if (nextSibling)
iterator = function(node) { parent.insertBefore(node, nextSibling) };
else
iterator = function(node) { parent.appendChild(node); }
fragments.each(iterator);
} else {
element.outerHTML = content.stripScripts();
}
content.evalScripts.bind(content).defer();
return element;
}
if ('outerHTML' in document.documentElement)
replace = replace_IE;
function isContent(content) {
if (Object.isUndefined(content) || content === null) return false;
if (Object.isString(content) || Object.isNumber(content)) return true;
if (Object.isElement(content)) return true;
if (content.toElement || content.toHTML) return true;
return false;
}
function insertContentAt(element, content, position) {
position = position.toLowerCase();
var method = INSERTION_TRANSLATIONS[position];
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
method(element, content);
return element;
}
content = Object.toHTML(content);
var tagName = ((position === 'before' || position === 'after') ?
element.parentNode : element).tagName.toUpperCase();
var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());
if (position === 'top' || position === 'after') childNodes.reverse();
for (var i = 0, node; node = childNodes[i]; i++)
method(element, node);
content.evalScripts.bind(content).defer();
}
function insert(element, insertions) {
element = $(element);
if (isContent(insertions))
insertions = { bottom: insertions };
for (var position in insertions)
insertContentAt(element, insertions[position], position);
return element;
}
function wrap(element, wrapper, attributes) {
element = $(element);
if (Object.isElement(wrapper)) {
$(wrapper).writeAttribute(attributes || {});
} else if (Object.isString(wrapper)) {
wrapper = new Element(wrapper, attributes);
} else {
wrapper = new Element('div', wrapper);
}
if (element.parentNode)
element.parentNode.replaceChild(wrapper, element);
wrapper.appendChild(element);
return wrapper;
}
function cleanWhitespace(element) {
element = $(element);
var node = element.firstChild;
while (node) {
var nextNode = node.nextSibling;
if (node.nodeType === Node.TEXT_NODE && !/\S/.test(node.nodeValue))
element.removeChild(node);
node = nextNode;
}
return element;
}
function empty(element) {
return $(element).innerHTML.blank();
}
function getContentFromAnonymousElement(tagName, html, force) {
var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;
var workaround = !!t;
if (!workaround && force) {
workaround = true;
t = ['', '', 0];
}
if (workaround) {
div.innerHTML = '&#160;' + t[0] + html + t[1];
div.removeChild(div.firstChild);
for (var i = t[2]; i--; )
div = div.firstChild;
} else {
div.innerHTML = html;
}
return $A(div.childNodes);
}
function clone(element, deep) {
if (!(element = $(element))) return;
var clone = element.cloneNode(deep);
if (!HAS_UNIQUE_ID_PROPERTY) {
clone._prototypeUID = UNDEFINED;
if (deep) {
var descendants = Element.select(clone, '*'),
i = descendants.length;
while (i--)
descendants[i]._prototypeUID = UNDEFINED;
}
}
return Element.extend(clone);
}
function purgeElement(element) {
var uid = getUniqueElementID(element);
if (uid) {
Element.stopObserving(element);
if (!HAS_UNIQUE_ID_PROPERTY)
element._prototypeUID = UNDEFINED;
delete Element.Storage[uid];
}
}
function purgeCollection(elements) {
var i = elements.length;
while (i--)
purgeElement(elements[i]);
}
function purgeCollection_IE(elements) {
var i = elements.length, element, uid;
while (i--) {
element = elements[i];
uid = getUniqueElementID(element);
delete Element.Storage[uid];
delete Event.cache[uid];
}
}
if (HAS_UNIQUE_ID_PROPERTY) {
purgeCollection = purgeCollection_IE;
}
function purge(element) {
if (!(element = $(element))) return;
purgeElement(element);
var descendants = element.getElementsByTagName('*'),
i = descendants.length;
while (i--) purgeElement(descendants[i]);
return null;
}
Object.extend(methods, {
remove: remove,
update: update,
replace: replace,
insert: insert,
wrap: wrap,
cleanWhitespace: cleanWhitespace,
empty: empty,
clone: clone,
purge: purge
});
function recursivelyCollect(element, property, maximumLength) {
element = $(element);
maximumLength = maximumLength || -1;
var elements = [];
while (element = element[property]) {
if (element.nodeType === Node.ELEMENT_NODE)
elements.push(Element.extend(element));
if (elements.length === maximumLength) break;
}
return elements;
}
function ancestors(element) {
return recursivelyCollect(element, 'parentNode');
}
function descendants(element) {
return Element.select(element, '*');
}
function firstDescendant(element) {
element = $(element).firstChild;
while (element && element.nodeType !== Node.ELEMENT_NODE)
element = element.nextSibling;
return $(element);
}
function immediateDescendants(element) {
var results = [], child = $(element).firstChild;
while (child) {
if (child.nodeType === Node.ELEMENT_NODE)
results.push(Element.extend(child));
child = child.nextSibling;
}
return results;
}
function previousSiblings(element) {
return recursivelyCollect(element, 'previousSibling');
}
function nextSiblings(element) {
return recursivelyCollect(element, 'nextSibling');
}
function siblings(element) {
element = $(element);
var previous = previousSiblings(element),
next = nextSiblings(element);
return previous.reverse().concat(next);
}
function match(element, selector) {
element = $(element);
if (Object.isString(selector))
return Prototype.Selector.match(element, selector);
return selector.match(element);
}
function _recursivelyFind(element, property, expression, index) {
element = $(element), expression = expression || 0, index = index || 0;
if (Object.isNumber(expression)) {
index = expression, expression = null;
}
while (element = element[property]) {
if (element.nodeType !== 1) continue;
if (expression && !Prototype.Selector.match(element, expression))
continue;
if (--index >= 0) continue;
return Element.extend(element);
}
}
function up(element, expression, index) {
element = $(element);
if (arguments.length === 1) return $(element.parentNode);
return _recursivelyFind(element, 'parentNode', expression, index);
}
function down(element, expression, index) {
if (arguments.length === 1) return firstDescendant(element);
element = $(element), expression = expression || 0, index = index || 0;
if (Object.isNumber(expression))
index = expression, expression = '*';
var node = Prototype.Selector.select(expression, element)[index];
return Element.extend(node);
}
function previous(element, expression, index) {
return _recursivelyFind(element, 'previousSibling', expression, index);
}
function next(element, expression, index) {
return _recursivelyFind(element, 'nextSibling', expression, index);
}
function select(element) {
element = $(element);
var expressions = SLICE.call(arguments, 1).join(', ');
return Prototype.Selector.select(expressions, element);
}
function adjacent(element) {
element = $(element);
var expressions = SLICE.call(arguments, 1).join(', ');
var siblings = Element.siblings(element), results = [];
for (var i = 0, sibling; sibling = siblings[i]; i++) {
if (Prototype.Selector.match(sibling, expressions))
results.push(sibling);
}
return results;
}
function descendantOf_DOM(element, ancestor) {
element = $(element), ancestor = $(ancestor);
while (element = element.parentNode)
if (element === ancestor) return true;
return false;
}
function descendantOf_contains(element, ancestor) {
element = $(element), ancestor = $(ancestor);
if (!ancestor.contains) return descendantOf_DOM(element, ancestor);
return ancestor.contains(element) && ancestor !== element;
}
function descendantOf_compareDocumentPosition(element, ancestor) {
element = $(element), ancestor = $(ancestor);
return (element.compareDocumentPosition(ancestor) & 8) === 8;
}
var descendantOf;
if (DIV.compareDocumentPosition) {
descendantOf = descendantOf_compareDocumentPosition;
} else if (DIV.contains) {
descendantOf = descendantOf_contains;
} else {
descendantOf = descendantOf_DOM;
}
Object.extend(methods, {
recursivelyCollect: recursivelyCollect,
ancestors: ancestors,
descendants: descendants,
firstDescendant: firstDescendant,
immediateDescendants: immediateDescendants,
previousSiblings: previousSiblings,
nextSiblings: nextSiblings,
siblings: siblings,
match: match,
up: up,
down: down,
previous: previous,
next: next,
select: select,
adjacent: adjacent,
descendantOf: descendantOf,
getElementsBySelector: select,
childElements: immediateDescendants
});
var idCounter = 1;
function identify(element) {
element = $(element);
var id = Element.readAttribute(element, 'id');
if (id) return id;
do { id = 'anonymous_element_' + idCounter++ } while ($(id));
Element.writeAttribute(element, 'id', id);
return id;
}
function readAttribute(element, name) {
return $(element).getAttribute(name);
}
function readAttribute_IE(element, name) {
element = $(element);
var table = ATTRIBUTE_TRANSLATIONS.read;
if (table.values[name])
return table.values[name](element, name);
if (table.names[name]) name = table.names[name];
if (name.include(':')) {
if (!element.attributes || !element.attributes[name]) return null;
return element.attributes[name].value;
}
return element.getAttribute(name);
}
function readAttribute_Opera(element, name) {
if (name === 'title') return element.title;
return element.getAttribute(name);
}
var PROBLEMATIC_ATTRIBUTE_READING = (function() {
DIV.setAttribute('onclick', []);
var value = DIV.getAttribute('onclick');
var isFunction = Object.isArray(value);
DIV.removeAttribute('onclick');
return isFunction;
})();
if (PROBLEMATIC_ATTRIBUTE_READING) {
readAttribute = readAttribute_IE;
} else if (Prototype.Browser.Opera) {
readAttribute = readAttribute_Opera;
}
function writeAttribute(element, name, value) {
element = $(element);
var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;
if (typeof name === 'object') {
attributes = name;
} else {
attributes[name] = Object.isUndefined(value) ? true : value;
}
for (var attr in attributes) {
name = table.names[attr] || attr;
value = attributes[attr];
if (table.values[attr])
name = table.values[attr](element, value) || name;
if (value === false || value === null)
element.removeAttribute(name);
else if (value === true)
element.setAttribute(name, name);
else element.setAttribute(name, value);
}
return element;
}
var PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES = (function () {
if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) {
return false;
}
var checkbox = document.createElement('<input type="checkbox">');
checkbox.checked = true;
var node = checkbox.getAttributeNode('checked');
return !node || !node.specified;
})();
function hasAttribute(element, attribute) {
attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;
var node = $(element).getAttributeNode(attribute);
return !!(node && node.specified);
}
function hasAttribute_IE(element, attribute) {
if (attribute === 'checked') {
return element.checked;
}
return hasAttribute(element, attribute);
}
GLOBAL.Element.Methods.Simulated.hasAttribute =
PROBLEMATIC_HAS_ATTRIBUTE_WITH_CHECKBOXES ?
hasAttribute_IE : hasAttribute;
function classNames(element) {
return new Element.ClassNames(element);
}
var regExpCache = {};
function getRegExpForClassName(className) {
if (regExpCache[className]) return regExpCache[className];
var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
regExpCache[className] = re;
return re;
}
function hasClassName(element, className) {
if (!(element = $(element))) return;
var elementClassName = element.className;
if (elementClassName.length === 0) return false;
if (elementClassName === className) return true;
return getRegExpForClassName(className).test(elementClassName);
}
function addClassName(element, className) {
if (!(element = $(element))) return;
if (!hasClassName(element, className))
element.className += (element.className ? ' ' : '') + className;
return element;
}
function removeClassName(element, className) {
if (!(element = $(element))) return;
element.className = element.className.replace(
getRegExpForClassName(className), ' ').strip();
return element;
}
function toggleClassName(element, className, bool) {
if (!(element = $(element))) return;
if (Object.isUndefined(bool))
bool = !hasClassName(element, className);
var method = Element[bool ? 'addClassName' : 'removeClassName'];
return method(element, className);
}
var ATTRIBUTE_TRANSLATIONS = {};
var classProp = 'className', forProp = 'for';
DIV.setAttribute(classProp, 'x');
if (DIV.className !== 'x') {
DIV.setAttribute('class', 'x');
if (DIV.className === 'x')
classProp = 'class';
}
var LABEL = document.createElement('label');
LABEL.setAttribute(forProp, 'x');
if (LABEL.htmlFor !== 'x') {
LABEL.setAttribute('htmlFor', 'x');
if (LABEL.htmlFor === 'x')
forProp = 'htmlFor';
}
LABEL = null;
function _getAttr(element, attribute) {
return element.getAttribute(attribute);
}
function _getAttr2(element, attribute) {
return element.getAttribute(attribute, 2);
}
function _getAttrNode(element, attribute) {
var node = element.getAttributeNode(attribute);
return node ? node.value : '';
}
function _getFlag(element, attribute) {
return $(element).hasAttribute(attribute) ? attribute : null;
}
DIV.onclick = Prototype.emptyFunction;
var onclickValue = DIV.getAttribute('onclick');
var _getEv;
if (String(onclickValue).indexOf('{') > -1) {
_getEv = function(element, attribute) {
var value = element.getAttribute(attribute);
if (!value) return null;
value = value.toString();
value = value.split('{')[1];
value = value.split('}')[0];
return value.strip();
};
}
else if (onclickValue === '') {
_getEv = function(element, attribute) {
var value = element.getAttribute(attribute);
if (!value) return null;
return value.strip();
};
}
ATTRIBUTE_TRANSLATIONS.read = {
names: {
'class': classProp,
'className': classProp,
'for': forProp,
'htmlFor': forProp
},
values: {
style: function(element) {
return element.style.cssText.toLowerCase();
},
title: function(element) {
return element.title;
}
}
};
ATTRIBUTE_TRANSLATIONS.write = {
names: {
className: 'class',
htmlFor: 'for',
cellpadding: 'cellPadding',
cellspacing: 'cellSpacing'
},
values: {
checked: function(element, value) {
element.checked = !!value;
},
style: function(element, value) {
element.style.cssText = value ? value : '';
}
}
};
ATTRIBUTE_TRANSLATIONS.has = { names: {} };
Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,
ATTRIBUTE_TRANSLATIONS.read.names);
var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +
'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');
for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {
ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;
ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()] = attr;
}
Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {
href: _getAttr2,
src: _getAttr2,
type: _getAttr,
action: _getAttrNode,
disabled: _getFlag,
checked: _getFlag,
readonly: _getFlag,
multiple: _getFlag,
onload: _getEv,
onunload: _getEv,
onclick: _getEv,
ondblclick: _getEv,
onmousedown: _getEv,
onmouseup: _getEv,
onmouseover: _getEv,
onmousemove: _getEv,
onmouseout: _getEv,
onfocus: _getEv,
onblur: _getEv,
onkeypress: _getEv,
onkeydown: _getEv,
onkeyup: _getEv,
onsubmit: _getEv,
onreset: _getEv,
onselect: _getEv,
onchange: _getEv
});
Object.extend(methods, {
identify: identify,
readAttribute: readAttribute,
writeAttribute: writeAttribute,
classNames: classNames,
hasClassName: hasClassName,
addClassName: addClassName,
removeClassName: removeClassName,
toggleClassName: toggleClassName
});
function normalizeStyleName(style) {
if (style === 'float' || style === 'styleFloat')
return 'cssFloat';
return style.camelize();
}
function normalizeStyleName_IE(style) {
if (style === 'float' || style === 'cssFloat')
return 'styleFloat';
return style.camelize();
}
function setStyle(element, styles) {
element = $(element);
var elementStyle = element.style, match;
if (Object.isString(styles)) {
elementStyle.cssText += ';' + styles;
if (styles.include('opacity')) {
var opacity = styles.match(/opacity:\s*(\d?\.?\d*)/)[1];
Element.setOpacity(element, opacity);
}
return element;
}
for (var property in styles) {
if (property === 'opacity') {
Element.setOpacity(element, styles[property]);
} else {
var value = styles[property];
if (property === 'float' || property === 'cssFloat') {
property = Object.isUndefined(elementStyle.styleFloat) ?
'cssFloat' : 'styleFloat';
}
elementStyle[property] = value;
}
}
return element;
}
function getStyle(element, style) {
element = $(element);
style = normalizeStyleName(style);
var value = element.style[style];
if (!value || value === 'auto') {
var css = document.defaultView.getComputedStyle(element, null);
value = css ? css[style] : null;
}
if (style === 'opacity') return value ? parseFloat(value) : 1.0;
return value === 'auto' ? null : value;
}
function getStyle_Opera(element, style) {
switch (style) {
case 'height': case 'width':
if (!Element.visible(element)) return null;
var dim = parseInt(getStyle(element, style), 10);
if (dim !== element['offset' + style.capitalize()])
return dim + 'px';
return Element.measure(element, style);
default: return getStyle(element, style);
}
}
function getStyle_IE(element, style) {
element = $(element);
style = normalizeStyleName_IE(style);
var value = element.style[style];
if (!value && element.currentStyle) {
value = element.currentStyle[style];
}
if (style === 'opacity' && !STANDARD_CSS_OPACITY_SUPPORTED)
return getOpacity_IE(element);
if (value === 'auto') {
if ((style === 'width' || style === 'height') && Element.visible(element))
return Element.measure(element, style) + 'px';
return null;
}
return value;
}
function stripAlphaFromFilter_IE(filter) {
return (filter || '').replace(/alpha\([^\)]*\)/gi, '');
}
function hasLayout_IE(element) {
if (!element.currentStyle || !element.currentStyle.hasLayout)
element.style.zoom = 1;
return element;
}
var STANDARD_CSS_OPACITY_SUPPORTED = (function() {
DIV.style.cssText = "opacity:.55";
return /^0.55/.test(DIV.style.opacity);
})();
function setOpacity(element, value) {
element = $(element);
if (value == 1 || value === '') value = '';
else if (value < 0.00001) value = 0;
element.style.opacity = value;
return element;
}
function setOpacity_IE(element, value) {
if (STANDARD_CSS_OPACITY_SUPPORTED)
return setOpacity(element, value);
element = hasLayout_IE($(element));
var filter = Element.getStyle(element, 'filter'),
style = element.style;
if (value == 1 || value === '') {
filter = stripAlphaFromFilter_IE(filter);
if (filter) style.filter = filter;
else style.removeAttribute('filter');
return element;
}
if (value < 0.00001) value = 0;
style.filter = stripAlphaFromFilter_IE(filter) +
'alpha(opacity=' + (value * 100) + ')';
return element;
}
function getOpacity(element) {
return Element.getStyle(element, 'opacity');
}
function getOpacity_IE(element) {
if (STANDARD_CSS_OPACITY_SUPPORTED)
return getOpacity(element);
var filter = Element.getStyle(element, 'filter');
if (filter.length === 0) return 1.0;
var match = (filter || '').match(/alpha\(opacity=(.*)\)/);
if (match && match[1]) return parseFloat(match[1]) / 100;
return 1.0;
}
Object.extend(methods, {
setStyle: setStyle,
getStyle: getStyle,
setOpacity: setOpacity,
getOpacity: getOpacity
});
if ('styleFloat' in DIV.style) {
methods.getStyle = getStyle_IE;
methods.setOpacity = setOpacity_IE;
methods.getOpacity = getOpacity_IE;
}
var UID = 0;
GLOBAL.Element.Storage = { UID: 1 };
function getUniqueElementID(element) {
if (element === window) return 0;
if (typeof element._prototypeUID === 'undefined')
element._prototypeUID = Element.Storage.UID++;
return element._prototypeUID;
}
function getUniqueElementID_IE(element) {
if (element === window) return 0;
if (element == document) return 1;
return element.uniqueID;
}
var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);
if (HAS_UNIQUE_ID_PROPERTY)
getUniqueElementID = getUniqueElementID_IE;
function getStorage(element) {
if (!(element = $(element))) return;
var uid = getUniqueElementID(element);
if (!Element.Storage[uid])
Element.Storage[uid] = $H();
return Element.Storage[uid];
}
function store(element, key, value) {
if (!(element = $(element))) return;
var storage = getStorage(element);
if (arguments.length === 2) {
storage.update(key);
} else {
storage.set(key, value);
}
return element;
}
function retrieve(element, key, defaultValue) {
if (!(element = $(element))) return;
var storage = getStorage(element), value = storage.get(key);
if (Object.isUndefined(value)) {
storage.set(key, defaultValue);
value = defaultValue;
}
return value;
}
Object.extend(methods, {
getStorage: getStorage,
store: store,
retrieve: retrieve
});
var Methods = {}, ByTag = Element.Methods.ByTag,
F = Prototype.BrowserFeatures;
if (!F.ElementExtensions && ('__proto__' in DIV)) {
GLOBAL.HTMLElement = {};
GLOBAL.HTMLElement.prototype = DIV['__proto__'];
F.ElementExtensions = true;
}
function checkElementPrototypeDeficiency(tagName) {
if (typeof window.Element === 'undefined') return false;
if (!HAS_EXTENDED_CREATE_ELEMENT_SYNTAX) return false;
var proto = window.Element.prototype;
if (proto) {
var id = '_' + (Math.random() + '').slice(2),
el = document.createElement(tagName);
proto[id] = 'x';
var isBuggy = (el[id] !== 'x');
delete proto[id];
el = null;
return isBuggy;
}
return false;
}
var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =
checkElementPrototypeDeficiency('object');
function extendElementWith(element, methods) {
for (var property in methods) {
var value = methods[property];
if (Object.isFunction(value) && !(property in element))
element[property] = value.methodize();
}
}
var EXTENDED = {};
function elementIsExtended(element) {
var uid = getUniqueElementID(element);
return (uid in EXTENDED);
}
function extend(element) {
if (!element || elementIsExtended(element)) return element;
if (element.nodeType !== Node.ELEMENT_NODE || element == window)
return element;
var methods = Object.clone(Methods),
tagName = element.tagName.toUpperCase();
if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
extendElementWith(element, methods);
EXTENDED[getUniqueElementID(element)] = true;
return element;
}
function extend_IE8(element) {
if (!element || elementIsExtended(element)) return element;
var t = element.tagName;
if (t && (/^(?:object|applet|embed)$/i.test(t))) {
extendElementWith(element, Element.Methods);
extendElementWith(element, Element.Methods.Simulated);
extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
}
return element;
}
if (F.SpecificElementExtensions) {
extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;
}
function addMethodsToTagName(tagName, methods) {
tagName = tagName.toUpperCase();
if (!ByTag[tagName]) ByTag[tagName] = {};
Object.extend(ByTag[tagName], methods);
}
function mergeMethods(destination, methods, onlyIfAbsent) {
if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;
for (var property in methods) {
var value = methods[property];
if (!Object.isFunction(value)) continue;
if (!onlyIfAbsent || !(property in destination))
destination[property] = value.methodize();
}
}
function findDOMClass(tagName) {
var klass;
var trans = {
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
"TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
"FrameSet", "IFRAME": "IFrame"
};
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName.capitalize() + 'Element';
if (window[klass]) return window[klass];
var element = document.createElement(tagName),
proto = element['__proto__'] || element.constructor.prototype;
element = null;
return proto;
}
function addMethods(methods) {
if (arguments.length === 0) addFormMethods();
if (arguments.length === 2) {
var tagName = methods;
methods = arguments[1];
}
if (!tagName) {
Object.extend(Element.Methods, methods || {});
} else {
if (Object.isArray(tagName)) {
for (var i = 0, tag; tag = tagName[i]; i++)
addMethodsToTagName(tag, methods);
} else {
addMethodsToTagName(tagName, methods);
}
}
var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
Element.prototype;
if (F.ElementExtensions) {
mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);
mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);
}
if (F.SpecificElementExtensions) {
for (var tag in Element.Methods.ByTag) {
var klass = findDOMClass(tag);
if (Object.isUndefined(klass)) continue;
mergeMethods(klass.prototype, ByTag[tag]);
}
}
Object.extend(Element, Element.Methods);
Object.extend(Element, Element.Methods.Simulated);
delete Element.ByTag;
delete Element.Simulated;
Element.extend.refresh();
ELEMENT_CACHE = {};
}
Object.extend(GLOBAL.Element, {
extend: extend,
addMethods: addMethods
});
if (extend === Prototype.K) {
GLOBAL.Element.extend.refresh = Prototype.emptyFunction;
} else {
GLOBAL.Element.extend.refresh = function() {
if (Prototype.BrowserFeatures.ElementExtensions) return;
Object.extend(Methods, Element.Methods);
Object.extend(Methods, Element.Methods.Simulated);
EXTENDED = {};
};
}
function addFormMethods() {
Object.extend(Form, Form.Methods);
Object.extend(Form.Element, Form.Element.Methods);
Object.extend(Element.Methods.ByTag, {
"FORM": Object.clone(Form.Methods),
"INPUT": Object.clone(Form.Element.Methods),
"SELECT": Object.clone(Form.Element.Methods),
"TEXTAREA": Object.clone(Form.Element.Methods),
"BUTTON": Object.clone(Form.Element.Methods)
});
}
Element.addMethods(methods);
function destroyCache_IE() {
DIV = null;
ELEMENT_CACHE = null;
}
if (window.attachEvent)
window.attachEvent('onunload', destroyCache_IE);
})(this);
(function() {
function toDecimal(pctString) {
var match = pctString.match(/^(\d+)%?$/i);
if (!match) return null;
return (Number(match[1]) / 100);
}
function getRawStyle(element, style) {
element = $(element);
var value = element.style[style];
if (!value || value === 'auto') {
var css = document.defaultView.getComputedStyle(element, null);
value = css ? css[style] : null;
}
if (style === 'opacity') return value ? parseFloat(value) : 1.0;
return value === 'auto' ? null : value;
}
function getRawStyle_IE(element, style) {
var value = element.style[style];
if (!value && element.currentStyle) {
value = element.currentStyle[style];
}
return value;
}
function getContentWidth(element, context) {
var boxWidth = element.offsetWidth;
var bl = getPixelValue(element, 'borderLeftWidth', context) || 0;
var br = getPixelValue(element, 'borderRightWidth', context) || 0;
var pl = getPixelValue(element, 'paddingLeft', context) || 0;
var pr = getPixelValue(element, 'paddingRight', context) || 0;
return boxWidth - bl - br - pl - pr;
}
if ('currentStyle' in document.documentElement) {
getRawStyle = getRawStyle_IE;
}
function getPixelValue(value, property, context) {
var element = null;
if (Object.isElement(value)) {
element = value;
value = getRawStyle(element, property);
}
if (value === null || Object.isUndefined(value)) {
return null;
}
if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) {
return window.parseFloat(value);
}
var isPercentage = value.include('%'), isViewport = (context === document.viewport);
if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
var style = element.style.left, rStyle = element.runtimeStyle.left;
element.runtimeStyle.left = element.currentStyle.left;
element.style.left = value || 0;
value = element.style.pixelLeft;
element.style.left = style;
element.runtimeStyle.left = rStyle;
return value;
}
if (element && isPercentage) {
context = context || element.parentNode;
var decimal = toDecimal(value), whole = null;
var isHorizontal = property.include('left') || property.include('right') ||
property.include('width');
var isVertical = property.include('top') || property.include('bottom') ||
property.include('height');
if (context === document.viewport) {
if (isHorizontal) {
whole = document.viewport.getWidth();
} else if (isVertical) {
whole = document.viewport.getHeight();
}
} else {
if (isHorizontal) {
whole = $(context).measure('width');
} else if (isVertical) {
whole = $(context).measure('height');
}
}
return (whole === null) ? 0 : whole * decimal;
}
return 0;
}
function toCSSPixels(number) {
if (Object.isString(number) && number.endsWith('px'))
return number;
return number + 'px';
}
function isDisplayed(element) {
while (element && element.parentNode) {
var display = element.getStyle('display');
if (display === 'none') {
return false;
}
element = $(element.parentNode);
}
return true;
}
var hasLayout = Prototype.K;
if ('currentStyle' in document.documentElement) {
hasLayout = function(element) {
if (!element.currentStyle.hasLayout) {
element.style.zoom = 1;
}
return element;
};
}
function cssNameFor(key) {
if (key.include('border')) key = key + '-width';
return key.camelize();
}
Element.Layout = Class.create(Hash, {
initialize: function($super, element, preCompute) {
$super();
this.element = $(element);
Element.Layout.PROPERTIES.each( function(property) {
this._set(property, null);
}, this);
if (preCompute) {
this._preComputing = true;
this._begin();
Element.Layout.PROPERTIES.each( this._compute, this );
this._end();
this._preComputing = false;
}
},
_set: function(property, value) {
return Hash.prototype.set.call(this, property, value);
},
set: function(property, value) {
throw "Properties of Element.Layout are read-only.";
},
get: function($super, property) {
var value = $super(property);
return value === null ? this._compute(property) : value;
},
_begin: function() {
if (this._isPrepared()) return;
var element = this.element;
if (isDisplayed(element)) {
this._setPrepared(true);
return;
}
var originalStyles = {
position: element.style.position || '',
width: element.style.width || '',
visibility: element.style.visibility || '',
display: element.style.display || ''
};
element.store('prototype_original_styles', originalStyles);
var position = getRawStyle(element, 'position'), width = element.offsetWidth;
if (width === 0 || width === null) {
element.style.display = 'block';
width = element.offsetWidth;
}
var context = (position === 'fixed') ? document.viewport :
element.parentNode;
var tempStyles = {
visibility: 'hidden',
display: 'block'
};
if (position !== 'fixed') tempStyles.position = 'absolute';
element.setStyle(tempStyles);
var positionedWidth = element.offsetWidth, newWidth;
if (width && (positionedWidth === width)) {
newWidth = getContentWidth(element, context);
} else if (position === 'absolute' || position === 'fixed') {
newWidth = getContentWidth(element, context);
} else {
var parent = element.parentNode, pLayout = $(parent).getLayout();
newWidth = pLayout.get('width') -
this.get('margin-left') -
this.get('border-left') -
this.get('padding-left') -
this.get('padding-right') -
this.get('border-right') -
this.get('margin-right');
}
element.setStyle({ width: newWidth + 'px' });
this._setPrepared(true);
},
_end: function() {
var element = this.element;
var originalStyles = element.retrieve('prototype_original_styles');
element.store('prototype_original_styles', null);
element.setStyle(originalStyles);
this._setPrepared(false);
},
_compute: function(property) {
var COMPUTATIONS = Element.Layout.COMPUTATIONS;
if (!(property in COMPUTATIONS)) {
throw "Property not found.";
}
return this._set(property, COMPUTATIONS[property].call(this, this.element));
},
_isPrepared: function() {
return this.element.retrieve('prototype_element_layout_prepared', false);
},
_setPrepared: function(bool) {
return this.element.store('prototype_element_layout_prepared', bool);
},
toObject: function() {
var args = $A(arguments);
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
args.join(' ').split(' ');
var obj = {};
keys.each( function(key) {
if (!Element.Layout.PROPERTIES.include(key)) return;
var value = this.get(key);
if (value != null) obj[key] = value;
}, this);
return obj;
},
toHash: function() {
var obj = this.toObject.apply(this, arguments);
return new Hash(obj);
},
toCSS: function() {
var args = $A(arguments);
var keys = (args.length === 0) ? Element.Layout.PROPERTIES :
args.join(' ').split(' ');
var css = {};
keys.each( function(key) {
if (!Element.Layout.PROPERTIES.include(key)) return;
if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;
var value = this.get(key);
if (value != null) css[cssNameFor(key)] = value + 'px';
}, this);
return css;
},
inspect: function() {
return "#<Element.Layout>";
}
});
Object.extend(Element.Layout, {
PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),
COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),
COMPUTATIONS: {
'height': function(element) {
if (!this._preComputing) this._begin();
var bHeight = this.get('border-box-height');
if (bHeight <= 0) {
if (!this._preComputing) this._end();
return 0;
}
var bTop = this.get('border-top'),
bBottom = this.get('border-bottom');
var pTop = this.get('padding-top'),
pBottom = this.get('padding-bottom');
if (!this._preComputing) this._end();
return bHeight - bTop - bBottom - pTop - pBottom;
},
'width': function(element) {
if (!this._preComputing) this._begin();
var bWidth = this.get('border-box-width');
if (bWidth <= 0) {
if (!this._preComputing) this._end();
return 0;
}
var bLeft = this.get('border-left'),
bRight = this.get('border-right');
var pLeft = this.get('padding-left'),
pRight = this.get('padding-right');
if (!this._preComputing) this._end();
return bWidth - bLeft - bRight - pLeft - pRight;
},
'padding-box-height': function(element) {
var height = this.get('height'),
pTop = this.get('padding-top'),
pBottom = this.get('padding-bottom');
return height + pTop + pBottom;
},
'padding-box-width': function(element) {
var width = this.get('width'),
pLeft = this.get('padding-left'),
pRight = this.get('padding-right');
return width + pLeft + pRight;
},
'border-box-height': function(element) {
if (!this._preComputing) this._begin();
var height = element.offsetHeight;
if (!this._preComputing) this._end();
return height;
},
'border-box-width': function(element) {
if (!this._preComputing) this._begin();
var width = element.offsetWidth;
if (!this._preComputing) this._end();
return width;
},
'margin-box-height': function(element) {
var bHeight = this.get('border-box-height'),
mTop = this.get('margin-top'),
mBottom = this.get('margin-bottom');
if (bHeight <= 0) return 0;
return bHeight + mTop + mBottom;
},
'margin-box-width': function(element) {
var bWidth = this.get('border-box-width'),
mLeft = this.get('margin-left'),
mRight = this.get('margin-right');
if (bWidth <= 0) return 0;
return bWidth + mLeft + mRight;
},
'top': function(element) {
var offset = element.positionedOffset();
return offset.top;
},
'bottom': function(element) {
var offset = element.positionedOffset(),
parent = element.getOffsetParent(),
pHeight = parent.measure('height');
var mHeight = this.get('border-box-height');
return pHeight - mHeight - offset.top;
},
'left': function(element) {
var offset = element.positionedOffset();
return offset.left;
},
'right': function(element) {
var offset = element.positionedOffset(),
parent = element.getOffsetParent(),
pWidth = parent.measure('width');
var mWidth = this.get('border-box-width');
return pWidth - mWidth - offset.left;
},
'padding-top': function(element) {
return getPixelValue(element, 'paddingTop');
},
'padding-bottom': function(element) {
return getPixelValue(element, 'paddingBottom');
},
'padding-left': function(element) {
return getPixelValue(element, 'paddingLeft');
},
'padding-right': function(element) {
return getPixelValue(element, 'paddingRight');
},
'border-top': function(element) {
return getPixelValue(element, 'borderTopWidth');
},
'border-bottom': function(element) {
return getPixelValue(element, 'borderBottomWidth');
},
'border-left': function(element) {
return getPixelValue(element, 'borderLeftWidth');
},
'border-right': function(element) {
return getPixelValue(element, 'borderRightWidth');
},
'margin-top': function(element) {
return getPixelValue(element, 'marginTop');
},
'margin-bottom': function(element) {
return getPixelValue(element, 'marginBottom');
},
'margin-left': function(element) {
return getPixelValue(element, 'marginLeft');
},
'margin-right': function(element) {
return getPixelValue(element, 'marginRight');
}
}
});
if ('getBoundingClientRect' in document.documentElement) {
Object.extend(Element.Layout.COMPUTATIONS, {
'right': function(element) {
var parent = hasLayout(element.getOffsetParent());
var rect = element.getBoundingClientRect(),
pRect = parent.getBoundingClientRect();
return (pRect.right - rect.right).round();
},
'bottom': function(element) {
var parent = hasLayout(element.getOffsetParent());
var rect = element.getBoundingClientRect(),
pRect = parent.getBoundingClientRect();
return (pRect.bottom - rect.bottom).round();
}
});
}
Element.Offset = Class.create({
initialize: function(left, top) {
this.left = left.round();
this.top = top.round();
this[0] = this.left;
this[1] = this.top;
},
relativeTo: function(offset) {
return new Element.Offset(
this.left - offset.left,
this.top - offset.top
);
},
inspect: function() {
return "#<Element.Offset left: #{left} top: #{top}>".interpolate(this);
},
toString: function() {
return "[#{left}, #{top}]".interpolate(this);
},
toArray: function() {
return [this.left, this.top];
}
});
function getLayout(element, preCompute) {
return new Element.Layout(element, preCompute);
}
function measure(element, property) {
return $(element).getLayout().get(property);
}
function getHeight(element) {
return Element.getDimensions(element).height;
}
function getWidth(element) {
return Element.getDimensions(element).width;
}
function getDimensions(element) {
element = $(element);
var display = Element.getStyle(element, 'display');
if (display && display !== 'none') {
return { width: element.offsetWidth, height: element.offsetHeight };
}
var style = element.style;
var originalStyles = {
visibility: style.visibility,
position: style.position,
display: style.display
};
var newStyles = {
visibility: 'hidden',
display: 'block'
};
if (originalStyles.position !== 'fixed')
newStyles.position = 'absolute';
Element.setStyle(element, newStyles);
var dimensions = {
width: element.offsetWidth,
height: element.offsetHeight
};
Element.setStyle(element, originalStyles);
return dimensions;
}
function getOffsetParent(element) {
element = $(element);
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
return $(document.body);
var isInline = (Element.getStyle(element, 'display') === 'inline');
if (!isInline && element.offsetParent) return $(element.offsetParent);
while ((element = element.parentNode) && element !== document.body) {
if (Element.getStyle(element, 'position') !== 'static') {
return isHtml(element) ? $(document.body) : $(element);
}
}
return $(document.body);
}
function cumulativeOffset(element) {
element = $(element);
var valueT = 0, valueL = 0;
if (element.parentNode) {
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
} while (element);
}
return new Element.Offset(valueL, valueT);
}
function positionedOffset(element) {
element = $(element);
var layout = element.getLayout();
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
element = element.offsetParent;
if (element) {
if (isBody(element)) break;
var p = Element.getStyle(element, 'position');
if (p !== 'static') break;
}
} while (element);
valueL -= layout.get('margin-top');
valueT -= layout.get('margin-left');
return new Element.Offset(valueL, valueT);
}
function cumulativeScrollOffset(element) {
var valueT = 0, valueL = 0;
do {
if (element === document.body) {
var bodyScrollNode = document.documentElement || document.body.parentNode || document.body;
valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0;
valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0;
break;
} else {
valueT += element.scrollTop || 0;
valueL += element.scrollLeft || 0;
element = element.parentNode;
}
} while (element);
return new Element.Offset(valueL, valueT);
}
function viewportOffset(forElement) {
var valueT = 0, valueL = 0, docBody = document.body;
forElement = $(forElement);
var element = forElement;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == docBody &&
Element.getStyle(element, 'position') == 'absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
if (element != docBody) {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
}
} while (element = element.parentNode);
return new Element.Offset(valueL, valueT);
}
function absolutize(element) {
element = $(element);
if (Element.getStyle(element, 'position') === 'absolute') {
return element;
}
var offsetParent = getOffsetParent(element);
var eOffset = element.viewportOffset(),
pOffset = offsetParent.viewportOffset();
var offset = eOffset.relativeTo(pOffset);
var layout = element.getLayout();
element.store('prototype_absolutize_original_styles', {
position: element.getStyle('position'),
left: element.getStyle('left'),
top: element.getStyle('top'),
width: element.getStyle('width'),
height: element.getStyle('height')
});
element.setStyle({
position: 'absolute',
top: offset.top + 'px',
left: offset.left + 'px',
width: layout.get('width') + 'px',
height: layout.get('height') + 'px'
});
return element;
}
function relativize(element) {
element = $(element);
if (Element.getStyle(element, 'position') === 'relative') {
return element;
}
var originalStyles =
element.retrieve('prototype_absolutize_original_styles');
if (originalStyles) element.setStyle(originalStyles);
return element;
}
function scrollTo(element) {
element = $(element);
var pos = Element.cumulativeOffset(element);
window.scrollTo(pos.left, pos.top);
return element;
}
function makePositioned(element) {
element = $(element);
var position = Element.getStyle(element, 'position'), styles = {};
if (position === 'static' || !position) {
styles.position = 'relative';
if (Prototype.Browser.Opera) {
styles.top = 0;
styles.left = 0;
}
Element.setStyle(element, styles);
Element.store(element, 'prototype_made_positioned', true);
}
return element;
}
function undoPositioned(element) {
element = $(element);
var storage = Element.getStorage(element),
madePositioned = storage.get('prototype_made_positioned');
if (madePositioned) {
storage.unset('prototype_made_positioned');
Element.setStyle(element, {
position: '',
top: '',
bottom: '',
left: '',
right: ''
});
}
return element;
}
function makeClipping(element) {
element = $(element);
var storage = Element.getStorage(element),
madeClipping = storage.get('prototype_made_clipping');
if (Object.isUndefined(madeClipping)) {
var overflow = Element.getStyle(element, 'overflow');
storage.set('prototype_made_clipping', overflow);
if (overflow !== 'hidden')
element.style.overflow = 'hidden';
}
return element;
}
function undoClipping(element) {
element = $(element);
var storage = Element.getStorage(element),
overflow = storage.get('prototype_made_clipping');
if (!Object.isUndefined(overflow)) {
storage.unset('prototype_made_clipping');
element.style.overflow = overflow || '';
}
return element;
}
function clonePosition(element, source, options) {
options = Object.extend({
setLeft: true,
setTop: true,
setWidth: true,
setHeight: true,
offsetTop: 0,
offsetLeft: 0
}, options || {});
source = $(source);
element = $(element);
var p, delta, layout, styles = {};
if (options.setLeft || options.setTop) {
p = Element.viewportOffset(source);
delta = [0, 0];
if (Element.getStyle(element, 'position') === 'absolute') {
var parent = Element.getOffsetParent(element);
if (parent !== document.body) delta = Element.viewportOffset(parent);
}
}
if (options.setWidth || options.setHeight) {
layout = Element.getLayout(source);
}
if (options.setLeft)
styles.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
if (options.setTop)
styles.top = (p[1] - delta[1] + options.offsetTop) + 'px';
if (options.setWidth)
styles.width = layout.get('border-box-width') + 'px';
if (options.setHeight)
styles.height = layout.get('border-box-height') + 'px';
return Element.setStyle(element, styles);
}
if (Prototype.Browser.IE) {
getOffsetParent = getOffsetParent.wrap(
function(proceed, element) {
element = $(element);
if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
return $(document.body);
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
}
);
positionedOffset = positionedOffset.wrap(function(proceed, element) {
element = $(element);
if (!element.parentNode) return new Element.Offset(0, 0);
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
var offsetParent = element.getOffsetParent();
if (offsetParent && offsetParent.getStyle('position') === 'fixed')
hasLayout(offsetParent);
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
});
} else if (Prototype.Browser.Webkit) {
cumulativeOffset = function(element) {
element = $(element);
var valueT = 0, valueL = 0;
do {
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
if (element.offsetParent == document.body) {
if (Element.getStyle(element, 'position') == 'absolute') break;
}
element = element.offsetParent;
} while (element);
return new Element.Offset(valueL, valueT);
};
}
Element.addMethods({
getLayout: getLayout,
measure: measure,
getWidth: getWidth,
getHeight: getHeight,
getDimensions: getDimensions,
getOffsetParent: getOffsetParent,
cumulativeOffset: cumulativeOffset,
positionedOffset: positionedOffset,
cumulativeScrollOffset: cumulativeScrollOffset,
viewportOffset: viewportOffset,
absolutize: absolutize,
relativize: relativize,
scrollTo: scrollTo,
makePositioned: makePositioned,
undoPositioned: undoPositioned,
makeClipping: makeClipping,
undoClipping: undoClipping,
clonePosition: clonePosition
});
function isBody(element) {
return element.nodeName.toUpperCase() === 'BODY';
}
function isHtml(element) {
return element.nodeName.toUpperCase() === 'HTML';
}
function isDocument(element) {
return element.nodeType === Node.DOCUMENT_NODE;
}
function isDetached(element) {
return element !== document.body &&
!Element.descendantOf(element, document.body);
}
if ('getBoundingClientRect' in document.documentElement) {
Element.addMethods({
viewportOffset: function(element) {
element = $(element);
if (isDetached(element)) return new Element.Offset(0, 0);
var rect = element.getBoundingClientRect(),
docEl = document.documentElement;
return new Element.Offset(rect.left - docEl.clientLeft,
rect.top - docEl.clientTop);
}
});
}
})();
(function() {
var IS_OLD_OPERA = Prototype.Browser.Opera &&
(window.parseFloat(window.opera.version()) < 9.5);
var ROOT = null;
function getRootElement() {
if (ROOT) return ROOT;
ROOT = IS_OLD_OPERA ? document.body : document.documentElement;
return ROOT;
}
function getDimensions() {
return { width: this.getWidth(), height: this.getHeight() };
}
function getWidth() {
return getRootElement().clientWidth;
}
function getHeight() {
return getRootElement().clientHeight;
}
function getScrollOffsets() {
var x = window.pageXOffset || document.documentElement.scrollLeft ||
document.body.scrollLeft;
var y = window.pageYOffset || document.documentElement.scrollTop ||
document.body.scrollTop;
return new Element.Offset(x, y);
}
document.viewport = {
getDimensions: getDimensions,
getWidth: getWidth,
getHeight: getHeight,
getScrollOffsets: getScrollOffsets
};
})();
window.$$ = function() {
var expression = $A(arguments).join(', ');
return Prototype.Selector.select(expression, document);
};
Prototype.Selector = (function() {
function select() {
throw new Error('Method "Prototype.Selector.select" must be defined.');
}
function match() {
throw new Error('Method "Prototype.Selector.match" must be defined.');
}
function find(elements, expression, index) {
index = index || 0;
var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;
for (i = 0; i < length; i++) {
if (match(elements[i], expression) && index == matchIndex++) {
return Element.extend(elements[i]);
}
}
}
function extendElements(elements) {
for (var i = 0, length = elements.length; i < length; i++) {
Element.extend(elements[i]);
}
return elements;
}
var K = Prototype.K;
return {
select: select,
match: match,
find: find,
extendElements: (Element.extend === K) ? K : extendElements,
extendElement: Element.extend
};
})();
Prototype._original_property = window.Sizzle;
/*!
* Sizzle CSS Selector Engine v@VERSION
* http://sizzlejs.com/
*
* Copyright 2013 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: @DATE
*/
(function( window ) {
var i,
support,
Expr,
getText,
isXML,
compile,
select,
outermostContext,
sortInput,
hasDuplicate,
setDocument,
document,
docElem,
documentIsHTML,
rbuggyQSA,
rbuggyMatches,
matches,
contains,
expando = "sizzle" + -(new Date()),
preferredDoc = window.document,
dirruns = 0,
done = 0,
classCache = createCache(),
tokenCache = createCache(),
compilerCache = createCache(),
sortOrder = function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
}
return 0;
},
strundefined = typeof undefined,
MAX_NEGATIVE = 1 << 31,
hasOwn = ({}).hasOwnProperty,
arr = [],
pop = arr.pop,
push_native = arr.push,
push = arr.push,
slice = arr.slice,
indexOf = arr.indexOf || function( elem ) {
var i = 0,
len = this.length;
for ( ; i < len; i++ ) {
if ( this[i] === elem ) {
return i;
}
}
return -1;
},
booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
whitespace = "[\\x20\\t\\r\\n\\f]",
characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
identifier = characterEncoding.replace( "w", "w#" ),
attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
rpseudo = new RegExp( pseudos ),
ridentifier = new RegExp( "^" + identifier + "$" ),
matchExpr = {
"ID": new RegExp( "^#(" + characterEncoding + ")" ),
"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
"ATTR": new RegExp( "^" + attributes ),
"PSEUDO": new RegExp( "^" + pseudos ),
"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
},
rinputs = /^(?:input|select|textarea|button)$/i,
rheader = /^h\d$/i,
rnative = /^[^{]+\{\s*\[native \w/,
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
rsibling = /[+~]/,
rescape = /'|\\/g,
runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
funescape = function( _, escaped, escapedWhitespace ) {
var high = "0x" + escaped - 0x10000;
return high !== high || escapedWhitespace ?
escaped :
high < 0 ?
String.fromCharCode( high + 0x10000 ) :
String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
};
try {
push.apply(
(arr = slice.call( preferredDoc.childNodes )),
preferredDoc.childNodes
);
arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
push = { apply: arr.length ?
function( target, els ) {
push_native.apply( target, slice.call(els) );
} :
function( target, els ) {
var j = target.length,
i = 0;
while ( (target[j++] = els[i++]) ) {}
target.length = j - 1;
}
};
}
function Sizzle( selector, context, results, seed ) {
var match, elem, m, nodeType,
i, groups, old, nid, newContext, newSelector;
if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
setDocument( context );
}
context = context || document;
results = results || [];
if ( !selector || typeof selector !== "string" ) {
return results;
}
if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
return [];
}
if ( documentIsHTML && !seed ) {
if ( (match = rquickExpr.exec( selector )) ) {
if ( (m = match[1]) ) {
if ( nodeType === 9 ) {
elem = context.getElementById( m );
if ( elem && elem.parentNode ) {
if ( elem.id === m ) {
results.push( elem );
return results;
}
} else {
return results;
}
} else {
if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
contains( context, elem ) && elem.id === m ) {
results.push( elem );
return results;
}
}
} else if ( match[2] ) {
push.apply( results, context.getElementsByTagName( selector ) );
return results;
} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
push.apply( results, context.getElementsByClassName( m ) );
return results;
}
}
if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
nid = old = expando;
newContext = context;
newSelector = nodeType === 9 && selector;
if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
groups = tokenize( selector );
if ( (old = context.getAttribute("id")) ) {
nid = old.replace( rescape, "\\$&" );
} else {
context.setAttribute( "id", nid );
}
nid = "[id='" + nid + "'] ";
i = groups.length;
while ( i-- ) {
groups[i] = nid + toSelector( groups[i] );
}
newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
newSelector = groups.join(",");
}
if ( newSelector ) {
try {
push.apply( results,
newContext.querySelectorAll( newSelector )
);
return results;
} catch(qsaError) {
} finally {
if ( !old ) {
context.removeAttribute("id");
}
}
}
}
}
return select( selector.replace( rtrim, "$1" ), context, results, seed );
}
/**
* Create key-value caches of limited size
* @returns {Function(string, Object)} Returns the Object data after storing it on itself with
* property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
* deleting the oldest entry
*/
function createCache() {
var keys = [];
function cache( key, value ) {
if ( keys.push( key + " " ) > Expr.cacheLength ) {
delete cache[ keys.shift() ];
}
return (cache[ key + " " ] = value);
}
return cache;
}
/**
* Mark a function for special use by Sizzle
* @param {Function} fn The function to mark
*/
function markFunction( fn ) {
fn[ expando ] = true;
return fn;
}
/**
* Support testing using an element
* @param {Function} fn Passed the created div and expects a boolean result
*/
function assert( fn ) {
var div = document.createElement("div");
try {
return !!fn( div );
} catch (e) {
return false;
} finally {
if ( div.parentNode ) {
div.parentNode.removeChild( div );
}
div = null;
}
}
/**
* Adds the same handler for all of the specified attrs
* @param {String} attrs Pipe-separated list of attributes
* @param {Function} handler The method that will be applied
*/
function addHandle( attrs, handler ) {
var arr = attrs.split("|"),
i = attrs.length;
while ( i-- ) {
Expr.attrHandle[ arr[i] ] = handler;
}
}
/**
* Checks document order of two siblings
* @param {Element} a
* @param {Element} b
* @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
*/
function siblingCheck( a, b ) {
var cur = b && a,
diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
( ~b.sourceIndex || MAX_NEGATIVE ) -
( ~a.sourceIndex || MAX_NEGATIVE );
if ( diff ) {
return diff;
}
if ( cur ) {
while ( (cur = cur.nextSibling) ) {
if ( cur === b ) {
return -1;
}
}
}
return a ? 1 : -1;
}
/**
* Returns a function to use in pseudos for input types
* @param {String} type
*/
function createInputPseudo( type ) {
return function( elem ) {
var name = elem.nodeName.toLowerCase();
return name === "input" && elem.type === type;
};
}
/**
* Returns a function to use in pseudos for buttons
* @param {String} type
*/
function createButtonPseudo( type ) {
return function( elem ) {
var name = elem.nodeName.toLowerCase();
return (name === "input" || name === "button") && elem.type === type;
};
}
/**
* Returns a function to use in pseudos for positionals
* @param {Function} fn
*/
function createPositionalPseudo( fn ) {
return markFunction(function( argument ) {
argument = +argument;
return markFunction(function( seed, matches ) {
var j,
matchIndexes = fn( [], seed.length, argument ),
i = matchIndexes.length;
while ( i-- ) {
if ( seed[ (j = matchIndexes[i]) ] ) {
seed[j] = !(matches[j] = seed[j]);
}
}
});
});
}
/**
* Checks a node for validity as a Sizzle context
* @param {Element|Object=} context
* @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
*/
function testContext( context ) {
return context && typeof context.getElementsByTagName !== strundefined && context;
}
support = Sizzle.support = {};
/**
* Detects XML nodes
* @param {Element|Object} elem An element or a document
* @returns {Boolean} True iff elem is a non-HTML XML node
*/
isXML = Sizzle.isXML = function( elem ) {
var documentElement = elem && (elem.ownerDocument || elem).documentElement;
return documentElement ? documentElement.nodeName !== "HTML" : false;
};
/**
* Sets document-related variables once based on the current document
* @param {Element|Object} [doc] An element or document object to use to set the document
* @returns {Object} Returns the current document
*/
setDocument = Sizzle.setDocument = function( node ) {
var hasCompare,
doc = node ? node.ownerDocument || node : preferredDoc,
parent = doc.defaultView;
if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
return document;
}
document = doc;
docElem = doc.documentElement;
documentIsHTML = !isXML( doc );
if ( parent && parent !== parent.top ) {
if ( parent.addEventListener ) {
parent.addEventListener( "unload", function() {
setDocument();
}, false );
} else if ( parent.attachEvent ) {
parent.attachEvent( "onunload", function() {
setDocument();
});
}
}
/* Attributes
---------------------------------------------------------------------- */
support.attributes = assert(function( div ) {
div.className = "i";
return !div.getAttribute("className");
});
/* getElement(s)By*
---------------------------------------------------------------------- */
support.getElementsByTagName = assert(function( div ) {
div.appendChild( doc.createComment("") );
return !div.getElementsByTagName("*").length;
});
support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
div.innerHTML = "<div class='a'></div><div class='a i'></div>";
div.firstChild.className = "i";
return div.getElementsByClassName("i").length === 2;
});
support.getById = assert(function( div ) {
docElem.appendChild( div ).id = expando;
return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
});
if ( support.getById ) {
Expr.find["ID"] = function( id, context ) {
if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
var m = context.getElementById( id );
return m && m.parentNode ? [m] : [];
}
};
Expr.filter["ID"] = function( id ) {
var attrId = id.replace( runescape, funescape );
return function( elem ) {
return elem.getAttribute("id") === attrId;
};
};
} else {
delete Expr.find["ID"];
Expr.filter["ID"] = function( id ) {
var attrId = id.replace( runescape, funescape );
return function( elem ) {
var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
return node && node.value === attrId;
};
};
}
Expr.find["TAG"] = support.getElementsByTagName ?
function( tag, context ) {
if ( typeof context.getElementsByTagName !== strundefined ) {
return context.getElementsByTagName( tag );
}
} :
function( tag, context ) {
var elem,
tmp = [],
i = 0,
results = context.getElementsByTagName( tag );
if ( tag === "*" ) {
while ( (elem = results[i++]) ) {
if ( elem.nodeType === 1 ) {
tmp.push( elem );
}
}
return tmp;
}
return results;
};
Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
return context.getElementsByClassName( className );
}
};
/* QSA/matchesSelector
---------------------------------------------------------------------- */
rbuggyMatches = [];
rbuggyQSA = [];
if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
assert(function( div ) {
div.innerHTML = "<select t=''><option selected=''></option></select>";
if ( div.querySelectorAll("[t^='']").length ) {
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
}
if ( !div.querySelectorAll("[selected]").length ) {
rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
}
if ( !div.querySelectorAll(":checked").length ) {
rbuggyQSA.push(":checked");
}
});
assert(function( div ) {
var input = doc.createElement("input");
input.setAttribute( "type", "hidden" );
div.appendChild( input ).setAttribute( "name", "D" );
if ( div.querySelectorAll("[name=d]").length ) {
rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
}
if ( !div.querySelectorAll(":enabled").length ) {
rbuggyQSA.push( ":enabled", ":disabled" );
}
div.querySelectorAll("*,:x");
rbuggyQSA.push(",.*:");
});
}
if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
docElem.mozMatchesSelector ||
docElem.oMatchesSelector ||
docElem.msMatchesSelector) )) ) {
assert(function( div ) {
support.disconnectedMatch = matches.call( div, "div" );
matches.call( div, "[s!='']:x" );
rbuggyMatches.push( "!=", pseudos );
});
}
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
/* Contains
---------------------------------------------------------------------- */
hasCompare = rnative.test( docElem.compareDocumentPosition );
contains = hasCompare || rnative.test( docElem.contains ) ?
function( a, b ) {
var adown = a.nodeType === 9 ? a.documentElement : a,
bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && (
adown.contains ?
adown.contains( bup ) :
a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
));
} :
function( a, b ) {
if ( b ) {
while ( (b = b.parentNode) ) {
if ( b === a ) {
return true;
}
}
}
return false;
};
/* Sorting
---------------------------------------------------------------------- */
sortOrder = hasCompare ?
function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
return 0;
}
var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
if ( compare ) {
return compare;
}
compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
a.compareDocumentPosition( b ) :
1;
if ( compare & 1 ||
(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
return -1;
}
if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
return 1;
}
return sortInput ?
( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
0;
}
return compare & 4 ? -1 : 1;
} :
function( a, b ) {
if ( a === b ) {
hasDuplicate = true;
return 0;
}
var cur,
i = 0,
aup = a.parentNode,
bup = b.parentNode,
ap = [ a ],
bp = [ b ];
if ( !aup || !bup ) {
return a === doc ? -1 :
b === doc ? 1 :
aup ? -1 :
bup ? 1 :
sortInput ?
( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
0;
} else if ( aup === bup ) {
return siblingCheck( a, b );
}
cur = a;
while ( (cur = cur.parentNode) ) {
ap.unshift( cur );
}
cur = b;
while ( (cur = cur.parentNode) ) {
bp.unshift( cur );
}
while ( ap[i] === bp[i] ) {
i++;
}
return i ?
siblingCheck( ap[i], bp[i] ) :
ap[i] === preferredDoc ? -1 :
bp[i] === preferredDoc ? 1 :
0;
};
return doc;
};
Sizzle.matches = function( expr, elements ) {
return Sizzle( expr, null, null, elements );
};
Sizzle.matchesSelector = function( elem, expr ) {
if ( ( elem.ownerDocument || elem ) !== document ) {
setDocument( elem );
}
expr = expr.replace( rattributeQuotes, "='$1']" );
if ( support.matchesSelector && documentIsHTML &&
( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
try {
var ret = matches.call( elem, expr );
if ( ret || support.disconnectedMatch ||
elem.document && elem.document.nodeType !== 11 ) {
return ret;
}
} catch(e) {}
}
return Sizzle( expr, document, null, [elem] ).length > 0;
};
Sizzle.contains = function( context, elem ) {
if ( ( context.ownerDocument || context ) !== document ) {
setDocument( context );
}
return contains( context, elem );
};
Sizzle.attr = function( elem, name ) {
if ( ( elem.ownerDocument || elem ) !== document ) {
setDocument( elem );
}
var fn = Expr.attrHandle[ name.toLowerCase() ],
val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
fn( elem, name, !documentIsHTML ) :
undefined;
return val !== undefined ?
val :
support.attributes || !documentIsHTML ?
elem.getAttribute( name ) :
(val = elem.getAttributeNode(name)) && val.specified ?
val.value :
null;
};
Sizzle.error = function( msg ) {
throw new Error( "Syntax error, unrecognized expression: " + msg );
};
/**
* Document sorting and removing duplicates
* @param {ArrayLike} results
*/
Sizzle.uniqueSort = function( results ) {
var elem,
duplicates = [],
j = 0,
i = 0;
hasDuplicate = !support.detectDuplicates;
sortInput = !support.sortStable && results.slice( 0 );
results.sort( sortOrder );
if ( hasDuplicate ) {
while ( (elem = results[i++]) ) {
if ( elem === results[ i ] ) {
j = duplicates.push( i );
}
}
while ( j-- ) {
results.splice( duplicates[ j ], 1 );
}
}
sortInput = null;
return results;
};
/**
* Utility function for retrieving the text value of an array of DOM nodes
* @param {Array|Element} elem
*/
getText = Sizzle.getText = function( elem ) {
var node,
ret = "",
i = 0,
nodeType = elem.nodeType;
if ( !nodeType ) {
while ( (node = elem[i++]) ) {
ret += getText( node );
}
} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
if ( typeof elem.textContent === "string" ) {
return elem.textContent;
} else {
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
ret += getText( elem );
}
}
} else if ( nodeType === 3 || nodeType === 4 ) {
return elem.nodeValue;
}
return ret;
};
Expr = Sizzle.selectors = {
cacheLength: 50,
createPseudo: markFunction,
match: matchExpr,
attrHandle: {},
find: {},
relative: {
">": { dir: "parentNode", first: true },
" ": { dir: "parentNode" },
"+": { dir: "previousSibling", first: true },
"~": { dir: "previousSibling" }
},
preFilter: {
"ATTR": function( match ) {
match[1] = match[1].replace( runescape, funescape );
match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
if ( match[2] === "~=" ) {
match[3] = " " + match[3] + " ";
}
return match.slice( 0, 4 );
},
"CHILD": function( match ) {
/* matches from matchExpr["CHILD"]
1 type (only|nth|...)
2 what (child|of-type)
3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4 xn-component of xn+y argument ([+-]?\d*n|)
5 sign of xn-component
6 x of xn-component
7 sign of y-component
8 y of y-component
*/
match[1] = match[1].toLowerCase();
if ( match[1].slice( 0, 3 ) === "nth" ) {
if ( !match[3] ) {
Sizzle.error( match[0] );
}
match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
} else if ( match[3] ) {
Sizzle.error( match[0] );
}
return match;
},
"PSEUDO": function( match ) {
var excess,
unquoted = !match[5] && match[2];
if ( matchExpr["CHILD"].test( match[0] ) ) {
return null;
}
if ( match[3] && match[4] !== undefined ) {
match[2] = match[4];
} else if ( unquoted && rpseudo.test( unquoted ) &&
(excess = tokenize( unquoted, true )) &&
(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
match[0] = match[0].slice( 0, excess );
match[2] = unquoted.slice( 0, excess );
}
return match.slice( 0, 3 );
}
},
filter: {
"TAG": function( nodeNameSelector ) {
var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
return nodeNameSelector === "*" ?
function() { return true; } :
function( elem ) {
return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
};
},
"CLASS": function( className ) {
var pattern = classCache[ className + " " ];
return pattern ||
(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
classCache( className, function( elem ) {
return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
});
},
"ATTR": function( name, operator, check ) {
return function( elem ) {
var result = Sizzle.attr( elem, name );
if ( result == null ) {
return operator === "!=";
}
if ( !operator ) {
return true;
}
result += "";
return operator === "=" ? result === check :
operator === "!=" ? result !== check :
operator === "^=" ? check && result.indexOf( check ) === 0 :
operator === "*=" ? check && result.indexOf( check ) > -1 :
operator === "$=" ? check && result.slice( -check.length ) === check :
operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
false;
};
},
"CHILD": function( type, what, argument, first, last ) {
var simple = type.slice( 0, 3 ) !== "nth",
forward = type.slice( -4 ) !== "last",
ofType = what === "of-type";
return first === 1 && last === 0 ?
function( elem ) {
return !!elem.parentNode;
} :
function( elem, context, xml ) {
var cache, outerCache, node, diff, nodeIndex, start,
dir = simple !== forward ? "nextSibling" : "previousSibling",
parent = elem.parentNode,
name = ofType && elem.nodeName.toLowerCase(),
useCache = !xml && !ofType;
if ( parent ) {
if ( simple ) {
while ( dir ) {
node = elem;
while ( (node = node[ dir ]) ) {
if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
return false;
}
}
start = dir = type === "only" && !start && "nextSibling";
}
return true;
}
start = [ forward ? parent.firstChild : parent.lastChild ];
if ( forward && useCache ) {
outerCache = parent[ expando ] || (parent[ expando ] = {});
cache = outerCache[ type ] || [];
nodeIndex = cache[0] === dirruns && cache[1];
diff = cache[0] === dirruns && cache[2];
node = nodeIndex && parent.childNodes[ nodeIndex ];
while ( (node = ++nodeIndex && node && node[ dir ] ||
(diff = nodeIndex = 0) || start.pop()) ) {
if ( node.nodeType === 1 && ++diff && node === elem ) {
outerCache[ type ] = [ dirruns, nodeIndex, diff ];
break;
}
}
} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
diff = cache[1];
} else {
while ( (node = ++nodeIndex && node && node[ dir ] ||
(diff = nodeIndex = 0) || start.pop()) ) {
if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
if ( useCache ) {
(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
}
if ( node === elem ) {
break;
}
}
}
}
diff -= last;
return diff === first || ( diff % first === 0 && diff / first >= 0 );
}
};
},
"PSEUDO": function( pseudo, argument ) {
var args,
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
Sizzle.error( "unsupported pseudo: " + pseudo );
if ( fn[ expando ] ) {
return fn( argument );
}
if ( fn.length > 1 ) {
args = [ pseudo, pseudo, "", argument ];
return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
markFunction(function( seed, matches ) {
var idx,
matched = fn( seed, argument ),
i = matched.length;
while ( i-- ) {
idx = indexOf.call( seed, matched[i] );
seed[ idx ] = !( matches[ idx ] = matched[i] );
}
}) :
function( elem ) {
return fn( elem, 0, args );
};
}
return fn;
}
},
pseudos: {
"not": markFunction(function( selector ) {
var input = [],
results = [],
matcher = compile( selector.replace( rtrim, "$1" ) );
return matcher[ expando ] ?
markFunction(function( seed, matches, context, xml ) {
var elem,
unmatched = matcher( seed, null, xml, [] ),
i = seed.length;
while ( i-- ) {
if ( (elem = unmatched[i]) ) {
seed[i] = !(matches[i] = elem);
}
}
}) :
function( elem, context, xml ) {
input[0] = elem;
matcher( input, null, xml, results );
return !results.pop();
};
}),
"has": markFunction(function( selector ) {
return function( elem ) {
return Sizzle( selector, elem ).length > 0;
};
}),
"contains": markFunction(function( text ) {
return function( elem ) {
return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
};
}),
"lang": markFunction( function( lang ) {
if ( !ridentifier.test(lang || "") ) {
Sizzle.error( "unsupported lang: " + lang );
}
lang = lang.replace( runescape, funescape ).toLowerCase();
return function( elem ) {
var elemLang;
do {
if ( (elemLang = documentIsHTML ?
elem.lang :
elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
elemLang = elemLang.toLowerCase();
return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
}
} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
return false;
};
}),
"target": function( elem ) {
var hash = window.location && window.location.hash;
return hash && hash.slice( 1 ) === elem.id;
},
"root": function( elem ) {
return elem === docElem;
},
"focus": function( elem ) {
return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
},
"enabled": function( elem ) {
return elem.disabled === false;
},
"disabled": function( elem ) {
return elem.disabled === true;
},
"checked": function( elem ) {
var nodeName = elem.nodeName.toLowerCase();
return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
},
"selected": function( elem ) {
if ( elem.parentNode ) {
elem.parentNode.selectedIndex;
}
return elem.selected === true;
},
"empty": function( elem ) {
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
if ( elem.nodeType < 6 ) {
return false;
}
}
return true;
},
"parent": function( elem ) {
return !Expr.pseudos["empty"]( elem );
},
"header": function( elem ) {
return rheader.test( elem.nodeName );
},
"input": function( elem ) {
return rinputs.test( elem.nodeName );
},
"button": function( elem ) {
var name = elem.nodeName.toLowerCase();
return name === "input" && elem.type === "button" || name === "button";
},
"text": function( elem ) {
var attr;
return elem.nodeName.toLowerCase() === "input" &&
elem.type === "text" &&
( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
},
"first": createPositionalPseudo(function() {
return [ 0 ];
}),
"last": createPositionalPseudo(function( matchIndexes, length ) {
return [ length - 1 ];
}),
"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
return [ argument < 0 ? argument + length : argument ];
}),
"even": createPositionalPseudo(function( matchIndexes, length ) {
var i = 0;
for ( ; i < length; i += 2 ) {
matchIndexes.push( i );
}
return matchIndexes;
}),
"odd": createPositionalPseudo(function( matchIndexes, length ) {
var i = 1;
for ( ; i < length; i += 2 ) {
matchIndexes.push( i );
}
return matchIndexes;
}),
"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
var i = argument < 0 ? argument + length : argument;
for ( ; --i >= 0; ) {
matchIndexes.push( i );
}
return matchIndexes;
}),
"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
var i = argument < 0 ? argument + length : argument;
for ( ; ++i < length; ) {
matchIndexes.push( i );
}
return matchIndexes;
})
}
};
Expr.pseudos["nth"] = Expr.pseudos["eq"];
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
Expr.pseudos[ i ] = createButtonPseudo( i );
}
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();
function tokenize( selector, parseOnly ) {
var matched, match, tokens, type,
soFar, groups, preFilters,
cached = tokenCache[ selector + " " ];
if ( cached ) {
return parseOnly ? 0 : cached.slice( 0 );
}
soFar = selector;
groups = [];
preFilters = Expr.preFilter;
while ( soFar ) {
if ( !matched || (match = rcomma.exec( soFar )) ) {
if ( match ) {
soFar = soFar.slice( match[0].length ) || soFar;
}
groups.push( (tokens = []) );
}
matched = false;
if ( (match = rcombinators.exec( soFar )) ) {
matched = match.shift();
tokens.push({
value: matched,
type: match[0].replace( rtrim, " " )
});
soFar = soFar.slice( matched.length );
}
for ( type in Expr.filter ) {
if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
(match = preFilters[ type ]( match ))) ) {
matched = match.shift();
tokens.push({
value: matched,
type: type,
matches: match
});
soFar = soFar.slice( matched.length );
}
}
if ( !matched ) {
break;
}
}
return parseOnly ?
soFar.length :
soFar ?
Sizzle.error( selector ) :
tokenCache( selector, groups ).slice( 0 );
}
function toSelector( tokens ) {
var i = 0,
len = tokens.length,
selector = "";
for ( ; i < len; i++ ) {
selector += tokens[i].value;
}
return selector;
}
function addCombinator( matcher, combinator, base ) {
var dir = combinator.dir,
checkNonElements = base && dir === "parentNode",
doneName = done++;
return combinator.first ?
function( elem, context, xml ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
return matcher( elem, context, xml );
}
}
} :
function( elem, context, xml ) {
var oldCache, outerCache,
newCache = [ dirruns, doneName ];
if ( xml ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
if ( matcher( elem, context, xml ) ) {
return true;
}
}
}
} else {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
outerCache = elem[ expando ] || (elem[ expando ] = {});
if ( (oldCache = outerCache[ dir ]) &&
oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
return (newCache[ 2 ] = oldCache[ 2 ]);
} else {
outerCache[ dir ] = newCache;
if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
return true;
}
}
}
}
}
};
}
function elementMatcher( matchers ) {
return matchers.length > 1 ?
function( elem, context, xml ) {
var i = matchers.length;
while ( i-- ) {
if ( !matchers[i]( elem, context, xml ) ) {
return false;
}
}
return true;
} :
matchers[0];
}
function multipleContexts( selector, contexts, results ) {
var i = 0,
len = contexts.length;
for ( ; i < len; i++ ) {
Sizzle( selector, contexts[i], results );
}
return results;
}
function condense( unmatched, map, filter, context, xml ) {
var elem,
newUnmatched = [],
i = 0,
len = unmatched.length,
mapped = map != null;
for ( ; i < len; i++ ) {
if ( (elem = unmatched[i]) ) {
if ( !filter || filter( elem, context, xml ) ) {
newUnmatched.push( elem );
if ( mapped ) {
map.push( i );
}
}
}
}
return newUnmatched;
}
function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
if ( postFilter && !postFilter[ expando ] ) {
postFilter = setMatcher( postFilter );
}
if ( postFinder && !postFinder[ expando ] ) {
postFinder = setMatcher( postFinder, postSelector );
}
return markFunction(function( seed, results, context, xml ) {
var temp, i, elem,
preMap = [],
postMap = [],
preexisting = results.length,
elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
matcherIn = preFilter && ( seed || !selector ) ?
condense( elems, preMap, preFilter, context, xml ) :
elems,
matcherOut = matcher ?
postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
[] :
results :
matcherIn;
if ( matcher ) {
matcher( matcherIn, matcherOut, context, xml );
}
if ( postFilter ) {
temp = condense( matcherOut, postMap );
postFilter( temp, [], context, xml );
i = temp.length;
while ( i-- ) {
if ( (elem = temp[i]) ) {
matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
}
}
}
if ( seed ) {
if ( postFinder || preFilter ) {
if ( postFinder ) {
temp = [];
i = matcherOut.length;
while ( i-- ) {
if ( (elem = matcherOut[i]) ) {
temp.push( (matcherIn[i] = elem) );
}
}
postFinder( null, (matcherOut = []), temp, xml );
}
i = matcherOut.length;
while ( i-- ) {
if ( (elem = matcherOut[i]) &&
(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
seed[temp] = !(results[temp] = elem);
}
}
}
} else {
matcherOut = condense(
matcherOut === results ?
matcherOut.splice( preexisting, matcherOut.length ) :
matcherOut
);
if ( postFinder ) {
postFinder( null, results, matcherOut, xml );
} else {
push.apply( results, matcherOut );
}
}
});
}
function matcherFromTokens( tokens ) {
var checkContext, matcher, j,
len = tokens.length,
leadingRelative = Expr.relative[ tokens[0].type ],
implicitRelative = leadingRelative || Expr.relative[" "],
i = leadingRelative ? 1 : 0,
matchContext = addCombinator( function( elem ) {
return elem === checkContext;
}, implicitRelative, true ),
matchAnyContext = addCombinator( function( elem ) {
return indexOf.call( checkContext, elem ) > -1;
}, implicitRelative, true ),
matchers = [ function( elem, context, xml ) {
return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
(checkContext = context).nodeType ?
matchContext( elem, context, xml ) :
matchAnyContext( elem, context, xml ) );
} ];
for ( ; i < len; i++ ) {
if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
} else {
matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
if ( matcher[ expando ] ) {
j = ++i;
for ( ; j < len; j++ ) {
if ( Expr.relative[ tokens[j].type ] ) {
break;
}
}
return setMatcher(
i > 1 && elementMatcher( matchers ),
i > 1 && toSelector(
tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
).replace( rtrim, "$1" ),
matcher,
i < j && matcherFromTokens( tokens.slice( i, j ) ),
j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
j < len && toSelector( tokens )
);
}
matchers.push( matcher );
}
}
return elementMatcher( matchers );
}
function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
var bySet = setMatchers.length > 0,
byElement = elementMatchers.length > 0,
superMatcher = function( seed, context, xml, results, outermost ) {
var elem, j, matcher,
matchedCount = 0,
i = "0",
unmatched = seed && [],
setMatched = [],
contextBackup = outermostContext,
elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
len = elems.length;
if ( outermost ) {
outermostContext = context !== document && context;
}
for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
if ( byElement && elem ) {
j = 0;
while ( (matcher = elementMatchers[j++]) ) {
if ( matcher( elem, context, xml ) ) {
results.push( elem );
break;
}
}
if ( outermost ) {
dirruns = dirrunsUnique;
}
}
if ( bySet ) {
if ( (elem = !matcher && elem) ) {
matchedCount--;
}
if ( seed ) {
unmatched.push( elem );
}
}
}
matchedCount += i;
if ( bySet && i !== matchedCount ) {
j = 0;
while ( (matcher = setMatchers[j++]) ) {
matcher( unmatched, setMatched, context, xml );
}
if ( seed ) {
if ( matchedCount > 0 ) {
while ( i-- ) {
if ( !(unmatched[i] || setMatched[i]) ) {
setMatched[i] = pop.call( results );
}
}
}
setMatched = condense( setMatched );
}
push.apply( results, setMatched );
if ( outermost && !seed && setMatched.length > 0 &&
( matchedCount + setMatchers.length ) > 1 ) {
Sizzle.uniqueSort( results );
}
}
if ( outermost ) {
dirruns = dirrunsUnique;
outermostContext = contextBackup;
}
return unmatched;
};
return bySet ?
markFunction( superMatcher ) :
superMatcher;
}
compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
var i,
setMatchers = [],
elementMatchers = [],
cached = compilerCache[ selector + " " ];
if ( !cached ) {
if ( !match ) {
match = tokenize( selector );
}
i = match.length;
while ( i-- ) {
cached = matcherFromTokens( match[i] );
if ( cached[ expando ] ) {
setMatchers.push( cached );
} else {
elementMatchers.push( cached );
}
}
cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
cached.selector = selector;
}
return cached;
};
/**
* A low-level selection function that works with Sizzle's compiled
* selector functions
* @param {String|Function} selector A selector or a pre-compiled
* selector function built with Sizzle.compile
* @param {Element} context
* @param {Array} [results]
* @param {Array} [seed] A set of elements to match against
*/
select = Sizzle.select = function( selector, context, results, seed ) {
var i, tokens, token, type, find,
compiled = typeof selector === "function" && selector,
match = !seed && tokenize( (selector = compiled.selector || selector) );
results = results || [];
if ( match.length === 1 ) {
tokens = match[0] = match[0].slice( 0 );
if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
support.getById && context.nodeType === 9 && documentIsHTML &&
Expr.relative[ tokens[1].type ] ) {
context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
if ( !context ) {
return results;
} else if ( compiled ) {
context = context.parentNode;
}
selector = selector.slice( tokens.shift().value.length );
}
i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
while ( i-- ) {
token = tokens[i];
if ( Expr.relative[ (type = token.type) ] ) {
break;
}
if ( (find = Expr.find[ type ]) ) {
if ( (seed = find(
token.matches[0].replace( runescape, funescape ),
rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
)) ) {
tokens.splice( i, 1 );
selector = seed.length && toSelector( tokens );
if ( !selector ) {
push.apply( results, seed );
return results;
}
break;
}
}
}
}
( compiled || compile( selector, match ) )(
seed,
context,
!documentIsHTML,
results,
rsibling.test( selector ) && testContext( context.parentNode ) || context
);
return results;
};
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
support.detectDuplicates = !!hasDuplicate;
setDocument();
support.sortDetached = assert(function( div1 ) {
return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});
if ( !assert(function( div ) {
div.innerHTML = "<a href='#'></a>";
return div.firstChild.getAttribute("href") === "#" ;
}) ) {
addHandle( "type|href|height|width", function( elem, name, isXML ) {
if ( !isXML ) {
return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
}
});
}
if ( !support.attributes || !assert(function( div ) {
div.innerHTML = "<input/>";
div.firstChild.setAttribute( "value", "" );
return div.firstChild.getAttribute( "value" ) === "";
}) ) {
addHandle( "value", function( elem, name, isXML ) {
if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
return elem.defaultValue;
}
});
}
if ( !assert(function( div ) {
return div.getAttribute("disabled") == null;
}) ) {
addHandle( booleans, function( elem, name, isXML ) {
var val;
if ( !isXML ) {
return elem[ name ] === true ? name.toLowerCase() :
(val = elem.getAttributeNode( name )) && val.specified ?
val.value :
null;
}
});
}
if ( typeof define === "function" && define.amd ) {
define(function() { return Sizzle; });
} else if ( typeof module !== "undefined" && module.exports ) {
module.exports = Sizzle;
} else {
window.Sizzle = Sizzle;
}
})( window );
;(function(engine) {
var extendElements = Prototype.Selector.extendElements;
function select(selector, scope) {
return extendElements(engine(selector, scope || document));
}
function match(element, selector) {
return engine.matches(selector, [element]).length == 1;
}
Prototype.Selector.engine = engine;
Prototype.Selector.select = select;
Prototype.Selector.match = match;
})(Sizzle);
window.Sizzle = Prototype._original_property;
delete Prototype._original_property;
var Form = {
reset: function(form) {
form = $(form);
form.reset();
return form;
},
serializeElements: function(elements, options) {
if (typeof options != 'object') options = { hash: !!options };
else if (Object.isUndefined(options.hash)) options.hash = true;
var key, value, submitted = false, submit = options.submit, accumulator, initial;
if (options.hash) {
initial = {};
accumulator = function(result, key, value) {
if (key in result) {
if (!Object.isArray(result[key])) result[key] = [result[key]];
result[key] = result[key].concat(value);
} else result[key] = value;
return result;
};
} else {
initial = '';
accumulator = function(result, key, values) {
if (!Object.isArray(values)) {values = [values];}
if (!values.length) {return result;}
var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');
return result + (result ? "&" : "") + values.map(function (value) {
value = value.gsub(/(\r)?\n/, '\r\n');
value = encodeURIComponent(value);
value = value.gsub(/%20/, '+');
return encodedKey + "=" + value;
}).join("&");
};
}
return elements.inject(initial, function(result, element) {
if (!element.disabled && element.name) {
key = element.name; value = $(element).getValue();
if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
submit !== false && (!submit || key == submit) && (submitted = true)))) {
result = accumulator(result, key, value);
}
}
return result;
});
}
};
Form.Methods = {
serialize: function(form, options) {
return Form.serializeElements(Form.getElements(form), options);
},
getElements: function(form) {
var elements = $(form).getElementsByTagName('*');
var element, results = [], serializers = Form.Element.Serializers;
for (var i = 0; element = elements[i]; i++) {
if (serializers[element.tagName.toLowerCase()])
results.push(Element.extend(element));
}
return results;
},
getInputs: function(form, typeName, name) {
form = $(form);
var inputs = form.getElementsByTagName('input');
if (!typeName && !name) return $A(inputs).map(Element.extend);
for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
var input = inputs[i];
if ((typeName && input.type != typeName) || (name && input.name != name))
continue;
matchingInputs.push(Element.extend(input));
}
return matchingInputs;
},
disable: function(form) {
form = $(form);
Form.getElements(form).invoke('disable');
return form;
},
enable: function(form) {
form = $(form);
Form.getElements(form).invoke('enable');
return form;
},
findFirstElement: function(form) {
var elements = $(form).getElements().findAll(function(element) {
return 'hidden' != element.type && !element.disabled;
});
var firstByIndex = elements.findAll(function(element) {
return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
}).sortBy(function(element) { return element.tabIndex }).first();
return firstByIndex ? firstByIndex : elements.find(function(element) {
return /^(?:input|select|textarea)$/i.test(element.tagName);
});
},
focusFirstElement: function(form) {
form = $(form);
var element = form.findFirstElement();
if (element) element.activate();
return form;
},
request: function(form, options) {
form = $(form), options = Object.clone(options || { });
var params = options.parameters, action = form.readAttribute('action') || '';
if (action.blank()) action = window.location.href;
options.parameters = form.serialize(true);
if (params) {
if (Object.isString(params)) params = params.toQueryParams();
Object.extend(options.parameters, params);
}
if (form.hasAttribute('method') && !options.method)
options.method = form.method;
return new Ajax.Request(action, options);
}
};
/*--------------------------------------------------------------------------*/
Form.Element = {
focus: function(element) {
$(element).focus();
return element;
},
select: function(element) {
$(element).select();
return element;
}
};
Form.Element.Methods = {
serialize: function(element) {
element = $(element);
if (!element.disabled && element.name) {
var value = element.getValue();
if (value != undefined) {
var pair = { };
pair[element.name] = value;
return Object.toQueryString(pair);
}
}
return '';
},
getValue: function(element) {
element = $(element);
var method = element.tagName.toLowerCase();
return Form.Element.Serializers[method](element);
},
setValue: function(element, value) {
element = $(element);
var method = element.tagName.toLowerCase();
Form.Element.Serializers[method](element, value);
return element;
},
clear: function(element) {
$(element).value = '';
return element;
},
present: function(element) {
return $(element).value != '';
},
activate: function(element) {
element = $(element);
try {
element.focus();
if (element.select && (element.tagName.toLowerCase() != 'input' ||
!(/^(?:button|reset|submit)$/i.test(element.type))))
element.select();
} catch (e) { }
return element;
},
disable: function(element) {
element = $(element);
element.disabled = true;
return element;
},
enable: function(element) {
element = $(element);
element.disabled = false;
return element;
}
};
/*--------------------------------------------------------------------------*/
var Field = Form.Element;
var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/
Form.Element.Serializers = (function() {
function input(element, value) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
return inputSelector(element, value);
default:
return valueSelector(element, value);
}
}
function inputSelector(element, value) {
if (Object.isUndefined(value))
return element.checked ? element.value : null;
else element.checked = !!value;
}
function valueSelector(element, value) {
if (Object.isUndefined(value)) return element.value;
else element.value = value;
}
function select(element, value) {
if (Object.isUndefined(value))
return (element.type === 'select-one' ? selectOne : selectMany)(element);
var opt, currentValue, single = !Object.isArray(value);
for (var i = 0, length = element.length; i < length; i++) {
opt = element.options[i];
currentValue = this.optionValue(opt);
if (single) {
if (currentValue == value) {
opt.selected = true;
return;
}
}
else opt.selected = value.include(currentValue);
}
}
function selectOne(element) {
var index = element.selectedIndex;
return index >= 0 ? optionValue(element.options[index]) : null;
}
function selectMany(element) {
var values, length = element.length;
if (!length) return null;
for (var i = 0, values = []; i < length; i++) {
var opt = element.options[i];
if (opt.selected) values.push(optionValue(opt));
}
return values;
}
function optionValue(opt) {
return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
}
return {
input: input,
inputSelector: inputSelector,
textarea: valueSelector,
select: select,
selectOne: selectOne,
selectMany: selectMany,
optionValue: optionValue,
button: valueSelector
};
})();
/*--------------------------------------------------------------------------*/
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
initialize: function($super, element, frequency, callback) {
$super(callback, frequency);
this.element = $(element);
this.lastValue = this.getValue();
},
execute: function() {
var value = this.getValue();
if (Object.isString(this.lastValue) && Object.isString(value) ?
this.lastValue != value : String(this.lastValue) != String(value)) {
this.callback(this.element, value);
this.lastValue = value;
}
}
});
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.Observer = Class.create(Abstract.TimedObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
/*--------------------------------------------------------------------------*/
Abstract.EventObserver = Class.create({
initialize: function(element, callback) {
this.element = $(element);
this.callback = callback;
this.lastValue = this.getValue();
if (this.element.tagName.toLowerCase() == 'form')
this.registerFormCallbacks();
else
this.registerCallback(this.element);
},
onElementEvent: function() {
var value = this.getValue();
if (this.lastValue != value) {
this.callback(this.element, value);
this.lastValue = value;
}
},
registerFormCallbacks: function() {
Form.getElements(this.element).each(this.registerCallback, this);
},
registerCallback: function(element) {
if (element.type) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
Event.observe(element, 'click', this.onElementEvent.bind(this));
break;
default:
Event.observe(element, 'change', this.onElementEvent.bind(this));
break;
}
}
}
});
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.Element.getValue(this.element);
}
});
Form.EventObserver = Class.create(Abstract.EventObserver, {
getValue: function() {
return Form.serialize(this.element);
}
});
(function(GLOBAL) {
var DIV = document.createElement('div');
var docEl = document.documentElement;
var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
&& 'onmouseleave' in docEl;
var Event = {
KEY_BACKSPACE: 8,
KEY_TAB: 9,
KEY_RETURN: 13,
KEY_ESC: 27,
KEY_LEFT: 37,
KEY_UP: 38,
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_DELETE: 46,
KEY_HOME: 36,
KEY_END: 35,
KEY_PAGEUP: 33,
KEY_PAGEDOWN: 34,
KEY_INSERT: 45
};
var isIELegacyEvent = function(event) { return false; };
if (window.attachEvent) {
if (window.addEventListener) {
isIELegacyEvent = function(event) {
return !(event instanceof window.Event);
};
} else {
isIELegacyEvent = function(event) { return true; };
}
}
var _isButton;
function _isButtonForDOMEvents(event, code) {
return event.which ? (event.which === code + 1) : (event.button === code);
}
var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
function _isButtonForLegacyEvents(event, code) {
return event.button === legacyButtonMap[code];
}
function _isButtonForWebKit(event, code) {
switch (code) {
case 0: return event.which == 1 && !event.metaKey;
case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
case 2: return event.which == 3;
default: return false;
}
}
if (window.attachEvent) {
if (!window.addEventListener) {
_isButton = _isButtonForLegacyEvents;
} else {
_isButton = function(event, code) {
return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
_isButtonForDOMEvents(event, code);
}
}
} else if (Prototype.Browser.WebKit) {
_isButton = _isButtonForWebKit;
} else {
_isButton = _isButtonForDOMEvents;
}
function isLeftClick(event) { return _isButton(event, 0) }
function isMiddleClick(event) { return _isButton(event, 1) }
function isRightClick(event) { return _isButton(event, 2) }
function element(event) {
return Element.extend(_element(event));
}
function _element(event) {
event = Event.extend(event);
var node = event.target, type = event.type,
currentTarget = event.currentTarget;
if (currentTarget && currentTarget.tagName) {
if (type === 'load' || type === 'error' ||
(type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
&& currentTarget.type === 'radio'))
node = currentTarget;
}
return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;
}
function findElement(event, expression) {
var element = _element(event), selector = Prototype.Selector;
if (!expression) return Element.extend(element);
while (element) {
if (Object.isElement(element) && selector.match(element, expression))
return Element.extend(element);
element = element.parentNode;
}
}
function pointer(event) {
return { x: pointerX(event), y: pointerY(event) };
}
function pointerX(event) {
var docElement = document.documentElement,
body = document.body || { scrollLeft: 0 };
return event.pageX || (event.clientX +
(docElement.scrollLeft || body.scrollLeft) -
(docElement.clientLeft || 0));
}
function pointerY(event) {
var docElement = document.documentElement,
body = document.body || { scrollTop: 0 };
return event.pageY || (event.clientY +
(docElement.scrollTop || body.scrollTop) -
(docElement.clientTop || 0));
}
function stop(event) {
Event.extend(event);
event.preventDefault();
event.stopPropagation();
event.stopped = true;
}
Event.Methods = {
isLeftClick: isLeftClick,
isMiddleClick: isMiddleClick,
isRightClick: isRightClick,
element: element,
findElement: findElement,
pointer: pointer,
pointerX: pointerX,
pointerY: pointerY,
stop: stop
};
var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
m[name] = Event.Methods[name].methodize();
return m;
});
if (window.attachEvent) {
function _relatedTarget(event) {
var element;
switch (event.type) {
case 'mouseover':
case 'mouseenter':
element = event.fromElement;
break;
case 'mouseout':
case 'mouseleave':
element = event.toElement;
break;
default:
return null;
}
return Element.extend(element);
}
var additionalMethods = {
stopPropagation: function() { this.cancelBubble = true },
preventDefault: function() { this.returnValue = false },
inspect: function() { return '[object Event]' }
};
Event.extend = function(event, element) {
if (!event) return false;
if (!isIELegacyEvent(event)) return event;
if (event._extendedByPrototype) return event;
event._extendedByPrototype = Prototype.emptyFunction;
var pointer = Event.pointer(event);
Object.extend(event, {
target: event.srcElement || element,
relatedTarget: _relatedTarget(event),
pageX: pointer.x,
pageY: pointer.y
});
Object.extend(event, methods);
Object.extend(event, additionalMethods);
return event;
};
} else {
Event.extend = Prototype.K;
}
if (window.addEventListener) {
Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
Object.extend(Event.prototype, methods);
}
var EVENT_TRANSLATIONS = {
mouseenter: 'mouseover',
mouseleave: 'mouseout'
};
function getDOMEventName(eventName) {
return EVENT_TRANSLATIONS[eventName] || eventName;
}
if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)
getDOMEventName = Prototype.K;
function getUniqueElementID(element) {
if (element === window) return 0;
if (typeof element._prototypeUID === 'undefined')
element._prototypeUID = Element.Storage.UID++;
return element._prototypeUID;
}
function getUniqueElementID_IE(element) {
if (element === window) return 0;
if (element == document) return 1;
return element.uniqueID;
}
if ('uniqueID' in DIV)
getUniqueElementID = getUniqueElementID_IE;
function isCustomEvent(eventName) {
return eventName.include(':');
}
Event._isCustomEvent = isCustomEvent;
function getRegistryForElement(element, uid) {
var CACHE = GLOBAL.Event.cache;
if (Object.isUndefined(uid))
uid = getUniqueElementID(element);
if (!CACHE[uid]) CACHE[uid] = { element: element };
return CACHE[uid];
}
function destroyRegistryForElement(element, uid) {
if (Object.isUndefined(uid))
uid = getUniqueElementID(element);
delete GLOBAL.Event.cache[uid];
}
function register(element, eventName, handler) {
var registry = getRegistryForElement(element);
if (!registry[eventName]) registry[eventName] = [];
var entries = registry[eventName];
var i = entries.length;
while (i--)
if (entries[i].handler === handler) return null;
var uid = getUniqueElementID(element);
var responder = GLOBAL.Event._createResponder(uid, eventName, handler);
var entry = {
responder: responder,
handler: handler
};
entries.push(entry);
return entry;
}
function unregister(element, eventName, handler) {
var registry = getRegistryForElement(element);
var entries = registry[eventName];
if (!entries) return;
var i = entries.length, entry;
while (i--) {
if (entries[i].handler === handler) {
entry = entries[i];
break;
}
}
if (!entry) return;
var index = entries.indexOf(entry);
entries.splice(index, 1);
return entry;
}
function observe(element, eventName, handler) {
element = $(element);
var entry = register(element, eventName, handler);
if (entry === null) return element;
var responder = entry.responder;
if (isCustomEvent(eventName))
observeCustomEvent(element, eventName, responder);
else
observeStandardEvent(element, eventName, responder);
return element;
}
function observeStandardEvent(element, eventName, responder) {
var actualEventName = getDOMEventName(eventName);
if (element.addEventListener) {
element.addEventListener(actualEventName, responder, false);
} else {
element.attachEvent('on' + actualEventName, responder);
}
}
function observeCustomEvent(element, eventName, responder) {
if (element.addEventListener) {
element.addEventListener('dataavailable', responder, false);
} else {
element.attachEvent('ondataavailable', responder);
element.attachEvent('onlosecapture', responder);
}
}
function stopObserving(element, eventName, handler) {
element = $(element);
var handlerGiven = !Object.isUndefined(handler),
eventNameGiven = !Object.isUndefined(eventName);
if (!eventNameGiven && !handlerGiven) {
stopObservingElement(element);
return element;
}
if (!handlerGiven) {
stopObservingEventName(element, eventName);
return element;
}
var entry = unregister(element, eventName, handler);
if (!entry) return element;
removeEvent(element, eventName, entry.responder);
return element;
}
function stopObservingStandardEvent(element, eventName, responder) {
var actualEventName = getDOMEventName(eventName);
if (element.removeEventListener) {
element.removeEventListener(actualEventName, responder, false);
} else {
element.detachEvent('on' + actualEventName, responder);
}
}
function stopObservingCustomEvent(element, eventName, responder) {
if (element.removeEventListener) {
element.removeEventListener('dataavailable', responder, false);
} else {
element.detachEvent('ondataavailable', responder);
element.detachEvent('onlosecapture', responder);
}
}
function stopObservingElement(element) {
var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];
if (!registry) return;
destroyRegistryForElement(element, uid);
var entries, i;
for (var eventName in registry) {
if (eventName === 'element') continue;
entries = registry[eventName];
i = entries.length;
while (i--)
removeEvent(element, eventName, entries[i].responder);
}
}
function stopObservingEventName(element, eventName) {
var registry = getRegistryForElement(element);
var entries = registry[eventName];
if (!entries) return;
delete registry[eventName];
var i = entries.length;
while (i--)
removeEvent(element, eventName, entries[i].responder);
}
function removeEvent(element, eventName, handler) {
if (isCustomEvent(eventName))
stopObservingCustomEvent(element, eventName, handler);
else
stopObservingStandardEvent(element, eventName, handler);
}
function getFireTarget(element) {
if (element !== document) return element;
if (document.createEvent && !element.dispatchEvent)
return document.documentElement;
return element;
}
function fire(element, eventName, memo, bubble) {
element = getFireTarget($(element));
if (Object.isUndefined(bubble)) bubble = true;
memo = memo || {};
var event = fireEvent(element, eventName, memo, bubble);
return Event.extend(event);
}
function fireEvent_DOM(element, eventName, memo, bubble) {
var event = document.createEvent('HTMLEvents');
event.initEvent('dataavailable', bubble, true);
event.eventName = eventName;
event.memo = memo;
element.dispatchEvent(event);
return event;
}
function fireEvent_IE(element, eventName, memo, bubble) {
var event = document.createEventObject();
event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
event.eventName = eventName;
event.memo = memo;
element.fireEvent(event.eventType, event);
return event;
}
var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;
Event.Handler = Class.create({
initialize: function(element, eventName, selector, callback) {
this.element = $(element);
this.eventName = eventName;
this.selector = selector;
this.callback = callback;
this.handler = this.handleEvent.bind(this);
},
start: function() {
Event.observe(this.element, this.eventName, this.handler);
return this;
},
stop: function() {
Event.stopObserving(this.element, this.eventName, this.handler);
return this;
},
handleEvent: function(event) {
var element = Event.findElement(event, this.selector);
if (element) this.callback.call(this.element, event, element);
}
});
function on(element, eventName, selector, callback) {
element = $(element);
if (Object.isFunction(selector) && Object.isUndefined(callback)) {
callback = selector, selector = null;
}
return new Event.Handler(element, eventName, selector, callback).start();
}
Object.extend(Event, Event.Methods);
Object.extend(Event, {
fire: fire,
observe: observe,
stopObserving: stopObserving,
on: on
});
Element.addMethods({
fire: fire,
observe: observe,
stopObserving: stopObserving,
on: on
});
Object.extend(document, {
fire: fire.methodize(),
observe: observe.methodize(),
stopObserving: stopObserving.methodize(),
on: on.methodize(),
loaded: false
});
if (GLOBAL.Event) Object.extend(window.Event, Event);
else GLOBAL.Event = Event;
GLOBAL.Event.cache = {};
function destroyCache_IE() {
GLOBAL.Event.cache = null;
}
if (window.attachEvent)
window.attachEvent('onunload', destroyCache_IE);
DIV = null;
docEl = null;
})(this);
(function(GLOBAL) {
/* Code for creating leak-free event responders is based on work by
John-David Dalton. */
var docEl = document.documentElement;
var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
&& 'onmouseleave' in docEl;
function isSimulatedMouseEnterLeaveEvent(eventName) {
return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
(eventName === 'mouseenter' || eventName === 'mouseleave');
}
function createResponder(uid, eventName, handler) {
if (Event._isCustomEvent(eventName))
return createResponderForCustomEvent(uid, eventName, handler);
if (isSimulatedMouseEnterLeaveEvent(eventName))
return createMouseEnterLeaveResponder(uid, eventName, handler);
return function(event) {
if (!Event.cache) return;
var element = Event.cache[uid].element;
Event.extend(event, element);
handler.call(element, event);
};
}
function createResponderForCustomEvent(uid, eventName, handler) {
return function(event) {
var element = Event.cache[uid].element;
if (Object.isUndefined(event.eventName))
return false;
if (event.eventName !== eventName)
return false;
Event.extend(event, element);
handler.call(element, event);
};
}
function createMouseEnterLeaveResponder(uid, eventName, handler) {
return function(event) {
var element = Event.cache[uid].element;
Event.extend(event, element);
var parent = event.relatedTarget;
while (parent && parent !== element) {
try { parent = parent.parentNode; }
catch(e) { parent = element; }
}
if (parent === element) return;
handler.call(element, event);
}
}
GLOBAL.Event._createResponder = createResponder;
docEl = null;
})(this);
(function(GLOBAL) {
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */
var TIMER;
function fireContentLoadedEvent() {
if (document.loaded) return;
if (TIMER) window.clearTimeout(TIMER);
document.loaded = true;
document.fire('dom:loaded');
}
function checkReadyState() {
if (document.readyState === 'complete') {
document.detachEvent('onreadystatechange', checkReadyState);
fireContentLoadedEvent();
}
}
function pollDoScroll() {
try {
document.documentElement.doScroll('left');
} catch (e) {
TIMER = pollDoScroll.defer();
return;
}
fireContentLoadedEvent();
}
if (document.readyState === 'complete') {
fireContentLoadedEvent();
return;
}
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
} else {
document.attachEvent('onreadystatechange', checkReadyState);
if (window == top) TIMER = pollDoScroll.defer();
}
Event.observe(window, 'load', fireContentLoadedEvent);
})(this);
Element.addMethods();
/*------------------------------- DEPRECATED -------------------------------*/
Hash.toQueryString = Object.toQueryString;
var Toggle = { display: Element.toggle };
Element.Methods.childOf = Element.Methods.descendantOf;
var Insertion = {
Before: function(element, content) {
return Element.insert(element, {before:content});
},
Top: function(element, content) {
return Element.insert(element, {top:content});
},
Bottom: function(element, content) {
return Element.insert(element, {bottom:content});
},
After: function(element, content) {
return Element.insert(element, {after:content});
}
};
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
var Position = {
includeScrollOffsets: false,
prepare: function() {
this.deltaX = window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
this.deltaY = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
},
within: function(element, x, y) {
if (this.includeScrollOffsets)
return this.withinIncludingScrolloffsets(element, x, y);
this.xcomp = x;
this.ycomp = y;
this.offset = Element.cumulativeOffset(element);
return (y >= this.offset[1] &&
y < this.offset[1] + element.offsetHeight &&
x >= this.offset[0] &&
x < this.offset[0] + element.offsetWidth);
},
withinIncludingScrolloffsets: function(element, x, y) {
var offsetcache = Element.cumulativeScrollOffset(element);
this.xcomp = x + offsetcache[0] - this.deltaX;
this.ycomp = y + offsetcache[1] - this.deltaY;
this.offset = Element.cumulativeOffset(element);
return (this.ycomp >= this.offset[1] &&
this.ycomp < this.offset[1] + element.offsetHeight &&
this.xcomp >= this.offset[0] &&
this.xcomp < this.offset[0] + element.offsetWidth);
},
overlap: function(mode, element) {
if (!mode) return 0;
if (mode == 'vertical')
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
element.offsetHeight;
if (mode == 'horizontal')
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
element.offsetWidth;
},
cumulativeOffset: Element.Methods.cumulativeOffset,
positionedOffset: Element.Methods.positionedOffset,
absolutize: function(element) {
Position.prepare();
return Element.absolutize(element);
},
relativize: function(element) {
Position.prepare();
return Element.relativize(element);
},
realOffset: Element.Methods.cumulativeScrollOffset,
offsetParent: Element.Methods.getOffsetParent,
page: Element.Methods.viewportOffset,
clone: function(source, target, options) {
options = options || { };
return Element.clonePosition(target, source, options);
}
};
/*--------------------------------------------------------------------------*/
if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
function iter(name) {
return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
}
instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
function(element, className) {
className = className.toString().strip();
var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
} : function(element, className) {
className = className.toString().strip();
var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
if (!classNames && !className) return elements;
var nodes = $(element).getElementsByTagName('*');
className = ' ' + className + ' ';
for (var i = 0, child, cn; child = nodes[i]; i++) {
if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
(classNames && classNames.all(function(name) {
return !name.toString().blank() && cn.include(' ' + name + ' ');
}))))
elements.push(Element.extend(child));
}
return elements;
};
return function(className, parentElement) {
return $(parentElement || document.body).getElementsByClassName(className);
};
}(Element.Methods);
/*--------------------------------------------------------------------------*/
Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
initialize: function(element) {
this.element = $(element);
},
_each: function(iterator, context) {
this.element.className.split(/\s+/).select(function(name) {
return name.length > 0;
})._each(iterator, context);
},
set: function(className) {
this.element.className = className;
},
add: function(classNameToAdd) {
if (this.include(classNameToAdd)) return;
this.set($A(this).concat(classNameToAdd).join(' '));
},
remove: function(classNameToRemove) {
if (!this.include(classNameToRemove)) return;
this.set($A(this).without(classNameToRemove).join(' '));
},
toString: function() {
return $A(this).join(' ');
}
};
Object.extend(Element.ClassNames.prototype, Enumerable);
/*--------------------------------------------------------------------------*/
(function() {
window.Selector = Class.create({
initialize: function(expression) {
this.expression = expression.strip();
},
findElements: function(rootElement) {
return Prototype.Selector.select(this.expression, rootElement);
},
match: function(element) {
return Prototype.Selector.match(element, this.expression);
},
toString: function() {
return this.expression;
},
inspect: function() {
return "#<Selector: " + this.expression + ">";
}
});
Object.extend(Selector, {
matchElements: function(elements, expression) {
var match = Prototype.Selector.match,
results = [];
for (var i = 0, length = elements.length; i < length; i++) {
var element = elements[i];
if (match(element, expression)) {
results.push(Element.extend(element));
}
}
return results;
},
findElement: function(elements, expression, index) {
index = index || 0;
var matchIndex = 0, element;
for (var i = 0, length = elements.length; i < length; i++) {
element = elements[i];
if (Prototype.Selector.match(element, expression) && index === matchIndex++) {
return Element.extend(element);
}
}
},
findChildElements: function(element, expressions) {
var selector = expressions.toArray().join(', ');
return Prototype.Selector.select(selector, element || document);
}
});
})();
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/public/dist/jsconcat.js","/public/dist")
},{"_process":5,"buffer":1}],7:[function(require,module,exports){
(function (process,global,Buffer,__argument0,__argument1,__argument2,__argument3,__filename,__dirname){
require('jsconcat');
alert(JSON.stringify);
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],"/templates/js/foo.js","/templates/js")
},{"_process":5,"buffer":1,"jsconcat":6}]},{},[7])
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL25vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvaXMtYXJyYXkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwicHVibGljL2Rpc3QvanNjb25jYXQuanMiLCJ0ZW1wbGF0ZXMvanMvZm9vLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNweUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3RGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3QxT0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzLWFycmF5JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbnZhciBrTWF4TGVuZ3RoID0gMHgzZmZmZmZmZlxudmFyIHJvb3RQYXJlbnQgPSB7fVxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqIC0gSW1wbGVtZW50YXRpb24gbXVzdCBzdXBwb3J0IGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLlxuICogICBGaXJlZm94IDQtMjkgbGFja2VkIHN1cHBvcnQsIGZpeGVkIGluIEZpcmVmb3ggMzArLlxuICogICBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOC5cbiAqXG4gKiAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgIGluY29ycmVjdCBsZW5ndGggaW4gc29tZSBzaXR1YXRpb25zLlxuICpcbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGAgdG8gYGZhbHNlYCBzbyB0aGV5IHdpbGxcbiAqIGdldCB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyBzbG93ZXIgYnV0IHdpbGwgd29yayBjb3JyZWN0bHkuXG4gKi9cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gKGZ1bmN0aW9uICgpIHtcbiAgdHJ5IHtcbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDApXG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KGJ1ZilcbiAgICBhcnIuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfVxuICAgIHJldHVybiA0MiA9PT0gYXJyLmZvbygpICYmIC8vIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkXG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgJiYgLy8gY2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gICAgICAgIG5ldyBVaW50OEFycmF5KDEpLnN1YmFycmF5KDEsIDEpLmJ5dGVMZW5ndGggPT09IDAgLy8gaWUxMCBoYXMgYnJva2VuIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59KSgpXG5cbi8qKlxuICogQ2xhc3M6IEJ1ZmZlclxuICogPT09PT09PT09PT09PVxuICpcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgYXJlIGF1Z21lbnRlZFxuICogd2l0aCBmdW5jdGlvbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgQVBJIGZ1bmN0aW9ucy4gV2UgdXNlXG4gKiBgVWludDhBcnJheWAgc28gdGhhdCBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdCByZXR1cm5zXG4gKiBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBCeSBhdWdtZW50aW5nIHRoZSBpbnN0YW5jZXMsIHdlIGNhbiBhdm9pZCBtb2RpZnlpbmcgdGhlIGBVaW50OEFycmF5YFxuICogcHJvdG90eXBlLlxuICovXG5mdW5jdGlvbiBCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpXG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybylcblxuICB2YXIgdHlwZSA9IHR5cGVvZiBzdWJqZWN0XG5cbiAgLy8gRmluZCB0aGUgbGVuZ3RoXG4gIHZhciBsZW5ndGhcbiAgaWYgKHR5cGUgPT09ICdudW1iZXInKVxuICAgIGxlbmd0aCA9IHN1YmplY3QgPiAwID8gc3ViamVjdCA+Pj4gMCA6IDBcbiAgZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBsZW5ndGggPSBCdWZmZXIuYnl0ZUxlbmd0aChzdWJqZWN0LCBlbmNvZGluZylcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0JyAmJiBzdWJqZWN0ICE9PSBudWxsKSB7IC8vIGFzc3VtZSBvYmplY3QgaXMgYXJyYXktbGlrZVxuICAgIGlmIChzdWJqZWN0LnR5cGUgPT09ICdCdWZmZXInICYmIGlzQXJyYXkoc3ViamVjdC5kYXRhKSlcbiAgICAgIHN1YmplY3QgPSBzdWJqZWN0LmRhdGFcbiAgICBsZW5ndGggPSArc3ViamVjdC5sZW5ndGggPiAwID8gTWF0aC5mbG9vcigrc3ViamVjdC5sZW5ndGgpIDogMFxuICB9IGVsc2VcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtdXN0IHN0YXJ0IHdpdGggbnVtYmVyLCBidWZmZXIsIGFycmF5IG9yIHN0cmluZycpXG5cbiAgaWYgKGxlbmd0aCA+IGtNYXhMZW5ndGgpXG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAnc2l6ZTogMHgnICsga01heExlbmd0aC50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcblxuICB2YXIgYnVmXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFByZWZlcnJlZDogUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICBidWYgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkobGVuZ3RoKSlcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIFRISVMgaW5zdGFuY2Ugb2YgQnVmZmVyIChjcmVhdGVkIGJ5IGBuZXdgKVxuICAgIGJ1ZiA9IHRoaXNcbiAgICBidWYubGVuZ3RoID0gbGVuZ3RoXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWVcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiB0eXBlb2Ygc3ViamVjdC5ieXRlTGVuZ3RoID09PSAnbnVtYmVyJykge1xuICAgIC8vIFNwZWVkIG9wdGltaXphdGlvbiAtLSB1c2Ugc2V0IGlmIHdlJ3JlIGNvcHlpbmcgZnJvbSBhIHR5cGVkIGFycmF5XG4gICAgYnVmLl9zZXQoc3ViamVjdClcbiAgfSBlbHNlIGlmIChpc0FycmF5aXNoKHN1YmplY3QpKSB7XG4gICAgLy8gVHJlYXQgYXJyYXktaXNoIG9iamVjdHMgYXMgYSBieXRlIGFycmF5XG4gICAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihzdWJqZWN0KSkge1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKVxuICAgICAgICBidWZbaV0gPSBzdWJqZWN0LnJlYWRVSW50OChpKVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspXG4gICAgICAgIGJ1ZltpXSA9ICgoc3ViamVjdFtpXSAlIDI1NikgKyAyNTYpICUgMjU2XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgYnVmLndyaXRlKHN1YmplY3QsIDAsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInICYmICFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiAhbm9aZXJvKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBidWZbaV0gPSAwXG4gICAgfVxuICB9XG5cbiAgaWYgKGxlbmd0aCA+IDAgJiYgbGVuZ3RoIDw9IEJ1ZmZlci5wb29sU2l6ZSlcbiAgICBidWYucGFyZW50ID0gcm9vdFBhcmVudFxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlcihzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTbG93QnVmZmVyKSlcbiAgICByZXR1cm4gbmV3IFNsb3dCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybylcblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKVxuICBkZWxldGUgYnVmLnBhcmVudFxuICByZXR1cm4gYnVmXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5jb21wYXJlID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYSkgfHwgIUJ1ZmZlci5pc0J1ZmZlcihiKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudHMgbXVzdCBiZSBCdWZmZXJzJylcblxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IE1hdGgubWluKHgsIHkpOyBpIDwgbGVuICYmIGFbaV0gPT09IGJbaV07IGkrKykge31cbiAgaWYgKGkgIT09IGxlbikge1xuICAgIHggPSBhW2ldXG4gICAgeSA9IGJbaV1cbiAgfVxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICdyYXcnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIHRvdGFsTGVuZ3RoKSB7XG4gIGlmICghaXNBcnJheShsaXN0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdFssIGxlbmd0aF0pJylcblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcigwKVxuICB9IGVsc2UgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGxpc3RbMF1cbiAgfVxuXG4gIHZhciBpXG4gIGlmICh0b3RhbExlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdG90YWxMZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRvdGFsTGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIodG90YWxMZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldXG4gICAgaXRlbS5jb3B5KGJ1ZiwgcG9zKVxuICAgIHBvcyArPSBpdGVtLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZcbn1cblxuQnVmZmVyLmJ5dGVMZW5ndGggPSBmdW5jdGlvbiAoc3RyLCBlbmNvZGluZykge1xuICB2YXIgcmV0XG4gIHN0ciA9IHN0ciArICcnXG4gIHN3aXRjaCAoZW5jb2RpbmcgfHwgJ3V0ZjgnKSB7XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAncmF3JzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGggKiAyXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2hleCc6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoID4+PiAxXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IHV0ZjhUb0J5dGVzKHN0cikubGVuZ3RoXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXQgPSBiYXNlNjRUb0J5dGVzKHN0cikubGVuZ3RoXG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG4vLyBwcmUtc2V0IGZvciB2YWx1ZXMgdGhhdCBtYXkgZXhpc3QgaW4gdGhlIGZ1dHVyZVxuQnVmZmVyLnByb3RvdHlwZS5sZW5ndGggPSB1bmRlZmluZWRcbkJ1ZmZlci5wcm90b3R5cGUucGFyZW50ID0gdW5kZWZpbmVkXG5cbi8vIHRvU3RyaW5nKGVuY29kaW5nLCBzdGFydD0wLCBlbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICBzdGFydCA9IHN0YXJ0ID4+PiAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA9PT0gSW5maW5pdHkgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG4gIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmIChlbmQgPD0gc3RhcnQpIHJldHVybiAnJ1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGJpbmFyeVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdXRmMTZsZVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSlcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYikgPT09IDBcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkubWF0Y2goLy57Mn0vZykuam9pbignICcpXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KVxuICAgICAgc3RyICs9ICcgLi4uICdcbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKVxufVxuXG4vLyBgZ2V0YCB3aWxsIGJlIHJlbW92ZWQgaW4gTm9kZSAwLjEzK1xuQnVmZmVyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAob2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuZ2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy5yZWFkVUludDgob2Zmc2V0KVxufVxuXG4vLyBgc2V0YCB3aWxsIGJlIHJlbW92ZWQgaW4gTm9kZSAwLjEzK1xuQnVmZmVyLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAodiwgb2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuc2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy53cml0ZVVJbnQ4KHYsIG9mZnNldClcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICAvLyBtdXN0IGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGRpZ2l0c1xuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAoc3RyTGVuICUgMiAhPT0gMCkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgYnl0ZSA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAoaXNOYU4oYnl0ZSkpIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSBieXRlXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiBhc2NpaVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IGJsaXRCdWZmZXIoYXNjaWlUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gYmluYXJ5V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBibGl0QnVmZmVyKHV0ZjE2bGVUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgsIDIpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBTdXBwb3J0IGJvdGggKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKVxuICAvLyBhbmQgdGhlIGxlZ2FjeSAoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0LCBsZW5ndGgpXG4gIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgaWYgKCFpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICB9IGVsc2UgeyAgLy8gbGVnYWN5XG4gICAgdmFyIHN3YXAgPSBlbmNvZGluZ1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgb2Zmc2V0ID0gbGVuZ3RoXG4gICAgbGVuZ3RoID0gc3dhcFxuICB9XG5cbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuXG4gIGlmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDAgfHwgb2Zmc2V0ID4gdGhpcy5sZW5ndGgpXG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJyk7XG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG5cbiAgdmFyIHJldFxuICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgICByZXQgPSBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICByZXQgPSBiaW5hcnlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IHV0ZjE2bGVXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXMgPSAnJ1xuICB2YXIgdG1wID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgaWYgKGJ1ZltpXSA8PSAweDdGKSB7XG4gICAgICByZXMgKz0gZGVjb2RlVXRmOENoYXIodG1wKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICAgICAgdG1wID0gJydcbiAgICB9IGVsc2Uge1xuICAgICAgdG1wICs9ICclJyArIGJ1ZltpXS50b1N0cmluZygxNilcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzICsgZGVjb2RlVXRmOENoYXIodG1wKVxufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBiaW5hcnlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSArIDFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW47XG4gICAgaWYgKHN0YXJ0IDwgMClcbiAgICAgIHN0YXJ0ID0gMFxuICB9IGVsc2UgaWYgKHN0YXJ0ID4gbGVuKSB7XG4gICAgc3RhcnQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCAwKSB7XG4gICAgZW5kICs9IGxlblxuICAgIGlmIChlbmQgPCAwKVxuICAgICAgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KVxuICAgIGVuZCA9IHN0YXJ0XG5cbiAgdmFyIG5ld0J1ZlxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBuZXdCdWYgPSBCdWZmZXIuX2F1Z21lbnQodGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSlcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIG5ld0J1ZiA9IG5ldyBCdWZmZXIoc2xpY2VMZW4sIHVuZGVmaW5lZCwgdHJ1ZSlcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNsaWNlTGVuOyBpKyspIHtcbiAgICAgIG5ld0J1ZltpXSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfVxuXG4gIGlmIChuZXdCdWYubGVuZ3RoKVxuICAgIG5ld0J1Zi5wYXJlbnQgPSB0aGlzLnBhcmVudCB8fCB0aGlzXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMClcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb2Zmc2V0IGlzIG5vdCB1aW50JylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGxlbmd0aClcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXVxuICB2YXIgbXVsID0gMVxuICB3aGlsZSAoYnl0ZUxlbmd0aCA+IDAgJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bDtcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDgpIHwgdGhpc1tvZmZzZXQgKyAxXVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKCh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSkgK1xuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10gKiAweDEwMDAwMDApXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdICogMHgxMDAwMDAwKSArXG4gICAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAgIHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSlcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKVxuICAgIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludEJFID0gZnVuY3Rpb24gKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGhcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1pXSAqIG11bFxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKVxuICAgIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIGlmICghKHRoaXNbb2Zmc2V0XSAmIDB4ODApKVxuICAgIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydClcbiAgICBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDI0KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgNTIsIDgpXG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignYnVmZmVyIG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKVxuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludExFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSwgMClcblxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAodmFsdWUgLyBtdWwpID4+PiAwICYgMHhGRlxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgPj4+IDAgJiAweEZGXG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4ZmYsIDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuZnVuY3Rpb24gb2JqZWN0V3JpdGVVSW50MTYgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuKSB7XG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgMik7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgJiAoMHhmZiA8PCAoOCAqIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpKSkpID4+PlxuICAgICAgKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkgKiA4XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSB2YWx1ZVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbmZ1bmN0aW9uIG9iamVjdFdyaXRlVUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbikge1xuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCA0KTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSA+Pj4gKGxpdHRsZUVuZGlhbiA/IGkgOiAzIC0gaSkgKiA4KSAmIDB4ZmZcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gdmFsdWVcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0ludCh0aGlzLFxuICAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgIG9mZnNldCxcbiAgICAgICAgICAgICBieXRlTGVuZ3RoLFxuICAgICAgICAgICAgIE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSkgLSAxLFxuICAgICAgICAgICAgIC1NYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpKVxuICB9XG5cbiAgdmFyIGkgPSAwXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpXG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSW50KHRoaXMsXG4gICAgICAgICAgICAgdmFsdWUsXG4gICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgIGJ5dGVMZW5ndGgsXG4gICAgICAgICAgICAgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKSAtIDEsXG4gICAgICAgICAgICAgLU1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoIC0gMSkpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSlcbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9IHZhbHVlXG4gIH0gZWxzZSBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgfSBlbHNlIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KVxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSB2YWx1ZVxuICB9IGVsc2Ugb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG4gIGlmIChvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuZnVuY3Rpb24gd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpXG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG4gIHJldHVybiBvZmZzZXQgKyA4XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiAodGFyZ2V0LCB0YXJnZXRfc3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHNvdXJjZSA9IHRoaXNcblxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0X3N0YXJ0ID49IHRhcmdldC5sZW5ndGgpIHRhcmdldF9zdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRfc3RhcnQpIHRhcmdldF9zdGFydCA9IDBcbiAgaWYgKGVuZCA+IDAgJiYgZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm4gMFxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCBzb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldF9zdGFydCA8IDApXG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHNvdXJjZS5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKVxuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0X3N0YXJ0IDwgZW5kIC0gc3RhcnQpXG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldF9zdGFydCArIHN0YXJ0XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG5cbiAgaWYgKGxlbiA8IDEwMDAgfHwgIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRfc3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRhcmdldC5fc2V0KHRoaXMuc3ViYXJyYXkoc3RhcnQsIHN0YXJ0ICsgbGVuKSwgdGFyZ2V0X3N0YXJ0KVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBmaWxsKHZhbHVlLCBzdGFydD0wLCBlbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uICh2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IDBcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kKSBlbmQgPSB0aGlzLmxlbmd0aFxuXG4gIGlmIChlbmQgPCBzdGFydCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCA8IHN0YXJ0JylcblxuICAvLyBGaWxsIDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDAgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdlbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJ5dGVzID0gdXRmOFRvQnl0ZXModmFsdWUudG9TdHJpbmcoKSlcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gKCkge1xuICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgICByZXR1cm4gKG5ldyBCdWZmZXIodGhpcykpLmJ1ZmZlclxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYnVmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgpXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gYnVmLmxlbmd0aDsgaSA8IGxlbjsgaSArPSAxKSB7XG4gICAgICAgIGJ1ZltpXSA9IHRoaXNbaV1cbiAgICAgIH1cbiAgICAgIHJldHVybiBidWYuYnVmZmVyXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0J1ZmZlci50b0FycmF5QnVmZmVyIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBicm93c2VyJylcbiAgfVxufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbnZhciBCUCA9IEJ1ZmZlci5wcm90b3R5cGVcblxuLyoqXG4gKiBBdWdtZW50IGEgVWludDhBcnJheSAqaW5zdGFuY2UqIChub3QgdGhlIFVpbnQ4QXJyYXkgY2xhc3MhKSB3aXRoIEJ1ZmZlciBtZXRob2RzXG4gKi9cbkJ1ZmZlci5fYXVnbWVudCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgYXJyLmNvbnN0cnVjdG9yID0gQnVmZmVyXG4gIGFyci5faXNCdWZmZXIgPSB0cnVlXG5cbiAgLy8gc2F2ZSByZWZlcmVuY2UgdG8gb3JpZ2luYWwgVWludDhBcnJheSBnZXQvc2V0IG1ldGhvZHMgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fZ2V0ID0gYXJyLmdldFxuICBhcnIuX3NldCA9IGFyci5zZXRcblxuICAvLyBkZXByZWNhdGVkLCB3aWxsIGJlIHJlbW92ZWQgaW4gbm9kZSAwLjEzK1xuICBhcnIuZ2V0ID0gQlAuZ2V0XG4gIGFyci5zZXQgPSBCUC5zZXRcblxuICBhcnIud3JpdGUgPSBCUC53cml0ZVxuICBhcnIudG9TdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9Mb2NhbGVTdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9KU09OID0gQlAudG9KU09OXG4gIGFyci5lcXVhbHMgPSBCUC5lcXVhbHNcbiAgYXJyLmNvbXBhcmUgPSBCUC5jb21wYXJlXG4gIGFyci5jb3B5ID0gQlAuY29weVxuICBhcnIuc2xpY2UgPSBCUC5zbGljZVxuICBhcnIucmVhZFVJbnRMRSA9IEJQLnJlYWRVSW50TEVcbiAgYXJyLnJlYWRVSW50QkUgPSBCUC5yZWFkVUludEJFXG4gIGFyci5yZWFkVUludDggPSBCUC5yZWFkVUludDhcbiAgYXJyLnJlYWRVSW50MTZMRSA9IEJQLnJlYWRVSW50MTZMRVxuICBhcnIucmVhZFVJbnQxNkJFID0gQlAucmVhZFVJbnQxNkJFXG4gIGFyci5yZWFkVUludDMyTEUgPSBCUC5yZWFkVUludDMyTEVcbiAgYXJyLnJlYWRVSW50MzJCRSA9IEJQLnJlYWRVSW50MzJCRVxuICBhcnIucmVhZEludExFID0gQlAucmVhZEludExFXG4gIGFyci5yZWFkSW50QkUgPSBCUC5yZWFkSW50QkVcbiAgYXJyLnJlYWRJbnQ4ID0gQlAucmVhZEludDhcbiAgYXJyLnJlYWRJbnQxNkxFID0gQlAucmVhZEludDE2TEVcbiAgYXJyLnJlYWRJbnQxNkJFID0gQlAucmVhZEludDE2QkVcbiAgYXJyLnJlYWRJbnQzMkxFID0gQlAucmVhZEludDMyTEVcbiAgYXJyLnJlYWRJbnQzMkJFID0gQlAucmVhZEludDMyQkVcbiAgYXJyLnJlYWRGbG9hdExFID0gQlAucmVhZEZsb2F0TEVcbiAgYXJyLnJlYWRGbG9hdEJFID0gQlAucmVhZEZsb2F0QkVcbiAgYXJyLnJlYWREb3VibGVMRSA9IEJQLnJlYWREb3VibGVMRVxuICBhcnIucmVhZERvdWJsZUJFID0gQlAucmVhZERvdWJsZUJFXG4gIGFyci53cml0ZVVJbnQ4ID0gQlAud3JpdGVVSW50OFxuICBhcnIud3JpdGVVSW50TEUgPSBCUC53cml0ZVVJbnRMRVxuICBhcnIud3JpdGVVSW50QkUgPSBCUC53cml0ZVVJbnRCRVxuICBhcnIud3JpdGVVSW50MTZMRSA9IEJQLndyaXRlVUludDE2TEVcbiAgYXJyLndyaXRlVUludDE2QkUgPSBCUC53cml0ZVVJbnQxNkJFXG4gIGFyci53cml0ZVVJbnQzMkxFID0gQlAud3JpdGVVSW50MzJMRVxuICBhcnIud3JpdGVVSW50MzJCRSA9IEJQLndyaXRlVUludDMyQkVcbiAgYXJyLndyaXRlSW50TEUgPSBCUC53cml0ZUludExFXG4gIGFyci53cml0ZUludEJFID0gQlAud3JpdGVJbnRCRVxuICBhcnIud3JpdGVJbnQ4ID0gQlAud3JpdGVJbnQ4XG4gIGFyci53cml0ZUludDE2TEUgPSBCUC53cml0ZUludDE2TEVcbiAgYXJyLndyaXRlSW50MTZCRSA9IEJQLndyaXRlSW50MTZCRVxuICBhcnIud3JpdGVJbnQzMkxFID0gQlAud3JpdGVJbnQzMkxFXG4gIGFyci53cml0ZUludDMyQkUgPSBCUC53cml0ZUludDMyQkVcbiAgYXJyLndyaXRlRmxvYXRMRSA9IEJQLndyaXRlRmxvYXRMRVxuICBhcnIud3JpdGVGbG9hdEJFID0gQlAud3JpdGVGbG9hdEJFXG4gIGFyci53cml0ZURvdWJsZUxFID0gQlAud3JpdGVEb3VibGVMRVxuICBhcnIud3JpdGVEb3VibGVCRSA9IEJQLndyaXRlRG91YmxlQkVcbiAgYXJyLmZpbGwgPSBCUC5maWxsXG4gIGFyci5pbnNwZWN0ID0gQlAuaW5zcGVjdFxuICBhcnIudG9BcnJheUJ1ZmZlciA9IEJQLnRvQXJyYXlCdWZmZXJcblxuICByZXR1cm4gYXJyXG59XG5cbnZhciBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXitcXC8wLTlBLXpcXC1dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHN0cmlwcyBvdXQgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgXFxuIGFuZCBcXHQgZnJvbSB0aGUgc3RyaW5nLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgc3RyID0gc3RyaW5ndHJpbShzdHIpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHN0cmluZ3RyaW0gKHN0cikge1xuICBpZiAoc3RyLnRyaW0pIHJldHVybiBzdHIudHJpbSgpXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpXG59XG5cbmZ1bmN0aW9uIGlzQXJyYXlpc2ggKHN1YmplY3QpIHtcbiAgcmV0dXJuIGlzQXJyYXkoc3ViamVjdCkgfHwgQnVmZmVyLmlzQnVmZmVyKHN1YmplY3QpIHx8XG4gICAgICBzdWJqZWN0ICYmIHR5cGVvZiBzdWJqZWN0ID09PSAnb2JqZWN0JyAmJlxuICAgICAgdHlwZW9mIHN1YmplY3QubGVuZ3RoID09PSAnbnVtYmVyJ1xufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzKHN0cmluZywgdW5pdHMpIHtcbiAgdmFyIGNvZGVQb2ludCwgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgYnl0ZXMgPSBbXVxuICB2YXIgaSA9IDBcblxuICBmb3IgKDsgaTxsZW5ndGg7IGkrKykge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcblxuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmIChsZWFkU3Vycm9nYXRlKSB7XG5cbiAgICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBjb2RlUG9pbnQgPSBsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwIHwgMHgxMDAwMFxuICAgICAgICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgIGVsc2Uge1xuXG4gICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgIGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gICAgfVxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9XG4gICAgZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApO1xuICAgIH1cbiAgICBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApO1xuICAgIH1cbiAgICBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDIwMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIsIHVuaXRzKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG5cbiAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcblxuICAgIGMgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGhpID0gYyA+PiA4XG4gICAgbG8gPSBjICUgMjU2XG4gICAgYnl0ZUFycmF5LnB1c2gobG8pXG4gICAgYnl0ZUFycmF5LnB1c2goaGkpXG4gIH1cblxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMgKHN0cikge1xuICByZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KGJhc2U2NGNsZWFuKHN0cikpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCwgdW5pdFNpemUpIHtcbiAgaWYgKHVuaXRTaXplKSBsZW5ndGggLT0gbGVuZ3RoICUgdW5pdFNpemU7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpXG4gICAgICBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIGRlY29kZVV0ZjhDaGFyIChzdHIpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0cilcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoMHhGRkZEKSAvLyBVVEYgOCBpbnZhbGlkIGNoYXJcbiAgfVxufVxuIiwidmFyIGxvb2t1cCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQndXNlIHN0cmljdCc7XG5cbiAgdmFyIEFyciA9ICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgPyBVaW50OEFycmF5XG4gICAgOiBBcnJheVxuXG5cdHZhciBQTFVTICAgPSAnKycuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0ggID0gJy8nLmNoYXJDb2RlQXQoMClcblx0dmFyIE5VTUJFUiA9ICcwJy5jaGFyQ29kZUF0KDApXG5cdHZhciBMT1dFUiAgPSAnYScuY2hhckNvZGVBdCgwKVxuXHR2YXIgVVBQRVIgID0gJ0EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFBMVVNfVVJMX1NBRkUgPSAnLScuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0hfVVJMX1NBRkUgPSAnXycuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTIHx8XG5cdFx0ICAgIGNvZGUgPT09IFBMVVNfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjIgLy8gJysnXG5cdFx0aWYgKGNvZGUgPT09IFNMQVNIIHx8XG5cdFx0ICAgIGNvZGUgPT09IFNMQVNIX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYzIC8vICcvJ1xuXHRcdGlmIChjb2RlIDwgTlVNQkVSKVxuXHRcdFx0cmV0dXJuIC0xIC8vbm8gbWF0Y2hcblx0XHRpZiAoY29kZSA8IE5VTUJFUiArIDEwKVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBOVU1CRVIgKyAyNiArIDI2XG5cdFx0aWYgKGNvZGUgPCBVUFBFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBVUFBFUlxuXHRcdGlmIChjb2RlIDwgTE9XRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gTE9XRVIgKyAyNlxuXHR9XG5cblx0ZnVuY3Rpb24gYjY0VG9CeXRlQXJyYXkgKGI2NCkge1xuXHRcdHZhciBpLCBqLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG5cblx0XHRpZiAoYjY0Lmxlbmd0aCAlIDQgPiAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuXHRcdH1cblxuXHRcdC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuXHRcdC8vIHJlcHJlc2VudCBvbmUgYnl0ZVxuXHRcdC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuXHRcdC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2Vcblx0XHR2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXHRcdHBsYWNlSG9sZGVycyA9ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAyKSA/IDIgOiAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMSkgPyAxIDogMFxuXG5cdFx0Ly8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5cdFx0YXJyID0gbmV3IEFycihiNjQubGVuZ3RoICogMyAvIDQgLSBwbGFjZUhvbGRlcnMpXG5cblx0XHQvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG5cdFx0bCA9IHBsYWNlSG9sZGVycyA+IDAgPyBiNjQubGVuZ3RoIC0gNCA6IGI2NC5sZW5ndGhcblxuXHRcdHZhciBMID0gMFxuXG5cdFx0ZnVuY3Rpb24gcHVzaCAodikge1xuXHRcdFx0YXJyW0wrK10gPSB2XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsOyBpICs9IDQsIGogKz0gMykge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxOCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCAxMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA8PCA2KSB8IGRlY29kZShiNjQuY2hhckF0KGkgKyAzKSlcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMDAwKSA+PiAxNilcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMCkgPj4gOClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPj4gNClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxMCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCA0KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpID4+IDIpXG5cdFx0XHRwdXNoKCh0bXAgPj4gOCkgJiAweEZGKVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdHJldHVybiBhcnJcblx0fVxuXG5cdGZ1bmN0aW9uIHVpbnQ4VG9CYXNlNjQgKHVpbnQ4KSB7XG5cdFx0dmFyIGksXG5cdFx0XHRleHRyYUJ5dGVzID0gdWludDgubGVuZ3RoICUgMywgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcblx0XHRcdG91dHB1dCA9IFwiXCIsXG5cdFx0XHR0ZW1wLCBsZW5ndGhcblxuXHRcdGZ1bmN0aW9uIGVuY29kZSAobnVtKSB7XG5cdFx0XHRyZXR1cm4gbG9va3VwLmNoYXJBdChudW0pXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcblx0XHRcdHJldHVybiBlbmNvZGUobnVtID4+IDE4ICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDEyICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDYgJiAweDNGKSArIGVuY29kZShudW0gJiAweDNGKVxuXHRcdH1cblxuXHRcdC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcblx0XHRmb3IgKGkgPSAwLCBsZW5ndGggPSB1aW50OC5sZW5ndGggLSBleHRyYUJ5dGVzOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcblx0XHRcdHRlbXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG5cdFx0XHRvdXRwdXQgKz0gdHJpcGxldFRvQmFzZTY0KHRlbXApXG5cdFx0fVxuXG5cdFx0Ly8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuXHRcdHN3aXRjaCAoZXh0cmFCeXRlcykge1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHR0ZW1wID0gdWludDhbdWludDgubGVuZ3RoIC0gMV1cblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDIpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz09J1xuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHR0ZW1wID0gKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDJdIDw8IDgpICsgKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMTApXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPj4gNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDIpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9J1xuXHRcdFx0XHRicmVha1xuXHRcdH1cblxuXHRcdHJldHVybiBvdXRwdXRcblx0fVxuXG5cdGV4cG9ydHMudG9CeXRlQXJyYXkgPSBiNjRUb0J5dGVBcnJheVxuXHRleHBvcnRzLmZyb21CeXRlQXJyYXkgPSB1aW50OFRvQmFzZTY0XG59KHR5cGVvZiBleHBvcnRzID09PSAndW5kZWZpbmVkJyA/ICh0aGlzLmJhc2U2NGpzID0ge30pIDogZXhwb3J0cykpXG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbihidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIG5CaXRzID0gLTcsXG4gICAgICBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDAsXG4gICAgICBkID0gaXNMRSA/IC0xIDogMSxcbiAgICAgIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV07XG5cbiAgaSArPSBkO1xuXG4gIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xuICBzID4+PSAoLW5CaXRzKTtcbiAgbkJpdHMgKz0gZUxlbjtcbiAgZm9yICg7IG5CaXRzID4gMDsgZSA9IGUgKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCk7XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSk7XG4gIGUgPj49ICgtbkJpdHMpO1xuICBuQml0cyArPSBtTGVuO1xuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KTtcblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXM7XG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KTtcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pO1xuICAgIGUgPSBlIC0gZUJpYXM7XG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbik7XG59O1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGMsXG4gICAgICBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxLFxuICAgICAgZU1heCA9ICgxIDw8IGVMZW4pIC0gMSxcbiAgICAgIGVCaWFzID0gZU1heCA+PiAxLFxuICAgICAgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApLFxuICAgICAgaSA9IGlzTEUgPyAwIDogKG5CeXRlcyAtIDEpLFxuICAgICAgZCA9IGlzTEUgPyAxIDogLTEsXG4gICAgICBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwO1xuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpO1xuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwO1xuICAgIGUgPSBlTWF4O1xuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKTtcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS07XG4gICAgICBjICo9IDI7XG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcyk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrO1xuICAgICAgYyAvPSAyO1xuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDA7XG4gICAgICBlID0gZU1heDtcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gZSArIGVCaWFzO1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gMDtcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KTtcblxuICBlID0gKGUgPDwgbUxlbikgfCBtO1xuICBlTGVuICs9IG1MZW47XG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCk7XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4O1xufTtcbiIsIlxuLyoqXG4gKiBpc0FycmF5XG4gKi9cblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG4vKipcbiAqIHRvU3RyaW5nXG4gKi9cblxudmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qKlxuICogV2hldGhlciBvciBub3QgdGhlIGdpdmVuIGB2YWxgXG4gKiBpcyBhbiBhcnJheS5cbiAqXG4gKiBleGFtcGxlOlxuICpcbiAqICAgICAgICBpc0FycmF5KFtdKTtcbiAqICAgICAgICAvLyA+IHRydWVcbiAqICAgICAgICBpc0FycmF5KGFyZ3VtZW50cyk7XG4gKiAgICAgICAgLy8gPiBmYWxzZVxuICogICAgICAgIGlzQXJyYXkoJycpO1xuICogICAgICAgIC8vID4gZmFsc2VcbiAqXG4gKiBAcGFyYW0ge21peGVkfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2x9XG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBpc0FycmF5IHx8IGZ1bmN0aW9uICh2YWwpIHtcbiAgcmV0dXJuICEhIHZhbCAmJiAnW29iamVjdCBBcnJheV0nID09IHN0ci5jYWxsKHZhbCk7XG59O1xuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuTXV0YXRpb25PYnNlcnZlciA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXI7XG4gICAgdmFyIGNhblBvc3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5wb3N0TWVzc2FnZSAmJiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuICAgIDtcblxuICAgIGlmIChjYW5TZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmKSB7IHJldHVybiB3aW5kb3cuc2V0SW1tZWRpYXRlKGYpIH07XG4gICAgfVxuXG4gICAgdmFyIHF1ZXVlID0gW107XG5cbiAgICBpZiAoY2FuTXV0YXRpb25PYnNlcnZlcikge1xuICAgICAgICB2YXIgaGlkZGVuRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgdmFyIG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHF1ZXVlTGlzdCA9IHF1ZXVlLnNsaWNlKCk7XG4gICAgICAgICAgICBxdWV1ZS5sZW5ndGggPSAwO1xuICAgICAgICAgICAgcXVldWVMaXN0LmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICBvYnNlcnZlci5vYnNlcnZlKGhpZGRlbkRpdiwgeyBhdHRyaWJ1dGVzOiB0cnVlIH0pO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICAgICAgaWYgKCFxdWV1ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBoaWRkZW5EaXYuc2V0QXR0cmlidXRlKCd5ZXMnLCAnbm8nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmIChjYW5Qb3N0KSB7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gZXYuc291cmNlO1xuICAgICAgICAgICAgaWYgKChzb3VyY2UgPT09IHdpbmRvdyB8fCBzb3VyY2UgPT09IG51bGwpICYmIGV2LmRhdGEgPT09ICdwcm9jZXNzLXRpY2snKSB7XG4gICAgICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZuID0gcXVldWUuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICAgICAgcXVldWUucHVzaChmbik7XG4gICAgICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ3Byb2Nlc3MtdGljaycsICcqJyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgIH07XG59KSgpO1xuXG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbi8vIFRPRE8oc2h0eWxtYW4pXG5wcm9jZXNzLmN3ZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICcvJyB9O1xucHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcbiIsIi8qICBQcm90b3R5cGUgSmF2YVNjcmlwdCBmcmFtZXdvcmssIHZlcnNpb24gMS43LjJcbiAqICAoYykgMjAwNS0yMDEwIFNhbSBTdGVwaGVuc29uXG4gKlxuICogIFByb3RvdHlwZSBpcyBmcmVlbHkgZGlzdHJpYnV0YWJsZSB1bmRlciB0aGUgdGVybXMgb2YgYW4gTUlULXN0eWxlIGxpY2Vuc2UuXG4gKiAgRm9yIGRldGFpbHMsIHNlZSB0aGUgUHJvdG90eXBlIHdlYiBzaXRlOiBodHRwOi8vd3d3LnByb3RvdHlwZWpzLm9yZy9cbiAqXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxudmFyIFByb3RvdHlwZSA9IHtcblxuICBWZXJzaW9uOiAnMS43LjInLFxuXG4gIEJyb3dzZXI6IChmdW5jdGlvbigpe1xuICAgIHZhciB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgdmFyIGlzT3BlcmEgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwod2luZG93Lm9wZXJhKSA9PSAnW29iamVjdCBPcGVyYV0nO1xuICAgIHJldHVybiB7XG4gICAgICBJRTogICAgICAgICAgICAgISF3aW5kb3cuYXR0YWNoRXZlbnQgJiYgIWlzT3BlcmEsXG4gICAgICBPcGVyYTogICAgICAgICAgaXNPcGVyYSxcbiAgICAgIFdlYktpdDogICAgICAgICB1YS5pbmRleE9mKCdBcHBsZVdlYktpdC8nKSA+IC0xLFxuICAgICAgR2Vja286ICAgICAgICAgIHVhLmluZGV4T2YoJ0dlY2tvJykgPiAtMSAmJiB1YS5pbmRleE9mKCdLSFRNTCcpID09PSAtMSxcbiAgICAgIE1vYmlsZVNhZmFyaTogICAvQXBwbGUuKk1vYmlsZS8udGVzdCh1YSlcbiAgICB9XG4gIH0pKCksXG5cbiAgQnJvd3NlckZlYXR1cmVzOiB7XG4gICAgWFBhdGg6ICEhZG9jdW1lbnQuZXZhbHVhdGUsXG5cbiAgICBTZWxlY3RvcnNBUEk6ICEhZG9jdW1lbnQucXVlcnlTZWxlY3RvcixcblxuICAgIEVsZW1lbnRFeHRlbnNpb25zOiAoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgY29uc3RydWN0b3IgPSB3aW5kb3cuRWxlbWVudCB8fCB3aW5kb3cuSFRNTEVsZW1lbnQ7XG4gICAgICByZXR1cm4gISEoY29uc3RydWN0b3IgJiYgY29uc3RydWN0b3IucHJvdG90eXBlKTtcbiAgICB9KSgpLFxuICAgIFNwZWNpZmljRWxlbWVudEV4dGVuc2lvbnM6IChmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0eXBlb2Ygd2luZG93LkhUTUxEaXZFbGVtZW50ICE9PSAndW5kZWZpbmVkJylcbiAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICAgIHZhciBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcbiAgICAgICAgICBmb3JtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZm9ybScpLFxuICAgICAgICAgIGlzU3VwcG9ydGVkID0gZmFsc2U7XG5cbiAgICAgIGlmIChkaXZbJ19fcHJvdG9fXyddICYmIChkaXZbJ19fcHJvdG9fXyddICE9PSBmb3JtWydfX3Byb3RvX18nXSkpIHtcbiAgICAgICAgaXNTdXBwb3J0ZWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBkaXYgPSBmb3JtID0gbnVsbDtcblxuICAgICAgcmV0dXJuIGlzU3VwcG9ydGVkO1xuICAgIH0pKClcbiAgfSxcblxuICBTY3JpcHRGcmFnbWVudDogJzxzY3JpcHRbXj5dKj4oW1xcXFxTXFxcXHNdKj8pPFxcL3NjcmlwdFxcXFxzKj4nLFxuICBKU09ORmlsdGVyOiAvXlxcL1xcKi1zZWN1cmUtKFtcXHNcXFNdKilcXCpcXC9cXHMqJC8sXG5cbiAgZW1wdHlGdW5jdGlvbjogZnVuY3Rpb24oKSB7IH0sXG5cbiAgSzogZnVuY3Rpb24oeCkgeyByZXR1cm4geCB9XG59O1xuXG5pZiAoUHJvdG90eXBlLkJyb3dzZXIuTW9iaWxlU2FmYXJpKVxuICBQcm90b3R5cGUuQnJvd3NlckZlYXR1cmVzLlNwZWNpZmljRWxlbWVudEV4dGVuc2lvbnMgPSBmYWxzZTtcbi8qIEJhc2VkIG9uIEFsZXggQXJuZWxsJ3MgaW5oZXJpdGFuY2UgaW1wbGVtZW50YXRpb24uICovXG5cbnZhciBDbGFzcyA9IChmdW5jdGlvbigpIHtcblxuICB2YXIgSVNfRE9OVEVOVU1fQlVHR1kgPSAoZnVuY3Rpb24oKXtcbiAgICBmb3IgKHZhciBwIGluIHsgdG9TdHJpbmc6IDEgfSkge1xuICAgICAgaWYgKHAgPT09ICd0b1N0cmluZycpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH0pKCk7XG5cbiAgZnVuY3Rpb24gc3ViY2xhc3MoKSB7fTtcbiAgZnVuY3Rpb24gY3JlYXRlKCkge1xuICAgIHZhciBwYXJlbnQgPSBudWxsLCBwcm9wZXJ0aWVzID0gJEEoYXJndW1lbnRzKTtcbiAgICBpZiAoT2JqZWN0LmlzRnVuY3Rpb24ocHJvcGVydGllc1swXSkpXG4gICAgICBwYXJlbnQgPSBwcm9wZXJ0aWVzLnNoaWZ0KCk7XG5cbiAgICBmdW5jdGlvbiBrbGFzcygpIHtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cblxuICAgIE9iamVjdC5leHRlbmQoa2xhc3MsIENsYXNzLk1ldGhvZHMpO1xuICAgIGtsYXNzLnN1cGVyY2xhc3MgPSBwYXJlbnQ7XG4gICAga2xhc3Muc3ViY2xhc3NlcyA9IFtdO1xuXG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgc3ViY2xhc3MucHJvdG90eXBlID0gcGFyZW50LnByb3RvdHlwZTtcbiAgICAgIGtsYXNzLnByb3RvdHlwZSA9IG5ldyBzdWJjbGFzcztcbiAgICAgIHBhcmVudC5zdWJjbGFzc2VzLnB1c2goa2xhc3MpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBwcm9wZXJ0aWVzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKVxuICAgICAga2xhc3MuYWRkTWV0aG9kcyhwcm9wZXJ0aWVzW2ldKTtcblxuICAgIGlmICgha2xhc3MucHJvdG90eXBlLmluaXRpYWxpemUpXG4gICAgICBrbGFzcy5wcm90b3R5cGUuaW5pdGlhbGl6ZSA9IFByb3RvdHlwZS5lbXB0eUZ1bmN0aW9uO1xuXG4gICAga2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0ga2xhc3M7XG4gICAgcmV0dXJuIGtsYXNzO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRkTWV0aG9kcyhzb3VyY2UpIHtcbiAgICB2YXIgYW5jZXN0b3IgICA9IHRoaXMuc3VwZXJjbGFzcyAmJiB0aGlzLnN1cGVyY2xhc3MucHJvdG90eXBlLFxuICAgICAgICBwcm9wZXJ0aWVzID0gT2JqZWN0LmtleXMoc291cmNlKTtcblxuICAgIGlmIChJU19ET05URU5VTV9CVUdHWSkge1xuICAgICAgaWYgKHNvdXJjZS50b1N0cmluZyAhPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKVxuICAgICAgICBwcm9wZXJ0aWVzLnB1c2goXCJ0b1N0cmluZ1wiKTtcbiAgICAgIGlmIChzb3VyY2UudmFsdWVPZiAhPSBPYmplY3QucHJvdG90eXBlLnZhbHVlT2YpXG4gICAgICAgIHByb3BlcnRpZXMucHVzaChcInZhbHVlT2ZcIik7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IHByb3BlcnRpZXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbaV0sIHZhbHVlID0gc291cmNlW3Byb3BlcnR5XTtcbiAgICAgIGlmIChhbmNlc3RvciAmJiBPYmplY3QuaXNGdW5jdGlvbih2YWx1ZSkgJiZcbiAgICAgICAgICB2YWx1ZS5hcmd1bWVudE5hbWVzKClbMF0gPT0gXCIkc3VwZXJcIikge1xuICAgICAgICB2YXIgbWV0aG9kID0gdmFsdWU7XG4gICAgICAgIHZhbHVlID0gKGZ1bmN0aW9uKG0pIHtcbiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiBhbmNlc3RvclttXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyB9O1xuICAgICAgICB9KShwcm9wZXJ0eSkud3JhcChtZXRob2QpO1xuXG4gICAgICAgIHZhbHVlLnZhbHVlT2YgPSAoZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyByZXR1cm4gbWV0aG9kLnZhbHVlT2YuY2FsbChtZXRob2QpOyB9O1xuICAgICAgICB9KShtZXRob2QpO1xuXG4gICAgICAgIHZhbHVlLnRvU3RyaW5nID0gKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ldGhvZC50b1N0cmluZy5jYWxsKG1ldGhvZCk7IH07XG4gICAgICAgIH0pKG1ldGhvZCk7XG4gICAgICB9XG4gICAgICB0aGlzLnByb3RvdHlwZVtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgTWV0aG9kczoge1xuICAgICAgYWRkTWV0aG9kczogYWRkTWV0aG9kc1xuICAgIH1cbiAgfTtcbn0pKCk7XG4oZnVuY3Rpb24oKSB7XG5cbiAgdmFyIF90b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcsXG4gICAgICBfaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LFxuICAgICAgTlVMTF9UWVBFID0gJ051bGwnLFxuICAgICAgVU5ERUZJTkVEX1RZUEUgPSAnVW5kZWZpbmVkJyxcbiAgICAgIEJPT0xFQU5fVFlQRSA9ICdCb29sZWFuJyxcbiAgICAgIE5VTUJFUl9UWVBFID0gJ051bWJlcicsXG4gICAgICBTVFJJTkdfVFlQRSA9ICdTdHJpbmcnLFxuICAgICAgT0JKRUNUX1RZUEUgPSAnT2JqZWN0JyxcbiAgICAgIEZVTkNUSU9OX0NMQVNTID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICAgIEJPT0xFQU5fQ0xBU1MgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgICBOVU1CRVJfQ0xBU1MgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICAgIFNUUklOR19DTEFTUyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgICAgQVJSQVlfQ0xBU1MgPSAnW29iamVjdCBBcnJheV0nLFxuICAgICAgREFURV9DTEFTUyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICAgIE5BVElWRV9KU09OX1NUUklOR0lGWV9TVVBQT1JUID0gd2luZG93LkpTT04gJiZcbiAgICAgICAgdHlwZW9mIEpTT04uc3RyaW5naWZ5ID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KDApID09PSAnMCcgJiZcbiAgICAgICAgdHlwZW9mIEpTT04uc3RyaW5naWZ5KFByb3RvdHlwZS5LKSA9PT0gJ3VuZGVmaW5lZCc7XG5cblxuXG4gIHZhciBET05UX0VOVU1TID0gWyd0b1N0cmluZycsICd0b0xvY2FsZVN0cmluZycsICd2YWx1ZU9mJyxcbiAgICdoYXNPd25Qcm9wZXJ0eScsICdpc1Byb3RvdHlwZU9mJywgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJywgJ2NvbnN0cnVjdG9yJ107XG5cbiAgdmFyIElTX0RPTlRFTlVNX0JVR0dZID0gKGZ1bmN0aW9uKCl7XG4gICAgZm9yICh2YXIgcCBpbiB7IHRvU3RyaW5nOiAxIH0pIHtcbiAgICAgIGlmIChwID09PSAndG9TdHJpbmcnKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9KSgpO1xuXG4gIGZ1bmN0aW9uIFR5cGUobykge1xuICAgIHN3aXRjaChvKSB7XG4gICAgICBjYXNlIG51bGw6IHJldHVybiBOVUxMX1RZUEU7XG4gICAgICBjYXNlICh2b2lkIDApOiByZXR1cm4gVU5ERUZJTkVEX1RZUEU7XG4gICAgfVxuICAgIHZhciB0eXBlID0gdHlwZW9mIG87XG4gICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2Jvb2xlYW4nOiByZXR1cm4gQk9PTEVBTl9UWVBFO1xuICAgICAgY2FzZSAnbnVtYmVyJzogIHJldHVybiBOVU1CRVJfVFlQRTtcbiAgICAgIGNhc2UgJ3N0cmluZyc6ICByZXR1cm4gU1RSSU5HX1RZUEU7XG4gICAgfVxuICAgIHJldHVybiBPQkpFQ1RfVFlQRTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGV4dGVuZChkZXN0aW5hdGlvbiwgc291cmNlKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gc291cmNlKVxuICAgICAgZGVzdGluYXRpb25bcHJvcGVydHldID0gc291cmNlW3Byb3BlcnR5XTtcbiAgICByZXR1cm4gZGVzdGluYXRpb247XG4gIH1cblxuICBmdW5jdGlvbiBpbnNwZWN0KG9iamVjdCkge1xuICAgIHRyeSB7XG4gICAgICBpZiAoaXNVbmRlZmluZWQob2JqZWN0KSkgcmV0dXJuICd1bmRlZmluZWQnO1xuICAgICAgaWYgKG9iamVjdCA9PT0gbnVsbCkgcmV0dXJuICdudWxsJztcbiAgICAgIHJldHVybiBvYmplY3QuaW5zcGVjdCA/IG9iamVjdC5pbnNwZWN0KCkgOiBTdHJpbmcob2JqZWN0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZSBpbnN0YW5jZW9mIFJhbmdlRXJyb3IpIHJldHVybiAnLi4uJztcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdG9KU09OKHZhbHVlKSB7XG4gICAgcmV0dXJuIFN0cignJywgeyAnJzogdmFsdWUgfSwgW10pO1xuICB9XG5cbiAgZnVuY3Rpb24gU3RyKGtleSwgaG9sZGVyLCBzdGFjaykge1xuICAgIHZhciB2YWx1ZSA9IGhvbGRlcltrZXldO1xuICAgIGlmIChUeXBlKHZhbHVlKSA9PT0gT0JKRUNUX1RZUEUgJiYgdHlwZW9mIHZhbHVlLnRvSlNPTiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdmFsdWUgPSB2YWx1ZS50b0pTT04oa2V5KTtcbiAgICB9XG5cbiAgICB2YXIgX2NsYXNzID0gX3RvU3RyaW5nLmNhbGwodmFsdWUpO1xuXG4gICAgc3dpdGNoIChfY2xhc3MpIHtcbiAgICAgIGNhc2UgTlVNQkVSX0NMQVNTOlxuICAgICAgY2FzZSBCT09MRUFOX0NMQVNTOlxuICAgICAgY2FzZSBTVFJJTkdfQ0xBU1M6XG4gICAgICAgIHZhbHVlID0gdmFsdWUudmFsdWVPZigpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgIGNhc2UgbnVsbDogcmV0dXJuICdudWxsJztcbiAgICAgIGNhc2UgdHJ1ZTogcmV0dXJuICd0cnVlJztcbiAgICAgIGNhc2UgZmFsc2U6IHJldHVybiAnZmFsc2UnO1xuICAgIH1cblxuICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgcmV0dXJuIHZhbHVlLmluc3BlY3QodHJ1ZSk7XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICByZXR1cm4gaXNGaW5pdGUodmFsdWUpID8gU3RyaW5nKHZhbHVlKSA6ICdudWxsJztcbiAgICAgIGNhc2UgJ29iamVjdCc6XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IHN0YWNrLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKHN0YWNrW2ldID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkN5Y2xpYyByZWZlcmVuY2UgdG8gJ1wiICsgdmFsdWUgKyBcIicgaW4gb2JqZWN0XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFjay5wdXNoKHZhbHVlKTtcblxuICAgICAgICB2YXIgcGFydGlhbCA9IFtdO1xuICAgICAgICBpZiAoX2NsYXNzID09PSBBUlJBWV9DTEFTUykge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSB2YWx1ZS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHN0ciA9IFN0cihpLCB2YWx1ZSwgc3RhY2spO1xuICAgICAgICAgICAgcGFydGlhbC5wdXNoKHR5cGVvZiBzdHIgPT09ICd1bmRlZmluZWQnID8gJ251bGwnIDogc3RyKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFydGlhbCA9ICdbJyArIHBhcnRpYWwuam9pbignLCcpICsgJ10nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXModmFsdWUpO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXSwgc3RyID0gU3RyKGtleSwgdmFsdWUsIHN0YWNrKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc3RyICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICBwYXJ0aWFsLnB1c2goa2V5Lmluc3BlY3QodHJ1ZSkrICc6JyArIHN0cik7XG4gICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJ0aWFsID0gJ3snICsgcGFydGlhbC5qb2luKCcsJykgKyAnfSc7XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2sucG9wKCk7XG4gICAgICAgIHJldHVybiBwYXJ0aWFsO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0cmluZ2lmeShvYmplY3QpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqZWN0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRvUXVlcnlTdHJpbmcob2JqZWN0KSB7XG4gICAgcmV0dXJuICRIKG9iamVjdCkudG9RdWVyeVN0cmluZygpO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9IVE1MKG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgJiYgb2JqZWN0LnRvSFRNTCA/IG9iamVjdC50b0hUTUwoKSA6IFN0cmluZy5pbnRlcnByZXQob2JqZWN0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGtleXMob2JqZWN0KSB7XG4gICAgaWYgKFR5cGUob2JqZWN0KSAhPT0gT0JKRUNUX1RZUEUpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigpOyB9XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiBvYmplY3QpIHtcbiAgICAgIGlmIChfaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KSlcbiAgICAgICAgcmVzdWx0cy5wdXNoKHByb3BlcnR5KTtcbiAgICB9XG5cbiAgICBpZiAoSVNfRE9OVEVOVU1fQlVHR1kpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBwcm9wZXJ0eSA9IERPTlRfRU5VTVNbaV07IGkrKykge1xuICAgICAgICBpZiAoX2hhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wZXJ0eSkpXG4gICAgICAgICAgcmVzdWx0cy5wdXNoKHByb3BlcnR5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIG9iamVjdClcbiAgICAgIHJlc3VsdHMucHVzaChvYmplY3RbcHJvcGVydHldKTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsb25lKG9iamVjdCkge1xuICAgIHJldHVybiBleHRlbmQoeyB9LCBvYmplY3QpO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNFbGVtZW50KG9iamVjdCkge1xuICAgIHJldHVybiAhIShvYmplY3QgJiYgb2JqZWN0Lm5vZGVUeXBlID09IDEpO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNBcnJheShvYmplY3QpIHtcbiAgICByZXR1cm4gX3RvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gQVJSQVlfQ0xBU1M7XG4gIH1cblxuICB2YXIgaGFzTmF0aXZlSXNBcnJheSA9ICh0eXBlb2YgQXJyYXkuaXNBcnJheSA9PSAnZnVuY3Rpb24nKVxuICAgICYmIEFycmF5LmlzQXJyYXkoW10pICYmICFBcnJheS5pc0FycmF5KHt9KTtcblxuICBpZiAoaGFzTmF0aXZlSXNBcnJheSkge1xuICAgIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICB9XG5cbiAgZnVuY3Rpb24gaXNIYXNoKG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiBIYXNoO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNGdW5jdGlvbihvYmplY3QpIHtcbiAgICByZXR1cm4gX3RvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gRlVOQ1RJT05fQ0xBU1M7XG4gIH1cblxuICBmdW5jdGlvbiBpc1N0cmluZyhvYmplY3QpIHtcbiAgICByZXR1cm4gX3RvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gU1RSSU5HX0NMQVNTO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNOdW1iZXIob2JqZWN0KSB7XG4gICAgcmV0dXJuIF90b1N0cmluZy5jYWxsKG9iamVjdCkgPT09IE5VTUJFUl9DTEFTUztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRGF0ZShvYmplY3QpIHtcbiAgICByZXR1cm4gX3RvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gREFURV9DTEFTUztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzVW5kZWZpbmVkKG9iamVjdCkge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqZWN0ID09PSBcInVuZGVmaW5lZFwiO1xuICB9XG5cbiAgZXh0ZW5kKE9iamVjdCwge1xuICAgIGV4dGVuZDogICAgICAgIGV4dGVuZCxcbiAgICBpbnNwZWN0OiAgICAgICBpbnNwZWN0LFxuICAgIHRvSlNPTjogICAgICAgIE5BVElWRV9KU09OX1NUUklOR0lGWV9TVVBQT1JUID8gc3RyaW5naWZ5IDogdG9KU09OLFxuICAgIHRvUXVlcnlTdHJpbmc6IHRvUXVlcnlTdHJpbmcsXG4gICAgdG9IVE1MOiAgICAgICAgdG9IVE1MLFxuICAgIGtleXM6ICAgICAgICAgIE9iamVjdC5rZXlzIHx8IGtleXMsXG4gICAgdmFsdWVzOiAgICAgICAgdmFsdWVzLFxuICAgIGNsb25lOiAgICAgICAgIGNsb25lLFxuICAgIGlzRWxlbWVudDogICAgIGlzRWxlbWVudCxcbiAgICBpc0FycmF5OiAgICAgICBpc0FycmF5LFxuICAgIGlzSGFzaDogICAgICAgIGlzSGFzaCxcbiAgICBpc0Z1bmN0aW9uOiAgICBpc0Z1bmN0aW9uLFxuICAgIGlzU3RyaW5nOiAgICAgIGlzU3RyaW5nLFxuICAgIGlzTnVtYmVyOiAgICAgIGlzTnVtYmVyLFxuICAgIGlzRGF0ZTogICAgICAgIGlzRGF0ZSxcbiAgICBpc1VuZGVmaW5lZDogICBpc1VuZGVmaW5lZFxuICB9KTtcbn0pKCk7XG5PYmplY3QuZXh0ZW5kKEZ1bmN0aW9uLnByb3RvdHlwZSwgKGZ1bmN0aW9uKCkge1xuICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbiAgZnVuY3Rpb24gdXBkYXRlKGFycmF5LCBhcmdzKSB7XG4gICAgdmFyIGFycmF5TGVuZ3RoID0gYXJyYXkubGVuZ3RoLCBsZW5ndGggPSBhcmdzLmxlbmd0aDtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIGFycmF5W2FycmF5TGVuZ3RoICsgbGVuZ3RoXSA9IGFyZ3NbbGVuZ3RoXTtcbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICBmdW5jdGlvbiBtZXJnZShhcnJheSwgYXJncykge1xuICAgIGFycmF5ID0gc2xpY2UuY2FsbChhcnJheSwgMCk7XG4gICAgcmV0dXJuIHVwZGF0ZShhcnJheSwgYXJncyk7XG4gIH1cblxuICBmdW5jdGlvbiBhcmd1bWVudE5hbWVzKCkge1xuICAgIHZhciBuYW1lcyA9IHRoaXMudG9TdHJpbmcoKS5tYXRjaCgvXltcXHNcXChdKmZ1bmN0aW9uW14oXSpcXCgoW14pXSopXFwpLylbMV1cbiAgICAgIC5yZXBsYWNlKC9cXC9cXC8uKj9bXFxyXFxuXXxcXC9cXCooPzoufFtcXHJcXG5dKSo/XFwqXFwvL2csICcnKVxuICAgICAgLnJlcGxhY2UoL1xccysvZywgJycpLnNwbGl0KCcsJyk7XG4gICAgcmV0dXJuIG5hbWVzLmxlbmd0aCA9PSAxICYmICFuYW1lc1swXSA/IFtdIDogbmFtZXM7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGJpbmQoY29udGV4dCkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMiAmJiBPYmplY3QuaXNVbmRlZmluZWQoYXJndW1lbnRzWzBdKSlcbiAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKCFPYmplY3QuaXNGdW5jdGlvbih0aGlzKSlcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJUaGUgb2JqZWN0IGlzIG5vdCBjYWxsYWJsZS5cIik7XG5cbiAgICB2YXIgbm9wID0gZnVuY3Rpb24oKSB7fTtcbiAgICB2YXIgX19tZXRob2QgPSB0aGlzLCBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXG4gICAgdmFyIGJvdW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYSA9IG1lcmdlKGFyZ3MsIGFyZ3VtZW50cyk7XG4gICAgICB2YXIgYyA9IHRoaXMgaW5zdGFuY2VvZiBib3VuZCA/IHRoaXMgOiBjb250ZXh0O1xuICAgICAgcmV0dXJuIF9fbWV0aG9kLmFwcGx5KGMsIGEpO1xuICAgIH07XG5cbiAgICBub3AucHJvdG90eXBlICAgPSB0aGlzLnByb3RvdHlwZTtcbiAgICBib3VuZC5wcm90b3R5cGUgPSBuZXcgbm9wKCk7XG5cbiAgICByZXR1cm4gYm91bmQ7XG4gIH1cblxuICBmdW5jdGlvbiBiaW5kQXNFdmVudExpc3RlbmVyKGNvbnRleHQpIHtcbiAgICB2YXIgX19tZXRob2QgPSB0aGlzLCBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBmdW5jdGlvbihldmVudCkge1xuICAgICAgdmFyIGEgPSB1cGRhdGUoW2V2ZW50IHx8IHdpbmRvdy5ldmVudF0sIGFyZ3MpO1xuICAgICAgcmV0dXJuIF9fbWV0aG9kLmFwcGx5KGNvbnRleHQsIGEpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGN1cnJ5KCkge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRoaXM7XG4gICAgdmFyIF9fbWV0aG9kID0gdGhpcywgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYSA9IG1lcmdlKGFyZ3MsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gX19tZXRob2QuYXBwbHkodGhpcywgYSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZGVsYXkodGltZW91dCkge1xuICAgIHZhciBfX21ldGhvZCA9IHRoaXMsIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgdGltZW91dCA9IHRpbWVvdXQgKiAxMDAwO1xuICAgIHJldHVybiB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfX21ldGhvZC5hcHBseShfX21ldGhvZCwgYXJncyk7XG4gICAgfSwgdGltZW91dCk7XG4gIH1cblxuICBmdW5jdGlvbiBkZWZlcigpIHtcbiAgICB2YXIgYXJncyA9IHVwZGF0ZShbMC4wMV0sIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIHRoaXMuZGVsYXkuYXBwbHkodGhpcywgYXJncyk7XG4gIH1cblxuICBmdW5jdGlvbiB3cmFwKHdyYXBwZXIpIHtcbiAgICB2YXIgX19tZXRob2QgPSB0aGlzO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhID0gdXBkYXRlKFtfX21ldGhvZC5iaW5kKHRoaXMpXSwgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiB3cmFwcGVyLmFwcGx5KHRoaXMsIGEpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG1ldGhvZGl6ZSgpIHtcbiAgICBpZiAodGhpcy5fbWV0aG9kaXplZCkgcmV0dXJuIHRoaXMuX21ldGhvZGl6ZWQ7XG4gICAgdmFyIF9fbWV0aG9kID0gdGhpcztcbiAgICByZXR1cm4gdGhpcy5fbWV0aG9kaXplZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGEgPSB1cGRhdGUoW3RoaXNdLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIF9fbWV0aG9kLmFwcGx5KG51bGwsIGEpO1xuICAgIH07XG4gIH1cblxuICB2YXIgZXh0ZW5zaW9ucyA9IHtcbiAgICBhcmd1bWVudE5hbWVzOiAgICAgICBhcmd1bWVudE5hbWVzLFxuICAgIGJpbmRBc0V2ZW50TGlzdGVuZXI6IGJpbmRBc0V2ZW50TGlzdGVuZXIsXG4gICAgY3Vycnk6ICAgICAgICAgICAgICAgY3VycnksXG4gICAgZGVsYXk6ICAgICAgICAgICAgICAgZGVsYXksXG4gICAgZGVmZXI6ICAgICAgICAgICAgICAgZGVmZXIsXG4gICAgd3JhcDogICAgICAgICAgICAgICAgd3JhcCxcbiAgICBtZXRob2RpemU6ICAgICAgICAgICBtZXRob2RpemVcbiAgfTtcblxuICBpZiAoIUZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kKVxuICAgIGV4dGVuc2lvbnMuYmluZCA9IGJpbmQ7XG5cbiAgcmV0dXJuIGV4dGVuc2lvbnM7XG59KSgpKTtcblxuXG5cbihmdW5jdGlvbihwcm90bykge1xuXG5cbiAgZnVuY3Rpb24gdG9JU09TdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VVRDRnVsbFllYXIoKSArICctJyArXG4gICAgICAodGhpcy5nZXRVVENNb250aCgpICsgMSkudG9QYWRkZWRTdHJpbmcoMikgKyAnLScgK1xuICAgICAgdGhpcy5nZXRVVENEYXRlKCkudG9QYWRkZWRTdHJpbmcoMikgKyAnVCcgK1xuICAgICAgdGhpcy5nZXRVVENIb3VycygpLnRvUGFkZGVkU3RyaW5nKDIpICsgJzonICtcbiAgICAgIHRoaXMuZ2V0VVRDTWludXRlcygpLnRvUGFkZGVkU3RyaW5nKDIpICsgJzonICtcbiAgICAgIHRoaXMuZ2V0VVRDU2Vjb25kcygpLnRvUGFkZGVkU3RyaW5nKDIpICsgJ1onO1xuICB9XG5cblxuICBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgcmV0dXJuIHRoaXMudG9JU09TdHJpbmcoKTtcbiAgfVxuXG4gIGlmICghcHJvdG8udG9JU09TdHJpbmcpIHByb3RvLnRvSVNPU3RyaW5nID0gdG9JU09TdHJpbmc7XG4gIGlmICghcHJvdG8udG9KU09OKSBwcm90by50b0pTT04gPSB0b0pTT047XG5cbn0pKERhdGUucHJvdG90eXBlKTtcblxuXG5SZWdFeHAucHJvdG90eXBlLm1hdGNoID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0O1xuXG5SZWdFeHAuZXNjYXBlID0gZnVuY3Rpb24oc3RyKSB7XG4gIHJldHVybiBTdHJpbmcoc3RyKS5yZXBsYWNlKC8oWy4qKz9ePSE6JHt9KCl8W1xcXVxcL1xcXFxdKS9nLCAnXFxcXCQxJyk7XG59O1xudmFyIFBlcmlvZGljYWxFeGVjdXRlciA9IENsYXNzLmNyZWF0ZSh7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKGNhbGxiYWNrLCBmcmVxdWVuY3kpIHtcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgdGhpcy5mcmVxdWVuY3kgPSBmcmVxdWVuY3k7XG4gICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSBmYWxzZTtcblxuICAgIHRoaXMucmVnaXN0ZXJDYWxsYmFjaygpO1xuICB9LFxuXG4gIHJlZ2lzdGVyQ2FsbGJhY2s6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMudGltZXIgPSBzZXRJbnRlcnZhbCh0aGlzLm9uVGltZXJFdmVudC5iaW5kKHRoaXMpLCB0aGlzLmZyZXF1ZW5jeSAqIDEwMDApO1xuICB9LFxuXG4gIGV4ZWN1dGU6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuY2FsbGJhY2sodGhpcyk7XG4gIH0sXG5cbiAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKCF0aGlzLnRpbWVyKSByZXR1cm47XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLnRpbWVyKTtcbiAgICB0aGlzLnRpbWVyID0gbnVsbDtcbiAgfSxcblxuICBvblRpbWVyRXZlbnQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICghdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5leGVjdXRlKCk7XG4gICAgICAgIHRoaXMuY3VycmVudGx5RXhlY3V0aW5nID0gZmFsc2U7XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50bHlFeGVjdXRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn0pO1xuT2JqZWN0LmV4dGVuZChTdHJpbmcsIHtcbiAgaW50ZXJwcmV0OiBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsID8gJycgOiBTdHJpbmcodmFsdWUpO1xuICB9LFxuICBzcGVjaWFsQ2hhcjoge1xuICAgICdcXGInOiAnXFxcXGInLFxuICAgICdcXHQnOiAnXFxcXHQnLFxuICAgICdcXG4nOiAnXFxcXG4nLFxuICAgICdcXGYnOiAnXFxcXGYnLFxuICAgICdcXHInOiAnXFxcXHInLFxuICAgICdcXFxcJzogJ1xcXFxcXFxcJ1xuICB9XG59KTtcblxuT2JqZWN0LmV4dGVuZChTdHJpbmcucHJvdG90eXBlLCAoZnVuY3Rpb24oKSB7XG4gIHZhciBOQVRJVkVfSlNPTl9QQVJTRV9TVVBQT1JUID0gd2luZG93LkpTT04gJiZcbiAgICB0eXBlb2YgSlNPTi5wYXJzZSA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgIEpTT04ucGFyc2UoJ3tcInRlc3RcIjogdHJ1ZX0nKS50ZXN0O1xuXG4gIGZ1bmN0aW9uIHByZXBhcmVSZXBsYWNlbWVudChyZXBsYWNlbWVudCkge1xuICAgIGlmIChPYmplY3QuaXNGdW5jdGlvbihyZXBsYWNlbWVudCkpIHJldHVybiByZXBsYWNlbWVudDtcbiAgICB2YXIgdGVtcGxhdGUgPSBuZXcgVGVtcGxhdGUocmVwbGFjZW1lbnQpO1xuICAgIHJldHVybiBmdW5jdGlvbihtYXRjaCkgeyByZXR1cm4gdGVtcGxhdGUuZXZhbHVhdGUobWF0Y2gpIH07XG4gIH1cblxuICBmdW5jdGlvbiBpc05vbkVtcHR5UmVnRXhwKHJlZ2V4cCkge1xuICAgIHJldHVybiByZWdleHAuc291cmNlICYmIHJlZ2V4cC5zb3VyY2UgIT09ICcoPzopJztcbiAgfVxuXG5cbiAgZnVuY3Rpb24gZ3N1YihwYXR0ZXJuLCByZXBsYWNlbWVudCkge1xuICAgIHZhciByZXN1bHQgPSAnJywgc291cmNlID0gdGhpcywgbWF0Y2g7XG4gICAgcmVwbGFjZW1lbnQgPSBwcmVwYXJlUmVwbGFjZW1lbnQocmVwbGFjZW1lbnQpO1xuXG4gICAgaWYgKE9iamVjdC5pc1N0cmluZyhwYXR0ZXJuKSlcbiAgICAgIHBhdHRlcm4gPSBSZWdFeHAuZXNjYXBlKHBhdHRlcm4pO1xuXG4gICAgaWYgKCEocGF0dGVybi5sZW5ndGggfHwgaXNOb25FbXB0eVJlZ0V4cChwYXR0ZXJuKSkpIHtcbiAgICAgIHJlcGxhY2VtZW50ID0gcmVwbGFjZW1lbnQoJycpO1xuICAgICAgcmV0dXJuIHJlcGxhY2VtZW50ICsgc291cmNlLnNwbGl0KCcnKS5qb2luKHJlcGxhY2VtZW50KSArIHJlcGxhY2VtZW50O1xuICAgIH1cblxuICAgIHdoaWxlIChzb3VyY2UubGVuZ3RoID4gMCkge1xuICAgICAgbWF0Y2ggPSBzb3VyY2UubWF0Y2gocGF0dGVybilcbiAgICAgIGlmIChtYXRjaCAmJiBtYXRjaFswXS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJlc3VsdCArPSBzb3VyY2Uuc2xpY2UoMCwgbWF0Y2guaW5kZXgpO1xuICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmludGVycHJldChyZXBsYWNlbWVudChtYXRjaCkpO1xuICAgICAgICBzb3VyY2UgID0gc291cmNlLnNsaWNlKG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCArPSBzb3VyY2UsIHNvdXJjZSA9ICcnO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gc3ViKHBhdHRlcm4sIHJlcGxhY2VtZW50LCBjb3VudCkge1xuICAgIHJlcGxhY2VtZW50ID0gcHJlcGFyZVJlcGxhY2VtZW50KHJlcGxhY2VtZW50KTtcbiAgICBjb3VudCA9IE9iamVjdC5pc1VuZGVmaW5lZChjb3VudCkgPyAxIDogY291bnQ7XG5cbiAgICByZXR1cm4gdGhpcy5nc3ViKHBhdHRlcm4sIGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgICBpZiAoLS1jb3VudCA8IDApIHJldHVybiBtYXRjaFswXTtcbiAgICAgIHJldHVybiByZXBsYWNlbWVudChtYXRjaCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBzY2FuKHBhdHRlcm4sIGl0ZXJhdG9yKSB7XG4gICAgdGhpcy5nc3ViKHBhdHRlcm4sIGl0ZXJhdG9yKTtcbiAgICByZXR1cm4gU3RyaW5nKHRoaXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJ1bmNhdGUobGVuZ3RoLCB0cnVuY2F0aW9uKSB7XG4gICAgbGVuZ3RoID0gbGVuZ3RoIHx8IDMwO1xuICAgIHRydW5jYXRpb24gPSBPYmplY3QuaXNVbmRlZmluZWQodHJ1bmNhdGlvbikgPyAnLi4uJyA6IHRydW5jYXRpb247XG4gICAgcmV0dXJuIHRoaXMubGVuZ3RoID4gbGVuZ3RoID9cbiAgICAgIHRoaXMuc2xpY2UoMCwgbGVuZ3RoIC0gdHJ1bmNhdGlvbi5sZW5ndGgpICsgdHJ1bmNhdGlvbiA6IFN0cmluZyh0aGlzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0cmlwKCkge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2UoL15cXHMrLywgJycpLnJlcGxhY2UoL1xccyskLywgJycpO1xuICB9XG5cbiAgZnVuY3Rpb24gc3RyaXBUYWdzKCkge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2UoLzxcXHcrKFxccysoXCJbXlwiXSpcInwnW14nXSonfFtePl0pKyk/Pnw8XFwvXFx3Kz4vZ2ksICcnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0cmlwU2NyaXB0cygpIHtcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlKG5ldyBSZWdFeHAoUHJvdG90eXBlLlNjcmlwdEZyYWdtZW50LCAnaW1nJyksICcnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGV4dHJhY3RTY3JpcHRzKCkge1xuICAgIHZhciBtYXRjaEFsbCA9IG5ldyBSZWdFeHAoUHJvdG90eXBlLlNjcmlwdEZyYWdtZW50LCAnaW1nJyksXG4gICAgICAgIG1hdGNoT25lID0gbmV3IFJlZ0V4cChQcm90b3R5cGUuU2NyaXB0RnJhZ21lbnQsICdpbScpO1xuICAgIHJldHVybiAodGhpcy5tYXRjaChtYXRjaEFsbCkgfHwgW10pLm1hcChmdW5jdGlvbihzY3JpcHRUYWcpIHtcbiAgICAgIHJldHVybiAoc2NyaXB0VGFnLm1hdGNoKG1hdGNoT25lKSB8fCBbJycsICcnXSlbMV07XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBldmFsU2NyaXB0cygpIHtcbiAgICByZXR1cm4gdGhpcy5leHRyYWN0U2NyaXB0cygpLm1hcChmdW5jdGlvbihzY3JpcHQpIHsgcmV0dXJuIGV2YWwoc2NyaXB0KTsgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBlc2NhcGVIVE1MKCkge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2UoLyYvZywnJmFtcDsnKS5yZXBsYWNlKC88L2csJyZsdDsnKS5yZXBsYWNlKC8+L2csJyZndDsnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVuZXNjYXBlSFRNTCgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHJpcFRhZ3MoKS5yZXBsYWNlKC8mbHQ7L2csJzwnKS5yZXBsYWNlKC8mZ3Q7L2csJz4nKS5yZXBsYWNlKC8mYW1wOy9nLCcmJyk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIHRvUXVlcnlQYXJhbXMoc2VwYXJhdG9yKSB7XG4gICAgdmFyIG1hdGNoID0gdGhpcy5zdHJpcCgpLm1hdGNoKC8oW14/I10qKSgjLiopPyQvKTtcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4geyB9O1xuXG4gICAgcmV0dXJuIG1hdGNoWzFdLnNwbGl0KHNlcGFyYXRvciB8fCAnJicpLmluamVjdCh7IH0sIGZ1bmN0aW9uKGhhc2gsIHBhaXIpIHtcbiAgICAgIGlmICgocGFpciA9IHBhaXIuc3BsaXQoJz0nKSlbMF0pIHtcbiAgICAgICAgdmFyIGtleSA9IGRlY29kZVVSSUNvbXBvbmVudChwYWlyLnNoaWZ0KCkpLFxuICAgICAgICAgICAgdmFsdWUgPSBwYWlyLmxlbmd0aCA+IDEgPyBwYWlyLmpvaW4oJz0nKSA6IHBhaXJbMF07XG5cbiAgICAgICAgaWYgKHZhbHVlICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHZhbHVlID0gdmFsdWUuZ3N1YignKycsICcgJyk7XG4gICAgICAgICAgdmFsdWUgPSBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGtleSBpbiBoYXNoKSB7XG4gICAgICAgICAgaWYgKCFPYmplY3QuaXNBcnJheShoYXNoW2tleV0pKSBoYXNoW2tleV0gPSBbaGFzaFtrZXldXTtcbiAgICAgICAgICBoYXNoW2tleV0ucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBoYXNoW2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYXNoO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9BcnJheSgpIHtcbiAgICByZXR1cm4gdGhpcy5zcGxpdCgnJyk7XG4gIH1cblxuICBmdW5jdGlvbiBzdWNjKCkge1xuICAgIHJldHVybiB0aGlzLnNsaWNlKDAsIHRoaXMubGVuZ3RoIC0gMSkgK1xuICAgICAgU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLmNoYXJDb2RlQXQodGhpcy5sZW5ndGggLSAxKSArIDEpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXMoY291bnQpIHtcbiAgICByZXR1cm4gY291bnQgPCAxID8gJycgOiBuZXcgQXJyYXkoY291bnQgKyAxKS5qb2luKHRoaXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FtZWxpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZSgvLSsoLik/L2csIGZ1bmN0aW9uKG1hdGNoLCBjaHIpIHtcbiAgICAgIHJldHVybiBjaHIgPyBjaHIudG9VcHBlckNhc2UoKSA6ICcnO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FwaXRhbGl6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHRoaXMuc3Vic3RyaW5nKDEpLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICBmdW5jdGlvbiB1bmRlcnNjb3JlKCkge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2UoLzo6L2csICcvJylcbiAgICAgICAgICAgICAgIC5yZXBsYWNlKC8oW0EtWl0rKShbQS1aXVthLXpdKS9nLCAnJDFfJDInKVxuICAgICAgICAgICAgICAgLnJlcGxhY2UoLyhbYS16XFxkXSkoW0EtWl0pL2csICckMV8kMicpXG4gICAgICAgICAgICAgICAucmVwbGFjZSgvLS9nLCAnXycpXG4gICAgICAgICAgICAgICAudG9Mb3dlckNhc2UoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRhc2hlcml6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5yZXBsYWNlKC9fL2csICctJyk7XG4gIH1cblxuICBmdW5jdGlvbiBpbnNwZWN0KHVzZURvdWJsZVF1b3Rlcykge1xuICAgIHZhciBlc2NhcGVkU3RyaW5nID0gdGhpcy5yZXBsYWNlKC9bXFx4MDAtXFx4MWZcXFxcXS9nLCBmdW5jdGlvbihjaGFyYWN0ZXIpIHtcbiAgICAgIGlmIChjaGFyYWN0ZXIgaW4gU3RyaW5nLnNwZWNpYWxDaGFyKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcuc3BlY2lhbENoYXJbY2hhcmFjdGVyXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAnXFxcXHUwMCcgKyBjaGFyYWN0ZXIuY2hhckNvZGVBdCgpLnRvUGFkZGVkU3RyaW5nKDIsIDE2KTtcbiAgICB9KTtcbiAgICBpZiAodXNlRG91YmxlUXVvdGVzKSByZXR1cm4gJ1wiJyArIGVzY2FwZWRTdHJpbmcucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpICsgJ1wiJztcbiAgICByZXR1cm4gXCInXCIgKyBlc2NhcGVkU3RyaW5nLnJlcGxhY2UoLycvZywgJ1xcXFxcXCcnKSArIFwiJ1wiO1xuICB9XG5cbiAgZnVuY3Rpb24gdW5maWx0ZXJKU09OKGZpbHRlcikge1xuICAgIHJldHVybiB0aGlzLnJlcGxhY2UoZmlsdGVyIHx8IFByb3RvdHlwZS5KU09ORmlsdGVyLCAnJDEnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSlNPTigpIHtcbiAgICB2YXIgc3RyID0gdGhpcztcbiAgICBpZiAoc3RyLmJsYW5rKCkpIHJldHVybiBmYWxzZTtcbiAgICBzdHIgPSBzdHIucmVwbGFjZSgvXFxcXCg/OltcIlxcXFxcXC9iZm5ydF18dVswLTlhLWZBLUZdezR9KS9nLCAnQCcpO1xuICAgIHN0ciA9IHN0ci5yZXBsYWNlKC9cIlteXCJcXFxcXFxuXFxyXSpcInx0cnVlfGZhbHNlfG51bGx8LT9cXGQrKD86XFwuXFxkKik/KD86W2VFXVsrXFwtXT9cXGQrKT8vZywgJ10nKTtcbiAgICBzdHIgPSBzdHIucmVwbGFjZSgvKD86Xnw6fCwpKD86XFxzKlxcWykrL2csICcnKTtcbiAgICByZXR1cm4gKC9eW1xcXSw6e31cXHNdKiQvKS50ZXN0KHN0cik7XG4gIH1cblxuICBmdW5jdGlvbiBldmFsSlNPTihzYW5pdGl6ZSkge1xuICAgIHZhciBqc29uID0gdGhpcy51bmZpbHRlckpTT04oKSxcbiAgICAgICAgY3ggPSAvW1xcdTAwMDBcXHUwMGFkXFx1MDYwMC1cXHUwNjA0XFx1MDcwZlxcdTE3YjRcXHUxN2I1XFx1MjAwYy1cXHUyMDBmXFx1MjAyOC1cXHUyMDJmXFx1MjA2MC1cXHUyMDZmXFx1ZmVmZlxcdWZmZjAtXFx1ZmZmZl0vZztcbiAgICBpZiAoY3gudGVzdChqc29uKSkge1xuICAgICAganNvbiA9IGpzb24ucmVwbGFjZShjeCwgZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgcmV0dXJuICdcXFxcdScgKyAoJzAwMDAnICsgYS5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KSkuc2xpY2UoLTQpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBpZiAoIXNhbml0aXplIHx8IGpzb24uaXNKU09OKCkpIHJldHVybiBldmFsKCcoJyArIGpzb24gKyAnKScpO1xuICAgIH0gY2F0Y2ggKGUpIHsgfVxuICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignQmFkbHkgZm9ybWVkIEpTT04gc3RyaW5nOiAnICsgdGhpcy5pbnNwZWN0KCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VKU09OKCkge1xuICAgIHZhciBqc29uID0gdGhpcy51bmZpbHRlckpTT04oKTtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShqc29uKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluY2x1ZGUocGF0dGVybikge1xuICAgIHJldHVybiB0aGlzLmluZGV4T2YocGF0dGVybikgPiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0YXJ0c1dpdGgocGF0dGVybiwgcG9zaXRpb24pIHtcbiAgICBwb3NpdGlvbiA9IE9iamVjdC5pc051bWJlcihwb3NpdGlvbikgPyBwb3NpdGlvbiA6IDA7XG4gICAgcmV0dXJuIHRoaXMubGFzdEluZGV4T2YocGF0dGVybiwgcG9zaXRpb24pID09PSBwb3NpdGlvbjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZHNXaXRoKHBhdHRlcm4sIHBvc2l0aW9uKSB7XG4gICAgcGF0dGVybiA9IFN0cmluZyhwYXR0ZXJuKTtcbiAgICBwb3NpdGlvbiA9IE9iamVjdC5pc051bWJlcihwb3NpdGlvbikgPyBwb3NpdGlvbiA6IHRoaXMubGVuZ3RoO1xuICAgIGlmIChwb3NpdGlvbiA8IDApIHBvc2l0aW9uID0gMDtcbiAgICBpZiAocG9zaXRpb24gPiB0aGlzLmxlbmd0aCkgcG9zaXRpb24gPSB0aGlzLmxlbmd0aDtcbiAgICB2YXIgZCA9IHBvc2l0aW9uIC0gcGF0dGVybi5sZW5ndGg7XG4gICAgcmV0dXJuIGQgPj0gMCAmJiB0aGlzLmluZGV4T2YocGF0dGVybiwgZCkgPT09IGQ7XG4gIH1cblxuICBmdW5jdGlvbiBlbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcyA9PSAnJztcbiAgfVxuXG4gIGZ1bmN0aW9uIGJsYW5rKCkge1xuICAgIHJldHVybiAvXlxccyokLy50ZXN0KHRoaXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gaW50ZXJwb2xhdGUob2JqZWN0LCBwYXR0ZXJuKSB7XG4gICAgcmV0dXJuIG5ldyBUZW1wbGF0ZSh0aGlzLCBwYXR0ZXJuKS5ldmFsdWF0ZShvYmplY3QpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBnc3ViOiAgICAgICAgICAgZ3N1YixcbiAgICBzdWI6ICAgICAgICAgICAgc3ViLFxuICAgIHNjYW46ICAgICAgICAgICBzY2FuLFxuICAgIHRydW5jYXRlOiAgICAgICB0cnVuY2F0ZSxcbiAgICBzdHJpcDogICAgICAgICAgU3RyaW5nLnByb3RvdHlwZS50cmltIHx8IHN0cmlwLFxuICAgIHN0cmlwVGFnczogICAgICBzdHJpcFRhZ3MsXG4gICAgc3RyaXBTY3JpcHRzOiAgIHN0cmlwU2NyaXB0cyxcbiAgICBleHRyYWN0U2NyaXB0czogZXh0cmFjdFNjcmlwdHMsXG4gICAgZXZhbFNjcmlwdHM6ICAgIGV2YWxTY3JpcHRzLFxuICAgIGVzY2FwZUhUTUw6ICAgICBlc2NhcGVIVE1MLFxuICAgIHVuZXNjYXBlSFRNTDogICB1bmVzY2FwZUhUTUwsXG4gICAgdG9RdWVyeVBhcmFtczogIHRvUXVlcnlQYXJhbXMsXG4gICAgcGFyc2VRdWVyeTogICAgIHRvUXVlcnlQYXJhbXMsXG4gICAgdG9BcnJheTogICAgICAgIHRvQXJyYXksXG4gICAgc3VjYzogICAgICAgICAgIHN1Y2MsXG4gICAgdGltZXM6ICAgICAgICAgIHRpbWVzLFxuICAgIGNhbWVsaXplOiAgICAgICBjYW1lbGl6ZSxcbiAgICBjYXBpdGFsaXplOiAgICAgY2FwaXRhbGl6ZSxcbiAgICB1bmRlcnNjb3JlOiAgICAgdW5kZXJzY29yZSxcbiAgICBkYXNoZXJpemU6ICAgICAgZGFzaGVyaXplLFxuICAgIGluc3BlY3Q6ICAgICAgICBpbnNwZWN0LFxuICAgIHVuZmlsdGVySlNPTjogICB1bmZpbHRlckpTT04sXG4gICAgaXNKU09OOiAgICAgICAgIGlzSlNPTixcbiAgICBldmFsSlNPTjogICAgICAgTkFUSVZFX0pTT05fUEFSU0VfU1VQUE9SVCA/IHBhcnNlSlNPTiA6IGV2YWxKU09OLFxuICAgIGluY2x1ZGU6ICAgICAgICBpbmNsdWRlLFxuICAgIHN0YXJ0c1dpdGg6ICAgICBTdHJpbmcucHJvdG90eXBlLnN0YXJ0c1dpdGggfHwgc3RhcnRzV2l0aCxcbiAgICBlbmRzV2l0aDogICAgICAgU3RyaW5nLnByb3RvdHlwZS5lbmRzV2l0aCB8fCBlbmRzV2l0aCxcbiAgICBlbXB0eTogICAgICAgICAgZW1wdHksXG4gICAgYmxhbms6ICAgICAgICAgIGJsYW5rLFxuICAgIGludGVycG9sYXRlOiAgICBpbnRlcnBvbGF0ZVxuICB9O1xufSkoKSk7XG5cbnZhciBUZW1wbGF0ZSA9IENsYXNzLmNyZWF0ZSh7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKHRlbXBsYXRlLCBwYXR0ZXJuKSB7XG4gICAgdGhpcy50ZW1wbGF0ZSA9IHRlbXBsYXRlLnRvU3RyaW5nKCk7XG4gICAgdGhpcy5wYXR0ZXJuID0gcGF0dGVybiB8fCBUZW1wbGF0ZS5QYXR0ZXJuO1xuICB9LFxuXG4gIGV2YWx1YXRlOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0ICYmIE9iamVjdC5pc0Z1bmN0aW9uKG9iamVjdC50b1RlbXBsYXRlUmVwbGFjZW1lbnRzKSlcbiAgICAgIG9iamVjdCA9IG9iamVjdC50b1RlbXBsYXRlUmVwbGFjZW1lbnRzKCk7XG5cbiAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZS5nc3ViKHRoaXMucGF0dGVybiwgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkgcmV0dXJuIChtYXRjaFsxXSArICcnKTtcblxuICAgICAgdmFyIGJlZm9yZSA9IG1hdGNoWzFdIHx8ICcnO1xuICAgICAgaWYgKGJlZm9yZSA9PSAnXFxcXCcpIHJldHVybiBtYXRjaFsyXTtcblxuICAgICAgdmFyIGN0eCA9IG9iamVjdCwgZXhwciA9IG1hdGNoWzNdLFxuICAgICAgICAgIHBhdHRlcm4gPSAvXihbXi5bXSt8XFxbKCg/Oi4qP1teXFxcXF0pPylcXF0pKFxcLnxcXFt8JCkvO1xuXG4gICAgICBtYXRjaCA9IHBhdHRlcm4uZXhlYyhleHByKTtcbiAgICAgIGlmIChtYXRjaCA9PSBudWxsKSByZXR1cm4gYmVmb3JlO1xuXG4gICAgICB3aGlsZSAobWF0Y2ggIT0gbnVsbCkge1xuICAgICAgICB2YXIgY29tcCA9IG1hdGNoWzFdLnN0YXJ0c1dpdGgoJ1snKSA/IG1hdGNoWzJdLnJlcGxhY2UoL1xcXFxcXFxcXS9nLCAnXScpIDogbWF0Y2hbMV07XG4gICAgICAgIGN0eCA9IGN0eFtjb21wXTtcbiAgICAgICAgaWYgKG51bGwgPT0gY3R4IHx8ICcnID09IG1hdGNoWzNdKSBicmVhaztcbiAgICAgICAgZXhwciA9IGV4cHIuc3Vic3RyaW5nKCdbJyA9PSBtYXRjaFszXSA/IG1hdGNoWzFdLmxlbmd0aCA6IG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgIG1hdGNoID0gcGF0dGVybi5leGVjKGV4cHIpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYmVmb3JlICsgU3RyaW5nLmludGVycHJldChjdHgpO1xuICAgIH0pO1xuICB9XG59KTtcblRlbXBsYXRlLlBhdHRlcm4gPSAvKF58LnxcXHJ8XFxuKSgjXFx7KC4qPylcXH0pLztcblxudmFyICRicmVhayA9IHsgfTtcblxudmFyIEVudW1lcmFibGUgPSAoZnVuY3Rpb24oKSB7XG4gIGZ1bmN0aW9uIGVhY2goaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5fZWFjaChpdGVyYXRvciwgY29udGV4dCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUgIT0gJGJyZWFrKSB0aHJvdyBlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGZ1bmN0aW9uIGVhY2hTbGljZShudW1iZXIsIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgdmFyIGluZGV4ID0gLW51bWJlciwgc2xpY2VzID0gW10sIGFycmF5ID0gdGhpcy50b0FycmF5KCk7XG4gICAgaWYgKG51bWJlciA8IDEpIHJldHVybiBhcnJheTtcbiAgICB3aGlsZSAoKGluZGV4ICs9IG51bWJlcikgPCBhcnJheS5sZW5ndGgpXG4gICAgICBzbGljZXMucHVzaChhcnJheS5zbGljZShpbmRleCwgaW5kZXgrbnVtYmVyKSk7XG4gICAgcmV0dXJuIHNsaWNlcy5jb2xsZWN0KGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFsbChpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG4gICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgcmVzdWx0ID0gcmVzdWx0ICYmICEhaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIHRoaXMpO1xuICAgICAgaWYgKCFyZXN1bHQpIHRocm93ICRicmVhaztcbiAgICB9LCB0aGlzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gYW55KGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0b3IgPSBpdGVyYXRvciB8fCBQcm90b3R5cGUuSztcbiAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgaWYgKHJlc3VsdCA9ICEhaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIHRoaXMpKVxuICAgICAgICB0aHJvdyAkYnJlYWs7XG4gICAgfSwgdGhpcyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbGxlY3QoaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRvciA9IGl0ZXJhdG9yIHx8IFByb3RvdHlwZS5LO1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgcmVzdWx0cy5wdXNoKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCB0aGlzKSk7XG4gICAgfSwgdGhpcyk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBmdW5jdGlvbiBkZXRlY3QoaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0O1xuICAgIHRoaXMuZWFjaChmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGlmIChpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgdGhpcykpIHtcbiAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIHRocm93ICRicmVhaztcbiAgICAgIH1cbiAgICB9LCB0aGlzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gZmluZEFsbChpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCB0aGlzKSlcbiAgICAgICAgcmVzdWx0cy5wdXNoKHZhbHVlKTtcbiAgICB9LCB0aGlzKTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIGdyZXAoZmlsdGVyLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcblxuICAgIGlmIChPYmplY3QuaXNTdHJpbmcoZmlsdGVyKSlcbiAgICAgIGZpbHRlciA9IG5ldyBSZWdFeHAoUmVnRXhwLmVzY2FwZShmaWx0ZXIpKTtcblxuICAgIHRoaXMuZWFjaChmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGlmIChmaWx0ZXIubWF0Y2godmFsdWUpKVxuICAgICAgICByZXN1bHRzLnB1c2goaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIHRoaXMpKTtcbiAgICB9LCB0aGlzKTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIGluY2x1ZGUob2JqZWN0KSB7XG4gICAgaWYgKE9iamVjdC5pc0Z1bmN0aW9uKHRoaXMuaW5kZXhPZikgJiYgdGhpcy5pbmRleE9mKG9iamVjdCkgIT0gLTEpXG4gICAgICByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBmb3VuZCA9IGZhbHNlO1xuICAgIHRoaXMuZWFjaChmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09IG9iamVjdCkge1xuICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgIHRocm93ICRicmVhaztcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gZm91bmQ7XG4gIH1cblxuICBmdW5jdGlvbiBpbkdyb3Vwc09mKG51bWJlciwgZmlsbFdpdGgpIHtcbiAgICBmaWxsV2l0aCA9IE9iamVjdC5pc1VuZGVmaW5lZChmaWxsV2l0aCkgPyBudWxsIDogZmlsbFdpdGg7XG4gICAgcmV0dXJuIHRoaXMuZWFjaFNsaWNlKG51bWJlciwgZnVuY3Rpb24oc2xpY2UpIHtcbiAgICAgIHdoaWxlKHNsaWNlLmxlbmd0aCA8IG51bWJlcikgc2xpY2UucHVzaChmaWxsV2l0aCk7XG4gICAgICByZXR1cm4gc2xpY2U7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbmplY3QobWVtbywgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB0aGlzLmVhY2goZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBtZW1vID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBtZW1vLCB2YWx1ZSwgaW5kZXgsIHRoaXMpO1xuICAgIH0sIHRoaXMpO1xuICAgIHJldHVybiBtZW1vO1xuICB9XG5cbiAgZnVuY3Rpb24gaW52b2tlKG1ldGhvZCkge1xuICAgIHZhciBhcmdzID0gJEEoYXJndW1lbnRzKS5zbGljZSgxKTtcbiAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZVttZXRob2RdLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1heChpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG4gICAgdmFyIHJlc3VsdDtcbiAgICB0aGlzLmVhY2goZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICB2YWx1ZSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCB0aGlzKTtcbiAgICAgIGlmIChyZXN1bHQgPT0gbnVsbCB8fCB2YWx1ZSA+PSByZXN1bHQpXG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgIH0sIHRoaXMpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBtaW4oaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRvciA9IGl0ZXJhdG9yIHx8IFByb3RvdHlwZS5LO1xuICAgIHZhciByZXN1bHQ7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgdmFsdWUgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgdGhpcyk7XG4gICAgICBpZiAocmVzdWx0ID09IG51bGwgfHwgdmFsdWUgPCByZXN1bHQpXG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgIH0sIHRoaXMpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJ0aXRpb24oaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRvciA9IGl0ZXJhdG9yIHx8IFByb3RvdHlwZS5LO1xuICAgIHZhciB0cnVlcyA9IFtdLCBmYWxzZXMgPSBbXTtcbiAgICB0aGlzLmVhY2goZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIHRoaXMpID9cbiAgICAgICAgdHJ1ZXMgOiBmYWxzZXMpLnB1c2godmFsdWUpO1xuICAgIH0sIHRoaXMpO1xuICAgIHJldHVybiBbdHJ1ZXMsIGZhbHNlc107XG4gIH1cblxuICBmdW5jdGlvbiBwbHVjayhwcm9wZXJ0eSkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXN1bHRzLnB1c2godmFsdWVbcHJvcGVydHldKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlamVjdChpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgaWYgKCFpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgdGhpcykpXG4gICAgICAgIHJlc3VsdHMucHVzaCh2YWx1ZSk7XG4gICAgfSwgdGhpcyk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBmdW5jdGlvbiBzb3J0QnkoaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGNyaXRlcmlhOiBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgdGhpcylcbiAgICAgIH07XG4gICAgfSwgdGhpcykuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICAgICAgdmFyIGEgPSBsZWZ0LmNyaXRlcmlhLCBiID0gcmlnaHQuY3JpdGVyaWE7XG4gICAgICByZXR1cm4gYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IDA7XG4gICAgfSkucGx1Y2soJ3ZhbHVlJyk7XG4gIH1cblxuICBmdW5jdGlvbiB0b0FycmF5KCkge1xuICAgIHJldHVybiB0aGlzLm1hcCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gemlwKCkge1xuICAgIHZhciBpdGVyYXRvciA9IFByb3RvdHlwZS5LLCBhcmdzID0gJEEoYXJndW1lbnRzKTtcbiAgICBpZiAoT2JqZWN0LmlzRnVuY3Rpb24oYXJncy5sYXN0KCkpKVxuICAgICAgaXRlcmF0b3IgPSBhcmdzLnBvcCgpO1xuXG4gICAgdmFyIGNvbGxlY3Rpb25zID0gW3RoaXNdLmNvbmNhdChhcmdzKS5tYXAoJEEpO1xuICAgIHJldHVybiB0aGlzLm1hcChmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIHJldHVybiBpdGVyYXRvcihjb2xsZWN0aW9ucy5wbHVjayhpbmRleCkpO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gc2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy50b0FycmF5KCkubGVuZ3RoO1xuICB9XG5cbiAgZnVuY3Rpb24gaW5zcGVjdCgpIHtcbiAgICByZXR1cm4gJyM8RW51bWVyYWJsZTonICsgdGhpcy50b0FycmF5KCkuaW5zcGVjdCgpICsgJz4nO1xuICB9XG5cblxuXG5cblxuXG5cblxuXG4gIHJldHVybiB7XG4gICAgZWFjaDogICAgICAgZWFjaCxcbiAgICBlYWNoU2xpY2U6ICBlYWNoU2xpY2UsXG4gICAgYWxsOiAgICAgICAgYWxsLFxuICAgIGV2ZXJ5OiAgICAgIGFsbCxcbiAgICBhbnk6ICAgICAgICBhbnksXG4gICAgc29tZTogICAgICAgYW55LFxuICAgIGNvbGxlY3Q6ICAgIGNvbGxlY3QsXG4gICAgbWFwOiAgICAgICAgY29sbGVjdCxcbiAgICBkZXRlY3Q6ICAgICBkZXRlY3QsXG4gICAgZmluZEFsbDogICAgZmluZEFsbCxcbiAgICBzZWxlY3Q6ICAgICBmaW5kQWxsLFxuICAgIGZpbHRlcjogICAgIGZpbmRBbGwsXG4gICAgZ3JlcDogICAgICAgZ3JlcCxcbiAgICBpbmNsdWRlOiAgICBpbmNsdWRlLFxuICAgIG1lbWJlcjogICAgIGluY2x1ZGUsXG4gICAgaW5Hcm91cHNPZjogaW5Hcm91cHNPZixcbiAgICBpbmplY3Q6ICAgICBpbmplY3QsXG4gICAgaW52b2tlOiAgICAgaW52b2tlLFxuICAgIG1heDogICAgICAgIG1heCxcbiAgICBtaW46ICAgICAgICBtaW4sXG4gICAgcGFydGl0aW9uOiAgcGFydGl0aW9uLFxuICAgIHBsdWNrOiAgICAgIHBsdWNrLFxuICAgIHJlamVjdDogICAgIHJlamVjdCxcbiAgICBzb3J0Qnk6ICAgICBzb3J0QnksXG4gICAgdG9BcnJheTogICAgdG9BcnJheSxcbiAgICBlbnRyaWVzOiAgICB0b0FycmF5LFxuICAgIHppcDogICAgICAgIHppcCxcbiAgICBzaXplOiAgICAgICBzaXplLFxuICAgIGluc3BlY3Q6ICAgIGluc3BlY3QsXG4gICAgZmluZDogICAgICAgZGV0ZWN0XG4gIH07XG59KSgpO1xuXG5mdW5jdGlvbiAkQShpdGVyYWJsZSkge1xuICBpZiAoIWl0ZXJhYmxlKSByZXR1cm4gW107XG4gIGlmICgndG9BcnJheScgaW4gT2JqZWN0KGl0ZXJhYmxlKSkgcmV0dXJuIGl0ZXJhYmxlLnRvQXJyYXkoKTtcbiAgdmFyIGxlbmd0aCA9IGl0ZXJhYmxlLmxlbmd0aCB8fCAwLCByZXN1bHRzID0gbmV3IEFycmF5KGxlbmd0aCk7XG4gIHdoaWxlIChsZW5ndGgtLSkgcmVzdWx0c1tsZW5ndGhdID0gaXRlcmFibGVbbGVuZ3RoXTtcbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cblxuZnVuY3Rpb24gJHcoc3RyaW5nKSB7XG4gIGlmICghT2JqZWN0LmlzU3RyaW5nKHN0cmluZykpIHJldHVybiBbXTtcbiAgc3RyaW5nID0gc3RyaW5nLnN0cmlwKCk7XG4gIHJldHVybiBzdHJpbmcgPyBzdHJpbmcuc3BsaXQoL1xccysvKSA6IFtdO1xufVxuXG5BcnJheS5mcm9tID0gJEE7XG5cblxuKGZ1bmN0aW9uKCkge1xuICB2YXIgYXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZSxcbiAgICAgIHNsaWNlID0gYXJyYXlQcm90by5zbGljZSxcbiAgICAgIF9lYWNoID0gYXJyYXlQcm90by5mb3JFYWNoOyAvLyB1c2UgbmF0aXZlIGJyb3dzZXIgSlMgMS42IGltcGxlbWVudGF0aW9uIGlmIGF2YWlsYWJsZVxuXG4gIGZ1bmN0aW9uIGVhY2goaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gdGhpcy5sZW5ndGggPj4+IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGkgaW4gdGhpcykgaXRlcmF0b3IuY2FsbChjb250ZXh0LCB0aGlzW2ldLCBpLCB0aGlzKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFfZWFjaCkgX2VhY2ggPSBlYWNoO1xuXG4gIGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpcnN0KCkge1xuICAgIHJldHVybiB0aGlzWzBdO1xuICB9XG5cbiAgZnVuY3Rpb24gbGFzdCgpIHtcbiAgICByZXR1cm4gdGhpc1t0aGlzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgZnVuY3Rpb24gY29tcGFjdCgpIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3QoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZmxhdHRlbigpIHtcbiAgICByZXR1cm4gdGhpcy5pbmplY3QoW10sIGZ1bmN0aW9uKGFycmF5LCB2YWx1ZSkge1xuICAgICAgaWYgKE9iamVjdC5pc0FycmF5KHZhbHVlKSlcbiAgICAgICAgcmV0dXJuIGFycmF5LmNvbmNhdCh2YWx1ZS5mbGF0dGVuKCkpO1xuICAgICAgYXJyYXkucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB3aXRob3V0KCkge1xuICAgIHZhciB2YWx1ZXMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0KGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gIXZhbHVlcy5pbmNsdWRlKHZhbHVlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJldmVyc2UoaW5saW5lKSB7XG4gICAgcmV0dXJuIChpbmxpbmUgPT09IGZhbHNlID8gdGhpcy50b0FycmF5KCkgOiB0aGlzKS5fcmV2ZXJzZSgpO1xuICB9XG5cbiAgZnVuY3Rpb24gdW5pcShzb3J0ZWQpIHtcbiAgICByZXR1cm4gdGhpcy5pbmplY3QoW10sIGZ1bmN0aW9uKGFycmF5LCB2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGlmICgwID09IGluZGV4IHx8IChzb3J0ZWQgPyBhcnJheS5sYXN0KCkgIT0gdmFsdWUgOiAhYXJyYXkuaW5jbHVkZSh2YWx1ZSkpKVxuICAgICAgICBhcnJheS5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGludGVyc2VjdChhcnJheSkge1xuICAgIHJldHVybiB0aGlzLnVuaXEoKS5maW5kQWxsKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgIHJldHVybiBhcnJheS5pbmRleE9mKGl0ZW0pICE9PSAtMTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gY2xvbmUoKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwodGhpcywgMCk7XG4gIH1cblxuICBmdW5jdGlvbiBzaXplKCkge1xuICAgIHJldHVybiB0aGlzLmxlbmd0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluc3BlY3QoKSB7XG4gICAgcmV0dXJuICdbJyArIHRoaXMubWFwKE9iamVjdC5pbnNwZWN0KS5qb2luKCcsICcpICsgJ10nO1xuICB9XG5cbiAgZnVuY3Rpb24gaW5kZXhPZihpdGVtLCBpKSB7XG4gICAgaWYgKHRoaXMgPT0gbnVsbCkgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuXG4gICAgdmFyIGFycmF5ID0gT2JqZWN0KHRoaXMpLCBsZW5ndGggPSBhcnJheS5sZW5ndGggPj4+IDA7XG4gICAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xO1xuXG4gICAgaSA9IE51bWJlcihpKTtcbiAgICBpZiAoaXNOYU4oaSkpIHtcbiAgICAgIGkgPSAwO1xuICAgIH0gZWxzZSBpZiAoaSAhPT0gMCAmJiBpc0Zpbml0ZShpKSkge1xuICAgICAgaSA9IChpID4gMCA/IDEgOiAtMSkgKiBNYXRoLmZsb29yKE1hdGguYWJzKGkpKTtcbiAgICB9XG5cbiAgICBpZiAoaSA+IGxlbmd0aCkgcmV0dXJuIC0xO1xuXG4gICAgdmFyIGsgPSBpID49IDAgPyBpIDogTWF0aC5tYXgobGVuZ3RoIC0gTWF0aC5hYnMoaSksIDApO1xuICAgIGZvciAoOyBrIDwgbGVuZ3RoOyBrKyspXG4gICAgICBpZiAoayBpbiBhcnJheSAmJiBhcnJheVtrXSA9PT0gaXRlbSkgcmV0dXJuIGs7XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cblxuICBmdW5jdGlvbiBsYXN0SW5kZXhPZihpdGVtLCBpKSB7XG4gICAgaWYgKHRoaXMgPT0gbnVsbCkgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuXG4gICAgdmFyIGFycmF5ID0gT2JqZWN0KHRoaXMpLCBsZW5ndGggPSBhcnJheS5sZW5ndGggPj4+IDA7XG4gICAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xO1xuXG4gICAgaWYgKCFPYmplY3QuaXNVbmRlZmluZWQoaSkpIHtcbiAgICAgIGkgPSBOdW1iZXIoaSk7XG4gICAgICBpZiAoaXNOYU4oaSkpIHtcbiAgICAgICAgaSA9IDA7XG4gICAgICB9IGVsc2UgaWYgKGkgIT09IDAgJiYgaXNGaW5pdGUoaSkpIHtcbiAgICAgICAgaSA9IChpID4gMCA/IDEgOiAtMSkgKiBNYXRoLmZsb29yKE1hdGguYWJzKGkpKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaSA9IGxlbmd0aDtcbiAgICB9XG5cbiAgICB2YXIgayA9IGkgPj0gMCA/IE1hdGgubWluKGksIGxlbmd0aCAtIDEpIDpcbiAgICAgbGVuZ3RoIC0gTWF0aC5hYnMoaSk7XG5cbiAgICBmb3IgKDsgayA+PSAwOyBrLS0pXG4gICAgICBpZiAoayBpbiBhcnJheSAmJiBhcnJheVtrXSA9PT0gaXRlbSkgcmV0dXJuIGs7XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gY29uY2F0KF8pIHtcbiAgICB2YXIgYXJyYXkgPSBbXSwgaXRlbXMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMCksIGl0ZW0sIG4gPSAwO1xuICAgIGl0ZW1zLnVuc2hpZnQodGhpcyk7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGl0ZW1zLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpdGVtID0gaXRlbXNbaV07XG4gICAgICBpZiAoT2JqZWN0LmlzQXJyYXkoaXRlbSkgJiYgISgnY2FsbGVlJyBpbiBpdGVtKSkge1xuICAgICAgICBmb3IgKHZhciBqID0gMCwgYXJyYXlMZW5ndGggPSBpdGVtLmxlbmd0aDsgaiA8IGFycmF5TGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBpZiAoaiBpbiBpdGVtKSBhcnJheVtuXSA9IGl0ZW1bal07XG4gICAgICAgICAgbisrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcnJheVtuKytdID0gaXRlbTtcbiAgICAgIH1cbiAgICB9XG4gICAgYXJyYXkubGVuZ3RoID0gbjtcbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIHdyYXBOYXRpdmUobWV0aG9kKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG1ldGhvZC5jYWxsKHRoaXMsIFByb3RvdHlwZS5LKTtcbiAgICAgIH0gZWxzZSBpZiAoYXJndW1lbnRzWzBdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIGFyZ3MudW5zaGlmdChQcm90b3R5cGUuSyk7XG4gICAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gbWFwKGl0ZXJhdG9yKSB7XG4gICAgaWYgKHRoaXMgPT0gbnVsbCkgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG5cbiAgICB2YXIgb2JqZWN0ID0gT2JqZWN0KHRoaXMpO1xuICAgIHZhciByZXN1bHRzID0gW10sIGNvbnRleHQgPSBhcmd1bWVudHNbMV0sIG4gPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG9iamVjdC5sZW5ndGggPj4+IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGkgaW4gb2JqZWN0KSB7XG4gICAgICAgIHJlc3VsdHNbbl0gPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9iamVjdFtpXSwgaSwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIG4rKztcbiAgICB9XG4gICAgcmVzdWx0cy5sZW5ndGggPSBuO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgaWYgKGFycmF5UHJvdG8ubWFwKSB7XG4gICAgbWFwID0gd3JhcE5hdGl2ZShBcnJheS5wcm90b3R5cGUubWFwKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbHRlcihpdGVyYXRvcikge1xuICAgIGlmICh0aGlzID09IG51bGwgfHwgIU9iamVjdC5pc0Z1bmN0aW9uKGl0ZXJhdG9yKSlcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoKTtcblxuICAgIHZhciBvYmplY3QgPSBPYmplY3QodGhpcyk7XG4gICAgdmFyIHJlc3VsdHMgPSBbXSwgY29udGV4dCA9IGFyZ3VtZW50c1sxXSwgdmFsdWU7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqZWN0Lmxlbmd0aCA+Pj4gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoaSBpbiBvYmplY3QpIHtcbiAgICAgICAgdmFsdWUgPSBvYmplY3RbaV07XG4gICAgICAgIGlmIChpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpLCBvYmplY3QpKSB7XG4gICAgICAgICAgcmVzdWx0cy5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGlmIChhcnJheVByb3RvLmZpbHRlcikge1xuICAgIGZpbHRlciA9IEFycmF5LnByb3RvdHlwZS5maWx0ZXI7XG4gIH1cblxuICBmdW5jdGlvbiBzb21lKGl0ZXJhdG9yKSB7XG4gICAgaWYgKHRoaXMgPT0gbnVsbCkgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG4gICAgdmFyIGNvbnRleHQgPSBhcmd1bWVudHNbMV07XG5cbiAgICB2YXIgb2JqZWN0ID0gT2JqZWN0KHRoaXMpO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmplY3QubGVuZ3RoID4+PiAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChpIGluIG9iamVjdCAmJiBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9iamVjdFtpXSwgaSwgb2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoYXJyYXlQcm90by5zb21lKSB7XG4gICAgdmFyIHNvbWUgPSB3cmFwTmF0aXZlKEFycmF5LnByb3RvdHlwZS5zb21lKTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gZXZlcnkoaXRlcmF0b3IpIHtcbiAgICBpZiAodGhpcyA9PSBudWxsKSB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XG4gICAgaXRlcmF0b3IgPSBpdGVyYXRvciB8fCBQcm90b3R5cGUuSztcbiAgICB2YXIgY29udGV4dCA9IGFyZ3VtZW50c1sxXTtcblxuICAgIHZhciBvYmplY3QgPSBPYmplY3QodGhpcyk7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG9iamVjdC5sZW5ndGggPj4+IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGkgaW4gb2JqZWN0ICYmICFpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9iamVjdFtpXSwgaSwgb2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpZiAoYXJyYXlQcm90by5ldmVyeSkge1xuICAgIHZhciBldmVyeSA9IHdyYXBOYXRpdmUoQXJyYXkucHJvdG90eXBlLmV2ZXJ5KTtcbiAgfVxuXG4gIHZhciBfcmVkdWNlID0gYXJyYXlQcm90by5yZWR1Y2U7XG4gIGZ1bmN0aW9uIGluamVjdChtZW1vLCBpdGVyYXRvcikge1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgfHwgUHJvdG90eXBlLks7XG4gICAgdmFyIGNvbnRleHQgPSBhcmd1bWVudHNbMl07XG4gICAgcmV0dXJuIF9yZWR1Y2UuY2FsbCh0aGlzLCBpdGVyYXRvci5iaW5kKGNvbnRleHQpLCBtZW1vKTtcbiAgfVxuXG4gIGlmICghYXJyYXlQcm90by5yZWR1Y2UpIHtcbiAgICB2YXIgaW5qZWN0ID0gRW51bWVyYWJsZS5pbmplY3Q7XG4gIH1cblxuICBPYmplY3QuZXh0ZW5kKGFycmF5UHJvdG8sIEVudW1lcmFibGUpO1xuXG4gIGlmICghYXJyYXlQcm90by5fcmV2ZXJzZSlcbiAgICBhcnJheVByb3RvLl9yZXZlcnNlID0gYXJyYXlQcm90by5yZXZlcnNlO1xuXG4gIE9iamVjdC5leHRlbmQoYXJyYXlQcm90bywge1xuICAgIF9lYWNoOiAgICAgX2VhY2gsXG5cbiAgICBtYXA6ICAgICAgIG1hcCxcbiAgICBjb2xsZWN0OiAgIG1hcCxcbiAgICBzZWxlY3Q6ICAgIGZpbHRlcixcbiAgICBmaWx0ZXI6ICAgIGZpbHRlcixcbiAgICBmaW5kQWxsOiAgIGZpbHRlcixcbiAgICBzb21lOiAgICAgIHNvbWUsXG4gICAgYW55OiAgICAgICBzb21lLFxuICAgIGV2ZXJ5OiAgICAgZXZlcnksXG4gICAgYWxsOiAgICAgICBldmVyeSxcbiAgICBpbmplY3Q6ICAgIGluamVjdCxcblxuICAgIGNsZWFyOiAgICAgY2xlYXIsXG4gICAgZmlyc3Q6ICAgICBmaXJzdCxcbiAgICBsYXN0OiAgICAgIGxhc3QsXG4gICAgY29tcGFjdDogICBjb21wYWN0LFxuICAgIGZsYXR0ZW46ICAgZmxhdHRlbixcbiAgICB3aXRob3V0OiAgIHdpdGhvdXQsXG4gICAgcmV2ZXJzZTogICByZXZlcnNlLFxuICAgIHVuaXE6ICAgICAgdW5pcSxcbiAgICBpbnRlcnNlY3Q6IGludGVyc2VjdCxcbiAgICBjbG9uZTogICAgIGNsb25lLFxuICAgIHRvQXJyYXk6ICAgY2xvbmUsXG4gICAgc2l6ZTogICAgICBzaXplLFxuICAgIGluc3BlY3Q6ICAgaW5zcGVjdFxuICB9KTtcblxuICB2YXIgQ09OQ0FUX0FSR1VNRU5UU19CVUdHWSA9IChmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gW10uY29uY2F0KGFyZ3VtZW50cylbMF1bMF0gIT09IDE7XG4gIH0pKDEsMik7XG5cbiAgaWYgKENPTkNBVF9BUkdVTUVOVFNfQlVHR1kpIGFycmF5UHJvdG8uY29uY2F0ID0gY29uY2F0O1xuXG4gIGlmICghYXJyYXlQcm90by5pbmRleE9mKSBhcnJheVByb3RvLmluZGV4T2YgPSBpbmRleE9mO1xuICBpZiAoIWFycmF5UHJvdG8ubGFzdEluZGV4T2YpIGFycmF5UHJvdG8ubGFzdEluZGV4T2YgPSBsYXN0SW5kZXhPZjtcbn0pKCk7XG5mdW5jdGlvbiAkSChvYmplY3QpIHtcbiAgcmV0dXJuIG5ldyBIYXNoKG9iamVjdCk7XG59O1xuXG52YXIgSGFzaCA9IENsYXNzLmNyZWF0ZShFbnVtZXJhYmxlLCAoZnVuY3Rpb24oKSB7XG4gIGZ1bmN0aW9uIGluaXRpYWxpemUob2JqZWN0KSB7XG4gICAgdGhpcy5fb2JqZWN0ID0gT2JqZWN0LmlzSGFzaChvYmplY3QpID8gb2JqZWN0LnRvT2JqZWN0KCkgOiBPYmplY3QuY2xvbmUob2JqZWN0KTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gX2VhY2goaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgaSA9IDA7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuX29iamVjdCkge1xuICAgICAgdmFyIHZhbHVlID0gdGhpcy5fb2JqZWN0W2tleV0sIHBhaXIgPSBba2V5LCB2YWx1ZV07XG4gICAgICBwYWlyLmtleSA9IGtleTtcbiAgICAgIHBhaXIudmFsdWUgPSB2YWx1ZTtcbiAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgcGFpciwgaSk7XG4gICAgICBpKys7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5fb2JqZWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldChrZXkpIHtcbiAgICBpZiAodGhpcy5fb2JqZWN0W2tleV0gIT09IE9iamVjdC5wcm90b3R5cGVba2V5XSlcbiAgICAgIHJldHVybiB0aGlzLl9vYmplY3Rba2V5XTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVuc2V0KGtleSkge1xuICAgIHZhciB2YWx1ZSA9IHRoaXMuX29iamVjdFtrZXldO1xuICAgIGRlbGV0ZSB0aGlzLl9vYmplY3Rba2V5XTtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiB0b09iamVjdCgpIHtcbiAgICByZXR1cm4gT2JqZWN0LmNsb25lKHRoaXMuX29iamVjdCk7XG4gIH1cblxuXG5cbiAgZnVuY3Rpb24ga2V5cygpIHtcbiAgICByZXR1cm4gdGhpcy5wbHVjaygna2V5Jyk7XG4gIH1cblxuICBmdW5jdGlvbiB2YWx1ZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMucGx1Y2soJ3ZhbHVlJyk7XG4gIH1cblxuICBmdW5jdGlvbiBpbmRleCh2YWx1ZSkge1xuICAgIHZhciBtYXRjaCA9IHRoaXMuZGV0ZWN0KGZ1bmN0aW9uKHBhaXIpIHtcbiAgICAgIHJldHVybiBwYWlyLnZhbHVlID09PSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gbWF0Y2ggJiYgbWF0Y2gua2V5O1xuICB9XG5cbiAgZnVuY3Rpb24gbWVyZ2Uob2JqZWN0KSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS51cGRhdGUob2JqZWN0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVwZGF0ZShvYmplY3QpIHtcbiAgICByZXR1cm4gbmV3IEhhc2gob2JqZWN0KS5pbmplY3QodGhpcywgZnVuY3Rpb24ocmVzdWx0LCBwYWlyKSB7XG4gICAgICByZXN1bHQuc2V0KHBhaXIua2V5LCBwYWlyLnZhbHVlKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB0b1F1ZXJ5UGFpcihrZXksIHZhbHVlKSB7XG4gICAgaWYgKE9iamVjdC5pc1VuZGVmaW5lZCh2YWx1ZSkpIHJldHVybiBrZXk7XG5cbiAgICB2YWx1ZSA9IFN0cmluZy5pbnRlcnByZXQodmFsdWUpO1xuXG4gICAgdmFsdWUgPSB2YWx1ZS5nc3ViKC8oXFxyKT9cXG4vLCAnXFxyXFxuJyk7XG4gICAgdmFsdWUgPSBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgIHZhbHVlID0gdmFsdWUuZ3N1YigvJTIwLywgJysnKTtcbiAgICByZXR1cm4ga2V5ICsgJz0nICsgdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiB0b1F1ZXJ5U3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmluamVjdChbXSwgZnVuY3Rpb24ocmVzdWx0cywgcGFpcikge1xuICAgICAgdmFyIGtleSA9IGVuY29kZVVSSUNvbXBvbmVudChwYWlyLmtleSksIHZhbHVlcyA9IHBhaXIudmFsdWU7XG5cbiAgICAgIGlmICh2YWx1ZXMgJiYgdHlwZW9mIHZhbHVlcyA9PSAnb2JqZWN0Jykge1xuICAgICAgICBpZiAoT2JqZWN0LmlzQXJyYXkodmFsdWVzKSkge1xuICAgICAgICAgIHZhciBxdWVyeVZhbHVlcyA9IFtdO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSB2YWx1ZXMubGVuZ3RoLCB2YWx1ZTsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlc1tpXTtcbiAgICAgICAgICAgIHF1ZXJ5VmFsdWVzLnB1c2godG9RdWVyeVBhaXIoa2V5LCB2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0cy5jb25jYXQocXVlcnlWYWx1ZXMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgcmVzdWx0cy5wdXNoKHRvUXVlcnlQYWlyKGtleSwgdmFsdWVzKSk7XG4gICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9KS5qb2luKCcmJyk7XG4gIH1cblxuICBmdW5jdGlvbiBpbnNwZWN0KCkge1xuICAgIHJldHVybiAnIzxIYXNoOnsnICsgdGhpcy5tYXAoZnVuY3Rpb24ocGFpcikge1xuICAgICAgcmV0dXJuIHBhaXIubWFwKE9iamVjdC5pbnNwZWN0KS5qb2luKCc6ICcpO1xuICAgIH0pLmpvaW4oJywgJykgKyAnfT4nO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmUoKSB7XG4gICAgcmV0dXJuIG5ldyBIYXNoKHRoaXMpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBpbml0aWFsaXplOiAgICAgICAgICAgICBpbml0aWFsaXplLFxuICAgIF9lYWNoOiAgICAgICAgICAgICAgICAgIF9lYWNoLFxuICAgIHNldDogICAgICAgICAgICAgICAgICAgIHNldCxcbiAgICBnZXQ6ICAgICAgICAgICAgICAgICAgICBnZXQsXG4gICAgdW5zZXQ6ICAgICAgICAgICAgICAgICAgdW5zZXQsXG4gICAgdG9PYmplY3Q6ICAgICAgICAgICAgICAgdG9PYmplY3QsXG4gICAgdG9UZW1wbGF0ZVJlcGxhY2VtZW50czogdG9PYmplY3QsXG4gICAga2V5czogICAgICAgICAgICAgICAgICAga2V5cyxcbiAgICB2YWx1ZXM6ICAgICAgICAgICAgICAgICB2YWx1ZXMsXG4gICAgaW5kZXg6ICAgICAgICAgICAgICAgICAgaW5kZXgsXG4gICAgbWVyZ2U6ICAgICAgICAgICAgICAgICAgbWVyZ2UsXG4gICAgdXBkYXRlOiAgICAgICAgICAgICAgICAgdXBkYXRlLFxuICAgIHRvUXVlcnlTdHJpbmc6ICAgICAgICAgIHRvUXVlcnlTdHJpbmcsXG4gICAgaW5zcGVjdDogICAgICAgICAgICAgICAgaW5zcGVjdCxcbiAgICB0b0pTT046ICAgICAgICAgICAgICAgICB0b09iamVjdCxcbiAgICBjbG9uZTogICAgICAgICAgICAgICAgICBjbG9uZVxuICB9O1xufSkoKSk7XG5cbkhhc2guZnJvbSA9ICRIO1xuT2JqZWN0LmV4dGVuZChOdW1iZXIucHJvdG90eXBlLCAoZnVuY3Rpb24oKSB7XG4gIGZ1bmN0aW9uIHRvQ29sb3JQYXJ0KCkge1xuICAgIHJldHVybiB0aGlzLnRvUGFkZGVkU3RyaW5nKDIsIDE2KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN1Y2MoKSB7XG4gICAgcmV0dXJuIHRoaXMgKyAxO1xuICB9XG5cbiAgZnVuY3Rpb24gdGltZXMoaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICAkUigwLCB0aGlzLCB0cnVlKS5lYWNoKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGZ1bmN0aW9uIHRvUGFkZGVkU3RyaW5nKGxlbmd0aCwgcmFkaXgpIHtcbiAgICB2YXIgc3RyaW5nID0gdGhpcy50b1N0cmluZyhyYWRpeCB8fCAxMCk7XG4gICAgcmV0dXJuICcwJy50aW1lcyhsZW5ndGggLSBzdHJpbmcubGVuZ3RoKSArIHN0cmluZztcbiAgfVxuXG4gIGZ1bmN0aW9uIGFicygpIHtcbiAgICByZXR1cm4gTWF0aC5hYnModGhpcyk7XG4gIH1cblxuICBmdW5jdGlvbiByb3VuZCgpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCh0aGlzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNlaWwoKSB7XG4gICAgcmV0dXJuIE1hdGguY2VpbCh0aGlzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsb29yKCkge1xuICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0b0NvbG9yUGFydDogICAgdG9Db2xvclBhcnQsXG4gICAgc3VjYzogICAgICAgICAgIHN1Y2MsXG4gICAgdGltZXM6ICAgICAgICAgIHRpbWVzLFxuICAgIHRvUGFkZGVkU3RyaW5nOiB0b1BhZGRlZFN0cmluZyxcbiAgICBhYnM6ICAgICAgICAgICAgYWJzLFxuICAgIHJvdW5kOiAgICAgICAgICByb3VuZCxcbiAgICBjZWlsOiAgICAgICAgICAgY2VpbCxcbiAgICBmbG9vcjogICAgICAgICAgZmxvb3JcbiAgfTtcbn0pKCkpO1xuXG5mdW5jdGlvbiAkUihzdGFydCwgZW5kLCBleGNsdXNpdmUpIHtcbiAgcmV0dXJuIG5ldyBPYmplY3RSYW5nZShzdGFydCwgZW5kLCBleGNsdXNpdmUpO1xufVxuXG52YXIgT2JqZWN0UmFuZ2UgPSBDbGFzcy5jcmVhdGUoRW51bWVyYWJsZSwgKGZ1bmN0aW9uKCkge1xuICBmdW5jdGlvbiBpbml0aWFsaXplKHN0YXJ0LCBlbmQsIGV4Y2x1c2l2ZSkge1xuICAgIHRoaXMuc3RhcnQgPSBzdGFydDtcbiAgICB0aGlzLmVuZCA9IGVuZDtcbiAgICB0aGlzLmV4Y2x1c2l2ZSA9IGV4Y2x1c2l2ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9lYWNoKGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgdmFyIHZhbHVlID0gdGhpcy5zdGFydCwgaTtcbiAgICBmb3IgKGkgPSAwOyB0aGlzLmluY2x1ZGUodmFsdWUpOyBpKyspIHtcbiAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGkpO1xuICAgICAgdmFsdWUgPSB2YWx1ZS5zdWNjKCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5jbHVkZSh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA8IHRoaXMuc3RhcnQpXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHRoaXMuZXhjbHVzaXZlKVxuICAgICAgcmV0dXJuIHZhbHVlIDwgdGhpcy5lbmQ7XG4gICAgcmV0dXJuIHZhbHVlIDw9IHRoaXMuZW5kO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBpbml0aWFsaXplOiBpbml0aWFsaXplLFxuICAgIF9lYWNoOiAgICAgIF9lYWNoLFxuICAgIGluY2x1ZGU6ICAgIGluY2x1ZGVcbiAgfTtcbn0pKCkpO1xuXG5cblxudmFyIEFic3RyYWN0ID0geyB9O1xuXG5cbnZhciBUcnkgPSB7XG4gIHRoZXNlOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmV0dXJuVmFsdWU7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgbGFtYmRhID0gYXJndW1lbnRzW2ldO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuVmFsdWUgPSBsYW1iZGEoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9IGNhdGNoIChlKSB7IH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gIH1cbn07XG5cbnZhciBBamF4ID0ge1xuICBnZXRUcmFuc3BvcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBUcnkudGhlc2UoXG4gICAgICBmdW5jdGlvbigpIHtyZXR1cm4gbmV3IFhNTEh0dHBSZXF1ZXN0KCl9LFxuICAgICAgZnVuY3Rpb24oKSB7cmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNc3htbDIuWE1MSFRUUCcpfSxcbiAgICAgIGZ1bmN0aW9uKCkge3JldHVybiBuZXcgQWN0aXZlWE9iamVjdCgnTWljcm9zb2Z0LlhNTEhUVFAnKX1cbiAgICApIHx8IGZhbHNlO1xuICB9LFxuXG4gIGFjdGl2ZVJlcXVlc3RDb3VudDogMFxufTtcblxuQWpheC5SZXNwb25kZXJzID0ge1xuICByZXNwb25kZXJzOiBbXSxcblxuICBfZWFjaDogZnVuY3Rpb24oaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB0aGlzLnJlc3BvbmRlcnMuX2VhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICB9LFxuXG4gIHJlZ2lzdGVyOiBmdW5jdGlvbihyZXNwb25kZXIpIHtcbiAgICBpZiAoIXRoaXMuaW5jbHVkZShyZXNwb25kZXIpKVxuICAgICAgdGhpcy5yZXNwb25kZXJzLnB1c2gocmVzcG9uZGVyKTtcbiAgfSxcblxuICB1bnJlZ2lzdGVyOiBmdW5jdGlvbihyZXNwb25kZXIpIHtcbiAgICB0aGlzLnJlc3BvbmRlcnMgPSB0aGlzLnJlc3BvbmRlcnMud2l0aG91dChyZXNwb25kZXIpO1xuICB9LFxuXG4gIGRpc3BhdGNoOiBmdW5jdGlvbihjYWxsYmFjaywgcmVxdWVzdCwgdHJhbnNwb3J0LCBqc29uKSB7XG4gICAgdGhpcy5lYWNoKGZ1bmN0aW9uKHJlc3BvbmRlcikge1xuICAgICAgaWYgKE9iamVjdC5pc0Z1bmN0aW9uKHJlc3BvbmRlcltjYWxsYmFja10pKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzcG9uZGVyW2NhbGxiYWNrXS5hcHBseShyZXNwb25kZXIsIFtyZXF1ZXN0LCB0cmFuc3BvcnQsIGpzb25dKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn07XG5cbk9iamVjdC5leHRlbmQoQWpheC5SZXNwb25kZXJzLCBFbnVtZXJhYmxlKTtcblxuQWpheC5SZXNwb25kZXJzLnJlZ2lzdGVyKHtcbiAgb25DcmVhdGU6ICAgZnVuY3Rpb24oKSB7IEFqYXguYWN0aXZlUmVxdWVzdENvdW50KysgfSxcbiAgb25Db21wbGV0ZTogZnVuY3Rpb24oKSB7IEFqYXguYWN0aXZlUmVxdWVzdENvdW50LS0gfVxufSk7XG5BamF4LkJhc2UgPSBDbGFzcy5jcmVhdGUoe1xuICBpbml0aWFsaXplOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgbWV0aG9kOiAgICAgICAncG9zdCcsXG4gICAgICBhc3luY2hyb25vdXM6IHRydWUsXG4gICAgICBjb250ZW50VHlwZTogICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgZW5jb2Rpbmc6ICAgICAnVVRGLTgnLFxuICAgICAgcGFyYW1ldGVyczogICAnJyxcbiAgICAgIGV2YWxKU09OOiAgICAgdHJ1ZSxcbiAgICAgIGV2YWxKUzogICAgICAgdHJ1ZVxuICAgIH07XG4gICAgT2JqZWN0LmV4dGVuZCh0aGlzLm9wdGlvbnMsIG9wdGlvbnMgfHwgeyB9KTtcblxuICAgIHRoaXMub3B0aW9ucy5tZXRob2QgPSB0aGlzLm9wdGlvbnMubWV0aG9kLnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAoT2JqZWN0LmlzSGFzaCh0aGlzLm9wdGlvbnMucGFyYW1ldGVycykpXG4gICAgICB0aGlzLm9wdGlvbnMucGFyYW1ldGVycyA9IHRoaXMub3B0aW9ucy5wYXJhbWV0ZXJzLnRvT2JqZWN0KCk7XG4gIH1cbn0pO1xuQWpheC5SZXF1ZXN0ID0gQ2xhc3MuY3JlYXRlKEFqYXguQmFzZSwge1xuICBfY29tcGxldGU6IGZhbHNlLFxuXG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKCRzdXBlciwgdXJsLCBvcHRpb25zKSB7XG4gICAgJHN1cGVyKG9wdGlvbnMpO1xuICAgIHRoaXMudHJhbnNwb3J0ID0gQWpheC5nZXRUcmFuc3BvcnQoKTtcbiAgICB0aGlzLnJlcXVlc3QodXJsKTtcbiAgfSxcblxuICByZXF1ZXN0OiBmdW5jdGlvbih1cmwpIHtcbiAgICB0aGlzLnVybCA9IHVybDtcbiAgICB0aGlzLm1ldGhvZCA9IHRoaXMub3B0aW9ucy5tZXRob2Q7XG4gICAgdmFyIHBhcmFtcyA9IE9iamVjdC5pc1N0cmluZyh0aGlzLm9wdGlvbnMucGFyYW1ldGVycykgP1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5wYXJhbWV0ZXJzIDpcbiAgICAgICAgICBPYmplY3QudG9RdWVyeVN0cmluZyh0aGlzLm9wdGlvbnMucGFyYW1ldGVycyk7XG5cbiAgICBpZiAoIVsnZ2V0JywgJ3Bvc3QnXS5pbmNsdWRlKHRoaXMubWV0aG9kKSkge1xuICAgICAgcGFyYW1zICs9IChwYXJhbXMgPyAnJicgOiAnJykgKyBcIl9tZXRob2Q9XCIgKyB0aGlzLm1ldGhvZDtcbiAgICAgIHRoaXMubWV0aG9kID0gJ3Bvc3QnO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMgJiYgdGhpcy5tZXRob2QgPT09ICdnZXQnKSB7XG4gICAgICB0aGlzLnVybCArPSAodGhpcy51cmwuaW5jbHVkZSgnPycpID8gJyYnIDogJz8nKSArIHBhcmFtcztcbiAgICB9XG5cbiAgICB0aGlzLnBhcmFtZXRlcnMgPSBwYXJhbXMudG9RdWVyeVBhcmFtcygpO1xuXG4gICAgdHJ5IHtcbiAgICAgIHZhciByZXNwb25zZSA9IG5ldyBBamF4LlJlc3BvbnNlKHRoaXMpO1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5vbkNyZWF0ZSkgdGhpcy5vcHRpb25zLm9uQ3JlYXRlKHJlc3BvbnNlKTtcbiAgICAgIEFqYXguUmVzcG9uZGVycy5kaXNwYXRjaCgnb25DcmVhdGUnLCB0aGlzLCByZXNwb25zZSk7XG5cbiAgICAgIHRoaXMudHJhbnNwb3J0Lm9wZW4odGhpcy5tZXRob2QudG9VcHBlckNhc2UoKSwgdGhpcy51cmwsXG4gICAgICAgIHRoaXMub3B0aW9ucy5hc3luY2hyb25vdXMpO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmFzeW5jaHJvbm91cykgdGhpcy5yZXNwb25kVG9SZWFkeVN0YXRlLmJpbmQodGhpcykuZGVmZXIoMSk7XG5cbiAgICAgIHRoaXMudHJhbnNwb3J0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IHRoaXMub25TdGF0ZUNoYW5nZS5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5zZXRSZXF1ZXN0SGVhZGVycygpO1xuXG4gICAgICB0aGlzLmJvZHkgPSB0aGlzLm1ldGhvZCA9PSAncG9zdCcgPyAodGhpcy5vcHRpb25zLnBvc3RCb2R5IHx8IHBhcmFtcykgOiBudWxsO1xuICAgICAgdGhpcy50cmFuc3BvcnQuc2VuZCh0aGlzLmJvZHkpO1xuXG4gICAgICAvKiBGb3JjZSBGaXJlZm94IHRvIGhhbmRsZSByZWFkeSBzdGF0ZSA0IGZvciBzeW5jaHJvbm91cyByZXF1ZXN0cyAqL1xuICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuYXN5bmNocm9ub3VzICYmIHRoaXMudHJhbnNwb3J0Lm92ZXJyaWRlTWltZVR5cGUpXG4gICAgICAgIHRoaXMub25TdGF0ZUNoYW5nZSgpO1xuXG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmRpc3BhdGNoRXhjZXB0aW9uKGUpO1xuICAgIH1cbiAgfSxcblxuICBvblN0YXRlQ2hhbmdlOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVhZHlTdGF0ZSA9IHRoaXMudHJhbnNwb3J0LnJlYWR5U3RhdGU7XG4gICAgaWYgKHJlYWR5U3RhdGUgPiAxICYmICEoKHJlYWR5U3RhdGUgPT0gNCkgJiYgdGhpcy5fY29tcGxldGUpKVxuICAgICAgdGhpcy5yZXNwb25kVG9SZWFkeVN0YXRlKHRoaXMudHJhbnNwb3J0LnJlYWR5U3RhdGUpO1xuICB9LFxuXG4gIHNldFJlcXVlc3RIZWFkZXJzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgaGVhZGVycyA9IHtcbiAgICAgICdYLVJlcXVlc3RlZC1XaXRoJzogJ1hNTEh0dHBSZXF1ZXN0JyxcbiAgICAgICdYLVByb3RvdHlwZS1WZXJzaW9uJzogUHJvdG90eXBlLlZlcnNpb24sXG4gICAgICAnQWNjZXB0JzogJ3RleHQvamF2YXNjcmlwdCwgdGV4dC9odG1sLCBhcHBsaWNhdGlvbi94bWwsIHRleHQveG1sLCAqLyonXG4gICAgfTtcblxuICAgIGlmICh0aGlzLm1ldGhvZCA9PSAncG9zdCcpIHtcbiAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtdHlwZSddID0gdGhpcy5vcHRpb25zLmNvbnRlbnRUeXBlICtcbiAgICAgICAgKHRoaXMub3B0aW9ucy5lbmNvZGluZyA/ICc7IGNoYXJzZXQ9JyArIHRoaXMub3B0aW9ucy5lbmNvZGluZyA6ICcnKTtcblxuICAgICAgLyogRm9yY2UgXCJDb25uZWN0aW9uOiBjbG9zZVwiIGZvciBvbGRlciBNb3ppbGxhIGJyb3dzZXJzIHRvIHdvcmtcbiAgICAgICAqIGFyb3VuZCBhIGJ1ZyB3aGVyZSBYTUxIdHRwUmVxdWVzdCBzZW5kcyBhbiBpbmNvcnJlY3RcbiAgICAgICAqIENvbnRlbnQtbGVuZ3RoIGhlYWRlci4gU2VlIE1vemlsbGEgQnVnemlsbGEgIzI0NjY1MS5cbiAgICAgICAqL1xuICAgICAgaWYgKHRoaXMudHJhbnNwb3J0Lm92ZXJyaWRlTWltZVR5cGUgJiZcbiAgICAgICAgICAobmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvR2Vja29cXC8oXFxkezR9KS8pIHx8IFswLDIwMDVdKVsxXSA8IDIwMDUpXG4gICAgICAgICAgICBoZWFkZXJzWydDb25uZWN0aW9uJ10gPSAnY2xvc2UnO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdGhpcy5vcHRpb25zLnJlcXVlc3RIZWFkZXJzID09ICdvYmplY3QnKSB7XG4gICAgICB2YXIgZXh0cmFzID0gdGhpcy5vcHRpb25zLnJlcXVlc3RIZWFkZXJzO1xuXG4gICAgICBpZiAoT2JqZWN0LmlzRnVuY3Rpb24oZXh0cmFzLnB1c2gpKVxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZXh0cmFzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSArPSAyKVxuICAgICAgICAgIGhlYWRlcnNbZXh0cmFzW2ldXSA9IGV4dHJhc1tpKzFdO1xuICAgICAgZWxzZVxuICAgICAgICAkSChleHRyYXMpLmVhY2goZnVuY3Rpb24ocGFpcikgeyBoZWFkZXJzW3BhaXIua2V5XSA9IHBhaXIudmFsdWUgfSk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgbmFtZSBpbiBoZWFkZXJzKVxuICAgICAgaWYgKGhlYWRlcnNbbmFtZV0gIT0gbnVsbClcbiAgICAgICAgdGhpcy50cmFuc3BvcnQuc2V0UmVxdWVzdEhlYWRlcihuYW1lLCBoZWFkZXJzW25hbWVdKTtcbiAgfSxcblxuICBzdWNjZXNzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgc3RhdHVzID0gdGhpcy5nZXRTdGF0dXMoKTtcbiAgICByZXR1cm4gIXN0YXR1cyB8fCAoc3RhdHVzID49IDIwMCAmJiBzdGF0dXMgPCAzMDApIHx8IHN0YXR1cyA9PSAzMDQ7XG4gIH0sXG5cbiAgZ2V0U3RhdHVzOiBmdW5jdGlvbigpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMudHJhbnNwb3J0LnN0YXR1cyA9PT0gMTIyMykgcmV0dXJuIDIwNDtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5zdGF0dXMgfHwgMDtcbiAgICB9IGNhdGNoIChlKSB7IHJldHVybiAwIH1cbiAgfSxcblxuICByZXNwb25kVG9SZWFkeVN0YXRlOiBmdW5jdGlvbihyZWFkeVN0YXRlKSB7XG4gICAgdmFyIHN0YXRlID0gQWpheC5SZXF1ZXN0LkV2ZW50c1tyZWFkeVN0YXRlXSwgcmVzcG9uc2UgPSBuZXcgQWpheC5SZXNwb25zZSh0aGlzKTtcblxuICAgIGlmIChzdGF0ZSA9PSAnQ29tcGxldGUnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLl9jb21wbGV0ZSA9IHRydWU7XG4gICAgICAgICh0aGlzLm9wdGlvbnNbJ29uJyArIHJlc3BvbnNlLnN0YXR1c11cbiAgICAgICAgIHx8IHRoaXMub3B0aW9uc1snb24nICsgKHRoaXMuc3VjY2VzcygpID8gJ1N1Y2Nlc3MnIDogJ0ZhaWx1cmUnKV1cbiAgICAgICAgIHx8IFByb3RvdHlwZS5lbXB0eUZ1bmN0aW9uKShyZXNwb25zZSwgcmVzcG9uc2UuaGVhZGVySlNPTik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFeGNlcHRpb24oZSk7XG4gICAgICB9XG5cbiAgICAgIHZhciBjb250ZW50VHlwZSA9IHJlc3BvbnNlLmdldEhlYWRlcignQ29udGVudC10eXBlJyk7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmV2YWxKUyA9PSAnZm9yY2UnXG4gICAgICAgICAgfHwgKHRoaXMub3B0aW9ucy5ldmFsSlMgJiYgdGhpcy5pc1NhbWVPcmlnaW4oKSAmJiBjb250ZW50VHlwZVxuICAgICAgICAgICYmIGNvbnRlbnRUeXBlLm1hdGNoKC9eXFxzKih0ZXh0fGFwcGxpY2F0aW9uKVxcLyh4LSk/KGphdmF8ZWNtYSlzY3JpcHQoOy4qKT9cXHMqJC9pKSkpXG4gICAgICAgIHRoaXMuZXZhbFJlc3BvbnNlKCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgICh0aGlzLm9wdGlvbnNbJ29uJyArIHN0YXRlXSB8fCBQcm90b3R5cGUuZW1wdHlGdW5jdGlvbikocmVzcG9uc2UsIHJlc3BvbnNlLmhlYWRlckpTT04pO1xuICAgICAgQWpheC5SZXNwb25kZXJzLmRpc3BhdGNoKCdvbicgKyBzdGF0ZSwgdGhpcywgcmVzcG9uc2UsIHJlc3BvbnNlLmhlYWRlckpTT04pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuZGlzcGF0Y2hFeGNlcHRpb24oZSk7XG4gICAgfVxuXG4gICAgaWYgKHN0YXRlID09ICdDb21wbGV0ZScpIHtcbiAgICAgIHRoaXMudHJhbnNwb3J0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IFByb3RvdHlwZS5lbXB0eUZ1bmN0aW9uO1xuICAgIH1cbiAgfSxcblxuICBpc1NhbWVPcmlnaW46IGZ1bmN0aW9uKCkge1xuICAgIHZhciBtID0gdGhpcy51cmwubWF0Y2goL15cXHMqaHR0cHM/OlxcL1xcL1teXFwvXSovKTtcbiAgICByZXR1cm4gIW0gfHwgKG1bMF0gPT0gJyN7cHJvdG9jb2x9Ly8je2RvbWFpbn0je3BvcnR9Jy5pbnRlcnBvbGF0ZSh7XG4gICAgICBwcm90b2NvbDogbG9jYXRpb24ucHJvdG9jb2wsXG4gICAgICBkb21haW46IGRvY3VtZW50LmRvbWFpbixcbiAgICAgIHBvcnQ6IGxvY2F0aW9uLnBvcnQgPyAnOicgKyBsb2NhdGlvbi5wb3J0IDogJydcbiAgICB9KSk7XG4gIH0sXG5cbiAgZ2V0SGVhZGVyOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5nZXRSZXNwb25zZUhlYWRlcihuYW1lKSB8fCBudWxsO1xuICAgIH0gY2F0Y2ggKGUpIHsgcmV0dXJuIG51bGw7IH1cbiAgfSxcblxuICBldmFsUmVzcG9uc2U6IGZ1bmN0aW9uKCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZXZhbCgodGhpcy50cmFuc3BvcnQucmVzcG9uc2VUZXh0IHx8ICcnKS51bmZpbHRlckpTT04oKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5kaXNwYXRjaEV4Y2VwdGlvbihlKTtcbiAgICB9XG4gIH0sXG5cbiAgZGlzcGF0Y2hFeGNlcHRpb246IGZ1bmN0aW9uKGV4Y2VwdGlvbikge1xuICAgICh0aGlzLm9wdGlvbnMub25FeGNlcHRpb24gfHwgUHJvdG90eXBlLmVtcHR5RnVuY3Rpb24pKHRoaXMsIGV4Y2VwdGlvbik7XG4gICAgQWpheC5SZXNwb25kZXJzLmRpc3BhdGNoKCdvbkV4Y2VwdGlvbicsIHRoaXMsIGV4Y2VwdGlvbik7XG4gIH1cbn0pO1xuXG5BamF4LlJlcXVlc3QuRXZlbnRzID1cbiAgWydVbmluaXRpYWxpemVkJywgJ0xvYWRpbmcnLCAnTG9hZGVkJywgJ0ludGVyYWN0aXZlJywgJ0NvbXBsZXRlJ107XG5cblxuXG5cblxuXG5cblxuQWpheC5SZXNwb25zZSA9IENsYXNzLmNyZWF0ZSh7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKHJlcXVlc3Qpe1xuICAgIHRoaXMucmVxdWVzdCA9IHJlcXVlc3Q7XG4gICAgdmFyIHRyYW5zcG9ydCAgPSB0aGlzLnRyYW5zcG9ydCAgPSByZXF1ZXN0LnRyYW5zcG9ydCxcbiAgICAgICAgcmVhZHlTdGF0ZSA9IHRoaXMucmVhZHlTdGF0ZSA9IHRyYW5zcG9ydC5yZWFkeVN0YXRlO1xuXG4gICAgaWYgKChyZWFkeVN0YXRlID4gMiAmJiAhUHJvdG90eXBlLkJyb3dzZXIuSUUpIHx8IHJlYWR5U3RhdGUgPT0gNCkge1xuICAgICAgdGhpcy5zdGF0dXMgICAgICAgPSB0aGlzLmdldFN0YXR1cygpO1xuICAgICAgdGhpcy5zdGF0dXNUZXh0ICAgPSB0aGlzLmdldFN0YXR1c1RleHQoKTtcbiAgICAgIHRoaXMucmVzcG9uc2VUZXh0ID0gU3RyaW5nLmludGVycHJldCh0cmFuc3BvcnQucmVzcG9uc2VUZXh0KTtcbiAgICAgIHRoaXMuaGVhZGVySlNPTiAgID0gdGhpcy5fZ2V0SGVhZGVySlNPTigpO1xuICAgIH1cblxuICAgIGlmIChyZWFkeVN0YXRlID09IDQpIHtcbiAgICAgIHZhciB4bWwgPSB0cmFuc3BvcnQucmVzcG9uc2VYTUw7XG4gICAgICB0aGlzLnJlc3BvbnNlWE1MICA9IE9iamVjdC5pc1VuZGVmaW5lZCh4bWwpID8gbnVsbCA6IHhtbDtcbiAgICAgIHRoaXMucmVzcG9uc2VKU09OID0gdGhpcy5fZ2V0UmVzcG9uc2VKU09OKCk7XG4gICAgfVxuICB9LFxuXG4gIHN0YXR1czogICAgICAwLFxuXG4gIHN0YXR1c1RleHQ6ICcnLFxuXG4gIGdldFN0YXR1czogQWpheC5SZXF1ZXN0LnByb3RvdHlwZS5nZXRTdGF0dXMsXG5cbiAgZ2V0U3RhdHVzVGV4dDogZnVuY3Rpb24oKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5zdGF0dXNUZXh0IHx8ICcnO1xuICAgIH0gY2F0Y2ggKGUpIHsgcmV0dXJuICcnIH1cbiAgfSxcblxuICBnZXRIZWFkZXI6IEFqYXguUmVxdWVzdC5wcm90b3R5cGUuZ2V0SGVhZGVyLFxuXG4gIGdldEFsbEhlYWRlcnM6IGZ1bmN0aW9uKCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKTtcbiAgICB9IGNhdGNoIChlKSB7IHJldHVybiBudWxsIH1cbiAgfSxcblxuICBnZXRSZXNwb25zZUhlYWRlcjogZnVuY3Rpb24obmFtZSkge1xuICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5nZXRSZXNwb25zZUhlYWRlcihuYW1lKTtcbiAgfSxcblxuICBnZXRBbGxSZXNwb25zZUhlYWRlcnM6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKTtcbiAgfSxcblxuICBfZ2V0SGVhZGVySlNPTjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGpzb24gPSB0aGlzLmdldEhlYWRlcignWC1KU09OJyk7XG4gICAgaWYgKCFqc29uKSByZXR1cm4gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICBqc29uID0gZGVjb2RlVVJJQ29tcG9uZW50KGVzY2FwZShqc29uKSk7XG4gICAgfSBjYXRjaChlKSB7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBqc29uLmV2YWxKU09OKHRoaXMucmVxdWVzdC5vcHRpb25zLnNhbml0aXplSlNPTiB8fFxuICAgICAgICAhdGhpcy5yZXF1ZXN0LmlzU2FtZU9yaWdpbigpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLnJlcXVlc3QuZGlzcGF0Y2hFeGNlcHRpb24oZSk7XG4gICAgfVxuICB9LFxuXG4gIF9nZXRSZXNwb25zZUpTT046IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvcHRpb25zID0gdGhpcy5yZXF1ZXN0Lm9wdGlvbnM7XG4gICAgaWYgKCFvcHRpb25zLmV2YWxKU09OIHx8IChvcHRpb25zLmV2YWxKU09OICE9ICdmb3JjZScgJiZcbiAgICAgICEodGhpcy5nZXRIZWFkZXIoJ0NvbnRlbnQtdHlwZScpIHx8ICcnKS5pbmNsdWRlKCdhcHBsaWNhdGlvbi9qc29uJykpIHx8XG4gICAgICAgIHRoaXMucmVzcG9uc2VUZXh0LmJsYW5rKCkpXG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlVGV4dC5ldmFsSlNPTihvcHRpb25zLnNhbml0aXplSlNPTiB8fFxuICAgICAgICAhdGhpcy5yZXF1ZXN0LmlzU2FtZU9yaWdpbigpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLnJlcXVlc3QuZGlzcGF0Y2hFeGNlcHRpb24oZSk7XG4gICAgfVxuICB9XG59KTtcblxuQWpheC5VcGRhdGVyID0gQ2xhc3MuY3JlYXRlKEFqYXguUmVxdWVzdCwge1xuICBpbml0aWFsaXplOiBmdW5jdGlvbigkc3VwZXIsIGNvbnRhaW5lciwgdXJsLCBvcHRpb25zKSB7XG4gICAgdGhpcy5jb250YWluZXIgPSB7XG4gICAgICBzdWNjZXNzOiAoY29udGFpbmVyLnN1Y2Nlc3MgfHwgY29udGFpbmVyKSxcbiAgICAgIGZhaWx1cmU6IChjb250YWluZXIuZmFpbHVyZSB8fCAoY29udGFpbmVyLnN1Y2Nlc3MgPyBudWxsIDogY29udGFpbmVyKSlcbiAgICB9O1xuXG4gICAgb3B0aW9ucyA9IE9iamVjdC5jbG9uZShvcHRpb25zKTtcbiAgICB2YXIgb25Db21wbGV0ZSA9IG9wdGlvbnMub25Db21wbGV0ZTtcbiAgICBvcHRpb25zLm9uQ29tcGxldGUgPSAoZnVuY3Rpb24ocmVzcG9uc2UsIGpzb24pIHtcbiAgICAgIHRoaXMudXBkYXRlQ29udGVudChyZXNwb25zZS5yZXNwb25zZVRleHQpO1xuICAgICAgaWYgKE9iamVjdC5pc0Z1bmN0aW9uKG9uQ29tcGxldGUpKSBvbkNvbXBsZXRlKHJlc3BvbnNlLCBqc29uKTtcbiAgICB9KS5iaW5kKHRoaXMpO1xuXG4gICAgJHN1cGVyKHVybCwgb3B0aW9ucyk7XG4gIH0sXG5cbiAgdXBkYXRlQ29udGVudDogZnVuY3Rpb24ocmVzcG9uc2VUZXh0KSB7XG4gICAgdmFyIHJlY2VpdmVyID0gdGhpcy5jb250YWluZXJbdGhpcy5zdWNjZXNzKCkgPyAnc3VjY2VzcycgOiAnZmFpbHVyZSddLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG4gICAgaWYgKCFvcHRpb25zLmV2YWxTY3JpcHRzKSByZXNwb25zZVRleHQgPSByZXNwb25zZVRleHQuc3RyaXBTY3JpcHRzKCk7XG5cbiAgICBpZiAocmVjZWl2ZXIgPSAkKHJlY2VpdmVyKSkge1xuICAgICAgaWYgKG9wdGlvbnMuaW5zZXJ0aW9uKSB7XG4gICAgICAgIGlmIChPYmplY3QuaXNTdHJpbmcob3B0aW9ucy5pbnNlcnRpb24pKSB7XG4gICAgICAgICAgdmFyIGluc2VydGlvbiA9IHsgfTsgaW5zZXJ0aW9uW29wdGlvbnMuaW5zZXJ0aW9uXSA9IHJlc3BvbnNlVGV4dDtcbiAgICAgICAgICByZWNlaXZlci5pbnNlcnQoaW5zZXJ0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIG9wdGlvbnMuaW5zZXJ0aW9uKHJlY2VpdmVyLCByZXNwb25zZVRleHQpO1xuICAgICAgfVxuICAgICAgZWxzZSByZWNlaXZlci51cGRhdGUocmVzcG9uc2VUZXh0KTtcbiAgICB9XG4gIH1cbn0pO1xuXG5BamF4LlBlcmlvZGljYWxVcGRhdGVyID0gQ2xhc3MuY3JlYXRlKEFqYXguQmFzZSwge1xuICBpbml0aWFsaXplOiBmdW5jdGlvbigkc3VwZXIsIGNvbnRhaW5lciwgdXJsLCBvcHRpb25zKSB7XG4gICAgJHN1cGVyKG9wdGlvbnMpO1xuICAgIHRoaXMub25Db21wbGV0ZSA9IHRoaXMub3B0aW9ucy5vbkNvbXBsZXRlO1xuXG4gICAgdGhpcy5mcmVxdWVuY3kgPSAodGhpcy5vcHRpb25zLmZyZXF1ZW5jeSB8fCAyKTtcbiAgICB0aGlzLmRlY2F5ID0gKHRoaXMub3B0aW9ucy5kZWNheSB8fCAxKTtcblxuICAgIHRoaXMudXBkYXRlciA9IHsgfTtcbiAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcbiAgICB0aGlzLnVybCA9IHVybDtcblxuICAgIHRoaXMuc3RhcnQoKTtcbiAgfSxcblxuICBzdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5vcHRpb25zLm9uQ29tcGxldGUgPSB0aGlzLnVwZGF0ZUNvbXBsZXRlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5vblRpbWVyRXZlbnQoKTtcbiAgfSxcblxuICBzdG9wOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnVwZGF0ZXIub3B0aW9ucy5vbkNvbXBsZXRlID0gdW5kZWZpbmVkO1xuICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVyKTtcbiAgICAodGhpcy5vbkNvbXBsZXRlIHx8IFByb3RvdHlwZS5lbXB0eUZ1bmN0aW9uKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9LFxuXG4gIHVwZGF0ZUNvbXBsZXRlOiBmdW5jdGlvbihyZXNwb25zZSkge1xuICAgIGlmICh0aGlzLm9wdGlvbnMuZGVjYXkpIHtcbiAgICAgIHRoaXMuZGVjYXkgPSAocmVzcG9uc2UucmVzcG9uc2VUZXh0ID09IHRoaXMubGFzdFRleHQgP1xuICAgICAgICB0aGlzLmRlY2F5ICogdGhpcy5vcHRpb25zLmRlY2F5IDogMSk7XG5cbiAgICAgIHRoaXMubGFzdFRleHQgPSByZXNwb25zZS5yZXNwb25zZVRleHQ7XG4gICAgfVxuICAgIHRoaXMudGltZXIgPSB0aGlzLm9uVGltZXJFdmVudC5iaW5kKHRoaXMpLmRlbGF5KHRoaXMuZGVjYXkgKiB0aGlzLmZyZXF1ZW5jeSk7XG4gIH0sXG5cbiAgb25UaW1lckV2ZW50OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnVwZGF0ZXIgPSBuZXcgQWpheC5VcGRhdGVyKHRoaXMuY29udGFpbmVyLCB0aGlzLnVybCwgdGhpcy5vcHRpb25zKTtcbiAgfVxufSk7XG5cbihmdW5jdGlvbihHTE9CQUwpIHtcblxuICB2YXIgVU5ERUZJTkVEO1xuICB2YXIgU0xJQ0UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbiAgdmFyIERJViA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG5cbiAgZnVuY3Rpb24gJChlbGVtZW50KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgZWxlbWVudHMgPSBbXSwgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKVxuICAgICAgICBlbGVtZW50cy5wdXNoKCQoYXJndW1lbnRzW2ldKSk7XG4gICAgICByZXR1cm4gZWxlbWVudHM7XG4gICAgfVxuXG4gICAgaWYgKE9iamVjdC5pc1N0cmluZyhlbGVtZW50KSlcbiAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtZW50KTtcbiAgICByZXR1cm4gRWxlbWVudC5leHRlbmQoZWxlbWVudCk7XG4gIH1cblxuICBHTE9CQUwuJCA9ICQ7XG5cblxuICBpZiAoIUdMT0JBTC5Ob2RlKSBHTE9CQUwuTm9kZSA9IHt9O1xuXG4gIGlmICghR0xPQkFMLk5vZGUuRUxFTUVOVF9OT0RFKSB7XG4gICAgT2JqZWN0LmV4dGVuZChHTE9CQUwuTm9kZSwge1xuICAgICAgRUxFTUVOVF9OT0RFOiAgICAgICAgICAgICAgICAxLFxuICAgICAgQVRUUklCVVRFX05PREU6ICAgICAgICAgICAgICAyLFxuICAgICAgVEVYVF9OT0RFOiAgICAgICAgICAgICAgICAgICAzLFxuICAgICAgQ0RBVEFfU0VDVElPTl9OT0RFOiAgICAgICAgICA0LFxuICAgICAgRU5USVRZX1JFRkVSRU5DRV9OT0RFOiAgICAgICA1LFxuICAgICAgRU5USVRZX05PREU6ICAgICAgICAgICAgICAgICA2LFxuICAgICAgUFJPQ0VTU0lOR19JTlNUUlVDVElPTl9OT0RFOiA3LFxuICAgICAgQ09NTUVOVF9OT0RFOiAgICAgICAgICAgICAgICA4LFxuICAgICAgRE9DVU1FTlRfTk9ERTogICAgICAgICAgICAgICA5LFxuICAgICAgRE9DVU1FTlRfVFlQRV9OT0RFOiAgICAgICAgIDEwLFxuICAgICAgRE9DVU1FTlRfRlJBR01FTlRfTk9ERTogICAgIDExLFxuICAgICAgTk9UQVRJT05fTk9ERTogICAgICAgICAgICAgIDEyXG4gICAgfSk7XG4gIH1cblxuICB2YXIgRUxFTUVOVF9DQUNIRSA9IHt9O1xuXG4gIGZ1bmN0aW9uIHNob3VsZFVzZUNyZWF0aW9uQ2FjaGUodGFnTmFtZSwgYXR0cmlidXRlcykge1xuICAgIGlmICh0YWdOYW1lID09PSAnc2VsZWN0JykgcmV0dXJuIGZhbHNlO1xuICAgIGlmICgndHlwZScgaW4gYXR0cmlidXRlcykgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgdmFyIEhBU19FWFRFTkRFRF9DUkVBVEVfRUxFTUVOVF9TWU5UQVggPSAoZnVuY3Rpb24oKXtcbiAgICB0cnkge1xuICAgICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnPGlucHV0IG5hbWU9XCJ4XCI+Jyk7XG4gICAgICByZXR1cm4gZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnICYmIGVsLm5hbWUgPT09ICd4JztcbiAgICB9XG4gICAgY2F0Y2goZXJyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9KSgpO1xuXG5cbiAgdmFyIG9sZEVsZW1lbnQgPSBHTE9CQUwuRWxlbWVudDtcbiAgZnVuY3Rpb24gRWxlbWVudCh0YWdOYW1lLCBhdHRyaWJ1dGVzKSB7XG4gICAgYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMgfHwge307XG4gICAgdGFnTmFtZSA9IHRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgIGlmIChIQVNfRVhURU5ERURfQ1JFQVRFX0VMRU1FTlRfU1lOVEFYICYmIGF0dHJpYnV0ZXMubmFtZSkge1xuICAgICAgdGFnTmFtZSA9ICc8JyArIHRhZ05hbWUgKyAnIG5hbWU9XCInICsgYXR0cmlidXRlcy5uYW1lICsgJ1wiPic7XG4gICAgICBkZWxldGUgYXR0cmlidXRlcy5uYW1lO1xuICAgICAgcmV0dXJuIEVsZW1lbnQud3JpdGVBdHRyaWJ1dGUoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKSwgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgaWYgKCFFTEVNRU5UX0NBQ0hFW3RhZ05hbWVdKVxuICAgICAgRUxFTUVOVF9DQUNIRVt0YWdOYW1lXSA9IEVsZW1lbnQuZXh0ZW5kKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSkpO1xuXG4gICAgdmFyIG5vZGUgPSBzaG91bGRVc2VDcmVhdGlvbkNhY2hlKHRhZ05hbWUsIGF0dHJpYnV0ZXMpID9cbiAgICAgRUxFTUVOVF9DQUNIRVt0YWdOYW1lXS5jbG9uZU5vZGUoZmFsc2UpIDogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcblxuICAgIHJldHVybiBFbGVtZW50LndyaXRlQXR0cmlidXRlKG5vZGUsIGF0dHJpYnV0ZXMpO1xuICB9XG5cbiAgR0xPQkFMLkVsZW1lbnQgPSBFbGVtZW50O1xuXG4gIE9iamVjdC5leHRlbmQoR0xPQkFMLkVsZW1lbnQsIG9sZEVsZW1lbnQgfHwge30pO1xuICBpZiAob2xkRWxlbWVudCkgR0xPQkFMLkVsZW1lbnQucHJvdG90eXBlID0gb2xkRWxlbWVudC5wcm90b3R5cGU7XG5cbiAgRWxlbWVudC5NZXRob2RzID0geyBCeVRhZzoge30sIFNpbXVsYXRlZDoge30gfTtcblxuICB2YXIgbWV0aG9kcyA9IHt9O1xuXG4gIHZhciBJTlNQRUNUX0FUVFJJQlVURVMgPSB7IGlkOiAnaWQnLCBjbGFzc05hbWU6ICdjbGFzcycgfTtcbiAgZnVuY3Rpb24gaW5zcGVjdChlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIHJlc3VsdCA9ICc8JyArIGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgdmFyIGF0dHJpYnV0ZSwgdmFsdWU7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gSU5TUEVDVF9BVFRSSUJVVEVTKSB7XG4gICAgICBhdHRyaWJ1dGUgPSBJTlNQRUNUX0FUVFJJQlVURVNbcHJvcGVydHldO1xuICAgICAgdmFsdWUgPSAoZWxlbWVudFtwcm9wZXJ0eV0gfHwgJycpLnRvU3RyaW5nKCk7XG4gICAgICBpZiAodmFsdWUpIHJlc3VsdCArPSAnICcgKyBhdHRyaWJ1dGUgKyAnPScgKyB2YWx1ZS5pbnNwZWN0KHRydWUpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQgKyAnPic7XG4gIH1cblxuICBtZXRob2RzLmluc3BlY3QgPSBpbnNwZWN0O1xuXG5cbiAgZnVuY3Rpb24gdmlzaWJsZShlbGVtZW50KSB7XG4gICAgcmV0dXJuICQoZWxlbWVudCkuc3R5bGUuZGlzcGxheSAhPT0gJ25vbmUnO1xuICB9XG5cbiAgZnVuY3Rpb24gdG9nZ2xlKGVsZW1lbnQsIGJvb2wpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKGJvb2wpKVxuICAgICAgYm9vbCA9ICFFbGVtZW50LnZpc2libGUoZWxlbWVudCk7XG4gICAgRWxlbWVudFtib29sID8gJ3Nob3cnIDogJ2hpZGUnXShlbGVtZW50KTtcblxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gaGlkZShlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gc2hvdyhlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuXG4gIE9iamVjdC5leHRlbmQobWV0aG9kcywge1xuICAgIHZpc2libGU6IHZpc2libGUsXG4gICAgdG9nZ2xlOiAgdG9nZ2xlLFxuICAgIGhpZGU6ICAgIGhpZGUsXG4gICAgc2hvdzogICAgc2hvd1xuICB9KTtcblxuXG4gIGZ1bmN0aW9uIHJlbW92ZShlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgZWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsZW1lbnQpO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgdmFyIFNFTEVDVF9FTEVNRU5UX0lOTkVSSFRNTF9CVUdHWSA9IChmdW5jdGlvbigpe1xuICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzZWxlY3RcIiksXG4gICAgICAgIGlzQnVnZ3kgPSB0cnVlO1xuICAgIGVsLmlubmVySFRNTCA9IFwiPG9wdGlvbiB2YWx1ZT1cXFwidGVzdFxcXCI+dGVzdDwvb3B0aW9uPlwiO1xuICAgIGlmIChlbC5vcHRpb25zICYmIGVsLm9wdGlvbnNbMF0pIHtcbiAgICAgIGlzQnVnZ3kgPSBlbC5vcHRpb25zWzBdLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgIT09IFwiT1BUSU9OXCI7XG4gICAgfVxuICAgIGVsID0gbnVsbDtcbiAgICByZXR1cm4gaXNCdWdneTtcbiAgfSkoKTtcblxuICB2YXIgVEFCTEVfRUxFTUVOVF9JTk5FUkhUTUxfQlVHR1kgPSAoZnVuY3Rpb24oKXtcbiAgICB0cnkge1xuICAgICAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInRhYmxlXCIpO1xuICAgICAgaWYgKGVsICYmIGVsLnRCb2RpZXMpIHtcbiAgICAgICAgZWwuaW5uZXJIVE1MID0gXCI8dGJvZHk+PHRyPjx0ZD50ZXN0PC90ZD48L3RyPjwvdGJvZHk+XCI7XG4gICAgICAgIHZhciBpc0J1Z2d5ID0gdHlwZW9mIGVsLnRCb2RpZXNbMF0gPT0gXCJ1bmRlZmluZWRcIjtcbiAgICAgICAgZWwgPSBudWxsO1xuICAgICAgICByZXR1cm4gaXNCdWdneTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgdmFyIExJTktfRUxFTUVOVF9JTk5FUkhUTUxfQlVHR1kgPSAoZnVuY3Rpb24oKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZWwuaW5uZXJIVE1MID0gXCI8bGluayAvPlwiO1xuICAgICAgdmFyIGlzQnVnZ3kgPSAoZWwuY2hpbGROb2Rlcy5sZW5ndGggPT09IDApO1xuICAgICAgZWwgPSBudWxsO1xuICAgICAgcmV0dXJuIGlzQnVnZ3k7XG4gICAgfSBjYXRjaChlKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgdmFyIEFOWV9JTk5FUkhUTUxfQlVHR1kgPSBTRUxFQ1RfRUxFTUVOVF9JTk5FUkhUTUxfQlVHR1kgfHxcbiAgIFRBQkxFX0VMRU1FTlRfSU5ORVJIVE1MX0JVR0dZIHx8IExJTktfRUxFTUVOVF9JTk5FUkhUTUxfQlVHR1k7XG5cbiAgdmFyIFNDUklQVF9FTEVNRU5UX1JFSkVDVFNfVEVYVE5PREVfQVBQRU5ESU5HID0gKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIiksXG4gICAgICAgIGlzQnVnZ3kgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgcy5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShcIlwiKSk7XG4gICAgICBpc0J1Z2d5ID0gIXMuZmlyc3RDaGlsZCB8fFxuICAgICAgICBzLmZpcnN0Q2hpbGQgJiYgcy5maXJzdENoaWxkLm5vZGVUeXBlICE9PSAzO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlzQnVnZ3kgPSB0cnVlO1xuICAgIH1cbiAgICBzID0gbnVsbDtcbiAgICByZXR1cm4gaXNCdWdneTtcbiAgfSkoKTtcblxuICBmdW5jdGlvbiB1cGRhdGUoZWxlbWVudCwgY29udGVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXG4gICAgdmFyIGRlc2NlbmRhbnRzID0gZWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnKicpLFxuICAgICBpID0gZGVzY2VuZGFudHMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pIHB1cmdlRWxlbWVudChkZXNjZW5kYW50c1tpXSk7XG5cbiAgICBpZiAoY29udGVudCAmJiBjb250ZW50LnRvRWxlbWVudClcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnRvRWxlbWVudCgpO1xuXG4gICAgaWYgKE9iamVjdC5pc0VsZW1lbnQoY29udGVudCkpXG4gICAgICByZXR1cm4gZWxlbWVudC51cGRhdGUoKS5pbnNlcnQoY29udGVudCk7XG5cblxuICAgIGNvbnRlbnQgPSBPYmplY3QudG9IVE1MKGNvbnRlbnQpO1xuICAgIHZhciB0YWdOYW1lID0gZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG5cbiAgICBpZiAodGFnTmFtZSA9PT0gJ1NDUklQVCcgJiYgU0NSSVBUX0VMRU1FTlRfUkVKRUNUU19URVhUTk9ERV9BUFBFTkRJTkcpIHtcbiAgICAgIGVsZW1lbnQudGV4dCA9IGNvbnRlbnQ7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICBpZiAoQU5ZX0lOTkVSSFRNTF9CVUdHWSkge1xuICAgICAgaWYgKHRhZ05hbWUgaW4gSU5TRVJUSU9OX1RSQU5TTEFUSU9OUy50YWdzKSB7XG4gICAgICAgIHdoaWxlIChlbGVtZW50LmZpcnN0Q2hpbGQpXG4gICAgICAgICAgZWxlbWVudC5yZW1vdmVDaGlsZChlbGVtZW50LmZpcnN0Q2hpbGQpO1xuXG4gICAgICAgIHZhciBub2RlcyA9IGdldENvbnRlbnRGcm9tQW5vbnltb3VzRWxlbWVudCh0YWdOYW1lLCBjb250ZW50LnN0cmlwU2NyaXB0cygpKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIG5vZGU7IG5vZGUgPSBub2Rlc1tpXTsgaSsrKVxuICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQobm9kZSk7XG5cbiAgICAgIH0gZWxzZSBpZiAoTElOS19FTEVNRU5UX0lOTkVSSFRNTF9CVUdHWSAmJiBPYmplY3QuaXNTdHJpbmcoY29udGVudCkgJiYgY29udGVudC5pbmRleE9mKCc8bGluaycpID4gLTEpIHtcbiAgICAgICAgd2hpbGUgKGVsZW1lbnQuZmlyc3RDaGlsZClcbiAgICAgICAgICBlbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQuZmlyc3RDaGlsZCk7XG5cbiAgICAgICAgdmFyIG5vZGVzID0gZ2V0Q29udGVudEZyb21Bbm9ueW1vdXNFbGVtZW50KHRhZ05hbWUsXG4gICAgICAgICBjb250ZW50LnN0cmlwU2NyaXB0cygpLCB0cnVlKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbm9kZTsgbm9kZSA9IG5vZGVzW2ldOyBpKyspXG4gICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChub2RlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gY29udGVudC5zdHJpcFNjcmlwdHMoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBjb250ZW50LnN0cmlwU2NyaXB0cygpO1xuICAgIH1cblxuICAgIGNvbnRlbnQuZXZhbFNjcmlwdHMuYmluZChjb250ZW50KS5kZWZlcigpO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVwbGFjZShlbGVtZW50LCBjb250ZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICBpZiAoY29udGVudCAmJiBjb250ZW50LnRvRWxlbWVudCkge1xuICAgICAgY29udGVudCA9IGNvbnRlbnQudG9FbGVtZW50KCk7XG4gICAgfSBlbHNlIGlmICghT2JqZWN0LmlzRWxlbWVudChjb250ZW50KSkge1xuICAgICAgY29udGVudCA9IE9iamVjdC50b0hUTUwoY29udGVudCk7XG4gICAgICB2YXIgcmFuZ2UgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgIHJhbmdlLnNlbGVjdE5vZGUoZWxlbWVudCk7XG4gICAgICBjb250ZW50LmV2YWxTY3JpcHRzLmJpbmQoY29udGVudCkuZGVmZXIoKTtcbiAgICAgIGNvbnRlbnQgPSByYW5nZS5jcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQoY29udGVudC5zdHJpcFNjcmlwdHMoKSk7XG4gICAgfVxuXG4gICAgZWxlbWVudC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChjb250ZW50LCBlbGVtZW50KTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHZhciBJTlNFUlRJT05fVFJBTlNMQVRJT05TID0ge1xuICAgIGJlZm9yZTogZnVuY3Rpb24oZWxlbWVudCwgbm9kZSkge1xuICAgICAgZWxlbWVudC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShub2RlLCBlbGVtZW50KTtcbiAgICB9LFxuICAgIHRvcDogZnVuY3Rpb24oZWxlbWVudCwgbm9kZSkge1xuICAgICAgZWxlbWVudC5pbnNlcnRCZWZvcmUobm9kZSwgZWxlbWVudC5maXJzdENoaWxkKTtcbiAgICB9LFxuICAgIGJvdHRvbTogZnVuY3Rpb24oZWxlbWVudCwgbm9kZSkge1xuICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChub2RlKTtcbiAgICB9LFxuICAgIGFmdGVyOiBmdW5jdGlvbihlbGVtZW50LCBub2RlKSB7XG4gICAgICBlbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGVsZW1lbnQubmV4dFNpYmxpbmcpO1xuICAgIH0sXG5cbiAgICB0YWdzOiB7XG4gICAgICBUQUJMRTogIFsnPHRhYmxlPicsICAgICAgICAgICAgICAgICc8L3RhYmxlPicsICAgICAgICAgICAgICAgICAgIDFdLFxuICAgICAgVEJPRFk6ICBbJzx0YWJsZT48dGJvZHk+JywgICAgICAgICAnPC90Ym9keT48L3RhYmxlPicsICAgICAgICAgICAyXSxcbiAgICAgIFRSOiAgICAgWyc8dGFibGU+PHRib2R5Pjx0cj4nLCAgICAgJzwvdHI+PC90Ym9keT48L3RhYmxlPicsICAgICAgM10sXG4gICAgICBURDogICAgIFsnPHRhYmxlPjx0Ym9keT48dHI+PHRkPicsICc8L3RkPjwvdHI+PC90Ym9keT48L3RhYmxlPicsIDRdLFxuICAgICAgU0VMRUNUOiBbJzxzZWxlY3Q+JywgICAgICAgICAgICAgICAnPC9zZWxlY3Q+JywgICAgICAgICAgICAgICAgICAxXVxuICAgIH1cbiAgfTtcblxuICB2YXIgdGFncyA9IElOU0VSVElPTl9UUkFOU0xBVElPTlMudGFncztcblxuICBPYmplY3QuZXh0ZW5kKHRhZ3MsIHtcbiAgICBUSEVBRDogdGFncy5UQk9EWSxcbiAgICBURk9PVDogdGFncy5UQk9EWSxcbiAgICBUSDogICAgdGFncy5URFxuICB9KTtcblxuICBmdW5jdGlvbiByZXBsYWNlX0lFKGVsZW1lbnQsIGNvbnRlbnQpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICBpZiAoY29udGVudCAmJiBjb250ZW50LnRvRWxlbWVudClcbiAgICAgIGNvbnRlbnQgPSBjb250ZW50LnRvRWxlbWVudCgpO1xuICAgIGlmIChPYmplY3QuaXNFbGVtZW50KGNvbnRlbnQpKSB7XG4gICAgICBlbGVtZW50LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGNvbnRlbnQsIGVsZW1lbnQpO1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgY29udGVudCA9IE9iamVjdC50b0hUTUwoY29udGVudCk7XG4gICAgdmFyIHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZSwgdGFnTmFtZSA9IHBhcmVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG5cbiAgICBpZiAodGFnTmFtZSBpbiBJTlNFUlRJT05fVFJBTlNMQVRJT05TLnRhZ3MpIHtcbiAgICAgIHZhciBuZXh0U2libGluZyA9IEVsZW1lbnQubmV4dChlbGVtZW50KTtcbiAgICAgIHZhciBmcmFnbWVudHMgPSBnZXRDb250ZW50RnJvbUFub255bW91c0VsZW1lbnQoXG4gICAgICAgdGFnTmFtZSwgY29udGVudC5zdHJpcFNjcmlwdHMoKSk7XG5cbiAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChlbGVtZW50KTtcblxuICAgICAgdmFyIGl0ZXJhdG9yO1xuICAgICAgaWYgKG5leHRTaWJsaW5nKVxuICAgICAgICBpdGVyYXRvciA9IGZ1bmN0aW9uKG5vZGUpIHsgcGFyZW50Lmluc2VydEJlZm9yZShub2RlLCBuZXh0U2libGluZykgfTtcbiAgICAgIGVsc2VcbiAgICAgICAgaXRlcmF0b3IgPSBmdW5jdGlvbihub2RlKSB7IHBhcmVudC5hcHBlbmRDaGlsZChub2RlKTsgfVxuXG4gICAgICBmcmFnbWVudHMuZWFjaChpdGVyYXRvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZW1lbnQub3V0ZXJIVE1MID0gY29udGVudC5zdHJpcFNjcmlwdHMoKTtcbiAgICB9XG5cbiAgICBjb250ZW50LmV2YWxTY3JpcHRzLmJpbmQoY29udGVudCkuZGVmZXIoKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGlmICgnb3V0ZXJIVE1MJyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpXG4gICAgcmVwbGFjZSA9IHJlcGxhY2VfSUU7XG5cbiAgZnVuY3Rpb24gaXNDb250ZW50KGNvbnRlbnQpIHtcbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKGNvbnRlbnQpIHx8IGNvbnRlbnQgPT09IG51bGwpIHJldHVybiBmYWxzZTtcblxuICAgIGlmIChPYmplY3QuaXNTdHJpbmcoY29udGVudCkgfHwgT2JqZWN0LmlzTnVtYmVyKGNvbnRlbnQpKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAoT2JqZWN0LmlzRWxlbWVudChjb250ZW50KSkgcmV0dXJuIHRydWU7XG4gICAgaWYgKGNvbnRlbnQudG9FbGVtZW50IHx8IGNvbnRlbnQudG9IVE1MKSByZXR1cm4gdHJ1ZTtcblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluc2VydENvbnRlbnRBdChlbGVtZW50LCBjb250ZW50LCBwb3NpdGlvbikge1xuICAgIHBvc2l0aW9uICAgPSBwb3NpdGlvbi50b0xvd2VyQ2FzZSgpO1xuICAgIHZhciBtZXRob2QgPSBJTlNFUlRJT05fVFJBTlNMQVRJT05TW3Bvc2l0aW9uXTtcblxuICAgIGlmIChjb250ZW50ICYmIGNvbnRlbnQudG9FbGVtZW50KSBjb250ZW50ID0gY29udGVudC50b0VsZW1lbnQoKTtcbiAgICBpZiAoT2JqZWN0LmlzRWxlbWVudChjb250ZW50KSkge1xuICAgICAgbWV0aG9kKGVsZW1lbnQsIGNvbnRlbnQpO1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgY29udGVudCA9IE9iamVjdC50b0hUTUwoY29udGVudCk7XG4gICAgdmFyIHRhZ05hbWUgPSAoKHBvc2l0aW9uID09PSAnYmVmb3JlJyB8fCBwb3NpdGlvbiA9PT0gJ2FmdGVyJykgP1xuICAgICBlbGVtZW50LnBhcmVudE5vZGUgOiBlbGVtZW50KS50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG5cbiAgICB2YXIgY2hpbGROb2RlcyA9IGdldENvbnRlbnRGcm9tQW5vbnltb3VzRWxlbWVudCh0YWdOYW1lLCBjb250ZW50LnN0cmlwU2NyaXB0cygpKTtcblxuICAgIGlmIChwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgcG9zaXRpb24gPT09ICdhZnRlcicpIGNoaWxkTm9kZXMucmV2ZXJzZSgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIG5vZGU7IG5vZGUgPSBjaGlsZE5vZGVzW2ldOyBpKyspXG4gICAgICBtZXRob2QoZWxlbWVudCwgbm9kZSk7XG5cbiAgICBjb250ZW50LmV2YWxTY3JpcHRzLmJpbmQoY29udGVudCkuZGVmZXIoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluc2VydChlbGVtZW50LCBpbnNlcnRpb25zKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICBpZiAoaXNDb250ZW50KGluc2VydGlvbnMpKVxuICAgICAgaW5zZXJ0aW9ucyA9IHsgYm90dG9tOiBpbnNlcnRpb25zIH07XG5cbiAgICBmb3IgKHZhciBwb3NpdGlvbiBpbiBpbnNlcnRpb25zKVxuICAgICAgaW5zZXJ0Q29udGVudEF0KGVsZW1lbnQsIGluc2VydGlvbnNbcG9zaXRpb25dLCBwb3NpdGlvbik7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdyYXAoZWxlbWVudCwgd3JhcHBlciwgYXR0cmlidXRlcykge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXG4gICAgaWYgKE9iamVjdC5pc0VsZW1lbnQod3JhcHBlcikpIHtcbiAgICAgICQod3JhcHBlcikud3JpdGVBdHRyaWJ1dGUoYXR0cmlidXRlcyB8fCB7fSk7XG4gICAgfSBlbHNlIGlmIChPYmplY3QuaXNTdHJpbmcod3JhcHBlcikpIHtcbiAgICAgIHdyYXBwZXIgPSBuZXcgRWxlbWVudCh3cmFwcGVyLCBhdHRyaWJ1dGVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd3JhcHBlciA9IG5ldyBFbGVtZW50KCdkaXYnLCB3cmFwcGVyKTtcbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudC5wYXJlbnROb2RlKVxuICAgICAgZWxlbWVudC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZCh3cmFwcGVyLCBlbGVtZW50KTtcblxuICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG5cbiAgICByZXR1cm4gd3JhcHBlcjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNsZWFuV2hpdGVzcGFjZShlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIG5vZGUgPSBlbGVtZW50LmZpcnN0Q2hpbGQ7XG5cbiAgICB3aGlsZSAobm9kZSkge1xuICAgICAgdmFyIG5leHROb2RlID0gbm9kZS5uZXh0U2libGluZztcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSAmJiAhL1xcUy8udGVzdChub2RlLm5vZGVWYWx1ZSkpXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICBub2RlID0gbmV4dE5vZGU7XG4gICAgfVxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gZW1wdHkoZWxlbWVudCkge1xuICAgIHJldHVybiAkKGVsZW1lbnQpLmlubmVySFRNTC5ibGFuaygpO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Q29udGVudEZyb21Bbm9ueW1vdXNFbGVtZW50KHRhZ05hbWUsIGh0bWwsIGZvcmNlKSB7XG4gICAgdmFyIHQgPSBJTlNFUlRJT05fVFJBTlNMQVRJT05TLnRhZ3NbdGFnTmFtZV0sIGRpdiA9IERJVjtcblxuICAgIHZhciB3b3JrYXJvdW5kID0gISF0O1xuICAgIGlmICghd29ya2Fyb3VuZCAmJiBmb3JjZSkge1xuICAgICAgd29ya2Fyb3VuZCA9IHRydWU7XG4gICAgICB0ID0gWycnLCAnJywgMF07XG4gICAgfVxuXG4gICAgaWYgKHdvcmthcm91bmQpIHtcbiAgICAgIGRpdi5pbm5lckhUTUwgPSAnJiMxNjA7JyArIHRbMF0gKyBodG1sICsgdFsxXTtcbiAgICAgIGRpdi5yZW1vdmVDaGlsZChkaXYuZmlyc3RDaGlsZCk7XG4gICAgICBmb3IgKHZhciBpID0gdFsyXTsgaS0tOyApXG4gICAgICAgIGRpdiA9IGRpdi5maXJzdENoaWxkO1xuICAgIH0gZWxzZSB7XG4gICAgICBkaXYuaW5uZXJIVE1MID0gaHRtbDtcbiAgICB9XG5cbiAgICByZXR1cm4gJEEoZGl2LmNoaWxkTm9kZXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmUoZWxlbWVudCwgZGVlcCkge1xuICAgIGlmICghKGVsZW1lbnQgPSAkKGVsZW1lbnQpKSkgcmV0dXJuO1xuICAgIHZhciBjbG9uZSA9IGVsZW1lbnQuY2xvbmVOb2RlKGRlZXApO1xuICAgIGlmICghSEFTX1VOSVFVRV9JRF9QUk9QRVJUWSkge1xuICAgICAgY2xvbmUuX3Byb3RvdHlwZVVJRCA9IFVOREVGSU5FRDtcbiAgICAgIGlmIChkZWVwKSB7XG4gICAgICAgIHZhciBkZXNjZW5kYW50cyA9IEVsZW1lbnQuc2VsZWN0KGNsb25lLCAnKicpLFxuICAgICAgICAgaSA9IGRlc2NlbmRhbnRzLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGktLSlcbiAgICAgICAgICBkZXNjZW5kYW50c1tpXS5fcHJvdG90eXBlVUlEID0gVU5ERUZJTkVEO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gRWxlbWVudC5leHRlbmQoY2xvbmUpO1xuICB9XG5cbiAgZnVuY3Rpb24gcHVyZ2VFbGVtZW50KGVsZW1lbnQpIHtcbiAgICB2YXIgdWlkID0gZ2V0VW5pcXVlRWxlbWVudElEKGVsZW1lbnQpO1xuICAgIGlmICh1aWQpIHtcbiAgICAgIEVsZW1lbnQuc3RvcE9ic2VydmluZyhlbGVtZW50KTtcbiAgICAgIGlmICghSEFTX1VOSVFVRV9JRF9QUk9QRVJUWSlcbiAgICAgICAgZWxlbWVudC5fcHJvdG90eXBlVUlEID0gVU5ERUZJTkVEO1xuICAgICAgZGVsZXRlIEVsZW1lbnQuU3RvcmFnZVt1aWRdO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHB1cmdlQ29sbGVjdGlvbihlbGVtZW50cykge1xuICAgIHZhciBpID0gZWxlbWVudHMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pXG4gICAgICBwdXJnZUVsZW1lbnQoZWxlbWVudHNbaV0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcHVyZ2VDb2xsZWN0aW9uX0lFKGVsZW1lbnRzKSB7XG4gICAgdmFyIGkgPSBlbGVtZW50cy5sZW5ndGgsIGVsZW1lbnQsIHVpZDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBlbGVtZW50ID0gZWxlbWVudHNbaV07XG4gICAgICB1aWQgPSBnZXRVbmlxdWVFbGVtZW50SUQoZWxlbWVudCk7XG4gICAgICBkZWxldGUgRWxlbWVudC5TdG9yYWdlW3VpZF07XG4gICAgICBkZWxldGUgRXZlbnQuY2FjaGVbdWlkXTtcbiAgICB9XG4gIH1cblxuICBpZiAoSEFTX1VOSVFVRV9JRF9QUk9QRVJUWSkge1xuICAgIHB1cmdlQ29sbGVjdGlvbiA9IHB1cmdlQ29sbGVjdGlvbl9JRTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gcHVyZ2UoZWxlbWVudCkge1xuICAgIGlmICghKGVsZW1lbnQgPSAkKGVsZW1lbnQpKSkgcmV0dXJuO1xuICAgIHB1cmdlRWxlbWVudChlbGVtZW50KTtcblxuICAgIHZhciBkZXNjZW5kYW50cyA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJyonKSxcbiAgICAgaSA9IGRlc2NlbmRhbnRzLmxlbmd0aDtcblxuICAgIHdoaWxlIChpLS0pIHB1cmdlRWxlbWVudChkZXNjZW5kYW50c1tpXSk7XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIE9iamVjdC5leHRlbmQobWV0aG9kcywge1xuICAgIHJlbW92ZTogIHJlbW92ZSxcbiAgICB1cGRhdGU6ICB1cGRhdGUsXG4gICAgcmVwbGFjZTogcmVwbGFjZSxcbiAgICBpbnNlcnQ6ICBpbnNlcnQsXG4gICAgd3JhcDogICAgd3JhcCxcbiAgICBjbGVhbldoaXRlc3BhY2U6IGNsZWFuV2hpdGVzcGFjZSxcbiAgICBlbXB0eTogICBlbXB0eSxcbiAgICBjbG9uZTogICBjbG9uZSxcbiAgICBwdXJnZTogICBwdXJnZVxuICB9KTtcblxuXG5cbiAgZnVuY3Rpb24gcmVjdXJzaXZlbHlDb2xsZWN0KGVsZW1lbnQsIHByb3BlcnR5LCBtYXhpbXVtTGVuZ3RoKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgbWF4aW11bUxlbmd0aCA9IG1heGltdW1MZW5ndGggfHwgLTE7XG4gICAgdmFyIGVsZW1lbnRzID0gW107XG5cbiAgICB3aGlsZSAoZWxlbWVudCA9IGVsZW1lbnRbcHJvcGVydHldKSB7XG4gICAgICBpZiAoZWxlbWVudC5ub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUpXG4gICAgICAgIGVsZW1lbnRzLnB1c2goRWxlbWVudC5leHRlbmQoZWxlbWVudCkpO1xuXG4gICAgICBpZiAoZWxlbWVudHMubGVuZ3RoID09PSBtYXhpbXVtTGVuZ3RoKSBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudHM7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGFuY2VzdG9ycyhlbGVtZW50KSB7XG4gICAgcmV0dXJuIHJlY3Vyc2l2ZWx5Q29sbGVjdChlbGVtZW50LCAncGFyZW50Tm9kZScpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVzY2VuZGFudHMoZWxlbWVudCkge1xuICAgIHJldHVybiBFbGVtZW50LnNlbGVjdChlbGVtZW50LCAnKicpO1xuICB9XG5cbiAgZnVuY3Rpb24gZmlyc3REZXNjZW5kYW50KGVsZW1lbnQpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KS5maXJzdENoaWxkO1xuICAgIHdoaWxlIChlbGVtZW50ICYmIGVsZW1lbnQubm9kZVR5cGUgIT09IE5vZGUuRUxFTUVOVF9OT0RFKVxuICAgICAgZWxlbWVudCA9IGVsZW1lbnQubmV4dFNpYmxpbmc7XG5cbiAgICByZXR1cm4gJChlbGVtZW50KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGltbWVkaWF0ZURlc2NlbmRhbnRzKGVsZW1lbnQpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdLCBjaGlsZCA9ICQoZWxlbWVudCkuZmlyc3RDaGlsZDtcblxuICAgIHdoaWxlIChjaGlsZCkge1xuICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSlcbiAgICAgICAgcmVzdWx0cy5wdXNoKEVsZW1lbnQuZXh0ZW5kKGNoaWxkKSk7XG5cbiAgICAgIGNoaWxkID0gY2hpbGQubmV4dFNpYmxpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBmdW5jdGlvbiBwcmV2aW91c1NpYmxpbmdzKGVsZW1lbnQpIHtcbiAgICByZXR1cm4gcmVjdXJzaXZlbHlDb2xsZWN0KGVsZW1lbnQsICdwcmV2aW91c1NpYmxpbmcnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG5leHRTaWJsaW5ncyhlbGVtZW50KSB7XG4gICAgcmV0dXJuIHJlY3Vyc2l2ZWx5Q29sbGVjdChlbGVtZW50LCAnbmV4dFNpYmxpbmcnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNpYmxpbmdzKGVsZW1lbnQpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICB2YXIgcHJldmlvdXMgPSBwcmV2aW91c1NpYmxpbmdzKGVsZW1lbnQpLFxuICAgICBuZXh0ID0gbmV4dFNpYmxpbmdzKGVsZW1lbnQpO1xuICAgIHJldHVybiBwcmV2aW91cy5yZXZlcnNlKCkuY29uY2F0KG5leHQpO1xuICB9XG5cbiAgZnVuY3Rpb24gbWF0Y2goZWxlbWVudCwgc2VsZWN0b3IpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcblxuICAgIGlmIChPYmplY3QuaXNTdHJpbmcoc2VsZWN0b3IpKVxuICAgICAgcmV0dXJuIFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaChlbGVtZW50LCBzZWxlY3Rvcik7XG5cbiAgICByZXR1cm4gc2VsZWN0b3IubWF0Y2goZWxlbWVudCk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIF9yZWN1cnNpdmVseUZpbmQoZWxlbWVudCwgcHJvcGVydHksIGV4cHJlc3Npb24sIGluZGV4KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCksIGV4cHJlc3Npb24gPSBleHByZXNzaW9uIHx8IDAsIGluZGV4ID0gaW5kZXggfHwgMDtcbiAgICBpZiAoT2JqZWN0LmlzTnVtYmVyKGV4cHJlc3Npb24pKSB7XG4gICAgICBpbmRleCA9IGV4cHJlc3Npb24sIGV4cHJlc3Npb24gPSBudWxsO1xuICAgIH1cblxuICAgIHdoaWxlIChlbGVtZW50ID0gZWxlbWVudFtwcm9wZXJ0eV0pIHtcbiAgICAgIGlmIChlbGVtZW50Lm5vZGVUeXBlICE9PSAxKSBjb250aW51ZTtcbiAgICAgIGlmIChleHByZXNzaW9uICYmICFQcm90b3R5cGUuU2VsZWN0b3IubWF0Y2goZWxlbWVudCwgZXhwcmVzc2lvbikpXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgaWYgKC0taW5kZXggPj0gMCkgY29udGludWU7XG5cbiAgICAgIHJldHVybiBFbGVtZW50LmV4dGVuZChlbGVtZW50KTtcbiAgICB9XG4gIH1cblxuXG4gIGZ1bmN0aW9uIHVwKGVsZW1lbnQsIGV4cHJlc3Npb24sIGluZGV4KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuICQoZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICByZXR1cm4gX3JlY3Vyc2l2ZWx5RmluZChlbGVtZW50LCAncGFyZW50Tm9kZScsIGV4cHJlc3Npb24sIGluZGV4KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRvd24oZWxlbWVudCwgZXhwcmVzc2lvbiwgaW5kZXgpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIGZpcnN0RGVzY2VuZGFudChlbGVtZW50KTtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KSwgZXhwcmVzc2lvbiA9IGV4cHJlc3Npb24gfHwgMCwgaW5kZXggPSBpbmRleCB8fCAwO1xuXG4gICAgaWYgKE9iamVjdC5pc051bWJlcihleHByZXNzaW9uKSlcbiAgICAgIGluZGV4ID0gZXhwcmVzc2lvbiwgZXhwcmVzc2lvbiA9ICcqJztcblxuICAgIHZhciBub2RlID0gUHJvdG90eXBlLlNlbGVjdG9yLnNlbGVjdChleHByZXNzaW9uLCBlbGVtZW50KVtpbmRleF07XG4gICAgcmV0dXJuIEVsZW1lbnQuZXh0ZW5kKG5vZGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJldmlvdXMoZWxlbWVudCwgZXhwcmVzc2lvbiwgaW5kZXgpIHtcbiAgICByZXR1cm4gX3JlY3Vyc2l2ZWx5RmluZChlbGVtZW50LCAncHJldmlvdXNTaWJsaW5nJywgZXhwcmVzc2lvbiwgaW5kZXgpO1xuICB9XG5cbiAgZnVuY3Rpb24gbmV4dChlbGVtZW50LCBleHByZXNzaW9uLCBpbmRleCkge1xuICAgIHJldHVybiBfcmVjdXJzaXZlbHlGaW5kKGVsZW1lbnQsICduZXh0U2libGluZycsIGV4cHJlc3Npb24sIGluZGV4KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdChlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIGV4cHJlc3Npb25zID0gU0xJQ0UuY2FsbChhcmd1bWVudHMsIDEpLmpvaW4oJywgJyk7XG4gICAgcmV0dXJuIFByb3RvdHlwZS5TZWxlY3Rvci5zZWxlY3QoZXhwcmVzc2lvbnMsIGVsZW1lbnQpO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRqYWNlbnQoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBleHByZXNzaW9ucyA9IFNMSUNFLmNhbGwoYXJndW1lbnRzLCAxKS5qb2luKCcsICcpO1xuICAgIHZhciBzaWJsaW5ncyA9IEVsZW1lbnQuc2libGluZ3MoZWxlbWVudCksIHJlc3VsdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMCwgc2libGluZzsgc2libGluZyA9IHNpYmxpbmdzW2ldOyBpKyspIHtcbiAgICAgIGlmIChQcm90b3R5cGUuU2VsZWN0b3IubWF0Y2goc2libGluZywgZXhwcmVzc2lvbnMpKVxuICAgICAgICByZXN1bHRzLnB1c2goc2libGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBmdW5jdGlvbiBkZXNjZW5kYW50T2ZfRE9NKGVsZW1lbnQsIGFuY2VzdG9yKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCksIGFuY2VzdG9yID0gJChhbmNlc3Rvcik7XG4gICAgd2hpbGUgKGVsZW1lbnQgPSBlbGVtZW50LnBhcmVudE5vZGUpXG4gICAgICBpZiAoZWxlbWVudCA9PT0gYW5jZXN0b3IpIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlc2NlbmRhbnRPZl9jb250YWlucyhlbGVtZW50LCBhbmNlc3Rvcikge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpLCBhbmNlc3RvciA9ICQoYW5jZXN0b3IpO1xuICAgIGlmICghYW5jZXN0b3IuY29udGFpbnMpIHJldHVybiBkZXNjZW5kYW50T2ZfRE9NKGVsZW1lbnQsIGFuY2VzdG9yKTtcbiAgICByZXR1cm4gYW5jZXN0b3IuY29udGFpbnMoZWxlbWVudCkgJiYgYW5jZXN0b3IgIT09IGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiBkZXNjZW5kYW50T2ZfY29tcGFyZURvY3VtZW50UG9zaXRpb24oZWxlbWVudCwgYW5jZXN0b3IpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KSwgYW5jZXN0b3IgPSAkKGFuY2VzdG9yKTtcbiAgICByZXR1cm4gKGVsZW1lbnQuY29tcGFyZURvY3VtZW50UG9zaXRpb24oYW5jZXN0b3IpICYgOCkgPT09IDg7XG4gIH1cblxuICB2YXIgZGVzY2VuZGFudE9mO1xuICBpZiAoRElWLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKSB7XG4gICAgZGVzY2VuZGFudE9mID0gZGVzY2VuZGFudE9mX2NvbXBhcmVEb2N1bWVudFBvc2l0aW9uO1xuICB9IGVsc2UgaWYgKERJVi5jb250YWlucykge1xuICAgIGRlc2NlbmRhbnRPZiA9IGRlc2NlbmRhbnRPZl9jb250YWlucztcbiAgfSBlbHNlIHtcbiAgICBkZXNjZW5kYW50T2YgPSBkZXNjZW5kYW50T2ZfRE9NO1xuICB9XG5cblxuICBPYmplY3QuZXh0ZW5kKG1ldGhvZHMsIHtcbiAgICByZWN1cnNpdmVseUNvbGxlY3Q6ICAgcmVjdXJzaXZlbHlDb2xsZWN0LFxuICAgIGFuY2VzdG9yczogICAgICAgICAgICBhbmNlc3RvcnMsXG4gICAgZGVzY2VuZGFudHM6ICAgICAgICAgIGRlc2NlbmRhbnRzLFxuICAgIGZpcnN0RGVzY2VuZGFudDogICAgICBmaXJzdERlc2NlbmRhbnQsXG4gICAgaW1tZWRpYXRlRGVzY2VuZGFudHM6IGltbWVkaWF0ZURlc2NlbmRhbnRzLFxuICAgIHByZXZpb3VzU2libGluZ3M6ICAgICBwcmV2aW91c1NpYmxpbmdzLFxuICAgIG5leHRTaWJsaW5nczogICAgICAgICBuZXh0U2libGluZ3MsXG4gICAgc2libGluZ3M6ICAgICAgICAgICAgIHNpYmxpbmdzLFxuICAgIG1hdGNoOiAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICB1cDogICAgICAgICAgICAgICAgICAgdXAsXG4gICAgZG93bjogICAgICAgICAgICAgICAgIGRvd24sXG4gICAgcHJldmlvdXM6ICAgICAgICAgICAgIHByZXZpb3VzLFxuICAgIG5leHQ6ICAgICAgICAgICAgICAgICBuZXh0LFxuICAgIHNlbGVjdDogICAgICAgICAgICAgICBzZWxlY3QsXG4gICAgYWRqYWNlbnQ6ICAgICAgICAgICAgIGFkamFjZW50LFxuICAgIGRlc2NlbmRhbnRPZjogICAgICAgICBkZXNjZW5kYW50T2YsXG5cbiAgICBnZXRFbGVtZW50c0J5U2VsZWN0b3I6IHNlbGVjdCxcblxuICAgIGNoaWxkRWxlbWVudHM6ICAgICAgICAgaW1tZWRpYXRlRGVzY2VuZGFudHNcbiAgfSk7XG5cblxuICB2YXIgaWRDb3VudGVyID0gMTtcbiAgZnVuY3Rpb24gaWRlbnRpZnkoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBpZCA9IEVsZW1lbnQucmVhZEF0dHJpYnV0ZShlbGVtZW50LCAnaWQnKTtcbiAgICBpZiAoaWQpIHJldHVybiBpZDtcblxuICAgIGRvIHsgaWQgPSAnYW5vbnltb3VzX2VsZW1lbnRfJyArIGlkQ291bnRlcisrIH0gd2hpbGUgKCQoaWQpKTtcblxuICAgIEVsZW1lbnQud3JpdGVBdHRyaWJ1dGUoZWxlbWVudCwgJ2lkJywgaWQpO1xuICAgIHJldHVybiBpZDtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gcmVhZEF0dHJpYnV0ZShlbGVtZW50LCBuYW1lKSB7XG4gICAgcmV0dXJuICQoZWxlbWVudCkuZ2V0QXR0cmlidXRlKG5hbWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVhZEF0dHJpYnV0ZV9JRShlbGVtZW50LCBuYW1lKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICB2YXIgdGFibGUgPSBBVFRSSUJVVEVfVFJBTlNMQVRJT05TLnJlYWQ7XG4gICAgaWYgKHRhYmxlLnZhbHVlc1tuYW1lXSlcbiAgICAgIHJldHVybiB0YWJsZS52YWx1ZXNbbmFtZV0oZWxlbWVudCwgbmFtZSk7XG5cbiAgICBpZiAodGFibGUubmFtZXNbbmFtZV0pIG5hbWUgPSB0YWJsZS5uYW1lc1tuYW1lXTtcblxuICAgIGlmIChuYW1lLmluY2x1ZGUoJzonKSkge1xuICAgICAgaWYgKCFlbGVtZW50LmF0dHJpYnV0ZXMgfHwgIWVsZW1lbnQuYXR0cmlidXRlc1tuYW1lXSkgcmV0dXJuIG51bGw7XG4gICAgICByZXR1cm4gZWxlbWVudC5hdHRyaWJ1dGVzW25hbWVdLnZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50LmdldEF0dHJpYnV0ZShuYW1lKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWRBdHRyaWJ1dGVfT3BlcmEoZWxlbWVudCwgbmFtZSkge1xuICAgIGlmIChuYW1lID09PSAndGl0bGUnKSByZXR1cm4gZWxlbWVudC50aXRsZTtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUobmFtZSk7XG4gIH1cblxuICB2YXIgUFJPQkxFTUFUSUNfQVRUUklCVVRFX1JFQURJTkcgPSAoZnVuY3Rpb24oKSB7XG4gICAgRElWLnNldEF0dHJpYnV0ZSgnb25jbGljaycsIFtdKTtcbiAgICB2YXIgdmFsdWUgPSBESVYuZ2V0QXR0cmlidXRlKCdvbmNsaWNrJyk7XG4gICAgdmFyIGlzRnVuY3Rpb24gPSBPYmplY3QuaXNBcnJheSh2YWx1ZSk7XG4gICAgRElWLnJlbW92ZUF0dHJpYnV0ZSgnb25jbGljaycpO1xuICAgIHJldHVybiBpc0Z1bmN0aW9uO1xuICB9KSgpO1xuXG4gIGlmIChQUk9CTEVNQVRJQ19BVFRSSUJVVEVfUkVBRElORykge1xuICAgIHJlYWRBdHRyaWJ1dGUgPSByZWFkQXR0cmlidXRlX0lFO1xuICB9IGVsc2UgaWYgKFByb3RvdHlwZS5Ccm93c2VyLk9wZXJhKSB7XG4gICAgcmVhZEF0dHJpYnV0ZSA9IHJlYWRBdHRyaWJ1dGVfT3BlcmE7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIHdyaXRlQXR0cmlidXRlKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIGF0dHJpYnV0ZXMgPSB7fSwgdGFibGUgPSBBVFRSSUJVVEVfVFJBTlNMQVRJT05TLndyaXRlO1xuXG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSAnb2JqZWN0Jykge1xuICAgICAgYXR0cmlidXRlcyA9IG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF0dHJpYnV0ZXNbbmFtZV0gPSBPYmplY3QuaXNVbmRlZmluZWQodmFsdWUpID8gdHJ1ZSA6IHZhbHVlO1xuICAgIH1cblxuICAgIGZvciAodmFyIGF0dHIgaW4gYXR0cmlidXRlcykge1xuICAgICAgbmFtZSA9IHRhYmxlLm5hbWVzW2F0dHJdIHx8IGF0dHI7XG4gICAgICB2YWx1ZSA9IGF0dHJpYnV0ZXNbYXR0cl07XG4gICAgICBpZiAodGFibGUudmFsdWVzW2F0dHJdKVxuICAgICAgICBuYW1lID0gdGFibGUudmFsdWVzW2F0dHJdKGVsZW1lbnQsIHZhbHVlKSB8fCBuYW1lO1xuICAgICAgaWYgKHZhbHVlID09PSBmYWxzZSB8fCB2YWx1ZSA9PT0gbnVsbClcbiAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gICAgICBlbHNlIGlmICh2YWx1ZSA9PT0gdHJ1ZSlcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUobmFtZSwgbmFtZSk7XG4gICAgICBlbHNlIGVsZW1lbnQuc2V0QXR0cmlidXRlKG5hbWUsIHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHZhciBQUk9CTEVNQVRJQ19IQVNfQVRUUklCVVRFX1dJVEhfQ0hFQ0tCT1hFUyA9IChmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFIQVNfRVhURU5ERURfQ1JFQVRFX0VMRU1FTlRfU1lOVEFYKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHZhciBjaGVja2JveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJzxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIj4nKTtcbiAgICBjaGVja2JveC5jaGVja2VkID0gdHJ1ZTtcbiAgICB2YXIgbm9kZSA9IGNoZWNrYm94LmdldEF0dHJpYnV0ZU5vZGUoJ2NoZWNrZWQnKTtcbiAgICByZXR1cm4gIW5vZGUgfHwgIW5vZGUuc3BlY2lmaWVkO1xuICB9KSgpO1xuXG4gIGZ1bmN0aW9uIGhhc0F0dHJpYnV0ZShlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICBhdHRyaWJ1dGUgPSBBVFRSSUJVVEVfVFJBTlNMQVRJT05TLmhhc1thdHRyaWJ1dGVdIHx8IGF0dHJpYnV0ZTtcbiAgICB2YXIgbm9kZSA9ICQoZWxlbWVudCkuZ2V0QXR0cmlidXRlTm9kZShhdHRyaWJ1dGUpO1xuICAgIHJldHVybiAhIShub2RlICYmIG5vZGUuc3BlY2lmaWVkKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhc0F0dHJpYnV0ZV9JRShlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICBpZiAoYXR0cmlidXRlID09PSAnY2hlY2tlZCcpIHtcbiAgICAgIHJldHVybiBlbGVtZW50LmNoZWNrZWQ7XG4gICAgfVxuICAgIHJldHVybiBoYXNBdHRyaWJ1dGUoZWxlbWVudCwgYXR0cmlidXRlKTtcbiAgfVxuXG4gIEdMT0JBTC5FbGVtZW50Lk1ldGhvZHMuU2ltdWxhdGVkLmhhc0F0dHJpYnV0ZSA9XG4gICBQUk9CTEVNQVRJQ19IQVNfQVRUUklCVVRFX1dJVEhfQ0hFQ0tCT1hFUyA/XG4gICBoYXNBdHRyaWJ1dGVfSUUgOiBoYXNBdHRyaWJ1dGU7XG5cbiAgZnVuY3Rpb24gY2xhc3NOYW1lcyhlbGVtZW50KSB7XG4gICAgcmV0dXJuIG5ldyBFbGVtZW50LkNsYXNzTmFtZXMoZWxlbWVudCk7XG4gIH1cblxuICB2YXIgcmVnRXhwQ2FjaGUgPSB7fTtcbiAgZnVuY3Rpb24gZ2V0UmVnRXhwRm9yQ2xhc3NOYW1lKGNsYXNzTmFtZSkge1xuICAgIGlmIChyZWdFeHBDYWNoZVtjbGFzc05hbWVdKSByZXR1cm4gcmVnRXhwQ2FjaGVbY2xhc3NOYW1lXTtcblxuICAgIHZhciByZSA9IG5ldyBSZWdFeHAoXCIoXnxcXFxccyspXCIgKyBjbGFzc05hbWUgKyBcIihcXFxccyt8JClcIik7XG4gICAgcmVnRXhwQ2FjaGVbY2xhc3NOYW1lXSA9IHJlO1xuICAgIHJldHVybiByZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhc0NsYXNzTmFtZShlbGVtZW50LCBjbGFzc05hbWUpIHtcbiAgICBpZiAoIShlbGVtZW50ID0gJChlbGVtZW50KSkpIHJldHVybjtcblxuICAgIHZhciBlbGVtZW50Q2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWU7XG5cbiAgICBpZiAoZWxlbWVudENsYXNzTmFtZS5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgICBpZiAoZWxlbWVudENsYXNzTmFtZSA9PT0gY2xhc3NOYW1lKSByZXR1cm4gdHJ1ZTtcblxuICAgIHJldHVybiBnZXRSZWdFeHBGb3JDbGFzc05hbWUoY2xhc3NOYW1lKS50ZXN0KGVsZW1lbnRDbGFzc05hbWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRkQ2xhc3NOYW1lKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuICAgIGlmICghKGVsZW1lbnQgPSAkKGVsZW1lbnQpKSkgcmV0dXJuO1xuXG4gICAgaWYgKCFoYXNDbGFzc05hbWUoZWxlbWVudCwgY2xhc3NOYW1lKSlcbiAgICAgIGVsZW1lbnQuY2xhc3NOYW1lICs9IChlbGVtZW50LmNsYXNzTmFtZSA/ICcgJyA6ICcnKSArIGNsYXNzTmFtZTtcblxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlQ2xhc3NOYW1lKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuICAgIGlmICghKGVsZW1lbnQgPSAkKGVsZW1lbnQpKSkgcmV0dXJuO1xuXG4gICAgZWxlbWVudC5jbGFzc05hbWUgPSBlbGVtZW50LmNsYXNzTmFtZS5yZXBsYWNlKFxuICAgICBnZXRSZWdFeHBGb3JDbGFzc05hbWUoY2xhc3NOYW1lKSwgJyAnKS5zdHJpcCgpO1xuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiB0b2dnbGVDbGFzc05hbWUoZWxlbWVudCwgY2xhc3NOYW1lLCBib29sKSB7XG4gICAgaWYgKCEoZWxlbWVudCA9ICQoZWxlbWVudCkpKSByZXR1cm47XG5cbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKGJvb2wpKVxuICAgICAgYm9vbCA9ICFoYXNDbGFzc05hbWUoZWxlbWVudCwgY2xhc3NOYW1lKTtcblxuICAgIHZhciBtZXRob2QgPSBFbGVtZW50W2Jvb2wgPyAnYWRkQ2xhc3NOYW1lJyA6ICdyZW1vdmVDbGFzc05hbWUnXTtcbiAgICByZXR1cm4gbWV0aG9kKGVsZW1lbnQsIGNsYXNzTmFtZSk7XG4gIH1cblxuICB2YXIgQVRUUklCVVRFX1RSQU5TTEFUSU9OUyA9IHt9O1xuXG4gIHZhciBjbGFzc1Byb3AgPSAnY2xhc3NOYW1lJywgZm9yUHJvcCA9ICdmb3InO1xuXG4gIERJVi5zZXRBdHRyaWJ1dGUoY2xhc3NQcm9wLCAneCcpO1xuICBpZiAoRElWLmNsYXNzTmFtZSAhPT0gJ3gnKSB7XG4gICAgRElWLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAneCcpO1xuICAgIGlmIChESVYuY2xhc3NOYW1lID09PSAneCcpXG4gICAgICBjbGFzc1Byb3AgPSAnY2xhc3MnO1xuICB9XG5cbiAgdmFyIExBQkVMID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGFiZWwnKTtcbiAgTEFCRUwuc2V0QXR0cmlidXRlKGZvclByb3AsICd4Jyk7XG4gIGlmIChMQUJFTC5odG1sRm9yICE9PSAneCcpIHtcbiAgICBMQUJFTC5zZXRBdHRyaWJ1dGUoJ2h0bWxGb3InLCAneCcpO1xuICAgIGlmIChMQUJFTC5odG1sRm9yID09PSAneCcpXG4gICAgICBmb3JQcm9wID0gJ2h0bWxGb3InO1xuICB9XG4gIExBQkVMID0gbnVsbDtcblxuICBmdW5jdGlvbiBfZ2V0QXR0cihlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9nZXRBdHRyMihlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9nZXRBdHRyTm9kZShlbGVtZW50LCBhdHRyaWJ1dGUpIHtcbiAgICB2YXIgbm9kZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlTm9kZShhdHRyaWJ1dGUpO1xuICAgIHJldHVybiBub2RlID8gbm9kZS52YWx1ZSA6ICcnO1xuICB9XG5cbiAgZnVuY3Rpb24gX2dldEZsYWcoZWxlbWVudCwgYXR0cmlidXRlKSB7XG4gICAgcmV0dXJuICQoZWxlbWVudCkuaGFzQXR0cmlidXRlKGF0dHJpYnV0ZSkgPyBhdHRyaWJ1dGUgOiBudWxsO1xuICB9XG5cbiAgRElWLm9uY2xpY2sgPSBQcm90b3R5cGUuZW1wdHlGdW5jdGlvbjtcbiAgdmFyIG9uY2xpY2tWYWx1ZSA9IERJVi5nZXRBdHRyaWJ1dGUoJ29uY2xpY2snKTtcblxuICB2YXIgX2dldEV2O1xuXG4gIGlmIChTdHJpbmcob25jbGlja1ZhbHVlKS5pbmRleE9mKCd7JykgPiAtMSkge1xuICAgIF9nZXRFdiA9IGZ1bmN0aW9uKGVsZW1lbnQsIGF0dHJpYnV0ZSkge1xuICAgICAgdmFyIHZhbHVlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoYXR0cmlidXRlKTtcbiAgICAgIGlmICghdmFsdWUpIHJldHVybiBudWxsO1xuICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgdmFsdWUgPSB2YWx1ZS5zcGxpdCgneycpWzFdO1xuICAgICAgdmFsdWUgPSB2YWx1ZS5zcGxpdCgnfScpWzBdO1xuICAgICAgcmV0dXJuIHZhbHVlLnN0cmlwKCk7XG4gICAgfTtcbiAgfVxuICBlbHNlIGlmIChvbmNsaWNrVmFsdWUgPT09ICcnKSB7XG4gICAgX2dldEV2ID0gZnVuY3Rpb24oZWxlbWVudCwgYXR0cmlidXRlKSB7XG4gICAgICB2YXIgdmFsdWUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZShhdHRyaWJ1dGUpO1xuICAgICAgaWYgKCF2YWx1ZSkgcmV0dXJuIG51bGw7XG4gICAgICByZXR1cm4gdmFsdWUuc3RyaXAoKTtcbiAgICB9O1xuICB9XG5cbiAgQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5yZWFkID0ge1xuICAgIG5hbWVzOiB7XG4gICAgICAnY2xhc3MnOiAgICAgY2xhc3NQcm9wLFxuICAgICAgJ2NsYXNzTmFtZSc6IGNsYXNzUHJvcCxcbiAgICAgICdmb3InOiAgICAgICBmb3JQcm9wLFxuICAgICAgJ2h0bWxGb3InOiAgIGZvclByb3BcbiAgICB9LFxuXG4gICAgdmFsdWVzOiB7XG4gICAgICBzdHlsZTogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZWxlbWVudC5zdHlsZS5jc3NUZXh0LnRvTG93ZXJDYXNlKCk7XG4gICAgICB9LFxuICAgICAgdGl0bGU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQudGl0bGU7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIEFUVFJJQlVURV9UUkFOU0xBVElPTlMud3JpdGUgPSB7XG4gICAgbmFtZXM6IHtcbiAgICAgIGNsYXNzTmFtZTogICAnY2xhc3MnLFxuICAgICAgaHRtbEZvcjogICAgICdmb3InLFxuICAgICAgY2VsbHBhZGRpbmc6ICdjZWxsUGFkZGluZycsXG4gICAgICBjZWxsc3BhY2luZzogJ2NlbGxTcGFjaW5nJ1xuICAgIH0sXG5cbiAgICB2YWx1ZXM6IHtcbiAgICAgIGNoZWNrZWQ6IGZ1bmN0aW9uKGVsZW1lbnQsIHZhbHVlKSB7XG4gICAgICAgIGVsZW1lbnQuY2hlY2tlZCA9ICEhdmFsdWU7XG4gICAgICB9LFxuXG4gICAgICBzdHlsZTogZnVuY3Rpb24oZWxlbWVudCwgdmFsdWUpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS5jc3NUZXh0ID0gdmFsdWUgPyB2YWx1ZSA6ICcnO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBBVFRSSUJVVEVfVFJBTlNMQVRJT05TLmhhcyA9IHsgbmFtZXM6IHt9IH07XG5cbiAgT2JqZWN0LmV4dGVuZChBVFRSSUJVVEVfVFJBTlNMQVRJT05TLndyaXRlLm5hbWVzLFxuICAgQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5yZWFkLm5hbWVzKTtcblxuICB2YXIgQ0FNRUxfQ0FTRURfQVRUUklCVVRFX05BTUVTID0gJHcoJ2NvbFNwYW4gcm93U3BhbiB2QWxpZ24gZGF0ZVRpbWUgJyArXG4gICAnYWNjZXNzS2V5IHRhYkluZGV4IGVuY1R5cGUgbWF4TGVuZ3RoIHJlYWRPbmx5IGxvbmdEZXNjIGZyYW1lQm9yZGVyJyk7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGF0dHI7IGF0dHIgPSBDQU1FTF9DQVNFRF9BVFRSSUJVVEVfTkFNRVNbaV07IGkrKykge1xuICAgIEFUVFJJQlVURV9UUkFOU0xBVElPTlMud3JpdGUubmFtZXNbYXR0ci50b0xvd2VyQ2FzZSgpXSA9IGF0dHI7XG4gICAgQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5oYXMubmFtZXNbYXR0ci50b0xvd2VyQ2FzZSgpXSAgID0gYXR0cjtcbiAgfVxuXG4gIE9iamVjdC5leHRlbmQoQVRUUklCVVRFX1RSQU5TTEFUSU9OUy5yZWFkLnZhbHVlcywge1xuICAgIGhyZWY6ICAgICAgICBfZ2V0QXR0cjIsXG4gICAgc3JjOiAgICAgICAgIF9nZXRBdHRyMixcbiAgICB0eXBlOiAgICAgICAgX2dldEF0dHIsXG4gICAgYWN0aW9uOiAgICAgIF9nZXRBdHRyTm9kZSxcbiAgICBkaXNhYmxlZDogICAgX2dldEZsYWcsXG4gICAgY2hlY2tlZDogICAgIF9nZXRGbGFnLFxuICAgIHJlYWRvbmx5OiAgICBfZ2V0RmxhZyxcbiAgICBtdWx0aXBsZTogICAgX2dldEZsYWcsXG4gICAgb25sb2FkOiAgICAgIF9nZXRFdixcbiAgICBvbnVubG9hZDogICAgX2dldEV2LFxuICAgIG9uY2xpY2s6ICAgICBfZ2V0RXYsXG4gICAgb25kYmxjbGljazogIF9nZXRFdixcbiAgICBvbm1vdXNlZG93bjogX2dldEV2LFxuICAgIG9ubW91c2V1cDogICBfZ2V0RXYsXG4gICAgb25tb3VzZW92ZXI6IF9nZXRFdixcbiAgICBvbm1vdXNlbW92ZTogX2dldEV2LFxuICAgIG9ubW91c2VvdXQ6ICBfZ2V0RXYsXG4gICAgb25mb2N1czogICAgIF9nZXRFdixcbiAgICBvbmJsdXI6ICAgICAgX2dldEV2LFxuICAgIG9ua2V5cHJlc3M6ICBfZ2V0RXYsXG4gICAgb25rZXlkb3duOiAgIF9nZXRFdixcbiAgICBvbmtleXVwOiAgICAgX2dldEV2LFxuICAgIG9uc3VibWl0OiAgICBfZ2V0RXYsXG4gICAgb25yZXNldDogICAgIF9nZXRFdixcbiAgICBvbnNlbGVjdDogICAgX2dldEV2LFxuICAgIG9uY2hhbmdlOiAgICBfZ2V0RXZcbiAgfSk7XG5cblxuICBPYmplY3QuZXh0ZW5kKG1ldGhvZHMsIHtcbiAgICBpZGVudGlmeTogICAgICAgIGlkZW50aWZ5LFxuICAgIHJlYWRBdHRyaWJ1dGU6ICAgcmVhZEF0dHJpYnV0ZSxcbiAgICB3cml0ZUF0dHJpYnV0ZTogIHdyaXRlQXR0cmlidXRlLFxuICAgIGNsYXNzTmFtZXM6ICAgICAgY2xhc3NOYW1lcyxcbiAgICBoYXNDbGFzc05hbWU6ICAgIGhhc0NsYXNzTmFtZSxcbiAgICBhZGRDbGFzc05hbWU6ICAgIGFkZENsYXNzTmFtZSxcbiAgICByZW1vdmVDbGFzc05hbWU6IHJlbW92ZUNsYXNzTmFtZSxcbiAgICB0b2dnbGVDbGFzc05hbWU6IHRvZ2dsZUNsYXNzTmFtZVxuICB9KTtcblxuXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZVN0eWxlTmFtZShzdHlsZSkge1xuICAgIGlmIChzdHlsZSA9PT0gJ2Zsb2F0JyB8fCBzdHlsZSA9PT0gJ3N0eWxlRmxvYXQnKVxuICAgICAgcmV0dXJuICdjc3NGbG9hdCc7XG4gICAgcmV0dXJuIHN0eWxlLmNhbWVsaXplKCk7XG4gIH1cblxuICBmdW5jdGlvbiBub3JtYWxpemVTdHlsZU5hbWVfSUUoc3R5bGUpIHtcbiAgICBpZiAoc3R5bGUgPT09ICdmbG9hdCcgfHwgc3R5bGUgPT09ICdjc3NGbG9hdCcpXG4gICAgICByZXR1cm4gJ3N0eWxlRmxvYXQnO1xuICAgIHJldHVybiBzdHlsZS5jYW1lbGl6ZSgpO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0U3R5bGUoZWxlbWVudCwgc3R5bGVzKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIGVsZW1lbnRTdHlsZSA9IGVsZW1lbnQuc3R5bGUsIG1hdGNoO1xuXG4gICAgaWYgKE9iamVjdC5pc1N0cmluZyhzdHlsZXMpKSB7XG4gICAgICBlbGVtZW50U3R5bGUuY3NzVGV4dCArPSAnOycgKyBzdHlsZXM7XG4gICAgICBpZiAoc3R5bGVzLmluY2x1ZGUoJ29wYWNpdHknKSkge1xuICAgICAgICB2YXIgb3BhY2l0eSA9IHN0eWxlcy5tYXRjaCgvb3BhY2l0eTpcXHMqKFxcZD9cXC4/XFxkKikvKVsxXTtcbiAgICAgICAgRWxlbWVudC5zZXRPcGFjaXR5KGVsZW1lbnQsIG9wYWNpdHkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gc3R5bGVzKSB7XG4gICAgICBpZiAocHJvcGVydHkgPT09ICdvcGFjaXR5Jykge1xuICAgICAgICBFbGVtZW50LnNldE9wYWNpdHkoZWxlbWVudCwgc3R5bGVzW3Byb3BlcnR5XSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdmFsdWUgPSBzdHlsZXNbcHJvcGVydHldO1xuICAgICAgICBpZiAocHJvcGVydHkgPT09ICdmbG9hdCcgfHwgcHJvcGVydHkgPT09ICdjc3NGbG9hdCcpIHtcbiAgICAgICAgICBwcm9wZXJ0eSA9IE9iamVjdC5pc1VuZGVmaW5lZChlbGVtZW50U3R5bGUuc3R5bGVGbG9hdCkgP1xuICAgICAgICAgICAnY3NzRmxvYXQnIDogJ3N0eWxlRmxvYXQnO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnRTdHlsZVtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gZ2V0U3R5bGUoZWxlbWVudCwgc3R5bGUpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICBzdHlsZSA9IG5vcm1hbGl6ZVN0eWxlTmFtZShzdHlsZSk7XG5cbiAgICB2YXIgdmFsdWUgPSBlbGVtZW50LnN0eWxlW3N0eWxlXTtcbiAgICBpZiAoIXZhbHVlIHx8IHZhbHVlID09PSAnYXV0bycpIHtcbiAgICAgIHZhciBjc3MgPSBkb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQsIG51bGwpO1xuICAgICAgdmFsdWUgPSBjc3MgPyBjc3Nbc3R5bGVdIDogbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoc3R5bGUgPT09ICdvcGFjaXR5JykgcmV0dXJuIHZhbHVlID8gcGFyc2VGbG9hdCh2YWx1ZSkgOiAxLjA7XG4gICAgcmV0dXJuIHZhbHVlID09PSAnYXV0bycgPyBudWxsIDogdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTdHlsZV9PcGVyYShlbGVtZW50LCBzdHlsZSkge1xuICAgIHN3aXRjaCAoc3R5bGUpIHtcbiAgICAgIGNhc2UgJ2hlaWdodCc6IGNhc2UgJ3dpZHRoJzpcbiAgICAgICAgaWYgKCFFbGVtZW50LnZpc2libGUoZWxlbWVudCkpIHJldHVybiBudWxsO1xuXG4gICAgICAgIHZhciBkaW0gPSBwYXJzZUludChnZXRTdHlsZShlbGVtZW50LCBzdHlsZSksIDEwKTtcblxuICAgICAgICBpZiAoZGltICE9PSBlbGVtZW50WydvZmZzZXQnICsgc3R5bGUuY2FwaXRhbGl6ZSgpXSlcbiAgICAgICAgICByZXR1cm4gZGltICsgJ3B4JztcblxuICAgICAgICByZXR1cm4gRWxlbWVudC5tZWFzdXJlKGVsZW1lbnQsIHN0eWxlKTtcblxuICAgICAgZGVmYXVsdDogcmV0dXJuIGdldFN0eWxlKGVsZW1lbnQsIHN0eWxlKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTdHlsZV9JRShlbGVtZW50LCBzdHlsZSkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHN0eWxlID0gbm9ybWFsaXplU3R5bGVOYW1lX0lFKHN0eWxlKTtcblxuICAgIHZhciB2YWx1ZSA9IGVsZW1lbnQuc3R5bGVbc3R5bGVdO1xuICAgIGlmICghdmFsdWUgJiYgZWxlbWVudC5jdXJyZW50U3R5bGUpIHtcbiAgICAgIHZhbHVlID0gZWxlbWVudC5jdXJyZW50U3R5bGVbc3R5bGVdO1xuICAgIH1cblxuICAgIGlmIChzdHlsZSA9PT0gJ29wYWNpdHknICYmICFTVEFOREFSRF9DU1NfT1BBQ0lUWV9TVVBQT1JURUQpXG4gICAgICByZXR1cm4gZ2V0T3BhY2l0eV9JRShlbGVtZW50KTtcblxuICAgIGlmICh2YWx1ZSA9PT0gJ2F1dG8nKSB7XG4gICAgICBpZiAoKHN0eWxlID09PSAnd2lkdGgnIHx8IHN0eWxlID09PSAnaGVpZ2h0JykgJiYgRWxlbWVudC52aXNpYmxlKGVsZW1lbnQpKVxuICAgICAgICByZXR1cm4gRWxlbWVudC5tZWFzdXJlKGVsZW1lbnQsIHN0eWxlKSArICdweCc7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiBzdHJpcEFscGhhRnJvbUZpbHRlcl9JRShmaWx0ZXIpIHtcbiAgICByZXR1cm4gKGZpbHRlciB8fCAnJykucmVwbGFjZSgvYWxwaGFcXChbXlxcKV0qXFwpL2dpLCAnJyk7XG4gIH1cblxuICBmdW5jdGlvbiBoYXNMYXlvdXRfSUUoZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5jdXJyZW50U3R5bGUgfHwgIWVsZW1lbnQuY3VycmVudFN0eWxlLmhhc0xheW91dClcbiAgICAgIGVsZW1lbnQuc3R5bGUuem9vbSA9IDE7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICB2YXIgU1RBTkRBUkRfQ1NTX09QQUNJVFlfU1VQUE9SVEVEID0gKGZ1bmN0aW9uKCkge1xuICAgIERJVi5zdHlsZS5jc3NUZXh0ID0gXCJvcGFjaXR5Oi41NVwiO1xuICAgIHJldHVybiAvXjAuNTUvLnRlc3QoRElWLnN0eWxlLm9wYWNpdHkpO1xuICB9KSgpO1xuXG4gIGZ1bmN0aW9uIHNldE9wYWNpdHkoZWxlbWVudCwgdmFsdWUpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICBpZiAodmFsdWUgPT0gMSB8fCB2YWx1ZSA9PT0gJycpIHZhbHVlID0gJyc7XG4gICAgZWxzZSBpZiAodmFsdWUgPCAwLjAwMDAxKSB2YWx1ZSA9IDA7XG4gICAgZWxlbWVudC5zdHlsZS5vcGFjaXR5ID0gdmFsdWU7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRPcGFjaXR5X0lFKGVsZW1lbnQsIHZhbHVlKSB7XG4gICAgaWYgKFNUQU5EQVJEX0NTU19PUEFDSVRZX1NVUFBPUlRFRClcbiAgICAgIHJldHVybiBzZXRPcGFjaXR5KGVsZW1lbnQsIHZhbHVlKTtcblxuICAgIGVsZW1lbnQgPSBoYXNMYXlvdXRfSUUoJChlbGVtZW50KSk7XG4gICAgdmFyIGZpbHRlciA9IEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ2ZpbHRlcicpLFxuICAgICBzdHlsZSA9IGVsZW1lbnQuc3R5bGU7XG5cbiAgICBpZiAodmFsdWUgPT0gMSB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgIGZpbHRlciA9IHN0cmlwQWxwaGFGcm9tRmlsdGVyX0lFKGZpbHRlcik7XG4gICAgICBpZiAoZmlsdGVyKSBzdHlsZS5maWx0ZXIgPSBmaWx0ZXI7XG4gICAgICBlbHNlIHN0eWxlLnJlbW92ZUF0dHJpYnV0ZSgnZmlsdGVyJyk7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgPCAwLjAwMDAxKSB2YWx1ZSA9IDA7XG5cbiAgICBzdHlsZS5maWx0ZXIgPSBzdHJpcEFscGhhRnJvbUZpbHRlcl9JRShmaWx0ZXIpICtcbiAgICAgJ2FscGhhKG9wYWNpdHk9JyArICh2YWx1ZSAqIDEwMCkgKyAnKSc7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gZ2V0T3BhY2l0eShlbGVtZW50KSB7XG4gICAgcmV0dXJuIEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ29wYWNpdHknKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldE9wYWNpdHlfSUUoZWxlbWVudCkge1xuICAgIGlmIChTVEFOREFSRF9DU1NfT1BBQ0lUWV9TVVBQT1JURUQpXG4gICAgICByZXR1cm4gZ2V0T3BhY2l0eShlbGVtZW50KTtcblxuICAgIHZhciBmaWx0ZXIgPSBFbGVtZW50LmdldFN0eWxlKGVsZW1lbnQsICdmaWx0ZXInKTtcbiAgICBpZiAoZmlsdGVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuIDEuMDtcbiAgICB2YXIgbWF0Y2ggPSAoZmlsdGVyIHx8ICcnKS5tYXRjaCgvYWxwaGFcXChvcGFjaXR5PSguKilcXCkvKTtcbiAgICBpZiAobWF0Y2ggJiYgbWF0Y2hbMV0pIHJldHVybiBwYXJzZUZsb2F0KG1hdGNoWzFdKSAvIDEwMDtcbiAgICByZXR1cm4gMS4wO1xuICB9XG5cblxuICBPYmplY3QuZXh0ZW5kKG1ldGhvZHMsIHtcbiAgICBzZXRTdHlsZTogICBzZXRTdHlsZSxcbiAgICBnZXRTdHlsZTogICBnZXRTdHlsZSxcbiAgICBzZXRPcGFjaXR5OiBzZXRPcGFjaXR5LFxuICAgIGdldE9wYWNpdHk6IGdldE9wYWNpdHlcbiAgfSk7XG5cbiAgaWYgKCdzdHlsZUZsb2F0JyBpbiBESVYuc3R5bGUpIHtcbiAgICBtZXRob2RzLmdldFN0eWxlID0gZ2V0U3R5bGVfSUU7XG4gICAgbWV0aG9kcy5zZXRPcGFjaXR5ID0gc2V0T3BhY2l0eV9JRTtcbiAgICBtZXRob2RzLmdldE9wYWNpdHkgPSBnZXRPcGFjaXR5X0lFO1xuICB9XG5cbiAgdmFyIFVJRCA9IDA7XG5cbiAgR0xPQkFMLkVsZW1lbnQuU3RvcmFnZSA9IHsgVUlEOiAxIH07XG5cbiAgZnVuY3Rpb24gZ2V0VW5pcXVlRWxlbWVudElEKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudCA9PT0gd2luZG93KSByZXR1cm4gMDtcblxuICAgIGlmICh0eXBlb2YgZWxlbWVudC5fcHJvdG90eXBlVUlEID09PSAndW5kZWZpbmVkJylcbiAgICAgIGVsZW1lbnQuX3Byb3RvdHlwZVVJRCA9IEVsZW1lbnQuU3RvcmFnZS5VSUQrKztcbiAgICByZXR1cm4gZWxlbWVudC5fcHJvdG90eXBlVUlEO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0VW5pcXVlRWxlbWVudElEX0lFKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudCA9PT0gd2luZG93KSByZXR1cm4gMDtcbiAgICBpZiAoZWxlbWVudCA9PSBkb2N1bWVudCkgcmV0dXJuIDE7XG4gICAgcmV0dXJuIGVsZW1lbnQudW5pcXVlSUQ7XG4gIH1cblxuICB2YXIgSEFTX1VOSVFVRV9JRF9QUk9QRVJUWSA9ICgndW5pcXVlSUQnIGluIERJVik7XG4gIGlmIChIQVNfVU5JUVVFX0lEX1BST1BFUlRZKVxuICAgIGdldFVuaXF1ZUVsZW1lbnRJRCA9IGdldFVuaXF1ZUVsZW1lbnRJRF9JRTtcblxuICBmdW5jdGlvbiBnZXRTdG9yYWdlKGVsZW1lbnQpIHtcbiAgICBpZiAoIShlbGVtZW50ID0gJChlbGVtZW50KSkpIHJldHVybjtcblxuICAgIHZhciB1aWQgPSBnZXRVbmlxdWVFbGVtZW50SUQoZWxlbWVudCk7XG5cbiAgICBpZiAoIUVsZW1lbnQuU3RvcmFnZVt1aWRdKVxuICAgICAgRWxlbWVudC5TdG9yYWdlW3VpZF0gPSAkSCgpO1xuXG4gICAgcmV0dXJuIEVsZW1lbnQuU3RvcmFnZVt1aWRdO1xuICB9XG5cbiAgZnVuY3Rpb24gc3RvcmUoZWxlbWVudCwga2V5LCB2YWx1ZSkge1xuICAgIGlmICghKGVsZW1lbnQgPSAkKGVsZW1lbnQpKSkgcmV0dXJuO1xuICAgIHZhciBzdG9yYWdlID0gZ2V0U3RvcmFnZShlbGVtZW50KTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgc3RvcmFnZS51cGRhdGUoa2V5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RvcmFnZS5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gcmV0cmlldmUoZWxlbWVudCwga2V5LCBkZWZhdWx0VmFsdWUpIHtcbiAgICBpZiAoIShlbGVtZW50ID0gJChlbGVtZW50KSkpIHJldHVybjtcbiAgICB2YXIgc3RvcmFnZSA9IGdldFN0b3JhZ2UoZWxlbWVudCksIHZhbHVlID0gc3RvcmFnZS5nZXQoa2V5KTtcblxuICAgIGlmIChPYmplY3QuaXNVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgICBzdG9yYWdlLnNldChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICB2YWx1ZSA9IGRlZmF1bHRWYWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuXG4gIE9iamVjdC5leHRlbmQobWV0aG9kcywge1xuICAgIGdldFN0b3JhZ2U6IGdldFN0b3JhZ2UsXG4gICAgc3RvcmU6ICAgICAgc3RvcmUsXG4gICAgcmV0cmlldmU6ICAgcmV0cmlldmVcbiAgfSk7XG5cblxuICB2YXIgTWV0aG9kcyA9IHt9LCBCeVRhZyA9IEVsZW1lbnQuTWV0aG9kcy5CeVRhZyxcbiAgIEYgPSBQcm90b3R5cGUuQnJvd3NlckZlYXR1cmVzO1xuXG4gIGlmICghRi5FbGVtZW50RXh0ZW5zaW9ucyAmJiAoJ19fcHJvdG9fXycgaW4gRElWKSkge1xuICAgIEdMT0JBTC5IVE1MRWxlbWVudCA9IHt9O1xuICAgIEdMT0JBTC5IVE1MRWxlbWVudC5wcm90b3R5cGUgPSBESVZbJ19fcHJvdG9fXyddO1xuICAgIEYuRWxlbWVudEV4dGVuc2lvbnMgPSB0cnVlO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tFbGVtZW50UHJvdG90eXBlRGVmaWNpZW5jeSh0YWdOYW1lKSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cuRWxlbWVudCA9PT0gJ3VuZGVmaW5lZCcpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIUhBU19FWFRFTkRFRF9DUkVBVEVfRUxFTUVOVF9TWU5UQVgpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgcHJvdG8gPSB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGU7XG4gICAgaWYgKHByb3RvKSB7XG4gICAgICB2YXIgaWQgPSAnXycgKyAoTWF0aC5yYW5kb20oKSArICcnKS5zbGljZSgyKSxcbiAgICAgICBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSk7XG4gICAgICBwcm90b1tpZF0gPSAneCc7XG4gICAgICB2YXIgaXNCdWdneSA9IChlbFtpZF0gIT09ICd4Jyk7XG4gICAgICBkZWxldGUgcHJvdG9baWRdO1xuICAgICAgZWwgPSBudWxsO1xuICAgICAgcmV0dXJuIGlzQnVnZ3k7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIEhUTUxPQkpFQ1RFTEVNRU5UX1BST1RPVFlQRV9CVUdHWSA9XG4gICBjaGVja0VsZW1lbnRQcm90b3R5cGVEZWZpY2llbmN5KCdvYmplY3QnKTtcblxuICBmdW5jdGlvbiBleHRlbmRFbGVtZW50V2l0aChlbGVtZW50LCBtZXRob2RzKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gbWV0aG9kcykge1xuICAgICAgdmFyIHZhbHVlID0gbWV0aG9kc1twcm9wZXJ0eV07XG4gICAgICBpZiAoT2JqZWN0LmlzRnVuY3Rpb24odmFsdWUpICYmICEocHJvcGVydHkgaW4gZWxlbWVudCkpXG4gICAgICAgIGVsZW1lbnRbcHJvcGVydHldID0gdmFsdWUubWV0aG9kaXplKCk7XG4gICAgfVxuICB9XG5cbiAgdmFyIEVYVEVOREVEID0ge307XG4gIGZ1bmN0aW9uIGVsZW1lbnRJc0V4dGVuZGVkKGVsZW1lbnQpIHtcbiAgICB2YXIgdWlkID0gZ2V0VW5pcXVlRWxlbWVudElEKGVsZW1lbnQpO1xuICAgIHJldHVybiAodWlkIGluIEVYVEVOREVEKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGV4dGVuZChlbGVtZW50KSB7XG4gICAgaWYgKCFlbGVtZW50IHx8IGVsZW1lbnRJc0V4dGVuZGVkKGVsZW1lbnQpKSByZXR1cm4gZWxlbWVudDtcbiAgICBpZiAoZWxlbWVudC5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREUgfHwgZWxlbWVudCA9PSB3aW5kb3cpXG4gICAgICByZXR1cm4gZWxlbWVudDtcblxuICAgIHZhciBtZXRob2RzID0gT2JqZWN0LmNsb25lKE1ldGhvZHMpLFxuICAgICB0YWdOYW1lID0gZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG5cbiAgICBpZiAoQnlUYWdbdGFnTmFtZV0pIE9iamVjdC5leHRlbmQobWV0aG9kcywgQnlUYWdbdGFnTmFtZV0pO1xuXG4gICAgZXh0ZW5kRWxlbWVudFdpdGgoZWxlbWVudCwgbWV0aG9kcyk7XG4gICAgRVhURU5ERURbZ2V0VW5pcXVlRWxlbWVudElEKGVsZW1lbnQpXSA9IHRydWU7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiBleHRlbmRfSUU4KGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQgfHwgZWxlbWVudElzRXh0ZW5kZWQoZWxlbWVudCkpIHJldHVybiBlbGVtZW50O1xuXG4gICAgdmFyIHQgPSBlbGVtZW50LnRhZ05hbWU7XG4gICAgaWYgKHQgJiYgKC9eKD86b2JqZWN0fGFwcGxldHxlbWJlZCkkL2kudGVzdCh0KSkpIHtcbiAgICAgIGV4dGVuZEVsZW1lbnRXaXRoKGVsZW1lbnQsIEVsZW1lbnQuTWV0aG9kcyk7XG4gICAgICBleHRlbmRFbGVtZW50V2l0aChlbGVtZW50LCBFbGVtZW50Lk1ldGhvZHMuU2ltdWxhdGVkKTtcbiAgICAgIGV4dGVuZEVsZW1lbnRXaXRoKGVsZW1lbnQsIEVsZW1lbnQuTWV0aG9kcy5CeVRhZ1t0LnRvVXBwZXJDYXNlKCldKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGlmIChGLlNwZWNpZmljRWxlbWVudEV4dGVuc2lvbnMpIHtcbiAgICBleHRlbmQgPSBIVE1MT0JKRUNURUxFTUVOVF9QUk9UT1RZUEVfQlVHR1kgPyBleHRlbmRfSUU4IDogUHJvdG90eXBlLks7XG4gIH1cblxuICBmdW5jdGlvbiBhZGRNZXRob2RzVG9UYWdOYW1lKHRhZ05hbWUsIG1ldGhvZHMpIHtcbiAgICB0YWdOYW1lID0gdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmICghQnlUYWdbdGFnTmFtZV0pIEJ5VGFnW3RhZ05hbWVdID0ge307XG4gICAgT2JqZWN0LmV4dGVuZChCeVRhZ1t0YWdOYW1lXSwgbWV0aG9kcyk7XG4gIH1cblxuICBmdW5jdGlvbiBtZXJnZU1ldGhvZHMoZGVzdGluYXRpb24sIG1ldGhvZHMsIG9ubHlJZkFic2VudCkge1xuICAgIGlmIChPYmplY3QuaXNVbmRlZmluZWQob25seUlmQWJzZW50KSkgb25seUlmQWJzZW50ID0gZmFsc2U7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gbWV0aG9kcykge1xuICAgICAgdmFyIHZhbHVlID0gbWV0aG9kc1twcm9wZXJ0eV07XG4gICAgICBpZiAoIU9iamVjdC5pc0Z1bmN0aW9uKHZhbHVlKSkgY29udGludWU7XG4gICAgICBpZiAoIW9ubHlJZkFic2VudCB8fCAhKHByb3BlcnR5IGluIGRlc3RpbmF0aW9uKSlcbiAgICAgICAgZGVzdGluYXRpb25bcHJvcGVydHldID0gdmFsdWUubWV0aG9kaXplKCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZmluZERPTUNsYXNzKHRhZ05hbWUpIHtcbiAgICB2YXIga2xhc3M7XG4gICAgdmFyIHRyYW5zID0ge1xuICAgICAgXCJPUFRHUk9VUFwiOiBcIk9wdEdyb3VwXCIsIFwiVEVYVEFSRUFcIjogXCJUZXh0QXJlYVwiLCBcIlBcIjogXCJQYXJhZ3JhcGhcIixcbiAgICAgIFwiRklFTERTRVRcIjogXCJGaWVsZFNldFwiLCBcIlVMXCI6IFwiVUxpc3RcIiwgXCJPTFwiOiBcIk9MaXN0XCIsIFwiRExcIjogXCJETGlzdFwiLFxuICAgICAgXCJESVJcIjogXCJEaXJlY3RvcnlcIiwgXCJIMVwiOiBcIkhlYWRpbmdcIiwgXCJIMlwiOiBcIkhlYWRpbmdcIiwgXCJIM1wiOiBcIkhlYWRpbmdcIixcbiAgICAgIFwiSDRcIjogXCJIZWFkaW5nXCIsIFwiSDVcIjogXCJIZWFkaW5nXCIsIFwiSDZcIjogXCJIZWFkaW5nXCIsIFwiUVwiOiBcIlF1b3RlXCIsXG4gICAgICBcIklOU1wiOiBcIk1vZFwiLCBcIkRFTFwiOiBcIk1vZFwiLCBcIkFcIjogXCJBbmNob3JcIiwgXCJJTUdcIjogXCJJbWFnZVwiLCBcIkNBUFRJT05cIjpcbiAgICAgIFwiVGFibGVDYXB0aW9uXCIsIFwiQ09MXCI6IFwiVGFibGVDb2xcIiwgXCJDT0xHUk9VUFwiOiBcIlRhYmxlQ29sXCIsIFwiVEhFQURcIjpcbiAgICAgIFwiVGFibGVTZWN0aW9uXCIsIFwiVEZPT1RcIjogXCJUYWJsZVNlY3Rpb25cIiwgXCJUQk9EWVwiOiBcIlRhYmxlU2VjdGlvblwiLCBcIlRSXCI6XG4gICAgICBcIlRhYmxlUm93XCIsIFwiVEhcIjogXCJUYWJsZUNlbGxcIiwgXCJURFwiOiBcIlRhYmxlQ2VsbFwiLCBcIkZSQU1FU0VUXCI6XG4gICAgICBcIkZyYW1lU2V0XCIsIFwiSUZSQU1FXCI6IFwiSUZyYW1lXCJcbiAgICB9O1xuICAgIGlmICh0cmFuc1t0YWdOYW1lXSkga2xhc3MgPSAnSFRNTCcgKyB0cmFuc1t0YWdOYW1lXSArICdFbGVtZW50JztcbiAgICBpZiAod2luZG93W2tsYXNzXSkgcmV0dXJuIHdpbmRvd1trbGFzc107XG4gICAga2xhc3MgPSAnSFRNTCcgKyB0YWdOYW1lICsgJ0VsZW1lbnQnO1xuICAgIGlmICh3aW5kb3dba2xhc3NdKSByZXR1cm4gd2luZG93W2tsYXNzXTtcbiAgICBrbGFzcyA9ICdIVE1MJyArIHRhZ05hbWUuY2FwaXRhbGl6ZSgpICsgJ0VsZW1lbnQnO1xuICAgIGlmICh3aW5kb3dba2xhc3NdKSByZXR1cm4gd2luZG93W2tsYXNzXTtcblxuICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKSxcbiAgICAgcHJvdG8gPSBlbGVtZW50WydfX3Byb3RvX18nXSB8fCBlbGVtZW50LmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcblxuICAgIGVsZW1lbnQgPSBudWxsO1xuICAgIHJldHVybiBwcm90bztcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZE1ldGhvZHMobWV0aG9kcykge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSBhZGRGb3JtTWV0aG9kcygpO1xuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHtcbiAgICAgIHZhciB0YWdOYW1lID0gbWV0aG9kcztcbiAgICAgIG1ldGhvZHMgPSBhcmd1bWVudHNbMV07XG4gICAgfVxuXG4gICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICBPYmplY3QuZXh0ZW5kKEVsZW1lbnQuTWV0aG9kcywgbWV0aG9kcyB8fCB7fSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChPYmplY3QuaXNBcnJheSh0YWdOYW1lKSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgdGFnOyB0YWcgPSB0YWdOYW1lW2ldOyBpKyspXG4gICAgICAgICAgYWRkTWV0aG9kc1RvVGFnTmFtZSh0YWcsIG1ldGhvZHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWRkTWV0aG9kc1RvVGFnTmFtZSh0YWdOYW1lLCBtZXRob2RzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgRUxFTUVOVF9QUk9UT1RZUEUgPSB3aW5kb3cuSFRNTEVsZW1lbnQgPyBIVE1MRWxlbWVudC5wcm90b3R5cGUgOlxuICAgICBFbGVtZW50LnByb3RvdHlwZTtcblxuICAgIGlmIChGLkVsZW1lbnRFeHRlbnNpb25zKSB7XG4gICAgICBtZXJnZU1ldGhvZHMoRUxFTUVOVF9QUk9UT1RZUEUsIEVsZW1lbnQuTWV0aG9kcyk7XG4gICAgICBtZXJnZU1ldGhvZHMoRUxFTUVOVF9QUk9UT1RZUEUsIEVsZW1lbnQuTWV0aG9kcy5TaW11bGF0ZWQsIHRydWUpO1xuICAgIH1cblxuICAgIGlmIChGLlNwZWNpZmljRWxlbWVudEV4dGVuc2lvbnMpIHtcbiAgICAgIGZvciAodmFyIHRhZyBpbiBFbGVtZW50Lk1ldGhvZHMuQnlUYWcpIHtcbiAgICAgICAgdmFyIGtsYXNzID0gZmluZERPTUNsYXNzKHRhZyk7XG4gICAgICAgIGlmIChPYmplY3QuaXNVbmRlZmluZWQoa2xhc3MpKSBjb250aW51ZTtcbiAgICAgICAgbWVyZ2VNZXRob2RzKGtsYXNzLnByb3RvdHlwZSwgQnlUYWdbdGFnXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgT2JqZWN0LmV4dGVuZChFbGVtZW50LCBFbGVtZW50Lk1ldGhvZHMpO1xuICAgIE9iamVjdC5leHRlbmQoRWxlbWVudCwgRWxlbWVudC5NZXRob2RzLlNpbXVsYXRlZCk7XG4gICAgZGVsZXRlIEVsZW1lbnQuQnlUYWc7XG4gICAgZGVsZXRlIEVsZW1lbnQuU2ltdWxhdGVkO1xuXG4gICAgRWxlbWVudC5leHRlbmQucmVmcmVzaCgpO1xuXG4gICAgRUxFTUVOVF9DQUNIRSA9IHt9O1xuICB9XG5cbiAgT2JqZWN0LmV4dGVuZChHTE9CQUwuRWxlbWVudCwge1xuICAgIGV4dGVuZDogICAgIGV4dGVuZCxcbiAgICBhZGRNZXRob2RzOiBhZGRNZXRob2RzXG4gIH0pO1xuXG4gIGlmIChleHRlbmQgPT09IFByb3RvdHlwZS5LKSB7XG4gICAgR0xPQkFMLkVsZW1lbnQuZXh0ZW5kLnJlZnJlc2ggPSBQcm90b3R5cGUuZW1wdHlGdW5jdGlvbjtcbiAgfSBlbHNlIHtcbiAgICBHTE9CQUwuRWxlbWVudC5leHRlbmQucmVmcmVzaCA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKFByb3RvdHlwZS5Ccm93c2VyRmVhdHVyZXMuRWxlbWVudEV4dGVuc2lvbnMpIHJldHVybjtcbiAgICAgIE9iamVjdC5leHRlbmQoTWV0aG9kcywgRWxlbWVudC5NZXRob2RzKTtcbiAgICAgIE9iamVjdC5leHRlbmQoTWV0aG9kcywgRWxlbWVudC5NZXRob2RzLlNpbXVsYXRlZCk7XG5cbiAgICAgIEVYVEVOREVEID0ge307XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZEZvcm1NZXRob2RzKCkge1xuICAgIE9iamVjdC5leHRlbmQoRm9ybSwgRm9ybS5NZXRob2RzKTtcbiAgICBPYmplY3QuZXh0ZW5kKEZvcm0uRWxlbWVudCwgRm9ybS5FbGVtZW50Lk1ldGhvZHMpO1xuICAgIE9iamVjdC5leHRlbmQoRWxlbWVudC5NZXRob2RzLkJ5VGFnLCB7XG4gICAgICBcIkZPUk1cIjogICAgIE9iamVjdC5jbG9uZShGb3JtLk1ldGhvZHMpLFxuICAgICAgXCJJTlBVVFwiOiAgICBPYmplY3QuY2xvbmUoRm9ybS5FbGVtZW50Lk1ldGhvZHMpLFxuICAgICAgXCJTRUxFQ1RcIjogICBPYmplY3QuY2xvbmUoRm9ybS5FbGVtZW50Lk1ldGhvZHMpLFxuICAgICAgXCJURVhUQVJFQVwiOiBPYmplY3QuY2xvbmUoRm9ybS5FbGVtZW50Lk1ldGhvZHMpLFxuICAgICAgXCJCVVRUT05cIjogICBPYmplY3QuY2xvbmUoRm9ybS5FbGVtZW50Lk1ldGhvZHMpXG4gICAgfSk7XG4gIH1cblxuICBFbGVtZW50LmFkZE1ldGhvZHMobWV0aG9kcyk7XG5cbiAgZnVuY3Rpb24gZGVzdHJveUNhY2hlX0lFKCkge1xuICAgIERJViA9IG51bGw7XG4gICAgRUxFTUVOVF9DQUNIRSA9IG51bGw7XG4gIH1cblxuICBpZiAod2luZG93LmF0dGFjaEV2ZW50KVxuICAgIHdpbmRvdy5hdHRhY2hFdmVudCgnb251bmxvYWQnLCBkZXN0cm95Q2FjaGVfSUUpO1xuXG59KSh0aGlzKTtcbihmdW5jdGlvbigpIHtcblxuICBmdW5jdGlvbiB0b0RlY2ltYWwocGN0U3RyaW5nKSB7XG4gICAgdmFyIG1hdGNoID0gcGN0U3RyaW5nLm1hdGNoKC9eKFxcZCspJT8kL2kpO1xuICAgIGlmICghbWF0Y2gpIHJldHVybiBudWxsO1xuICAgIHJldHVybiAoTnVtYmVyKG1hdGNoWzFdKSAvIDEwMCk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRSYXdTdHlsZShlbGVtZW50LCBzdHlsZSkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXG4gICAgdmFyIHZhbHVlID0gZWxlbWVudC5zdHlsZVtzdHlsZV07XG4gICAgaWYgKCF2YWx1ZSB8fCB2YWx1ZSA9PT0gJ2F1dG8nKSB7XG4gICAgICB2YXIgY3NzID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50LCBudWxsKTtcbiAgICAgIHZhbHVlID0gY3NzID8gY3NzW3N0eWxlXSA6IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHN0eWxlID09PSAnb3BhY2l0eScpIHJldHVybiB2YWx1ZSA/IHBhcnNlRmxvYXQodmFsdWUpIDogMS4wO1xuICAgIHJldHVybiB2YWx1ZSA9PT0gJ2F1dG8nID8gbnVsbCA6IHZhbHVlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0UmF3U3R5bGVfSUUoZWxlbWVudCwgc3R5bGUpIHtcbiAgICB2YXIgdmFsdWUgPSBlbGVtZW50LnN0eWxlW3N0eWxlXTtcbiAgICBpZiAoIXZhbHVlICYmIGVsZW1lbnQuY3VycmVudFN0eWxlKSB7XG4gICAgICB2YWx1ZSA9IGVsZW1lbnQuY3VycmVudFN0eWxlW3N0eWxlXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Q29udGVudFdpZHRoKGVsZW1lbnQsIGNvbnRleHQpIHtcbiAgICB2YXIgYm94V2lkdGggPSBlbGVtZW50Lm9mZnNldFdpZHRoO1xuXG4gICAgdmFyIGJsID0gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnYm9yZGVyTGVmdFdpZHRoJywgIGNvbnRleHQpIHx8IDA7XG4gICAgdmFyIGJyID0gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnYm9yZGVyUmlnaHRXaWR0aCcsIGNvbnRleHQpIHx8IDA7XG4gICAgdmFyIHBsID0gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAncGFkZGluZ0xlZnQnLCAgICAgIGNvbnRleHQpIHx8IDA7XG4gICAgdmFyIHByID0gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAncGFkZGluZ1JpZ2h0JywgICAgIGNvbnRleHQpIHx8IDA7XG5cbiAgICByZXR1cm4gYm94V2lkdGggLSBibCAtIGJyIC0gcGwgLSBwcjtcbiAgfVxuXG4gIGlmICgnY3VycmVudFN0eWxlJyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICBnZXRSYXdTdHlsZSA9IGdldFJhd1N0eWxlX0lFO1xuICB9XG5cblxuICBmdW5jdGlvbiBnZXRQaXhlbFZhbHVlKHZhbHVlLCBwcm9wZXJ0eSwgY29udGV4dCkge1xuICAgIHZhciBlbGVtZW50ID0gbnVsbDtcbiAgICBpZiAoT2JqZWN0LmlzRWxlbWVudCh2YWx1ZSkpIHtcbiAgICAgIGVsZW1lbnQgPSB2YWx1ZTtcbiAgICAgIHZhbHVlID0gZ2V0UmF3U3R5bGUoZWxlbWVudCwgcHJvcGVydHkpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBPYmplY3QuaXNVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoKC9eKD86LSk/XFxkKyhcXC5cXGQrKT8ocHgpPyQvaSkudGVzdCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB3aW5kb3cucGFyc2VGbG9hdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgdmFyIGlzUGVyY2VudGFnZSA9IHZhbHVlLmluY2x1ZGUoJyUnKSwgaXNWaWV3cG9ydCA9IChjb250ZXh0ID09PSBkb2N1bWVudC52aWV3cG9ydCk7XG5cbiAgICBpZiAoL1xcZC8udGVzdCh2YWx1ZSkgJiYgZWxlbWVudCAmJiBlbGVtZW50LnJ1bnRpbWVTdHlsZSAmJiAhKGlzUGVyY2VudGFnZSAmJiBpc1ZpZXdwb3J0KSkge1xuICAgICAgdmFyIHN0eWxlID0gZWxlbWVudC5zdHlsZS5sZWZ0LCByU3R5bGUgPSBlbGVtZW50LnJ1bnRpbWVTdHlsZS5sZWZ0O1xuICAgICAgZWxlbWVudC5ydW50aW1lU3R5bGUubGVmdCA9IGVsZW1lbnQuY3VycmVudFN0eWxlLmxlZnQ7XG4gICAgICBlbGVtZW50LnN0eWxlLmxlZnQgPSB2YWx1ZSB8fCAwO1xuICAgICAgdmFsdWUgPSBlbGVtZW50LnN0eWxlLnBpeGVsTGVmdDtcbiAgICAgIGVsZW1lbnQuc3R5bGUubGVmdCA9IHN0eWxlO1xuICAgICAgZWxlbWVudC5ydW50aW1lU3R5bGUubGVmdCA9IHJTdHlsZTtcblxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50ICYmIGlzUGVyY2VudGFnZSkge1xuICAgICAgY29udGV4dCA9IGNvbnRleHQgfHwgZWxlbWVudC5wYXJlbnROb2RlO1xuICAgICAgdmFyIGRlY2ltYWwgPSB0b0RlY2ltYWwodmFsdWUpLCB3aG9sZSA9IG51bGw7XG5cbiAgICAgIHZhciBpc0hvcml6b250YWwgPSBwcm9wZXJ0eS5pbmNsdWRlKCdsZWZ0JykgfHwgcHJvcGVydHkuaW5jbHVkZSgncmlnaHQnKSB8fFxuICAgICAgIHByb3BlcnR5LmluY2x1ZGUoJ3dpZHRoJyk7XG5cbiAgICAgIHZhciBpc1ZlcnRpY2FsICAgPSBwcm9wZXJ0eS5pbmNsdWRlKCd0b3AnKSB8fCBwcm9wZXJ0eS5pbmNsdWRlKCdib3R0b20nKSB8fFxuICAgICAgICBwcm9wZXJ0eS5pbmNsdWRlKCdoZWlnaHQnKTtcblxuICAgICAgaWYgKGNvbnRleHQgPT09IGRvY3VtZW50LnZpZXdwb3J0KSB7XG4gICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICB3aG9sZSA9IGRvY3VtZW50LnZpZXdwb3J0LmdldFdpZHRoKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNWZXJ0aWNhbCkge1xuICAgICAgICAgIHdob2xlID0gZG9jdW1lbnQudmlld3BvcnQuZ2V0SGVpZ2h0KCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChpc0hvcml6b250YWwpIHtcbiAgICAgICAgICB3aG9sZSA9ICQoY29udGV4dCkubWVhc3VyZSgnd2lkdGgnKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc1ZlcnRpY2FsKSB7XG4gICAgICAgICAgd2hvbGUgPSAkKGNvbnRleHQpLm1lYXN1cmUoJ2hlaWdodCcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAod2hvbGUgPT09IG51bGwpID8gMCA6IHdob2xlICogZGVjaW1hbDtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRvQ1NTUGl4ZWxzKG51bWJlcikge1xuICAgIGlmIChPYmplY3QuaXNTdHJpbmcobnVtYmVyKSAmJiBudW1iZXIuZW5kc1dpdGgoJ3B4JykpXG4gICAgICByZXR1cm4gbnVtYmVyO1xuICAgIHJldHVybiBudW1iZXIgKyAncHgnO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNEaXNwbGF5ZWQoZWxlbWVudCkge1xuICAgIHdoaWxlIChlbGVtZW50ICYmIGVsZW1lbnQucGFyZW50Tm9kZSkge1xuICAgICAgdmFyIGRpc3BsYXkgPSBlbGVtZW50LmdldFN0eWxlKCdkaXNwbGF5Jyk7XG4gICAgICBpZiAoZGlzcGxheSA9PT0gJ25vbmUnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQucGFyZW50Tm9kZSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgdmFyIGhhc0xheW91dCA9IFByb3RvdHlwZS5LO1xuICBpZiAoJ2N1cnJlbnRTdHlsZScgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgaGFzTGF5b3V0ID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgaWYgKCFlbGVtZW50LmN1cnJlbnRTdHlsZS5oYXNMYXlvdXQpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZS56b29tID0gMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjc3NOYW1lRm9yKGtleSkge1xuICAgIGlmIChrZXkuaW5jbHVkZSgnYm9yZGVyJykpIGtleSA9IGtleSArICctd2lkdGgnO1xuICAgIHJldHVybiBrZXkuY2FtZWxpemUoKTtcbiAgfVxuXG4gIEVsZW1lbnQuTGF5b3V0ID0gQ2xhc3MuY3JlYXRlKEhhc2gsIHtcbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbigkc3VwZXIsIGVsZW1lbnQsIHByZUNvbXB1dGUpIHtcbiAgICAgICRzdXBlcigpO1xuICAgICAgdGhpcy5lbGVtZW50ID0gJChlbGVtZW50KTtcblxuICAgICAgRWxlbWVudC5MYXlvdXQuUFJPUEVSVElFUy5lYWNoKCBmdW5jdGlvbihwcm9wZXJ0eSkge1xuICAgICAgICB0aGlzLl9zZXQocHJvcGVydHksIG51bGwpO1xuICAgICAgfSwgdGhpcyk7XG5cbiAgICAgIGlmIChwcmVDb21wdXRlKSB7XG4gICAgICAgIHRoaXMuX3ByZUNvbXB1dGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMuX2JlZ2luKCk7XG4gICAgICAgIEVsZW1lbnQuTGF5b3V0LlBST1BFUlRJRVMuZWFjaCggdGhpcy5fY29tcHV0ZSwgdGhpcyApO1xuICAgICAgICB0aGlzLl9lbmQoKTtcbiAgICAgICAgdGhpcy5fcHJlQ29tcHV0aW5nID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSxcblxuICAgIF9zZXQ6IGZ1bmN0aW9uKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIEhhc2gucHJvdG90eXBlLnNldC5jYWxsKHRoaXMsIHByb3BlcnR5LCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIHNldDogZnVuY3Rpb24ocHJvcGVydHksIHZhbHVlKSB7XG4gICAgICB0aHJvdyBcIlByb3BlcnRpZXMgb2YgRWxlbWVudC5MYXlvdXQgYXJlIHJlYWQtb25seS5cIjtcbiAgICB9LFxuXG4gICAgZ2V0OiBmdW5jdGlvbigkc3VwZXIsIHByb3BlcnR5KSB7XG4gICAgICB2YXIgdmFsdWUgPSAkc3VwZXIocHJvcGVydHkpO1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gdGhpcy5fY29tcHV0ZShwcm9wZXJ0eSkgOiB2YWx1ZTtcbiAgICB9LFxuXG4gICAgX2JlZ2luOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLl9pc1ByZXBhcmVkKCkpIHJldHVybjtcblxuICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQ7XG4gICAgICBpZiAoaXNEaXNwbGF5ZWQoZWxlbWVudCkpIHtcbiAgICAgICAgdGhpcy5fc2V0UHJlcGFyZWQodHJ1ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuXG4gICAgICB2YXIgb3JpZ2luYWxTdHlsZXMgPSB7XG4gICAgICAgIHBvc2l0aW9uOiAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gICB8fCAnJyxcbiAgICAgICAgd2lkdGg6ICAgICAgZWxlbWVudC5zdHlsZS53aWR0aCAgICAgIHx8ICcnLFxuICAgICAgICB2aXNpYmlsaXR5OiBlbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgfHwgJycsXG4gICAgICAgIGRpc3BsYXk6ICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSAgICB8fCAnJ1xuICAgICAgfTtcblxuICAgICAgZWxlbWVudC5zdG9yZSgncHJvdG90eXBlX29yaWdpbmFsX3N0eWxlcycsIG9yaWdpbmFsU3R5bGVzKTtcblxuICAgICAgdmFyIHBvc2l0aW9uID0gZ2V0UmF3U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJyksIHdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aDtcblxuICAgICAgaWYgKHdpZHRoID09PSAwIHx8IHdpZHRoID09PSBudWxsKSB7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgIHdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgIH1cblxuICAgICAgdmFyIGNvbnRleHQgPSAocG9zaXRpb24gPT09ICdmaXhlZCcpID8gZG9jdW1lbnQudmlld3BvcnQgOlxuICAgICAgIGVsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgdmFyIHRlbXBTdHlsZXMgPSB7XG4gICAgICAgIHZpc2liaWxpdHk6ICdoaWRkZW4nLFxuICAgICAgICBkaXNwbGF5OiAgICAnYmxvY2snXG4gICAgICB9O1xuXG4gICAgICBpZiAocG9zaXRpb24gIT09ICdmaXhlZCcpIHRlbXBTdHlsZXMucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuXG4gICAgICBlbGVtZW50LnNldFN0eWxlKHRlbXBTdHlsZXMpO1xuXG4gICAgICB2YXIgcG9zaXRpb25lZFdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aCwgbmV3V2lkdGg7XG4gICAgICBpZiAod2lkdGggJiYgKHBvc2l0aW9uZWRXaWR0aCA9PT0gd2lkdGgpKSB7XG4gICAgICAgIG5ld1dpZHRoID0gZ2V0Q29udGVudFdpZHRoKGVsZW1lbnQsIGNvbnRleHQpO1xuICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2Fic29sdXRlJyB8fCBwb3NpdGlvbiA9PT0gJ2ZpeGVkJykge1xuICAgICAgICBuZXdXaWR0aCA9IGdldENvbnRlbnRXaWR0aChlbGVtZW50LCBjb250ZXh0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBwYXJlbnQgPSBlbGVtZW50LnBhcmVudE5vZGUsIHBMYXlvdXQgPSAkKHBhcmVudCkuZ2V0TGF5b3V0KCk7XG5cbiAgICAgICAgbmV3V2lkdGggPSBwTGF5b3V0LmdldCgnd2lkdGgnKSAtXG4gICAgICAgICB0aGlzLmdldCgnbWFyZ2luLWxlZnQnKSAtXG4gICAgICAgICB0aGlzLmdldCgnYm9yZGVyLWxlZnQnKSAtXG4gICAgICAgICB0aGlzLmdldCgncGFkZGluZy1sZWZ0JykgLVxuICAgICAgICAgdGhpcy5nZXQoJ3BhZGRpbmctcmlnaHQnKSAtXG4gICAgICAgICB0aGlzLmdldCgnYm9yZGVyLXJpZ2h0JykgLVxuICAgICAgICAgdGhpcy5nZXQoJ21hcmdpbi1yaWdodCcpO1xuICAgICAgfVxuXG4gICAgICBlbGVtZW50LnNldFN0eWxlKHsgd2lkdGg6IG5ld1dpZHRoICsgJ3B4JyB9KTtcblxuICAgICAgdGhpcy5fc2V0UHJlcGFyZWQodHJ1ZSk7XG4gICAgfSxcblxuICAgIF9lbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLmVsZW1lbnQ7XG4gICAgICB2YXIgb3JpZ2luYWxTdHlsZXMgPSBlbGVtZW50LnJldHJpZXZlKCdwcm90b3R5cGVfb3JpZ2luYWxfc3R5bGVzJyk7XG4gICAgICBlbGVtZW50LnN0b3JlKCdwcm90b3R5cGVfb3JpZ2luYWxfc3R5bGVzJywgbnVsbCk7XG4gICAgICBlbGVtZW50LnNldFN0eWxlKG9yaWdpbmFsU3R5bGVzKTtcbiAgICAgIHRoaXMuX3NldFByZXBhcmVkKGZhbHNlKTtcbiAgICB9LFxuXG4gICAgX2NvbXB1dGU6IGZ1bmN0aW9uKHByb3BlcnR5KSB7XG4gICAgICB2YXIgQ09NUFVUQVRJT05TID0gRWxlbWVudC5MYXlvdXQuQ09NUFVUQVRJT05TO1xuICAgICAgaWYgKCEocHJvcGVydHkgaW4gQ09NUFVUQVRJT05TKSkge1xuICAgICAgICB0aHJvdyBcIlByb3BlcnR5IG5vdCBmb3VuZC5cIjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3NldChwcm9wZXJ0eSwgQ09NUFVUQVRJT05TW3Byb3BlcnR5XS5jYWxsKHRoaXMsIHRoaXMuZWxlbWVudCkpO1xuICAgIH0sXG5cbiAgICBfaXNQcmVwYXJlZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5lbGVtZW50LnJldHJpZXZlKCdwcm90b3R5cGVfZWxlbWVudF9sYXlvdXRfcHJlcGFyZWQnLCBmYWxzZSk7XG4gICAgfSxcblxuICAgIF9zZXRQcmVwYXJlZDogZnVuY3Rpb24oYm9vbCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5zdG9yZSgncHJvdG90eXBlX2VsZW1lbnRfbGF5b3V0X3ByZXBhcmVkJywgYm9vbCk7XG4gICAgfSxcblxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmdzID0gJEEoYXJndW1lbnRzKTtcbiAgICAgIHZhciBrZXlzID0gKGFyZ3MubGVuZ3RoID09PSAwKSA/IEVsZW1lbnQuTGF5b3V0LlBST1BFUlRJRVMgOlxuICAgICAgIGFyZ3Muam9pbignICcpLnNwbGl0KCcgJyk7XG4gICAgICB2YXIgb2JqID0ge307XG4gICAgICBrZXlzLmVhY2goIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoIUVsZW1lbnQuTGF5b3V0LlBST1BFUlRJRVMuaW5jbHVkZShrZXkpKSByZXR1cm47XG4gICAgICAgIHZhciB2YWx1ZSA9IHRoaXMuZ2V0KGtleSk7XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSBvYmpba2V5XSA9IHZhbHVlO1xuICAgICAgfSwgdGhpcyk7XG4gICAgICByZXR1cm4gb2JqO1xuICAgIH0sXG5cbiAgICB0b0hhc2g6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG9iaiA9IHRoaXMudG9PYmplY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBuZXcgSGFzaChvYmopO1xuICAgIH0sXG5cbiAgICB0b0NTUzogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9ICRBKGFyZ3VtZW50cyk7XG4gICAgICB2YXIga2V5cyA9IChhcmdzLmxlbmd0aCA9PT0gMCkgPyBFbGVtZW50LkxheW91dC5QUk9QRVJUSUVTIDpcbiAgICAgICBhcmdzLmpvaW4oJyAnKS5zcGxpdCgnICcpO1xuICAgICAgdmFyIGNzcyA9IHt9O1xuXG4gICAgICBrZXlzLmVhY2goIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoIUVsZW1lbnQuTGF5b3V0LlBST1BFUlRJRVMuaW5jbHVkZShrZXkpKSByZXR1cm47XG4gICAgICAgIGlmIChFbGVtZW50LkxheW91dC5DT01QT1NJVEVfUFJPUEVSVElFUy5pbmNsdWRlKGtleSkpIHJldHVybjtcblxuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLmdldChrZXkpO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkgY3NzW2Nzc05hbWVGb3Ioa2V5KV0gPSB2YWx1ZSArICdweCc7XG4gICAgICB9LCB0aGlzKTtcbiAgICAgIHJldHVybiBjc3M7XG4gICAgfSxcblxuICAgIGluc3BlY3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIFwiIzxFbGVtZW50LkxheW91dD5cIjtcbiAgICB9XG4gIH0pO1xuXG4gIE9iamVjdC5leHRlbmQoRWxlbWVudC5MYXlvdXQsIHtcbiAgICBQUk9QRVJUSUVTOiAkdygnaGVpZ2h0IHdpZHRoIHRvcCBsZWZ0IHJpZ2h0IGJvdHRvbSBib3JkZXItbGVmdCBib3JkZXItcmlnaHQgYm9yZGVyLXRvcCBib3JkZXItYm90dG9tIHBhZGRpbmctbGVmdCBwYWRkaW5nLXJpZ2h0IHBhZGRpbmctdG9wIHBhZGRpbmctYm90dG9tIG1hcmdpbi10b3AgbWFyZ2luLWJvdHRvbSBtYXJnaW4tbGVmdCBtYXJnaW4tcmlnaHQgcGFkZGluZy1ib3gtd2lkdGggcGFkZGluZy1ib3gtaGVpZ2h0IGJvcmRlci1ib3gtd2lkdGggYm9yZGVyLWJveC1oZWlnaHQgbWFyZ2luLWJveC13aWR0aCBtYXJnaW4tYm94LWhlaWdodCcpLFxuXG4gICAgQ09NUE9TSVRFX1BST1BFUlRJRVM6ICR3KCdwYWRkaW5nLWJveC13aWR0aCBwYWRkaW5nLWJveC1oZWlnaHQgbWFyZ2luLWJveC13aWR0aCBtYXJnaW4tYm94LWhlaWdodCBib3JkZXItYm94LXdpZHRoIGJvcmRlci1ib3gtaGVpZ2h0JyksXG5cbiAgICBDT01QVVRBVElPTlM6IHtcbiAgICAgICdoZWlnaHQnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9iZWdpbigpO1xuXG4gICAgICAgIHZhciBiSGVpZ2h0ID0gdGhpcy5nZXQoJ2JvcmRlci1ib3gtaGVpZ2h0Jyk7XG4gICAgICAgIGlmIChiSGVpZ2h0IDw9IDApIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX3ByZUNvbXB1dGluZykgdGhpcy5fZW5kKCk7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYlRvcCA9IHRoaXMuZ2V0KCdib3JkZXItdG9wJyksXG4gICAgICAgICBiQm90dG9tID0gdGhpcy5nZXQoJ2JvcmRlci1ib3R0b20nKTtcblxuICAgICAgICB2YXIgcFRvcCA9IHRoaXMuZ2V0KCdwYWRkaW5nLXRvcCcpLFxuICAgICAgICAgcEJvdHRvbSA9IHRoaXMuZ2V0KCdwYWRkaW5nLWJvdHRvbScpO1xuXG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9lbmQoKTtcblxuICAgICAgICByZXR1cm4gYkhlaWdodCAtIGJUb3AgLSBiQm90dG9tIC0gcFRvcCAtIHBCb3R0b207XG4gICAgICB9LFxuXG4gICAgICAnd2lkdGgnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9iZWdpbigpO1xuXG4gICAgICAgIHZhciBiV2lkdGggPSB0aGlzLmdldCgnYm9yZGVyLWJveC13aWR0aCcpO1xuICAgICAgICBpZiAoYldpZHRoIDw9IDApIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX3ByZUNvbXB1dGluZykgdGhpcy5fZW5kKCk7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYkxlZnQgPSB0aGlzLmdldCgnYm9yZGVyLWxlZnQnKSxcbiAgICAgICAgIGJSaWdodCA9IHRoaXMuZ2V0KCdib3JkZXItcmlnaHQnKTtcblxuICAgICAgICB2YXIgcExlZnQgPSB0aGlzLmdldCgncGFkZGluZy1sZWZ0JyksXG4gICAgICAgICBwUmlnaHQgPSB0aGlzLmdldCgncGFkZGluZy1yaWdodCcpO1xuXG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9lbmQoKTtcbiAgICAgICAgcmV0dXJuIGJXaWR0aCAtIGJMZWZ0IC0gYlJpZ2h0IC0gcExlZnQgLSBwUmlnaHQ7XG4gICAgICB9LFxuXG4gICAgICAncGFkZGluZy1ib3gtaGVpZ2h0JzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICB2YXIgaGVpZ2h0ID0gdGhpcy5nZXQoJ2hlaWdodCcpLFxuICAgICAgICAgcFRvcCA9IHRoaXMuZ2V0KCdwYWRkaW5nLXRvcCcpLFxuICAgICAgICAgcEJvdHRvbSA9IHRoaXMuZ2V0KCdwYWRkaW5nLWJvdHRvbScpO1xuXG4gICAgICAgIHJldHVybiBoZWlnaHQgKyBwVG9wICsgcEJvdHRvbTtcbiAgICAgIH0sXG5cbiAgICAgICdwYWRkaW5nLWJveC13aWR0aCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gdGhpcy5nZXQoJ3dpZHRoJyksXG4gICAgICAgICBwTGVmdCA9IHRoaXMuZ2V0KCdwYWRkaW5nLWxlZnQnKSxcbiAgICAgICAgIHBSaWdodCA9IHRoaXMuZ2V0KCdwYWRkaW5nLXJpZ2h0Jyk7XG5cbiAgICAgICAgcmV0dXJuIHdpZHRoICsgcExlZnQgKyBwUmlnaHQ7XG4gICAgICB9LFxuXG4gICAgICAnYm9yZGVyLWJveC1oZWlnaHQnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9iZWdpbigpO1xuICAgICAgICB2YXIgaGVpZ2h0ID0gZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIGlmICghdGhpcy5fcHJlQ29tcHV0aW5nKSB0aGlzLl9lbmQoKTtcbiAgICAgICAgcmV0dXJuIGhlaWdodDtcbiAgICAgIH0sXG5cbiAgICAgICdib3JkZXItYm94LXdpZHRoJzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICBpZiAoIXRoaXMuX3ByZUNvbXB1dGluZykgdGhpcy5fYmVnaW4oKTtcbiAgICAgICAgdmFyIHdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgaWYgKCF0aGlzLl9wcmVDb21wdXRpbmcpIHRoaXMuX2VuZCgpO1xuICAgICAgICByZXR1cm4gd2lkdGg7XG4gICAgICB9LFxuXG4gICAgICAnbWFyZ2luLWJveC1oZWlnaHQnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIHZhciBiSGVpZ2h0ID0gdGhpcy5nZXQoJ2JvcmRlci1ib3gtaGVpZ2h0JyksXG4gICAgICAgICBtVG9wID0gdGhpcy5nZXQoJ21hcmdpbi10b3AnKSxcbiAgICAgICAgIG1Cb3R0b20gPSB0aGlzLmdldCgnbWFyZ2luLWJvdHRvbScpO1xuXG4gICAgICAgIGlmIChiSGVpZ2h0IDw9IDApIHJldHVybiAwO1xuXG4gICAgICAgIHJldHVybiBiSGVpZ2h0ICsgbVRvcCArIG1Cb3R0b207XG4gICAgICB9LFxuXG4gICAgICAnbWFyZ2luLWJveC13aWR0aCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGJXaWR0aCA9IHRoaXMuZ2V0KCdib3JkZXItYm94LXdpZHRoJyksXG4gICAgICAgICBtTGVmdCA9IHRoaXMuZ2V0KCdtYXJnaW4tbGVmdCcpLFxuICAgICAgICAgbVJpZ2h0ID0gdGhpcy5nZXQoJ21hcmdpbi1yaWdodCcpO1xuXG4gICAgICAgIGlmIChiV2lkdGggPD0gMCkgcmV0dXJuIDA7XG5cbiAgICAgICAgcmV0dXJuIGJXaWR0aCArIG1MZWZ0ICsgbVJpZ2h0O1xuICAgICAgfSxcblxuICAgICAgJ3RvcCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIG9mZnNldCA9IGVsZW1lbnQucG9zaXRpb25lZE9mZnNldCgpO1xuICAgICAgICByZXR1cm4gb2Zmc2V0LnRvcDtcbiAgICAgIH0sXG5cbiAgICAgICdib3R0b20nOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSBlbGVtZW50LnBvc2l0aW9uZWRPZmZzZXQoKSxcbiAgICAgICAgIHBhcmVudCA9IGVsZW1lbnQuZ2V0T2Zmc2V0UGFyZW50KCksXG4gICAgICAgICBwSGVpZ2h0ID0gcGFyZW50Lm1lYXN1cmUoJ2hlaWdodCcpO1xuXG4gICAgICAgIHZhciBtSGVpZ2h0ID0gdGhpcy5nZXQoJ2JvcmRlci1ib3gtaGVpZ2h0Jyk7XG5cbiAgICAgICAgcmV0dXJuIHBIZWlnaHQgLSBtSGVpZ2h0IC0gb2Zmc2V0LnRvcDtcbiAgICAgIH0sXG5cbiAgICAgICdsZWZ0JzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICB2YXIgb2Zmc2V0ID0gZWxlbWVudC5wb3NpdGlvbmVkT2Zmc2V0KCk7XG4gICAgICAgIHJldHVybiBvZmZzZXQubGVmdDtcbiAgICAgIH0sXG5cbiAgICAgICdyaWdodCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIG9mZnNldCA9IGVsZW1lbnQucG9zaXRpb25lZE9mZnNldCgpLFxuICAgICAgICAgcGFyZW50ID0gZWxlbWVudC5nZXRPZmZzZXRQYXJlbnQoKSxcbiAgICAgICAgIHBXaWR0aCA9IHBhcmVudC5tZWFzdXJlKCd3aWR0aCcpO1xuXG4gICAgICAgIHZhciBtV2lkdGggPSB0aGlzLmdldCgnYm9yZGVyLWJveC13aWR0aCcpO1xuXG4gICAgICAgIHJldHVybiBwV2lkdGggLSBtV2lkdGggLSBvZmZzZXQubGVmdDtcbiAgICAgIH0sXG5cbiAgICAgICdwYWRkaW5nLXRvcCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ3BhZGRpbmdUb3AnKTtcbiAgICAgIH0sXG5cbiAgICAgICdwYWRkaW5nLWJvdHRvbSc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ3BhZGRpbmdCb3R0b20nKTtcbiAgICAgIH0sXG5cbiAgICAgICdwYWRkaW5nLWxlZnQnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBnZXRQaXhlbFZhbHVlKGVsZW1lbnQsICdwYWRkaW5nTGVmdCcpO1xuICAgICAgfSxcblxuICAgICAgJ3BhZGRpbmctcmlnaHQnOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgIHJldHVybiBnZXRQaXhlbFZhbHVlKGVsZW1lbnQsICdwYWRkaW5nUmlnaHQnKTtcbiAgICAgIH0sXG5cbiAgICAgICdib3JkZXItdG9wJzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnYm9yZGVyVG9wV2lkdGgnKTtcbiAgICAgIH0sXG5cbiAgICAgICdib3JkZXItYm90dG9tJzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnYm9yZGVyQm90dG9tV2lkdGgnKTtcbiAgICAgIH0sXG5cbiAgICAgICdib3JkZXItbGVmdCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ2JvcmRlckxlZnRXaWR0aCcpO1xuICAgICAgfSxcblxuICAgICAgJ2JvcmRlci1yaWdodCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ2JvcmRlclJpZ2h0V2lkdGgnKTtcbiAgICAgIH0sXG5cbiAgICAgICdtYXJnaW4tdG9wJzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnbWFyZ2luVG9wJyk7XG4gICAgICB9LFxuXG4gICAgICAnbWFyZ2luLWJvdHRvbSc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ21hcmdpbkJvdHRvbScpO1xuICAgICAgfSxcblxuICAgICAgJ21hcmdpbi1sZWZ0JzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gZ2V0UGl4ZWxWYWx1ZShlbGVtZW50LCAnbWFyZ2luTGVmdCcpO1xuICAgICAgfSxcblxuICAgICAgJ21hcmdpbi1yaWdodCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGdldFBpeGVsVmFsdWUoZWxlbWVudCwgJ21hcmdpblJpZ2h0Jyk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBpZiAoJ2dldEJvdW5kaW5nQ2xpZW50UmVjdCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgT2JqZWN0LmV4dGVuZChFbGVtZW50LkxheW91dC5DT01QVVRBVElPTlMsIHtcbiAgICAgICdyaWdodCc6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IGhhc0xheW91dChlbGVtZW50LmdldE9mZnNldFBhcmVudCgpKTtcbiAgICAgICAgdmFyIHJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFxuICAgICAgICAgcFJlY3QgPSBwYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgcmV0dXJuIChwUmVjdC5yaWdodCAtIHJlY3QucmlnaHQpLnJvdW5kKCk7XG4gICAgICB9LFxuXG4gICAgICAnYm90dG9tJzogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICB2YXIgcGFyZW50ID0gaGFzTGF5b3V0KGVsZW1lbnQuZ2V0T2Zmc2V0UGFyZW50KCkpO1xuICAgICAgICB2YXIgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksXG4gICAgICAgICBwUmVjdCA9IHBhcmVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICByZXR1cm4gKHBSZWN0LmJvdHRvbSAtIHJlY3QuYm90dG9tKS5yb3VuZCgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgRWxlbWVudC5PZmZzZXQgPSBDbGFzcy5jcmVhdGUoe1xuICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uKGxlZnQsIHRvcCkge1xuICAgICAgdGhpcy5sZWZ0ID0gbGVmdC5yb3VuZCgpO1xuICAgICAgdGhpcy50b3AgID0gdG9wLnJvdW5kKCk7XG5cbiAgICAgIHRoaXNbMF0gPSB0aGlzLmxlZnQ7XG4gICAgICB0aGlzWzFdID0gdGhpcy50b3A7XG4gICAgfSxcblxuICAgIHJlbGF0aXZlVG86IGZ1bmN0aW9uKG9mZnNldCkge1xuICAgICAgcmV0dXJuIG5ldyBFbGVtZW50Lk9mZnNldChcbiAgICAgICAgdGhpcy5sZWZ0IC0gb2Zmc2V0LmxlZnQsXG4gICAgICAgIHRoaXMudG9wICAtIG9mZnNldC50b3BcbiAgICAgICk7XG4gICAgfSxcblxuICAgIGluc3BlY3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIFwiIzxFbGVtZW50Lk9mZnNldCBsZWZ0OiAje2xlZnR9IHRvcDogI3t0b3B9PlwiLmludGVycG9sYXRlKHRoaXMpO1xuICAgIH0sXG5cbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXCJbI3tsZWZ0fSwgI3t0b3B9XVwiLmludGVycG9sYXRlKHRoaXMpO1xuICAgIH0sXG5cbiAgICB0b0FycmF5OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBbdGhpcy5sZWZ0LCB0aGlzLnRvcF07XG4gICAgfVxuICB9KTtcblxuICBmdW5jdGlvbiBnZXRMYXlvdXQoZWxlbWVudCwgcHJlQ29tcHV0ZSkge1xuICAgIHJldHVybiBuZXcgRWxlbWVudC5MYXlvdXQoZWxlbWVudCwgcHJlQ29tcHV0ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBtZWFzdXJlKGVsZW1lbnQsIHByb3BlcnR5KSB7XG4gICAgcmV0dXJuICQoZWxlbWVudCkuZ2V0TGF5b3V0KCkuZ2V0KHByb3BlcnR5KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEhlaWdodChlbGVtZW50KSB7XG4gICAgcmV0dXJuIEVsZW1lbnQuZ2V0RGltZW5zaW9ucyhlbGVtZW50KS5oZWlnaHQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRXaWR0aChlbGVtZW50KSB7XG4gICAgcmV0dXJuIEVsZW1lbnQuZ2V0RGltZW5zaW9ucyhlbGVtZW50KS53aWR0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERpbWVuc2lvbnMoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBkaXNwbGF5ID0gRWxlbWVudC5nZXRTdHlsZShlbGVtZW50LCAnZGlzcGxheScpO1xuXG4gICAgaWYgKGRpc3BsYXkgJiYgZGlzcGxheSAhPT0gJ25vbmUnKSB7XG4gICAgICByZXR1cm4geyB3aWR0aDogZWxlbWVudC5vZmZzZXRXaWR0aCwgaGVpZ2h0OiBlbGVtZW50Lm9mZnNldEhlaWdodCB9O1xuICAgIH1cblxuICAgIHZhciBzdHlsZSA9IGVsZW1lbnQuc3R5bGU7XG4gICAgdmFyIG9yaWdpbmFsU3R5bGVzID0ge1xuICAgICAgdmlzaWJpbGl0eTogc3R5bGUudmlzaWJpbGl0eSxcbiAgICAgIHBvc2l0aW9uOiAgIHN0eWxlLnBvc2l0aW9uLFxuICAgICAgZGlzcGxheTogICAgc3R5bGUuZGlzcGxheVxuICAgIH07XG5cbiAgICB2YXIgbmV3U3R5bGVzID0ge1xuICAgICAgdmlzaWJpbGl0eTogJ2hpZGRlbicsXG4gICAgICBkaXNwbGF5OiAgICAnYmxvY2snXG4gICAgfTtcblxuICAgIGlmIChvcmlnaW5hbFN0eWxlcy5wb3NpdGlvbiAhPT0gJ2ZpeGVkJylcbiAgICAgIG5ld1N0eWxlcy5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG5cbiAgICBFbGVtZW50LnNldFN0eWxlKGVsZW1lbnQsIG5ld1N0eWxlcyk7XG5cbiAgICB2YXIgZGltZW5zaW9ucyA9IHtcbiAgICAgIHdpZHRoOiAgZWxlbWVudC5vZmZzZXRXaWR0aCxcbiAgICAgIGhlaWdodDogZWxlbWVudC5vZmZzZXRIZWlnaHRcbiAgICB9O1xuXG4gICAgRWxlbWVudC5zZXRTdHlsZShlbGVtZW50LCBvcmlnaW5hbFN0eWxlcyk7XG5cbiAgICByZXR1cm4gZGltZW5zaW9ucztcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldE9mZnNldFBhcmVudChlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICBpZiAoaXNEb2N1bWVudChlbGVtZW50KSB8fCBpc0RldGFjaGVkKGVsZW1lbnQpIHx8IGlzQm9keShlbGVtZW50KSB8fCBpc0h0bWwoZWxlbWVudCkpXG4gICAgICByZXR1cm4gJChkb2N1bWVudC5ib2R5KTtcblxuICAgIHZhciBpc0lubGluZSA9IChFbGVtZW50LmdldFN0eWxlKGVsZW1lbnQsICdkaXNwbGF5JykgPT09ICdpbmxpbmUnKTtcbiAgICBpZiAoIWlzSW5saW5lICYmIGVsZW1lbnQub2Zmc2V0UGFyZW50KSByZXR1cm4gJChlbGVtZW50Lm9mZnNldFBhcmVudCk7XG5cbiAgICB3aGlsZSAoKGVsZW1lbnQgPSBlbGVtZW50LnBhcmVudE5vZGUpICYmIGVsZW1lbnQgIT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgIGlmIChFbGVtZW50LmdldFN0eWxlKGVsZW1lbnQsICdwb3NpdGlvbicpICE9PSAnc3RhdGljJykge1xuICAgICAgICByZXR1cm4gaXNIdG1sKGVsZW1lbnQpID8gJChkb2N1bWVudC5ib2R5KSA6ICQoZWxlbWVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICQoZG9jdW1lbnQuYm9keSk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGN1bXVsYXRpdmVPZmZzZXQoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciB2YWx1ZVQgPSAwLCB2YWx1ZUwgPSAwO1xuICAgIGlmIChlbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICAgIGRvIHtcbiAgICAgICAgdmFsdWVUICs9IGVsZW1lbnQub2Zmc2V0VG9wICB8fCAwO1xuICAgICAgICB2YWx1ZUwgKz0gZWxlbWVudC5vZmZzZXRMZWZ0IHx8IDA7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICAgIH0gd2hpbGUgKGVsZW1lbnQpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEVsZW1lbnQuT2Zmc2V0KHZhbHVlTCwgdmFsdWVUKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvc2l0aW9uZWRPZmZzZXQoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuXG4gICAgdmFyIGxheW91dCA9IGVsZW1lbnQuZ2V0TGF5b3V0KCk7XG5cbiAgICB2YXIgdmFsdWVUID0gMCwgdmFsdWVMID0gMDtcbiAgICBkbyB7XG4gICAgICB2YWx1ZVQgKz0gZWxlbWVudC5vZmZzZXRUb3AgIHx8IDA7XG4gICAgICB2YWx1ZUwgKz0gZWxlbWVudC5vZmZzZXRMZWZ0IHx8IDA7XG4gICAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQ7XG4gICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICBpZiAoaXNCb2R5KGVsZW1lbnQpKSBicmVhaztcbiAgICAgICAgdmFyIHAgPSBFbGVtZW50LmdldFN0eWxlKGVsZW1lbnQsICdwb3NpdGlvbicpO1xuICAgICAgICBpZiAocCAhPT0gJ3N0YXRpYycpIGJyZWFrO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKGVsZW1lbnQpO1xuXG4gICAgdmFsdWVMIC09IGxheW91dC5nZXQoJ21hcmdpbi10b3AnKTtcbiAgICB2YWx1ZVQgLT0gbGF5b3V0LmdldCgnbWFyZ2luLWxlZnQnKTtcblxuICAgIHJldHVybiBuZXcgRWxlbWVudC5PZmZzZXQodmFsdWVMLCB2YWx1ZVQpO1xuICB9XG5cbiAgZnVuY3Rpb24gY3VtdWxhdGl2ZVNjcm9sbE9mZnNldChlbGVtZW50KSB7XG4gICAgdmFyIHZhbHVlVCA9IDAsIHZhbHVlTCA9IDA7XG4gICAgZG8ge1xuICAgICAgaWYgKGVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICAgICAgdmFyIGJvZHlTY3JvbGxOb2RlID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IHx8IGRvY3VtZW50LmJvZHkucGFyZW50Tm9kZSB8fCBkb2N1bWVudC5ib2R5O1xuICAgICAgICB2YWx1ZVQgKz0gIU9iamVjdC5pc1VuZGVmaW5lZCh3aW5kb3cucGFnZVlPZmZzZXQpID8gd2luZG93LnBhZ2VZT2Zmc2V0IDogYm9keVNjcm9sbE5vZGUuc2Nyb2xsVG9wIHx8IDA7XG4gICAgICAgIHZhbHVlTCArPSAhT2JqZWN0LmlzVW5kZWZpbmVkKHdpbmRvdy5wYWdlWE9mZnNldCkgPyB3aW5kb3cucGFnZVhPZmZzZXQgOiBib2R5U2Nyb2xsTm9kZS5zY3JvbGxMZWZ0IHx8IDA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVUICs9IGVsZW1lbnQuc2Nyb2xsVG9wICB8fCAwO1xuICAgICAgICB2YWx1ZUwgKz0gZWxlbWVudC5zY3JvbGxMZWZ0IHx8IDA7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50LnBhcmVudE5vZGU7XG4gICAgICB9XG4gICAgfSB3aGlsZSAoZWxlbWVudCk7XG4gICAgcmV0dXJuIG5ldyBFbGVtZW50Lk9mZnNldCh2YWx1ZUwsIHZhbHVlVCk7XG4gIH1cblxuICBmdW5jdGlvbiB2aWV3cG9ydE9mZnNldChmb3JFbGVtZW50KSB7XG4gICAgdmFyIHZhbHVlVCA9IDAsIHZhbHVlTCA9IDAsIGRvY0JvZHkgPSBkb2N1bWVudC5ib2R5O1xuXG4gICAgZm9yRWxlbWVudCA9ICQoZm9yRWxlbWVudCk7XG4gICAgdmFyIGVsZW1lbnQgPSBmb3JFbGVtZW50O1xuICAgIGRvIHtcbiAgICAgIHZhbHVlVCArPSBlbGVtZW50Lm9mZnNldFRvcCAgfHwgMDtcbiAgICAgIHZhbHVlTCArPSBlbGVtZW50Lm9mZnNldExlZnQgfHwgMDtcbiAgICAgIGlmIChlbGVtZW50Lm9mZnNldFBhcmVudCA9PSBkb2NCb2R5ICYmXG4gICAgICAgIEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJykgPT0gJ2Fic29sdXRlJykgYnJlYWs7XG4gICAgfSB3aGlsZSAoZWxlbWVudCA9IGVsZW1lbnQub2Zmc2V0UGFyZW50KTtcblxuICAgIGVsZW1lbnQgPSBmb3JFbGVtZW50O1xuICAgIGRvIHtcbiAgICAgIGlmIChlbGVtZW50ICE9IGRvY0JvZHkpIHtcbiAgICAgICAgdmFsdWVUIC09IGVsZW1lbnQuc2Nyb2xsVG9wICB8fCAwO1xuICAgICAgICB2YWx1ZUwgLT0gZWxlbWVudC5zY3JvbGxMZWZ0IHx8IDA7XG4gICAgICB9XG4gICAgfSB3aGlsZSAoZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZSk7XG4gICAgcmV0dXJuIG5ldyBFbGVtZW50Lk9mZnNldCh2YWx1ZUwsIHZhbHVlVCk7XG4gIH1cblxuICBmdW5jdGlvbiBhYnNvbHV0aXplKGVsZW1lbnQpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcblxuICAgIGlmIChFbGVtZW50LmdldFN0eWxlKGVsZW1lbnQsICdwb3NpdGlvbicpID09PSAnYWJzb2x1dGUnKSB7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICB2YXIgb2Zmc2V0UGFyZW50ID0gZ2V0T2Zmc2V0UGFyZW50KGVsZW1lbnQpO1xuICAgIHZhciBlT2Zmc2V0ID0gZWxlbWVudC52aWV3cG9ydE9mZnNldCgpLFxuICAgICBwT2Zmc2V0ID0gb2Zmc2V0UGFyZW50LnZpZXdwb3J0T2Zmc2V0KCk7XG5cbiAgICB2YXIgb2Zmc2V0ID0gZU9mZnNldC5yZWxhdGl2ZVRvKHBPZmZzZXQpO1xuICAgIHZhciBsYXlvdXQgPSBlbGVtZW50LmdldExheW91dCgpO1xuXG4gICAgZWxlbWVudC5zdG9yZSgncHJvdG90eXBlX2Fic29sdXRpemVfb3JpZ2luYWxfc3R5bGVzJywge1xuICAgICAgcG9zaXRpb246IGVsZW1lbnQuZ2V0U3R5bGUoJ3Bvc2l0aW9uJyksXG4gICAgICBsZWZ0OiAgICAgZWxlbWVudC5nZXRTdHlsZSgnbGVmdCcpLFxuICAgICAgdG9wOiAgICAgIGVsZW1lbnQuZ2V0U3R5bGUoJ3RvcCcpLFxuICAgICAgd2lkdGg6ICAgIGVsZW1lbnQuZ2V0U3R5bGUoJ3dpZHRoJyksXG4gICAgICBoZWlnaHQ6ICAgZWxlbWVudC5nZXRTdHlsZSgnaGVpZ2h0JylcbiAgICB9KTtcblxuICAgIGVsZW1lbnQuc2V0U3R5bGUoe1xuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICB0b3A6ICAgIG9mZnNldC50b3AgKyAncHgnLFxuICAgICAgbGVmdDogICBvZmZzZXQubGVmdCArICdweCcsXG4gICAgICB3aWR0aDogIGxheW91dC5nZXQoJ3dpZHRoJykgKyAncHgnLFxuICAgICAgaGVpZ2h0OiBsYXlvdXQuZ2V0KCdoZWlnaHQnKSArICdweCdcbiAgICB9KTtcblxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVsYXRpdml6ZShlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgaWYgKEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJykgPT09ICdyZWxhdGl2ZScpIHtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIHZhciBvcmlnaW5hbFN0eWxlcyA9XG4gICAgIGVsZW1lbnQucmV0cmlldmUoJ3Byb3RvdHlwZV9hYnNvbHV0aXplX29yaWdpbmFsX3N0eWxlcycpO1xuXG4gICAgaWYgKG9yaWdpbmFsU3R5bGVzKSBlbGVtZW50LnNldFN0eWxlKG9yaWdpbmFsU3R5bGVzKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gc2Nyb2xsVG8oZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBwb3MgPSBFbGVtZW50LmN1bXVsYXRpdmVPZmZzZXQoZWxlbWVudCk7XG4gICAgd2luZG93LnNjcm9sbFRvKHBvcy5sZWZ0LCBwb3MudG9wKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gbWFrZVBvc2l0aW9uZWQoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBwb3NpdGlvbiA9IEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJyksIHN0eWxlcyA9IHt9O1xuICAgIGlmIChwb3NpdGlvbiA9PT0gJ3N0YXRpYycgfHwgIXBvc2l0aW9uKSB7XG4gICAgICBzdHlsZXMucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgICAgaWYgKFByb3RvdHlwZS5Ccm93c2VyLk9wZXJhKSB7XG4gICAgICAgIHN0eWxlcy50b3AgID0gMDtcbiAgICAgICAgc3R5bGVzLmxlZnQgPSAwO1xuICAgICAgfVxuICAgICAgRWxlbWVudC5zZXRTdHlsZShlbGVtZW50LCBzdHlsZXMpO1xuICAgICAgRWxlbWVudC5zdG9yZShlbGVtZW50LCAncHJvdG90eXBlX21hZGVfcG9zaXRpb25lZCcsIHRydWUpO1xuICAgIH1cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVuZG9Qb3NpdGlvbmVkKGVsZW1lbnQpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICB2YXIgc3RvcmFnZSA9IEVsZW1lbnQuZ2V0U3RvcmFnZShlbGVtZW50KSxcbiAgICAgbWFkZVBvc2l0aW9uZWQgPSBzdG9yYWdlLmdldCgncHJvdG90eXBlX21hZGVfcG9zaXRpb25lZCcpO1xuXG4gICAgaWYgKG1hZGVQb3NpdGlvbmVkKSB7XG4gICAgICBzdG9yYWdlLnVuc2V0KCdwcm90b3R5cGVfbWFkZV9wb3NpdGlvbmVkJyk7XG4gICAgICBFbGVtZW50LnNldFN0eWxlKGVsZW1lbnQsIHtcbiAgICAgICAgcG9zaXRpb246ICcnLFxuICAgICAgICB0b3A6ICAgICAgJycsXG4gICAgICAgIGJvdHRvbTogICAnJyxcbiAgICAgICAgbGVmdDogICAgICcnLFxuICAgICAgICByaWdodDogICAgJydcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VDbGlwcGluZyhlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICB2YXIgc3RvcmFnZSA9IEVsZW1lbnQuZ2V0U3RvcmFnZShlbGVtZW50KSxcbiAgICAgbWFkZUNsaXBwaW5nID0gc3RvcmFnZS5nZXQoJ3Byb3RvdHlwZV9tYWRlX2NsaXBwaW5nJyk7XG5cbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKG1hZGVDbGlwcGluZykpIHtcbiAgICAgIHZhciBvdmVyZmxvdyA9IEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ292ZXJmbG93Jyk7XG4gICAgICBzdG9yYWdlLnNldCgncHJvdG90eXBlX21hZGVfY2xpcHBpbmcnLCBvdmVyZmxvdyk7XG4gICAgICBpZiAob3ZlcmZsb3cgIT09ICdoaWRkZW4nKVxuICAgICAgICBlbGVtZW50LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiB1bmRvQ2xpcHBpbmcoZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBzdG9yYWdlID0gRWxlbWVudC5nZXRTdG9yYWdlKGVsZW1lbnQpLFxuICAgICBvdmVyZmxvdyA9IHN0b3JhZ2UuZ2V0KCdwcm90b3R5cGVfbWFkZV9jbGlwcGluZycpO1xuXG4gICAgaWYgKCFPYmplY3QuaXNVbmRlZmluZWQob3ZlcmZsb3cpKSB7XG4gICAgICBzdG9yYWdlLnVuc2V0KCdwcm90b3R5cGVfbWFkZV9jbGlwcGluZycpO1xuICAgICAgZWxlbWVudC5zdHlsZS5vdmVyZmxvdyA9IG92ZXJmbG93IHx8ICcnO1xuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gY2xvbmVQb3NpdGlvbihlbGVtZW50LCBzb3VyY2UsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gT2JqZWN0LmV4dGVuZCh7XG4gICAgICBzZXRMZWZ0OiAgICB0cnVlLFxuICAgICAgc2V0VG9wOiAgICAgdHJ1ZSxcbiAgICAgIHNldFdpZHRoOiAgIHRydWUsXG4gICAgICBzZXRIZWlnaHQ6ICB0cnVlLFxuICAgICAgb2Zmc2V0VG9wOiAgMCxcbiAgICAgIG9mZnNldExlZnQ6IDBcbiAgICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICAgIHNvdXJjZSAgPSAkKHNvdXJjZSk7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIHAsIGRlbHRhLCBsYXlvdXQsIHN0eWxlcyA9IHt9O1xuXG4gICAgaWYgKG9wdGlvbnMuc2V0TGVmdCB8fCBvcHRpb25zLnNldFRvcCkge1xuICAgICAgcCA9IEVsZW1lbnQudmlld3BvcnRPZmZzZXQoc291cmNlKTtcbiAgICAgIGRlbHRhID0gWzAsIDBdO1xuICAgICAgaWYgKEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJykgPT09ICdhYnNvbHV0ZScpIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IEVsZW1lbnQuZ2V0T2Zmc2V0UGFyZW50KGVsZW1lbnQpO1xuICAgICAgICBpZiAocGFyZW50ICE9PSBkb2N1bWVudC5ib2R5KSBkZWx0YSA9IEVsZW1lbnQudmlld3BvcnRPZmZzZXQocGFyZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zZXRXaWR0aCB8fCBvcHRpb25zLnNldEhlaWdodCkge1xuICAgICAgbGF5b3V0ID0gRWxlbWVudC5nZXRMYXlvdXQoc291cmNlKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zZXRMZWZ0KVxuICAgICAgc3R5bGVzLmxlZnQgPSAocFswXSAtIGRlbHRhWzBdICsgb3B0aW9ucy5vZmZzZXRMZWZ0KSArICdweCc7XG4gICAgaWYgKG9wdGlvbnMuc2V0VG9wKVxuICAgICAgc3R5bGVzLnRvcCAgPSAocFsxXSAtIGRlbHRhWzFdICsgb3B0aW9ucy5vZmZzZXRUb3ApICArICdweCc7XG5cbiAgICBpZiAob3B0aW9ucy5zZXRXaWR0aClcbiAgICAgIHN0eWxlcy53aWR0aCAgPSBsYXlvdXQuZ2V0KCdib3JkZXItYm94LXdpZHRoJykgICsgJ3B4JztcbiAgICBpZiAob3B0aW9ucy5zZXRIZWlnaHQpXG4gICAgICBzdHlsZXMuaGVpZ2h0ID0gbGF5b3V0LmdldCgnYm9yZGVyLWJveC1oZWlnaHQnKSArICdweCc7XG5cbiAgICByZXR1cm4gRWxlbWVudC5zZXRTdHlsZShlbGVtZW50LCBzdHlsZXMpO1xuICB9XG5cblxuICBpZiAoUHJvdG90eXBlLkJyb3dzZXIuSUUpIHtcbiAgICBnZXRPZmZzZXRQYXJlbnQgPSBnZXRPZmZzZXRQYXJlbnQud3JhcChcbiAgICAgIGZ1bmN0aW9uKHByb2NlZWQsIGVsZW1lbnQpIHtcbiAgICAgICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG5cbiAgICAgICAgaWYgKGlzRG9jdW1lbnQoZWxlbWVudCkgfHwgaXNEZXRhY2hlZChlbGVtZW50KSB8fCBpc0JvZHkoZWxlbWVudCkgfHwgaXNIdG1sKGVsZW1lbnQpKVxuICAgICAgICAgIHJldHVybiAkKGRvY3VtZW50LmJvZHkpO1xuXG4gICAgICAgIHZhciBwb3NpdGlvbiA9IGVsZW1lbnQuZ2V0U3R5bGUoJ3Bvc2l0aW9uJyk7XG4gICAgICAgIGlmIChwb3NpdGlvbiAhPT0gJ3N0YXRpYycpIHJldHVybiBwcm9jZWVkKGVsZW1lbnQpO1xuXG4gICAgICAgIGVsZW1lbnQuc2V0U3R5bGUoeyBwb3NpdGlvbjogJ3JlbGF0aXZlJyB9KTtcbiAgICAgICAgdmFyIHZhbHVlID0gcHJvY2VlZChlbGVtZW50KTtcbiAgICAgICAgZWxlbWVudC5zZXRTdHlsZSh7IHBvc2l0aW9uOiBwb3NpdGlvbiB9KTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBwb3NpdGlvbmVkT2Zmc2V0ID0gcG9zaXRpb25lZE9mZnNldC53cmFwKGZ1bmN0aW9uKHByb2NlZWQsIGVsZW1lbnQpIHtcbiAgICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgICAgaWYgKCFlbGVtZW50LnBhcmVudE5vZGUpIHJldHVybiBuZXcgRWxlbWVudC5PZmZzZXQoMCwgMCk7XG4gICAgICB2YXIgcG9zaXRpb24gPSBlbGVtZW50LmdldFN0eWxlKCdwb3NpdGlvbicpO1xuICAgICAgaWYgKHBvc2l0aW9uICE9PSAnc3RhdGljJykgcmV0dXJuIHByb2NlZWQoZWxlbWVudCk7XG5cbiAgICAgIHZhciBvZmZzZXRQYXJlbnQgPSBlbGVtZW50LmdldE9mZnNldFBhcmVudCgpO1xuICAgICAgaWYgKG9mZnNldFBhcmVudCAmJiBvZmZzZXRQYXJlbnQuZ2V0U3R5bGUoJ3Bvc2l0aW9uJykgPT09ICdmaXhlZCcpXG4gICAgICAgIGhhc0xheW91dChvZmZzZXRQYXJlbnQpO1xuXG4gICAgICBlbGVtZW50LnNldFN0eWxlKHsgcG9zaXRpb246ICdyZWxhdGl2ZScgfSk7XG4gICAgICB2YXIgdmFsdWUgPSBwcm9jZWVkKGVsZW1lbnQpO1xuICAgICAgZWxlbWVudC5zZXRTdHlsZSh7IHBvc2l0aW9uOiBwb3NpdGlvbiB9KTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChQcm90b3R5cGUuQnJvd3Nlci5XZWJraXQpIHtcbiAgICBjdW11bGF0aXZlT2Zmc2V0ID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgICB2YXIgdmFsdWVUID0gMCwgdmFsdWVMID0gMDtcbiAgICAgIGRvIHtcbiAgICAgICAgdmFsdWVUICs9IGVsZW1lbnQub2Zmc2V0VG9wICB8fCAwO1xuICAgICAgICB2YWx1ZUwgKz0gZWxlbWVudC5vZmZzZXRMZWZ0IHx8IDA7XG4gICAgICAgIGlmIChlbGVtZW50Lm9mZnNldFBhcmVudCA9PSBkb2N1bWVudC5ib2R5KSB7XG4gICAgICAgICAgaWYgKEVsZW1lbnQuZ2V0U3R5bGUoZWxlbWVudCwgJ3Bvc2l0aW9uJykgPT0gJ2Fic29sdXRlJykgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQ7XG4gICAgICB9IHdoaWxlIChlbGVtZW50KTtcblxuICAgICAgcmV0dXJuIG5ldyBFbGVtZW50Lk9mZnNldCh2YWx1ZUwsIHZhbHVlVCk7XG4gICAgfTtcbiAgfVxuXG5cbiAgRWxlbWVudC5hZGRNZXRob2RzKHtcbiAgICBnZXRMYXlvdXQ6ICAgICAgICAgICAgICBnZXRMYXlvdXQsXG4gICAgbWVhc3VyZTogICAgICAgICAgICAgICAgbWVhc3VyZSxcbiAgICBnZXRXaWR0aDogICAgICAgICAgICAgICBnZXRXaWR0aCxcbiAgICBnZXRIZWlnaHQ6ICAgICAgICAgICAgICBnZXRIZWlnaHQsXG4gICAgZ2V0RGltZW5zaW9uczogICAgICAgICAgZ2V0RGltZW5zaW9ucyxcbiAgICBnZXRPZmZzZXRQYXJlbnQ6ICAgICAgICBnZXRPZmZzZXRQYXJlbnQsXG4gICAgY3VtdWxhdGl2ZU9mZnNldDogICAgICAgY3VtdWxhdGl2ZU9mZnNldCxcbiAgICBwb3NpdGlvbmVkT2Zmc2V0OiAgICAgICBwb3NpdGlvbmVkT2Zmc2V0LFxuICAgIGN1bXVsYXRpdmVTY3JvbGxPZmZzZXQ6IGN1bXVsYXRpdmVTY3JvbGxPZmZzZXQsXG4gICAgdmlld3BvcnRPZmZzZXQ6ICAgICAgICAgdmlld3BvcnRPZmZzZXQsXG4gICAgYWJzb2x1dGl6ZTogICAgICAgICAgICAgYWJzb2x1dGl6ZSxcbiAgICByZWxhdGl2aXplOiAgICAgICAgICAgICByZWxhdGl2aXplLFxuICAgIHNjcm9sbFRvOiAgICAgICAgICAgICAgIHNjcm9sbFRvLFxuICAgIG1ha2VQb3NpdGlvbmVkOiAgICAgICAgIG1ha2VQb3NpdGlvbmVkLFxuICAgIHVuZG9Qb3NpdGlvbmVkOiAgICAgICAgIHVuZG9Qb3NpdGlvbmVkLFxuICAgIG1ha2VDbGlwcGluZzogICAgICAgICAgIG1ha2VDbGlwcGluZyxcbiAgICB1bmRvQ2xpcHBpbmc6ICAgICAgICAgICB1bmRvQ2xpcHBpbmcsXG4gICAgY2xvbmVQb3NpdGlvbjogICAgICAgICAgY2xvbmVQb3NpdGlvblxuICB9KTtcblxuICBmdW5jdGlvbiBpc0JvZHkoZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50Lm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdCT0RZJztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSHRtbChlbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQubm9kZU5hbWUudG9VcHBlckNhc2UoKSA9PT0gJ0hUTUwnO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNEb2N1bWVudChlbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQubm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfTk9ERTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRGV0YWNoZWQoZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50ICE9PSBkb2N1bWVudC5ib2R5ICYmXG4gICAgICFFbGVtZW50LmRlc2NlbmRhbnRPZihlbGVtZW50LCBkb2N1bWVudC5ib2R5KTtcbiAgfVxuXG4gIGlmICgnZ2V0Qm91bmRpbmdDbGllbnRSZWN0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICBFbGVtZW50LmFkZE1ldGhvZHMoe1xuICAgICAgdmlld3BvcnRPZmZzZXQ6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgICAgIGlmIChpc0RldGFjaGVkKGVsZW1lbnQpKSByZXR1cm4gbmV3IEVsZW1lbnQuT2Zmc2V0KDAsIDApO1xuXG4gICAgICAgIHZhciByZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxcbiAgICAgICAgIGRvY0VsID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICByZXR1cm4gbmV3IEVsZW1lbnQuT2Zmc2V0KHJlY3QubGVmdCAtIGRvY0VsLmNsaWVudExlZnQsXG4gICAgICAgICByZWN0LnRvcCAtIGRvY0VsLmNsaWVudFRvcCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG59KSgpO1xuXG4oZnVuY3Rpb24oKSB7XG5cbiAgdmFyIElTX09MRF9PUEVSQSA9IFByb3RvdHlwZS5Ccm93c2VyLk9wZXJhICYmXG4gICAod2luZG93LnBhcnNlRmxvYXQod2luZG93Lm9wZXJhLnZlcnNpb24oKSkgPCA5LjUpO1xuICB2YXIgUk9PVCA9IG51bGw7XG4gIGZ1bmN0aW9uIGdldFJvb3RFbGVtZW50KCkge1xuICAgIGlmIChST09UKSByZXR1cm4gUk9PVDtcbiAgICBST09UID0gSVNfT0xEX09QRVJBID8gZG9jdW1lbnQuYm9keSA6IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICByZXR1cm4gUk9PVDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERpbWVuc2lvbnMoKSB7XG4gICAgcmV0dXJuIHsgd2lkdGg6IHRoaXMuZ2V0V2lkdGgoKSwgaGVpZ2h0OiB0aGlzLmdldEhlaWdodCgpIH07XG4gIH1cblxuICBmdW5jdGlvbiBnZXRXaWR0aCgpIHtcbiAgICByZXR1cm4gZ2V0Um9vdEVsZW1lbnQoKS5jbGllbnRXaWR0aDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEhlaWdodCgpIHtcbiAgICByZXR1cm4gZ2V0Um9vdEVsZW1lbnQoKS5jbGllbnRIZWlnaHQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTY3JvbGxPZmZzZXRzKCkge1xuICAgIHZhciB4ID0gd2luZG93LnBhZ2VYT2Zmc2V0IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0IHx8XG4gICAgIGRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdDtcbiAgICB2YXIgeSA9IHdpbmRvdy5wYWdlWU9mZnNldCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wIHx8XG4gICAgIGRvY3VtZW50LmJvZHkuc2Nyb2xsVG9wO1xuXG4gICAgcmV0dXJuIG5ldyBFbGVtZW50Lk9mZnNldCh4LCB5KTtcbiAgfVxuXG4gIGRvY3VtZW50LnZpZXdwb3J0ID0ge1xuICAgIGdldERpbWVuc2lvbnM6ICAgIGdldERpbWVuc2lvbnMsXG4gICAgZ2V0V2lkdGg6ICAgICAgICAgZ2V0V2lkdGgsXG4gICAgZ2V0SGVpZ2h0OiAgICAgICAgZ2V0SGVpZ2h0LFxuICAgIGdldFNjcm9sbE9mZnNldHM6IGdldFNjcm9sbE9mZnNldHNcbiAgfTtcblxufSkoKTtcbndpbmRvdy4kJCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZXhwcmVzc2lvbiA9ICRBKGFyZ3VtZW50cykuam9pbignLCAnKTtcbiAgcmV0dXJuIFByb3RvdHlwZS5TZWxlY3Rvci5zZWxlY3QoZXhwcmVzc2lvbiwgZG9jdW1lbnQpO1xufTtcblxuUHJvdG90eXBlLlNlbGVjdG9yID0gKGZ1bmN0aW9uKCkge1xuXG4gIGZ1bmN0aW9uIHNlbGVjdCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBcIlByb3RvdHlwZS5TZWxlY3Rvci5zZWxlY3RcIiBtdXN0IGJlIGRlZmluZWQuJyk7XG4gIH1cblxuICBmdW5jdGlvbiBtYXRjaCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBcIlByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaFwiIG11c3QgYmUgZGVmaW5lZC4nKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmQoZWxlbWVudHMsIGV4cHJlc3Npb24sIGluZGV4KSB7XG4gICAgaW5kZXggPSBpbmRleCB8fCAwO1xuICAgIHZhciBtYXRjaCA9IFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaCwgbGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoLCBtYXRjaEluZGV4ID0gMCwgaTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG1hdGNoKGVsZW1lbnRzW2ldLCBleHByZXNzaW9uKSAmJiBpbmRleCA9PSBtYXRjaEluZGV4KyspIHtcbiAgICAgICAgcmV0dXJuIEVsZW1lbnQuZXh0ZW5kKGVsZW1lbnRzW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBleHRlbmRFbGVtZW50cyhlbGVtZW50cykge1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBlbGVtZW50cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgRWxlbWVudC5leHRlbmQoZWxlbWVudHNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gZWxlbWVudHM7XG4gIH1cblxuXG4gIHZhciBLID0gUHJvdG90eXBlLks7XG5cbiAgcmV0dXJuIHtcbiAgICBzZWxlY3Q6IHNlbGVjdCxcbiAgICBtYXRjaDogbWF0Y2gsXG4gICAgZmluZDogZmluZCxcbiAgICBleHRlbmRFbGVtZW50czogKEVsZW1lbnQuZXh0ZW5kID09PSBLKSA/IEsgOiBleHRlbmRFbGVtZW50cyxcbiAgICBleHRlbmRFbGVtZW50OiBFbGVtZW50LmV4dGVuZFxuICB9O1xufSkoKTtcblByb3RvdHlwZS5fb3JpZ2luYWxfcHJvcGVydHkgPSB3aW5kb3cuU2l6emxlO1xuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2QFZFUlNJT05cbiAqIGh0dHA6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IDIwMTMgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKiBodHRwOi8vanF1ZXJ5Lm9yZy9saWNlbnNlXG4gKlxuICogRGF0ZTogQERBVEVcbiAqL1xuKGZ1bmN0aW9uKCB3aW5kb3cgKSB7XG5cbnZhciBpLFxuXHRzdXBwb3J0LFxuXHRFeHByLFxuXHRnZXRUZXh0LFxuXHRpc1hNTCxcblx0Y29tcGlsZSxcblx0c2VsZWN0LFxuXHRvdXRlcm1vc3RDb250ZXh0LFxuXHRzb3J0SW5wdXQsXG5cdGhhc0R1cGxpY2F0ZSxcblxuXHRzZXREb2N1bWVudCxcblx0ZG9jdW1lbnQsXG5cdGRvY0VsZW0sXG5cdGRvY3VtZW50SXNIVE1MLFxuXHRyYnVnZ3lRU0EsXG5cdHJidWdneU1hdGNoZXMsXG5cdG1hdGNoZXMsXG5cdGNvbnRhaW5zLFxuXG5cdGV4cGFuZG8gPSBcInNpenpsZVwiICsgLShuZXcgRGF0ZSgpKSxcblx0cHJlZmVycmVkRG9jID0gd2luZG93LmRvY3VtZW50LFxuXHRkaXJydW5zID0gMCxcblx0ZG9uZSA9IDAsXG5cdGNsYXNzQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHR0b2tlbkNhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0Y29tcGlsZXJDYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdHNvcnRPcmRlciA9IGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdGlmICggYSA9PT0gYiApIHtcblx0XHRcdGhhc0R1cGxpY2F0ZSA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiAwO1xuXHR9LFxuXG5cdHN0cnVuZGVmaW5lZCA9IHR5cGVvZiB1bmRlZmluZWQsXG5cdE1BWF9ORUdBVElWRSA9IDEgPDwgMzEsXG5cblx0aGFzT3duID0gKHt9KS5oYXNPd25Qcm9wZXJ0eSxcblx0YXJyID0gW10sXG5cdHBvcCA9IGFyci5wb3AsXG5cdHB1c2hfbmF0aXZlID0gYXJyLnB1c2gsXG5cdHB1c2ggPSBhcnIucHVzaCxcblx0c2xpY2UgPSBhcnIuc2xpY2UsXG5cdGluZGV4T2YgPSBhcnIuaW5kZXhPZiB8fCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgaSA9IDAsXG5cdFx0XHRsZW4gPSB0aGlzLmxlbmd0aDtcblx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdGlmICggdGhpc1tpXSA9PT0gZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAtMTtcblx0fSxcblxuXHRib29sZWFucyA9IFwiY2hlY2tlZHxzZWxlY3RlZHxhc3luY3xhdXRvZm9jdXN8YXV0b3BsYXl8Y29udHJvbHN8ZGVmZXJ8ZGlzYWJsZWR8aGlkZGVufGlzbWFwfGxvb3B8bXVsdGlwbGV8b3BlbnxyZWFkb25seXxyZXF1aXJlZHxzY29wZWRcIixcblxuXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cdGNoYXJhY3RlckVuY29kaW5nID0gXCIoPzpcXFxcXFxcXC58W1xcXFx3LV18W15cXFxceDAwLVxcXFx4YTBdKStcIixcblxuXHRpZGVudGlmaWVyID0gY2hhcmFjdGVyRW5jb2RpbmcucmVwbGFjZSggXCJ3XCIsIFwidyNcIiApLFxuXG5cdGF0dHJpYnV0ZXMgPSBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFwiICsgY2hhcmFjdGVyRW5jb2RpbmcgKyBcIilcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKig/OihbKl4kfCF+XT89KVwiICsgd2hpdGVzcGFjZSArIFwiKig/OihbJ1xcXCJdKSgoPzpcXFxcXFxcXC58W15cXFxcXFxcXF0pKj8pXFxcXDN8KFwiICsgaWRlbnRpZmllciArIFwiKXwpfClcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcXVwiLFxuXG5cdHBzZXVkb3MgPSBcIjooXCIgKyBjaGFyYWN0ZXJFbmNvZGluZyArIFwiKSg/OlxcXFwoKChbJ1xcXCJdKSgoPzpcXFxcXFxcXC58W15cXFxcXFxcXF0pKj8pXFxcXDN8KCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcKClbXFxcXF1dfFwiICsgYXR0cmlidXRlcy5yZXBsYWNlKCAzLCA4ICkgKyBcIikqKXwuKilcXFxcKXwpXCIsXG5cblx0cnRyaW0gPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIit8KCg/Ol58W15cXFxcXFxcXF0pKD86XFxcXFxcXFwuKSopXCIgKyB3aGl0ZXNwYWNlICsgXCIrJFwiLCBcImdcIiApLFxuXG5cdHJjb21tYSA9IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKixcIiArIHdoaXRlc3BhY2UgKyBcIipcIiApLFxuXHRyY29tYmluYXRvcnMgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiooWz4rfl18XCIgKyB3aGl0ZXNwYWNlICsgXCIpXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblxuXHRyYXR0cmlidXRlUXVvdGVzID0gbmV3IFJlZ0V4cCggXCI9XCIgKyB3aGl0ZXNwYWNlICsgXCIqKFteXFxcXF0nXFxcIl0qPylcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcXVwiLCBcImdcIiApLFxuXG5cdHJwc2V1ZG8gPSBuZXcgUmVnRXhwKCBwc2V1ZG9zICksXG5cdHJpZGVudGlmaWVyID0gbmV3IFJlZ0V4cCggXCJeXCIgKyBpZGVudGlmaWVyICsgXCIkXCIgKSxcblxuXHRtYXRjaEV4cHIgPSB7XG5cdFx0XCJJRFwiOiBuZXcgUmVnRXhwKCBcIl4jKFwiICsgY2hhcmFjdGVyRW5jb2RpbmcgKyBcIilcIiApLFxuXHRcdFwiQ0xBU1NcIjogbmV3IFJlZ0V4cCggXCJeXFxcXC4oXCIgKyBjaGFyYWN0ZXJFbmNvZGluZyArIFwiKVwiICksXG5cdFx0XCJUQUdcIjogbmV3IFJlZ0V4cCggXCJeKFwiICsgY2hhcmFjdGVyRW5jb2RpbmcucmVwbGFjZSggXCJ3XCIsIFwidypcIiApICsgXCIpXCIgKSxcblx0XHRcIkFUVFJcIjogbmV3IFJlZ0V4cCggXCJeXCIgKyBhdHRyaWJ1dGVzICksXG5cdFx0XCJQU0VVRE9cIjogbmV3IFJlZ0V4cCggXCJeXCIgKyBwc2V1ZG9zICksXG5cdFx0XCJDSElMRFwiOiBuZXcgUmVnRXhwKCBcIl46KG9ubHl8Zmlyc3R8bGFzdHxudGh8bnRoLWxhc3QpLShjaGlsZHxvZi10eXBlKSg/OlxcXFwoXCIgKyB3aGl0ZXNwYWNlICtcblx0XHRcdFwiKihldmVufG9kZHwoKFsrLV18KShcXFxcZCopbnwpXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86KFsrLV18KVwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooXFxcXGQrKXwpKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfClcIiwgXCJpXCIgKSxcblx0XHRcImJvb2xcIjogbmV3IFJlZ0V4cCggXCJeKD86XCIgKyBib29sZWFucyArIFwiKSRcIiwgXCJpXCIgKSxcblx0XHRcIm5lZWRzQ29udGV4dFwiOiBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIipbPit+XXw6KGV2ZW58b2RkfGVxfGd0fGx0fG50aHxmaXJzdHxsYXN0KSg/OlxcXFwoXCIgK1xuXHRcdFx0d2hpdGVzcGFjZSArIFwiKigoPzotXFxcXGQpP1xcXFxkKilcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpKD89W14tXXwkKVwiLCBcImlcIiApXG5cdH0sXG5cblx0cmlucHV0cyA9IC9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGJ1dHRvbikkL2ksXG5cdHJoZWFkZXIgPSAvXmhcXGQkL2ksXG5cblx0cm5hdGl2ZSA9IC9eW157XStcXHtcXHMqXFxbbmF0aXZlIFxcdy8sXG5cblx0cnF1aWNrRXhwciA9IC9eKD86IyhbXFx3LV0rKXwoXFx3Kyl8XFwuKFtcXHctXSspKSQvLFxuXG5cdHJzaWJsaW5nID0gL1srfl0vLFxuXHRyZXNjYXBlID0gLyd8XFxcXC9nLFxuXG5cdHJ1bmVzY2FwZSA9IG5ldyBSZWdFeHAoIFwiXFxcXFxcXFwoW1xcXFxkYS1mXXsxLDZ9XCIgKyB3aGl0ZXNwYWNlICsgXCI/fChcIiArIHdoaXRlc3BhY2UgKyBcIil8LilcIiwgXCJpZ1wiICksXG5cdGZ1bmVzY2FwZSA9IGZ1bmN0aW9uKCBfLCBlc2NhcGVkLCBlc2NhcGVkV2hpdGVzcGFjZSApIHtcblx0XHR2YXIgaGlnaCA9IFwiMHhcIiArIGVzY2FwZWQgLSAweDEwMDAwO1xuXHRcdHJldHVybiBoaWdoICE9PSBoaWdoIHx8IGVzY2FwZWRXaGl0ZXNwYWNlID9cblx0XHRcdGVzY2FwZWQgOlxuXHRcdFx0aGlnaCA8IDAgP1xuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoICsgMHgxMDAwMCApIDpcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCA+PiAxMCB8IDB4RDgwMCwgaGlnaCAmIDB4M0ZGIHwgMHhEQzAwICk7XG5cdH07XG5cbnRyeSB7XG5cdHB1c2guYXBwbHkoXG5cdFx0KGFyciA9IHNsaWNlLmNhbGwoIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzICkpLFxuXHRcdHByZWZlcnJlZERvYy5jaGlsZE5vZGVzXG5cdCk7XG5cdGFyclsgcHJlZmVycmVkRG9jLmNoaWxkTm9kZXMubGVuZ3RoIF0ubm9kZVR5cGU7XG59IGNhdGNoICggZSApIHtcblx0cHVzaCA9IHsgYXBwbHk6IGFyci5sZW5ndGggP1xuXG5cdFx0ZnVuY3Rpb24oIHRhcmdldCwgZWxzICkge1xuXHRcdFx0cHVzaF9uYXRpdmUuYXBwbHkoIHRhcmdldCwgc2xpY2UuY2FsbChlbHMpICk7XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHR2YXIgaiA9IHRhcmdldC5sZW5ndGgsXG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0d2hpbGUgKCAodGFyZ2V0W2orK10gPSBlbHNbaSsrXSkgKSB7fVxuXHRcdFx0dGFyZ2V0Lmxlbmd0aCA9IGogLSAxO1xuXHRcdH1cblx0fTtcbn1cblxuZnVuY3Rpb24gU2l6emxlKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIG1hdGNoLCBlbGVtLCBtLCBub2RlVHlwZSxcblx0XHRpLCBncm91cHMsIG9sZCwgbmlkLCBuZXdDb250ZXh0LCBuZXdTZWxlY3RvcjtcblxuXHRpZiAoICggY29udGV4dCA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogcHJlZmVycmVkRG9jICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBjb250ZXh0ICk7XG5cdH1cblxuXHRjb250ZXh0ID0gY29udGV4dCB8fCBkb2N1bWVudDtcblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0aWYgKCAhc2VsZWN0b3IgfHwgdHlwZW9mIHNlbGVjdG9yICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiByZXN1bHRzO1xuXHR9XG5cblx0aWYgKCAobm9kZVR5cGUgPSBjb250ZXh0Lm5vZGVUeXBlKSAhPT0gMSAmJiBub2RlVHlwZSAhPT0gOSApIHtcblx0XHRyZXR1cm4gW107XG5cdH1cblxuXHRpZiAoIGRvY3VtZW50SXNIVE1MICYmICFzZWVkICkge1xuXG5cdFx0aWYgKCAobWF0Y2ggPSBycXVpY2tFeHByLmV4ZWMoIHNlbGVjdG9yICkpICkge1xuXHRcdFx0aWYgKCAobSA9IG1hdGNoWzFdKSApIHtcblx0XHRcdFx0aWYgKCBub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0XHRlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApO1xuXHRcdFx0XHRcdGlmICggZWxlbSAmJiBlbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0uaWQgPT09IG0gKSB7XG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmICggY29udGV4dC5vd25lckRvY3VtZW50ICYmIChlbGVtID0gY29udGV4dC5vd25lckRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCBtICkpICYmXG5cdFx0XHRcdFx0XHRjb250YWlucyggY29udGV4dCwgZWxlbSApICYmIGVsZW0uaWQgPT09IG0gKSB7XG5cdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFsyXSApIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggc2VsZWN0b3IgKSApO1xuXHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblxuXHRcdFx0fSBlbHNlIGlmICggKG0gPSBtYXRjaFszXSkgJiYgc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCBtICkgKTtcblx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCBzdXBwb3J0LnFzYSAmJiAoIXJidWdneVFTQSB8fCAhcmJ1Z2d5UVNBLnRlc3QoIHNlbGVjdG9yICkpICkge1xuXHRcdFx0bmlkID0gb2xkID0gZXhwYW5kbztcblx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0bmV3U2VsZWN0b3IgPSBub2RlVHlwZSA9PT0gOSAmJiBzZWxlY3RvcjtcblxuXHRcdFx0aWYgKCBub2RlVHlwZSA9PT0gMSAmJiBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cdFx0XHRcdGdyb3VwcyA9IHRva2VuaXplKCBzZWxlY3RvciApO1xuXG5cdFx0XHRcdGlmICggKG9sZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKFwiaWRcIikpICkge1xuXHRcdFx0XHRcdG5pZCA9IG9sZC5yZXBsYWNlKCByZXNjYXBlLCBcIlxcXFwkJlwiICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29udGV4dC5zZXRBdHRyaWJ1dGUoIFwiaWRcIiwgbmlkICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0bmlkID0gXCJbaWQ9J1wiICsgbmlkICsgXCInXSBcIjtcblxuXHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0Z3JvdXBzW2ldID0gbmlkICsgdG9TZWxlY3RvciggZ3JvdXBzW2ldICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0bmV3Q29udGV4dCA9IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHQ7XG5cdFx0XHRcdG5ld1NlbGVjdG9yID0gZ3JvdXBzLmpvaW4oXCIsXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIG5ld1NlbGVjdG9yICkge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRuZXdDb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIG5ld1NlbGVjdG9yIClcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHR9IGNhdGNoKHFzYUVycm9yKSB7XG5cdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0aWYgKCAhb2xkICkge1xuXHRcdFx0XHRcdFx0Y29udGV4dC5yZW1vdmVBdHRyaWJ1dGUoXCJpZFwiKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gc2VsZWN0KCBzZWxlY3Rvci5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICksIGNvbnRleHQsIHJlc3VsdHMsIHNlZWQgKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUga2V5LXZhbHVlIGNhY2hlcyBvZiBsaW1pdGVkIHNpemVcbiAqIEByZXR1cm5zIHtGdW5jdGlvbihzdHJpbmcsIE9iamVjdCl9IFJldHVybnMgdGhlIE9iamVjdCBkYXRhIGFmdGVyIHN0b3JpbmcgaXQgb24gaXRzZWxmIHdpdGhcbiAqXHRwcm9wZXJ0eSBuYW1lIHRoZSAoc3BhY2Utc3VmZml4ZWQpIHN0cmluZyBhbmQgKGlmIHRoZSBjYWNoZSBpcyBsYXJnZXIgdGhhbiBFeHByLmNhY2hlTGVuZ3RoKVxuICpcdGRlbGV0aW5nIHRoZSBvbGRlc3QgZW50cnlcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQ2FjaGUoKSB7XG5cdHZhciBrZXlzID0gW107XG5cblx0ZnVuY3Rpb24gY2FjaGUoIGtleSwgdmFsdWUgKSB7XG5cdFx0aWYgKCBrZXlzLnB1c2goIGtleSArIFwiIFwiICkgPiBFeHByLmNhY2hlTGVuZ3RoICkge1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBkaXYgYW5kIGV4cGVjdHMgYSBib29sZWFuIHJlc3VsdFxuICovXG5mdW5jdGlvbiBhc3NlcnQoIGZuICkge1xuXHR2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblxuXHR0cnkge1xuXHRcdHJldHVybiAhIWZuKCBkaXYgKTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fSBmaW5hbGx5IHtcblx0XHRpZiAoIGRpdi5wYXJlbnROb2RlICkge1xuXHRcdFx0ZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIGRpdiApO1xuXHRcdH1cblx0XHRkaXYgPSBudWxsO1xuXHR9XG59XG5cbi8qKlxuICogQWRkcyB0aGUgc2FtZSBoYW5kbGVyIGZvciBhbGwgb2YgdGhlIHNwZWNpZmllZCBhdHRyc1xuICogQHBhcmFtIHtTdHJpbmd9IGF0dHJzIFBpcGUtc2VwYXJhdGVkIGxpc3Qgb2YgYXR0cmlidXRlc1xuICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlciBUaGUgbWV0aG9kIHRoYXQgd2lsbCBiZSBhcHBsaWVkXG4gKi9cbmZ1bmN0aW9uIGFkZEhhbmRsZSggYXR0cnMsIGhhbmRsZXIgKSB7XG5cdHZhciBhcnIgPSBhdHRycy5zcGxpdChcInxcIiksXG5cdFx0aSA9IGF0dHJzLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRFeHByLmF0dHJIYW5kbGVbIGFycltpXSBdID0gaGFuZGxlcjtcblx0fVxufVxuXG4vKipcbiAqIENoZWNrcyBkb2N1bWVudCBvcmRlciBvZiB0d28gc2libGluZ3NcbiAqIEBwYXJhbSB7RWxlbWVudH0gYVxuICogQHBhcmFtIHtFbGVtZW50fSBiXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIGxlc3MgdGhhbiAwIGlmIGEgcHJlY2VkZXMgYiwgZ3JlYXRlciB0aGFuIDAgaWYgYSBmb2xsb3dzIGJcbiAqL1xuZnVuY3Rpb24gc2libGluZ0NoZWNrKCBhLCBiICkge1xuXHR2YXIgY3VyID0gYiAmJiBhLFxuXHRcdGRpZmYgPSBjdXIgJiYgYS5ub2RlVHlwZSA9PT0gMSAmJiBiLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHQoIH5iLnNvdXJjZUluZGV4IHx8IE1BWF9ORUdBVElWRSApIC1cblx0XHRcdCggfmEuc291cmNlSW5kZXggfHwgTUFYX05FR0FUSVZFICk7XG5cblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIHBvc2l0aW9uYWxzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxuICovXG5mdW5jdGlvbiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKCBmbiApIHtcblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggYXJndW1lbnQgKSB7XG5cdFx0YXJndW1lbnQgPSArYXJndW1lbnQ7XG5cdFx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdHZhciBqLFxuXHRcdFx0XHRtYXRjaEluZGV4ZXMgPSBmbiggW10sIHNlZWQubGVuZ3RoLCBhcmd1bWVudCApLFxuXHRcdFx0XHRpID0gbWF0Y2hJbmRleGVzLmxlbmd0aDtcblxuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggc2VlZFsgKGogPSBtYXRjaEluZGV4ZXNbaV0pIF0gKSB7XG5cdFx0XHRcdFx0c2VlZFtqXSA9ICEobWF0Y2hlc1tqXSA9IHNlZWRbal0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xufVxuXG4vKipcbiAqIENoZWNrcyBhIG5vZGUgZm9yIHZhbGlkaXR5IGFzIGEgU2l6emxlIGNvbnRleHRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3Q9fSBjb250ZXh0XG4gKiBAcmV0dXJucyB7RWxlbWVudHxPYmplY3R8Qm9vbGVhbn0gVGhlIGlucHV0IG5vZGUgaWYgYWNjZXB0YWJsZSwgb3RoZXJ3aXNlIGEgZmFsc3kgdmFsdWVcbiAqL1xuZnVuY3Rpb24gdGVzdENvbnRleHQoIGNvbnRleHQgKSB7XG5cdHJldHVybiBjb250ZXh0ICYmIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lICE9PSBzdHJ1bmRlZmluZWQgJiYgY29udGV4dDtcbn1cblxuc3VwcG9ydCA9IFNpenpsZS5zdXBwb3J0ID0ge307XG5cbi8qKlxuICogRGV0ZWN0cyBYTUwgbm9kZXNcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IGVsZW0gQW4gZWxlbWVudCBvciBhIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZmYgZWxlbSBpcyBhIG5vbi1IVE1MIFhNTCBub2RlXG4gKi9cbmlzWE1MID0gU2l6emxlLmlzWE1MID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHZhciBkb2N1bWVudEVsZW1lbnQgPSBlbGVtICYmIChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSkuZG9jdW1lbnRFbGVtZW50O1xuXHRyZXR1cm4gZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lICE9PSBcIkhUTUxcIiA6IGZhbHNlO1xufTtcblxuLyoqXG4gKiBTZXRzIGRvY3VtZW50LXJlbGF0ZWQgdmFyaWFibGVzIG9uY2UgYmFzZWQgb24gdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IFtkb2NdIEFuIGVsZW1lbnQgb3IgZG9jdW1lbnQgb2JqZWN0IHRvIHVzZSB0byBzZXQgdGhlIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKi9cbnNldERvY3VtZW50ID0gU2l6emxlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oIG5vZGUgKSB7XG5cdHZhciBoYXNDb21wYXJlLFxuXHRcdGRvYyA9IG5vZGUgPyBub2RlLm93bmVyRG9jdW1lbnQgfHwgbm9kZSA6IHByZWZlcnJlZERvYyxcblx0XHRwYXJlbnQgPSBkb2MuZGVmYXVsdFZpZXc7XG5cblx0aWYgKCBkb2MgPT09IGRvY3VtZW50IHx8IGRvYy5ub2RlVHlwZSAhPT0gOSB8fCAhZG9jLmRvY3VtZW50RWxlbWVudCApIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQ7XG5cdH1cblxuXHRkb2N1bWVudCA9IGRvYztcblx0ZG9jRWxlbSA9IGRvYy5kb2N1bWVudEVsZW1lbnQ7XG5cblx0ZG9jdW1lbnRJc0hUTUwgPSAhaXNYTUwoIGRvYyApO1xuXG5cdGlmICggcGFyZW50ICYmIHBhcmVudCAhPT0gcGFyZW50LnRvcCApIHtcblx0XHRpZiAoIHBhcmVudC5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0cGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoIFwidW5sb2FkXCIsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRzZXREb2N1bWVudCgpO1xuXHRcdFx0fSwgZmFsc2UgKTtcblx0XHR9IGVsc2UgaWYgKCBwYXJlbnQuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRwYXJlbnQuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHNldERvY3VtZW50KCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHQvKiBBdHRyaWJ1dGVzXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHRzdXBwb3J0LmF0dHJpYnV0ZXMgPSBhc3NlcnQoZnVuY3Rpb24oIGRpdiApIHtcblx0XHRkaXYuY2xhc3NOYW1lID0gXCJpXCI7XG5cdFx0cmV0dXJuICFkaXYuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpO1xuXHR9KTtcblxuXHQvKiBnZXRFbGVtZW50KHMpQnkqXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHRzdXBwb3J0LmdldEVsZW1lbnRzQnlUYWdOYW1lID0gYXNzZXJ0KGZ1bmN0aW9uKCBkaXYgKSB7XG5cdFx0ZGl2LmFwcGVuZENoaWxkKCBkb2MuY3JlYXRlQ29tbWVudChcIlwiKSApO1xuXHRcdHJldHVybiAhZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiKlwiKS5sZW5ndGg7XG5cdH0pO1xuXG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jLmdldEVsZW1lbnRzQnlDbGFzc05hbWUgKSAmJiBhc3NlcnQoZnVuY3Rpb24oIGRpdiApIHtcblx0XHRkaXYuaW5uZXJIVE1MID0gXCI8ZGl2IGNsYXNzPSdhJz48L2Rpdj48ZGl2IGNsYXNzPSdhIGknPjwvZGl2PlwiO1xuXG5cdFx0ZGl2LmZpcnN0Q2hpbGQuY2xhc3NOYW1lID0gXCJpXCI7XG5cdFx0cmV0dXJuIGRpdi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaVwiKS5sZW5ndGggPT09IDI7XG5cdH0pO1xuXG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRcdGRvY0VsZW0uYXBwZW5kQ2hpbGQoIGRpdiApLmlkID0gZXhwYW5kbztcblx0XHRyZXR1cm4gIWRvYy5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jLmdldEVsZW1lbnRzQnlOYW1lKCBleHBhbmRvICkubGVuZ3RoO1xuXHR9KTtcblxuXHRpZiAoIHN1cHBvcnQuZ2V0QnlJZCApIHtcblx0XHRFeHByLmZpbmRbXCJJRFwiXSA9IGZ1bmN0aW9uKCBpZCwgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQgIT09IHN0cnVuZGVmaW5lZCAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdFx0dmFyIG0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBpZCApO1xuXHRcdFx0XHRyZXR1cm4gbSAmJiBtLnBhcmVudE5vZGUgPyBbbV0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSBmdW5jdGlvbiggaWQgKSB7XG5cdFx0XHR2YXIgYXR0cklkID0gaWQucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKFwiaWRcIikgPT09IGF0dHJJZDtcblx0XHRcdH07XG5cdFx0fTtcblx0fSBlbHNlIHtcblx0XHRkZWxldGUgRXhwci5maW5kW1wiSURcIl07XG5cblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gIGZ1bmN0aW9uKCBpZCApIHtcblx0XHRcdHZhciBhdHRySWQgPSBpZC5yZXBsYWNlKCBydW5lc2NhcGUsIGZ1bmVzY2FwZSApO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgbm9kZSA9IHR5cGVvZiBlbGVtLmdldEF0dHJpYnV0ZU5vZGUgIT09IHN0cnVuZGVmaW5lZCAmJiBlbGVtLmdldEF0dHJpYnV0ZU5vZGUoXCJpZFwiKTtcblx0XHRcdFx0cmV0dXJuIG5vZGUgJiYgbm9kZS52YWx1ZSA9PT0gYXR0cklkO1xuXHRcdFx0fTtcblx0XHR9O1xuXHR9XG5cblx0RXhwci5maW5kW1wiVEFHXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/XG5cdFx0ZnVuY3Rpb24oIHRhZywgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IHN0cnVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIHRhZyApO1xuXHRcdFx0fVxuXHRcdH0gOlxuXHRcdGZ1bmN0aW9uKCB0YWcsIGNvbnRleHQgKSB7XG5cdFx0XHR2YXIgZWxlbSxcblx0XHRcdFx0dG1wID0gW10sXG5cdFx0XHRcdGkgPSAwLFxuXHRcdFx0XHRyZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnICk7XG5cblx0XHRcdGlmICggdGFnID09PSBcIipcIiApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRcdFx0dG1wLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdG1wO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0fTtcblxuXHRFeHByLmZpbmRbXCJDTEFTU1wiXSA9IHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBmdW5jdGlvbiggY2xhc3NOYW1lLCBjb250ZXh0ICkge1xuXHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gc3RydW5kZWZpbmVkICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSggY2xhc3NOYW1lICk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qIFFTQS9tYXRjaGVzU2VsZWN0b3Jcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdHJidWdneVFTQSA9IFtdO1xuXG5cdGlmICggKHN1cHBvcnQucXNhID0gcm5hdGl2ZS50ZXN0KCBkb2MucXVlcnlTZWxlY3RvckFsbCApKSApIHtcblx0XHRhc3NlcnQoZnVuY3Rpb24oIGRpdiApIHtcblx0XHRcdGRpdi5pbm5lckhUTUwgPSBcIjxzZWxlY3QgdD0nJz48b3B0aW9uIHNlbGVjdGVkPScnPjwvb3B0aW9uPjwvc2VsZWN0PlwiO1xuXG5cdFx0XHRpZiAoIGRpdi5xdWVyeVNlbGVjdG9yQWxsKFwiW3RePScnXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlsqXiRdPVwiICsgd2hpdGVzcGFjZSArIFwiKig/OicnfFxcXCJcXFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggIWRpdi5xdWVyeVNlbGVjdG9yQWxsKFwiW3NlbGVjdGVkXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86dmFsdWV8XCIgKyBib29sZWFucyArIFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggIWRpdi5xdWVyeVNlbGVjdG9yQWxsKFwiOmNoZWNrZWRcIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaChcIjpjaGVja2VkXCIpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0YXNzZXJ0KGZ1bmN0aW9uKCBkaXYgKSB7XG5cdFx0XHR2YXIgaW5wdXQgPSBkb2MuY3JlYXRlRWxlbWVudChcImlucHV0XCIpO1xuXHRcdFx0aW5wdXQuc2V0QXR0cmlidXRlKCBcInR5cGVcIiwgXCJoaWRkZW5cIiApO1xuXHRcdFx0ZGl2LmFwcGVuZENoaWxkKCBpbnB1dCApLnNldEF0dHJpYnV0ZSggXCJuYW1lXCIsIFwiRFwiICk7XG5cblx0XHRcdGlmICggZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCJbbmFtZT1kXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIm5hbWVcIiArIHdoaXRlc3BhY2UgKyBcIipbKl4kfCF+XT89XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZW5hYmxlZFwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIjplbmFibGVkXCIsIFwiOmRpc2FibGVkXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0ZGl2LnF1ZXJ5U2VsZWN0b3JBbGwoXCIqLDp4XCIpO1xuXHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCIsLio6XCIpO1xuXHRcdH0pO1xuXHR9XG5cblx0aWYgKCAoc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgPSBybmF0aXZlLnRlc3QoIChtYXRjaGVzID0gZG9jRWxlbS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1vek1hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ub01hdGNoZXNTZWxlY3RvciB8fFxuXHRcdGRvY0VsZW0ubXNNYXRjaGVzU2VsZWN0b3IpICkpICkge1xuXG5cdFx0YXNzZXJ0KGZ1bmN0aW9uKCBkaXYgKSB7XG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBkaXYsIFwiZGl2XCIgKTtcblxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBkaXYsIFwiW3MhPScnXTp4XCIgKTtcblx0XHRcdHJidWdneU1hdGNoZXMucHVzaCggXCIhPVwiLCBwc2V1ZG9zICk7XG5cdFx0fSk7XG5cdH1cblxuXHRyYnVnZ3lRU0EgPSByYnVnZ3lRU0EubGVuZ3RoICYmIG5ldyBSZWdFeHAoIHJidWdneVFTQS5qb2luKFwifFwiKSApO1xuXHRyYnVnZ3lNYXRjaGVzID0gcmJ1Z2d5TWF0Y2hlcy5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5TWF0Y2hlcy5qb2luKFwifFwiKSApO1xuXG5cdC8qIENvbnRhaW5zXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblx0aGFzQ29tcGFyZSA9IHJuYXRpdmUudGVzdCggZG9jRWxlbS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiApO1xuXG5cdGNvbnRhaW5zID0gaGFzQ29tcGFyZSB8fCBybmF0aXZlLnRlc3QoIGRvY0VsZW0uY29udGFpbnMgKSA/XG5cdFx0ZnVuY3Rpb24oIGEsIGIgKSB7XG5cdFx0XHR2YXIgYWRvd24gPSBhLm5vZGVUeXBlID09PSA5ID8gYS5kb2N1bWVudEVsZW1lbnQgOiBhLFxuXHRcdFx0XHRidXAgPSBiICYmIGIucGFyZW50Tm9kZTtcblx0XHRcdHJldHVybiBhID09PSBidXAgfHwgISEoIGJ1cCAmJiBidXAubm9kZVR5cGUgPT09IDEgJiYgKFxuXHRcdFx0XHRhZG93bi5jb250YWlucyA/XG5cdFx0XHRcdFx0YWRvd24uY29udGFpbnMoIGJ1cCApIDpcblx0XHRcdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICYmIGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGJ1cCApICYgMTZcblx0XHRcdCkpO1xuXHRcdH0gOlxuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0aWYgKCBiICkge1xuXHRcdFx0XHR3aGlsZSAoIChiID0gYi5wYXJlbnROb2RlKSApIHtcblx0XHRcdFx0XHRpZiAoIGIgPT09IGEgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9O1xuXG5cdC8qIFNvcnRpbmdcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdHNvcnRPcmRlciA9IGhhc0NvbXBhcmUgP1xuXHRmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdGlmICggYSA9PT0gYiApIHtcblx0XHRcdGhhc0R1cGxpY2F0ZSA9IHRydWU7XG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHR2YXIgY29tcGFyZSA9ICFhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uIC0gIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247XG5cdFx0aWYgKCBjb21wYXJlICkge1xuXHRcdFx0cmV0dXJuIGNvbXBhcmU7XG5cdFx0fVxuXG5cdFx0Y29tcGFyZSA9ICggYS5vd25lckRvY3VtZW50IHx8IGEgKSA9PT0gKCBiLm93bmVyRG9jdW1lbnQgfHwgYiApID9cblx0XHRcdGEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGIgKSA6XG5cblx0XHRcdDE7XG5cblx0XHRpZiAoIGNvbXBhcmUgJiAxIHx8XG5cdFx0XHQoIXN1cHBvcnQuc29ydERldGFjaGVkICYmIGIuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGEgKSA9PT0gY29tcGFyZSkgKSB7XG5cblx0XHRcdGlmICggYSA9PT0gZG9jIHx8IGEub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYSkgKSB7XG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHRcdGlmICggYiA9PT0gZG9jIHx8IGIub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYikgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gc29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mLmNhbGwoIHNvcnRJbnB1dCwgYSApIC0gaW5kZXhPZi5jYWxsKCBzb3J0SW5wdXQsIGIgKSApIDpcblx0XHRcdFx0MDtcblx0XHR9XG5cblx0XHRyZXR1cm4gY29tcGFyZSAmIDQgPyAtMSA6IDE7XG5cdH0gOlxuXHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0YXVwID0gYS5wYXJlbnROb2RlLFxuXHRcdFx0YnVwID0gYi5wYXJlbnROb2RlLFxuXHRcdFx0YXAgPSBbIGEgXSxcblx0XHRcdGJwID0gWyBiIF07XG5cblx0XHRpZiAoICFhdXAgfHwgIWJ1cCApIHtcblx0XHRcdHJldHVybiBhID09PSBkb2MgPyAtMSA6XG5cdFx0XHRcdGIgPT09IGRvYyA/IDEgOlxuXHRcdFx0XHRhdXAgPyAtMSA6XG5cdFx0XHRcdGJ1cCA/IDEgOlxuXHRcdFx0XHRzb3J0SW5wdXQgP1xuXHRcdFx0XHQoIGluZGV4T2YuY2FsbCggc29ydElucHV0LCBhICkgLSBpbmRleE9mLmNhbGwoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0fSBlbHNlIGlmICggYXVwID09PSBidXAgKSB7XG5cdFx0XHRyZXR1cm4gc2libGluZ0NoZWNrKCBhLCBiICk7XG5cdFx0fVxuXG5cdFx0Y3VyID0gYTtcblx0XHR3aGlsZSAoIChjdXIgPSBjdXIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRhcC51bnNoaWZ0KCBjdXIgKTtcblx0XHR9XG5cdFx0Y3VyID0gYjtcblx0XHR3aGlsZSAoIChjdXIgPSBjdXIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRicC51bnNoaWZ0KCBjdXIgKTtcblx0XHR9XG5cblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHRzaWJsaW5nQ2hlY2soIGFwW2ldLCBicFtpXSApIDpcblxuXHRcdFx0YXBbaV0gPT09IHByZWZlcnJlZERvYyA/IC0xIDpcblx0XHRcdGJwW2ldID09PSBwcmVmZXJyZWREb2MgPyAxIDpcblx0XHRcdDA7XG5cdH07XG5cblx0cmV0dXJuIGRvYztcbn07XG5cblNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1lbnRzICkge1xuXHRyZXR1cm4gU2l6emxlKCBleHByLCBudWxsLCBudWxsLCBlbGVtZW50cyApO1xufTtcblxuU2l6emxlLm1hdGNoZXNTZWxlY3RvciA9IGZ1bmN0aW9uKCBlbGVtLCBleHByICkge1xuXHRpZiAoICggZWxlbS5vd25lckRvY3VtZW50IHx8IGVsZW0gKSAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0c2V0RG9jdW1lbnQoIGVsZW0gKTtcblx0fVxuXG5cdGV4cHIgPSBleHByLnJlcGxhY2UoIHJhdHRyaWJ1dGVRdW90ZXMsIFwiPSckMSddXCIgKTtcblxuXHRpZiAoIHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yICYmIGRvY3VtZW50SXNIVE1MICYmXG5cdFx0KCAhcmJ1Z2d5TWF0Y2hlcyB8fCAhcmJ1Z2d5TWF0Y2hlcy50ZXN0KCBleHByICkgKSAmJlxuXHRcdCggIXJidWdneVFTQSAgICAgfHwgIXJidWdneVFTQS50ZXN0KCBleHByICkgKSApIHtcblxuXHRcdHRyeSB7XG5cdFx0XHR2YXIgcmV0ID0gbWF0Y2hlcy5jYWxsKCBlbGVtLCBleHByICk7XG5cblx0XHRcdGlmICggcmV0IHx8IHN1cHBvcnQuZGlzY29ubmVjdGVkTWF0Y2ggfHxcblx0XHRcdFx0XHRlbGVtLmRvY3VtZW50ICYmIGVsZW0uZG9jdW1lbnQubm9kZVR5cGUgIT09IDExICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2goZSkge31cblx0fVxuXG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIGRvY3VtZW50LCBudWxsLCBbZWxlbV0gKS5sZW5ndGggPiAwO1xufTtcblxuU2l6emxlLmNvbnRhaW5zID0gZnVuY3Rpb24oIGNvbnRleHQsIGVsZW0gKSB7XG5cdGlmICggKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgfHwgY29udGV4dCApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHR9XG5cdHJldHVybiBjb250YWlucyggY29udGV4dCwgZWxlbSApO1xufTtcblxuU2l6emxlLmF0dHIgPSBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHR2YXIgZm4gPSBFeHByLmF0dHJIYW5kbGVbIG5hbWUudG9Mb3dlckNhc2UoKSBdLFxuXHRcdHZhbCA9IGZuICYmIGhhc093bi5jYWxsKCBFeHByLmF0dHJIYW5kbGUsIG5hbWUudG9Mb3dlckNhc2UoKSApID9cblx0XHRcdGZuKCBlbGVtLCBuYW1lLCAhZG9jdW1lbnRJc0hUTUwgKSA6XG5cdFx0XHR1bmRlZmluZWQ7XG5cblx0cmV0dXJuIHZhbCAhPT0gdW5kZWZpbmVkID9cblx0XHR2YWwgOlxuXHRcdHN1cHBvcnQuYXR0cmlidXRlcyB8fCAhZG9jdW1lbnRJc0hUTUwgP1xuXHRcdFx0ZWxlbS5nZXRBdHRyaWJ1dGUoIG5hbWUgKSA6XG5cdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKG5hbWUpKSAmJiB2YWwuc3BlY2lmaWVkID9cblx0XHRcdFx0dmFsLnZhbHVlIDpcblx0XHRcdFx0bnVsbDtcbn07XG5cblNpenpsZS5lcnJvciA9IGZ1bmN0aW9uKCBtc2cgKSB7XG5cdHRocm93IG5ldyBFcnJvciggXCJTeW50YXggZXJyb3IsIHVucmVjb2duaXplZCBleHByZXNzaW9uOiBcIiArIG1zZyApO1xufTtcblxuLyoqXG4gKiBEb2N1bWVudCBzb3J0aW5nIGFuZCByZW1vdmluZyBkdXBsaWNhdGVzXG4gKiBAcGFyYW0ge0FycmF5TGlrZX0gcmVzdWx0c1xuICovXG5TaXp6bGUudW5pcXVlU29ydCA9IGZ1bmN0aW9uKCByZXN1bHRzICkge1xuXHR2YXIgZWxlbSxcblx0XHRkdXBsaWNhdGVzID0gW10sXG5cdFx0aiA9IDAsXG5cdFx0aSA9IDA7XG5cblx0aGFzRHVwbGljYXRlID0gIXN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcztcblx0c29ydElucHV0ID0gIXN1cHBvcnQuc29ydFN0YWJsZSAmJiByZXN1bHRzLnNsaWNlKCAwICk7XG5cdHJlc3VsdHMuc29ydCggc29ydE9yZGVyICk7XG5cblx0aWYgKCBoYXNEdXBsaWNhdGUgKSB7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRpZiAoIGVsZW0gPT09IHJlc3VsdHNbIGkgXSApIHtcblx0XHRcdFx0aiA9IGR1cGxpY2F0ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdHJlc3VsdHMuc3BsaWNlKCBkdXBsaWNhdGVzWyBqIF0sIDEgKTtcblx0XHR9XG5cdH1cblxuXHRzb3J0SW5wdXQgPSBudWxsO1xuXG5cdHJldHVybiByZXN1bHRzO1xufTtcblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9uIGZvciByZXRyaWV2aW5nIHRoZSB0ZXh0IHZhbHVlIG9mIGFuIGFycmF5IG9mIERPTSBub2Rlc1xuICogQHBhcmFtIHtBcnJheXxFbGVtZW50fSBlbGVtXG4gKi9cbmdldFRleHQgPSBTaXp6bGUuZ2V0VGV4dCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHR2YXIgbm9kZSxcblx0XHRyZXQgPSBcIlwiLFxuXHRcdGkgPSAwLFxuXHRcdG5vZGVUeXBlID0gZWxlbS5ub2RlVHlwZTtcblxuXHRpZiAoICFub2RlVHlwZSApIHtcblx0XHR3aGlsZSAoIChub2RlID0gZWxlbVtpKytdKSApIHtcblx0XHRcdHJldCArPSBnZXRUZXh0KCBub2RlICk7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKCBub2RlVHlwZSA9PT0gMSB8fCBub2RlVHlwZSA9PT0gOSB8fCBub2RlVHlwZSA9PT0gMTEgKSB7XG5cdFx0aWYgKCB0eXBlb2YgZWxlbS50ZXh0Q29udGVudCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiBlbGVtLnRleHRDb250ZW50O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBlbGVtID0gZWxlbS5maXJzdENoaWxkOyBlbGVtOyBlbGVtID0gZWxlbS5uZXh0U2libGluZyApIHtcblx0XHRcdFx0cmV0ICs9IGdldFRleHQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAzIHx8IG5vZGVUeXBlID09PSA0ICkge1xuXHRcdHJldHVybiBlbGVtLm5vZGVWYWx1ZTtcblx0fVxuXG5cdHJldHVybiByZXQ7XG59O1xuXG5FeHByID0gU2l6emxlLnNlbGVjdG9ycyA9IHtcblxuXHRjYWNoZUxlbmd0aDogNTAsXG5cblx0Y3JlYXRlUHNldWRvOiBtYXJrRnVuY3Rpb24sXG5cblx0bWF0Y2g6IG1hdGNoRXhwcixcblxuXHRhdHRySGFuZGxlOiB7fSxcblxuXHRmaW5kOiB7fSxcblxuXHRyZWxhdGl2ZToge1xuXHRcdFwiPlwiOiB7IGRpcjogXCJwYXJlbnROb2RlXCIsIGZpcnN0OiB0cnVlIH0sXG5cdFx0XCIgXCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiB9LFxuXHRcdFwiK1wiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIn5cIjogeyBkaXI6IFwicHJldmlvdXNTaWJsaW5nXCIgfVxuXHR9LFxuXG5cdHByZUZpbHRlcjoge1xuXHRcdFwiQVRUUlwiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHRtYXRjaFsxXSA9IG1hdGNoWzFdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cblx0XHRcdG1hdGNoWzNdID0gKCBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiICkucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsyXSA9PT0gXCJ+PVwiICkge1xuXHRcdFx0XHRtYXRjaFszXSA9IFwiIFwiICsgbWF0Y2hbM10gKyBcIiBcIjtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCA0ICk7XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0LyogbWF0Y2hlcyBmcm9tIG1hdGNoRXhwcltcIkNISUxEXCJdXG5cdFx0XHRcdDEgdHlwZSAob25seXxudGh8Li4uKVxuXHRcdFx0XHQyIHdoYXQgKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdDMgYXJndW1lbnQgKGV2ZW58b2RkfFxcZCp8XFxkKm4oWystXVxcZCspP3wuLi4pXG5cdFx0XHRcdDQgeG4tY29tcG9uZW50IG9mIHhuK3kgYXJndW1lbnQgKFsrLV0/XFxkKm58KVxuXHRcdFx0XHQ1IHNpZ24gb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDYgeCBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NyBzaWduIG9mIHktY29tcG9uZW50XG5cdFx0XHRcdDggeSBvZiB5LWNvbXBvbmVudFxuXHRcdFx0Ki9cblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsxXS5zbGljZSggMCwgMyApID09PSBcIm50aFwiICkge1xuXHRcdFx0XHRpZiAoICFtYXRjaFszXSApIHtcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRtYXRjaFs0XSA9ICsoIG1hdGNoWzRdID8gbWF0Y2hbNV0gKyAobWF0Y2hbNl0gfHwgMSkgOiAyICogKCBtYXRjaFszXSA9PT0gXCJldmVuXCIgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKSApO1xuXHRcdFx0XHRtYXRjaFs1XSA9ICsoICggbWF0Y2hbN10gKyBtYXRjaFs4XSApIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICk7XG5cblx0XHRcdH0gZWxzZSBpZiAoIG1hdGNoWzNdICkge1xuXHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBtYXRjaDtcblx0XHR9LFxuXG5cdFx0XCJQU0VVRE9cIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0dmFyIGV4Y2Vzcyxcblx0XHRcdFx0dW5xdW90ZWQgPSAhbWF0Y2hbNV0gJiYgbWF0Y2hbMl07XG5cblx0XHRcdGlmICggbWF0Y2hFeHByW1wiQ0hJTERcIl0udGVzdCggbWF0Y2hbMF0gKSApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggbWF0Y2hbM10gJiYgbWF0Y2hbNF0gIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0bWF0Y2hbMl0gPSBtYXRjaFs0XTtcblxuXHRcdFx0fSBlbHNlIGlmICggdW5xdW90ZWQgJiYgcnBzZXVkby50ZXN0KCB1bnF1b3RlZCApICYmXG5cdFx0XHRcdChleGNlc3MgPSB0b2tlbml6ZSggdW5xdW90ZWQsIHRydWUgKSkgJiZcblx0XHRcdFx0KGV4Y2VzcyA9IHVucXVvdGVkLmluZGV4T2YoIFwiKVwiLCB1bnF1b3RlZC5sZW5ndGggLSBleGNlc3MgKSAtIHVucXVvdGVkLmxlbmd0aCkgKSB7XG5cblx0XHRcdFx0bWF0Y2hbMF0gPSBtYXRjaFswXS5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHRcdG1hdGNoWzJdID0gdW5xdW90ZWQuc2xpY2UoIDAsIGV4Y2VzcyApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbWF0Y2guc2xpY2UoIDAsIDMgKTtcblx0XHR9XG5cdH0sXG5cblx0ZmlsdGVyOiB7XG5cblx0XHRcIlRBR1wiOiBmdW5jdGlvbiggbm9kZU5hbWVTZWxlY3RvciApIHtcblx0XHRcdHZhciBub2RlTmFtZSA9IG5vZGVOYW1lU2VsZWN0b3IucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIG5vZGVOYW1lU2VsZWN0b3IgPT09IFwiKlwiID9cblx0XHRcdFx0ZnVuY3Rpb24oKSB7IHJldHVybiB0cnVlOyB9IDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGVsZW0ubm9kZU5hbWUgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBub2RlTmFtZTtcblx0XHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDTEFTU1wiOiBmdW5jdGlvbiggY2xhc3NOYW1lICkge1xuXHRcdFx0dmFyIHBhdHRlcm4gPSBjbGFzc0NhY2hlWyBjbGFzc05hbWUgKyBcIiBcIiBdO1xuXG5cdFx0XHRyZXR1cm4gcGF0dGVybiB8fFxuXHRcdFx0XHQocGF0dGVybiA9IG5ldyBSZWdFeHAoIFwiKF58XCIgKyB3aGl0ZXNwYWNlICsgXCIpXCIgKyBjbGFzc05hbWUgKyBcIihcIiArIHdoaXRlc3BhY2UgKyBcInwkKVwiICkpICYmXG5cdFx0XHRcdGNsYXNzQ2FjaGUoIGNsYXNzTmFtZSwgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHBhdHRlcm4udGVzdCggdHlwZW9mIGVsZW0uY2xhc3NOYW1lID09PSBcInN0cmluZ1wiICYmIGVsZW0uY2xhc3NOYW1lIHx8IHR5cGVvZiBlbGVtLmdldEF0dHJpYnV0ZSAhPT0gc3RydW5kZWZpbmVkICYmIGVsZW0uZ2V0QXR0cmlidXRlKFwiY2xhc3NcIikgfHwgXCJcIiApO1xuXHRcdFx0XHR9KTtcblx0XHR9LFxuXG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBuYW1lLCBvcGVyYXRvciwgY2hlY2sgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciByZXN1bHQgPSBTaXp6bGUuYXR0ciggZWxlbSwgbmFtZSApO1xuXG5cdFx0XHRcdGlmICggcmVzdWx0ID09IG51bGwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG9wZXJhdG9yID09PSBcIiE9XCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCAhb3BlcmF0b3IgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXN1bHQgKz0gXCJcIjtcblxuXHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiPVwiID8gcmVzdWx0ID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiIT1cIiA/IHJlc3VsdCAhPT0gY2hlY2sgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIl49XCIgPyBjaGVjayAmJiByZXN1bHQuaW5kZXhPZiggY2hlY2sgKSA9PT0gMCA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiKj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID4gLTEgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIiQ9XCIgPyBjaGVjayAmJiByZXN1bHQuc2xpY2UoIC1jaGVjay5sZW5ndGggKSA9PT0gY2hlY2sgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcIn49XCIgPyAoIFwiIFwiICsgcmVzdWx0ICsgXCIgXCIgKS5pbmRleE9mKCBjaGVjayApID4gLTEgOlxuXHRcdFx0XHRcdG9wZXJhdG9yID09PSBcInw9XCIgPyByZXN1bHQgPT09IGNoZWNrIHx8IHJlc3VsdC5zbGljZSggMCwgY2hlY2subGVuZ3RoICsgMSApID09PSBjaGVjayArIFwiLVwiIDpcblx0XHRcdFx0XHRmYWxzZTtcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIHR5cGUsIHdoYXQsIGFyZ3VtZW50LCBmaXJzdCwgbGFzdCApIHtcblx0XHRcdHZhciBzaW1wbGUgPSB0eXBlLnNsaWNlKCAwLCAzICkgIT09IFwibnRoXCIsXG5cdFx0XHRcdGZvcndhcmQgPSB0eXBlLnNsaWNlKCAtNCApICE9PSBcImxhc3RcIixcblx0XHRcdFx0b2ZUeXBlID0gd2hhdCA9PT0gXCJvZi10eXBlXCI7XG5cblx0XHRcdHJldHVybiBmaXJzdCA9PT0gMSAmJiBsYXN0ID09PSAwID9cblxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0XHRyZXR1cm4gISFlbGVtLnBhcmVudE5vZGU7XG5cdFx0XHRcdH0gOlxuXG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0dmFyIGNhY2hlLCBvdXRlckNhY2hlLCBub2RlLCBkaWZmLCBub2RlSW5kZXgsIHN0YXJ0LFxuXHRcdFx0XHRcdFx0ZGlyID0gc2ltcGxlICE9PSBmb3J3YXJkID8gXCJuZXh0U2libGluZ1wiIDogXCJwcmV2aW91c1NpYmxpbmdcIixcblx0XHRcdFx0XHRcdHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZSxcblx0XHRcdFx0XHRcdG5hbWUgPSBvZlR5cGUgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLFxuXHRcdFx0XHRcdFx0dXNlQ2FjaGUgPSAheG1sICYmICFvZlR5cGU7XG5cblx0XHRcdFx0XHRpZiAoIHBhcmVudCApIHtcblxuXHRcdFx0XHRcdFx0aWYgKCBzaW1wbGUgKSB7XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggZGlyICkge1xuXHRcdFx0XHRcdFx0XHRcdG5vZGUgPSBlbGVtO1xuXHRcdFx0XHRcdFx0XHRcdHdoaWxlICggKG5vZGUgPSBub2RlWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoIG9mVHlwZSA/IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZSA6IG5vZGUubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0c3RhcnQgPSBkaXIgPSB0eXBlID09PSBcIm9ubHlcIiAmJiAhc3RhcnQgJiYgXCJuZXh0U2libGluZ1wiO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRzdGFydCA9IFsgZm9yd2FyZCA/IHBhcmVudC5maXJzdENoaWxkIDogcGFyZW50Lmxhc3RDaGlsZCBdO1xuXG5cdFx0XHRcdFx0XHRpZiAoIGZvcndhcmQgJiYgdXNlQ2FjaGUgKSB7XG5cdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBwYXJlbnRbIGV4cGFuZG8gXSB8fCAocGFyZW50WyBleHBhbmRvIF0gPSB7fSk7XG5cdFx0XHRcdFx0XHRcdGNhY2hlID0gb3V0ZXJDYWNoZVsgdHlwZSBdIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVswXSA9PT0gZGlycnVucyAmJiBjYWNoZVsxXTtcblx0XHRcdFx0XHRcdFx0ZGlmZiA9IGNhY2hlWzBdID09PSBkaXJydW5zICYmIGNhY2hlWzJdO1xuXHRcdFx0XHRcdFx0XHRub2RlID0gbm9kZUluZGV4ICYmIHBhcmVudC5jaGlsZE5vZGVzWyBub2RlSW5kZXggXTtcblxuXHRcdFx0XHRcdFx0XHR3aGlsZSAoIChub2RlID0gKytub2RlSW5kZXggJiYgbm9kZSAmJiBub2RlWyBkaXIgXSB8fFxuXG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRpZiAoIG5vZGUubm9kZVR5cGUgPT09IDEgJiYgKytkaWZmICYmIG5vZGUgPT09IGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIG5vZGVJbmRleCwgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHVzZUNhY2hlICYmIChjYWNoZSA9IChlbGVtWyBleHBhbmRvIF0gfHwgKGVsZW1bIGV4cGFuZG8gXSA9IHt9KSlbIHR5cGUgXSkgJiYgY2FjaGVbMF0gPT09IGRpcnJ1bnMgKSB7XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBjYWNoZVsxXTtcblxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdGlmICggKCBvZlR5cGUgPyBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUgOiBub2RlLm5vZGVUeXBlID09PSAxICkgJiYgKytkaWZmICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCB1c2VDYWNoZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0KG5vZGVbIGV4cGFuZG8gXSB8fCAobm9kZVsgZXhwYW5kbyBdID0ge30pKVsgdHlwZSBdID0gWyBkaXJydW5zLCBkaWZmIF07XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGRpZmYgLT0gbGFzdDtcblx0XHRcdFx0XHRcdHJldHVybiBkaWZmID09PSBmaXJzdCB8fCAoIGRpZmYgJSBmaXJzdCA9PT0gMCAmJiBkaWZmIC8gZmlyc3QgPj0gMCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJQU0VVRE9cIjogZnVuY3Rpb24oIHBzZXVkbywgYXJndW1lbnQgKSB7XG5cdFx0XHR2YXIgYXJncyxcblx0XHRcdFx0Zm4gPSBFeHByLnBzZXVkb3NbIHBzZXVkbyBdIHx8IEV4cHIuc2V0RmlsdGVyc1sgcHNldWRvLnRvTG93ZXJDYXNlKCkgXSB8fFxuXHRcdFx0XHRcdFNpenpsZS5lcnJvciggXCJ1bnN1cHBvcnRlZCBwc2V1ZG86IFwiICsgcHNldWRvICk7XG5cblx0XHRcdGlmICggZm5bIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZuKCBhcmd1bWVudCApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGZuLmxlbmd0aCA+IDEgKSB7XG5cdFx0XHRcdGFyZ3MgPSBbIHBzZXVkbywgcHNldWRvLCBcIlwiLCBhcmd1bWVudCBdO1xuXHRcdFx0XHRyZXR1cm4gRXhwci5zZXRGaWx0ZXJzLmhhc093blByb3BlcnR5KCBwc2V1ZG8udG9Mb3dlckNhc2UoKSApID9cblx0XHRcdFx0XHRtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlZWQsIG1hdGNoZXMgKSB7XG5cdFx0XHRcdFx0XHR2YXIgaWR4LFxuXHRcdFx0XHRcdFx0XHRtYXRjaGVkID0gZm4oIHNlZWQsIGFyZ3VtZW50ICksXG5cdFx0XHRcdFx0XHRcdGkgPSBtYXRjaGVkLmxlbmd0aDtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZHggPSBpbmRleE9mLmNhbGwoIHNlZWQsIG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdFx0c2VlZFsgaWR4IF0gPSAhKCBtYXRjaGVzWyBpZHggXSA9IG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZm4oIGVsZW0sIDAsIGFyZ3MgKTtcblx0XHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZm47XG5cdFx0fVxuXHR9LFxuXG5cdHBzZXVkb3M6IHtcblx0XHRcIm5vdFwiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0dmFyIGlucHV0ID0gW10sXG5cdFx0XHRcdHJlc3VsdHMgPSBbXSxcblx0XHRcdFx0bWF0Y2hlciA9IGNvbXBpbGUoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSApO1xuXG5cdFx0XHRyZXR1cm4gbWF0Y2hlclsgZXhwYW5kbyBdID9cblx0XHRcdFx0bWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdFx0XHR1bm1hdGNoZWQgPSBtYXRjaGVyKCBzZWVkLCBudWxsLCB4bWwsIFtdICksXG5cdFx0XHRcdFx0XHRpID0gc2VlZC5sZW5ndGg7XG5cblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGlmICggKGVsZW0gPSB1bm1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRzZWVkW2ldID0gIShtYXRjaGVzW2ldID0gZWxlbSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KSA6XG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRcdFx0aW5wdXRbMF0gPSBlbGVtO1xuXHRcdFx0XHRcdG1hdGNoZXIoIGlucHV0LCBudWxsLCB4bWwsIHJlc3VsdHMgKTtcblx0XHRcdFx0XHRyZXR1cm4gIXJlc3VsdHMucG9wKCk7XG5cdFx0XHRcdH07XG5cdFx0fSksXG5cblx0XHRcImhhc1wiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRyZXR1cm4gU2l6emxlKCBzZWxlY3RvciwgZWxlbSApLmxlbmd0aCA+IDA7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0XCJjb250YWluc1wiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHRleHQgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lclRleHQgfHwgZ2V0VGV4dCggZWxlbSApICkuaW5kZXhPZiggdGV4dCApID4gLTE7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0XCJsYW5nXCI6IG1hcmtGdW5jdGlvbiggZnVuY3Rpb24oIGxhbmcgKSB7XG5cdFx0XHRpZiAoICFyaWRlbnRpZmllci50ZXN0KGxhbmcgfHwgXCJcIikgKSB7XG5cdFx0XHRcdFNpenpsZS5lcnJvciggXCJ1bnN1cHBvcnRlZCBsYW5nOiBcIiArIGxhbmcgKTtcblx0XHRcdH1cblx0XHRcdGxhbmcgPSBsYW5nLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICkudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIGVsZW1MYW5nO1xuXHRcdFx0XHRkbyB7XG5cdFx0XHRcdFx0aWYgKCAoZWxlbUxhbmcgPSBkb2N1bWVudElzSFRNTCA/XG5cdFx0XHRcdFx0XHRlbGVtLmxhbmcgOlxuXHRcdFx0XHRcdFx0ZWxlbS5nZXRBdHRyaWJ1dGUoXCJ4bWw6bGFuZ1wiKSB8fCBlbGVtLmdldEF0dHJpYnV0ZShcImxhbmdcIikpICkge1xuXG5cdFx0XHRcdFx0XHRlbGVtTGFuZyA9IGVsZW1MYW5nLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbUxhbmcgPT09IGxhbmcgfHwgZWxlbUxhbmcuaW5kZXhPZiggbGFuZyArIFwiLVwiICkgPT09IDA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IHdoaWxlICggKGVsZW0gPSBlbGVtLnBhcmVudE5vZGUpICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwidGFyZ2V0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGhhc2ggPSB3aW5kb3cubG9jYXRpb24gJiYgd2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0XHRyZXR1cm4gaGFzaCAmJiBoYXNoLnNsaWNlKCAxICkgPT09IGVsZW0uaWQ7XG5cdFx0fSxcblxuXHRcdFwicm9vdFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBkb2NFbGVtO1xuXHRcdH0sXG5cblx0XHRcImZvY3VzXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKCFkb2N1bWVudC5oYXNGb2N1cyB8fCBkb2N1bWVudC5oYXNGb2N1cygpKSAmJiAhIShlbGVtLnR5cGUgfHwgZWxlbS5ocmVmIHx8IH5lbGVtLnRhYkluZGV4KTtcblx0XHR9LFxuXG5cdFx0XCJlbmFibGVkXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGZhbHNlO1xuXHRcdH0sXG5cblx0XHRcImRpc2FibGVkXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IHRydWU7XG5cdFx0fSxcblxuXHRcdFwiY2hlY2tlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHZhciBub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiAobm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiAhIWVsZW0uY2hlY2tlZCkgfHwgKG5vZGVOYW1lID09PSBcIm9wdGlvblwiICYmICEhZWxlbS5zZWxlY3RlZCk7XG5cdFx0fSxcblxuXHRcdFwic2VsZWN0ZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBlbGVtLnNlbGVjdGVkID09PSB0cnVlO1xuXHRcdH0sXG5cblx0XHRcImVtcHR5XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0Zm9yICggZWxlbSA9IGVsZW0uZmlyc3RDaGlsZDsgZWxlbTsgZWxlbSA9IGVsZW0ubmV4dFNpYmxpbmcgKSB7XG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA8IDYgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9LFxuXG5cdFx0XCJwYXJlbnRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gIUV4cHIucHNldWRvc1tcImVtcHR5XCJdKCBlbGVtICk7XG5cdFx0fSxcblxuXHRcdFwiaGVhZGVyXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIHJoZWFkZXIudGVzdCggZWxlbS5ub2RlTmFtZSApO1xuXHRcdH0sXG5cblx0XHRcImlucHV0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIHJpbnB1dHMudGVzdCggZWxlbS5ub2RlTmFtZSApO1xuXHRcdH0sXG5cblx0XHRcImJ1dHRvblwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIG5hbWUgPT09IFwiaW5wdXRcIiAmJiBlbGVtLnR5cGUgPT09IFwiYnV0dG9uXCIgfHwgbmFtZSA9PT0gXCJidXR0b25cIjtcblx0XHR9LFxuXG5cdFx0XCJ0ZXh0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGF0dHI7XG5cdFx0XHRyZXR1cm4gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlucHV0XCIgJiZcblx0XHRcdFx0ZWxlbS50eXBlID09PSBcInRleHRcIiAmJlxuXG5cdFx0XHRcdCggKGF0dHIgPSBlbGVtLmdldEF0dHJpYnV0ZShcInR5cGVcIikpID09IG51bGwgfHwgYXR0ci50b0xvd2VyQ2FzZSgpID09PSBcInRleHRcIiApO1xuXHRcdH0sXG5cblx0XHRcImZpcnN0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gWyAwIF07XG5cdFx0fSksXG5cblx0XHRcImxhc3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4gWyBsZW5ndGggLSAxIF07XG5cdFx0fSksXG5cblx0XHRcImVxXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHJldHVybiBbIGFyZ3VtZW50IDwgMCA/IGFyZ3VtZW50ICsgbGVuZ3RoIDogYXJndW1lbnQgXTtcblx0XHR9KSxcblxuXHRcdFwiZXZlblwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHZhciBpID0gMDtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSArPSAyICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwib2RkXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0dmFyIGkgPSAxO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpICs9IDIgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJsdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCwgYXJndW1lbnQgKSB7XG5cdFx0XHR2YXIgaSA9IGFyZ3VtZW50IDwgMCA/IGFyZ3VtZW50ICsgbGVuZ3RoIDogYXJndW1lbnQ7XG5cdFx0XHRmb3IgKCA7IC0taSA+PSAwOyApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcImd0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHZhciBpID0gYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudDtcblx0XHRcdGZvciAoIDsgKytpIDwgbGVuZ3RoOyApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSlcblx0fVxufTtcblxuRXhwci5wc2V1ZG9zW1wibnRoXCJdID0gRXhwci5wc2V1ZG9zW1wiZXFcIl07XG5cbmZvciAoIGkgaW4geyByYWRpbzogdHJ1ZSwgY2hlY2tib3g6IHRydWUsIGZpbGU6IHRydWUsIHBhc3N3b3JkOiB0cnVlLCBpbWFnZTogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUlucHV0UHNldWRvKCBpICk7XG59XG5mb3IgKCBpIGluIHsgc3VibWl0OiB0cnVlLCByZXNldDogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUJ1dHRvblBzZXVkbyggaSApO1xufVxuXG5mdW5jdGlvbiBzZXRGaWx0ZXJzKCkge31cbnNldEZpbHRlcnMucHJvdG90eXBlID0gRXhwci5maWx0ZXJzID0gRXhwci5wc2V1ZG9zO1xuRXhwci5zZXRGaWx0ZXJzID0gbmV3IHNldEZpbHRlcnMoKTtcblxuZnVuY3Rpb24gdG9rZW5pemUoIHNlbGVjdG9yLCBwYXJzZU9ubHkgKSB7XG5cdHZhciBtYXRjaGVkLCBtYXRjaCwgdG9rZW5zLCB0eXBlLFxuXHRcdHNvRmFyLCBncm91cHMsIHByZUZpbHRlcnMsXG5cdFx0Y2FjaGVkID0gdG9rZW5DYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggY2FjaGVkICkge1xuXHRcdHJldHVybiBwYXJzZU9ubHkgPyAwIDogY2FjaGVkLnNsaWNlKCAwICk7XG5cdH1cblxuXHRzb0ZhciA9IHNlbGVjdG9yO1xuXHRncm91cHMgPSBbXTtcblx0cHJlRmlsdGVycyA9IEV4cHIucHJlRmlsdGVyO1xuXG5cdHdoaWxlICggc29GYXIgKSB7XG5cblx0XHRpZiAoICFtYXRjaGVkIHx8IChtYXRjaCA9IHJjb21tYS5leGVjKCBzb0ZhciApKSApIHtcblx0XHRcdGlmICggbWF0Y2ggKSB7XG5cdFx0XHRcdHNvRmFyID0gc29GYXIuc2xpY2UoIG1hdGNoWzBdLmxlbmd0aCApIHx8IHNvRmFyO1xuXHRcdFx0fVxuXHRcdFx0Z3JvdXBzLnB1c2goICh0b2tlbnMgPSBbXSkgKTtcblx0XHR9XG5cblx0XHRtYXRjaGVkID0gZmFsc2U7XG5cblx0XHRpZiAoIChtYXRjaCA9IHJjb21iaW5hdG9ycy5leGVjKCBzb0ZhciApKSApIHtcblx0XHRcdG1hdGNoZWQgPSBtYXRjaC5zaGlmdCgpO1xuXHRcdFx0dG9rZW5zLnB1c2goe1xuXHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0dHlwZTogbWF0Y2hbMF0ucmVwbGFjZSggcnRyaW0sIFwiIFwiIClcblx0XHRcdH0pO1xuXHRcdFx0c29GYXIgPSBzb0Zhci5zbGljZSggbWF0Y2hlZC5sZW5ndGggKTtcblx0XHR9XG5cblx0XHRmb3IgKCB0eXBlIGluIEV4cHIuZmlsdGVyICkge1xuXHRcdFx0aWYgKCAobWF0Y2ggPSBtYXRjaEV4cHJbIHR5cGUgXS5leGVjKCBzb0ZhciApKSAmJiAoIXByZUZpbHRlcnNbIHR5cGUgXSB8fFxuXHRcdFx0XHQobWF0Y2ggPSBwcmVGaWx0ZXJzWyB0eXBlIF0oIG1hdGNoICkpKSApIHtcblx0XHRcdFx0bWF0Y2hlZCA9IG1hdGNoLnNoaWZ0KCk7XG5cdFx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRcdG1hdGNoZXM6IG1hdGNoXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIW1hdGNoZWQgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gcGFyc2VPbmx5ID9cblx0XHRzb0Zhci5sZW5ndGggOlxuXHRcdHNvRmFyID9cblx0XHRcdFNpenpsZS5lcnJvciggc2VsZWN0b3IgKSA6XG5cdFx0XHR0b2tlbkNhY2hlKCBzZWxlY3RvciwgZ3JvdXBzICkuc2xpY2UoIDAgKTtcbn1cblxuZnVuY3Rpb24gdG9TZWxlY3RvciggdG9rZW5zICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRzZWxlY3RvciA9IFwiXCI7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdHNlbGVjdG9yICs9IHRva2Vuc1tpXS52YWx1ZTtcblx0fVxuXHRyZXR1cm4gc2VsZWN0b3I7XG59XG5cbmZ1bmN0aW9uIGFkZENvbWJpbmF0b3IoIG1hdGNoZXIsIGNvbWJpbmF0b3IsIGJhc2UgKSB7XG5cdHZhciBkaXIgPSBjb21iaW5hdG9yLmRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBkaXIgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCBvdXRlckNhY2hlLFxuXHRcdFx0XHRuZXdDYWNoZSA9IFsgZGlycnVucywgZG9uZU5hbWUgXTtcblxuXHRcdFx0aWYgKCB4bWwgKSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSk7XG5cdFx0XHRcdFx0XHRpZiAoIChvbGRDYWNoZSA9IG91dGVyQ2FjaGVbIGRpciBdKSAmJlxuXHRcdFx0XHRcdFx0XHRvbGRDYWNoZVsgMCBdID09PSBkaXJydW5zICYmIG9sZENhY2hlWyAxIF0gPT09IGRvbmVOYW1lICkge1xuXG5cdFx0XHRcdFx0XHRcdHJldHVybiAobmV3Q2FjaGVbIDIgXSA9IG9sZENhY2hlWyAyIF0pO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0b3V0ZXJDYWNoZVsgZGlyIF0gPSBuZXdDYWNoZTtcblxuXHRcdFx0XHRcdFx0XHRpZiAoIChuZXdDYWNoZVsgMiBdID0gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkpICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fTtcbn1cblxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICkge1xuXHRyZXR1cm4gbWF0Y2hlcnMubGVuZ3RoID4gMSA/XG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciBpID0gbWF0Y2hlcnMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggIW1hdGNoZXJzW2ldKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gOlxuXHRcdG1hdGNoZXJzWzBdO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciwgY29udGV4dHMsIHJlc3VsdHMgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBjb250ZXh0cy5sZW5ndGg7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHRzW2ldLCByZXN1bHRzICk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdHM7XG59XG5cbmZ1bmN0aW9uIGNvbmRlbnNlKCB1bm1hdGNoZWQsIG1hcCwgZmlsdGVyLCBjb250ZXh0LCB4bWwgKSB7XG5cdHZhciBlbGVtLFxuXHRcdG5ld1VubWF0Y2hlZCA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGxlbiA9IHVubWF0Y2hlZC5sZW5ndGgsXG5cdFx0bWFwcGVkID0gbWFwICE9IG51bGw7XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRpZiAoICFmaWx0ZXIgfHwgZmlsdGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0bmV3VW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0aWYgKCBtYXBwZWQgKSB7XG5cdFx0XHRcdFx0bWFwLnB1c2goIGkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBuZXdVbm1hdGNoZWQ7XG59XG5cbmZ1bmN0aW9uIHNldE1hdGNoZXIoIHByZUZpbHRlciwgc2VsZWN0b3IsIG1hdGNoZXIsIHBvc3RGaWx0ZXIsIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApIHtcblx0aWYgKCBwb3N0RmlsdGVyICYmICFwb3N0RmlsdGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbHRlciA9IHNldE1hdGNoZXIoIHBvc3RGaWx0ZXIgKTtcblx0fVxuXHRpZiAoIHBvc3RGaW5kZXIgJiYgIXBvc3RGaW5kZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmluZGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICk7XG5cdH1cblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgcmVzdWx0cywgY29udGV4dCwgeG1sICkge1xuXHRcdHZhciB0ZW1wLCBpLCBlbGVtLFxuXHRcdFx0cHJlTWFwID0gW10sXG5cdFx0XHRwb3N0TWFwID0gW10sXG5cdFx0XHRwcmVleGlzdGluZyA9IHJlc3VsdHMubGVuZ3RoLFxuXG5cdFx0XHRlbGVtcyA9IHNlZWQgfHwgbXVsdGlwbGVDb250ZXh0cyggc2VsZWN0b3IgfHwgXCIqXCIsIGNvbnRleHQubm9kZVR5cGUgPyBbIGNvbnRleHQgXSA6IGNvbnRleHQsIFtdICksXG5cblx0XHRcdG1hdGNoZXJJbiA9IHByZUZpbHRlciAmJiAoIHNlZWQgfHwgIXNlbGVjdG9yICkgP1xuXHRcdFx0XHRjb25kZW5zZSggZWxlbXMsIHByZU1hcCwgcHJlRmlsdGVyLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdGVsZW1zLFxuXG5cdFx0XHRtYXRjaGVyT3V0ID0gbWF0Y2hlciA/XG5cdFx0XHRcdHBvc3RGaW5kZXIgfHwgKCBzZWVkID8gcHJlRmlsdGVyIDogcHJlZXhpc3RpbmcgfHwgcG9zdEZpbHRlciApID9cblxuXHRcdFx0XHRcdFtdIDpcblxuXHRcdFx0XHRcdHJlc3VsdHMgOlxuXHRcdFx0XHRtYXRjaGVySW47XG5cblx0XHRpZiAoIG1hdGNoZXIgKSB7XG5cdFx0XHRtYXRjaGVyKCBtYXRjaGVySW4sIG1hdGNoZXJPdXQsIGNvbnRleHQsIHhtbCApO1xuXHRcdH1cblxuXHRcdGlmICggcG9zdEZpbHRlciApIHtcblx0XHRcdHRlbXAgPSBjb25kZW5zZSggbWF0Y2hlck91dCwgcG9zdE1hcCApO1xuXHRcdFx0cG9zdEZpbHRlciggdGVtcCwgW10sIGNvbnRleHQsIHhtbCApO1xuXG5cdFx0XHRpID0gdGVtcC5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAoZWxlbSA9IHRlbXBbaV0pICkge1xuXHRcdFx0XHRcdG1hdGNoZXJPdXRbIHBvc3RNYXBbaV0gXSA9ICEobWF0Y2hlckluWyBwb3N0TWFwW2ldIF0gPSBlbGVtKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggc2VlZCApIHtcblx0XHRcdGlmICggcG9zdEZpbmRlciB8fCBwcmVGaWx0ZXIgKSB7XG5cdFx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0XHR0ZW1wID0gW107XG5cdFx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHR0ZW1wLnB1c2goIChtYXRjaGVySW5baV0gPSBlbGVtKSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCAobWF0Y2hlck91dCA9IFtdKSwgdGVtcCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSAmJlxuXHRcdFx0XHRcdFx0KHRlbXAgPSBwb3N0RmluZGVyID8gaW5kZXhPZi5jYWxsKCBzZWVkLCBlbGVtICkgOiBwcmVNYXBbaV0pID4gLTEgKSB7XG5cblx0XHRcdFx0XHRcdHNlZWRbdGVtcF0gPSAhKHJlc3VsdHNbdGVtcF0gPSBlbGVtKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXRjaGVyT3V0ID0gY29uZGVuc2UoXG5cdFx0XHRcdG1hdGNoZXJPdXQgPT09IHJlc3VsdHMgP1xuXHRcdFx0XHRcdG1hdGNoZXJPdXQuc3BsaWNlKCBwcmVleGlzdGluZywgbWF0Y2hlck91dC5sZW5ndGggKSA6XG5cdFx0XHRcdFx0bWF0Y2hlck91dFxuXHRcdFx0KTtcblx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0cG9zdEZpbmRlciggbnVsbCwgcmVzdWx0cywgbWF0Y2hlck91dCwgeG1sICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBtYXRjaGVyT3V0ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9KTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hlckZyb21Ub2tlbnMoIHRva2VucyApIHtcblx0dmFyIGNoZWNrQ29udGV4dCwgbWF0Y2hlciwgaixcblx0XHRsZW4gPSB0b2tlbnMubGVuZ3RoLFxuXHRcdGxlYWRpbmdSZWxhdGl2ZSA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1swXS50eXBlIF0sXG5cdFx0aW1wbGljaXRSZWxhdGl2ZSA9IGxlYWRpbmdSZWxhdGl2ZSB8fCBFeHByLnJlbGF0aXZlW1wiIFwiXSxcblx0XHRpID0gbGVhZGluZ1JlbGF0aXZlID8gMSA6IDAsXG5cblx0XHRtYXRjaENvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBjaGVja0NvbnRleHQ7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoQW55Q29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggY2hlY2tDb250ZXh0LCBlbGVtICkgPiAtMTtcblx0XHR9LCBpbXBsaWNpdFJlbGF0aXZlLCB0cnVlICksXG5cdFx0bWF0Y2hlcnMgPSBbIGZ1bmN0aW9uKCBlbGVtLCBjb250ZXh0LCB4bWwgKSB7XG5cdFx0XHRyZXR1cm4gKCAhbGVhZGluZ1JlbGF0aXZlICYmICggeG1sIHx8IGNvbnRleHQgIT09IG91dGVybW9zdENvbnRleHQgKSApIHx8IChcblx0XHRcdFx0KGNoZWNrQ29udGV4dCA9IGNvbnRleHQpLm5vZGVUeXBlID9cblx0XHRcdFx0XHRtYXRjaENvbnRleHQoIGVsZW0sIGNvbnRleHQsIHhtbCApIDpcblx0XHRcdFx0XHRtYXRjaEFueUNvbnRleHQoIGVsZW0sIGNvbnRleHQsIHhtbCApICk7XG5cdFx0fSBdO1xuXG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdGlmICggKG1hdGNoZXIgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbaV0udHlwZSBdKSApIHtcblx0XHRcdG1hdGNoZXJzID0gWyBhZGRDb21iaW5hdG9yKGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLCBtYXRjaGVyKSBdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXRjaGVyID0gRXhwci5maWx0ZXJbIHRva2Vuc1tpXS50eXBlIF0uYXBwbHkoIG51bGwsIHRva2Vuc1tpXS5tYXRjaGVzICk7XG5cblx0XHRcdGlmICggbWF0Y2hlclsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHRqID0gKytpO1xuXHRcdFx0XHRmb3IgKCA7IGogPCBsZW47IGorKyApIHtcblx0XHRcdFx0XHRpZiAoIEV4cHIucmVsYXRpdmVbIHRva2Vuc1tqXS50eXBlIF0gKSB7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHNldE1hdGNoZXIoXG5cdFx0XHRcdFx0aSA+IDEgJiYgZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksXG5cdFx0XHRcdFx0aSA+IDEgJiYgdG9TZWxlY3Rvcihcblx0XHRcdFx0XHRcdHRva2Vucy5zbGljZSggMCwgaSAtIDEgKS5jb25jYXQoeyB2YWx1ZTogdG9rZW5zWyBpIC0gMiBdLnR5cGUgPT09IFwiIFwiID8gXCIqXCIgOiBcIlwiIH0pXG5cdFx0XHRcdFx0KS5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICksXG5cdFx0XHRcdFx0bWF0Y2hlcixcblx0XHRcdFx0XHRpIDwgaiAmJiBtYXRjaGVyRnJvbVRva2VucyggdG9rZW5zLnNsaWNlKCBpLCBqICkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIG1hdGNoZXJGcm9tVG9rZW5zKCAodG9rZW5zID0gdG9rZW5zLnNsaWNlKCBqICkpICksXG5cdFx0XHRcdFx0aiA8IGxlbiAmJiB0b1NlbGVjdG9yKCB0b2tlbnMgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdFx0bWF0Y2hlcnMucHVzaCggbWF0Y2hlciApO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50TWF0Y2hlciggbWF0Y2hlcnMgKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hlckZyb21Hcm91cE1hdGNoZXJzKCBlbGVtZW50TWF0Y2hlcnMsIHNldE1hdGNoZXJzICkge1xuXHR2YXIgYnlTZXQgPSBzZXRNYXRjaGVycy5sZW5ndGggPiAwLFxuXHRcdGJ5RWxlbWVudCA9IGVsZW1lbnRNYXRjaGVycy5sZW5ndGggPiAwLFxuXHRcdHN1cGVyTWF0Y2hlciA9IGZ1bmN0aW9uKCBzZWVkLCBjb250ZXh0LCB4bWwsIHJlc3VsdHMsIG91dGVybW9zdCApIHtcblx0XHRcdHZhciBlbGVtLCBqLCBtYXRjaGVyLFxuXHRcdFx0XHRtYXRjaGVkQ291bnQgPSAwLFxuXHRcdFx0XHRpID0gXCIwXCIsXG5cdFx0XHRcdHVubWF0Y2hlZCA9IHNlZWQgJiYgW10sXG5cdFx0XHRcdHNldE1hdGNoZWQgPSBbXSxcblx0XHRcdFx0Y29udGV4dEJhY2t1cCA9IG91dGVybW9zdENvbnRleHQsXG5cdFx0XHRcdGVsZW1zID0gc2VlZCB8fCBieUVsZW1lbnQgJiYgRXhwci5maW5kW1wiVEFHXCJdKCBcIipcIiwgb3V0ZXJtb3N0ICksXG5cdFx0XHRcdGRpcnJ1bnNVbmlxdWUgPSAoZGlycnVucyArPSBjb250ZXh0QmFja3VwID09IG51bGwgPyAxIDogTWF0aC5yYW5kb20oKSB8fCAwLjEpLFxuXHRcdFx0XHRsZW4gPSBlbGVtcy5sZW5ndGg7XG5cblx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRvdXRlcm1vc3RDb250ZXh0ID0gY29udGV4dCAhPT0gZG9jdW1lbnQgJiYgY29udGV4dDtcblx0XHRcdH1cblxuXHRcdFx0Zm9yICggOyBpICE9PSBsZW4gJiYgKGVsZW0gPSBlbGVtc1tpXSkgIT0gbnVsbDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGJ5RWxlbWVudCAmJiBlbGVtICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKG1hdGNoZXIgPSBlbGVtZW50TWF0Y2hlcnNbaisrXSkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCBieVNldCApIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0XHR1bm1hdGNoZWQucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRtYXRjaGVkQ291bnQgKz0gaTtcblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0aWYgKCBtYXRjaGVkQ291bnQgPiAwICkge1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggISh1bm1hdGNoZWRbaV0gfHwgc2V0TWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0c2V0TWF0Y2hlZFtpXSA9IHBvcC5jYWxsKCByZXN1bHRzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsIHNldE1hdGNoZWQgKTtcblxuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKCBvdXRlcm1vc3QgKSB7XG5cdFx0XHRcdGRpcnJ1bnMgPSBkaXJydW5zVW5pcXVlO1xuXHRcdFx0XHRvdXRlcm1vc3RDb250ZXh0ID0gY29udGV4dEJhY2t1cDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHVubWF0Y2hlZDtcblx0XHR9O1xuXG5cdHJldHVybiBieVNldCA/XG5cdFx0bWFya0Z1bmN0aW9uKCBzdXBlck1hdGNoZXIgKSA6XG5cdFx0c3VwZXJNYXRjaGVyO1xufVxuXG5jb21waWxlID0gU2l6emxlLmNvbXBpbGUgPSBmdW5jdGlvbiggc2VsZWN0b3IsIG1hdGNoIC8qIEludGVybmFsIFVzZSBPbmx5ICovICkge1xuXHR2YXIgaSxcblx0XHRzZXRNYXRjaGVycyA9IFtdLFxuXHRcdGVsZW1lbnRNYXRjaGVycyA9IFtdLFxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXTtcblxuXHRpZiAoICFjYWNoZWQgKSB7XG5cdFx0aWYgKCAhbWF0Y2ggKSB7XG5cdFx0XHRtYXRjaCA9IHRva2VuaXplKCBzZWxlY3RvciApO1xuXHRcdH1cblx0XHRpID0gbWF0Y2gubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0Y2FjaGVkID0gbWF0Y2hlckZyb21Ub2tlbnMoIG1hdGNoW2ldICk7XG5cdFx0XHRpZiAoIGNhY2hlZFsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHRzZXRNYXRjaGVycy5wdXNoKCBjYWNoZWQgKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVsZW1lbnRNYXRjaGVycy5wdXNoKCBjYWNoZWQgKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRjYWNoZWQgPSBjb21waWxlckNhY2hlKCBzZWxlY3RvciwgbWF0Y2hlckZyb21Hcm91cE1hdGNoZXJzKCBlbGVtZW50TWF0Y2hlcnMsIHNldE1hdGNoZXJzICkgKTtcblxuXHRcdGNhY2hlZC5zZWxlY3RvciA9IHNlbGVjdG9yO1xuXHR9XG5cdHJldHVybiBjYWNoZWQ7XG59O1xuXG4vKipcbiAqIEEgbG93LWxldmVsIHNlbGVjdGlvbiBmdW5jdGlvbiB0aGF0IHdvcmtzIHdpdGggU2l6emxlJ3MgY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfEZ1bmN0aW9ufSBzZWxlY3RvciBBIHNlbGVjdG9yIG9yIGEgcHJlLWNvbXBpbGVkXG4gKiAgc2VsZWN0b3IgZnVuY3Rpb24gYnVpbHQgd2l0aCBTaXp6bGUuY29tcGlsZVxuICogQHBhcmFtIHtFbGVtZW50fSBjb250ZXh0XG4gKiBAcGFyYW0ge0FycmF5fSBbcmVzdWx0c11cbiAqIEBwYXJhbSB7QXJyYXl9IFtzZWVkXSBBIHNldCBvZiBlbGVtZW50cyB0byBtYXRjaCBhZ2FpbnN0XG4gKi9cbnNlbGVjdCA9IFNpenpsZS5zZWxlY3QgPSBmdW5jdGlvbiggc2VsZWN0b3IsIGNvbnRleHQsIHJlc3VsdHMsIHNlZWQgKSB7XG5cdHZhciBpLCB0b2tlbnMsIHRva2VuLCB0eXBlLCBmaW5kLFxuXHRcdGNvbXBpbGVkID0gdHlwZW9mIHNlbGVjdG9yID09PSBcImZ1bmN0aW9uXCIgJiYgc2VsZWN0b3IsXG5cdFx0bWF0Y2ggPSAhc2VlZCAmJiB0b2tlbml6ZSggKHNlbGVjdG9yID0gY29tcGlsZWQuc2VsZWN0b3IgfHwgc2VsZWN0b3IpICk7XG5cblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0aWYgKCBtYXRjaC5sZW5ndGggPT09IDEgKSB7XG5cblx0XHR0b2tlbnMgPSBtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwICk7XG5cdFx0aWYgKCB0b2tlbnMubGVuZ3RoID4gMiAmJiAodG9rZW4gPSB0b2tlbnNbMF0pLnR5cGUgPT09IFwiSURcIiAmJlxuXHRcdFx0XHRzdXBwb3J0LmdldEJ5SWQgJiYgY29udGV4dC5ub2RlVHlwZSA9PT0gOSAmJiBkb2N1bWVudElzSFRNTCAmJlxuXHRcdFx0XHRFeHByLnJlbGF0aXZlWyB0b2tlbnNbMV0udHlwZSBdICkge1xuXG5cdFx0XHRjb250ZXh0ID0gKCBFeHByLmZpbmRbXCJJRFwiXSggdG9rZW4ubWF0Y2hlc1swXS5yZXBsYWNlKHJ1bmVzY2FwZSwgZnVuZXNjYXBlKSwgY29udGV4dCApIHx8IFtdIClbMF07XG5cdFx0XHRpZiAoICFjb250ZXh0ICkge1xuXHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblxuXHRcdFx0fSBlbHNlIGlmICggY29tcGlsZWQgKSB7XG5cdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0LnBhcmVudE5vZGU7XG5cdFx0XHR9XG5cblx0XHRcdHNlbGVjdG9yID0gc2VsZWN0b3Iuc2xpY2UoIHRva2Vucy5zaGlmdCgpLnZhbHVlLmxlbmd0aCApO1xuXHRcdH1cblxuXHRcdGkgPSBtYXRjaEV4cHJbXCJuZWVkc0NvbnRleHRcIl0udGVzdCggc2VsZWN0b3IgKSA/IDAgOiB0b2tlbnMubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG9rZW4gPSB0b2tlbnNbaV07XG5cblx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgKHR5cGUgPSB0b2tlbi50eXBlKSBdICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggKGZpbmQgPSBFeHByLmZpbmRbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdGlmICggKHNlZWQgPSBmaW5kKFxuXHRcdFx0XHRcdHRva2VuLm1hdGNoZXNbMF0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKSxcblx0XHRcdFx0XHRyc2libGluZy50ZXN0KCB0b2tlbnNbMF0udHlwZSApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fCBjb250ZXh0XG5cdFx0XHRcdCkpICkge1xuXG5cdFx0XHRcdFx0dG9rZW5zLnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdHNlbGVjdG9yID0gc2VlZC5sZW5ndGggJiYgdG9TZWxlY3RvciggdG9rZW5zICk7XG5cdFx0XHRcdFx0aWYgKCAhc2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBzZWVkICk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdCggY29tcGlsZWQgfHwgY29tcGlsZSggc2VsZWN0b3IsIG1hdGNoICkgKShcblx0XHRzZWVkLFxuXHRcdGNvbnRleHQsXG5cdFx0IWRvY3VtZW50SXNIVE1MLFxuXHRcdHJlc3VsdHMsXG5cdFx0cnNpYmxpbmcudGVzdCggc2VsZWN0b3IgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHQpO1xuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cblxuc3VwcG9ydC5zb3J0U3RhYmxlID0gZXhwYW5kby5zcGxpdChcIlwiKS5zb3J0KCBzb3J0T3JkZXIgKS5qb2luKFwiXCIpID09PSBleHBhbmRvO1xuXG5zdXBwb3J0LmRldGVjdER1cGxpY2F0ZXMgPSAhIWhhc0R1cGxpY2F0ZTtcblxuc2V0RG9jdW1lbnQoKTtcblxuc3VwcG9ydC5zb3J0RGV0YWNoZWQgPSBhc3NlcnQoZnVuY3Rpb24oIGRpdjEgKSB7XG5cdHJldHVybiBkaXYxLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpICkgJiAxO1xufSk7XG5cbmlmICggIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRkaXYuaW5uZXJIVE1MID0gXCI8YSBocmVmPScjJz48L2E+XCI7XG5cdHJldHVybiBkaXYuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRkaXYuaW5uZXJIVE1MID0gXCI8aW5wdXQvPlwiO1xuXHRkaXYuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZGl2LmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gXCJcIjtcbn0pICkge1xuXHRhZGRIYW5kbGUoIFwidmFsdWVcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpbnB1dFwiICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGVmYXVsdFZhbHVlO1xuXHRcdH1cblx0fSk7XG59XG5cbmlmICggIWFzc2VydChmdW5jdGlvbiggZGl2ICkge1xuXHRyZXR1cm4gZGl2LmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKGZ1bmN0aW9uKCkgeyByZXR1cm4gU2l6emxlOyB9KTtcbn0gZWxzZSBpZiAoIHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG5cdG1vZHVsZS5leHBvcnRzID0gU2l6emxlO1xufSBlbHNlIHtcblx0d2luZG93LlNpenpsZSA9IFNpenpsZTtcbn1cblxufSkoIHdpbmRvdyApO1xuXG47KGZ1bmN0aW9uKGVuZ2luZSkge1xuICB2YXIgZXh0ZW5kRWxlbWVudHMgPSBQcm90b3R5cGUuU2VsZWN0b3IuZXh0ZW5kRWxlbWVudHM7XG5cbiAgZnVuY3Rpb24gc2VsZWN0KHNlbGVjdG9yLCBzY29wZSkge1xuICAgIHJldHVybiBleHRlbmRFbGVtZW50cyhlbmdpbmUoc2VsZWN0b3IsIHNjb3BlIHx8IGRvY3VtZW50KSk7XG4gIH1cblxuICBmdW5jdGlvbiBtYXRjaChlbGVtZW50LCBzZWxlY3Rvcikge1xuICAgIHJldHVybiBlbmdpbmUubWF0Y2hlcyhzZWxlY3RvciwgW2VsZW1lbnRdKS5sZW5ndGggPT0gMTtcbiAgfVxuXG4gIFByb3RvdHlwZS5TZWxlY3Rvci5lbmdpbmUgPSBlbmdpbmU7XG4gIFByb3RvdHlwZS5TZWxlY3Rvci5zZWxlY3QgPSBzZWxlY3Q7XG4gIFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaCA9IG1hdGNoO1xufSkoU2l6emxlKTtcblxud2luZG93LlNpenpsZSA9IFByb3RvdHlwZS5fb3JpZ2luYWxfcHJvcGVydHk7XG5kZWxldGUgUHJvdG90eXBlLl9vcmlnaW5hbF9wcm9wZXJ0eTtcblxudmFyIEZvcm0gPSB7XG4gIHJlc2V0OiBmdW5jdGlvbihmb3JtKSB7XG4gICAgZm9ybSA9ICQoZm9ybSk7XG4gICAgZm9ybS5yZXNldCgpO1xuICAgIHJldHVybiBmb3JtO1xuICB9LFxuXG4gIHNlcmlhbGl6ZUVsZW1lbnRzOiBmdW5jdGlvbihlbGVtZW50cywgb3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucyAhPSAnb2JqZWN0Jykgb3B0aW9ucyA9IHsgaGFzaDogISFvcHRpb25zIH07XG4gICAgZWxzZSBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKG9wdGlvbnMuaGFzaCkpIG9wdGlvbnMuaGFzaCA9IHRydWU7XG4gICAgdmFyIGtleSwgdmFsdWUsIHN1Ym1pdHRlZCA9IGZhbHNlLCBzdWJtaXQgPSBvcHRpb25zLnN1Ym1pdCwgYWNjdW11bGF0b3IsIGluaXRpYWw7XG5cbiAgICBpZiAob3B0aW9ucy5oYXNoKSB7XG4gICAgICBpbml0aWFsID0ge307XG4gICAgICBhY2N1bXVsYXRvciA9IGZ1bmN0aW9uKHJlc3VsdCwga2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAoa2V5IGluIHJlc3VsdCkge1xuICAgICAgICAgIGlmICghT2JqZWN0LmlzQXJyYXkocmVzdWx0W2tleV0pKSByZXN1bHRba2V5XSA9IFtyZXN1bHRba2V5XV07XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSByZXN1bHRba2V5XS5jb25jYXQodmFsdWUpO1xuICAgICAgICB9IGVsc2UgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGluaXRpYWwgPSAnJztcbiAgICAgIGFjY3VtdWxhdG9yID0gZnVuY3Rpb24ocmVzdWx0LCBrZXksIHZhbHVlcykge1xuICAgICAgICBpZiAoIU9iamVjdC5pc0FycmF5KHZhbHVlcykpIHt2YWx1ZXMgPSBbdmFsdWVzXTt9XG4gICAgICAgIGlmICghdmFsdWVzLmxlbmd0aCkge3JldHVybiByZXN1bHQ7fVxuICAgICAgICB2YXIgZW5jb2RlZEtleSA9IGVuY29kZVVSSUNvbXBvbmVudChrZXkpLmdzdWIoLyUyMC8sICcrJyk7XG4gICAgICAgIHJldHVybiByZXN1bHQgKyAocmVzdWx0ID8gXCImXCIgOiBcIlwiKSArIHZhbHVlcy5tYXAoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgdmFsdWUgPSB2YWx1ZS5nc3ViKC8oXFxyKT9cXG4vLCAnXFxyXFxuJyk7XG4gICAgICAgICAgdmFsdWUgPSBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgICAgICAgIHZhbHVlID0gdmFsdWUuZ3N1YigvJTIwLywgJysnKTtcbiAgICAgICAgICByZXR1cm4gZW5jb2RlZEtleSArIFwiPVwiICsgdmFsdWU7XG4gICAgICAgIH0pLmpvaW4oXCImXCIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZWxlbWVudHMuaW5qZWN0KGluaXRpYWwsIGZ1bmN0aW9uKHJlc3VsdCwgZWxlbWVudCkge1xuICAgICAgaWYgKCFlbGVtZW50LmRpc2FibGVkICYmIGVsZW1lbnQubmFtZSkge1xuICAgICAgICBrZXkgPSBlbGVtZW50Lm5hbWU7IHZhbHVlID0gJChlbGVtZW50KS5nZXRWYWx1ZSgpO1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCAmJiBlbGVtZW50LnR5cGUgIT0gJ2ZpbGUnICYmIChlbGVtZW50LnR5cGUgIT0gJ3N1Ym1pdCcgfHwgKCFzdWJtaXR0ZWQgJiZcbiAgICAgICAgICAgIHN1Ym1pdCAhPT0gZmFsc2UgJiYgKCFzdWJtaXQgfHwga2V5ID09IHN1Ym1pdCkgJiYgKHN1Ym1pdHRlZCA9IHRydWUpKSkpIHtcbiAgICAgICAgICByZXN1bHQgPSBhY2N1bXVsYXRvcihyZXN1bHQsIGtleSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuICB9XG59O1xuXG5Gb3JtLk1ldGhvZHMgPSB7XG4gIHNlcmlhbGl6ZTogZnVuY3Rpb24oZm9ybSwgb3B0aW9ucykge1xuICAgIHJldHVybiBGb3JtLnNlcmlhbGl6ZUVsZW1lbnRzKEZvcm0uZ2V0RWxlbWVudHMoZm9ybSksIG9wdGlvbnMpO1xuICB9LFxuXG5cbiAgZ2V0RWxlbWVudHM6IGZ1bmN0aW9uKGZvcm0pIHtcbiAgICB2YXIgZWxlbWVudHMgPSAkKGZvcm0pLmdldEVsZW1lbnRzQnlUYWdOYW1lKCcqJyk7XG4gICAgdmFyIGVsZW1lbnQsIHJlc3VsdHMgPSBbXSwgc2VyaWFsaXplcnMgPSBGb3JtLkVsZW1lbnQuU2VyaWFsaXplcnM7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgZWxlbWVudCA9IGVsZW1lbnRzW2ldOyBpKyspIHtcbiAgICAgIGlmIChzZXJpYWxpemVyc1tlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKV0pXG4gICAgICAgIHJlc3VsdHMucHVzaChFbGVtZW50LmV4dGVuZChlbGVtZW50KSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9LFxuXG4gIGdldElucHV0czogZnVuY3Rpb24oZm9ybSwgdHlwZU5hbWUsIG5hbWUpIHtcbiAgICBmb3JtID0gJChmb3JtKTtcbiAgICB2YXIgaW5wdXRzID0gZm9ybS5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaW5wdXQnKTtcblxuICAgIGlmICghdHlwZU5hbWUgJiYgIW5hbWUpIHJldHVybiAkQShpbnB1dHMpLm1hcChFbGVtZW50LmV4dGVuZCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbWF0Y2hpbmdJbnB1dHMgPSBbXSwgbGVuZ3RoID0gaW5wdXRzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaW5wdXQgPSBpbnB1dHNbaV07XG4gICAgICBpZiAoKHR5cGVOYW1lICYmIGlucHV0LnR5cGUgIT0gdHlwZU5hbWUpIHx8IChuYW1lICYmIGlucHV0Lm5hbWUgIT0gbmFtZSkpXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgbWF0Y2hpbmdJbnB1dHMucHVzaChFbGVtZW50LmV4dGVuZChpbnB1dCkpO1xuICAgIH1cblxuICAgIHJldHVybiBtYXRjaGluZ0lucHV0cztcbiAgfSxcblxuICBkaXNhYmxlOiBmdW5jdGlvbihmb3JtKSB7XG4gICAgZm9ybSA9ICQoZm9ybSk7XG4gICAgRm9ybS5nZXRFbGVtZW50cyhmb3JtKS5pbnZva2UoJ2Rpc2FibGUnKTtcbiAgICByZXR1cm4gZm9ybTtcbiAgfSxcblxuICBlbmFibGU6IGZ1bmN0aW9uKGZvcm0pIHtcbiAgICBmb3JtID0gJChmb3JtKTtcbiAgICBGb3JtLmdldEVsZW1lbnRzKGZvcm0pLmludm9rZSgnZW5hYmxlJyk7XG4gICAgcmV0dXJuIGZvcm07XG4gIH0sXG5cbiAgZmluZEZpcnN0RWxlbWVudDogZnVuY3Rpb24oZm9ybSkge1xuICAgIHZhciBlbGVtZW50cyA9ICQoZm9ybSkuZ2V0RWxlbWVudHMoKS5maW5kQWxsKGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiAnaGlkZGVuJyAhPSBlbGVtZW50LnR5cGUgJiYgIWVsZW1lbnQuZGlzYWJsZWQ7XG4gICAgfSk7XG4gICAgdmFyIGZpcnN0QnlJbmRleCA9IGVsZW1lbnRzLmZpbmRBbGwoZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcmV0dXJuIGVsZW1lbnQuaGFzQXR0cmlidXRlKCd0YWJJbmRleCcpICYmIGVsZW1lbnQudGFiSW5kZXggPj0gMDtcbiAgICB9KS5zb3J0QnkoZnVuY3Rpb24oZWxlbWVudCkgeyByZXR1cm4gZWxlbWVudC50YWJJbmRleCB9KS5maXJzdCgpO1xuXG4gICAgcmV0dXJuIGZpcnN0QnlJbmRleCA/IGZpcnN0QnlJbmRleCA6IGVsZW1lbnRzLmZpbmQoZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcmV0dXJuIC9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhKSQvaS50ZXN0KGVsZW1lbnQudGFnTmFtZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgZm9jdXNGaXJzdEVsZW1lbnQ6IGZ1bmN0aW9uKGZvcm0pIHtcbiAgICBmb3JtID0gJChmb3JtKTtcbiAgICB2YXIgZWxlbWVudCA9IGZvcm0uZmluZEZpcnN0RWxlbWVudCgpO1xuICAgIGlmIChlbGVtZW50KSBlbGVtZW50LmFjdGl2YXRlKCk7XG4gICAgcmV0dXJuIGZvcm07XG4gIH0sXG5cbiAgcmVxdWVzdDogZnVuY3Rpb24oZm9ybSwgb3B0aW9ucykge1xuICAgIGZvcm0gPSAkKGZvcm0pLCBvcHRpb25zID0gT2JqZWN0LmNsb25lKG9wdGlvbnMgfHwgeyB9KTtcblxuICAgIHZhciBwYXJhbXMgPSBvcHRpb25zLnBhcmFtZXRlcnMsIGFjdGlvbiA9IGZvcm0ucmVhZEF0dHJpYnV0ZSgnYWN0aW9uJykgfHwgJyc7XG4gICAgaWYgKGFjdGlvbi5ibGFuaygpKSBhY3Rpb24gPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcbiAgICBvcHRpb25zLnBhcmFtZXRlcnMgPSBmb3JtLnNlcmlhbGl6ZSh0cnVlKTtcblxuICAgIGlmIChwYXJhbXMpIHtcbiAgICAgIGlmIChPYmplY3QuaXNTdHJpbmcocGFyYW1zKSkgcGFyYW1zID0gcGFyYW1zLnRvUXVlcnlQYXJhbXMoKTtcbiAgICAgIE9iamVjdC5leHRlbmQob3B0aW9ucy5wYXJhbWV0ZXJzLCBwYXJhbXMpO1xuICAgIH1cblxuICAgIGlmIChmb3JtLmhhc0F0dHJpYnV0ZSgnbWV0aG9kJykgJiYgIW9wdGlvbnMubWV0aG9kKVxuICAgICAgb3B0aW9ucy5tZXRob2QgPSBmb3JtLm1ldGhvZDtcblxuICAgIHJldHVybiBuZXcgQWpheC5SZXF1ZXN0KGFjdGlvbiwgb3B0aW9ucyk7XG4gIH1cbn07XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5cbkZvcm0uRWxlbWVudCA9IHtcbiAgZm9jdXM6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAkKGVsZW1lbnQpLmZvY3VzKCk7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH0sXG5cbiAgc2VsZWN0OiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgJChlbGVtZW50KS5zZWxlY3QoKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxufTtcblxuRm9ybS5FbGVtZW50Lk1ldGhvZHMgPSB7XG5cbiAgc2VyaWFsaXplOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgaWYgKCFlbGVtZW50LmRpc2FibGVkICYmIGVsZW1lbnQubmFtZSkge1xuICAgICAgdmFyIHZhbHVlID0gZWxlbWVudC5nZXRWYWx1ZSgpO1xuICAgICAgaWYgKHZhbHVlICE9IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgcGFpciA9IHsgfTtcbiAgICAgICAgcGFpcltlbGVtZW50Lm5hbWVdID0gdmFsdWU7XG4gICAgICAgIHJldHVybiBPYmplY3QudG9RdWVyeVN0cmluZyhwYWlyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9LFxuXG4gIGdldFZhbHVlOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIG1ldGhvZCA9IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIHJldHVybiBGb3JtLkVsZW1lbnQuU2VyaWFsaXplcnNbbWV0aG9kXShlbGVtZW50KTtcbiAgfSxcblxuICBzZXRWYWx1ZTogZnVuY3Rpb24oZWxlbWVudCwgdmFsdWUpIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICB2YXIgbWV0aG9kID0gZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgRm9ybS5FbGVtZW50LlNlcmlhbGl6ZXJzW21ldGhvZF0oZWxlbWVudCwgdmFsdWUpO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9LFxuXG4gIGNsZWFyOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgJChlbGVtZW50KS52YWx1ZSA9ICcnO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9LFxuXG4gIHByZXNlbnQ6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICByZXR1cm4gJChlbGVtZW50KS52YWx1ZSAhPSAnJztcbiAgfSxcblxuICBhY3RpdmF0ZTogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHRyeSB7XG4gICAgICBlbGVtZW50LmZvY3VzKCk7XG4gICAgICBpZiAoZWxlbWVudC5zZWxlY3QgJiYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpICE9ICdpbnB1dCcgfHxcbiAgICAgICAgICAhKC9eKD86YnV0dG9ufHJlc2V0fHN1Ym1pdCkkL2kudGVzdChlbGVtZW50LnR5cGUpKSkpXG4gICAgICAgIGVsZW1lbnQuc2VsZWN0KCk7XG4gICAgfSBjYXRjaCAoZSkgeyB9XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH0sXG5cbiAgZGlzYWJsZTogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIGVsZW1lbnQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9LFxuXG4gIGVuYWJsZTogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIGVsZW1lbnQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxufTtcblxuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbnZhciBGaWVsZCA9IEZvcm0uRWxlbWVudDtcblxudmFyICRGID0gRm9ybS5FbGVtZW50Lk1ldGhvZHMuZ2V0VmFsdWU7XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5Gb3JtLkVsZW1lbnQuU2VyaWFsaXplcnMgPSAoZnVuY3Rpb24oKSB7XG4gIGZ1bmN0aW9uIGlucHV0KGVsZW1lbnQsIHZhbHVlKSB7XG4gICAgc3dpdGNoIChlbGVtZW50LnR5cGUudG9Mb3dlckNhc2UoKSkge1xuICAgICAgY2FzZSAnY2hlY2tib3gnOlxuICAgICAgY2FzZSAncmFkaW8nOlxuICAgICAgICByZXR1cm4gaW5wdXRTZWxlY3RvcihlbGVtZW50LCB2YWx1ZSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdmFsdWVTZWxlY3RvcihlbGVtZW50LCB2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5wdXRTZWxlY3RvcihlbGVtZW50LCB2YWx1ZSkge1xuICAgIGlmIChPYmplY3QuaXNVbmRlZmluZWQodmFsdWUpKVxuICAgICAgcmV0dXJuIGVsZW1lbnQuY2hlY2tlZCA/IGVsZW1lbnQudmFsdWUgOiBudWxsO1xuICAgIGVsc2UgZWxlbWVudC5jaGVja2VkID0gISF2YWx1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZhbHVlU2VsZWN0b3IoZWxlbWVudCwgdmFsdWUpIHtcbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKHZhbHVlKSkgcmV0dXJuIGVsZW1lbnQudmFsdWU7XG4gICAgZWxzZSBlbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gIH1cblxuICBmdW5jdGlvbiBzZWxlY3QoZWxlbWVudCwgdmFsdWUpIHtcbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKHZhbHVlKSlcbiAgICAgIHJldHVybiAoZWxlbWVudC50eXBlID09PSAnc2VsZWN0LW9uZScgPyBzZWxlY3RPbmUgOiBzZWxlY3RNYW55KShlbGVtZW50KTtcblxuICAgIHZhciBvcHQsIGN1cnJlbnRWYWx1ZSwgc2luZ2xlID0gIU9iamVjdC5pc0FycmF5KHZhbHVlKTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZWxlbWVudC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgb3B0ID0gZWxlbWVudC5vcHRpb25zW2ldO1xuICAgICAgY3VycmVudFZhbHVlID0gdGhpcy5vcHRpb25WYWx1ZShvcHQpO1xuICAgICAgaWYgKHNpbmdsZSkge1xuICAgICAgICBpZiAoY3VycmVudFZhbHVlID09IHZhbHVlKSB7XG4gICAgICAgICAgb3B0LnNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Ugb3B0LnNlbGVjdGVkID0gdmFsdWUuaW5jbHVkZShjdXJyZW50VmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdE9uZShlbGVtZW50KSB7XG4gICAgdmFyIGluZGV4ID0gZWxlbWVudC5zZWxlY3RlZEluZGV4O1xuICAgIHJldHVybiBpbmRleCA+PSAwID8gb3B0aW9uVmFsdWUoZWxlbWVudC5vcHRpb25zW2luZGV4XSkgOiBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gc2VsZWN0TWFueShlbGVtZW50KSB7XG4gICAgdmFyIHZhbHVlcywgbGVuZ3RoID0gZWxlbWVudC5sZW5ndGg7XG4gICAgaWYgKCFsZW5ndGgpIHJldHVybiBudWxsO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIHZhbHVlcyA9IFtdOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBvcHQgPSBlbGVtZW50Lm9wdGlvbnNbaV07XG4gICAgICBpZiAob3B0LnNlbGVjdGVkKSB2YWx1ZXMucHVzaChvcHRpb25WYWx1ZShvcHQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfVxuXG4gIGZ1bmN0aW9uIG9wdGlvblZhbHVlKG9wdCkge1xuICAgIHJldHVybiBFbGVtZW50Lmhhc0F0dHJpYnV0ZShvcHQsICd2YWx1ZScpID8gb3B0LnZhbHVlIDogb3B0LnRleHQ7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGlucHV0OiAgICAgICAgIGlucHV0LFxuICAgIGlucHV0U2VsZWN0b3I6IGlucHV0U2VsZWN0b3IsXG4gICAgdGV4dGFyZWE6ICAgICAgdmFsdWVTZWxlY3RvcixcbiAgICBzZWxlY3Q6ICAgICAgICBzZWxlY3QsXG4gICAgc2VsZWN0T25lOiAgICAgc2VsZWN0T25lLFxuICAgIHNlbGVjdE1hbnk6ICAgIHNlbGVjdE1hbnksXG4gICAgb3B0aW9uVmFsdWU6ICAgb3B0aW9uVmFsdWUsXG4gICAgYnV0dG9uOiAgICAgICAgdmFsdWVTZWxlY3RvclxuICB9O1xufSkoKTtcblxuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cblxuQWJzdHJhY3QuVGltZWRPYnNlcnZlciA9IENsYXNzLmNyZWF0ZShQZXJpb2RpY2FsRXhlY3V0ZXIsIHtcbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oJHN1cGVyLCBlbGVtZW50LCBmcmVxdWVuY3ksIGNhbGxiYWNrKSB7XG4gICAgJHN1cGVyKGNhbGxiYWNrLCBmcmVxdWVuY3kpO1xuICAgIHRoaXMuZWxlbWVudCAgID0gJChlbGVtZW50KTtcbiAgICB0aGlzLmxhc3RWYWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcbiAgfSxcblxuICBleGVjdXRlOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWUgPSB0aGlzLmdldFZhbHVlKCk7XG4gICAgaWYgKE9iamVjdC5pc1N0cmluZyh0aGlzLmxhc3RWYWx1ZSkgJiYgT2JqZWN0LmlzU3RyaW5nKHZhbHVlKSA/XG4gICAgICAgIHRoaXMubGFzdFZhbHVlICE9IHZhbHVlIDogU3RyaW5nKHRoaXMubGFzdFZhbHVlKSAhPSBTdHJpbmcodmFsdWUpKSB7XG4gICAgICB0aGlzLmNhbGxiYWNrKHRoaXMuZWxlbWVudCwgdmFsdWUpO1xuICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZTtcbiAgICB9XG4gIH1cbn0pO1xuXG5Gb3JtLkVsZW1lbnQuT2JzZXJ2ZXIgPSBDbGFzcy5jcmVhdGUoQWJzdHJhY3QuVGltZWRPYnNlcnZlciwge1xuICBnZXRWYWx1ZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIEZvcm0uRWxlbWVudC5nZXRWYWx1ZSh0aGlzLmVsZW1lbnQpO1xuICB9XG59KTtcblxuRm9ybS5PYnNlcnZlciA9IENsYXNzLmNyZWF0ZShBYnN0cmFjdC5UaW1lZE9ic2VydmVyLCB7XG4gIGdldFZhbHVlOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gRm9ybS5zZXJpYWxpemUodGhpcy5lbGVtZW50KTtcbiAgfVxufSk7XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5BYnN0cmFjdC5FdmVudE9ic2VydmVyID0gQ2xhc3MuY3JlYXRlKHtcbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oZWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmVsZW1lbnQgID0gJChlbGVtZW50KTtcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG5cbiAgICB0aGlzLmxhc3RWYWx1ZSA9IHRoaXMuZ2V0VmFsdWUoKTtcbiAgICBpZiAodGhpcy5lbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PSAnZm9ybScpXG4gICAgICB0aGlzLnJlZ2lzdGVyRm9ybUNhbGxiYWNrcygpO1xuICAgIGVsc2VcbiAgICAgIHRoaXMucmVnaXN0ZXJDYWxsYmFjayh0aGlzLmVsZW1lbnQpO1xuICB9LFxuXG4gIG9uRWxlbWVudEV2ZW50OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWUgPSB0aGlzLmdldFZhbHVlKCk7XG4gICAgaWYgKHRoaXMubGFzdFZhbHVlICE9IHZhbHVlKSB7XG4gICAgICB0aGlzLmNhbGxiYWNrKHRoaXMuZWxlbWVudCwgdmFsdWUpO1xuICAgICAgdGhpcy5sYXN0VmFsdWUgPSB2YWx1ZTtcbiAgICB9XG4gIH0sXG5cbiAgcmVnaXN0ZXJGb3JtQ2FsbGJhY2tzOiBmdW5jdGlvbigpIHtcbiAgICBGb3JtLmdldEVsZW1lbnRzKHRoaXMuZWxlbWVudCkuZWFjaCh0aGlzLnJlZ2lzdGVyQ2FsbGJhY2ssIHRoaXMpO1xuICB9LFxuXG4gIHJlZ2lzdGVyQ2FsbGJhY2s6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC50eXBlKSB7XG4gICAgICBzd2l0Y2ggKGVsZW1lbnQudHlwZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgIGNhc2UgJ2NoZWNrYm94JzpcbiAgICAgICAgY2FzZSAncmFkaW8nOlxuICAgICAgICAgIEV2ZW50Lm9ic2VydmUoZWxlbWVudCwgJ2NsaWNrJywgdGhpcy5vbkVsZW1lbnRFdmVudC5iaW5kKHRoaXMpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBFdmVudC5vYnNlcnZlKGVsZW1lbnQsICdjaGFuZ2UnLCB0aGlzLm9uRWxlbWVudEV2ZW50LmJpbmQodGhpcykpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxufSk7XG5cbkZvcm0uRWxlbWVudC5FdmVudE9ic2VydmVyID0gQ2xhc3MuY3JlYXRlKEFic3RyYWN0LkV2ZW50T2JzZXJ2ZXIsIHtcbiAgZ2V0VmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBGb3JtLkVsZW1lbnQuZ2V0VmFsdWUodGhpcy5lbGVtZW50KTtcbiAgfVxufSk7XG5cbkZvcm0uRXZlbnRPYnNlcnZlciA9IENsYXNzLmNyZWF0ZShBYnN0cmFjdC5FdmVudE9ic2VydmVyLCB7XG4gIGdldFZhbHVlOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gRm9ybS5zZXJpYWxpemUodGhpcy5lbGVtZW50KTtcbiAgfVxufSk7XG4oZnVuY3Rpb24oR0xPQkFMKSB7XG4gIHZhciBESVYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgdmFyIGRvY0VsID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB2YXIgTU9VU0VFTlRFUl9NT1VTRUxFQVZFX0VWRU5UU19TVVBQT1JURUQgPSAnb25tb3VzZWVudGVyJyBpbiBkb2NFbFxuICAgJiYgJ29ubW91c2VsZWF2ZScgaW4gZG9jRWw7XG5cbiAgdmFyIEV2ZW50ID0ge1xuICAgIEtFWV9CQUNLU1BBQ0U6IDgsXG4gICAgS0VZX1RBQjogICAgICAgOSxcbiAgICBLRVlfUkVUVVJOOiAgIDEzLFxuICAgIEtFWV9FU0M6ICAgICAgMjcsXG4gICAgS0VZX0xFRlQ6ICAgICAzNyxcbiAgICBLRVlfVVA6ICAgICAgIDM4LFxuICAgIEtFWV9SSUdIVDogICAgMzksXG4gICAgS0VZX0RPV046ICAgICA0MCxcbiAgICBLRVlfREVMRVRFOiAgIDQ2LFxuICAgIEtFWV9IT01FOiAgICAgMzYsXG4gICAgS0VZX0VORDogICAgICAzNSxcbiAgICBLRVlfUEFHRVVQOiAgIDMzLFxuICAgIEtFWV9QQUdFRE9XTjogMzQsXG4gICAgS0VZX0lOU0VSVDogICA0NVxuICB9O1xuXG5cbiAgdmFyIGlzSUVMZWdhY3lFdmVudCA9IGZ1bmN0aW9uKGV2ZW50KSB7IHJldHVybiBmYWxzZTsgfTtcblxuICBpZiAod2luZG93LmF0dGFjaEV2ZW50KSB7XG4gICAgaWYgKHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICBpc0lFTGVnYWN5RXZlbnQgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgICByZXR1cm4gIShldmVudCBpbnN0YW5jZW9mIHdpbmRvdy5FdmVudCk7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBpc0lFTGVnYWN5RXZlbnQgPSBmdW5jdGlvbihldmVudCkgeyByZXR1cm4gdHJ1ZTsgfTtcbiAgICB9XG4gIH1cblxuICB2YXIgX2lzQnV0dG9uO1xuXG4gIGZ1bmN0aW9uIF9pc0J1dHRvbkZvckRPTUV2ZW50cyhldmVudCwgY29kZSkge1xuICAgIHJldHVybiBldmVudC53aGljaCA/IChldmVudC53aGljaCA9PT0gY29kZSArIDEpIDogKGV2ZW50LmJ1dHRvbiA9PT0gY29kZSk7XG4gIH1cblxuICB2YXIgbGVnYWN5QnV0dG9uTWFwID0geyAwOiAxLCAxOiA0LCAyOiAyIH07XG4gIGZ1bmN0aW9uIF9pc0J1dHRvbkZvckxlZ2FjeUV2ZW50cyhldmVudCwgY29kZSkge1xuICAgIHJldHVybiBldmVudC5idXR0b24gPT09IGxlZ2FjeUJ1dHRvbk1hcFtjb2RlXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIF9pc0J1dHRvbkZvcldlYktpdChldmVudCwgY29kZSkge1xuICAgIHN3aXRjaCAoY29kZSkge1xuICAgICAgY2FzZSAwOiByZXR1cm4gZXZlbnQud2hpY2ggPT0gMSAmJiAhZXZlbnQubWV0YUtleTtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGV2ZW50LndoaWNoID09IDIgfHwgKGV2ZW50LndoaWNoID09IDEgJiYgZXZlbnQubWV0YUtleSk7XG4gICAgICBjYXNlIDI6IHJldHVybiBldmVudC53aGljaCA9PSAzO1xuICAgICAgZGVmYXVsdDogcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGlmICh3aW5kb3cuYXR0YWNoRXZlbnQpIHtcbiAgICBpZiAoIXdpbmRvdy5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICBfaXNCdXR0b24gPSBfaXNCdXR0b25Gb3JMZWdhY3lFdmVudHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9pc0J1dHRvbiA9IGZ1bmN0aW9uKGV2ZW50LCBjb2RlKSB7XG4gICAgICAgIHJldHVybiBpc0lFTGVnYWN5RXZlbnQoZXZlbnQpID8gX2lzQnV0dG9uRm9yTGVnYWN5RXZlbnRzKGV2ZW50LCBjb2RlKSA6XG4gICAgICAgICBfaXNCdXR0b25Gb3JET01FdmVudHMoZXZlbnQsIGNvZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChQcm90b3R5cGUuQnJvd3Nlci5XZWJLaXQpIHtcbiAgICBfaXNCdXR0b24gPSBfaXNCdXR0b25Gb3JXZWJLaXQ7XG4gIH0gZWxzZSB7XG4gICAgX2lzQnV0dG9uID0gX2lzQnV0dG9uRm9yRE9NRXZlbnRzO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNMZWZ0Q2xpY2soZXZlbnQpICAgeyByZXR1cm4gX2lzQnV0dG9uKGV2ZW50LCAwKSB9XG5cbiAgZnVuY3Rpb24gaXNNaWRkbGVDbGljayhldmVudCkgeyByZXR1cm4gX2lzQnV0dG9uKGV2ZW50LCAxKSB9XG5cbiAgZnVuY3Rpb24gaXNSaWdodENsaWNrKGV2ZW50KSAgeyByZXR1cm4gX2lzQnV0dG9uKGV2ZW50LCAyKSB9XG5cbiAgZnVuY3Rpb24gZWxlbWVudChldmVudCkge1xuICAgIHJldHVybiBFbGVtZW50LmV4dGVuZChfZWxlbWVudChldmVudCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gX2VsZW1lbnQoZXZlbnQpIHtcbiAgICBldmVudCA9IEV2ZW50LmV4dGVuZChldmVudCk7XG5cbiAgICB2YXIgbm9kZSA9IGV2ZW50LnRhcmdldCwgdHlwZSA9IGV2ZW50LnR5cGUsXG4gICAgIGN1cnJlbnRUYXJnZXQgPSBldmVudC5jdXJyZW50VGFyZ2V0O1xuXG4gICAgaWYgKGN1cnJlbnRUYXJnZXQgJiYgY3VycmVudFRhcmdldC50YWdOYW1lKSB7XG4gICAgICBpZiAodHlwZSA9PT0gJ2xvYWQnIHx8IHR5cGUgPT09ICdlcnJvcicgfHxcbiAgICAgICAgKHR5cGUgPT09ICdjbGljaycgJiYgY3VycmVudFRhcmdldC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCdcbiAgICAgICAgICAmJiBjdXJyZW50VGFyZ2V0LnR5cGUgPT09ICdyYWRpbycpKVxuICAgICAgICAgICAgbm9kZSA9IGN1cnJlbnRUYXJnZXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT0gTm9kZS5URVhUX05PREUgPyBub2RlLnBhcmVudE5vZGUgOiBub2RlO1xuICB9XG5cbiAgZnVuY3Rpb24gZmluZEVsZW1lbnQoZXZlbnQsIGV4cHJlc3Npb24pIHtcbiAgICB2YXIgZWxlbWVudCA9IF9lbGVtZW50KGV2ZW50KSwgc2VsZWN0b3IgPSBQcm90b3R5cGUuU2VsZWN0b3I7XG4gICAgaWYgKCFleHByZXNzaW9uKSByZXR1cm4gRWxlbWVudC5leHRlbmQoZWxlbWVudCk7XG4gICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgIGlmIChPYmplY3QuaXNFbGVtZW50KGVsZW1lbnQpICYmIHNlbGVjdG9yLm1hdGNoKGVsZW1lbnQsIGV4cHJlc3Npb24pKVxuICAgICAgICByZXR1cm4gRWxlbWVudC5leHRlbmQoZWxlbWVudCk7XG4gICAgICBlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBvaW50ZXIoZXZlbnQpIHtcbiAgICByZXR1cm4geyB4OiBwb2ludGVyWChldmVudCksIHk6IHBvaW50ZXJZKGV2ZW50KSB9O1xuICB9XG5cbiAgZnVuY3Rpb24gcG9pbnRlclgoZXZlbnQpIHtcbiAgICB2YXIgZG9jRWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCxcbiAgICAgYm9keSA9IGRvY3VtZW50LmJvZHkgfHwgeyBzY3JvbGxMZWZ0OiAwIH07XG5cbiAgICByZXR1cm4gZXZlbnQucGFnZVggfHwgKGV2ZW50LmNsaWVudFggK1xuICAgICAgKGRvY0VsZW1lbnQuc2Nyb2xsTGVmdCB8fCBib2R5LnNjcm9sbExlZnQpIC1cbiAgICAgIChkb2NFbGVtZW50LmNsaWVudExlZnQgfHwgMCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9pbnRlclkoZXZlbnQpIHtcbiAgICB2YXIgZG9jRWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCxcbiAgICAgYm9keSA9IGRvY3VtZW50LmJvZHkgfHwgeyBzY3JvbGxUb3A6IDAgfTtcblxuICAgIHJldHVybiAgZXZlbnQucGFnZVkgfHwgKGV2ZW50LmNsaWVudFkgK1xuICAgICAgIChkb2NFbGVtZW50LnNjcm9sbFRvcCB8fCBib2R5LnNjcm9sbFRvcCkgLVxuICAgICAgIChkb2NFbGVtZW50LmNsaWVudFRvcCB8fCAwKSk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIHN0b3AoZXZlbnQpIHtcbiAgICBFdmVudC5leHRlbmQoZXZlbnQpO1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBldmVudC5zdG9wcGVkID0gdHJ1ZTtcbiAgfVxuXG5cbiAgRXZlbnQuTWV0aG9kcyA9IHtcbiAgICBpc0xlZnRDbGljazogICBpc0xlZnRDbGljayxcbiAgICBpc01pZGRsZUNsaWNrOiBpc01pZGRsZUNsaWNrLFxuICAgIGlzUmlnaHRDbGljazogIGlzUmlnaHRDbGljayxcblxuICAgIGVsZW1lbnQ6ICAgICBlbGVtZW50LFxuICAgIGZpbmRFbGVtZW50OiBmaW5kRWxlbWVudCxcblxuICAgIHBvaW50ZXI6ICBwb2ludGVyLFxuICAgIHBvaW50ZXJYOiBwb2ludGVyWCxcbiAgICBwb2ludGVyWTogcG9pbnRlclksXG5cbiAgICBzdG9wOiBzdG9wXG4gIH07XG5cbiAgdmFyIG1ldGhvZHMgPSBPYmplY3Qua2V5cyhFdmVudC5NZXRob2RzKS5pbmplY3QoeyB9LCBmdW5jdGlvbihtLCBuYW1lKSB7XG4gICAgbVtuYW1lXSA9IEV2ZW50Lk1ldGhvZHNbbmFtZV0ubWV0aG9kaXplKCk7XG4gICAgcmV0dXJuIG07XG4gIH0pO1xuXG4gIGlmICh3aW5kb3cuYXR0YWNoRXZlbnQpIHtcbiAgICBmdW5jdGlvbiBfcmVsYXRlZFRhcmdldChldmVudCkge1xuICAgICAgdmFyIGVsZW1lbnQ7XG4gICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgY2FzZSAnbW91c2VvdmVyJzpcbiAgICAgICAgY2FzZSAnbW91c2VlbnRlcic6XG4gICAgICAgICAgZWxlbWVudCA9IGV2ZW50LmZyb21FbGVtZW50O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdtb3VzZW91dCc6XG4gICAgICAgIGNhc2UgJ21vdXNlbGVhdmUnOlxuICAgICAgICAgIGVsZW1lbnQgPSBldmVudC50b0VsZW1lbnQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gRWxlbWVudC5leHRlbmQoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgdmFyIGFkZGl0aW9uYWxNZXRob2RzID0ge1xuICAgICAgc3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbigpIHsgdGhpcy5jYW5jZWxCdWJibGUgPSB0cnVlIH0sXG4gICAgICBwcmV2ZW50RGVmYXVsdDogIGZ1bmN0aW9uKCkgeyB0aGlzLnJldHVyblZhbHVlID0gZmFsc2UgfSxcbiAgICAgIGluc3BlY3Q6IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ1tvYmplY3QgRXZlbnRdJyB9XG4gICAgfTtcblxuICAgIEV2ZW50LmV4dGVuZCA9IGZ1bmN0aW9uKGV2ZW50LCBlbGVtZW50KSB7XG4gICAgICBpZiAoIWV2ZW50KSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGlmICghaXNJRUxlZ2FjeUV2ZW50KGV2ZW50KSkgcmV0dXJuIGV2ZW50O1xuXG4gICAgICBpZiAoZXZlbnQuX2V4dGVuZGVkQnlQcm90b3R5cGUpIHJldHVybiBldmVudDtcbiAgICAgIGV2ZW50Ll9leHRlbmRlZEJ5UHJvdG90eXBlID0gUHJvdG90eXBlLmVtcHR5RnVuY3Rpb247XG5cbiAgICAgIHZhciBwb2ludGVyID0gRXZlbnQucG9pbnRlcihldmVudCk7XG5cbiAgICAgIE9iamVjdC5leHRlbmQoZXZlbnQsIHtcbiAgICAgICAgdGFyZ2V0OiBldmVudC5zcmNFbGVtZW50IHx8IGVsZW1lbnQsXG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IF9yZWxhdGVkVGFyZ2V0KGV2ZW50KSxcbiAgICAgICAgcGFnZVg6ICBwb2ludGVyLngsXG4gICAgICAgIHBhZ2VZOiAgcG9pbnRlci55XG4gICAgICB9KTtcblxuICAgICAgT2JqZWN0LmV4dGVuZChldmVudCwgbWV0aG9kcyk7XG4gICAgICBPYmplY3QuZXh0ZW5kKGV2ZW50LCBhZGRpdGlvbmFsTWV0aG9kcyk7XG5cbiAgICAgIHJldHVybiBldmVudDtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIEV2ZW50LmV4dGVuZCA9IFByb3RvdHlwZS5LO1xuICB9XG5cbiAgaWYgKHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgRXZlbnQucHJvdG90eXBlID0gd2luZG93LkV2ZW50LnByb3RvdHlwZSB8fCBkb2N1bWVudC5jcmVhdGVFdmVudCgnSFRNTEV2ZW50cycpLl9fcHJvdG9fXztcbiAgICBPYmplY3QuZXh0ZW5kKEV2ZW50LnByb3RvdHlwZSwgbWV0aG9kcyk7XG4gIH1cblxuICB2YXIgRVZFTlRfVFJBTlNMQVRJT05TID0ge1xuICAgIG1vdXNlZW50ZXI6ICdtb3VzZW92ZXInLFxuICAgIG1vdXNlbGVhdmU6ICdtb3VzZW91dCdcbiAgfTtcblxuICBmdW5jdGlvbiBnZXRET01FdmVudE5hbWUoZXZlbnROYW1lKSB7XG4gICAgcmV0dXJuIEVWRU5UX1RSQU5TTEFUSU9OU1tldmVudE5hbWVdIHx8IGV2ZW50TmFtZTtcbiAgfVxuXG4gIGlmIChNT1VTRUVOVEVSX01PVVNFTEVBVkVfRVZFTlRTX1NVUFBPUlRFRClcbiAgICBnZXRET01FdmVudE5hbWUgPSBQcm90b3R5cGUuSztcblxuICBmdW5jdGlvbiBnZXRVbmlxdWVFbGVtZW50SUQoZWxlbWVudCkge1xuICAgIGlmIChlbGVtZW50ID09PSB3aW5kb3cpIHJldHVybiAwO1xuXG4gICAgaWYgKHR5cGVvZiBlbGVtZW50Ll9wcm90b3R5cGVVSUQgPT09ICd1bmRlZmluZWQnKVxuICAgICAgZWxlbWVudC5fcHJvdG90eXBlVUlEID0gRWxlbWVudC5TdG9yYWdlLlVJRCsrO1xuICAgIHJldHVybiBlbGVtZW50Ll9wcm90b3R5cGVVSUQ7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRVbmlxdWVFbGVtZW50SURfSUUoZWxlbWVudCkge1xuICAgIGlmIChlbGVtZW50ID09PSB3aW5kb3cpIHJldHVybiAwO1xuICAgIGlmIChlbGVtZW50ID09IGRvY3VtZW50KSByZXR1cm4gMTtcbiAgICByZXR1cm4gZWxlbWVudC51bmlxdWVJRDtcbiAgfVxuXG4gIGlmICgndW5pcXVlSUQnIGluIERJVilcbiAgICBnZXRVbmlxdWVFbGVtZW50SUQgPSBnZXRVbmlxdWVFbGVtZW50SURfSUU7XG5cbiAgZnVuY3Rpb24gaXNDdXN0b21FdmVudChldmVudE5hbWUpIHtcbiAgICByZXR1cm4gZXZlbnROYW1lLmluY2x1ZGUoJzonKTtcbiAgfVxuXG4gIEV2ZW50Ll9pc0N1c3RvbUV2ZW50ID0gaXNDdXN0b21FdmVudDtcblxuICBmdW5jdGlvbiBnZXRSZWdpc3RyeUZvckVsZW1lbnQoZWxlbWVudCwgdWlkKSB7XG4gICAgdmFyIENBQ0hFID0gR0xPQkFMLkV2ZW50LmNhY2hlO1xuICAgIGlmIChPYmplY3QuaXNVbmRlZmluZWQodWlkKSlcbiAgICAgIHVpZCA9IGdldFVuaXF1ZUVsZW1lbnRJRChlbGVtZW50KTtcbiAgICBpZiAoIUNBQ0hFW3VpZF0pIENBQ0hFW3VpZF0gPSB7IGVsZW1lbnQ6IGVsZW1lbnQgfTtcbiAgICByZXR1cm4gQ0FDSEVbdWlkXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlc3Ryb3lSZWdpc3RyeUZvckVsZW1lbnQoZWxlbWVudCwgdWlkKSB7XG4gICAgaWYgKE9iamVjdC5pc1VuZGVmaW5lZCh1aWQpKVxuICAgICAgdWlkID0gZ2V0VW5pcXVlRWxlbWVudElEKGVsZW1lbnQpO1xuICAgIGRlbGV0ZSBHTE9CQUwuRXZlbnQuY2FjaGVbdWlkXTtcbiAgfVxuXG5cbiAgZnVuY3Rpb24gcmVnaXN0ZXIoZWxlbWVudCwgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gICAgdmFyIHJlZ2lzdHJ5ID0gZ2V0UmVnaXN0cnlGb3JFbGVtZW50KGVsZW1lbnQpO1xuICAgIGlmICghcmVnaXN0cnlbZXZlbnROYW1lXSkgcmVnaXN0cnlbZXZlbnROYW1lXSA9IFtdO1xuICAgIHZhciBlbnRyaWVzID0gcmVnaXN0cnlbZXZlbnROYW1lXTtcblxuICAgIHZhciBpID0gZW50cmllcy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSlcbiAgICAgIGlmIChlbnRyaWVzW2ldLmhhbmRsZXIgPT09IGhhbmRsZXIpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIHVpZCA9IGdldFVuaXF1ZUVsZW1lbnRJRChlbGVtZW50KTtcbiAgICB2YXIgcmVzcG9uZGVyID0gR0xPQkFMLkV2ZW50Ll9jcmVhdGVSZXNwb25kZXIodWlkLCBldmVudE5hbWUsIGhhbmRsZXIpO1xuICAgIHZhciBlbnRyeSA9IHtcbiAgICAgIHJlc3BvbmRlcjogcmVzcG9uZGVyLFxuICAgICAgaGFuZGxlcjogICBoYW5kbGVyXG4gICAgfTtcblxuICAgIGVudHJpZXMucHVzaChlbnRyeSk7XG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cbiAgZnVuY3Rpb24gdW5yZWdpc3RlcihlbGVtZW50LCBldmVudE5hbWUsIGhhbmRsZXIpIHtcbiAgICB2YXIgcmVnaXN0cnkgPSBnZXRSZWdpc3RyeUZvckVsZW1lbnQoZWxlbWVudCk7XG4gICAgdmFyIGVudHJpZXMgPSByZWdpc3RyeVtldmVudE5hbWVdO1xuICAgIGlmICghZW50cmllcykgcmV0dXJuO1xuXG4gICAgdmFyIGkgPSBlbnRyaWVzLmxlbmd0aCwgZW50cnk7XG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgaWYgKGVudHJpZXNbaV0uaGFuZGxlciA9PT0gaGFuZGxlcikge1xuICAgICAgICBlbnRyeSA9IGVudHJpZXNbaV07XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghZW50cnkpIHJldHVybjtcblxuICAgIHZhciBpbmRleCA9IGVudHJpZXMuaW5kZXhPZihlbnRyeSk7XG4gICAgZW50cmllcy5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cblxuICBmdW5jdGlvbiBvYnNlcnZlKGVsZW1lbnQsIGV2ZW50TmFtZSwgaGFuZGxlcikge1xuICAgIGVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICAgIHZhciBlbnRyeSA9IHJlZ2lzdGVyKGVsZW1lbnQsIGV2ZW50TmFtZSwgaGFuZGxlcik7XG5cbiAgICBpZiAoZW50cnkgPT09IG51bGwpIHJldHVybiBlbGVtZW50O1xuXG4gICAgdmFyIHJlc3BvbmRlciA9IGVudHJ5LnJlc3BvbmRlcjtcbiAgICBpZiAoaXNDdXN0b21FdmVudChldmVudE5hbWUpKVxuICAgICAgb2JzZXJ2ZUN1c3RvbUV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgcmVzcG9uZGVyKTtcbiAgICBlbHNlXG4gICAgICBvYnNlcnZlU3RhbmRhcmRFdmVudChlbGVtZW50LCBldmVudE5hbWUsIHJlc3BvbmRlcik7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9ic2VydmVTdGFuZGFyZEV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgcmVzcG9uZGVyKSB7XG4gICAgdmFyIGFjdHVhbEV2ZW50TmFtZSA9IGdldERPTUV2ZW50TmFtZShldmVudE5hbWUpO1xuICAgIGlmIChlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihhY3R1YWxFdmVudE5hbWUsIHJlc3BvbmRlciwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KCdvbicgKyBhY3R1YWxFdmVudE5hbWUsIHJlc3BvbmRlcik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gb2JzZXJ2ZUN1c3RvbUV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgcmVzcG9uZGVyKSB7XG4gICAgaWYgKGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdkYXRhYXZhaWxhYmxlJywgcmVzcG9uZGVyLCBmYWxzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZW1lbnQuYXR0YWNoRXZlbnQoJ29uZGF0YWF2YWlsYWJsZScsIHJlc3BvbmRlcik7XG4gICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KCdvbmxvc2VjYXB0dXJlJywgICByZXNwb25kZXIpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0b3BPYnNlcnZpbmcoZWxlbWVudCwgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gICAgZWxlbWVudCA9ICQoZWxlbWVudCk7XG4gICAgdmFyIGhhbmRsZXJHaXZlbiA9ICFPYmplY3QuaXNVbmRlZmluZWQoaGFuZGxlciksXG4gICAgIGV2ZW50TmFtZUdpdmVuID0gIU9iamVjdC5pc1VuZGVmaW5lZChldmVudE5hbWUpO1xuXG4gICAgaWYgKCFldmVudE5hbWVHaXZlbiAmJiAhaGFuZGxlckdpdmVuKSB7XG4gICAgICBzdG9wT2JzZXJ2aW5nRWxlbWVudChlbGVtZW50KTtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIGlmICghaGFuZGxlckdpdmVuKSB7XG4gICAgICBzdG9wT2JzZXJ2aW5nRXZlbnROYW1lKGVsZW1lbnQsIGV2ZW50TmFtZSk7XG4gICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICB2YXIgZW50cnkgPSB1bnJlZ2lzdGVyKGVsZW1lbnQsIGV2ZW50TmFtZSwgaGFuZGxlcik7XG5cbiAgICBpZiAoIWVudHJ5KSByZXR1cm4gZWxlbWVudDtcbiAgICByZW1vdmVFdmVudChlbGVtZW50LCBldmVudE5hbWUsIGVudHJ5LnJlc3BvbmRlcik7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICBmdW5jdGlvbiBzdG9wT2JzZXJ2aW5nU3RhbmRhcmRFdmVudChlbGVtZW50LCBldmVudE5hbWUsIHJlc3BvbmRlcikge1xuICAgIHZhciBhY3R1YWxFdmVudE5hbWUgPSBnZXRET01FdmVudE5hbWUoZXZlbnROYW1lKTtcbiAgICBpZiAoZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoYWN0dWFsRXZlbnROYW1lLCByZXNwb25kZXIsIGZhbHNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5kZXRhY2hFdmVudCgnb24nICsgYWN0dWFsRXZlbnROYW1lLCByZXNwb25kZXIpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0b3BPYnNlcnZpbmdDdXN0b21FdmVudChlbGVtZW50LCBldmVudE5hbWUsIHJlc3BvbmRlcikge1xuICAgIGlmIChlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIpIHtcbiAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGF0YWF2YWlsYWJsZScsIHJlc3BvbmRlciwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVtZW50LmRldGFjaEV2ZW50KCdvbmRhdGFhdmFpbGFibGUnLCByZXNwb25kZXIpO1xuICAgICAgZWxlbWVudC5kZXRhY2hFdmVudCgnb25sb3NlY2FwdHVyZScsICAgcmVzcG9uZGVyKTtcbiAgICB9XG4gIH1cblxuXG5cbiAgZnVuY3Rpb24gc3RvcE9ic2VydmluZ0VsZW1lbnQoZWxlbWVudCkge1xuICAgIHZhciB1aWQgPSBnZXRVbmlxdWVFbGVtZW50SUQoZWxlbWVudCksIHJlZ2lzdHJ5ID0gR0xPQkFMLkV2ZW50LmNhY2hlW3VpZF07XG4gICAgaWYgKCFyZWdpc3RyeSkgcmV0dXJuO1xuXG4gICAgZGVzdHJveVJlZ2lzdHJ5Rm9yRWxlbWVudChlbGVtZW50LCB1aWQpO1xuXG4gICAgdmFyIGVudHJpZXMsIGk7XG4gICAgZm9yICh2YXIgZXZlbnROYW1lIGluIHJlZ2lzdHJ5KSB7XG4gICAgICBpZiAoZXZlbnROYW1lID09PSAnZWxlbWVudCcpIGNvbnRpbnVlO1xuXG4gICAgICBlbnRyaWVzID0gcmVnaXN0cnlbZXZlbnROYW1lXTtcbiAgICAgIGkgPSBlbnRyaWVzLmxlbmd0aDtcbiAgICAgIHdoaWxlIChpLS0pXG4gICAgICAgIHJlbW92ZUV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgZW50cmllc1tpXS5yZXNwb25kZXIpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0b3BPYnNlcnZpbmdFdmVudE5hbWUoZWxlbWVudCwgZXZlbnROYW1lKSB7XG4gICAgdmFyIHJlZ2lzdHJ5ID0gZ2V0UmVnaXN0cnlGb3JFbGVtZW50KGVsZW1lbnQpO1xuICAgIHZhciBlbnRyaWVzID0gcmVnaXN0cnlbZXZlbnROYW1lXTtcbiAgICBpZiAoIWVudHJpZXMpIHJldHVybjtcbiAgICBkZWxldGUgcmVnaXN0cnlbZXZlbnROYW1lXTtcblxuICAgIHZhciBpID0gZW50cmllcy5sZW5ndGg7XG4gICAgd2hpbGUgKGktLSlcbiAgICAgIHJlbW92ZUV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgZW50cmllc1tpXS5yZXNwb25kZXIpO1xuICB9XG5cblxuICBmdW5jdGlvbiByZW1vdmVFdmVudChlbGVtZW50LCBldmVudE5hbWUsIGhhbmRsZXIpIHtcbiAgICBpZiAoaXNDdXN0b21FdmVudChldmVudE5hbWUpKVxuICAgICAgc3RvcE9ic2VydmluZ0N1c3RvbUV2ZW50KGVsZW1lbnQsIGV2ZW50TmFtZSwgaGFuZGxlcik7XG4gICAgZWxzZVxuICAgICAgc3RvcE9ic2VydmluZ1N0YW5kYXJkRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lLCBoYW5kbGVyKTtcbiAgfVxuXG5cblxuICBmdW5jdGlvbiBnZXRGaXJlVGFyZ2V0KGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudCAhPT0gZG9jdW1lbnQpIHJldHVybiBlbGVtZW50O1xuICAgIGlmIChkb2N1bWVudC5jcmVhdGVFdmVudCAmJiAhZWxlbWVudC5kaXNwYXRjaEV2ZW50KVxuICAgICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpcmUoZWxlbWVudCwgZXZlbnROYW1lLCBtZW1vLCBidWJibGUpIHtcbiAgICBlbGVtZW50ID0gZ2V0RmlyZVRhcmdldCgkKGVsZW1lbnQpKTtcbiAgICBpZiAoT2JqZWN0LmlzVW5kZWZpbmVkKGJ1YmJsZSkpIGJ1YmJsZSA9IHRydWU7XG4gICAgbWVtbyA9IG1lbW8gfHwge307XG5cbiAgICB2YXIgZXZlbnQgPSBmaXJlRXZlbnQoZWxlbWVudCwgZXZlbnROYW1lLCBtZW1vLCBidWJibGUpO1xuICAgIHJldHVybiBFdmVudC5leHRlbmQoZXZlbnQpO1xuICB9XG5cbiAgZnVuY3Rpb24gZmlyZUV2ZW50X0RPTShlbGVtZW50LCBldmVudE5hbWUsIG1lbW8sIGJ1YmJsZSkge1xuICAgIHZhciBldmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdIVE1MRXZlbnRzJyk7XG4gICAgZXZlbnQuaW5pdEV2ZW50KCdkYXRhYXZhaWxhYmxlJywgYnViYmxlLCB0cnVlKTtcblxuICAgIGV2ZW50LmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICBldmVudC5tZW1vID0gbWVtbztcblxuICAgIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgcmV0dXJuIGV2ZW50O1xuICB9XG5cbiAgZnVuY3Rpb24gZmlyZUV2ZW50X0lFKGVsZW1lbnQsIGV2ZW50TmFtZSwgbWVtbywgYnViYmxlKSB7XG4gICAgdmFyIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnRPYmplY3QoKTtcbiAgICBldmVudC5ldmVudFR5cGUgPSBidWJibGUgPyAnb25kYXRhYXZhaWxhYmxlJyA6ICdvbmxvc2VjYXB0dXJlJztcblxuICAgIGV2ZW50LmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICBldmVudC5tZW1vID0gbWVtbztcblxuICAgIGVsZW1lbnQuZmlyZUV2ZW50KGV2ZW50LmV2ZW50VHlwZSwgZXZlbnQpO1xuICAgIHJldHVybiBldmVudDtcbiAgfVxuXG4gIHZhciBmaXJlRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCA/IGZpcmVFdmVudF9ET00gOiBmaXJlRXZlbnRfSUU7XG5cblxuXG4gIEV2ZW50LkhhbmRsZXIgPSBDbGFzcy5jcmVhdGUoe1xuICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uKGVsZW1lbnQsIGV2ZW50TmFtZSwgc2VsZWN0b3IsIGNhbGxiYWNrKSB7XG4gICAgICB0aGlzLmVsZW1lbnQgICA9ICQoZWxlbWVudCk7XG4gICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgIHRoaXMuc2VsZWN0b3IgID0gc2VsZWN0b3I7XG4gICAgICB0aGlzLmNhbGxiYWNrICA9IGNhbGxiYWNrO1xuICAgICAgdGhpcy5oYW5kbGVyICAgPSB0aGlzLmhhbmRsZUV2ZW50LmJpbmQodGhpcyk7XG4gICAgfSxcblxuXG4gICAgc3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgRXZlbnQub2JzZXJ2ZSh0aGlzLmVsZW1lbnQsIHRoaXMuZXZlbnROYW1lLCB0aGlzLmhhbmRsZXIpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHN0b3A6IGZ1bmN0aW9uKCkge1xuICAgICAgRXZlbnQuc3RvcE9ic2VydmluZyh0aGlzLmVsZW1lbnQsIHRoaXMuZXZlbnROYW1lLCB0aGlzLmhhbmRsZXIpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGhhbmRsZUV2ZW50OiBmdW5jdGlvbihldmVudCkge1xuICAgICAgdmFyIGVsZW1lbnQgPSBFdmVudC5maW5kRWxlbWVudChldmVudCwgdGhpcy5zZWxlY3Rvcik7XG4gICAgICBpZiAoZWxlbWVudCkgdGhpcy5jYWxsYmFjay5jYWxsKHRoaXMuZWxlbWVudCwgZXZlbnQsIGVsZW1lbnQpO1xuICAgIH1cbiAgfSk7XG5cbiAgZnVuY3Rpb24gb24oZWxlbWVudCwgZXZlbnROYW1lLCBzZWxlY3RvciwgY2FsbGJhY2spIHtcbiAgICBlbGVtZW50ID0gJChlbGVtZW50KTtcbiAgICBpZiAoT2JqZWN0LmlzRnVuY3Rpb24oc2VsZWN0b3IpICYmIE9iamVjdC5pc1VuZGVmaW5lZChjYWxsYmFjaykpIHtcbiAgICAgIGNhbGxiYWNrID0gc2VsZWN0b3IsIHNlbGVjdG9yID0gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEV2ZW50LkhhbmRsZXIoZWxlbWVudCwgZXZlbnROYW1lLCBzZWxlY3RvciwgY2FsbGJhY2spLnN0YXJ0KCk7XG4gIH1cblxuICBPYmplY3QuZXh0ZW5kKEV2ZW50LCBFdmVudC5NZXRob2RzKTtcblxuICBPYmplY3QuZXh0ZW5kKEV2ZW50LCB7XG4gICAgZmlyZTogICAgICAgICAgZmlyZSxcbiAgICBvYnNlcnZlOiAgICAgICBvYnNlcnZlLFxuICAgIHN0b3BPYnNlcnZpbmc6IHN0b3BPYnNlcnZpbmcsXG4gICAgb246ICAgICAgICAgICAgb25cbiAgfSk7XG5cbiAgRWxlbWVudC5hZGRNZXRob2RzKHtcbiAgICBmaXJlOiAgICAgICAgICBmaXJlLFxuXG4gICAgb2JzZXJ2ZTogICAgICAgb2JzZXJ2ZSxcblxuICAgIHN0b3BPYnNlcnZpbmc6IHN0b3BPYnNlcnZpbmcsXG5cbiAgICBvbjogICAgICAgICAgICBvblxuICB9KTtcblxuICBPYmplY3QuZXh0ZW5kKGRvY3VtZW50LCB7XG4gICAgZmlyZTogICAgICAgICAgZmlyZS5tZXRob2RpemUoKSxcblxuICAgIG9ic2VydmU6ICAgICAgIG9ic2VydmUubWV0aG9kaXplKCksXG5cbiAgICBzdG9wT2JzZXJ2aW5nOiBzdG9wT2JzZXJ2aW5nLm1ldGhvZGl6ZSgpLFxuXG4gICAgb246ICAgICAgICAgICAgb24ubWV0aG9kaXplKCksXG5cbiAgICBsb2FkZWQ6ICAgICAgICBmYWxzZVxuICB9KTtcblxuICBpZiAoR0xPQkFMLkV2ZW50KSBPYmplY3QuZXh0ZW5kKHdpbmRvdy5FdmVudCwgRXZlbnQpO1xuICBlbHNlIEdMT0JBTC5FdmVudCA9IEV2ZW50O1xuXG4gIEdMT0JBTC5FdmVudC5jYWNoZSA9IHt9O1xuXG4gIGZ1bmN0aW9uIGRlc3Ryb3lDYWNoZV9JRSgpIHtcbiAgICBHTE9CQUwuRXZlbnQuY2FjaGUgPSBudWxsO1xuICB9XG5cbiAgaWYgKHdpbmRvdy5hdHRhY2hFdmVudClcbiAgICB3aW5kb3cuYXR0YWNoRXZlbnQoJ29udW5sb2FkJywgZGVzdHJveUNhY2hlX0lFKTtcblxuICBESVYgPSBudWxsO1xuICBkb2NFbCA9IG51bGw7XG59KSh0aGlzKTtcblxuKGZ1bmN0aW9uKEdMT0JBTCkge1xuICAvKiBDb2RlIGZvciBjcmVhdGluZyBsZWFrLWZyZWUgZXZlbnQgcmVzcG9uZGVycyBpcyBiYXNlZCBvbiB3b3JrIGJ5XG4gICBKb2huLURhdmlkIERhbHRvbi4gKi9cblxuICB2YXIgZG9jRWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIHZhciBNT1VTRUVOVEVSX01PVVNFTEVBVkVfRVZFTlRTX1NVUFBPUlRFRCA9ICdvbm1vdXNlZW50ZXInIGluIGRvY0VsXG4gICAgJiYgJ29ubW91c2VsZWF2ZScgaW4gZG9jRWw7XG5cbiAgZnVuY3Rpb24gaXNTaW11bGF0ZWRNb3VzZUVudGVyTGVhdmVFdmVudChldmVudE5hbWUpIHtcbiAgICByZXR1cm4gIU1PVVNFRU5URVJfTU9VU0VMRUFWRV9FVkVOVFNfU1VQUE9SVEVEICYmXG4gICAgIChldmVudE5hbWUgPT09ICdtb3VzZWVudGVyJyB8fCBldmVudE5hbWUgPT09ICdtb3VzZWxlYXZlJyk7XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVSZXNwb25kZXIodWlkLCBldmVudE5hbWUsIGhhbmRsZXIpIHtcbiAgICBpZiAoRXZlbnQuX2lzQ3VzdG9tRXZlbnQoZXZlbnROYW1lKSlcbiAgICAgIHJldHVybiBjcmVhdGVSZXNwb25kZXJGb3JDdXN0b21FdmVudCh1aWQsIGV2ZW50TmFtZSwgaGFuZGxlcik7XG4gICAgaWYgKGlzU2ltdWxhdGVkTW91c2VFbnRlckxlYXZlRXZlbnQoZXZlbnROYW1lKSlcbiAgICAgIHJldHVybiBjcmVhdGVNb3VzZUVudGVyTGVhdmVSZXNwb25kZXIodWlkLCBldmVudE5hbWUsIGhhbmRsZXIpO1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICBpZiAoIUV2ZW50LmNhY2hlKSByZXR1cm47XG5cbiAgICAgIHZhciBlbGVtZW50ID0gRXZlbnQuY2FjaGVbdWlkXS5lbGVtZW50O1xuICAgICAgRXZlbnQuZXh0ZW5kKGV2ZW50LCBlbGVtZW50KTtcbiAgICAgIGhhbmRsZXIuY2FsbChlbGVtZW50LCBldmVudCk7XG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVJlc3BvbmRlckZvckN1c3RvbUV2ZW50KHVpZCwgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICB2YXIgZWxlbWVudCA9IEV2ZW50LmNhY2hlW3VpZF0uZWxlbWVudDtcblxuICAgICAgaWYgKE9iamVjdC5pc1VuZGVmaW5lZChldmVudC5ldmVudE5hbWUpKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGlmIChldmVudC5ldmVudE5hbWUgIT09IGV2ZW50TmFtZSlcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICBFdmVudC5leHRlbmQoZXZlbnQsIGVsZW1lbnQpO1xuICAgICAgaGFuZGxlci5jYWxsKGVsZW1lbnQsIGV2ZW50KTtcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gY3JlYXRlTW91c2VFbnRlckxlYXZlUmVzcG9uZGVyKHVpZCwgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICB2YXIgZWxlbWVudCA9IEV2ZW50LmNhY2hlW3VpZF0uZWxlbWVudDtcblxuICAgICAgRXZlbnQuZXh0ZW5kKGV2ZW50LCBlbGVtZW50KTtcbiAgICAgIHZhciBwYXJlbnQgPSBldmVudC5yZWxhdGVkVGFyZ2V0O1xuXG4gICAgICB3aGlsZSAocGFyZW50ICYmIHBhcmVudCAhPT0gZWxlbWVudCkge1xuICAgICAgICB0cnkgeyBwYXJlbnQgPSBwYXJlbnQucGFyZW50Tm9kZTsgfVxuICAgICAgICBjYXRjaChlKSB7IHBhcmVudCA9IGVsZW1lbnQ7IH1cbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmVudCA9PT0gZWxlbWVudCkgcmV0dXJuO1xuICAgICAgaGFuZGxlci5jYWxsKGVsZW1lbnQsIGV2ZW50KTtcbiAgICB9XG4gIH1cblxuICBHTE9CQUwuRXZlbnQuX2NyZWF0ZVJlc3BvbmRlciA9IGNyZWF0ZVJlc3BvbmRlcjtcbiAgZG9jRWwgPSBudWxsO1xufSkodGhpcyk7XG5cbihmdW5jdGlvbihHTE9CQUwpIHtcbiAgLyogU3VwcG9ydCBmb3IgdGhlIERPTUNvbnRlbnRMb2FkZWQgZXZlbnQgaXMgYmFzZWQgb24gd29yayBieSBEYW4gV2ViYixcbiAgICAgTWF0dGhpYXMgTWlsbGVyLCBEZWFuIEVkd2FyZHMsIEpvaG4gUmVzaWcsIGFuZCBEaWVnbyBQZXJpbmkuICovXG5cbiAgdmFyIFRJTUVSO1xuXG4gIGZ1bmN0aW9uIGZpcmVDb250ZW50TG9hZGVkRXZlbnQoKSB7XG4gICAgaWYgKGRvY3VtZW50LmxvYWRlZCkgcmV0dXJuO1xuICAgIGlmIChUSU1FUikgd2luZG93LmNsZWFyVGltZW91dChUSU1FUik7XG4gICAgZG9jdW1lbnQubG9hZGVkID0gdHJ1ZTtcbiAgICBkb2N1bWVudC5maXJlKCdkb206bG9hZGVkJyk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja1JlYWR5U3RhdGUoKSB7XG4gICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgIGRvY3VtZW50LmRldGFjaEV2ZW50KCdvbnJlYWR5c3RhdGVjaGFuZ2UnLCBjaGVja1JlYWR5U3RhdGUpO1xuICAgICAgZmlyZUNvbnRlbnRMb2FkZWRFdmVudCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBvbGxEb1Njcm9sbCgpIHtcbiAgICB0cnkge1xuICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmRvU2Nyb2xsKCdsZWZ0Jyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgVElNRVIgPSBwb2xsRG9TY3JvbGwuZGVmZXIoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmaXJlQ29udGVudExvYWRlZEV2ZW50KCk7XG4gIH1cblxuXG4gIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgZmlyZUNvbnRlbnRMb2FkZWRFdmVudCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZpcmVDb250ZW50TG9hZGVkRXZlbnQsIGZhbHNlKTtcbiAgfSBlbHNlIHtcbiAgICBkb2N1bWVudC5hdHRhY2hFdmVudCgnb25yZWFkeXN0YXRlY2hhbmdlJywgY2hlY2tSZWFkeVN0YXRlKTtcbiAgICBpZiAod2luZG93ID09IHRvcCkgVElNRVIgPSBwb2xsRG9TY3JvbGwuZGVmZXIoKTtcbiAgfVxuXG4gIEV2ZW50Lm9ic2VydmUod2luZG93LCAnbG9hZCcsIGZpcmVDb250ZW50TG9hZGVkRXZlbnQpO1xufSkodGhpcyk7XG5cblxuRWxlbWVudC5hZGRNZXRob2RzKCk7XG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gREVQUkVDQVRFRCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuSGFzaC50b1F1ZXJ5U3RyaW5nID0gT2JqZWN0LnRvUXVlcnlTdHJpbmc7XG5cbnZhciBUb2dnbGUgPSB7IGRpc3BsYXk6IEVsZW1lbnQudG9nZ2xlIH07XG5cbkVsZW1lbnQuTWV0aG9kcy5jaGlsZE9mID0gRWxlbWVudC5NZXRob2RzLmRlc2NlbmRhbnRPZjtcblxudmFyIEluc2VydGlvbiA9IHtcbiAgQmVmb3JlOiBmdW5jdGlvbihlbGVtZW50LCBjb250ZW50KSB7XG4gICAgcmV0dXJuIEVsZW1lbnQuaW5zZXJ0KGVsZW1lbnQsIHtiZWZvcmU6Y29udGVudH0pO1xuICB9LFxuXG4gIFRvcDogZnVuY3Rpb24oZWxlbWVudCwgY29udGVudCkge1xuICAgIHJldHVybiBFbGVtZW50Lmluc2VydChlbGVtZW50LCB7dG9wOmNvbnRlbnR9KTtcbiAgfSxcblxuICBCb3R0b206IGZ1bmN0aW9uKGVsZW1lbnQsIGNvbnRlbnQpIHtcbiAgICByZXR1cm4gRWxlbWVudC5pbnNlcnQoZWxlbWVudCwge2JvdHRvbTpjb250ZW50fSk7XG4gIH0sXG5cbiAgQWZ0ZXI6IGZ1bmN0aW9uKGVsZW1lbnQsIGNvbnRlbnQpIHtcbiAgICByZXR1cm4gRWxlbWVudC5pbnNlcnQoZWxlbWVudCwge2FmdGVyOmNvbnRlbnR9KTtcbiAgfVxufTtcblxudmFyICRjb250aW51ZSA9IG5ldyBFcnJvcignXCJ0aHJvdyAkY29udGludWVcIiBpcyBkZXByZWNhdGVkLCB1c2UgXCJyZXR1cm5cIiBpbnN0ZWFkJyk7XG5cbnZhciBQb3NpdGlvbiA9IHtcbiAgaW5jbHVkZVNjcm9sbE9mZnNldHM6IGZhbHNlLFxuXG4gIHByZXBhcmU6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuZGVsdGFYID0gIHdpbmRvdy5wYWdlWE9mZnNldFxuICAgICAgICAgICAgICAgIHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0XG4gICAgICAgICAgICAgICAgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0XG4gICAgICAgICAgICAgICAgfHwgMDtcbiAgICB0aGlzLmRlbHRhWSA9ICB3aW5kb3cucGFnZVlPZmZzZXRcbiAgICAgICAgICAgICAgICB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wXG4gICAgICAgICAgICAgICAgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxUb3BcbiAgICAgICAgICAgICAgICB8fCAwO1xuICB9LFxuXG4gIHdpdGhpbjogZnVuY3Rpb24oZWxlbWVudCwgeCwgeSkge1xuICAgIGlmICh0aGlzLmluY2x1ZGVTY3JvbGxPZmZzZXRzKVxuICAgICAgcmV0dXJuIHRoaXMud2l0aGluSW5jbHVkaW5nU2Nyb2xsb2Zmc2V0cyhlbGVtZW50LCB4LCB5KTtcbiAgICB0aGlzLnhjb21wID0geDtcbiAgICB0aGlzLnljb21wID0geTtcbiAgICB0aGlzLm9mZnNldCA9IEVsZW1lbnQuY3VtdWxhdGl2ZU9mZnNldChlbGVtZW50KTtcblxuICAgIHJldHVybiAoeSA+PSB0aGlzLm9mZnNldFsxXSAmJlxuICAgICAgICAgICAgeSA8ICB0aGlzLm9mZnNldFsxXSArIGVsZW1lbnQub2Zmc2V0SGVpZ2h0ICYmXG4gICAgICAgICAgICB4ID49IHRoaXMub2Zmc2V0WzBdICYmXG4gICAgICAgICAgICB4IDwgIHRoaXMub2Zmc2V0WzBdICsgZWxlbWVudC5vZmZzZXRXaWR0aCk7XG4gIH0sXG5cbiAgd2l0aGluSW5jbHVkaW5nU2Nyb2xsb2Zmc2V0czogZnVuY3Rpb24oZWxlbWVudCwgeCwgeSkge1xuICAgIHZhciBvZmZzZXRjYWNoZSA9IEVsZW1lbnQuY3VtdWxhdGl2ZVNjcm9sbE9mZnNldChlbGVtZW50KTtcblxuICAgIHRoaXMueGNvbXAgPSB4ICsgb2Zmc2V0Y2FjaGVbMF0gLSB0aGlzLmRlbHRhWDtcbiAgICB0aGlzLnljb21wID0geSArIG9mZnNldGNhY2hlWzFdIC0gdGhpcy5kZWx0YVk7XG4gICAgdGhpcy5vZmZzZXQgPSBFbGVtZW50LmN1bXVsYXRpdmVPZmZzZXQoZWxlbWVudCk7XG5cbiAgICByZXR1cm4gKHRoaXMueWNvbXAgPj0gdGhpcy5vZmZzZXRbMV0gJiZcbiAgICAgICAgICAgIHRoaXMueWNvbXAgPCAgdGhpcy5vZmZzZXRbMV0gKyBlbGVtZW50Lm9mZnNldEhlaWdodCAmJlxuICAgICAgICAgICAgdGhpcy54Y29tcCA+PSB0aGlzLm9mZnNldFswXSAmJlxuICAgICAgICAgICAgdGhpcy54Y29tcCA8ICB0aGlzLm9mZnNldFswXSArIGVsZW1lbnQub2Zmc2V0V2lkdGgpO1xuICB9LFxuXG4gIG92ZXJsYXA6IGZ1bmN0aW9uKG1vZGUsIGVsZW1lbnQpIHtcbiAgICBpZiAoIW1vZGUpIHJldHVybiAwO1xuICAgIGlmIChtb2RlID09ICd2ZXJ0aWNhbCcpXG4gICAgICByZXR1cm4gKCh0aGlzLm9mZnNldFsxXSArIGVsZW1lbnQub2Zmc2V0SGVpZ2h0KSAtIHRoaXMueWNvbXApIC9cbiAgICAgICAgZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgaWYgKG1vZGUgPT0gJ2hvcml6b250YWwnKVxuICAgICAgcmV0dXJuICgodGhpcy5vZmZzZXRbMF0gKyBlbGVtZW50Lm9mZnNldFdpZHRoKSAtIHRoaXMueGNvbXApIC9cbiAgICAgICAgZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgfSxcblxuXG4gIGN1bXVsYXRpdmVPZmZzZXQ6IEVsZW1lbnQuTWV0aG9kcy5jdW11bGF0aXZlT2Zmc2V0LFxuXG4gIHBvc2l0aW9uZWRPZmZzZXQ6IEVsZW1lbnQuTWV0aG9kcy5wb3NpdGlvbmVkT2Zmc2V0LFxuXG4gIGFic29sdXRpemU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBQb3NpdGlvbi5wcmVwYXJlKCk7XG4gICAgcmV0dXJuIEVsZW1lbnQuYWJzb2x1dGl6ZShlbGVtZW50KTtcbiAgfSxcblxuICByZWxhdGl2aXplOiBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgUG9zaXRpb24ucHJlcGFyZSgpO1xuICAgIHJldHVybiBFbGVtZW50LnJlbGF0aXZpemUoZWxlbWVudCk7XG4gIH0sXG5cbiAgcmVhbE9mZnNldDogRWxlbWVudC5NZXRob2RzLmN1bXVsYXRpdmVTY3JvbGxPZmZzZXQsXG5cbiAgb2Zmc2V0UGFyZW50OiBFbGVtZW50Lk1ldGhvZHMuZ2V0T2Zmc2V0UGFyZW50LFxuXG4gIHBhZ2U6IEVsZW1lbnQuTWV0aG9kcy52aWV3cG9ydE9mZnNldCxcblxuICBjbG9uZTogZnVuY3Rpb24oc291cmNlLCB0YXJnZXQsIG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7IH07XG4gICAgcmV0dXJuIEVsZW1lbnQuY2xvbmVQb3NpdGlvbih0YXJnZXQsIHNvdXJjZSwgb3B0aW9ucyk7XG4gIH1cbn07XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5pZiAoIWRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUpIGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUgPSBmdW5jdGlvbihpbnN0YW5jZU1ldGhvZHMpe1xuICBmdW5jdGlvbiBpdGVyKG5hbWUpIHtcbiAgICByZXR1cm4gbmFtZS5ibGFuaygpID8gbnVsbCA6IFwiW2NvbnRhaW5zKGNvbmNhdCgnICcsIEBjbGFzcywgJyAnKSwgJyBcIiArIG5hbWUgKyBcIiAnKV1cIjtcbiAgfVxuXG4gIGluc3RhbmNlTWV0aG9kcy5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lID0gUHJvdG90eXBlLkJyb3dzZXJGZWF0dXJlcy5YUGF0aCA/XG4gIGZ1bmN0aW9uKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuICAgIGNsYXNzTmFtZSA9IGNsYXNzTmFtZS50b1N0cmluZygpLnN0cmlwKCk7XG4gICAgdmFyIGNvbmQgPSAvXFxzLy50ZXN0KGNsYXNzTmFtZSkgPyAkdyhjbGFzc05hbWUpLm1hcChpdGVyKS5qb2luKCcnKSA6IGl0ZXIoY2xhc3NOYW1lKTtcbiAgICByZXR1cm4gY29uZCA/IGRvY3VtZW50Ll9nZXRFbGVtZW50c0J5WFBhdGgoJy4vLyonICsgY29uZCwgZWxlbWVudCkgOiBbXTtcbiAgfSA6IGZ1bmN0aW9uKGVsZW1lbnQsIGNsYXNzTmFtZSkge1xuICAgIGNsYXNzTmFtZSA9IGNsYXNzTmFtZS50b1N0cmluZygpLnN0cmlwKCk7XG4gICAgdmFyIGVsZW1lbnRzID0gW10sIGNsYXNzTmFtZXMgPSAoL1xccy8udGVzdChjbGFzc05hbWUpID8gJHcoY2xhc3NOYW1lKSA6IG51bGwpO1xuICAgIGlmICghY2xhc3NOYW1lcyAmJiAhY2xhc3NOYW1lKSByZXR1cm4gZWxlbWVudHM7XG5cbiAgICB2YXIgbm9kZXMgPSAkKGVsZW1lbnQpLmdldEVsZW1lbnRzQnlUYWdOYW1lKCcqJyk7XG4gICAgY2xhc3NOYW1lID0gJyAnICsgY2xhc3NOYW1lICsgJyAnO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGNoaWxkLCBjbjsgY2hpbGQgPSBub2Rlc1tpXTsgaSsrKSB7XG4gICAgICBpZiAoY2hpbGQuY2xhc3NOYW1lICYmIChjbiA9ICcgJyArIGNoaWxkLmNsYXNzTmFtZSArICcgJykgJiYgKGNuLmluY2x1ZGUoY2xhc3NOYW1lKSB8fFxuICAgICAgICAgIChjbGFzc05hbWVzICYmIGNsYXNzTmFtZXMuYWxsKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiAhbmFtZS50b1N0cmluZygpLmJsYW5rKCkgJiYgY24uaW5jbHVkZSgnICcgKyBuYW1lICsgJyAnKTtcbiAgICAgICAgICB9KSkpKVxuICAgICAgICBlbGVtZW50cy5wdXNoKEVsZW1lbnQuZXh0ZW5kKGNoaWxkKSk7XG4gICAgfVxuICAgIHJldHVybiBlbGVtZW50cztcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24oY2xhc3NOYW1lLCBwYXJlbnRFbGVtZW50KSB7XG4gICAgcmV0dXJuICQocGFyZW50RWxlbWVudCB8fCBkb2N1bWVudC5ib2R5KS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGNsYXNzTmFtZSk7XG4gIH07XG59KEVsZW1lbnQuTWV0aG9kcyk7XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5FbGVtZW50LkNsYXNzTmFtZXMgPSBDbGFzcy5jcmVhdGUoKTtcbkVsZW1lbnQuQ2xhc3NOYW1lcy5wcm90b3R5cGUgPSB7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICB0aGlzLmVsZW1lbnQgPSAkKGVsZW1lbnQpO1xuICB9LFxuXG4gIF9lYWNoOiBmdW5jdGlvbihpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHRoaXMuZWxlbWVudC5jbGFzc05hbWUuc3BsaXQoL1xccysvKS5zZWxlY3QoZnVuY3Rpb24obmFtZSkge1xuICAgICAgcmV0dXJuIG5hbWUubGVuZ3RoID4gMDtcbiAgICB9KS5fZWFjaChpdGVyYXRvciwgY29udGV4dCk7XG4gIH0sXG5cbiAgc2V0OiBmdW5jdGlvbihjbGFzc05hbWUpIHtcbiAgICB0aGlzLmVsZW1lbnQuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xuICB9LFxuXG4gIGFkZDogZnVuY3Rpb24oY2xhc3NOYW1lVG9BZGQpIHtcbiAgICBpZiAodGhpcy5pbmNsdWRlKGNsYXNzTmFtZVRvQWRkKSkgcmV0dXJuO1xuICAgIHRoaXMuc2V0KCRBKHRoaXMpLmNvbmNhdChjbGFzc05hbWVUb0FkZCkuam9pbignICcpKTtcbiAgfSxcblxuICByZW1vdmU6IGZ1bmN0aW9uKGNsYXNzTmFtZVRvUmVtb3ZlKSB7XG4gICAgaWYgKCF0aGlzLmluY2x1ZGUoY2xhc3NOYW1lVG9SZW1vdmUpKSByZXR1cm47XG4gICAgdGhpcy5zZXQoJEEodGhpcykud2l0aG91dChjbGFzc05hbWVUb1JlbW92ZSkuam9pbignICcpKTtcbiAgfSxcblxuICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICRBKHRoaXMpLmpvaW4oJyAnKTtcbiAgfVxufTtcblxuT2JqZWN0LmV4dGVuZChFbGVtZW50LkNsYXNzTmFtZXMucHJvdG90eXBlLCBFbnVtZXJhYmxlKTtcblxuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbihmdW5jdGlvbigpIHtcbiAgd2luZG93LlNlbGVjdG9yID0gQ2xhc3MuY3JlYXRlKHtcbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbihleHByZXNzaW9uKSB7XG4gICAgICB0aGlzLmV4cHJlc3Npb24gPSBleHByZXNzaW9uLnN0cmlwKCk7XG4gICAgfSxcblxuICAgIGZpbmRFbGVtZW50czogZnVuY3Rpb24ocm9vdEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBQcm90b3R5cGUuU2VsZWN0b3Iuc2VsZWN0KHRoaXMuZXhwcmVzc2lvbiwgcm9vdEVsZW1lbnQpO1xuICAgIH0sXG5cbiAgICBtYXRjaDogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcmV0dXJuIFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaChlbGVtZW50LCB0aGlzLmV4cHJlc3Npb24pO1xuICAgIH0sXG5cbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5leHByZXNzaW9uO1xuICAgIH0sXG5cbiAgICBpbnNwZWN0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBcIiM8U2VsZWN0b3I6IFwiICsgdGhpcy5leHByZXNzaW9uICsgXCI+XCI7XG4gICAgfVxuICB9KTtcblxuICBPYmplY3QuZXh0ZW5kKFNlbGVjdG9yLCB7XG4gICAgbWF0Y2hFbGVtZW50czogZnVuY3Rpb24oZWxlbWVudHMsIGV4cHJlc3Npb24pIHtcbiAgICAgIHZhciBtYXRjaCA9IFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaCxcbiAgICAgICAgICByZXN1bHRzID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBlbGVtZW50cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgICBpZiAobWF0Y2goZWxlbWVudCwgZXhwcmVzc2lvbikpIHtcbiAgICAgICAgICByZXN1bHRzLnB1c2goRWxlbWVudC5leHRlbmQoZWxlbWVudCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9LFxuXG4gICAgZmluZEVsZW1lbnQ6IGZ1bmN0aW9uKGVsZW1lbnRzLCBleHByZXNzaW9uLCBpbmRleCkge1xuICAgICAgaW5kZXggPSBpbmRleCB8fCAwO1xuICAgICAgdmFyIG1hdGNoSW5kZXggPSAwLCBlbGVtZW50O1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGVsZW1lbnRzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgICAgaWYgKFByb3RvdHlwZS5TZWxlY3Rvci5tYXRjaChlbGVtZW50LCBleHByZXNzaW9uKSAmJiBpbmRleCA9PT0gbWF0Y2hJbmRleCsrKSB7XG4gICAgICAgICAgcmV0dXJuIEVsZW1lbnQuZXh0ZW5kKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcblxuICAgIGZpbmRDaGlsZEVsZW1lbnRzOiBmdW5jdGlvbihlbGVtZW50LCBleHByZXNzaW9ucykge1xuICAgICAgdmFyIHNlbGVjdG9yID0gZXhwcmVzc2lvbnMudG9BcnJheSgpLmpvaW4oJywgJyk7XG4gICAgICByZXR1cm4gUHJvdG90eXBlLlNlbGVjdG9yLnNlbGVjdChzZWxlY3RvciwgZWxlbWVudCB8fCBkb2N1bWVudCk7XG4gICAgfVxuICB9KTtcbn0pKCk7XG4iLCJyZXF1aXJlKCdqc2NvbmNhdCcpO1xuXG5hbGVydChKU09OLnN0cmluZ2lmeSk7XG4iXX0=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment